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

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

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

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

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

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

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

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

引言

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

支付流程

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

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

app查詢:調(diào)起“查詢訂單”

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

app退款查詢:調(diào)起“查詢退款”

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

支付代碼實現(xiàn)

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

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

支付代碼

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

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)建失敗:" + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
 }
 webutil.response(response, webutil.packjsonp(callback, json
 .tojsonstring(new jsonresult(-1, "訂單獲取失敗", new responsedata()), serializerfeatureutil.features)));
 }
 }
 
 
 /**
 * 查詢支付結(jié)果
 *
 * @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è)務(wù)邏輯
 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)));
 }
 }
 
 
 /**
 * 訂單支付微信服務(wù)器異步通知
 *
 * @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("支付結(jié)果通知:" + restmap);
 if ("success".equals(restmap.get("result_code"))) {
 // 訂單支付成功 業(yè)務(wù)處理
 string out_trade_no = restmap.get("out_trade_no"); // 商戶訂單號
 // 通過商戶訂單判斷是否該訂單已經(jīng)處理 如果處理跳過 如果未處理先校驗sign簽名 再進(jìn)行訂單業(yè)務(wù)相關(guān)的處理
 
 string sing = restmap.get("sign"); // 返回的簽名
 restmap.remove("sign");
 string signnow = payutil.getsign(restmap, api_secret);
 if (signnow.equals(sing)) {
 // 進(jìn)行業(yè)務(wù)處理
 log.info("訂單支付通知: 支付成功,訂單號" + out_trade_no);
 
 // 處理成功后相應(yīng)給響應(yīng)xml
 map<string, string> respmap = new hashmap<>();
 respmap = new hashmap<string, string>();
 respmap.put("return_code", "success"); //相應(yīng)給微信服務(wù)器
 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è)務(wù)邏輯獲取
 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("訂單退款失敗:" + 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è)務(wù)邏輯
 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支付文檔。

微信支付工具類

包含簽名、訂單號、退單號、隨機串、服務(wù)器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();
 }
 
 /**
 * 獲取服務(wù)器的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();
 }
 
 /**
 * 構(gòu)造簽名
 *
 * @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);
 }
}

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

支付結(jié)果

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

app支付測試完成

源代碼地址:微信app支付

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产这里有精品 | 国产精品毛片va一区二区三区 | 黑人双渗透| 国产成人青草视频 | 日韩大片在线 | 日韩性大片免费 | bbbxxx乱大交欧美小说 | 四虎影音先锋 | 91肥熟国产老肥熟在线 | 国内自拍2019| 好逼365 | 体检小说 | www.男人的天堂| 关晓彤一级做a爰片性色毛片 | 男人女人插 | www.国产自拍 | 四虎影视在线影院在线观看观看 | 搡60一70岁的老女人小说 | 欧美国产日本精品一区二区三区 | 女人狂吮男人命根gif视频 | ass亚洲熟妇毛茸茸pics | 办公室里被迫高h | 国产激情一区二区三区四区 | 国产日韩欧美在线播放 | 高h辣h双处全是肉军婚 | 日韩天堂视频 | 免费看男女污污完整版 | 91久久偷偷做嫩草影院免费看 | 91.久久| 女教师系列三上悠亚在线观看 | 精品日韩一区二区三区 | 色一情一区二区三区四区 | 菠萝视频在线完整版 | 久久这里只有精品无码3D | 高h视频免费观看 | 天天操天天射天天爽 | 精品久久久久久午夜 | 久久全国免费观看视频 | 91精品手机国产在线观 | 14一15sexvideo日本| 四虎4hu新地址入口 四虎1515h永久 |