From 93a43d24a6efb705f019be0b95f60ec11fe5857a Mon Sep 17 00:00:00 2001 From: chenbo <709206448@qq.com> Date: Thu, 16 Nov 2023 17:33:16 +0800 Subject: [PATCH] =?UTF-8?q?add=20=E6=94=B9=E4=B8=BAv3=E6=94=AF=E4=BB=98?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E3=80=82=E6=96=B0=E5=A2=9E=E9=80=80=E6=AC=BE?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../logic/setting/pay/PayConfigLogic.php | 1 + .../WechatPayServiceMerchantPayController.php | 25 +++++++++ .../WechatPayServiceMerchantPaymentLogic.php | 23 +++++++- app/common/model/pay/RefundOrder.php | 10 ++++ .../service/pay/WeChatPayMerchantService.php | 56 +++++++++++-------- .../wechat/WeChatPayMerchantConfigService.php | 11 +++- 6 files changed, 100 insertions(+), 26 deletions(-) create mode 100644 app/common/model/pay/RefundOrder.php diff --git a/app/adminapi/logic/setting/pay/PayConfigLogic.php b/app/adminapi/logic/setting/pay/PayConfigLogic.php index 53f6cee..cc69e4f 100644 --- a/app/adminapi/logic/setting/pay/PayConfigLogic.php +++ b/app/adminapi/logic/setting/pay/PayConfigLogic.php @@ -51,6 +51,7 @@ class PayConfigLogic extends BaseLogic 'pay_sign_key' => $params['config']['pay_sign_key'], 'apiclient_cert' => $params['config']['apiclient_cert'], 'apiclient_key' => $params['config']['apiclient_key'], + 'platform_certs' => $params['config']['platform_certs'], ]; } if ($payConfig['pay_way'] == PayEnum::ALI_PAY) { diff --git a/app/api/controller/WechatPayServiceMerchantPayController.php b/app/api/controller/WechatPayServiceMerchantPayController.php index 28a573b..db84695 100644 --- a/app/api/controller/WechatPayServiceMerchantPayController.php +++ b/app/api/controller/WechatPayServiceMerchantPayController.php @@ -31,6 +31,23 @@ class WechatPayServiceMerchantPayController extends BaseApiController return $this->success('', $result); } + /** + * 申请退款 + */ + public function refund() + { + $params = $this->request->param(); // business_order_no order_type + $refundOrder = WechatPayServiceMerchantPaymentLogic::createRefundOrder($params); + if (false === $refundOrder) { + return $this->fail('退款订单创建失败', $params); + } + //支付流程 + $result = (new WeChatPayMerchantService())->refund($refundOrder); + if (false === $result) { + return $this->fail((new WeChatPayMerchantService())->getError(), $params); + } + } + /** * @notes app支付回调 * @return \Psr\Http\Message\ResponseInterface @@ -44,4 +61,12 @@ class WechatPayServiceMerchantPayController extends BaseApiController { return (new WeChatPayMerchantService())->notify(); } + + /** + * 退款回调 + */ + public function refundNotify() + { + return (new WeChatPayMerchantService())->refundNotify(); + } } \ No newline at end of file diff --git a/app/common/logic/WechatPayServiceMerchantPaymentLogic.php b/app/common/logic/WechatPayServiceMerchantPaymentLogic.php index e606ad9..c5e32d2 100644 --- a/app/common/logic/WechatPayServiceMerchantPaymentLogic.php +++ b/app/common/logic/WechatPayServiceMerchantPaymentLogic.php @@ -20,6 +20,7 @@ use app\common\enum\PayOrderEnum; use app\common\enum\YesNoEnum; use app\common\model\pay\PayOrder; use app\common\model\pay\PayWay; +use app\common\model\pay\RefundOrder; use app\common\model\recharge\RechargeOrder; use app\common\model\SubMerchant; use app\common\model\user\User; @@ -45,7 +46,7 @@ class WechatPayServiceMerchantPaymentLogic extends BaseLogic 'collection_account' => $subMerchant['sub_mch_id'], // 子商户号 'pay_user_role' => $params['pay_user_role'], 'pay_user_info' => json_encode($params['pay_user_info']), - 'order_no' => generate_sn(PayOrder::class, 'order_no'), + 'order_no' => 'order'.generate_sn(PayOrder::class, 'order_no'), 'business_order_no' => $params['business_order_no'], 'total_fee' => $params['total_fee'], // int 单位:分 'pay_type' => PayOrderEnum::PAY_TYPE, @@ -57,4 +58,24 @@ class WechatPayServiceMerchantPaymentLogic extends BaseLogic return PayOrder::create($data); } + // 创建微信退款订单 + public static function createRefundOrder($params) + { + $payOrder = PayOrder::where(['business_order_no' => $params['business_order_no'], 'pay_status'=>PayOrderEnum::PAY_STATUS_ISPAID])->find(); + + $data = [ + 'refund_sn' => 'refund'.generate_sn(RefundOrder::class, 'refund_sn'), + 'order_sn' => $payOrder['order_no'], + 'business_order_sn' => $payOrder['business_order_sn'], + 'order_type' => $params['order_type'], + 'order_amount' => $payOrder['total_fee'], + 'refund_amount' => $payOrder['total_fee'], + 'refund_type' => 1, + 'refund_status' => 0, + 'create_time' => time(), + 'update_time' => time(), + ]; + return RefundOrder::create($data); + } + } \ No newline at end of file diff --git a/app/common/model/pay/RefundOrder.php b/app/common/model/pay/RefundOrder.php new file mode 100644 index 0000000..9fc34e2 --- /dev/null +++ b/app/common/model/pay/RefundOrder.php @@ -0,0 +1,10 @@ + PayEnum::WECHAT_PAY])->findOrEmpty()->toArray(); - $client = $this->app->getClient(); - $response = $client->postXml('pay/unifiedorder', [ - 'appid' => $pay['config']['app_id'], - 'mch_id' => $this->config['mch_id'], - 'sub_mch_id' => $order['collection_account'], + $response = $this->app->getClient()->postJson('/v3/pay/partner/transactions/app', [ + 'sp_appid' => $pay['config']['app_id'], + 'sp_mchid' => $pay['config']['mch_id'], + 'sub_mchid' => $order['collection_account'], 'description' => PayOrderEnum::getPayOrderTypeDesc($order['order_type']), 'out_trade_no' => $order['order_no'], 'notify_url' => $this->config['notify_url'], - 'total_fee' => $order['total_fee'], - 'spbill_create_ip' => $_SERVER['SERVER_ADDR'], // 调用微信支付API的机器IP - 'time_start' => date('YmdHis', intval($order['create_time'])), - 'trade_type' => 'APP', + 'amount' => [ + 'total' => intval($order['total_fee']), + 'currency' => 'CNY' + ], 'attach' => $order['order_no'], - 'body' => PayOrderEnum::getPayOrderTypeDesc($order['order_type']).'订单' ]); - $result = $response->toArray(false);dd($result); + + $result = $response->toArray(false); $this->checkResultFail($result); - $re = $this->app->getUtils()->buildAppConfig($result['prepay_id'], $this->config['appid']); - $re['partnerid'] = $order['sub_mch_id']; + $re = $this->app->getUtils()->buildAppConfig($result['prepay_id'], $pay['config']['app_id']); + $re['partnerid'] = $order['collection_account']; return $re; -// } catch (\Exception $e) { -// $this->setError($e->getMessage()); -// return false; -// } + } catch (\Exception $e) { + $this->setError($e->getMessage()); + return false; + } } @@ -114,14 +114,17 @@ class WeChatPayMerchantService extends BasePayService * @author 段誉 * @date 2023/2/28 16:53 */ - public function refund(array $refundData) + public function refund($refundOrder) { - $response = $this->app->getClient()->postJson('secapi/pay/refund', [ - 'transaction_id' => $refundData['transaction_id'], - 'out_refund_no' => $refundData['refund_sn'], + + $payOrder = PayOrder::where(['order_no' => $refundOrder['order_sn'], 'pay_status'=>PayOrderEnum::PAY_STATUS_ISPAID])->find(); + $response = $this->app->getClient()->postJson('/v3/refund/domestic/refunds', [ + 'sub_mchid' => $payOrder['collection_account'], + 'out_refund_no' => $payOrder['order_no'], + 'notify_url' => (string)url('wechat_pay_service_merchant_pay/notifyApp', [], false, true), 'amount' => [ - 'refund' => intval($refundData['refund_amount'] * 100), - 'total' => intval($refundData['total_amount'] * 100), + 'refund' => $refundOrder['refund_amount'], + 'total' => $refundOrder['refund_amount'], 'currency' => 'CNY', ] ]); @@ -202,7 +205,12 @@ class WeChatPayMerchantService extends BasePayService } return true; }); + return $server->serve(); + } + public function refundNotify() + { + $server = $this->app->getServer(); // 退款通知 $server->handleRefunded(function (Message $message) { Log::info(['退款回调信息', $message]); diff --git a/app/common/service/wechat/WeChatPayMerchantConfigService.php b/app/common/service/wechat/WeChatPayMerchantConfigService.php index 05de365..0e8241b 100644 --- a/app/common/service/wechat/WeChatPayMerchantConfigService.php +++ b/app/common/service/wechat/WeChatPayMerchantConfigService.php @@ -41,9 +41,11 @@ class WeChatPayMerchantConfigService //写入文件 $apiclientCert = $pay['config']['apiclient_cert'] ?? ''; $apiclientKey = $pay['config']['apiclient_key'] ?? ''; + $plaformCert = $pay['config']['platform_certs'] ?? ''; $certPath = app()->getRootPath() . 'runtime/cert/' . md5($apiclientCert) . '.pem'; $keyPath = app()->getRootPath() . 'runtime/cert/' . md5($apiclientKey) . '.pem'; + $plaformCertPath = app()->getRootPath() . 'runtime/cert/' . md5($plaformCert) . '.pem'; if (!empty($apiclientCert) && !file_exists($certPath)) { static::setCert($certPath, trim($apiclientCert)); @@ -51,6 +53,9 @@ class WeChatPayMerchantConfigService if (!empty($apiclientKey) && !file_exists($keyPath)) { static::setCert($keyPath, trim($apiclientKey)); } + if (!empty($plaformCert) && !file_exists($plaformCertPath)) { + static::setCert($plaformCertPath, trim($plaformCert)); + } return [ // 服务商商户号 @@ -58,8 +63,12 @@ class WeChatPayMerchantConfigService // 商户证书 'private_key' => $keyPath, 'certificate' => $certPath, + // 平台证书 + 'platform_certs' => $plaformCertPath, + // v3 API 秘钥 + 'secret_key' => '1A1233CFB69D7F27211E36AFF9EC373A', // v2 API 秘钥 - 'v2_secret_key' => $pay['config']['pay_sign_key'] ?? '', +// 'v2_secret_key' => $pay['config']['pay_sign_key'] ?? '', 'notify_url' => $notifyUrl, 'http' => [ 'throw' => true, // 状态码非 200、300 时是否抛出异常,默认为开启