WorkerWeChatPayService.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <?php
  2. namespace app\common\service\pay;
  3. use app\common\enum\PayEnum;
  4. use app\common\enum\user\UserTerminalEnum;
  5. use app\common\logic\PayNotifyLogic;
  6. use app\common\model\master_worker\MasterWorkerAuth;
  7. use app\common\model\recharge\RechargeOrder;
  8. use app\common\model\user\UserAuth;
  9. use app\common\service\wechat\WeChatConfigService;
  10. use app\common\service\wechat\WorkerWeChatConfigService;
  11. use EasyWeChat\Pay\Application;
  12. use EasyWeChat\Pay\Message;
  13. use think\facade\Log;
  14. /**
  15. * 微信支付
  16. * Class WorkerWeChatPayService
  17. * @package app\common\server
  18. */
  19. class WorkerWeChatPayService extends BasePayService
  20. {
  21. /**
  22. * 授权信息
  23. * @var UserAuth|array|\think\Model
  24. */
  25. protected $auth;
  26. /**
  27. * 微信配置
  28. * @var
  29. */
  30. protected $config;
  31. /**
  32. * easyWeChat实例
  33. * @var
  34. */
  35. protected $app;
  36. /**
  37. * 当前使用客户端
  38. * @var
  39. */
  40. protected $terminal;
  41. /**
  42. * 初始化微信支付配置
  43. * @param $terminal //用户终端
  44. * @param null $userId //用户id(获取授权openid)
  45. */
  46. public function __construct($terminal, $userId = null)
  47. {
  48. $this->terminal = $terminal;
  49. $this->config = WeChatConfigService::getPayConfigByTerminal($terminal);
  50. $this->app = new Application($this->config);
  51. $this->auth = MasterWorkerAuth::where(['worker_id' => $userId, 'terminal' => $terminal])->findOrEmpty();
  52. }
  53. /**
  54. * @notes 发起微信支付统一下单
  55. * @param $from
  56. * @param $order
  57. * @return array|false|string
  58. * @author 段誉
  59. * @date 2021/8/4 15:05
  60. */
  61. public function pay($from, $order)
  62. {
  63. try {
  64. switch ($this->terminal) {
  65. case UserTerminalEnum::WECHAT_MMP:
  66. $config = WorkerWeChatConfigService::getMnpConfig();
  67. $result = $this->jsapiPay($from, $order, $config['app_id']);
  68. break;
  69. default:
  70. throw new \Exception('支付方式错误');
  71. }
  72. return [
  73. 'config' => $result,
  74. 'pay_way' => PayEnum::WECHAT_PAY
  75. ];
  76. } catch (\Exception $e) {
  77. $this->setError($e->getMessage());
  78. return false;
  79. }
  80. }
  81. /**
  82. * @notes jsapiPay
  83. * @param $from
  84. * @param $order
  85. * @param $appId
  86. * @return mixed
  87. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  88. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  89. * @author 段誉
  90. * @date 2023/2/28 12:12
  91. */
  92. public function jsapiPay($from, $order, $appId)
  93. {
  94. $response = $this->app->getClient()->postJson("v3/pay/transactions/jsapi", [
  95. "appid" => $appId,
  96. "mchid" => $this->config['mch_id'],
  97. "description" => $this->payDesc($from),
  98. "out_trade_no" => $order['pay_sn'],
  99. "notify_url" => $this->config['notify_url'],
  100. "amount" => [
  101. "total" => intval($order['order_amount'] * 100),
  102. ],
  103. "payer" => [
  104. "openid" => $this->auth['openid']
  105. ],
  106. 'attach' => $from
  107. ]);
  108. $result = $response->toArray(false);
  109. $this->checkResultFail($result);
  110. return $this->getPrepayConfig($result['prepay_id'], $appId);
  111. }
  112. /**
  113. * @notes 支付描述
  114. * @param $from
  115. * @return string
  116. * @author 段誉
  117. * @date 2023/2/27 17:54
  118. */
  119. public function payDesc($from)
  120. {
  121. $desc = [
  122. 'goods' => '商品',
  123. 'recharge' => '充值',
  124. ];
  125. return $desc[$from] ?? '商品';
  126. }
  127. /**
  128. * @notes 捕获错误
  129. * @param $result
  130. * @throws \Exception
  131. * @author 段誉
  132. * @date 2023/2/28 12:09
  133. */
  134. public function checkResultFail($result)
  135. {
  136. if (!empty($result['code']) || !empty($result['message'])) {
  137. throw new \Exception('微信:'. $result['code'] . '-' . $result['message']);
  138. }
  139. }
  140. /**
  141. * @notes 预支付配置
  142. * @param $prepayId
  143. * @param $appId
  144. * @return mixed[]
  145. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  146. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  147. * @author 段誉
  148. * @date 2023/2/28 17:38
  149. */
  150. public function getPrepayConfig($prepayId, $appId)
  151. {
  152. return $this->app->getUtils()->buildBridgeConfig($prepayId, $appId);
  153. }
  154. /**
  155. * @notes 支付回调
  156. * @return \Psr\Http\Message\ResponseInterface
  157. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  158. * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
  159. * @throws \ReflectionException
  160. * @throws \Throwable
  161. * @author 段誉
  162. * @date 2023/2/28 14:20
  163. */
  164. public function notify()
  165. {
  166. $server = $this->app->getServer();
  167. // 支付通知
  168. $server->handlePaid(function (Message $message) {
  169. Log::write(json_encode($message, JSON_UNESCAPED_UNICODE));
  170. if ($message['trade_state'] === 'SUCCESS') {
  171. $extra['transaction_id'] = $message['transaction_id'];
  172. $attach = $message['attach'];
  173. $message['out_trade_no'] = mb_substr($message['out_trade_no'], 0, 18);
  174. $order = RechargeOrder::where(['sn' => $message['out_trade_no']])->findOrEmpty();
  175. if($order->isEmpty() || $order->pay_status == PayEnum::ISPAID) {
  176. return true;
  177. }
  178. switch ($attach) {
  179. case 'recharge':
  180. PayNotifyLogic::handle('recharge', $message['out_trade_no'], $extra);
  181. break;
  182. case 'goods':
  183. PayNotifyLogic::handle('goods', $message['out_trade_no'], $extra);
  184. break;
  185. }
  186. }
  187. return true;
  188. });
  189. // 退款通知
  190. $server->handleRefunded(function (Message $message) {
  191. return true;
  192. });
  193. return $server->serve();
  194. }
  195. }