bypay.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <?php
  2. namespace App\Http\Controllers\Gateway;
  3. use App\Models\Payment;
  4. use Auth;
  5. use Illuminate\Http\JsonResponse;
  6. use Illuminate\Http\Request;
  7. use Response;
  8. use Illuminate\Support\Facades\Http;
  9. use Illuminate\Support\Facades\Log;
  10. class bypay extends AbstractPayment
  11. {
  12. public function purchase(Request $request): JsonResponse
  13. {
  14. $payment = $this->creatNewPayment(Auth::id(), $request->input('id'), $request->input('amount'));
  15. // switch ($request->input('type')) {
  16. // case 2:
  17. // $type = 'qqpay';
  18. // break;
  19. // case 3:
  20. // $type = 'wxpay';
  21. // break;
  22. // case 1:
  23. // default:
  24. // $type = 'alipay';
  25. // break;
  26. // }
  27. /*
  28. merchantId 商户号-平台统一提供的唯一ID号 true string
  29. merchantOrderId 商户订单号[自行维护唯一性] true string
  30. payCode 支付编码[alipay]|JD|zfb|wx] true string
  31. amount 支付金额(单位:元) 可以0.01元 true string
  32. callbackUrl 异步通知地址 true string
  33. notifyUrl 同步跳转地址 false string
  34. userLocalIp 用户IP true string
  35. sign 签名[参考平台签名算法] true string
  36. ext 附加参数[异步通知原路返回] false string
  37. SHA256 签名介绍
  38. 第一步,设所有发送或者接收到的数据为集合M,将集合M内的[参数名]按照参 ASCII 码从小到大排序(字典序)
  39. 第二步,使用 URL 键值对的格式(即 key1=value1&key2=value2…),将集合M内参数值,拼接成字符串 stringA; 参数中 sign 不参与签名
  40. 第三步,在 stringA 的最后拼接上 "&key=商户密钥值",得到字符串 stringB
  41. 第四步,对 stringB 进行 SHA256 运算,得到 stringC
  42. 第五步,将字符串 stringC 转换为大写,最后得到 签名值 sign
  43. */
  44. $key = "e7c359e9146345de86a41a099cacd67f";
  45. $data = [
  46. 'merchantId' => "1654045635701374976",
  47. 'merchantOrderId' => $payment->trade_no,
  48. 'payCode' => "wgzfbsm",
  49. 'amount' => $payment->amount,
  50. 'userLocalIp' => "192.178.31.34",
  51. 'notifyUrl' => route('invoice'),
  52. 'callbackUrl' => route('payment.notify', ['method' => 'bypay']),
  53. ];
  54. $str = $this->sortParams($data) . '&key=' . $key; //stringB
  55. Log::info("[BYPZ]请求支付接口". var_export($str, true));
  56. $StringC = strtolower($this->sha256($str));
  57. Log::info("[BYPZ]请求支付接口". var_export($StringC, true));
  58. $data['sign'] = strtoupper($StringC); //stringC
  59. Log::info("[BYPZ]请求支付接口". var_export($data, true));
  60. $postData = json_encode($data);
  61. $curl = curl_init();
  62. curl_setopt($curl, CURLOPT_URL, "https://bjzf88.vip/api/unifiedOrder/v2");
  63. curl_setopt($curl, CURLOPT_HEADER, 0);
  64. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  65. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  66. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  67. curl_setopt($curl, CURLOPT_POST, 1);
  68. curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
  69. curl_setopt($curl, CURLOPT_HTTPHEADER, array(
  70. 'Content-Type: application/json',
  71. 'Content-Length: ' . strlen($postData))
  72. );
  73. $res = curl_exec($curl);
  74. curl_close($curl);
  75. $result = json_decode($res, true);
  76. if (!$result) {
  77. return Response::json(['status' => 'success', 'url' => "", 'message' => '网络异常!']);
  78. }
  79. Log::info("[BYPZ]请求支付接口". var_export($result, true));
  80. if ($result["status"] != 200){
  81. return Response::json(['status' => 'fail', 'message' => '创建订单失败!'.$result['error']]);
  82. }
  83. return Response::json(['status' => 'success', 'url' => $result['data'], 'message' => '创建订单成功!']);
  84. }
  85. public function notify(Request $request): void
  86. {
  87. $postData = file_get_contents('php://input');
  88. $result = json_decode($postData,true);
  89. Log::info("[BYPZ]回调内容1". var_export($result, true));
  90. $notifyData = [
  91. 'merchantId'=>$result['merchantId'],
  92. 'merchantOrderId'=>$result['merchantOrderId'],
  93. 'orderId'=>$result['orderId'],
  94. 'amount'=>$result['amount'],
  95. 'factAmount'=>$result['factAmount'],
  96. 'ext'=>$result['ext'],
  97. 'state'=>$result['state'],
  98. 'sign'=>$result['sign']
  99. ];
  100. if ($this->verifySign($notifyData)){
  101. exit('fail');
  102. }
  103. Log::info("[BYPZ]回调内容". var_export($notifyData, true));
  104. if ($this->paymentReceived($notifyData['merchantOrderId']) ) {
  105. $this->addPamentCallback($notifyData['merchantOrderId'] ,$notifyData['orderId'] ,"");
  106. Log::info('【BYPZ】paymentReceived:'.var_export($request->all(), true));
  107. exit('success');
  108. }
  109. }
  110. function ASCII($params = array()){
  111. //ksort()对数组按照键名进行升序排序
  112. ksort($params);
  113. //reset()内部指针指向数组中的第一个元素
  114. reset($params);
  115. $str = http_build_query($params);
  116. return $str;
  117. }
  118. function verifySign($params)
  119. {
  120. $key = "e7c359e9146345de86a41a099cacd67f";
  121. $sign = $params['sign'];
  122. unset($params['sign']);
  123. ksort($params);
  124. $str = $this->sortParams($params) . '&key='.$key;
  125. $StringC = strtolower($this->sha256($str));
  126. if ($sign !== strtoupper($StringC)) {
  127. return false;
  128. }
  129. return $str;
  130. // 剃离sign,sign_type,空值
  131. // unset($data['sign'], $data['sign_type'] , $data["method"]);
  132. // if ($filter) {
  133. // $data = array_filter($data);
  134. // }
  135. // 排序
  136. // ksort($data, SORT_STRING);
  137. // reset($data);
  138. //
  139. //
  140. // $data["key"] = $key;
  141. // return strtoupper(md5(urldecode(http_build_query($data))));
  142. }
  143. function sortParams($params) {
  144. ksort($params);
  145. $str = '';
  146. foreach ($params as $key => $value) {
  147. $str .= $key . '=' . $value . '&';
  148. }
  149. return rtrim($str, '&');
  150. }
  151. function sha256($str) {
  152. $hash = hash('sha256', $str, true);
  153. $encdeStr = bin2hex($hash);
  154. return strtolower($encdeStr);
  155. }
  156. }