e2

滴滴侠,fai抖

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

微信支付,首先需要注册一个商户平台公众账号,(网址:https://pay.weixin.qq.com/index.php/home/d_login)

目前微信支付的接入方式有四种方式:公众号支付,APP支付,扫描支付,刷卡支付。本文中我将详细讲解一下APP支付。

微信支付→APP支付官方文档:https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=8_1

主要流程如下:(https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=8_3)

商户系统和微信支付系统主要交互说明:

步骤1:用户在商户APP中选择商品,提交订单,选择微信支付。

步骤2:商户后台收到用户支付单,调用微信支付统一下单接口。参见【统一下单API】。

步骤3:统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。参与签名的字段名为appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式为Sign=WXPay

步骤4:商户APP调起微信支付。api参见本章节【app端开发步骤说明】

步骤5:商户后台接收支付通知。api参见【支付结果通知API】

步骤6:商户后台查询支付结果。,api参见【查询订单API】

其中与后台相关的主要为步骤2和步骤6。虽然都有官方文档的说明,但是开发过程中,难免还会遇到不少的坑,比如签名问题,大小写问题等。

我首先讲解一下步骤2(统一下单API:https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_1):

统一下单接口地址:URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder,请求参数,返回参数等文档中都有详细描述,就不再一一说明,直接上代码:

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
@RequestMapping(value = "/createOrder", method = {RequestMethod.GET, RequestMethod.POST})
public String createOrder(Map model) throws Exception{
log.debug("WeChatPayController.createOrder,parameter[{trade_no,subject,total_fee},{"
+ request.getParameter("trade_no")
+ ","
+ request.getParameter("subject")
+ ","
+ request.getParameter("total_fee") + "}]");
 
WeChatRsp response = new WeChatRsp();
WeChat weChat = new WeChat();
 
String orderNo = request.getParameter("trade_no"); //订单号
String money = request.getParameter("total_fee"); //订单金额
String body = request.getParameter("subject"); //商品描述根据情况修改
 
//金额转化为分为单位
float sessionmoney = Float.parseFloat(money);
String finalmoney = String.format("%.2f", sessionmoney);
finalmoney = finalmoney.replace(".", "");
 
//商户相关资料
String appid = CommonUtils.getPropertiesValue("config", "appid");
String appsecret = CommonUtils.getPropertiesValue("config", "appsecret");
String partner = CommonUtils.getPropertiesValue("config", "partnerId");
String partnerkey = CommonUtils.getPropertiesValue("config", "partnerkey");
 
//商户号
String mch_id = partner;
//随机数
Random random = new Random();
String nonce_str = cn.emagsoftware.utils.MD5Util.getMD5String(String.valueOf(random.nextInt(10000)));
 
//商户订单号
String out_trade_no = orderNo;
int intMoney = Integer.parseInt(finalmoney);
 
//总金额以分为单位,不带小数点
int total_fee = intMoney;
//订单生成的机器 IP
String spbill_create_ip = request.getRemoteAddr();
System.out.println("订单生成的机器IP:"+spbill_create_ip);
 
//这里notify_url是 支付完成后微信发给该链接信息,可以判断会员是否支付成功,改变订单状态等。
String notify_url = CommonUtils.getPropertiesValue("config", "weChat_notify_url");
//交易类型
String trade_type = CommonUtils.getPropertiesValue("config", "trade_type");
 
SortedMap packageParams = new TreeMap();
packageParams.put("appid", appid);
packageParams.put("mch_id", mch_id);
packageParams.put("nonce_str", nonce_str);
packageParams.put("body", body);
packageParams.put("out_trade_no", out_trade_no);
 
packageParams.put("total_fee", total_fee+"");
packageParams.put("spbill_create_ip", spbill_create_ip);
packageParams.put("notify_url", notify_url);
 
packageParams.put("trade_type", trade_type);
 
HttpServletResponse httpServletResponse = null;
RequestHandler reqHandler = new RequestHandler(request, httpServletResponse);
reqHandler.init(appid, appsecret, partnerkey);
 
String sign = reqHandler.createSign(packageParams);
String xml=""+
""+appid+""+
""+
""+mch_id+""+
""+nonce_str+""+
""+notify_url+""+
""+out_trade_no+""+
""+sign+""+
""+spbill_create_ip+""+
""+total_fee+""+
""+trade_type+""+
"";
log.debug("xml = "+xml);
String createOrderURL = WECHAT_CREATE_ORDER_URL;
String prepay_id="";
//获取预支付交易号
try {
prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml, "prepay_id");
} catch (Exception e1) {
e1.printStackTrace();
response.setResultCode(Constant.ERROR_CODE_9998);
response.setResultMessage(Constant.ERROR_MESSAGE.get(Constant.ERROR_CODE_9998));
}
 
if (prepay_id!=null& !prepay_id.equals("")) {
response.setResultCode(Constant.SUCCESS_CODE);
response.setResultMessage(Constant.ERROR_MESSAGE.get(Constant.SUCCESS_CODE));
weChat.setAppid(appid);
weChat.setPrepayid(prepay_id);
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
String nonce_string = cn.emagsoftware.utils.MD5Util.getMD5String(timestamp);
weChat.setTimestamp(timestamp);
weChat.setNoncestr(nonce_string);
weChat.setPackages("Sign=WXPay");
weChat.setPartnerid(partner);
 
//二次签名
SortedMap finalpackage = new TreeMap();
finalpackage.put("appid", appid);
finalpackage.put("timestamp", timestamp);
finalpackage.put("noncestr", nonce_string);
finalpackage.put("package", "Sign=WXPay");
finalpackage.put("partnerid", mch_id);
finalpackage.put("prepayid", prepay_id);
String finalsign = reqHandler.createSign(finalpackage);
weChat.setSign(finalsign);
response.setData(weChat);
}else {
log.debug("预支付交易号生成失败。。。");
response.setResultCode(Constant.ERROR_CODE_9998);
response.setResultMessage(Constant.ERROR_MESSAGE.get(Constant.ERROR_CODE_9998));
}
 
try{
model.put(Constant.RETURN_MESSAGE, JsonUtils.getJSONString(response));
log.debug("WeChatPayController.createOrder.response=="+JsonUtils.getJSONString(response));
} catch (Exception ex) {
log.error("VersionController.getVersion", ex);
}
return RET_JSP;
}

APP端发起支付请求之后,会发送订单号给服务端程序,服务端拿到订单号之后,根据统一下单地址,发送xml文件给微信,微信接受处理后,如果返回成功,则同时会返回一个预支付交易会话标识(prepay_id),拿到这个标识之后,服务端进行二次签名,生成sign,签名参数如下:

1
2
3
4
5
6
7
8
9
10
11
12
//二次签名
SortedMap finalpackage = new TreeMap();
finalpackage.put("appid", appid);   //appid
finalpackage.put("timestamp", timestamp);  //时间戳  十位 
finalpackage.put("noncestr", nonce_string); //随机字符串
finalpackage.put("package", "Sign=WXPay");   //固定值
finalpackage.put("partnerid", mch_id);  //商户id(微信商户平台获取)
finalpackage.put("prepayid", prepay_id);  //第一次请求微信,成功后,返回的参数
String finalsign = reqHandler.createSign(finalpackage);  //生成签名
weChat.setSign(finalsign);  //生成签名后,放入对象中
 
response.setData(weChat);  //参数返回给前端

第一次发送统一下单的时候,官方文档中都有说明,哪些参数是必须的,哪些参数不是必须的,以及参数类型,此处不再一一解释,不理解的可以参考官方文档。重点说一下二次签名:

二次签名的时候涉及到的参数有appid,timestamp,noncestr,partnerid,prepayid,package,这6个参数全部是小写(大小写不同,MD5加密结果不一致,二次签名官方没有文档,比较坑)

APP端获取到服务端传递的参数后,调起支付接口(https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_12&index=2),这一点是APP端的操作,不在详解。

APP端支付成功后,会再次发送请求到服务器端,确定订单是否付款成功,服务端需要再次向微信发起请求,查询订单,具体操作查看下一章节。

注释:开发中遇到任务问题(服务端),欢迎咨询,我也是初次开发微信支付,希望可以帮到你。

posted on 2017-06-30 18:16  纯黑Se丶  阅读(904)  评论(0)    收藏  举报