微信开发——微信支付(公众号支付开发)

Posted by Cchua on 2017-04-24

  
  
  看到Tx的WeChatPay的文档真是无语了,感觉乱七八糟的……这里自己稍微整理下我的流程。这里的业务流程主要针对于公众号支付         

  

设置

  https://pay.weixin.qq.com
  
  在这取得
  MchId--商户号
  apiKey--商户Key
  
  https://mp.weixin.qq.com
  
  在这取得
  AppID-应用ID
  
  在页面的->微信支付->开发配置->公众号支付
  
  设置对应的支付授权目录、测试授权目录、已经将自己的微信号添加到白名单

  

统一下单

  买家在在提交订单以后,将向微信生成支付订单,在微信生成支付订单;

生成Sign值

  根据文档的说明,要产生一张订单,WeChat的接口需要我们Post一段带有订单信息的XML给他们。
  
  在自己的商城生成了该订单的相关信息以后,首先根据WeChat的Sign签名算法的生成签名,将要post过去除了sign以外的所有信息(一定是所有!这里特别强调下,我在这里给误导了好久以为只用把官方文档上要的Sign进行前面算法),进行官方的Sign签名算法(详情见微信文档),通过签名算法计算得出的签名值。
  
  代码示例:
  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static String getWXPayMD5(SortedMap<String, String> packageParams, String apiKey) {
StringBuffer sb = new StringBuffer();
Set es = packageParams.entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
if (null != v && !"".equals(v) && !"sign".equals(k)
&& !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + apiKey);
return MD5(sb.toString()).toUpperCase();
}

notify_url——异步接收微信支付结果通知的回调地址

  
  既然是支付,支付成功以后,微信就要告诉你卖家已经支付成功,也就是支付结果的通知,notify_url 就是拿来设置微信在哪里告诉你买家已经支付成功的地方。         

后台发送订单信息

  当生成Sign的签名值生成和回调的接口设置好以后,后台需要发送订单要生成的订单信息,并接受生成好订单信息;后台需要将Xml信息整合在一起在后台Post到微信的接口上,并且接收回调信息,这是他会告诉你订单是否接受成功,并且把微信支付订单的相关信息告诉你。(特别注意:这里要发起Https的请求)
  
  Post过去的信息举例如下:
  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<xml>
<appid>公众账号的ID</appid>
<attach>支付测试</attach>
<body>JSAPI支付测试</body>
<mch_id>商户号</mch_id>
<nonce_str>随机字符串</nonce_str>
<notify_url>你要回调的地址接口</notify_url>
<openid>用户标识-用户的openid</openid>
<out_trade_no>你自己系统内部的订单号</out_trade_no>
<spbill_create_ip>14.23.150.211</spbill_create_ip>
<total_fee>1</total_fee>
<trade_type>JSAPI</trade_type>
<sign>你其他信息合在一起的sign签名值</sign>
</xml>

Post成功后微信会在后台生成微信支付订单
  
 回调的信息举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>提交订单的公众账号ID
<mch_id><![CDATA[10000100]]></mch_id>提交订单的商户号
<nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
<openid><![CDATA[oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]></openid>
<sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx20141110174]]></prepay_id>微信生成的订单号
<trade_type><![CDATA[JSAPI]]></trade_type>
</xml>

生成paySign,回调订单信息给网页端

  当支付订单生成以后,需要生成paySign给网页端,准备让网页端调用支付的API;将appId、
timeStamp、nonceStr、package(特别注意格式prepay_id=XXXX)、signType、进行paySign签名生成,生成的方法和Sign一样。之后将这些信息返回给网页端;

  

网页端调起支付API

  当支付订单生成以后,得到了加密的PaySign以后,将appI、timeStamp、nonceStr、package、signType、paySign填写正确以后,微信将调用支付页面,买家将可以进行付款
  
  代码示例:
  

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
function onBridgeReady(){
WeixinJSBridge.invoke( //注意:WeixinJSBridge内置对象在其他浏览器中无效。
'getBrandWCPayRequest', { //以下都是后台处理好的信息,相当于支付的订单信息
"appId":"wx2421b1c4370ec43b",
"timeStamp":"1395712654",
"nonceStr":"e61463f8efa94090b1f366cccfbbb444",
"package":"prepay_id=u802345jgfjsdfgsdg888",
"signType":"MD5",
"paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89"
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {}
}
);
}
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
}else{
onBridgeReady();
}

接受支付成功信息

  当买家支付成功以后,微信会Psot一段信息到你的服务器上,之前notify_url——就是异步接收微信支付结果通知的回调地址,这种时候就需要写一个接口,让微信把支付成功的数据Post过来,我们需要接收处理这段数据,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。
  
  当收到这段信息以后,需要回调一段信息,告诉微信已经收到支付成功的信息了!不用再发了!
  

1
2
3
4
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>

  否则微信会通过一定的策略定期重新发起通知(通知频率为15/15/30/180/1800/1800/1800/1800/3600,单位:秒),

  告诉微信收到支付信息的同时,我们就可以处理其他业务信息了。~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RequestMapping(value = "/payresponse", method = RequestMethod.POST)
@ResponseBody
public String Payresponse(@RequestBody String PayResponse) {
public void run(){
/*开多个处理其他业务*/
}
String WXresult = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
return WXresult;
}
}

  
                                    ————完


世界上本没有坑,都是自己挖的!……