PaymentService.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. <?php
  2. /**
  3. * @Name
  4. * @Description
  5. * @Author 刘学玺
  6. * @Date 2024/10/17 14:43
  7. */
  8. namespace App\Http\Services\Frontend\Client\Wechat;
  9. use App\Http\Services\Service;
  10. use App\Models\Member\User;
  11. use App\Models\Service\Order;
  12. use EasyWeChat\Pay\Application;
  13. use EasyWeChat\Pay\Message;
  14. use Exception;
  15. use Illuminate\Support\Carbon;
  16. use Illuminate\Support\Facades\Auth;
  17. use Illuminate\Support\Facades\Log;
  18. use Overtrue\LaravelWeChat\EasyWeChat;
  19. use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
  20. use Throwable;
  21. class PaymentService extends Service
  22. {
  23. /**
  24. * @throws TransportExceptionInterface
  25. */
  26. public function payment(array $params)
  27. {
  28. try {
  29. $order_id = $params['order_id'];
  30. !$order_id && self::error('订单异常');
  31. // 查询订单详情
  32. $order = Order::query()->find($order_id);
  33. !$order && self::error('订单错误');
  34. $order->status === 1 && self::error('订单已支付');
  35. $order->status && self::error('订单状态异常');
  36. // 获取用户Openid
  37. $openid = User::query()->where('id', Auth::id())->value('openid');
  38. $pay = EasyWeChat::pay();
  39. $merchant = $pay->getMerchant();
  40. // $app = EasyWeChat::officialAccount();
  41. // $client = $app->getClient();
  42. $config = EasyWeChat::pay()->getConfig();
  43. $app = new Application($config);
  44. $openid = 'oBxIn6qjN6YCjz1iElb5NDfBdYaM';
  45. $response = $app->getClient()->postJson("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi", [
  46. "mchid" => (string)$merchant->getMerchantId(), // <---- 请修改为您的商户号
  47. "out_trade_no" => $order->order_sn, //uniqid('native') . rand(1, 1000), // "native12177525012012070352333'.rand(1,1000).'",
  48. "appid" => $app->getConfig()->get('app_id'), // <---- 请修改为服务号的 appid
  49. "description" => $order->project_name,
  50. "notify_url" => env('BACKEND_URL') . env('WECHAT_PAYMENT_NOTIFY_URL'),
  51. "amount" => [
  52. "total" => intval(round($order->pay_price * 100)),
  53. "currency" => "CNY"
  54. ],
  55. "payer" => [
  56. "openid" => $openid // <---- 请修改为服务号下单用户的 openid
  57. ]
  58. ]);
  59. $app->getValidator()->validate($response->toPsrResponse());
  60. // 验证通过
  61. // dd($response->toArray(false));
  62. $prepayId = $response['prepay_id'];
  63. $sign = [
  64. 'appId' => $config['app_id'], // 公众号 appid
  65. 'timeStamp' => (string)time(), // 时间戳
  66. 'nonceStr' => uniqid(), // 随机字符串
  67. 'package' => 'prepay_id=' . $prepayId, // prepay_id
  68. // 'signType' => 'RSA', // 签名类型,默认为 MD5
  69. ];
  70. $privateKey = file_get_contents($config['private_key']); // 拼接 key
  71. // 对参数进行排序并拼接成字符串
  72. // ksort($sign);
  73. $stringA = implode('\n', array_values($sign)) . '\n';
  74. // 使用 OpenSSL 生成签名
  75. // openssl_sign($stringA, $signature, $privateKey, OPENSSL_ALGO_SHA256);
  76. $greeting = <<<EOD
  77. {$sign['appId']}
  78. {$sign['timeStamp']}
  79. {$sign['nonceStr']}
  80. {$sign['package']}
  81. EOD;
  82. openssl_sign($greeting, $signature, $privateKey, OPENSSL_ALGO_SHA256);
  83. $sign['paySign'] = base64_encode($signature); // 生成签名
  84. $sign['signType'] = 'RSA'; // 签名类型,默认为 MD5
  85. return $sign;
  86. } catch (\Exception $e) {
  87. self::error($e->getMessage());
  88. // return response()->json(['error' => $e->getMessage()], 500);
  89. }
  90. // $app = EasyWeChat::pay();
  91. //
  92. // $server = $app->getServer();
  93. //// $server->prepend()
  94. // $server->handlePaid(function (Message $message, \Closure $next) use ($app) {
  95. // try {
  96. // $app->getValidator()->validate($app->getRequest());
  97. // // 验证通过,业务处理
  98. // } catch (Exception $e) {
  99. // // 验证失败
  100. // }
  101. // return $next($message);
  102. // });
  103. // return $server->serve();
  104. }
  105. /**
  106. * @throws Throwable
  107. */
  108. public function notify(): \Illuminate\Http\JsonResponse
  109. {
  110. try {
  111. $pay = EasyWeChat::pay();
  112. $server = $pay->getServer();
  113. $server->handlePaid(function (Message $message, \Closure $next) {
  114. $out_trade_no = $message['out_trade_no'];
  115. if ($message['trade_state'] === 'SUCCESS') {
  116. $order = Order::query()->where('order_sn', $out_trade_no)->first();
  117. Log::log('INFO', '$order', $order->toArray());
  118. if ($order->status === 0) {
  119. $order->status = 1;
  120. $order->transaction_id = $message['transaction_id'];
  121. $order->pay_time = Carbon::parse($message['success_time'])->timestamp;
  122. $order->save();
  123. }
  124. }
  125. // $message->out_trade_no 获取商户订单号
  126. // $message->payer['openid'] 获取支付者 openid
  127. // 🚨🚨🚨 注意:推送信息不一定靠谱哈,请务必验证
  128. // 建议是拿订单号调用微信支付查询接口,以查询到的订单状态为准
  129. // Log::log('INFO', 'payNotify', (array)$message);
  130. return $next($message);
  131. });
  132. // 默认返回 ['code' => 'SUCCESS', 'message' => '成功']
  133. $res = $server->serve();
  134. return response()->json(json_decode($res->getBody()->getContents(), true), $res->getStatusCode());
  135. } catch (Exception $e) {
  136. Log::log('error', $e->getMessage());
  137. return response()->json(['code' => 'FAIL', "message" => "失败"], 500);
  138. }
  139. }
  140. }