这段日子在写微信支付退款的时候,发现很多问题,当然主要问题还是发生在异步回调的路上。
申请退款
总的来说呢,申请退款是挺简单的。但是还是有几个重点的。比如说SSL证书的POST请求
,再比如说商家用户的KEY
。
这几个点可以在百度中找到答案。
我接下来就直接上申请退款的代码好了
代码实现之类文件
1.Xwechat.php ```php class Xwechat{ protected static function getConfig(){ $config = \think\facade\Config::get('tool.wechat.wechat_app'); if (!isset($config) || !isset($config['appid']) || !isset($config['appsecret']) || empty($config['appid']) || empty($config['appsecret'])){ outErr(31,'wechat app config is missing'); } return $config;
}
public static function refund($orderSn,$refundOrderSn,$total_fee,$refund_fee,$transaction_id){ $time = date('Y-m-d H:i:s',$time);
$config = self::getConfig();
$wechatConfig = \think\facade\Config::get('tool.wechat.wechat_pay');
$unifiedData = [
'appid' => $config['appid'],
'mch_id' => $wechatConfig['mchid'],
'nonce_str' => md5($time),
// 'body' => $body, 'out_trade_no' => $orderSn, 'out_refund_no' => $refundOrderSn, 'refund_fee' => $refund_fee * 100, 'total_fee' => $total_fee * 100, 'transaction_id' => $transaction_id, 'notify_url' => $wechatConfig['refund_notify'] ]; $unifiedData['sign'] = self::wechatPayCreateSign($unifiedData,$wechatConfig);
$xmlData = Xstring::arrayToXml($unifiedData);
$postData = HttpRequest::postRefundWechatPaySSLData($xmlData,'https://api.mch.weixin.qq.com/secapi/pay/refund');
$res = Xstring::xmlToArray($postData);
if ($res['return_code'] == 'FAIL'){
if (!empty($content['err_code_des'])) {
outErr(1,$content['err_code_des']);
}else{
outErr(1,$content['return_msg']);
}
}
return $res;
}
public static function wechatPayCreateSign($arr,$config){ ksort($arr);
$string="";
$i=1;
foreach($arr as $key=>$val){
if($i == 1){
$string .= $key."=".$val;
}else{
$string .= "&".$key."=".$val;
}
$i++;
}
$signtemp = $string."&key=".$config['key'];
$sign = MD5($signtemp);
$sign = strtoupper($sign);
return $sign;
} }
2.Xstring.php
```php
class Xstring{
public static function xmlToArray($data){
libxml_disable_entity_loader(true);
$data = json_decode(json_encode(simplexml_load_string($data,'SimpleXMLElement',LIBXML_NOCDATA)),true);
return $data;
}
public static function arrayToXml($arr){
$xml = "";
foreach ($arr as $key=>$val){
if (is_numeric($val)){
$xml.="<".$key.">".$val."".$key.">";
}else{
$xml.="<".$key.">".$key.">";
}
}
$xml.=" ";
return $xml;
}
}
3.HttpRequest.php
class HttpRequest{
public static function postRefundWechatPaySSLData($xml,$url,$second = 30){
$path = dirname(__DIR__).'/file/wechatRefundPaySSL/';
if (is_array($xml)) {
$xml = http_build_query($xml);
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
if (!empty($options)) {
curl_setopt_array($ch, $options);
}
//https请求 不验证证书和host
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
//第一种方法,cert 与 key 分别属于两个.pem文件
//默认格式为PEM,可以注释
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLCERT,$path.'apiclient_cert.pem');//证书路径
//默认格式为PEM,可以注释
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLKEY,$path.'apiclient_key.pem');//证书路径
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
}
代码实现之实现
1.Refund.php ```php class Refund{ Xwechat::refund('商家订单号','商家退款单号','订单总价','退款金额','transaction_id'); } ```退款回调
回调这里有个很严重的问题,那就是php>7.0的开发者注意,解密函数mcrypt_decrypt()不可用,要用openssl_decrypt()代码实现
1.Notify.php ```php class Notify{ public function refund(){ //先获取微信服务器过来的XML信息 //最主要是解密 $wechatConfig = \think\facade\Config::get('tool.wechat.wechat_pay'); $datas = Xstring::xmlToArray(self::refundDecrypt($data['req_info'],md5($wechatConfig['key']))); if ('SUCCESS' == $datas['refund_status']){
RefundAction::_updateStateById('success',[
'refundSn' => $datas['out_refund_no']
]);
$result = $datas;
}else{
$result = false;
}
}else{
$result = false;
}
if ($result){
$str=' ';
}else{
$str=' ';
}
echo $str;
}
//php>7.0
public static function refundDecrypt($str,$key){
$str = openssl_decrypt($str , 'aes-256-ecb',$key, OPENSSL_ZERO_PADDING);
$pad = ord($str[($len = strlen($str)) - 1]);
$len = strlen($str);
$pad = ord($str[$len - 1]);
return substr($str, 0, strlen($str) - $pad);
}
//php<=7.0
public static function refundDecrypt($str,$key){
$str = base64_decode($str);
$str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_ECB);
$block = mcrypt_get_block_size('rijndael_128', 'ecb');
$pad = ord($str[($len = strlen($str)) - 1]);
$len = strlen($str);
$pad = ord($str[$len - 1]);
return substr($str, 0, strlen($str) - $pad);
}
}
本文为ctexthuang原创文章,转载请注明来自[ctexthuang_blog][1]
[1]: https://ctexthuang.com