微信公众号支付详解

因为在弄微信公众号网页支付的时候,遇到比较多的坑,而且微信给出的文档也比较乱。自己在百度的时候也看到很多人遇到相同的问题,但是都没有得到满意的答案。
所以就自己写个日志记录一下,也算是自己的一个积累。
首先我这里将的微信公众号网页支付的方式也就是JS API 网页支付。是指用户打开图文消息戒者扫描二维码,在微信内置浏览器打开网页进行的支付。商户网页前端通过使用微信提供的 JS API,调用微信支付模块。这种方式,适合需要在商户网页进行选购下单的购买流程。
在进行微信公众支付之前,我们需要申请个公众好,以及申请微信支付的功能。这些不在之类讲述。
申请好了以后,我们需要获取一下信息。


然后我们再来看一下微信网页支付的流程图。 我们先从后端开始。 如下图:

从流程图可以看出,我们需要先拿到用户的openid,这个openid 是用户在这个公众号的唯一标识。需要拿到这个openid 是需要用户做授权的。
这个获取用户openid 的步骤 在微信官方文档讲述的还是比较详细的。 在这里就不详细讲述。详情看官方文档
在我们获取到用户的openid 的时候,此时我们就可以生成一个预支付的订单。在jsapi 生成预支付订单是需要用的openid的。所以一开始获取用户 的openid 也就是为了生存预支付订单做准备的。接下来我们来看,怎么生成预支付订单。
根据微信的官方文档,我们需要用微信统一支付接口生成预支付订单。
主要有以下几个步骤:
查看那些参数必须要上传的
对需要上传的参数进行加密,得到一个加密后的字符串,作为一个参数上传。
提交数据,并接受返回回来的结果。
需要上传的参数,因为参数还是比较多,详情看微信的官方文档(注意,参数是区分大小写的)
参数加密的步骤如下:
第一步:对参数按照key=value的格式,并按照参数名ASCII字典序排序如下:
java中可以用如下方法对参数进行ASCII字典序排序

String []  getPr =
{"appid","mch_id","nonce_str","body","out_trade_no","total_fee","spbill_create_ip","notify_url","trade_type","attach","openid"};
Arrays.sort(getPr);
for(String list :getPr ){
System.out.println(list);
}
stringA=”appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA”;

第二步:拼接API密钥:(拼接好后,进行MD5加密,然后把加密结果的小写字母转化为大写字母,从而得到加密字符串(sign))

stringSignTemp=”stringA&key=192006250b4c09247ec02edce69f6a2d”
sign=MD5(stringSignTemp).toUpperCase()=”9A0A8659F005D6984697E2CA0A9CF3B7”

最后一步,提交数据。注意这里提交数据的格式是以xml 的格式提交的。格式如下:

 <xml> <appid>wx2421b1c4370ec43b</appid>
 <attach>支付测试</attach>
 <body>JSAPI支付测试</body>
 <mch_id>10000100</mch_id> 
<nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str> 
<notify_url>http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php</notify_url> 
<openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid> 
<out_trade_no>1415659990</out_trade_no> 
<spbill_create_ip>14.23.150.211</spbill_create_ip> 
<total_fee>1</total_fee> 
<trade_type>JSAPI</trade_type> 
<sign>0CB01533B8C1EF103065174F50BCA001</sign> 
</xml>

然后微信服务器返回的数据也是xml格式的。这个就自己找方法去解析这样的数据。 成功后则返回一下的参数:
返回的参数了则包含了 prepay_id 也就是支付流程里要我们获取的一个数据,其实这个就是预支付订单的订单编号,网页端就是拿这个订单编号去支付的。
但是前端要支付也还是要各种加密的。这个是比较恶心的。
现在我们来看前端应该怎么写。
要用微信 的接口,我们首先要做相应的权限配置。 详情看官方文档

wx.config({
debug:true,// 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId:'',// 必填,公众号的唯一标识
timestamp: ,// 必填,生成签名的时间戳
nonceStr:'',// 必填,生成签名的随机串
signature:'',// 必填,签名,见附录1
jsApiList: []// 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});

这里生成signtrue 需要这个页面的全路径,不需要带参数。这个是需要注意的。
当配置成功后,就可以发起支付请求了。当使用了支付请求这个接口,是要到微信里去配安全域名的。不然则会失败。而且测试也是要发布的这个域名下进行测试。我之前就一直在本地测试,一直不成功,这是我最大的坑。设置安全域名如下图:



还要在微信支付里 设置 支付目录。


然后就就在前端调用微信支付请求。


wx.ready(function(res){
$.hideLoading();
WeixinJSBridge.invoke('getBrandWCPayRequest',{
"appId":"${prepay.appId}",//公众号名称,由商户传入
"timeStamp":"${prepay.timpstamp}",//时间戳,自 1970 年以来的秒数
"nonceStr":"${prepay.nonceStr}",//随机串
"package":"prepay_id=${prepay.prepayId}",
"signType":"${prepay.signType}",//微信签名方式:
"paySign":"${prepay.paySign}"//微信签名
},function(res){
console.info(res);
console.debug(res);
if(res.err_msg =="get_brand_wcpay_request:ok") {
}// 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg 将在用户支付成功后返回 ok,但幵丌保证它绝对可靠。
});
});

paysign 这个签名生成的方式跟之前预支付订单sign 生成的方式是一样的 参数是区分大小写的。
官方文档
这样一个支付就可以了

如果在这方面遇到问题而解决不了的话。欢迎交流。 邮箱xuewenke123@qq.com

推荐阅读更多精彩内容