add 改为v3支付接口。新增退款接口

This commit is contained in:
chenbo 2023-11-16 17:33:16 +08:00
parent eacdc1f9a5
commit 93a43d24a6
6 changed files with 100 additions and 26 deletions

View File

@ -51,6 +51,7 @@ class PayConfigLogic extends BaseLogic
'pay_sign_key' => $params['config']['pay_sign_key'], 'pay_sign_key' => $params['config']['pay_sign_key'],
'apiclient_cert' => $params['config']['apiclient_cert'], 'apiclient_cert' => $params['config']['apiclient_cert'],
'apiclient_key' => $params['config']['apiclient_key'], 'apiclient_key' => $params['config']['apiclient_key'],
'platform_certs' => $params['config']['platform_certs'],
]; ];
} }
if ($payConfig['pay_way'] == PayEnum::ALI_PAY) { if ($payConfig['pay_way'] == PayEnum::ALI_PAY) {

View File

@ -31,6 +31,23 @@ class WechatPayServiceMerchantPayController extends BaseApiController
return $this->success('', $result); 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支付回调 * @notes app支付回调
* @return \Psr\Http\Message\ResponseInterface * @return \Psr\Http\Message\ResponseInterface
@ -44,4 +61,12 @@ class WechatPayServiceMerchantPayController extends BaseApiController
{ {
return (new WeChatPayMerchantService())->notify(); return (new WeChatPayMerchantService())->notify();
} }
/**
* 退款回调
*/
public function refundNotify()
{
return (new WeChatPayMerchantService())->refundNotify();
}
} }

View File

@ -20,6 +20,7 @@ use app\common\enum\PayOrderEnum;
use app\common\enum\YesNoEnum; use app\common\enum\YesNoEnum;
use app\common\model\pay\PayOrder; use app\common\model\pay\PayOrder;
use app\common\model\pay\PayWay; use app\common\model\pay\PayWay;
use app\common\model\pay\RefundOrder;
use app\common\model\recharge\RechargeOrder; use app\common\model\recharge\RechargeOrder;
use app\common\model\SubMerchant; use app\common\model\SubMerchant;
use app\common\model\user\User; use app\common\model\user\User;
@ -45,7 +46,7 @@ class WechatPayServiceMerchantPaymentLogic extends BaseLogic
'collection_account' => $subMerchant['sub_mch_id'], // 子商户号 'collection_account' => $subMerchant['sub_mch_id'], // 子商户号
'pay_user_role' => $params['pay_user_role'], 'pay_user_role' => $params['pay_user_role'],
'pay_user_info' => json_encode($params['pay_user_info']), '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'], 'business_order_no' => $params['business_order_no'],
'total_fee' => $params['total_fee'], // int 单位:分 'total_fee' => $params['total_fee'], // int 单位:分
'pay_type' => PayOrderEnum::PAY_TYPE, 'pay_type' => PayOrderEnum::PAY_TYPE,
@ -57,4 +58,24 @@ class WechatPayServiceMerchantPaymentLogic extends BaseLogic
return PayOrder::create($data); 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);
}
} }

View File

@ -0,0 +1,10 @@
<?php
namespace app\common\model\pay;
use app\common\model\BaseModel;
class RefundOrder extends BaseModel
{
protected $name = 'refund_order';
}

View File

@ -21,6 +21,7 @@ use app\common\enum\PayOrderEnum;
use app\common\enum\user\UserTerminalEnum; use app\common\enum\user\UserTerminalEnum;
use app\common\logic\PayNotifyLogic; use app\common\logic\PayNotifyLogic;
use app\common\model\pay\PayConfig; use app\common\model\pay\PayConfig;
use app\common\model\pay\PayOrder;
use app\common\model\recharge\RechargeOrder; use app\common\model\recharge\RechargeOrder;
use app\common\model\user\UserAuth; use app\common\model\user\UserAuth;
use app\common\service\wechat\WeChatConfigService; use app\common\service\wechat\WeChatConfigService;
@ -76,32 +77,31 @@ class WeChatPayMerchantService extends BasePayService
public function wechatPayServiceMerchantAppPay($order) public function wechatPayServiceMerchantAppPay($order)
{ {
// try { try {
$pay = PayConfig::where(['pay_way' => PayEnum::WECHAT_PAY])->findOrEmpty()->toArray(); $pay = PayConfig::where(['pay_way' => PayEnum::WECHAT_PAY])->findOrEmpty()->toArray();
$client = $this->app->getClient(); $response = $this->app->getClient()->postJson('/v3/pay/partner/transactions/app', [
$response = $client->postXml('pay/unifiedorder', [ 'sp_appid' => $pay['config']['app_id'],
'appid' => $pay['config']['app_id'], 'sp_mchid' => $pay['config']['mch_id'],
'mch_id' => $this->config['mch_id'], 'sub_mchid' => $order['collection_account'],
'sub_mch_id' => $order['collection_account'],
'description' => PayOrderEnum::getPayOrderTypeDesc($order['order_type']), 'description' => PayOrderEnum::getPayOrderTypeDesc($order['order_type']),
'out_trade_no' => $order['order_no'], 'out_trade_no' => $order['order_no'],
'notify_url' => $this->config['notify_url'], 'notify_url' => $this->config['notify_url'],
'total_fee' => $order['total_fee'], 'amount' => [
'spbill_create_ip' => $_SERVER['SERVER_ADDR'], // 调用微信支付API的机器IP 'total' => intval($order['total_fee']),
'time_start' => date('YmdHis', intval($order['create_time'])), 'currency' => 'CNY'
'trade_type' => 'APP', ],
'attach' => $order['order_no'], 'attach' => $order['order_no'],
'body' => PayOrderEnum::getPayOrderTypeDesc($order['order_type']).'订单'
]); ]);
$result = $response->toArray(false);dd($result);
$result = $response->toArray(false);
$this->checkResultFail($result); $this->checkResultFail($result);
$re = $this->app->getUtils()->buildAppConfig($result['prepay_id'], $this->config['appid']); $re = $this->app->getUtils()->buildAppConfig($result['prepay_id'], $pay['config']['app_id']);
$re['partnerid'] = $order['sub_mch_id']; $re['partnerid'] = $order['collection_account'];
return $re; return $re;
// } catch (\Exception $e) { } catch (\Exception $e) {
// $this->setError($e->getMessage()); $this->setError($e->getMessage());
// return false; return false;
// } }
} }
@ -114,14 +114,17 @@ class WeChatPayMerchantService extends BasePayService
* @author 段誉 * @author 段誉
* @date 2023/2/28 16:53 * @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'], $payOrder = PayOrder::where(['order_no' => $refundOrder['order_sn'], 'pay_status'=>PayOrderEnum::PAY_STATUS_ISPAID])->find();
'out_refund_no' => $refundData['refund_sn'], $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' => [ 'amount' => [
'refund' => intval($refundData['refund_amount'] * 100), 'refund' => $refundOrder['refund_amount'],
'total' => intval($refundData['total_amount'] * 100), 'total' => $refundOrder['refund_amount'],
'currency' => 'CNY', 'currency' => 'CNY',
] ]
]); ]);
@ -202,7 +205,12 @@ class WeChatPayMerchantService extends BasePayService
} }
return true; return true;
}); });
return $server->serve();
}
public function refundNotify()
{
$server = $this->app->getServer();
// 退款通知 // 退款通知
$server->handleRefunded(function (Message $message) { $server->handleRefunded(function (Message $message) {
Log::info(['退款回调信息', $message]); Log::info(['退款回调信息', $message]);

View File

@ -41,9 +41,11 @@ class WeChatPayMerchantConfigService
//写入文件 //写入文件
$apiclientCert = $pay['config']['apiclient_cert'] ?? ''; $apiclientCert = $pay['config']['apiclient_cert'] ?? '';
$apiclientKey = $pay['config']['apiclient_key'] ?? ''; $apiclientKey = $pay['config']['apiclient_key'] ?? '';
$plaformCert = $pay['config']['platform_certs'] ?? '';
$certPath = app()->getRootPath() . 'runtime/cert/' . md5($apiclientCert) . '.pem'; $certPath = app()->getRootPath() . 'runtime/cert/' . md5($apiclientCert) . '.pem';
$keyPath = app()->getRootPath() . 'runtime/cert/' . md5($apiclientKey) . '.pem'; $keyPath = app()->getRootPath() . 'runtime/cert/' . md5($apiclientKey) . '.pem';
$plaformCertPath = app()->getRootPath() . 'runtime/cert/' . md5($plaformCert) . '.pem';
if (!empty($apiclientCert) && !file_exists($certPath)) { if (!empty($apiclientCert) && !file_exists($certPath)) {
static::setCert($certPath, trim($apiclientCert)); static::setCert($certPath, trim($apiclientCert));
@ -51,6 +53,9 @@ class WeChatPayMerchantConfigService
if (!empty($apiclientKey) && !file_exists($keyPath)) { if (!empty($apiclientKey) && !file_exists($keyPath)) {
static::setCert($keyPath, trim($apiclientKey)); static::setCert($keyPath, trim($apiclientKey));
} }
if (!empty($plaformCert) && !file_exists($plaformCertPath)) {
static::setCert($plaformCertPath, trim($plaformCert));
}
return [ return [
// 服务商商户号 // 服务商商户号
@ -58,8 +63,12 @@ class WeChatPayMerchantConfigService
// 商户证书 // 商户证书
'private_key' => $keyPath, 'private_key' => $keyPath,
'certificate' => $certPath, 'certificate' => $certPath,
// 平台证书
'platform_certs' => $plaformCertPath,
// v3 API 秘钥
'secret_key' => '1A1233CFB69D7F27211E36AFF9EC373A',
// v2 API 秘钥 // v2 API 秘钥
'v2_secret_key' => $pay['config']['pay_sign_key'] ?? '', // 'v2_secret_key' => $pay['config']['pay_sign_key'] ?? '',
'notify_url' => $notifyUrl, 'notify_url' => $notifyUrl,
'http' => [ 'http' => [
'throw' => true, // 状态码非 200、300 时是否抛出异常,默认为开启 'throw' => true, // 状态码非 200、300 时是否抛出异常,默认为开启