UserExtractController.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. <?php
  2. namespace app\api\controller\user;
  3. use app\models\user\UserBill;
  4. use app\models\user\UserExtract;
  5. use app\Request;
  6. use tw\services\payment\MachantPay;
  7. use tw\services\controller\PaymentService;
  8. use crmeb\services\UtilService;
  9. use think\facade\Log;
  10. use tw\redis\UserRds;
  11. /**
  12. * 提现类
  13. * Class UserExtractController
  14. * @package app\api\controller\user
  15. */
  16. class UserExtractController
  17. {
  18. /**
  19. * @api {get} /extract/bank 提现银行
  20. * @apiName ExtractBank
  21. * @apiGroup Brokerage
  22. *
  23. * @apiDescription 体现前请求,用户显示和客户端过滤
  24. *
  25. * @apiSuccess {float} broken_commission 冻结佣金
  26. * @apiSuccess {float} brokerage_price 总佣金
  27. * @apiSuccess {float} commissionCount 可提现佣金
  28. * @apiSuccess {string[]} extractBank 可体现银行列表
  29. * @apiSuccess {float} minPrice 最小提现金额
  30. * @apiSuccess {string} wxpayName 微信实名(以下 4 个参数用于记忆功能)
  31. * @apiSuccess {string} bankCardNo 银行卡号
  32. * @apiSuccess {string} bankUser 银行户名
  33. * @apiSuccess {string} bankName 银行名
  34. */
  35. public function bank(Request $request)
  36. {
  37. $user = $request->user();
  38. // 佣金冻结时间
  39. $frozen_days = intval(sys_config('extract_time'));
  40. $frozen_from = time() - 86400 * $frozen_days;
  41. //可提现佣金
  42. $brokerage_commission = UserBill::where(['uid' => $user['uid'], 'category' => 'now_money', 'type' => 'brokerage'])
  43. ->where('add_time', '>', $frozen_from)
  44. ->where('pm', 1)
  45. ->sum('number');
  46. $refund_commission = UserBill::where(['uid' => $user['uid'], 'category' => 'now_money', 'type' => 'brokerage'])
  47. ->where('add_time', '>', $frozen_from)
  48. ->where('pm', 0)
  49. ->sum('number');
  50. $data['broken_commission'] = floatval(bcsub($brokerage_commission, $refund_commission, 2));
  51. if ($data['broken_commission'] < 0) {
  52. $data['broken_commission'] = 0;
  53. }
  54. $data['brokerage_price'] = $user['brokerage_price'];
  55. //可提现佣金
  56. $data['commissionCount'] = floatval(bcsub($data['brokerage_price'], $data['broken_commission'], 2));
  57. $extractBank = sys_config('user_extract_bank') ?? []; //提现银行
  58. $extractBank = str_replace("\r\n", "\n", $extractBank); //防止不兼容
  59. $data['extractBank'] = explode("\n", is_array($extractBank) ? (isset($extractBank[0]) ? $extractBank[0] : $extractBank) : $extractBank);
  60. $data['minPrice'] = sys_config('user_extract_min_price'); //提现最低金额
  61. // 输入记忆
  62. $cach = (new UserRds)->gets($user['uid'], [
  63. UserRds::FILED_WXPAYNAME,
  64. UserRds::FIELD_BANKCARDNO,
  65. UserRds::FIELD_BANKUSER,
  66. UserRds::FIELD_BANKNAME,
  67. ]);
  68. $data['wxpayName'] = $cach[UserRds::FILED_WXPAYNAME] ? $cach[UserRds::FILED_WXPAYNAME] : '';
  69. $data['bankCardNo'] = $cach[UserRds::FIELD_BANKCARDNO] ? $cach[UserRds::FIELD_BANKCARDNO] : '';
  70. $data['bankUser'] = $cach[UserRds::FIELD_BANKUSER] ? $cach[UserRds::FIELD_BANKUSER] : '';
  71. $data['bankName'] = $cach[UserRds::FIELD_BANKNAME] ? $cach[UserRds::FIELD_BANKNAME] : '';
  72. return app('json')->successful($data);
  73. }
  74. /**
  75. * @api {post} /extract/bank_fee 查询银行提现手续费
  76. * @apiName PostExtractBankFee
  77. * @apiGroup Brokerage
  78. *
  79. * @apiBody {int} extract_type 提现类型/通道
  80. * @apiBody {float} money 提现金额
  81. *
  82. * @apiDescription 用于提示
  83. *
  84. * @apiSuccess {float} rate 手续费率
  85. * @apiSuccess {float} min 最少收取
  86. * @apiSuccess {float} max 最多收取
  87. * @apiSuccess {float} fee 当前收取
  88. * @apiSuccess {float} valid 实际到帐金额
  89. */
  90. public function bank_fee(Request $request)
  91. {
  92. $extractInfo = UtilService::postMore([
  93. ['alipay_code', ''],
  94. ['extract_type', ''],
  95. ['money', 0],
  96. ['name', ''],
  97. ['bankname', ''],
  98. ['cardnum', ''],
  99. ['weixin', ''],
  100. ], $request);
  101. $user = $request->user();
  102. if ($extractInfo['extract_type'] != 'bank') {
  103. return app('json')->fail('不是银行卡提现');
  104. }
  105. if ($extractInfo['money'] < sys_config('user_extract_min_price')) {
  106. return app('json')->fail('金额小于最低提现金额');
  107. }
  108. $bankMax = 1000; // 银行渠道限额
  109. if ($extractInfo['money'] > $bankMax) {
  110. return app('json')->fail("金额不能超过 $bankMax 元");
  111. }
  112. list($ok, $fee, $rate, $min, $max) = MachantPay::toBankByWeixinFee($extractInfo['money']);
  113. if (!$ok) {
  114. return app('json')->fail('金额错误');
  115. }
  116. // 实际到帐金额
  117. $valid = floatval(bcsub($extractInfo['money'], $fee, 2));
  118. return app('json')->successful([
  119. 'rate' => $rate, // 费率
  120. 'min' => $min, // 最少收费
  121. 'max' => $max, // 最大收费
  122. 'fee' => $fee, // 当前收费
  123. 'valid' => $valid, // 实际到帐
  124. ]);
  125. }
  126. /**
  127. * @api {post} /extract/cash 提现申请
  128. * @apiName ExtractCash
  129. * @apiGroup Brokerage
  130. *
  131. * @apiBody {string} alipay_code 支付宝号码
  132. * @apiBody {string="alipay","bank","weixin"} extract_type 提现类型
  133. * @apiBody {float} money 提现金额
  134. * @apiBody {string} bankName 开户行
  135. * @apiBody {string} cardnum 卡号
  136. * @apiBody {string} name 微信实名/银行户名/支付宝帐号
  137. * @apiBody {string} weixin 微信实名
  138. *
  139. * @apiSuccessExample Succeed
  140. * {
  141. *
  142. * }
  143. * @apiErrorExample Failed
  144. * {
  145. *
  146. * }
  147. *
  148. */
  149. public function cash(Request $request)
  150. {
  151. $extractInfo = UtilService::postMore([
  152. ['alipay_code', ''],
  153. ['extract_type', ''],
  154. ['money', 0],
  155. ['name', ''],
  156. ['bankname', ''],
  157. ['cardnum', ''],
  158. ['weixin', ''],
  159. ], $request);
  160. $user = $request->user();
  161. list($suc, $msg) = PaymentService::user_request_extract($user, $extractInfo);
  162. if ($suc) {
  163. return app('json')->successful('申请提现成功!');
  164. } else {
  165. return app('json')->fail($msg);
  166. }
  167. }
  168. /**
  169. * 即时提現,參數返回值同 cash
  170. * 本接口支持即時到帐,调用三方支付提现 API
  171. *
  172. * 用户账户必须满足以下规则。
  173. * 1. 满足对应提现通道要求,微信支付:每个用户1天限1次,每次限200, 平台每日限额 200,000
  174. * 2. 15 日内必须有退款订单。且30日内退款订单金额 > 提现金额
  175. * 3. 其他基本需求(最低提现限额等等)
  176. *
  177. * 不满足体现条件,则交给人工处理
  178. * API 执行失败,则必须重新提交提现请求,因为人工操作也是失败。
  179. * 如果API 返回 SYSTEMERROR, 则按照原订单参数重新提交。
  180. */
  181. public function flash_cash(Request $request)
  182. {
  183. // 提交申请
  184. $extractInfo = UtilService::postMore([
  185. ['alipay_code', ''],
  186. ['extract_type', ''],
  187. ['money', 0],
  188. ['name', ''],
  189. ['bankname', ''],
  190. ['cardnum', ''],
  191. ['weixin', ''],
  192. ], $request);
  193. $user = $request->user();
  194. list($suc, $msg) = PaymentService::user_request_extract($user, $extractInfo);
  195. if (!$suc) {
  196. return app('json')->fail($msg);
  197. }
  198. $row = $msg;
  199. $extractRow = UserExtract::getUserExtractInfo($user['uid'], $row['extract_type'], $row['add_time']);
  200. if (!$extractRow) {
  201. Log::error('Unbelievable error getUserExtractInfo(' . $user['uid'] . ' ' . $row['add_time'] . ')');
  202. return app('json')->fail('提交申请失败');
  203. }
  204. // 检查条件
  205. list($suc, $msg) = PaymentService::user_extract_auto_conditions($user);
  206. if (!$suc) {
  207. // 条件不满足,不进一步处理,相当与交给人工处理
  208. return app('json')->fail($msg);
  209. }
  210. // API
  211. list($suc, $ec, $es) = PaymentService::extract_by_api($extractRow);
  212. if (!$suc) {
  213. // API 失败 直接拒绝,因为重试也会大概率失败
  214. list($ok, $msg) = PaymentService::user_extract_reject($extractRow['id'], $es);
  215. if (!$ok) {
  216. errlog('user_extract_reject()' . $extractRow['id']);
  217. }
  218. return app('json')->fail($es);
  219. } else {
  220. list($ok, $msg) = PaymentService::user_extract_passed($extractRow);
  221. if (!$ok) {
  222. errlog('user_extract_passed()' . $extractRow['id']);
  223. }
  224. return app('json')->successful('提现成功');
  225. }
  226. }
  227. }