微信支付,首先需要注册一个商户平台公众账号,(网址: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;//订单生成的机器 IPString 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); //appidfinalpackage.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端支付成功后,会再次发送请求到服务器端,确定订单是否付款成功,服务端需要再次向微信发起请求,查询订单,具体操作查看下一章节。
注释:开发中遇到任务问题(服务端),欢迎咨询,我也是初次开发微信支付,希望可以帮到你。

浙公网安备 33010602011771号