WorkerWeChatPayService.php 6.8 KB

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