前面写了微信小程序支付这一块的 现在整理一下 写一下在做微信退款接口时遇到的坑
退款接口请求的api参数处理
public function refund(){
// 小程序id - 商户平台密钥
$key = "商户秘钥"; // 商户秘钥
$appid = '你的小程序appid'; //你的小程序appid
$mch_id = "商户号"; //商户号
$str="QWERTYUIPADGHJKLZXCVNM1234567890";
$nonce_str = str_shuffle($str); // 随机字符串
// 签名
$out_trade_no = '商户订单号'; //商户订单号
$transaction_id = '微信订单号';// 微信订单号
//注意 ###################### 其中微信订单号与商户订单号 有一个值就OK ###############
// 商户退款订单号
$out_refund_no = date("YmdHis");
//订单金额
$total_fee ='订单的金额'; // 注意是以分为单位
//退款金额
$refund_fee = '需要退款的金额' // 注意是以分为单位;
$notify_url = "异步地址"; //异步地址 注意 是要外网可以访问的地址 并且不能携带参数
if($out_trade_no && !empty($out_trade_no)){
$refund_array = [
"appid"=>$appid, //你的小程序appid
"mch_id"=>$mch_id,//商户号
"nonce_str"=>$nonce_str, // 随机字符串
"notify_url"=>$notify_url, //异步地址
"out_refund_no"=>$out_refund_no, // 商户退款订单号
"out_trade_no"=>$out_trade_no, //商户订单号
"refund_fee"=>$refund_fee, //订单金额
"total_fee"=>$total_fee, //订单金额
];
$signA = "appid=$appid&mch_id=$mch_id&nonce_str=$nonce_str¬ify_url=$notify_url&out_refund_no=$out_refund_no&out_trade_no=$out_trade_no&refund_fee=$refund_fee&total_fee=$total_fee";
}else if(($transaction_id&& !empty($transaction_id)){
$refund_array = [
"appid"=>$appid, //你的小程序appid
"mch_id"=>$mch_id,//商户号
"nonce_str"=>$nonce_str, // 随机字符串
"notify_url"=>$notify_url, //异步地址
"out_refund_no"=>$out_refund_no, // 商户退款订单号
"refund_fee"=>$refund_fee, //订单金额
"total_fee"=>$total_fee, //订单金额
"transaction_id"=>transaction_id, //商户订单号
];
$signA = "appid=$appid&mch_id=$mch_id&nonce_str=$nonce_str¬ify_url=$notify_url&out_trade_no=$out_trade_no&refund_fee=$refund_fee&total_fee=$total_fee&transaction_id=$transaction_id";
}
$sign = strtoupper(md5($signA."&key=".$key));
$refund_array['sign'] = $sign;
$url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
$data = $this->arrayToXml($refund_array);
$result = $this->refund_wxpost($url,$data);
var_dump($result);
}
异步回调函数处理 目前这里只接收微信返回给我们的数据 具体的逻辑处理需要根据自己的项目进行调整
// 退款异步回调地址
public function refund_notify_url(){
$receipt = $_REQUEST;
if($receipt==null){
$receipt = file_get_contents("php://input");
}
if($receipt == null){
$receipt = $GLOBALS['HTTP_RAW_POST_DATA'];
}
}
发送post 请求
// 发送post 请求
protected function refund_wxpost($url,$post)
{
//初始化
$curl = curl_init();
$header[] = "Content-type: text/xml";//定义content-type为xml
//设置抓取的url
curl_setopt($curl, CURLOPT_URL, $url);
//设置头文件的信息作为数据流输出
curl_setopt($curl, CURLOPT_HEADER, 1);
//定义请求类型
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
//设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
//设置post方式提交
curl_setopt($curl, CURLOPT_POST, 1);
//第一种方法,cert 与 key 分别属于两个.pem文件 // 证书参数
//默认格式为PEM,可以注释
curl_setopt($curl,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($curl,CURLOPT_SSLCERT, "./apiclient_cert.pem"); // 退款时需要用到商户的证书 这里写相对地址就可以了
//默认格式为PEM,可以注释
curl_setopt($curl,CURLOPT_SSLKEYTYPE,'PEM');
curl_setopt($curl,CURLOPT_SSLKEY,"./apiclient_key.pem"); // 退款时需要用到商户的证书 这里写相对地址就可以了
//第二种方式,两个文件合成一个.pem文件
// curl_setopt($ch,CURLOPT_SSLCERT,'./all.pem');
//设置post数据
$post_data = $post;
curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
//执行命令
$data = curl_exec($curl);
//显示获得的数据
if ($data)
{
curl_close($curl); //关闭URL请求
return $data;
}else{
$res = curl_error($curl);
curl_close($curl);//关闭URL请求
return $res;
}
}
其他中间的 xml转数组 以及 数组转xml的函数请参考我另外的一个文档
这个只是一个发送请求的接口 异步通知的返回的数据 就是上面设置的异步通知回调地址
下面是退款通知结果
其中req_info 是加密的之后的信息 需要进行解密之后才能看到详细信息
所以对返回的数据需要进行解密处理
上面是具体的解密步骤 在这里我也列出来 具体的解密方法 请在php7.2版本一下使用
function refund_decrypt($str, $key)
{
$str = base64_decode($str);
$str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_ECB);
$len = strlen($str);
$pad = ord($str[$len - 1]);
return substr($str, 0, strlen($str) - $pad);
}
拿到了微信处理之后的结果 我们就可以在 异步回调函数里面进行相关的的逻辑处理了 具体的处理方式需要根据自己的项目来定 这里就不写了