PartnerPayService.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. <?php
  2. namespace app\common\library\xmwechat\payment;
  3. use app\common\library\xmwechat\SingletonTrait;
  4. use app\common\library\xmwechat\WechatService;
  5. use EasyWeChat\Pay\Application;
  6. use Symfony\Component\HttpClient\Exception\ClientException;
  7. use Symfony\Component\HttpClient\Exception\ServerException;
  8. use think\facade\Log;
  9. /**
  10. * 微信合作伙伴(服务商)
  11. * https://pay.weixin.qq.com/docs/partner/apis/partner-mini-program-payment/partner-mini-prepay.html
  12. */
  13. class PartnerPayService extends WechatService
  14. {
  15. protected ?Application $app = null;
  16. use SingletonTrait;
  17. public function __construct()
  18. {
  19. parent::__construct();
  20. if (empty($this->wechatPartnerPayConfig['sp_mchid']) || empty($this->wechatPartnerPayConfig['sp_appid']) || empty($this->wechatPartnerPayConfig['sub_mchid']) || empty($this->wechatPartnerPayConfig['secret_key'])) {
  21. $this->result('请配置服务商支付相关参数');
  22. }
  23. $partnerPayConfig = [
  24. 'mch_id' => $this->wechatPartnerPayConfig['sp_mchid'],
  25. 'secret_key' => $this->wechatPartnerPayConfig['secret_key'],
  26. 'certificate' => root_path() . $this->wechatPartnerPayConfig['cert_path'],
  27. 'private_key' => root_path() . $this->wechatPartnerPayConfig['key_path'],
  28. 'notify_url' => $this->wechatPartnerPayConfig['notify_url'],
  29. 'http' => [
  30. 'throw' => true, // 状态码非 200、300 时是否抛出异常,默认为开启
  31. 'timeout' => 5.0,
  32. ],
  33. ];
  34. $this->app = new Application($partnerPayConfig);
  35. }
  36. /**
  37. * 服务商模式支付(小程序)
  38. * @param array $params
  39. * @return false|mixed[]|void
  40. * @author jsjxsz
  41. */
  42. public function pay(array $params)
  43. {
  44. if ($params) {
  45. try {
  46. $order_no = $params['order_no'];
  47. $response = $this->app->getClient()->postJson("/v3/pay/partner/transactions/jsapi", [
  48. 'sp_appid' => $this->wechatPartnerPayConfig['sp_appid'],// 服务商appid
  49. 'sp_mchid' => $this->wechatPartnerPayConfig['sp_mchid'],// 服务商商户号
  50. 'sub_mchid' => $this->wechatPartnerPayConfig['sub_mchid'],// 子商户号
  51. "out_trade_no" => $params['transaction_no'],// 交易号
  52. "description" => $params['body'],
  53. "notify_url" => $this->wechatPartnerPayConfig['notify_url'],// 回调地址
  54. "amount" => [
  55. "total" => intval($params['pay_price'] * 100),
  56. "currency" => "CNY"
  57. ],
  58. "payer" => [
  59. "sub_openid" => $params['openid']
  60. ]
  61. ]);
  62. $result = $response->toArray();
  63. if (!empty($result['prepay_id'])) {
  64. $prepayId = $result['prepay_id'];
  65. $utils = $this->app->getUtils();
  66. // 微信小程序appid; 公众号支付需用公众号appid
  67. $appId = $params['pay_type'] == 'miniProgram' ? $this->miniProgramConfig['app_id'] : $this->offiAccountConfig['app_id'];
  68. // 默认RSA,v2要传MD5
  69. $signType = 'RSA';
  70. $payResult = $utils->buildBridgeConfig($prepayId, $appId, $signType);
  71. if (isset($payResult['paySign']) && !empty($payResult['paySign'])) {
  72. return $payResult;
  73. }
  74. }
  75. } catch (ServerException|ClientException|\Exception $exception) {
  76. Log::info('wechatPartnerPay:' . $exception->getMessage());
  77. }
  78. return false;
  79. }
  80. }
  81. /**
  82. * 服务商模式退款(公众号、小程序)
  83. * @param $params
  84. * @return bool|string
  85. * @author jsjxsz
  86. */
  87. public function refunds($params): bool|string
  88. {
  89. try {
  90. $app = $this->app;
  91. $response = $app->getClient()->postJson("/v3/refund/domestic/refunds", [
  92. 'sub_mchid' => $this->wechatPartnerPayConfig['sub_mchid'],// 子商户号
  93. "out_trade_no" => $params['out_trade_no'],// 原支付交易对应的商户订单号
  94. "out_refund_no" => $params['out_refund_no'],// 商户退款单号,商户系统内部的退款单号,退款时生成,唯一
  95. "reason" => $params['reason'], //退款原因
  96. "notify_url" => $this->wechatPartnerPayConfig['refunds_notify_url'],
  97. "amount" => [
  98. // 退款金额,单位为分,只能为整数,不能超过原订单支付金额。
  99. "refund" => intval($params['refund_price'] * 100),
  100. // 原支付交易的订单总金额,单位为分,只能为整数。
  101. "total" => intval($params['pay_price'] * 100),
  102. "currency" => "CNY"
  103. ]
  104. ]);
  105. $result = $response->toArray();
  106. if (isset($result['status'])) {
  107. return $result['status'];
  108. }
  109. } catch (ServerException|ClientException|\Exception $exception) {
  110. Log::info('wechayPartnerRefunds:' . $exception->getMessage());
  111. }
  112. return false;
  113. }
  114. }