PS:本篇文章主要是对PHP实现小程序退款以及退款回调数据解密的流程做大概解释,代码请各位按照自身需求进行修改 小程序js代码:
refundOrder(){
var refund = this
wx.request({
url: 'http://127.0.0.1:2910/wxPayV2/refundOrder/refundOrderAction.php',
method:'POST',
header:{
'content-type':'application/x-www-form-urlencoded'
},
data:{
'out_trade_no':'商户订单号',
'refund_fee':'1'
},
success(res){
console.log(res)
}
})
},
PHP微信v2退款类文件 refundOrder.php
<?php
require_once dirname(__FILE__,3).'/config/appConfig.php';
require_once dirname(__FILE__,2).'/createOrder/createOrder.php';
class refundOrder
{
public function __construct(){
$this -> APIv2 = APIv2;
$this -> appid = appid;
$this -> mch_id = mch_id;
}
public function nonce_str(){
$getData = new createOrder;
return $getData -> nonce_str();
}
public function out_refund_no(): string
{
$getData = new createOrder;
$data = $getData -> out_trade_no();
return 'T'.$data;
}
public function signBody($nonce_str,$transaction_id,$out_refund_no,$total_fee,$refund_fee): array
{
$data = array(
'appid' => $this -> appid,
'mch_id' => $this -> mch_id,
'nonce_str' => $nonce_str,
'sign_type' => 'MD5',
'transaction_id' => $transaction_id,
'out_refund_no' => $out_refund_no,
'total_fee' => $total_fee,
'refund_fee' => $refund_fee,
);
ksort($data);
return $data;
}
public function disposeSignBody($data): string
{
$signBody = '';
foreach ($data as $key => $val){
$signBody .= "$key=$val&";
}
$signBody .= "key=$this->APIv2";
return $signBody;
}
public function sign($signBody): string
{
return strtoupper(MD5($signBody));
}
public function requestBody($sign,$signBody): string
{
$signArray = array(
'sign' => $sign
);
$requestArray = array_merge($signArray,$signBody);
$requestBody = '<xml>';
foreach($requestArray as $key => $val){
$requestBody .= "<$key>".$val."</$key>";
}
$requestBody .= '</xml>';
return $requestBody;
}
public function curlRequest($url,$data){
$action = curl_init();
curl_setopt($action, CURLOPT_URL,$url);
curl_setopt($action, CURLOPT_HEADER,0);
curl_setopt($action, CURLOPT_POST,1);
curl_setopt($action, CURLOPT_POSTFIELDS,$data);
curl_setopt($action, CURLOPT_SSL_VERIFYPEER,0);
curl_setopt($action, CURLOPT_SSLCERTTYPE,'pem');
curl_setopt($action, CURLOPT_SSLCERT,dirname(__FILE__,3).'/cert/apiclient_cert.pem');
curl_setopt($action, CURLOPT_SSLKEYTYPE,'pem');
curl_setopt($action, CURLOPT_SSLKEY,dirname(__FILE__,3).'/cert/apiclient_key.pem');
curl_setopt($action, CURLOPT_SSL_VERIFYHOST,0);
curl_setopt($action, CURLOPT_RETURNTRANSFER,1);
curl_setopt($action, CURLOPT_CONNECTTIMEOUT,60);
$result = curl_exec($action);
curl_close($action);
return $result;
}
public function verifySign($data): bool
{
$sign = $data['sign'];
unset($data['sign']);
ksort($data);
$signBody = '';
foreach ($data as $key => $val){
$signBody .= "$key=$val&";
}
$signBody .= "key=$this->APIv2";
$verifySign = strtoupper(MD5($signBody));
if($verifySign == $sign){
return true;
}else{
return false;
}
}
}
PHP退款代码 refundOrderAction.php
<?php
require_once dirname(__FILE__).'/refundOrder.php';
require_once dirname(__FILE__,3).'/database/connect.php';
$out_trade_no = $_POST['out_trade_no'];
$refund_fee = $_POST['refund_fee'];
$buildData = new refundOrder;
$getInDatabase = new Connect;
$selectRefund = 'select * from order_basic_information where out_trade_no = "'.$out_trade_no.'";';
$databaseResult = $getInDatabase -> querySql($selectRefund);
$resultData = mysqli_fetch_assoc($databaseResult);
$status = $resultData['status'];
if($status == 1){
die('该订单未支付不能进行退款操作');
}
if($status == 7){
die('该订单已经退款,不能再次进行退款');
}
$transaction_id = $resultData['transaction_id'];
$total_fee = $resultData['total_fee'];
$out_refund_no = $resultData['out_refund_no'];
if(!isset($out_refund_no)){
$out_refund_no = $buildData -> out_refund_no();
}
$nonce_str = $buildData -> nonce_str();
$signBody = $buildData -> signBody($nonce_str,$transaction_id,$out_refund_no,$total_fee,$refund_fee);
$disposeSignBody = $buildData -> disposeSignBody($signBody);
$sign = $buildData -> sign($disposeSignBody);
$requestData = $buildData -> requestBody($sign,$signBody);
file_put_contents('./requestAndResultData.xml',$requestData."\n\r",FILE_APPEND);
$url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
$wxResult = $buildData -> curlRequest($url,$requestData);
if(!isset($wxResult)){
die('未接收到微信的返回数据');
}
file_put_contents('./requestAndResultData.xml',$wxResult."\n\r",FILE_APPEND);
$disposeWxData = simplexml_load_string($wxResult,null,LIBXML_NOCDATA);
$json_data = json_encode($disposeWxData);
$array_data = json_decode($json_data,true);
$refund_id = $array_data['refund_id'];
$updateSql = 'update order_basic_information set status = 7,refund_id = "'.$refund_id.'",refund_fee = "'.$refund_fee.'",out_refund_no = "'.$out_refund_no.'",refund_time = "'.date('Y-m-d H:i:s').'" where out_trade_no = "'.$out_trade_no.'";';
$getInDatabase -> querySql($updateSql);
curl返回的数据如下:
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[appid]]></appid>
<mch_id><![CDATA[商户号]]></mch_id>
<nonce_str><![CDATA[HF1WsvV3kQxqr26R]]></nonce_str>
<sign><![CDATA[签名]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<transaction_id><![CDATA[微信支付单号]]></transaction_id>
<out_trade_no><![CDATA[商户订单号]]></out_trade_no>
<out_refund_no><![CDATA[商户退款单号]]></out_refund_no>
<refund_id><![CDATA[微信退款单号]]></refund_id>
<refund_channel><![CDATA[]]></refund_channel>
<refund_fee>1</refund_fee>
<coupon_refund_fee>0</coupon_refund_fee>
<total_fee>1</total_fee>
<cash_fee>1</cash_fee>
<coupon_refund_count>0</coupon_refund_count>
<cash_refund_fee>1</cash_refund_fee>
</xml>
PS:由于隐私原因,商法的部分数据我已经隐去,不影响各位观看数据结构
以下是对退款回调数据的处理 PHP类代码 refundCallBack.php
<?php
require_once dirname(__FILE__,4).'/config/appConfig.php';
class refundCallBack
{
public function xmlToArray($data){
$disposeData = simplexml_load_string($data,null,LIBXML_NOCDATA);
$json_data = json_encode($disposeData);
return json_decode($json_data,true);
}
public function decrypt($req_info){
$APIv2 = APIv2;
$disposeAPI = strtolower(MD5($APIv2));
$disposeReq = base64_decode($req_info);
$decrypt = openssl_decrypt($disposeReq,'AES-256-ECB',$disposeAPI,OPENSSL_RAW_DATA);
file_put_contents('./returnData.xml',$decrypt."\n\r",FILE_APPEND);
return $decrypt;
}
}
PHP调用方法的代码 refundCallBackAction.php
<?php
require_once dirname(__FILE__).'/refundCallBack.php';
require_once dirname(__FILE__,4).'/database/connect.php';
$returnData = file_get_contents('php://input');
$content = $returnData;
file_put_contents('./returnData.xml',$content."\n\r",FILE_APPEND);
$getData = new refundCallBack;
$disposeContent = $getData -> xmlToArray($content);
$req_info = $disposeContent['req_info'];
$getDecryptData = $getData -> decrypt($req_info);
$decryptData = $getData -> xmlToArray($getDecryptData);
$refund_id = $decryptData['refund_id'];
$out_refund_no = $decryptData['out_refund_no'];
$refund_fee = $decryptData['refund_fee'];
$out_trade_no = $decryptData['out_trade_no'];
$refund_time = $decryptData['success_time'];
$refund_state = $decryptData['refund_state'];
$getInDatabase = new Connect;
$selectSql = 'select * from order_basic_information where out_trade_no = "'.$out_trade_no.'";';
$resultInDatabase = $getInDatabase -> querySql($selectSql);
$dataInDatabase = mysqli_fetch_assoc($resultInDatabase);
$status = $dataInDatabase['status'];
if($status == 7){
die('订单已经退款,状态已经修改,无需继续修改');
}
if($refund_state != 'SUCCESS'){
die('解密数据订单状态错误,请排查后重试');
}
$updateSql = 'update order_basic_information set status = 7,out_refund_no = "'.$out_refund_no.'",refund_id = "'.$refund_id.'",refund_time = "'.$refund_time.'",refund_fee = "'.$refund_fee.'" where out_trade_no = "'.$out_trade_no.'";';
$databaseResult = $getInDatabase -> querySql($updateSql);
if($databaseResult == 1){
$getReturnWxData = file_get_contents('./returnWxData.xml');
echo $getReturnWxData;
}
微信回调数据的展示
<xml>
<return_code>SUCCESS</return_code>
<appid><![CDATA[appid]]></appid>
<mch_id><![CDATA[商户号]]></mch_id>
<nonce_str><![CDATA[28cf5d99e569ef56178d8e49ed3213ec]]></nonce_str>
<req_info><!微信加密后的数据</req_info>
</xml>
<root>
<cash_refund_fee><![CDATA[1]]></cash_refund_fee>
<out_refund_no><![CDATA[商户退款单号]]></out_refund_no>
<out_trade_no><![CDATA[商户订单号]]></out_trade_no>
<refund_account><![CDATA[REFUND_SOURCE_RECHARGE_FUNDS]]></refund_account>
<refund_fee><![CDATA[1]]></refund_fee>
<refund_id><![CDATA[微信退款单号]]></refund_id>
<refund_recv_accout><![CDATA[支付用户零钱]]></refund_recv_accout>
<refund_request_source><![CDATA[API]]></refund_request_source>
<refund_status><![CDATA[SUCCESS]]></refund_status>
<settlement_refund_fee><![CDATA[1]]></settlement_refund_fee>
<settlement_total_fee><![CDATA[1]]></settlement_total_fee>
<success_time><![CDATA[2022-08-12 14:24:12]]></success_time>
<total_fee><![CDATA[1]]></total_fee>
<transaction_id><![CDATA[微信支付单号]]></transaction_id>
</root>
PS:由于隐私原因,上方部分数据已经隐去,但不影响关看数据结构
下面附上返回给微信通知的数据
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>
注意使用这个代码返回给微信后,微信将停止发送回调数据,所以在完成自己的逻辑之后再将此xml数据返回给微信
本文由CSDN用户: 缱绻淡蓝海 原创,代码具有时效性,作者会不定期对往期文章进行更新
|