WorkerWeChatPayService.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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. if ($userId !== null) {
  52. $this->auth = MasterWorkerAuth::where(['worker_id' => $userId, 'terminal' => $terminal])->findOrEmpty();
  53. }
  54. }
  55. /**
  56. * @notes 发起微信支付统一下单
  57. * @param $from
  58. * @param $order
  59. * @return array|false|string
  60. * @author 段誉
  61. * @date 2021/8/4 15:05
  62. */
  63. public function pay($from, $order)
  64. {
  65. try {
  66. switch ($this->terminal) {
  67. case UserTerminalEnum::WECHAT_MMP:
  68. $config = WorkerWeChatConfigService::getMnpConfig();
  69. $result = $this->jsapiPay($from, $order, $config['app_id']);
  70. break;
  71. default:
  72. throw new \Exception('支付方式错误');
  73. }
  74. return [
  75. 'config' => $result,
  76. 'pay_way' => PayEnum::WECHAT_PAY
  77. ];
  78. } catch (\Exception $e) {
  79. $this->setError($e->getMessage());
  80. return false;
  81. }
  82. }
  83. /**
  84. * @notes jsapiPay
  85. * @param $from
  86. * @param $order
  87. * @param $appId
  88. * @return mixed
  89. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  90. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  91. * @author 段誉
  92. * @date 2023/2/28 12:12
  93. */
  94. public function jsapiPay($from, $order, $appId)
  95. {
  96. $response = $this->app->getClient()->postJson("v3/pay/transactions/jsapi", [
  97. "appid" => $appId,
  98. "mchid" => $this->config['mch_id'],
  99. "description" => $this->payDesc($from),
  100. "out_trade_no" => $order['pay_sn'],
  101. "notify_url" => $this->config['notify_url'],
  102. "amount" => [
  103. "total" => intval($order['order_amount'] * 100),
  104. ],
  105. "payer" => [
  106. "openid" => $this->auth['openid']
  107. ],
  108. 'attach' => $from
  109. ]);
  110. $result = $response->toArray(false);
  111. $this->checkResultFail($result);
  112. return $this->getPrepayConfig($result['prepay_id'], $appId);
  113. }
  114. /**
  115. * @notes 支付描述
  116. * @param $from
  117. * @return string
  118. * @author 段誉
  119. * @date 2023/2/27 17:54
  120. */
  121. public function payDesc($from)
  122. {
  123. $desc = [
  124. 'goods' => '商品',
  125. 'recharge' => '充值',
  126. ];
  127. return $desc[$from] ?? '商品';
  128. }
  129. /**
  130. * @notes 捕获错误
  131. * @param $result
  132. * @throws \Exception
  133. * @author 段誉
  134. * @date 2023/2/28 12:09
  135. */
  136. public function checkResultFail($result)
  137. {
  138. if (!empty($result['code']) || !empty($result['message'])) {
  139. throw new \Exception('微信:'. $result['code'] . '-' . $result['message']);
  140. }
  141. }
  142. /**
  143. * @notes 预支付配置
  144. * @param $prepayId
  145. * @param $appId
  146. * @return mixed[]
  147. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  148. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  149. * @author 段誉
  150. * @date 2023/2/28 17:38
  151. */
  152. public function getPrepayConfig($prepayId, $appId)
  153. {
  154. return $this->app->getUtils()->buildBridgeConfig($prepayId, $appId);
  155. }
  156. /**
  157. * @notes 支付回调
  158. * @return \Psr\Http\Message\ResponseInterface
  159. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  160. * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
  161. * @throws \ReflectionException
  162. * @throws \Throwable
  163. * @author 段誉
  164. * @date 2023/2/28 14:20
  165. */
  166. public function notify()
  167. {
  168. $server = $this->app->getServer();
  169. // 支付通知
  170. $server->handlePaid(function (Message $message) {
  171. if ($message['trade_state'] === 'SUCCESS') {
  172. $extra['transaction_id'] = $message['transaction_id'];
  173. $attach = $message['attach'];
  174. $message['out_trade_no'] = mb_substr($message['out_trade_no'], 0, 18);
  175. $order = RechargeOrder::where(['sn' => $message['out_trade_no']])->findOrEmpty();
  176. if($order->isEmpty() || $order->pay_status == PayEnum::ISPAID) {
  177. return true;
  178. }
  179. switch ($attach) {
  180. case 'recharge':
  181. PayNotifyLogic::handle('recharge', $message['out_trade_no'], $extra);
  182. break;
  183. case 'goods':
  184. PayNotifyLogic::handle('goods', $message['out_trade_no'], $extra);
  185. break;
  186. case 'shop_goods':
  187. PayNotifyLogic::handle('shop_goods', $message['out_trade_no'], $extra);
  188. break;
  189. }
  190. }
  191. return true;
  192. });
  193. // 退款通知
  194. $server->handleRefunded(function (Message $message) {
  195. return true;
  196. });
  197. return $server->serve();
  198. }
  199. }