1.获取订单信息
2.根据订单信息和支付相关的账号生成sign,并且生成支付参数
3.将支付参数信息POST到微信服务器,获取返回信息
4.根据返回信息生成相应的支付代码(微信内部)或是支付二维码(非微信内),完成支付。
下面分步骤的讲一下:
1.微信支付中相关的必须的订单参数有三个,分别是:body(商品名或订单描述),out_trade_no(一般为订单号)和total_fee(订单金额,单位“分”,要注意单位问题),在不同的应用中,首先要做的就是获取订单中的相关信息,为支付参数生成做准备。
2.其他必须的支付参数有 appid(微信appid),mch_id(申请成功后告知),device_info(web端和微信端该参数都是统一的,为大写的”WEB“),trade_type(根据使用场景不同,该值也是不同的,微信外部为”NATIVE“,微信内部为”JSAPI“),nonce_str(32位随机字符串),spbill_create_ip(发起支付的终端IP,即服务器IP),notify_url(支付回调地址,微信服务器通知网站支付完成与否,修改订单状态),sign(签名),还有一个需要说明的地方,如果trade_type为JSAPI的话,openid为必填的参数。
签名算法是比较容易出错的地方,在于签名步骤繁琐,其实很关键的是,sign不参与签名
A:将1、2中提到的除sign外的参数赋值,放到一个数组array里面,按照字典顺序排序,其实就是键值按照A—Z的顺序进行排序。
B:将数组转换成字符串string,格式为 k1=v1&k2=v2&...kN=vN
C:在此string后加上KEY值(在微信支付商户后台用户自己设定的)现在string = k1=v1&k2=v2&...kN=vN&key=KEY。
D:string = md5(string)
E: sign = strtoupper(string)
至此,sign生成完毕。
将sign添加到array数组里面生成新的数组。将该数组转换为XML。至此,微信支付的参数准备工作完成。
3.将2中生成的XML,使用POST的方式发送请求到微信(https://api.mch.weixin.qq.com/pay/unifiedorder),获取返回的XML信息,将该信息转换成数组格式方便操作。返回的XML信息如下:
1
2
3
4
5
6
7
8
9
10
11
|
< xml >
< return_code > <![CDATA[SUCCESS]]> </ return_code >
< return_msg > <![CDATA[OK]]> </ return_msg >
< appid > <![CDATA[wx2421b1c4370ec43b]]> </ appid >
< mch_id > <![CDATA[10000100]]> </ mch_id >
< nonce_str > <![CDATA[IITRi8Iabbblz1Jc]]> </ nonce_str >
< sign > <![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]> </ sign >
< result_code > <![CDATA[SUCCESS]]> </ result_code >
< prepay_id > <![CDATA[wx201411101639507cbf6ffd8b0779950874]]> </ prepay_id >
< trade_type > <![CDATA[JSAPI]]> </ trade_type >
</ xml >
|
如果是trade_type==native支付的话,还会多一个参数code_url,该URL为微信扫码支付的地址。
4.下面就是支付的过程了。
如果trade_type==native,那么使用一些方式将code_url转换成二维码,使用微信扫码就可以了,如果是微信内部点击支付的话,需要调用微信js-sdk中的相关东西,这一步中最关键是生成一个json格式的字符串。
首先要生成转换json字符串的数组array_jsapi。
A:该数组的参数包括:appId,timeStamp,nonceStr,package,signType(默认为”MD5“),要注意大小写和上面的数组里面是不一样的。
B:使用该数组生成paySign参数,签名方式同上。
C:将paySign参数追加到array_jsapi数组中。
D:将该数组使用json_encode格式化为字符串js_string。
完成上面的工作,就可以在微信内部进行支付了。
下面为相关支付的示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<script type= 'text/javascript' >
function jsApiCall()
{
WeixinJSBridge.invoke(
'getBrandWCPayRequest' ,
$js_string,
function (res){
WeixinJSBridge.log(res.err_msg);
if (res.err_msg== 'get_brand_wcpay_request:ok' )
{
alert( '支付成功' );
}
else
{
alert( '支付失败' );
}
}
);
}
function callpay()
{
if ( typeof WeixinJSBridge == 'undefined' ){
if ( document.addEventListener ){
document.addEventListener( 'WeixinJSBridgeReady' , jsApiCall, false );
} else if (document.attachEvent){
document.attachEvent( 'WeixinJSBridgeReady' , jsApiCall);
document.attachEvent( 'onWeixinJSBridgeReady' , jsApiCall);
}
} else {
jsApiCall();
}
}
</script>
|
代码中js_string即为我们生成的字符串。
HTML代码中调用callpay()函数发起支付。
这样微信支付的支付工作就完成了。
下面是回调工作,该功能确保订单支付成功后,有正确的状态显示给用户。
支付完成后,微信使用POST请求,将支付结果反馈给网站服务器,网站服务器获取POST信息,根据支付成功与否,来确定是否修改订单信息。
A:将POST参数中的sign去除,并且记录下来该值。
B:对剩余的参数进行签名
C:将签名结果和POST中的sign进行比对,相同说明签名正确,根据支付结果修改订单状态。
E:返回XML信息给微信,确保微信知道网站已经收到该通知,避免微信再次推送POST,示例如下:
1
2
3
4
|
< xml >
< return_code > <![CDATA[SUCCESS]]> </ return_code >
< return_msg > <![CDATA[OK]]> </ return_msg >
</ xml >
|
如果失败,则返回
1
2
3
4
|
< xml >
< return_code > <![CDATA[FAIL]]> </ return_code >
< return_msg > <![CDATA[失败原因]]> </ return_msg >
</ xml >
|
至此,微信支付的整个开发介绍完毕。