一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java實現(xiàn)微信App支付服務端

java實現(xiàn)微信App支付服務端

2021-06-02 14:18Andyzty Java教程

這篇文章主要為大家詳細介紹了java實現(xiàn)微信App支付服務端,具有一定的參考價值,感興趣的小伙伴們可以參考一下

微信app支付服務端的實現(xiàn)方法,供大家參考,具體內容如下

引言

主要實現(xiàn)app支付統(tǒng)一下單、異步通知、調起支付接口、支付訂單查詢、申請退款、查詢退款功能;封裝了https對發(fā)起退款的證書校驗、簽名、xml解析等。

支付流程

具體支付流程參考“微信app”文檔,文檔地址

app支付:app端點擊下單—-服務端生成訂單,并調起“統(tǒng)一下單”,返回app支付所需參數(shù)—–app端“調起支付接口“,發(fā)起支付—-微信服務器端調用服務端回調地址—–服務端按照“支付結果通知”,處理支付結果

app查詢:調起“查詢訂單”

app退款:發(fā)起退款請求,調用“申請退款”,發(fā)起退款,需雙向證書驗證

app退款查詢:調起“查詢退款”

java實現(xiàn)微信App支付服務端

支付代碼實現(xiàn)

代碼實現(xiàn)簽名、證書校驗、http和https封裝等,項目結構如下:

java實現(xiàn)微信App支付服務端

支付代碼

包含支付、支付查詢、異步通知、退款申請、退款查詢

java" id="highlighter_418350">
?
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
package org.andy.wxpay.controller;
 
import java.math.bigdecimal;
import java.util.hashmap;
import java.util.map;
 
import javax.servlet.servletinputstream;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
 
import org.andy.wxpay.model.jsonresult;
import org.andy.wxpay.model.responsedata;
import org.andy.wxpay.utils.collectionutil;
import org.andy.wxpay.utils.configutil;
import org.andy.wxpay.utils.fileutil;
import org.andy.wxpay.utils.httputils;
import org.andy.wxpay.utils.payutil;
import org.andy.wxpay.utils.serializerfeatureutil;
import org.andy.wxpay.utils.stringutil;
import org.andy.wxpay.utils.webutil;
import org.andy.wxpay.utils.xmlutil;
import org.apache.log4j.logger;
import org.springframework.stereotype.controller;
import org.springframework.web.bind.annotation.requestmapping;
import org.springframework.web.bind.annotation.requestmethod;
import org.springframework.web.bind.annotation.requestparam;
 
import com.alibaba.fastjson.json;
 
/**
 * 創(chuàng)建時間:2016年11月2日 下午4:16:32
 *
 * @author andy
 * @version 2.2
 */
@controller
@requestmapping("/order")
public class paycontroller {
 
 private static final logger log = logger.getlogger(paycontroller.class);
 
 private static final string order_pay = "https://api.mch.weixin.qq.com/pay/unifiedorder"; // 統(tǒng)一下單
 
 private static final string order_pay_query = "https://api.mch.weixin.qq.com/pay/orderquery"; // 支付訂單查詢
 
 private static final string order_refund = "https://api.mch.weixin.qq.com/secapi/pay/refund"; // 申請退款
 
 private static final string order_refund_query = "https://api.mch.weixin.qq.com/pay/refundquery"; // 申請退款
 
 private static final string app_id = configutil.getproperty("wx.appid");
 
 private static final string mch_id = configutil.getproperty("wx.mchid");
 
 private static final string api_secret = configutil.getproperty("wx.api.secret");
 
 /**
 * 支付下訂單
 *
 * @param request
 * @param response
 * @param cashnum
 * 支付金額
 * @param mercid
 * 商品id
 * @param callback
 */
 @requestmapping(value = "/pay", method = requestmethod.post)
 public void orderpay(httpservletrequest request, httpservletresponse response,
 @requestparam(required = false, defaultvalue = "0") double cashnum, string mercid, string callback) {
 log.info("[/order/pay]");
 if (!"001".equals(mercid)) {
 webutil.response(response, webutil.packjsonp(callback, json
 .tojsonstring(new jsonresult(-1, "商品不存在", new responsedata()), serializerfeatureutil.features)));
 }
 
 map<string, string> restmap = null;
 boolean flag = true; // 是否訂單創(chuàng)建成功
 try {
 string total_fee = bigdecimal.valueof(cashnum).multiply(bigdecimal.valueof(100))
 .setscale(0, bigdecimal.round_half_up).tostring();
 map<string, string> parm = new hashmap<string, string>();
 parm.put("appid", app_id);
 parm.put("mch_id", mch_id);
 parm.put("device_info", "web");
 parm.put("nonce_str", payutil.getnoncestr());
 parm.put("body", "測試付費");
 parm.put("attach", "andy");
 parm.put("out_trade_no", payutil.gettradeno());
 parm.put("total_fee", total_fee);
 parm.put("spbill_create_ip", payutil.getremoteaddrip(request));
 parm.put("notify_url", "https://www.andy.org/wxpay/order/pay/notify.shtml");
 parm.put("trade_type", "app");
 parm.put("sign", payutil.getsign(parm, api_secret));
 
 string restxml = httputils.post(order_pay, xmlutil.xmlformat(parm, false));
 restmap = xmlutil.xmlparse(restxml);
 } catch (exception e) {
 log.error(e.getmessage(), e);
 }
 
 map<string, string> paymap = new hashmap<string, string>();
 if (collectionutil.isnotempty(restmap) && "success".equals(restmap.get("result_code"))) {
 paymap.put("appid", app_id);
 paymap.put("partnerid", mch_id);
 paymap.put("prepayid", restmap.get("prepay_id"));
 paymap.put("package", "sign=wxpay");
 paymap.put("noncestr", payutil.getnoncestr());
 paymap.put("timestamp", payutil.paytimestamp());
 try {
 paymap.put("sign", payutil.getsign(paymap, api_secret));
 } catch (exception e) {
 flag = false;
 }
 }
 
 if (flag) {
 webutil.response(response,
 webutil.packjsonp(callback,
 json.tojsonstring(new jsonresult(1, "訂單獲取成功", new responsedata(null, paymap)),
  serializerfeatureutil.features)));
 } else {
 if (collectionutil.isnotempty(restmap)) {
 log.info("訂單創(chuàng)建失?。?quot; + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
 }
 webutil.response(response, webutil.packjsonp(callback, json
 .tojsonstring(new jsonresult(-1, "訂單獲取失敗", new responsedata()), serializerfeatureutil.features)));
 }
 }
 
 
 /**
 * 查詢支付結果
 *
 * @param request
 * @param response
 * @param tradeid 微信交易訂單號
 * @param tradeno 商品訂單號
 * @param callback
 */
 @requestmapping(value = "/pay/query", method = requestmethod.post)
 public void orderpayquery(httpservletrequest request, httpservletresponse response, string tradeid, string tradeno,
 string callback) {
 log.info("[/order/pay/query]");
 if (stringutil.isempty(tradeno) && stringutil.isempty(tradeid)) {
 webutil.response(response, webutil.packjsonp(callback, json
 .tojsonstring(new jsonresult(-1, "訂單號不能為空", new responsedata()), serializerfeatureutil.features)));
 }
 
 map<string, string> restmap = null;
 try {
 map<string, string> parm = new hashmap<string, string>();
 parm.put("appid", app_id);
 parm.put("mch_id", mch_id);
 parm.put("transaction_id", tradeid);
 parm.put("out_trade_no", tradeno);
 parm.put("nonce_str", payutil.getnoncestr());
 parm.put("sign", payutil.getsign(parm, api_secret));
 
 string restxml = httputils.post(order_pay_query, xmlutil.xmlformat(parm, false));
 restmap = xmlutil.xmlparse(restxml);
 } catch (exception e) {
 log.error(e.getmessage(), e);
 }
 
 if (collectionutil.isnotempty(restmap) && "success".equals(restmap.get("result_code"))) {
 // 訂單查詢成功 處理業(yè)務邏輯
 log.info("訂單查詢:訂單" + restmap.get("out_trade_no") + "支付成功");
 webutil.response(response, webutil.packjsonp(callback, json
 .tojsonstring(new jsonresult(1, "訂單支付成功", new responsedata()), serializerfeatureutil.features)));
 } else {
 if (collectionutil.isnotempty(restmap)) {
 log.info("訂單支付失敗:" + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
 }
 webutil.response(response, webutil.packjsonp(callback, json
 .tojsonstring(new jsonresult(-1, "訂單支付失敗", new responsedata()), serializerfeatureutil.features)));
 }
 }
 
 
 /**
 * 訂單支付微信服務器異步通知
 *
 * @param request
 * @param response
 */
 @requestmapping("/pay/notify")
 public void orderpaynotify(httpservletrequest request, httpservletresponse response) {
 log.info("[/order/pay/notify]");
 response.setcharacterencoding("utf-8");
 response.setcontenttype("text/xml");
 try {
 servletinputstream in = request.getinputstream();
 string resxml = fileutil.readinputstream2string(in);
 map<string, string> restmap = xmlutil.xmlparse(resxml);
 log.info("支付結果通知:" + restmap);
 if ("success".equals(restmap.get("result_code"))) {
 // 訂單支付成功 業(yè)務處理
 string out_trade_no = restmap.get("out_trade_no"); // 商戶訂單號
 // 通過商戶訂單判斷是否該訂單已經(jīng)處理 如果處理跳過 如果未處理先校驗sign簽名 再進行訂單業(yè)務相關的處理
 
 string sing = restmap.get("sign"); // 返回的簽名
 restmap.remove("sign");
 string signnow = payutil.getsign(restmap, api_secret);
 if (signnow.equals(sing)) {
 // 進行業(yè)務處理
 log.info("訂單支付通知: 支付成功,訂單號" + out_trade_no);
 
 // 處理成功后相應給響應xml
 map<string, string> respmap = new hashmap<>();
 respmap = new hashmap<string, string>();
 respmap.put("return_code", "success"); //相應給微信服務器
 respmap.put("return_msg", "ok");
 string resxml = xmlutil.xmlformat(restmap, true);
 response.getwriter().write(resxml);
 } else {
 log.info("訂單支付通知:簽名錯誤");
 }
 } else {
 log.info("訂單支付通知:支付失敗," + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
 }
 } catch (exception e) {
 log.error(e.getmessage(), e);
 }
 }
 
 /**
 * 訂單退款 需要雙向證書驗證
 *
 * @param request
 * @param response
 * @param tradeno 微信訂單號
 * @param orderno 商家訂單號
 * @param callback
 */
 @requestmapping(value = "/pay/refund", method = requestmethod.post)
 public void orderpayrefund(httpservletrequest request, httpservletresponse response, string tradeno, string orderno,
 string callback) {
 log.info("[/pay/refund]");
 if (stringutil.isempty(tradeno) && stringutil.isempty(orderno)) {
 webutil.response(response, webutil.packjsonp(callback, json
 .tojsonstring(new jsonresult(-1, "訂單號不能為空", new responsedata()), serializerfeatureutil.features)));
 }
 
 map<string, string> restmap = null;
 try {
 map<string, string> parm = new hashmap<string, string>();
 parm.put("appid", app_id);
 parm.put("mch_id", mch_id);
 parm.put("nonce_str", payutil.getnoncestr());
 parm.put("transaction_id", tradeno);
 parm.put("out_trade_no", orderno);//訂單號
 parm.put("out_refund_no", payutil.getrefundno()); //退款單號
 parm.put("total_fee", "10"); // 訂單總金額 從業(yè)務邏輯獲取
 parm.put("refund_fee", "10"); // 退款金額
 parm.put("op_user_id", mch_id);
 parm.put("refund_account", "refund_source_recharge_funds");//退款方式
 parm.put("sign", payutil.getsign(parm, api_secret));
 
 //string restxml = httputils.posts(order_refund, xmlutil.xmlformat(parm, false));
 string restxml = httputils.posts(order_refund, xmlutil.xmlformat(parm, false));
 restmap = xmlutil.xmlparse(restxml);
 } catch (exception e) {
 log.error(e.getmessage(), e);
 }
 
 map<string, string> refundmap = new hashmap<>();
 if (collectionutil.isnotempty(restmap) && "success".equals(restmap.get("result_code"))) {
 refundmap.put("transaction_id", restmap.get("transaction_id"));
 refundmap.put("out_trade_no", restmap.get("out_trade_no"));
 refundmap.put("refund_id", restmap.get("refund_id"));
 refundmap.put("out_refund_no", restmap.get("out_refund_no"));
 log.info("訂單退款:訂單" + restmap.get("out_trade_no") + "退款成功,商戶退款單號" + restmap.get("out_refund_no") + ",微信退款單號"
 + restmap.get("refund_id"));
 webutil.response(response,
 webutil.packjsonp(callback,
 json.tojsonstring(new jsonresult(1, "訂單獲取成功", new responsedata(null, refundmap)),
  serializerfeatureutil.features)));
 } else {
 if (collectionutil.isnotempty(restmap)) {
 log.info("訂單退款失?。?quot; + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
 }
 webutil.response(response, webutil.packjsonp(callback, json
 .tojsonstring(new jsonresult(-1, "訂單退款失敗", new responsedata()), serializerfeatureutil.features)));
 }
 }
 
 /**
 * 訂單退款查詢
 * @param request
 * @param response
 * @param tradeid 微信訂單號
 * @param tradeno 商戶訂單號
 * @param refundid 微信退款號
 * @param refundno 商家退款號
 * @param callback
 */
 @requestmapping(value = "/pay/refund/query", method = requestmethod.post)
 public void orderpayrefundquery(httpservletrequest request, httpservletresponse response, string refundid,
 string refundno, string tradeid, string tradeno, string callback) {
 log.info("[/pay/refund/query]");
 if (stringutil.isempty(tradeid) && stringutil.isempty(tradeno)
 && stringutil.isempty(refundno) && stringutil.isempty(refundid)) {
 webutil.response(response, webutil.packjsonp(callback, json
 .tojsonstring(new jsonresult(-1, "退單號或訂單號不能為空", new responsedata()), serializerfeatureutil.features)));
 }
 
 map<string, string> restmap = null;
 try {
 map<string, string> parm = new hashmap<string, string>();
 parm.put("appid", app_id);
 parm.put("mch_id", mch_id);
 parm.put("transaction_id", tradeid);
 parm.put("out_trade_no", tradeno);
 parm.put("refund_id", refundid);
 parm.put("out_refund_no", refundno);
 parm.put("nonce_str", payutil.getnoncestr());
 parm.put("sign", payutil.getsign(parm, api_secret));
 
 string restxml = httputils.post(order_refund_query, xmlutil.xmlformat(parm, false));
 restmap = xmlutil.xmlparse(restxml);
 } catch (exception e) {
 log.error(e.getmessage(), e);
 }
 
 map<string, string> refundmap = new hashmap<>();
 if (collectionutil.isnotempty(restmap) && "success".equals(restmap.get("result_code")) && "success".equals(restmap.get("result_code"))) {
 // 訂單退款查詢成功 處理業(yè)務邏輯
 log.info("退款訂單查詢:訂單" + restmap.get("out_trade_no") + "退款成功,退款狀態(tài)"+ restmap.get("refund_status_0"));
 refundmap.put("transaction_id", restmap.get("transaction_id"));
 refundmap.put("out_trade_no", restmap.get("out_trade_no"));
 refundmap.put("refund_id", restmap.get("refund_id_0"));
 refundmap.put("refund_no", restmap.get("out_refund_no_0"));
 refundmap.put("refund_status", restmap.get("refund_status_0"));
 webutil.response(response, webutil.packjsonp(callback, json
 .tojsonstring(new jsonresult(1, "訂單退款成功", new responsedata(null, refundmap)), serializerfeatureutil.features)));
 } else {
 if (collectionutil.isnotempty(restmap)) {
 log.info("訂單退款失敗:" + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
 }
 webutil.response(response, webutil.packjsonp(callback, json
 .tojsonstring(new jsonresult(-1, "訂單退款失敗", new responsedata()), serializerfeatureutil.features)));
 }
 }
 
}

微信支付接口參數(shù)含義具體參考微信app支付文檔。

微信支付工具類

包含簽名、訂單號、退單號、隨機串、服務器ip地址、客戶端ip地址等方法。

 

?
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package org.andy.wxpay.utils;
 
import java.io.unsupportedencodingexception;
import java.net.urlencoder;
import java.util.arrays;
import java.util.date;
import java.util.map;
import java.util.set;
 
import javax.servlet.http.httpservletrequest;
 
/**
 * 創(chuàng)建時間:2016年11月2日 下午7:12:44
 *
 * @author andy
 * @version 2.2
 */
 
public class payutil {
 
 /**
 * 生成訂單號
 *
 * @return
 */
 public static string gettradeno() {
 // 自增8位數(shù) 00000001
 return "tno" + datetimeutil.formatdate(new date(), datetimeutil.time_stamp_pattern) + "00000001";
 }
 
 /**
 * 退款單號
 *
 * @return
 */
 public static string getrefundno() {
 // 自增8位數(shù) 00000001
 return "rno" + datetimeutil.formatdate(new date(), datetimeutil.time_stamp_pattern) + "00000001";
 }
 
 /**
 * 退款單號
 *
 * @return
 */
 public static string gettransferno() {
 // 自增8位數(shù) 00000001
 return "tno" + datetimeutil.formatdate(new date(), datetimeutil.time_stamp_pattern) + "00000001";
 }
 
 /**
 * 返回客戶端ip
 *
 * @param request
 * @return
 */
 public static string getremoteaddrip(httpservletrequest request) {
 string ip = request.getheader("x-forwarded-for");
 if (stringutil.isnotempty(ip) && !"unknown".equalsignorecase(ip)) {
 // 多次反向代理后會有多個ip值,第一個ip才是真實ip
 int index = ip.indexof(",");
 if (index != -1) {
 return ip.substring(0, index);
 } else {
 return ip;
 }
 }
 ip = request.getheader("x-real-ip");
 if (stringutil.isnotempty(ip) && !"unknown".equalsignorecase(ip)) {
 return ip;
 }
 return request.getremoteaddr();
 }
 
 /**
 * 獲取服務器的ip地址
 *
 * @param request
 * @return
 */
 public static string getlocalip(httpservletrequest request) {
 return request.getlocaladdr();
 }
 
 public static string getsign(map<string, string> params, string paternerkey) throws unsupportedencodingexception {
 return md5utils.getmd5(createsign(params, false) + "&key=" + paternerkey).touppercase();
 }
 
 /**
 * 構造簽名
 *
 * @param params
 * @param encode
 * @return
 * @throws unsupportedencodingexception
 */
 public static string createsign(map<string, string> params, boolean encode) throws unsupportedencodingexception {
 set<string> keysset = params.keyset();
 object[] keys = keysset.toarray();
 arrays.sort(keys);
 stringbuffer temp = new stringbuffer();
 boolean first = true;
 for (object key : keys) {
 if (key == null || stringutil.isempty(params.get(key))) // 參數(shù)為空不參與簽名
 continue;
 if (first) {
 first = false;
 } else {
 temp.append("&");
 }
 temp.append(key).append("=");
 object value = params.get(key);
 string valuestr = "";
 if (null != value) {
 valuestr = value.tostring();
 }
 if (encode) {
 temp.append(urlencoder.encode(valuestr, "utf-8"));
 } else {
 temp.append(valuestr);
 }
 }
 return temp.tostring();
 }
 
 /**
 * 創(chuàng)建支付隨機字符串
 * @return
 */
 public static string getnoncestr(){
 return randomutil.randomstring(randomutil.letter_number_char, 32);
 }
 
 /**
 * 支付時間戳
 * @return
 */
 public static string paytimestamp() {
 return long.tostring(system.currenttimemillis() / 1000);
 }
}

其他所需工具類參考項目源碼

支付結果

java實現(xiàn)微信App支付服務端

app支付測試完成

源代碼地址:微信app支付

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/fengshizty/article/details/53199356

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 羞羞视频麻豆 | 国产一卡二卡3卡4卡四卡在线视频 | 亚洲国产在线午夜视频无 | 日韩在线观看一区二区不卡视频 | 无人区乱码1区2区3区网站 | 欧美一级特黄刺激大片视频 | 久久人妻少妇嫩草AV无码 | 亚洲国产成人久久综合区 | 美女脱了内裤打开腿让你桶爽 | 性做久久久久久 | 免费一级特黄特色大片 | 免费理伦片高清在线 | 色狠狠婷婷97 | 午夜国产理论 | 猫影视tv接口| 久久久久免费视频 | 成人免费高清视频 | 四虎影视紧急入口地址大全 | 日韩在线视频一区二区三区 | a∨79成人网| 视频在线观看入口一二三2021 | 97精品久久天干天天蜜 | 亚洲欧美久久婷婷爱综合一区天堂 | 91视频完整版 | 91私密保健女子养生spa | 特级非洲黑人一级毛片 | 亚洲成人一区在线 | 婷婷久久精品 | 黑人粗又长 | 午夜亚洲WWW湿好大 午夜想想爱 | 青青国产成人久久激情91麻豆 | 成人精品一区二区三区中文字幕 | 国产清纯女高中生在线观看 | 欧美日韩人成在线观看 | 69日本xxxx| 我在厨房摸岳的乳HD在线观看 | 黑人巨| 天天舔天天操天天干 | 四虎精品影视 | 免费一级日本c片完整版 | 香蕉国产精品偷在线播放 |