PHP 微信支付异步通知验签流程
总结微信支付异步通知notify_url的数据逻辑
1、微信的异步通知是XML,需要处理后才能转成json方便使用;
2、验签用到的key是商户后台 pay.weixin.qq.com 里边的apikey;
3、验签时,前边下单时透传到异步url参数里边的所有非标参数,均不能参与验签运算否则验签失败。
上码:
<?php
ini_set('date.timezone', 'Asia/Shanghai');
error_reporting(E_ERROR);
function wlog($str){
//追加方式记录文件,模式w 为覆盖重写
$myfile = fopen("/data/log/wxpayrecs.log", "a") or die("Unable to open file!");
fwrite($myfile, date('y-m-d H:i:s').$str."\r\n");
fclose($myfile);
}
$susretstr='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
$failretstr='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[]]></return_msg></xml>';
$inBody = file_get_contents('php://input'); //获取数据流
//样例数据 {"appid":"wx5c48****9f1","bank_type":"BOC_DEBIT","cash_fee":"1","fee_type":"CNY","is_subscribe":"Y","mch_id":"152****81",
//"nonce_str":"349217E0F*****1C8C249","openid":"oNvy-*****0SBLI","out_trade_no":"20210*****111",
//"rd":"704","result_code":"SUCCESS","return_code":"SUCCESS","sign":"5E828DF2933BED7E2B2F3BFF3F944CED","time_end":"20230208110409",
//"total_fee":"1","trade_type":"NATIVE","transaction_id":"420000******5576"}
if(empty($inBody)){ //没有发送数据流,可能是普通点击,直接无视为成功访问
exit($susretstr);
}
//wlog(' Body: '.str_replace("\n","",$inBody)); //调试阶段写日志
$xml=simplexml_load_string($inBody,'SimpleXMLElement', LIBXML_NOCDATA);
$result=json_decode(json_encode($xml),true);
if(empty($result["sign"])){ //缺少签名,直接失败
exit("fail");
}
if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
$Signature=$result['sign'];
//验签,todo 前边下单增加的透传参数不能参与验签
unset($result['sign'],$result['rd']);
//todo 这里可能需要增加sort排序操作
$s_src= http_build_query($result).'&key=51930******70D';
//wlog($s_src);
$vsign=strtoupper(md5($s_src));
if($Signature==$vsign){
wlog(' 支付验签 ok');
//todo 根据交易id,设置数据库交易未已成功
$out_trade_no=$result["out_trade_no"];
exit($susretstr);
}else{
wlog(' 验签失败 '.$vsign);
exit($failretstr);
}
}else{
exit($failretstr);
}