微信支付流程详解

1、统一下单前计算签名

除付款码支付场景以外,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易会话标识后再按Native、JSAPI、APP等不同场景生成交易串调起支付。

  • 1、将需要发送的必填参数名按照ASCII码从小到大排序
  • 2、参数数组使用URL键值对的格式(即key1=value1&key2=value2…)拼接为字符串
  • 3、在字符串后边拼接商户平台设置的密钥key
  • 4、使用md5加密拼接的字符串
  • 5、得到字符串全部转化为大写就是需要的签名
    注意:
    ◆ 参数名ASCII码从小到大排序(字典序);
    ◆ 如果参数的值为空不参与签名;
    ◆ 参数名区分大小写;
    ◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
    ◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段
    ◆ key设置路径:微信商户平台(pay.weixin.qq.com)–>账户设置–>API安全–>密钥设置
$post['appid'] = $appid;			//微信公众号的appid
$post['mch_id'] = $mch_id;   		//微信支付分配的商户号(微信支付平台查看)
$post['nonce_str'] = $nonce_str;	//随机字符串,长度要求在32位以内。
$post['body'] = $body;				//商品描述
$post['out_trade_no'] = $out_trade_no;   	//商户订单号
$post['total_fee'] = intval($total_fee);    //总金额 单位为分  最低为一分钱 必须是整数
$post['spbill_create_ip'] = $_SERVER['SERVER_ADDR'];		//服务器终端的ip
$post['notify_url'] = $notify_url;		//微信回调地址    异步通知
$post['trade_type'] = $trade_type;		//交易类型 JSAPI -JSAPI支付
$post['openid'] = $openid;				//

//计算签名
$sign = $this->MakeSign($post,$KEY);              //签名
//计算签名
function MakeSign( $params,$KEY){
    //签名步骤一:按字典序排序数组参数
    ksort($params);
    $string = $this->ToUrlParams($params);  //参数进行拼接key=value&k=v
    //签名步骤二:在string后加入KEY
    $string = $string . "&key=".$KEY;
    //签名步骤三:MD5加密
    $string = md5($string);
    //签名步骤四:所有字符转为大写
    $result = strtoupper($string);
    return $result;
}
//拼接字符串
function ToUrlParams( $params ){
    $string = '';
    if( !empty($params) ){
        $array = array();
        foreach( $params as $key => $value ){
            $array[] = $key.'='.$value;
        }
        $string = implode("&",$array);
    }
    return $string;
}

2、统一下单并判断是否成功

  • 1、将统一下单的必要参数和签名转化为xml格式
  • 2、以post方式提交到接口:https://api.mch.weixin.qq.com/pay/unifiedorder
  • 3、将返回的xml格式数据转为数组格式

当返回的return_code(状态码)和result_code(业务结果)都为success时,统一下单成功,否则根据err_code(错误代码)和err_code_des(错误代码描述)的值判断错误类型。
错误代码详情参考【微信支付常见错误和统一下单错误码详情

$post_xml=$this->ToXml(array_merge($post,['sign'=>$sign]));

$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$xml = $this->http_request($url,$post_xml);     //POST方式请求http
$array = $this->xml2array($xml);               //将【统一下单】api返回xml数据转换成数组,全要大写
//数组转xml
function ToXml($array){ 	
	$xml = "<xml>";
	foreach ($array as $key=>$val){
		if (is_numeric($val)){
			$xml.="<".$key.">".$val."</".$key.">";
		}else{
			$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
		}
	}
	$xml.="</xml>";
	return $xml; 
}
//获取xml里面数据,转换成array
private function xml2array($xml){
   $p = xml_parser_create();
   xml_parse_into_struct($p, $xml, $vals, $index);
   xml_parser_free($p);
   $data = "";
   foreach ($index as $key=>$value) {
       if($key == 'xml' || $key == 'XML') continue;
       $tag = $vals[$value[0]]['tag'];
       $value = $vals[$value[0]]['value'];
       $data[$tag] = $value;
   }
   return $data;
}
//curl请求
public function http_request($url,$data = null,$headers=array()){
   $curl = curl_init();
   if( count($headers) >= 1 ){
       curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
   }
   curl_setopt($curl, CURLOPT_URL, $url);

   curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
   curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);

   if (!empty($data)){
       curl_setopt($curl, CURLOPT_POST, 1);
       curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
   }
   curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
   $output = curl_exec($curl);
   curl_close($curl);
   return $output;
}

3、微信内H5调起支付

后台:进行签名的参数

名称变量名描述
公众号idappId商户注册具有支付权限的公众号成功后即可获得
时间戳timeStamp当前的时间
随机字符串nonceStr随机字符串,不长于32位
订单详情扩展字符串package统一下单接口返回的prepay_id参数值,提交格式如:prepay_id=***
签名方式signType签名类型,默认为MD5,支持HMAC-SHA256和MD5

注意:

  • 1、签名规则和第一步的规则相同。
  • 2、注意此处需与统一下单的签名类型一致
  • 3、时间戳必须为字符串类型
$time = time();
$tmp['appId'] = $appid;
$tmp['timeStamp'] = "$time";
$tmp['nonceStr'] = "$nonce_str";
$tmp['package'] = 'prepay_id='.$array['PREPAY_ID'];
$tmp['signType'] = 'MD5';

$data['paySign'] = $this->MakeSign($tmp,$KEY);       //签名,具体签名方案参见微信公众号支付帮助文档;
$data['timeStamp'] = "$time";           //时间戳
$data['nonceStr'] = "$nonce_str";         //随机字符串
$data['package'] = 'prepay_id='.$array['PREPAY_ID'];   //统一下单接口返回的 prepay_id 参数值
$data['signType'] = 'MD5';              //签名算法,暂支持 MD5

前端:然后在前端页面调用微信JS-SDK中的【chooseWXPay】微信支付->发起一个微信支付请求,具体详情参考【微信公众号调用微信接口上传图片https://blog.csdn.net/G925010178/article/details/106462391】注入配置信息【wx.comfig】。

<script>
wx.chooseWXPay({
	timestamp: data.data['timeStamp'], // 支付签名时间戳,支付后台生成签名使用的timeStamp字段名需大写其中的S字符
	nonceStr: data.data['nonceStr'], // 支付签名随机串,不长于 32 位
	package: data.data['package'], // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*
	signType: data.data['signType'], // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
	paySign: data.data['paySign'], // 支付签名
	success: function (res) {
		//支付成功后的回调函数
	},
	cancel:function(res){
		//微信支付回调
	},
	fail:function(res){
		//接口调用失败时执行的回调函数
	}
});
</script>

参考链接

微信支付-统一下单https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1
微信支付-接口规则-安全规范https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3
微信网页开发-JS-SDK说明文档https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#58

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值