WechatPay.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. <?php namespace App\Http\Controllers\Api;
  2. use App\Http\Controllers\Api\Api;
  3. use App\Models\Custom;
  4. use App\Models\Orders;
  5. use App\Facades\Servers\Logs\Log;
  6. use EasyWeChat\Factory;
  7. use Illuminate\Http\Request;
  8. use App\Servers\WechatPay\Payment;
  9. use App\Facades\Servers\WechatMini\Mini;
  10. use WeChatPay\Formatter;
  11. use WeChatPay\Crypto\AesGcm;
  12. use WeChatPay\Crypto\Rsa;
  13. /**
  14. * 微信支付接口
  15. *
  16. * @author JUN
  17. *
  18. * */
  19. class WechatPay extends Api{
  20. /**
  21. * 小程序微信支付下单 /api/wechat_pay/pay
  22. *
  23. * */
  24. public function pay(Custom $Custom)
  25. {
  26. // 检查登录
  27. $uid = $this->checkLogin();
  28. $code = request('code','');
  29. $orderId = request('order_id','');
  30. $orderInfo = Orders::query()->where('id','=',$orderId)->first()->toArray();
  31. if (empty($orderInfo))
  32. return json_send(['code'=>'error','msg'=>'订单不存在','data'=>['id'=>null]]);
  33. if ($orderInfo['custom_uid'] != $uid)
  34. return json_send(['code'=>'error','msg'=>'无权操作','data'=>['id'=>null]]);
  35. if ($orderInfo['status'] != 1)
  36. return json_send(['code'=>'error','msg'=>'订单已支付或取消','data'=>['id'=>null]]);
  37. //获取openid
  38. $result = Mini::jscode2session($code);
  39. if (!$result['openid']) return json_send(['code'=>'error','msg'=>'获取openid失败','data'=>$result['error']]);
  40. $openid = $result['openid'];
  41. $payment = new Payment();
  42. return $payment->pay(['out_trade_no' => $orderInfo['snowflake_id'],'openid' => $openid,'description' => '开邻智教课程','total_price' => $orderInfo['pay_total']]);
  43. }
  44. /**
  45. * 小程序微信支付回调 /api/wechat_pay/notify
  46. *
  47. * */
  48. public function notify(Custom $Custom)
  49. {
  50. $post_data = request();
  51. Log::log('notify_wechat_pay', 'post_data:' . $post_data);
  52. //获取headers参数
  53. $headers = request()->header();
  54. Log::log('notify_wechat_pay', '微信支付回调返回headers参数:' . json_encode($headers));
  55. $inWechatpaySignature = $headers['wechatpay-signature'];
  56. $inWechatpayTimestamp = $headers['wechatpay-timestamp'];
  57. $inWechatpaySerial = $headers['wechatpay-serial'];
  58. $inWechatpayNonce = $headers['wechatpay-nonce'];
  59. $inBody = $post_data;
  60. $apiv3Key = Config('wechat.APIV3');// 在商户平台上设置的APIv3密钥
  61. // 根据通知的平台证书序列号,查询本地平台证书文件,
  62. $platformCertificateFilePath = Config('wechat.platformCertificate');
  63. $platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
  64. // 检查通知时间偏移量,允许5分钟之内的偏移
  65. $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
  66. Log::log('notify_wechat_pay', '时间偏移量:' . $timeOffsetStatus);
  67. $verifiedStatus = Rsa::verify(
  68. // 构造验签名串
  69. Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
  70. $inWechatpaySignature,
  71. $platformPublicKeyInstance
  72. );
  73. Log::log('notify_wechat_pay', '验签:' . $verifiedStatus);
  74. $orderService = new OrderService();
  75. if ($timeOffsetStatus && $verifiedStatus) {
  76. // 转换通知的JSON文本消息为PHP Array数组
  77. $inBodyArray = (array)json_decode($inBody, true);
  78. // 使用PHP7的数据解构语法,从Array中解构并赋值变量
  79. ['resource' => [
  80. 'ciphertext' => $ciphertext,
  81. 'nonce' => $nonce,
  82. 'associated_data' => $aad
  83. ]] = $inBodyArray;
  84. // 加密文本消息解密
  85. $inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
  86. // 把解密后的文本转换为PHP Array数组
  87. $inBodyResourceArray = (array)json_decode($inBodyResource, true);
  88. Log::log('notify_wechat_pay', '打印解密后的结果:' . json_encode($inBodyResourceArray));
  89. Log::log('notify_wechat_pay', '参数:' . $inBodyResourceArray['trade_state'] . '订单号' . $inBodyResourceArray['out_trade_no'] . '微信支付号' . $inBodyResourceArray['transaction_id']);
  90. if ($inBodyResourceArray['trade_state'] == "SUCCESS") {
  91. Log::log('notify_wechat_pay', '通知订单');
  92. $res = $orderService->payCallback($inBodyResourceArray['out_trade_no'], $inBodyResourceArray['transaction_id']);
  93. Log::log('notify_wechat_pay', '通知返回' . json_encode($res));
  94. }
  95. }
  96. }
  97. }