569 lines
25 KiB
PHP
569 lines
25 KiB
PHP
<?php
|
||
/*
|
||
* description:
|
||
* author:wh
|
||
* email:
|
||
* createTime:{2021/08/24} {10:18}
|
||
*/
|
||
|
||
namespace wanghua\general_utility_tools_php\wechat;
|
||
|
||
|
||
use Omnipay\Omnipay;
|
||
use think\Exception;
|
||
use wanghua\general_utility_tools_php\Mmodel;
|
||
use wanghua\general_utility_tools_php\tool\Tools;
|
||
use WeChatPay\Builder;
|
||
use WeChatPay\Crypto\Rsa;
|
||
use WeChatPay\Formatter;
|
||
use WeChatPay\Util\PemUtil;
|
||
use Yurun\PaySDK\Weixin\Params\PublicParams;
|
||
use Yurun\PaySDK\Weixin\Refund\Request;
|
||
use Yurun\PaySDK\Weixin\SDK;
|
||
|
||
/**
|
||
* 微信支付逻辑
|
||
* Class WechatPayLogic
|
||
* @package app\index\logic
|
||
*/
|
||
class WechatPayLogic
|
||
{
|
||
|
||
/**
|
||
* @deprecated 废弃
|
||
*
|
||
* desc:调起h5支付
|
||
*
|
||
* composer包依赖: omnipay/common
|
||
*
|
||
* 其它工具包:wanghua/general-utility-tools-php
|
||
*
|
||
* author:wh
|
||
* @param array $config 微信支付配置
|
||
* @param array $order_info 订单信息
|
||
* @param string $notify_url 回调通知URL
|
||
* @return string 返回支付字符串,输出到浏览器进行支付
|
||
*/
|
||
function h5pay(array $config, array $order_info, string $notify_url){
|
||
|
||
$gateway = Omnipay::create('WechatPay_Mweb');
|
||
$gateway->setAppId($config['app_id']);
|
||
|
||
$gateway->setMchId(trim($config['mch_id']));
|
||
$gateway->setApiKey($config['api_key']);
|
||
|
||
$order_param = [
|
||
'body' => $order_info['goods_name'],
|
||
'out_trade_no' => $order_info['orderid'],
|
||
'total_fee' => $order_info['real_amount']*100, //=0.01 单位分
|
||
'spbill_create_ip' => request()->ip(),
|
||
'fee_type' => 'CNY',
|
||
'notify_url' => $notify_url,
|
||
'trade_type' => 'MWEB',
|
||
'nonce_str' => Tools::rand_str(),
|
||
];
|
||
|
||
$request = $gateway->purchase($order_param);
|
||
|
||
$response = $request->send();
|
||
|
||
$res_data = $response->getData();
|
||
|
||
if($res_data['return_code'] != 'SUCCESS'){
|
||
return '支付错误';
|
||
}
|
||
|
||
if($res_data['result_code'] != 'SUCCESS'){
|
||
return '支付出错了';
|
||
}
|
||
|
||
|
||
$mweb_url = $res_data['mweb_url'];
|
||
$pay_str = <<<EOF
|
||
<html><body><script type="text/javascript">location.href="{$mweb_url}"</script></body></html>
|
||
EOF;
|
||
|
||
return $pay_str;
|
||
|
||
}
|
||
|
||
/**
|
||
* @deprecated 废弃,SDK要报证书错误,实战推荐使用[yurunsoft/pay-sdk]库
|
||
*
|
||
* desc:微信jsapi支付
|
||
* author:wh
|
||
* @param $order
|
||
* @param $notify_url
|
||
* @return array
|
||
*/
|
||
function wxJsApiPay($order,$notify_url){
|
||
try {
|
||
$config = wxConfOrderPayFirm();
|
||
// 设置参数
|
||
// 商户号
|
||
$merchantId = $config['mch_id'];
|
||
|
||
//dump($config);
|
||
// 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
|
||
$merchantPrivateKeyFilePath = $config['merchantPrivateKeyFilePath'];//'file:///path/to/merchant/apiclient_key.pem';
|
||
$merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);
|
||
|
||
// 「商户API证书」的「证书序列号」
|
||
$merchantCertificateSerial = $config['merchantCertificateSerial'];//'3775B6A45ACD588826D15E583A95F5DD********';
|
||
|
||
// 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名
|
||
$platformCertificateFilePath = $config['platformCertificateFilePath'];//'file:///path/to/wechatpay/cert.pem';
|
||
$platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
|
||
|
||
// 从「微信支付平台证书」中获取「证书序列号」
|
||
$platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath);
|
||
|
||
// 构造一个 APIv3 客户端实例
|
||
$instance = Builder::factory([
|
||
'mchid' => $merchantId,
|
||
'serial' => $merchantCertificateSerial,
|
||
'privateKey' => $merchantPrivateKeyInstance,
|
||
'certs' => [
|
||
$platformCertificateSerial => $platformPublicKeyInstance,
|
||
],
|
||
]);
|
||
$resp = $instance
|
||
->chain('v3/pay/transactions/jsapi')
|
||
->post(['json' => [
|
||
'appid' => $config['appid'],//【公众号ID】 公众号ID
|
||
'mchid' => $config['mch_id'],//【直连商户号】 直连商户号
|
||
'description' => $order['goods_name'],//【商品描述】 商品描述
|
||
'out_trade_no' => $order['orderid'],//【商户订单号】 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一。
|
||
'notify_url' => $notify_url,
|
||
'amount' => [
|
||
'total' => $order['real_amount']*100,//【总金额】 订单总金额,单位为分。
|
||
'currency' => 'CNY'
|
||
],
|
||
'payer'=>[
|
||
'openid' =>$order['openid']//【用户标识】 用户在普通商户AppID下的唯一标识。 下单前需获取到用户的OpenID
|
||
],
|
||
]]);
|
||
|
||
//echo $resp->getStatusCode(), PHP_EOL;
|
||
//echo $resp->getBody(), PHP_EOL;
|
||
|
||
$responseData = json_decode($resp->getBody(), true);
|
||
|
||
// 构造JSAPI支付的参数
|
||
$jsapiParameters = [
|
||
'appId' => $config['appid'],
|
||
'timeStamp' => (string)Formatter::timestamp(),
|
||
'nonceStr' => Formatter::nonce(),
|
||
'package' => 'prepay_id=' . $responseData['prepay_id'],
|
||
'signType' => 'RSA-PSS',
|
||
];
|
||
|
||
// 对JSAPI支付参数进行签名
|
||
$jsapiParameters['paySign'] = Rsa::sign(
|
||
Formatter::joinedByLineFeed(...array_values($jsapiParameters)),
|
||
$merchantPrivateKeyInstance,
|
||
'sha256'
|
||
);
|
||
|
||
// 返回JSAPI支付参数
|
||
//header('Content-Type: application/json');
|
||
//echo json_encode($jsapiParameters);
|
||
//dump($jsapiParameters);
|
||
|
||
return Tools::set_ok('ok',$jsapiParameters);
|
||
} catch (\Exception $e) {
|
||
Tools::error_txt_log($e);
|
||
// 进行错误处理
|
||
//echo $e->getMessage(), PHP_EOL;
|
||
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
|
||
$r = $e->getResponse();
|
||
//echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
|
||
//echo $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
|
||
|
||
$res_arr = json_decode($r->getBody(),true);
|
||
return Tools::set_fail('异常.1',$res_arr);
|
||
}
|
||
//echo $e->getTraceAsString(), PHP_EOL;
|
||
return Tools::set_fail('异常.2',$e->getMessage());
|
||
}
|
||
}
|
||
/**
|
||
* desc:微信jsapi支付,虽然文档不好用,但是可以正常支付
|
||
*
|
||
* 场景:微信内的网页支付
|
||
*
|
||
* composer包依赖:请安装[ yurunsoft/pay-sdk ],附带自动安装yurunsoft/yurun-http包
|
||
* 其它工具包:wanghua/general-utility-tools-php
|
||
*
|
||
* author:wh
|
||
* @param array $config 微信支付的配置 必须参数:appid、mch_id、api_key
|
||
* @param array $wx_user_info 微信用户信息 必须参数:openid
|
||
* @param array $order_info 订单信息 必须参数:goods_name、orderid、goods_price(元)
|
||
* @param string $notify_url 回调URL
|
||
* @return false|string
|
||
*/
|
||
function jsapiPay(array $config, array $wx_user_info, array $order_info, string $notify_url){
|
||
// 配置参数
|
||
$params = new PublicParams();
|
||
$params->appID = $config['appid']; // 支付平台分配给开发者的应用ID
|
||
$params->mch_id = $config['mch_id']; // 微信支付分配的商户号
|
||
$params->key = $config['api_key']; // API 密钥
|
||
// 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书)
|
||
// $params->certPath = 'path/cert.pem'; // XXX: 绝对路径!!!
|
||
// $params->keyPath = 'path/key'; // XXX: 绝对路径!!!!
|
||
// 如果是子服务商需要配置
|
||
// $params->sub_appid = ''; // 微信分配的子商户公众账号ID,服务商、银行服务商需要。
|
||
// $params-> sub_mch_id = ''; // 微信支付分配的子商户号,开发者模式下必填,服务商、银行服务商需要。
|
||
// SDK实例化,传入公共配置
|
||
$pay = new \Yurun\PaySDK\Weixin\SDK($params);
|
||
// 支付接口(生成支付订单)
|
||
$request = new \Yurun\PaySDK\Weixin\JSAPI\Params\Pay\Request;
|
||
$request->body = $order_info['goods_name']; // 商品描述
|
||
$request->out_trade_no = $order_info['orderid']; // 订单号
|
||
$request->total_fee = $order_info['real_amount']*100; // 订单总金额,单位为:分
|
||
$request->spbill_create_ip = request()->ip(); // 客户端ip
|
||
$request->notify_url = $notify_url; // 异步通知地址
|
||
$request->openid = $wx_user_info['openid']; // 必须设置openid
|
||
$request->profit_sharing = empty($order_info['profit_sharing'])?'N':$order_info['profit_sharing'];//是否分账N,Y
|
||
// 调用接口
|
||
$result = $pay->execute($request);
|
||
//此调试代码禁止删除
|
||
//var_dump('result:', $result);
|
||
//var_dump('success:', $pay->checkResult());
|
||
//var_dump('error:', $pay->getError(), 'error_code:', $pay->getErrorCode());
|
||
if(!$pay->checkResult()){
|
||
throw new Exception('下单错误.'.$pay->getError());
|
||
}
|
||
|
||
$request = new \Yurun\PaySDK\Weixin\JSAPI\Params\JSParams\Request;
|
||
$request->prepay_id = $result['prepay_id'];
|
||
$jsapiParams = $pay->execute($request);
|
||
// 最后需要将数据传给js,使用WeixinJSBridge进行支付
|
||
return json_encode($jsapiParams);
|
||
}
|
||
|
||
|
||
/**
|
||
* desc: [推荐]微信退款,传入的金额保持“元”为单位,实际是以“分”的格式提交给微信支付
|
||
*
|
||
* 依赖:yurunsoft/pay-sdk
|
||
*
|
||
* author:wh
|
||
* @param array $config 支付配置
|
||
* @param array $order_info 订单信息
|
||
* @param string $reason 退款原因(可选)
|
||
* @return array
|
||
*/
|
||
function toWxRefund($config,$order_info,$reason=''){
|
||
return Mmodel::catch(function ()use($config,$order_info,$reason){
|
||
// 配置参数
|
||
$params = new PublicParams();
|
||
$params->appID = $config['appid']; // 支付平台分配给开发者的应用ID
|
||
$params->mch_id = $config['mch_id']; // 微信支付分配的商户号
|
||
$params->key = $config['api_key']; // API 密钥
|
||
// 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书)
|
||
$params->certPath = $config['platformCertificateFilePath'];//'path/to/cert.pem'; // 证书路径
|
||
$params->keyPath = $config['merchantPrivateKeyFilePath'];//'path/to/key'; // 密钥路径
|
||
|
||
// 如果是子服务商需要配置
|
||
// $params->sub_appid = ''; // 微信分配的子商户公众账号ID,服务商、银行服务商需要。
|
||
// $params->sub_mch_id = ''; // 微信支付分配的子商户号,开发者模式下必填,服务商、银行服务商需要。
|
||
|
||
// SDK实例化,传入公共配置
|
||
$pay = new SDK($params);
|
||
|
||
// 退款请求参数
|
||
$request = new Request();
|
||
$request->out_trade_no = $order_info['orderid']; // 原支付订单号
|
||
$request->out_refund_no = $order_info['orderid']; // 商户退款单号
|
||
$request->total_fee = $order_info['real_amount'] * 100; // 订单总金额,单位为:分
|
||
$request->refund_fee = $order_info['real_amount'] * 100; // 退款金额,单位为:分
|
||
|
||
try {
|
||
// 调用退款接口
|
||
Tools::log_to_write_txt(['调用退款接口,入参:orderid='.$order_info['orderid'],$request]);
|
||
$result = $pay->execute($request);
|
||
Tools::log_to_write_txt(['调用退款接口,出参:',$result]);
|
||
}catch (\Exception $e){
|
||
Tools::error_txt_log($e);
|
||
return Tools::set_fail('[err]:'.$e->getMessage());
|
||
}
|
||
|
||
// 调试代码
|
||
//var_dump('refund result:', $result);
|
||
//var_dump('success:', $pay->checkResult());
|
||
//var_dump('error:', $pay->getError(), 'error_code:', $pay->getErrorCode());
|
||
|
||
//打印:$result
|
||
//array(18) {
|
||
// ["return_code"] => string(7) "SUCCESS"
|
||
// ["return_msg"] => string(2) "OK"
|
||
// ["appid"] => string(18) "wx5904518b3a0b2965"
|
||
// ["mch_id"] => string(10) "1668824977"
|
||
// ["nonce_str"] => string(16) "3LyqioO7WmMEyFKk"
|
||
// ["sign"] => string(32) "6F0ECED3DED5F66200171B7050AFB635"
|
||
// ["result_code"] => string(7) "SUCCESS"
|
||
// ["transaction_id"] => string(28) "4200002407202408310164479484"
|
||
// ["out_trade_no"] => string(21) "phuzhe9n1725089504331"
|
||
// ["out_refund_no"] => string(21) "phuzhe9n1725089504331"
|
||
// ["refund_id"] => string(29) "50303600442024083127353984987"
|
||
// ["refund_channel"] => object(SimpleXMLElement)#63 (0) {
|
||
// }
|
||
// ["refund_fee"] => string(2) "10"
|
||
// ["coupon_refund_fee"] => string(1) "0"
|
||
// ["total_fee"] => string(2) "10"
|
||
// ["cash_fee"] => string(2) "10"
|
||
// ["coupon_refund_count"] => string(1) "0"
|
||
// ["cash_refund_fee"] => string(2) "10"
|
||
//}
|
||
//dump($result);
|
||
if (!$pay->checkResult()) {
|
||
Tools::log_to_write_txt([$pay]);
|
||
return Tools::set_fail('退款错误:' . $pay->getError(),[$result,$pay]);
|
||
}
|
||
if($result['return_code'] == 'SUCCESS' && $result['result_code']=='SUCCESS'){
|
||
return Tools::set_ok('退款成功',$result);
|
||
}
|
||
|
||
// 如果退款成功,$result 将包含退款操作的详细信息
|
||
//echo "退款成功,退款单号:" . $request->out_refund_no;
|
||
return Tools::set_fail('退款失败.',$result);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* @deprecated 废弃,推荐使用toWxRefund方法
|
||
*
|
||
* SDK要报证书错误,实战推荐使用[yurunsoft/pay-sdk]库
|
||
*
|
||
* 微信退款,单位“分”
|
||
*
|
||
* 依赖:wechatpay/wechatpay微信支付推荐sdk
|
||
*
|
||
* 注意返回(message不是msg):
|
||
* [code:'RESOURCE_NOT_EXISTS','message':'订单不存在']
|
||
*
|
||
* 错误码:
|
||
* SUCCESS: 退款成功
|
||
CLOSED: 退款关闭
|
||
PROCESSING: 退款处理中
|
||
ABNORMAL: 退款异常
|
||
*
|
||
*
|
||
* 代码经过测试没有问题,如果出现“The certs(xxxxxxxxxxxx) contains the merchant's certificate serial number(4xxxxxxxxxxxxx) which is not allowed here.”
|
||
* 则是sdk代码问题,需要注释掉D:\wanghua\projects\meebo_mid\vendor\wechatpay\wechatpay\src\ClientJsonTrait.php
|
||
* 大约文件中第225行代码。
|
||
* 代码:
|
||
* //if (array_key_exists($config['serial'], $config['certs'])) {
|
||
* // throw new Exception\InvalidArgumentException(sprintf(
|
||
* // Exception\ERR_INIT_CERTS_EXCLUDE_MCHSERIAL, implode(',', array_keys($config['certs'])), $config['serial']
|
||
* // ));
|
||
* //}
|
||
*/
|
||
function wxRefund($order, $reason=''){
|
||
$config = wxConfOrderPayFirm();
|
||
// 设置参数
|
||
// 商户号
|
||
$merchantId = $config['mch_id'];
|
||
|
||
//dump($config);
|
||
// 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
|
||
$merchantPrivateKeyFilePath = $config['merchantPrivateKeyFilePath'];//'file:///path/to/merchant/apiclient_key.pem';
|
||
$merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);
|
||
|
||
// 「商户API证书」的「证书序列号」
|
||
$merchantCertificateSerial = $config['merchantCertificateSerial'];//'3775B6A45ACD588826D15E583A95F5DD********';
|
||
|
||
// 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名
|
||
$platformCertificateFilePath = $config['platformCertificateFilePath'];//'file:///path/to/wechatpay/cert.pem';
|
||
$platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
|
||
|
||
// 从「微信支付平台证书」中获取「证书序列号」
|
||
$platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath);
|
||
|
||
// 构造一个 APIv3 客户端实例
|
||
$instance = Builder::factory([
|
||
'mchid' => $merchantId,
|
||
'serial' => $merchantCertificateSerial,
|
||
'privateKey' => $merchantPrivateKeyInstance,
|
||
'certs' => [
|
||
$platformCertificateSerial => $platformPublicKeyInstance,
|
||
],
|
||
]);
|
||
|
||
try {
|
||
$promise = $instance
|
||
->chain('v3/refund/domestic/refunds')
|
||
->postAsync([
|
||
'json' => [
|
||
'out_trade_no' => $order['orderid'],
|
||
'out_refund_no' => $order['orderid'],//退款单号 如果分批退款则单号必须每次唯一
|
||
'reason' => $reason,
|
||
'amount' => [
|
||
'refund' => $order['real_amount']*100,//单位分
|
||
'total' => $order['real_amount']*100,//单位分
|
||
'currency' => 'CNY',
|
||
],
|
||
],
|
||
])
|
||
->then(static function($response) {
|
||
// 正常逻辑回调处理
|
||
//dump(1111);
|
||
//echo $response->getBody(), PHP_EOL;
|
||
|
||
$res_arr = json_decode($response->getBody(),true);
|
||
return Tools::set_ok('ok',$res_arr);
|
||
})
|
||
->otherwise(static function($e){
|
||
// 异常错误处理
|
||
//echo $e->getMessage(), PHP_EOL;
|
||
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
|
||
$r = $e->getResponse();
|
||
//echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
|
||
//echo $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
|
||
throw new Exception($r->getBody());
|
||
}
|
||
//echo $e->getTraceAsString(), PHP_EOL;
|
||
|
||
throw new Exception($e->getMessage());
|
||
//return Tools::set_res(5890,'退款失败'.$e->getMessage());
|
||
});
|
||
// 同步等待
|
||
$promise->wait();
|
||
//这里稍作注意,不清楚then返回会不会走这里(经测试现在不会)
|
||
}catch (\Exception $e){
|
||
Tools::error_txt_log($e);
|
||
$json_decode = @json_decode($e->getMessage(),true);
|
||
return Tools::set_res(5890,'退款错误.',$json_decode);
|
||
}
|
||
}
|
||
/**
|
||
*
|
||
* [推荐]查询单笔退款
|
||
*
|
||
* 依赖:yurunsoft/pay-sdk
|
||
*
|
||
* 代码经过测试没有问题,如果出现“The certs(4xxxxxxxxxxxxx) contains the merchant's certificate serial number(4xxxxxxxxxxx) which is not allowed here.”
|
||
* 则是sdk代码问题,需要注释掉D:\wanghua\projects\meebo_mid\vendor\wechatpay\wechatpay\src\ClientJsonTrait.php
|
||
* 大约文件中第225行代码。
|
||
* 代码:
|
||
* //if (array_key_exists($config['serial'], $config['certs'])) {
|
||
* // throw new Exception\InvalidArgumentException(sprintf(
|
||
* // Exception\ERR_INIT_CERTS_EXCLUDE_MCHSERIAL, implode(',', array_keys($config['certs'])), $config['serial']
|
||
* // ));
|
||
* //}
|
||
*/
|
||
function toWxRefundQuery($config, $outRefundNo)
|
||
{
|
||
return Mmodel::catch(function () use ($config, $outRefundNo) {
|
||
// 配置参数
|
||
$params = new PublicParams();
|
||
$params->appID = $config['appid']; // 支付平台分配给开发者的应用ID
|
||
$params->mch_id = $config['mch_id']; // 微信支付分配的商户号
|
||
$params->key = $config['api_key']; // API 密钥
|
||
|
||
// 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书)
|
||
$params->certPath = $config['platformCertificateFilePath']; // 证书路径
|
||
$params->keyPath = $config['merchantPrivateKeyFilePath']; // 密钥路径
|
||
|
||
// SDK实例化,传入公共配置
|
||
$pay = new \Yurun\PaySDK\Weixin\SDK($params);
|
||
|
||
// 退款查询请求参数
|
||
$request = new \Yurun\PaySDK\Weixin\RefundQuery\Request();
|
||
$request->out_refund_no = $outRefundNo; // 商户退款单号
|
||
|
||
// 调用退款查询接口
|
||
Tools::log_to_write_txt(['调用退款查询接口,入参:outRefundNo=',$outRefundNo,$config]);
|
||
$result = $pay->execute($request);
|
||
Tools::log_to_write_txt(['调用退款查询接口,出参',$result]);
|
||
|
||
// 调试代码
|
||
if (!$pay->checkResult()) {
|
||
throw new Exception('退款查询错误:' . $pay->getError());
|
||
}
|
||
|
||
if($result['return_code'] == 'SUCCESS' && $result['result_code']=='SUCCESS'){
|
||
return Tools::set_ok('退款成功');
|
||
}
|
||
|
||
// 如果退款成功,$result 将包含退款操作的详细信息
|
||
//echo "退款成功,退款单号:" . $request->out_refund_no;
|
||
return Tools::set_fail('退款失败.',$result);
|
||
});
|
||
}
|
||
/**
|
||
* @deprecated 废弃,推荐使用toWxRefundQuery方法
|
||
*
|
||
* SDK要报证书错误,实战推荐使用[yurunsoft/pay-sdk]库
|
||
*
|
||
* 查询单笔退款
|
||
*
|
||
* 依赖:wechatpay/wechatpay微信支付推荐sdk
|
||
*
|
||
* 代码经过测试没有问题,如果出现“The certs(4xxxxxxxxxxxxx) contains the merchant's certificate serial number(4xxxxxxxxxxx) which is not allowed here.”
|
||
* 则是sdk代码问题,需要注释掉D:\wanghua\projects\meebo_mid\vendor\wechatpay\wechatpay\src\ClientJsonTrait.php
|
||
* 大约文件中第225行代码。
|
||
* 代码:
|
||
* //if (array_key_exists($config['serial'], $config['certs'])) {
|
||
* // throw new Exception\InvalidArgumentException(sprintf(
|
||
* // Exception\ERR_INIT_CERTS_EXCLUDE_MCHSERIAL, implode(',', array_keys($config['certs'])), $config['serial']
|
||
* // ));
|
||
* //}
|
||
*/
|
||
function wxRefundQuery($orderid){
|
||
$config = wxConfOrderPayFirm();
|
||
// 设置参数
|
||
// 商户号
|
||
$merchantId = $config['mch_id'];
|
||
|
||
//dump($config);
|
||
// 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名
|
||
$merchantPrivateKeyFilePath = $config['merchantPrivateKeyFilePath'];//'file:///path/to/merchant/apiclient_key.pem';
|
||
$merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);
|
||
|
||
// 「商户API证书」的「证书序列号」
|
||
$merchantCertificateSerial = $config['merchantCertificateSerial'];//'3775B6A45ACD588826D15E583A95F5DD********';
|
||
|
||
// 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名
|
||
$platformCertificateFilePath = $config['platformCertificateFilePath'];//'file:///path/to/wechatpay/cert.pem';
|
||
$platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
|
||
|
||
// 从「微信支付平台证书」中获取「证书序列号」
|
||
$platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath);
|
||
|
||
// 构造一个 APIv3 客户端实例
|
||
$instance = Builder::factory([
|
||
'mchid' => $merchantId,
|
||
'serial' => $merchantCertificateSerial,
|
||
'privateKey' => $merchantPrivateKeyInstance,
|
||
'certs' => [
|
||
$platformCertificateSerial => $platformPublicKeyInstance,
|
||
],
|
||
]);
|
||
// 退款单号
|
||
$outRefundNo = $orderid; // 商户系统内部的退款单号
|
||
|
||
try {
|
||
// 发起查询单笔退款请求
|
||
$response = $instance->chain("v3/refund/domestic/refunds/{$outRefundNo}")->get();
|
||
|
||
//echo $response->getStatusCode(), PHP_EOL;
|
||
//echo $response->getBody(), PHP_EOL;
|
||
$res_arr = json_decode($response->getBody(),true);
|
||
return Tools::set_ok('ok',$res_arr);
|
||
} catch (\Exception $e) {
|
||
Tools::error_txt_log($e);
|
||
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
|
||
$r = $e->getResponse();
|
||
//echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
|
||
//echo $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
|
||
|
||
$res_arr = json_decode($r->getBody(),true);
|
||
return Tools::set_fail('异常.',$res_arr);
|
||
}
|
||
//echo $e->getTraceAsString(), PHP_EOL;
|
||
return Tools::set_fail('异常.',$e->getMessage());
|
||
}
|
||
}
|
||
} |