Client.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace crmeb\services\easywechat\batches;
  12. use think\facade\Route;
  13. use crmeb\exceptions\PayException;
  14. use crmeb\services\wechat\Payment;
  15. use crmeb\services\easywechat\BaseClient;
  16. use think\exception\ValidateException;
  17. use think\facade\Log;
  18. class Client extends BaseClient
  19. {
  20. protected $isService = false;
  21. //发起转账
  22. const API_TRANSFER_BILLS_URL = '/v3/fund-app/mch-transfer/transfer-bills';
  23. /**
  24. * 商家转账到零钱
  25. * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_1.shtml
  26. * @param $type
  27. * @param array $order
  28. * @return mixed
  29. */
  30. public function send(array $order)
  31. {
  32. $params = [
  33. 'appid' => $this->app['config']['app_id'],
  34. 'out_batch_no' => $order['out_batch_no'],
  35. 'batch_name' => $order['batch_name'],
  36. 'batch_remark' => $order['batch_remark'],
  37. 'total_amount' => $order['total_amount'],
  38. 'total_num' => $order['total_num'],
  39. 'transfer_detail_list' => $order['transfer_detail_list'],
  40. ];
  41. $content = json_encode($params, JSON_UNESCAPED_UNICODE);
  42. $res = $this->request('/v3/transfer/batches', 'POST', ['sign_body' => $content]);
  43. if (isset($res['code'])) {
  44. throw new ValidateException('微信接口报错:' . $res['message']);
  45. }
  46. return $res;
  47. }
  48. /**
  49. * 发起转账新接口(2025年1月15日升级)
  50. *
  51. * @param string $outBatchNo
  52. * @param string $amount
  53. * @param string $openid
  54. * @param string $userName
  55. * @param string $remark
  56. * @param array $transferDetailList
  57. * @param string $transferSceneId
  58. * @param string $type
  59. * @param string $perception
  60. * @return void
  61. */
  62. public function transferBills(
  63. string $outBatchNo,
  64. string $amount,
  65. string $openid,
  66. string $userName,
  67. string $remark,
  68. array $transferDetailList,
  69. string $transferSceneId = '1000',
  70. string $type = 'wechat',
  71. string $perception = '现金奖励'
  72. ) {
  73. $appId = $this->app['config']['app_id'];
  74. $data = [
  75. 'appid' => $appId,
  76. 'out_bill_no' => $outBatchNo,
  77. 'transfer_scene_id' => $transferSceneId,
  78. 'openid' => $openid,
  79. 'transfer_amount' => (int)bcmul($amount, 100, 0),
  80. 'transfer_remark' => $remark,
  81. 'notify_url' => systemConfig('site_url') . Route::buildUrl('mchNotify',['type' => $type])->build(),
  82. 'user_recv_perception' => $perception,
  83. 'transfer_scene_report_infos' => $transferDetailList,
  84. ];
  85. if ($amount >= 200000) {
  86. if (empty($userName)) {
  87. throw new ValidateException('明细金额大于等于2000时,收款人姓名必须填写');
  88. }
  89. $data['user_name'] = $this->encryptSensitiveInformation($userName);
  90. }
  91. Log::info('发起转账 data :' . var_export($data, 1));
  92. $res = $this->request(self::API_TRANSFER_BILLS_URL, 'POST', ['sign_body' => json_encode($data)]);
  93. if (!$res || isset($res['code'], $res['message'])) {
  94. throw new ValidateException('微信商家转账:'.$res['message'] ?? '发起商家转账失败');
  95. }
  96. $res['app_id'] = $appId;
  97. $res['mch_id'] = $this->app['config']['payment']['merchant_id'];
  98. return $res;
  99. }
  100. public function handleNotify($callback)
  101. {
  102. $request = request();
  103. $data = $request->post('resource', []);
  104. $data = $this->decrypt($data);
  105. $handleResult = call_user_func_array($callback, [json_decode($data, true)]);
  106. if (is_bool($handleResult) && $handleResult) {
  107. $response = [
  108. 'code' => 'SUCCESS',
  109. 'message' => 'OK',
  110. ];
  111. } else {
  112. $response = [
  113. 'code' => 'FAIL',
  114. 'message' => $handleResult,
  115. ];
  116. }
  117. return response($response, 200, [], 'json');
  118. }
  119. }