Alipay.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. <?php
  2. namespace addons\shopro\library\pay\provider;
  3. use think\Log;
  4. use think\exception\HttpResponseException;
  5. use addons\shopro\service\pay\PayRefund;
  6. use Yansongda\Pay\Pay;
  7. class Alipay extends Base
  8. {
  9. protected $payService = null;
  10. protected $pay = null;
  11. protected $platform = null;
  12. public function __construct($payService, $platform = null)
  13. {
  14. $this->payService = $payService;
  15. $this->platform = $platform;
  16. }
  17. public function pay($order, $config = [], $from = null)
  18. {
  19. $this->init('alipay', $config);
  20. if (in_array($this->platform, ['WechatOfficialAccount', 'WechatMiniProgram', 'H5'])) {
  21. // 返回支付宝支付链接
  22. if (!$from == 'url') {
  23. // return request()->domain() . '/shop/api/pay/alipay?pay_sn=' . $order['out_trade_no'] . '&platform=' . $this->platform . '&return_url=' . urlencode($this->config['alipay']['default']['return_url']);
  24. return request()->domain() . '/addons/shopro/pay/alipay?pay_sn=' . $order['out_trade_no'] . '&platform=' . $this->platform . '&return_url=' . urlencode($this->config['alipay']['default']['return_url']);
  25. }
  26. }
  27. $method = $this->getMethod('alipay');
  28. $result = Pay::alipay()->$method($order);
  29. return $result;
  30. }
  31. public function transfer($payload, $config = [])
  32. {
  33. $this->init('alipay', $config);
  34. $code = 0;
  35. $response = Pay::alipay()->transfer($payload);
  36. if ($response['code'] === '10000' && $response['status'] === 'SUCCESS') {
  37. $code = 1;
  38. }
  39. return [$code, $response];
  40. }
  41. public function notify($callback, $config = [])
  42. {
  43. $this->init('alipay', $config);
  44. try {
  45. $data = Pay::alipay()->callback(); // 是的,验签就这么简单!
  46. // { // 支付宝支付成功回调参数
  47. // "gmt_create": "2022-06-21 14:54:39",
  48. // "charset": "utf-8",
  49. // "seller_email": "xptech@qq.com",
  50. // "subject": "\u5546\u57ce\u8ba2\u5355\u652f\u4ed8",
  51. // "buyer_id": "2088902485164146",
  52. // "invoice_amount": "0.01",
  53. // "notify_id": "2022062100222145440064141420932810",
  54. // "fund_bill_list": "[{\"amount\":\"0.01\",\"fundChannel\":\"ALIPAYACCOUNT\"}]",
  55. // "notify_type": "trade_status_sync",
  56. // "trade_status": "TRADE_SUCCESS",
  57. // "receipt_amount": "0.01",
  58. // "buyer_pay_amount": "0.01",
  59. // "app_id": "2021001114666742",
  60. // "seller_id": "2088721922277739",
  61. // "gmt_payment": "2022-06-21 14:54:40",
  62. // "notify_time": "2022-06-21 14:54:41",
  63. // "version": "1.0",
  64. // "out_trade_no": "P202202383569762189002100",
  65. // "total_amount": "0.01",
  66. // "trade_no": "2022062122001464141435375324",
  67. // "auth_app_id": "2021001114666742",
  68. // "buyer_logon_id": "157***@163.com",
  69. // "point_amount": "0.00"
  70. // }
  71. // { // 支付宝退款成功(交易关闭)回调参数
  72. // "gmt_create": "2022-06-21 15:31:34",
  73. // "charset": "utf-8",
  74. // "seller_email": "xptech@qq.com",
  75. // "gmt_payment": "2022-06-21 15:31:34",
  76. // "notify_time": "2022-06-21 15:53:32",
  77. // "subject": "商城订单支付",
  78. // "gmt_refund": "2022-06-21 15:53:32.158",
  79. // "out_biz_no": "R202203533190902732002100",
  80. // "buyer_id": "2088902485164146",
  81. // "version": "1.0",
  82. // "notify_id": "2022062100222155332064141421692866",
  83. // "notify_type": "trade_status_sync",
  84. // "out_trade_no": "P202203305611515511002100",
  85. // "total_amount": "0.01",
  86. // "trade_status": "TRADE_CLOSED",
  87. // "refund_fee": "0.01",
  88. // "trade_no": "2022062122001464141435383344",
  89. // "auth_app_id": "2021001114666742",
  90. // "buyer_logon_id": "157***@163.com",
  91. // "gmt_close": "2022-06-21 15:53:32",
  92. // "app_id": "2021001114666742",
  93. // "seller_id": "2088721922277739"
  94. // }
  95. Log::write('pay-notify-origin-data:' . json_encode($data));
  96. // 判断是否是支付宝退款(支付宝退款成功会通知该接口)
  97. $out_trade_no = $data['out_trade_no']; // 商户单号
  98. $out_refund_no = $data['out_biz_no'] ?? ''; // 退款单号
  99. if (
  100. $data['notify_type'] == 'trade_status_sync' // 同步交易状态
  101. && $data['trade_status'] == 'TRADE_CLOSED' // 交易关闭
  102. && $out_refund_no // 退款单号
  103. ) {
  104. // 交给退款实例处理
  105. $refund = new PayRefund();
  106. $refund->notify([
  107. 'out_trade_no' => $out_trade_no,
  108. 'out_refund_no' => $out_refund_no,
  109. 'payment_json' => json_encode($data)
  110. ]);
  111. return Pay::alipay()->success();
  112. }
  113. // 判断支付宝是否是支付成功状态,如果不是,直接返回响应
  114. if ($data['trade_status'] != 'TRADE_SUCCESS') {
  115. // 不是交易成功的通知,直接返回成功
  116. return Pay::alipay()->success();
  117. }
  118. $data['pay_fee'] = $data['total_amount'];
  119. $data['transaction_id'] = $data['trade_no'];
  120. $data['buyer_info'] = $data['buyer_logon_id'];
  121. return $callback($data);
  122. } catch (HttpResponseException $e) {
  123. $data = $e->getResponse()->getData();
  124. $message = $data ? ($data['msg'] ?? '') : $e->getMessage();
  125. format_log_error($e, 'alipayNotify.HttpResponseException', $message);
  126. return 'fail';
  127. } catch (\Exception $e) {
  128. format_log_error($e, 'alipayNotify');
  129. return 'fail';
  130. }
  131. }
  132. /**
  133. * 退款
  134. *
  135. * @param array $order_data
  136. * @param array $config
  137. * @return array
  138. */
  139. public function refund($order_data, $config = [])
  140. {
  141. $this->init('alipay', $config);
  142. $result = Pay::alipay()->refund($order_data);
  143. Log::write('pay-refund-origin-data:' . json_encode($result, JSON_UNESCAPED_UNICODE));
  144. // {
  145. // "code": "10000",
  146. // "msg": "Success",
  147. // "buyer_logon_id": "157***@163.com",
  148. // "buyer_user_id": "2088902485164146",
  149. // "fund_change": "Y",
  150. // "gmt_refund_pay": "2022-06-21 15:53:32",
  151. // "out_trade_no": "P202203305611515511002100",
  152. // "refund_fee": "0.01",
  153. // "send_back_fee": "0.00",
  154. // "trade_no": "2022062122001464141435383344"
  155. // }
  156. return $result;
  157. }
  158. /**
  159. * 格式化支付参数
  160. *
  161. * @param [type] $params
  162. * @return void
  163. */
  164. protected function formatConfig($config, $data = [])
  165. {
  166. $config['notify_url'] = request()->domain() . '/addons/shopro/pay/notify/payment/alipay/platform/' . $this->platform;
  167. if (in_array($this->platform, ['WechatOfficialAccount', 'WechatMiniProgram', 'H5'])) {
  168. // app 支付不能带着个参数
  169. $config['return_url'] = str_replace('&amp;', '&', request()->param('return_url', ''));
  170. }
  171. $config = $this->formatCert($config);
  172. return $config;
  173. }
  174. /**
  175. * 拼接支付证书绝对地址
  176. *
  177. * @param array $config
  178. * @return array
  179. */
  180. protected function formatCert($config)
  181. {
  182. $end = substr($config['app_secret_cert'], -4);
  183. if ($end == '.crt') {
  184. $config['app_secret_cert'] = ROOT_PATH . 'public' . $config['app_secret_cert'];
  185. }
  186. $config['alipay_public_cert_path'] = ROOT_PATH . 'public' . $config['alipay_public_cert_path'];
  187. $config['app_public_cert_path'] = ROOT_PATH . 'public' . $config['app_public_cert_path'];
  188. $config['alipay_root_cert_path'] = ROOT_PATH . 'public' . $config['alipay_root_cert_path'];
  189. // 兼容 epay
  190. $config['app_cert_public_key'] = $config['app_public_cert_path'];
  191. $config['alipay_root_cert'] = $config['alipay_root_cert_path'];
  192. return $config;
  193. }
  194. }