PaymentService.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <?php
  2. namespace crmeb\services\payment;
  3. use app\models\user\WechatUser;
  4. use crmeb\payment\MachantPay;
  5. use app\models\user\UserBill;
  6. use app\models\user\UserExtract;
  7. use app\admin\model\user\UserExtract as UserExtractAdmin;
  8. use tw\redis\UserRds;
  9. /**
  10. * 支付,提现相关业务逻辑,为了减少 Controller 部分的代码。
  11. * Controller 的代码不容易测试。
  12. */
  13. class PaymentService
  14. {
  15. /**
  16. * 执行用户申請提现
  17. *
  18. * @param Object $user
  19. * @param array $extractInfo:
  20. *
  21. * ['alipay_code', ''],
  22. * ['extract_type', ''],
  23. * ['money', 0],
  24. * ['name', ''],
  25. * ['bankname', ''],
  26. * ['cardnum', ''],
  27. * ['weixin', ''],
  28. *
  29. * @return [$ok, $err_msg]
  30. *
  31. */
  32. public static function user_request_extract($user, $extractInfo)
  33. {
  34. if (!preg_match('/^(([1-9][0-9]*)|(([0]\.\d{1,2}|[1-9][0-9]*\.\d{1,2})))$/', $extractInfo['money'])) {
  35. return [false, '提现金额输入有误'];
  36. }
  37. // 最小提现额度
  38. if($extractInfo['money'] < sys_config('user_extract_min_price')) {
  39. return [false, '金额小于最低提现金额'];
  40. }
  41. // 佣金冻结天数
  42. $frozen_days = intval(sys_config('extract_time'));
  43. $valid_time = time() - 86400 * $frozen_days;
  44. // 冻结期获得佣金
  45. $brokerage_commission = UserBill::where(['uid' => $user['uid'], 'category' => 'now_money', 'type' => 'brokerage'])
  46. ->where('add_time', '>', $valid_time)
  47. ->where('pm', 1)
  48. ->sum('number');
  49. // 冻结期花费佣金
  50. $refund_commission = UserBill::where(['uid' => $user['uid'], 'category' => 'now_money', 'type' => 'brokerage'])
  51. ->where('add_time', '>', $valid_time)
  52. ->where('pm', 0)
  53. ->sum('number');
  54. // 冻结佣金
  55. $data['broken_commission'] = bcsub($brokerage_commission, $refund_commission, 2);
  56. if ($data['broken_commission'] < 0) {
  57. $data['broken_commission'] = 0;
  58. }
  59. // 总佣金
  60. $data['brokerage_price'] = $user['brokerage_price'];
  61. //可提现佣金
  62. $commissionCount = bcsub($data['brokerage_price'], $data['broken_commission'], 2);
  63. if ($extractInfo['money'] > $commissionCount) {
  64. return [false, '可提现佣金不足'];
  65. }
  66. if (!$extractInfo['cardnum'] == '') {
  67. if (!preg_match('/^([1-9]{1})(\d{14}|\d{18})$/', $extractInfo['cardnum'])) {
  68. return [false, '银行卡号输入有误'];
  69. }
  70. }
  71. $row = UserExtract::userExtract($user, $extractInfo);
  72. if ($row) {
  73. return [true, $row];
  74. } else {
  75. return [false, UserExtract::getErrorInfo('提现失败')];
  76. }
  77. }
  78. /**
  79. * 執行通過提現申請
  80. */
  81. public static function user_extract_passed($extractInfo)
  82. {
  83. // if (!UserExtractAdmin::be(['id' => $extractId, 'status' => EXTRACT_AUDITING])) {
  84. // return [false, '操作记录不存在或状态错误!'];
  85. // }
  86. if ($extractInfo['status'] == EXTRACT_SUC) {
  87. return [false, '您已提现,请勿重复提现'];
  88. }
  89. if ($extractInfo['status'] == EXTRACT_FAILED) {
  90. return [false, '您的提现申请已被拒绝'];
  91. }
  92. $res = UserExtractAdmin::changeSuccess($extractInfo['id']);
  93. if ($res) {
  94. event('UserExtractSucc', [$extractInfo]);
  95. return [true, ''];
  96. } else {
  97. return [false, '操作失败'];
  98. }
  99. }
  100. /**
  101. * 拒絕提現申請
  102. */
  103. public static function user_extract_reject($extractId, $reason)
  104. {
  105. if (!UserExtractAdmin::be(['id' => $extractId, 'status' => EXTRACT_AUDITING])) {
  106. return [false, '操作记录不存在或状态错误'];
  107. }
  108. $extract = UserExtractAdmin::get($extractId);
  109. if (!$extract) {
  110. return [false, '操作记录不存在'];
  111. }
  112. if ($extract->status == EXTRACT_SUC) {
  113. return [false, '已经提现,错误操作'];
  114. }
  115. if ($extract->status == EXTRACT_FAILED) {
  116. return [false, '您的提现申请已被拒绝,请勿重复操作'];
  117. }
  118. UserExtractAdmin::beginTrans();
  119. $res = UserExtractAdmin::changeFail($extractId, $reason);
  120. if ($res) {
  121. UserExtractAdmin::commitTrans();
  122. event('UserExtractRejected', [$extract, $reason]);
  123. return [true, '操作成功'];
  124. } else {
  125. UserExtractAdmin::rollbackTrans();
  126. return [false, '操作失败'];
  127. }
  128. }
  129. /**
  130. * 用戶自動提現需要滿足的條件
  131. *
  132. * @param array $user:
  133. * @return boolean:
  134. */
  135. public static function user_extract_auto_conditions($user)
  136. {
  137. // 微信支付提現到零錢:每個用戶每天提現 1 次,每次最多 200, 平臺每天限額 200,000.
  138. return [true, ''];
  139. }
  140. /**
  141. * 用户提现,集成支持的各种提现渠道
  142. *
  143. * @param array $extractInfo: user_extract 行
  144. */
  145. public static function extract_by_api($extractInfo)
  146. {
  147. if (!$extractInfo) {
  148. return [false, -10404, '记录不存在'];
  149. }
  150. $trade_no = md5($extractInfo['uid'] . $extractInfo['extract_price'] . $extractInfo['add_time']);
  151. switch($extractInfo['extract_type']) {
  152. case 'weixin':
  153. $openid = WechatUser::where('uid', $extractInfo['uid'])->value('routine_openid');
  154. //
  155. $user = new UserRds();
  156. $user->set($extractInfo['uid'], 'wxpayName', $extractInfo['real_name']);
  157. //
  158. return MachantPay::toWeixin($openid, $trade_no, $extractInfo['extract_price'], '佣金提现', $extractInfo['real_name']);
  159. case 'bank':
  160. // 记忆银行信息
  161. break;
  162. default:
  163. // 其他情况不处理,返回失败
  164. errlog('unbelievable error: extract_type='. $extractInfo['extract_type']);
  165. return [false, -10000, '不支持的类型'];
  166. } // switch
  167. }
  168. }