最近因為項目要做微信支付、是以把過程記錄下來以備以後會需要到。
1.微信支付文檔:https://open.swiftpass.cn/openapi/doc?index_1=5&index_2=1&chapter_1=30&chapter_2=32#
2.因為項目是Java的、是以我下載下傳了Java的demo
如下:
這裡的servlet就是主要的方法:測試支付、訂單狀态查詢、通知、測試退款、退款查詢幾個方法、這些都有針對的APi文檔可以檢視;
1.測試支付
1 public String wechatPay(HttpServletRequest req, HttpServletResponse resp, DOPayBean bean) throws ServletException, IOException {
2 Map<String,String> orderResult = new HashMap<String, String>(); //用來存儲訂單的交易狀态(key:訂單号,value:狀态(0:未支付,1:已支付)) ---- 這裡可以根據需要存儲在資料庫中
3 req.setCharacterEncoding("utf-8");
4 resp.setCharacterEncoding("utf-8");
5
6 SortedMap<String,String> map = XmlUtils.getParameterMap(req);
7
8 9 map.put("mch_id", "175510359638");
10 //重複送出的時候直接查詢本地的狀态
11 /* if(orderResult != null && orderResult.containsKey(map.get("out_trade_no"))){
12 String status = "0".equals(orderResult.get(map.get("out_trade_no"))) ? "未支付" : "已支付";
13 resp.setHeader("Content-type", "text/html;charset=UTF-8");
14 resp.getWriter().write(status);
15 }else{*/
16 map.put("notify_url", "http://wasdsad.net/card/swpay/pay_notify_alipay_pay.html");
17 // map.put("out_trade_no", "2017060612004115998");
18 map.put("out_trade_no", "2017060612004115999");
19
20 map.put("service", "pay.weixin.wappay");
21 map.put("version", "2.0");
22 map.put("charset", "UTF-8");
23 map.put("sign_type", "MD5");
24 map.put("body", "測試購買商品");
25 map.put("attach", "附加資訊");
26 map.put("total_fee", "1");
27 map.put("mch_create_ip", "127.0.0.1");
28
29 map.put("nonce_str", String.valueOf(new Date().getTime()));
30 map.put("callback_url","https://www.baidu.com/");//前端頁面跳轉位址(包括支付成功和關閉時都會跳到這個位址)
31
32 //注意:device_info、mch_app_name、mch_app_id這三個具體傳值必須以文檔說明為準,傳真實有效的,否則有可能無法正常支付!!!
33 map.put("device_info", "AND_SDK");
34 map.put("mch_app_name", "王者榮耀");
35 map.put("mch_app_id", "com.tencent.tmgp.sgame");
36 Map<String,String> params = SignUtils.paraFilter(map);
37 StringBuilder buf = new StringBuilder((params.size() +1) * 10);
38 SignUtils.buildPayParams(buf,params,false);
39 String preStr = buf.toString();
40 String sign = MD5.sign(preStr, "&key=" + "61307e5f2aebcacecb****fe5296df9c", "utf-8");
41 map.put("sign", sign);
42
43 String reqUrl = "https://pay.swiftpass.cn/pay/gateway";
44 System.out.println("reqUrl:" + reqUrl);
45
46 System.out.println("reqParams:" + XmlUtils.parseXML(map));
47 CloseableHttpResponse response = null;
48 CloseableHttpClient client = null;
49 String res = null;
50 try {
51 HttpPost httpPost = new HttpPost(reqUrl);
52 StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map),"utf-8");
53 httpPost.setEntity(entityParams);
54 //httpPost.setHeader("Content-Type", "text/xml;charset=ISO-8859-1");
55 client = HttpClients.createDefault();
56 response = client.execute(httpPost);
57 if(response != null && response.getEntity() != null){
58 Map<String,String> resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
59 res = XmlUtils.toXml(resultMap);
60 System.out.println("請求結果:" + res);
61
62 if(resultMap.containsKey("sign")){
63 if(!SignUtils.checkParam(resultMap, SwiftpassConfig.key)){
64 res = "驗證簽名不通過";
65 }else{
66 if("0".equals(resultMap.get("status")) && "0".equals(resultMap.get("result_code"))){
67 if(orderResult == null){
68 orderResult = new HashMap<String,String>();
69 }
70 orderResult.put(map.get("out_trade_no"), "0");//初始狀态
72 String pay_info = resultMap.get("pay_info");
75 resp.sendRedirect(pay_info); //這裡直接挑轉到微信支付的頁面
81 }else{
82 req.setAttribute("result", res);
83 }
84 }
85 }
86 }else{
87 res = "操作失敗";
88 }
89 } catch (Exception e) {
90 e.printStackTrace();
91 res = "系統異常";
92 } finally {
93 if(response != null){
94 response.close();
95 }
96 if(client != null){
97 client.close();
98 }
99 }
100 if(res.startsWith("<")){
101 resp.setHeader("Content-type", "text/xml;charset=UTF-8");
102 }else{
103 resp.setHeader("Content-type", "text/html;charset=UTF-8");
104 }
105 resp.getWriter().write(res);
106 return res;
107 //}
108 }
109
注 :1.因為是用于測試,是以目前把所有參數都是寫死的。這樣根據以上代碼就可以完成支付了,給自己開發的時候就要換上自己的key和商戶号這些參數了
2. notify_url這個參數必須要傳給一個可以在公網上接收到的接口中、可以是接口、可以是方法(我本地用的是nat123 -- 友善開發測試、這個工具把本地的端口映射到公網、然後在支付的時候配置的接收通知的接口);下篇将講述接受通知的方法。