日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java后端对接微信支付(微信公众号、PC端扫码)

發布時間:2023/12/29 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java后端对接微信支付(微信公众号、PC端扫码) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

微信流程圖

項目結構

前期準備

復制證書

將證書中名為apiclient_key.pem的文件復制到你的項目中

依賴

<!-- 微信支付SDK--> <dependency><groupId>com.github.wechatpay-apiv3</groupId><artifactId>wechatpay-apache-httpclient</artifactId><version>0.3.0</version> </dependency>

properties文件(yaml也可以自己換一下)

# 微信支付相關參數 # 下面兩個用來標識用戶 # 商戶號 wxpay.mch-id= ****************** # APPID wxpay.appid= ****************** # 接下來兩個用來確保SSL(內容未作任何加密,只做了簽名.) # 商戶API證書序列號 wxpay.mch-serial-no= ******************# 商戶私鑰文件(第一步) wxpay.private-key-path= apiclient_key.pem # APIv3密鑰(在微信支付回調通知和商戶獲取平臺證書使用APIv3密鑰) wxpay.api-v3-key= ******************# 接下來兩個是相關地址 # 微信服務器地址 wxpay.domain= https://api.mch.weixin.qq.com # 接收結果通知地址 # 注意:每次重新啟動ngrok,都需要根據實際情況修改這個配置 wxpay.notify-domain= 填自己的回調地址

寫配置文件WxPayConfig(建議新建一個config文件夾存放配置文件)

package com.leng.paymentdemo.config;import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder; import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner; import com.wechat.pay.contrib.apache.httpclient.auth.ScheduledUpdateCertificatesVerifier; import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials; import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator; import com.wechat.pay.contrib.apache.httpclient.util.PemUtil; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.http.impl.client.CloseableHttpClient; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource;import java.io.FileInputStream; import java.io.FileNotFoundException; import java.nio.charset.StandardCharsets; import java.security.PrivateKey;/*** 微信支付信息配置* @author Admin*/ @Configuration @PropertySource("classpath:wxpay.properties") //讀取配置文件 @ConfigurationProperties(prefix="wxpay") //讀取wxpay節點 @Data //使用set方法將wxpay節點中的值填充到當前類的屬性中 @Slf4j public class WxPayConfig {// 商戶號private String mchId;// 商戶API證書序列號private String mchSerialNo;// 商戶私鑰文件private String privateKeyPath;// APIv3密鑰private String apiV3Key;// APPIDprivate String appid;// 微信服務器地址private String domain;// 接收結果通知地址private String notifyDomain;//商戶APIv2 keyprivate String partnerKey;/*** 獲取商戶的私鑰文件* @param filename* @return*/public PrivateKey getPrivateKey(String filename){try {return PemUtil.loadPrivateKey(new FileInputStream(filename));} catch (FileNotFoundException e) {throw new RuntimeException("私鑰文件不存在",e);}}/*** 獲取簽名驗證器* @return*/@Beanpublic ScheduledUpdateCertificatesVerifier getVerifier(){log.info("獲取簽名驗證器");//獲取商戶私鑰PrivateKey privateKey = getPrivateKey(privateKeyPath);//私鑰簽名對象PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, privateKey);//身份認證對象WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(mchId, privateKeySigner);// 使用定時更新的簽名驗證器,不需要傳入證書ScheduledUpdateCertificatesVerifier verifier = new ScheduledUpdateCertificatesVerifier(wechatPay2Credentials,apiV3Key.getBytes(StandardCharsets.UTF_8));return verifier;}/*** 獲取http請求對象* @param verifier* @return*/@Bean(name = "wxPayClient")public CloseableHttpClient getWxPayClient(ScheduledUpdateCertificatesVerifier verifier){log.info("獲取httpClient");//獲取商戶私鑰PrivateKey privateKey = getPrivateKey(privateKeyPath);WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create().withMerchant(mchId, mchSerialNo, privateKey).withValidator(new WechatPay2Validator(verifier));// ... 接下來,你仍然可以通過builder設置各種參數,來配置你的HttpClient// 通過WechatPayHttpClientBuilder構造的HttpClient,會自動的處理簽名和驗簽,并進行證書自動更新CloseableHttpClient httpClient = builder.build();return httpClient;}}

自定義統一返回結果(建議創建一個response存放)

CustomizeResultCode

package com.leng.paymentdemo.response;public interface CustomizeResultCode {/*** 獲取錯誤代碼* @return 錯誤狀態碼*/Integer getCode();/*** 獲取錯誤信息* @return 錯誤信息*/String getMessage(); }

Result

package com.leng.paymentdemo.response;import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.experimental.Accessors;import java.util.HashMap; import java.util.Map;/*** 自定義的統一返回結果類*/ @Data @Accessors(chain = true) //允許當前類進行鏈式操作 public class Result {@ApiModelProperty(value = "是否成功")private Boolean success;@ApiModelProperty(value = "返回碼")private Integer code;@ApiModelProperty(value = "返回消息")private String message;@ApiModelProperty(value = "返回數據")private Map<String, Object> data = new HashMap<>();/*** 構造方法私有化,里面的方法都是靜態方法* 達到保護屬性的作用*/private Result(){}/*** 這里是使用鏈式編程* @return 返回訪問成功后的結果集*/public static Result ok(){Result result=new Result();result.setSuccess(true);result.setCode(ResultCode.SUCCESS.getCode());result.setMessage(ResultCode.SUCCESS.getMessage());return result;}/*** 失敗* @return*/public static Result error(){Result result=new Result();result.setSuccess(false);result.setCode(ResultCode.COMMON_FAIL.getCode());result.setMessage(ResultCode.COMMON_FAIL.getMessage());return result;}/*** 根基錯誤類型返回* @param resultCoe* @return*/public static Result error(ResultCode resultCoe){Result result=new Result();result.setSuccess(false);result.setCode(resultCoe.getCode());result.setMessage(resultCoe.getMessage());return result;}public Result success(Boolean success){this.setSuccess(success);return this;}public Result message(String message){this.setMessage(message);return this;}public Result code(Integer code){this.setCode(code);return this;}public Result data(String key,Object value){this.data.put(key,value);return this;} }

ResultCode

package com.leng.paymentdemo.response; /*** @Author:* @Description: 返回碼定義* 規定:* #200表示成功* #1001~1999 區間表示參數錯誤* #2001~2999 區間表示用戶錯誤* #3001~3999 區間表示接口異常* #后面對什么的操作自己在這里注明就行了*/ public enum ResultCode implements CustomizeResultCode {/* 成功 */SUCCESS(200,"成功"),/* 默認失敗 */COMMON_FAIL(999,"失敗"),/* 參數錯誤:1000~1999 */PARAM_NOT_VALID(1001,"參數無效"),PARAM_IS_BLANK(1002,"參數無效"),PARAM_TYPE_ERROR(1003,"參數類型錯誤"),PARAM_NOT_COMPLETE(1004,"參數缺失"),/* 用戶錯誤 */USER_NOT_LOGIN(2001,"用戶未登錄"),USER_ACCOUNT_EXPIRED(2002,"賬戶已過期"),USER_CREDENTIALS_ERROR(2003,"密碼錯誤"),USER_CREDENTIALS_EXPIRED(2004,"密碼過期"),USER_ACCOUNT_DISABLE(2005,"賬戶不可用"),USER_ACCOUNT_LOCKED(2006,"賬戶被鎖定"),USER_ACCOUNT_NOT_EXIST(2007,"賬戶不存在"),USER_ACCOUNT_ALREADY_EXIST(2008,"賬戶已存在"),USER_ACCOUNT_USE_BY_OTHERS(2009,"賬戶下線"),/* 部門錯誤 */DEPARTMENT_NOT_EXIST(3007,"部門不存在"),DEPARTMENT_ALREADY_EXIST(3008,"部門已存在"),/* 業務錯誤 */NO_PERMISSION(3001,"沒有權限"),BUCKET_IS_EXISTS(3002,"bucket已經存在了"),/* 算數異常 */ARITHMETIC_EXCEPTION(9001,"算數異常"),NULL_POINTER_EXCEPTION(9002,"空指針異常");private Integer code;private String message;ResultCode(Integer code,String message){this.code=code;this.message=message;}@Overridepublic Integer getCode() {return code;}@Overridepublic String getMessage() {return message;} }

定義一個全局異常處理器(exception)

BusinessException

package com.leng.paymentdemo.exception;import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;@Data @AllArgsConstructor @NoArgsConstructor public class BusinessException extends RuntimeException{@ApiModelProperty(value = "狀態碼")private Integer code;@ApiModelProperty(value = "錯誤信息")private String errMsg;}

GlobalExceptionHandler

package com.leng.paymentdemo.exception;import com.leng.paymentdemo.response.Result; import com.leng.paymentdemo.response.ResultCode; import lombok.extern.slf4j.Slf4j; import org.springframework.context.support.DefaultMessageSourceResolvable; import org.springframework.http.HttpStatus; import org.springframework.validation.BindException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import java.util.stream.Collectors;/***@作者: 冷俊杰*@類名: GlobalExceptionHandler類*@創建時間: 2022/8/22 14:21*@描述:*全局異常處理器,它只會處理controller層的異常*@修改原圖*@修改作者*@修改時間*/ @Slf4j @ControllerAdvice public class GlobalExceptionHandler {@ResponseBody@ExceptionHandler(value = ArithmeticException.class)public Result exception(ArithmeticException e) {System.out.println("出現了異常");return Result.error(ResultCode.ARITHMETIC_EXCEPTION);}@ResponseBody@ExceptionHandler(value = NullPointerException.class)public Result exception(NullPointerException e) {System.out.println("出現了異常");return Result.error(ResultCode.NULL_POINTER_EXCEPTION);}/* @ResponseBody@ExceptionHandler(value = BusinessException.class)public Result exception(BusinessException e) {System.out.println("出現了異常");return Result.error().code(e.getCode()).message(e.getErrMsg());}*/@ResponseBody@ExceptionHandler(value = Exception.class)public Result exception(Exception e) {e.printStackTrace();log.error("出現了異常"+e.getMessage()+"-----------");return Result.error();}//處理Get請求中 使用@Valid 驗證路徑中請求實體校驗失敗后拋出的異常@ExceptionHandler(BindException.class)@ResponseBodypublic Result BindExceptionHandler(BindException e) {String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());return Result.error().message(message);}//處理請求參數格式錯誤 @RequestParam上validate失敗后拋出的異常是javax.validation.ConstraintViolationException /* @ExceptionHandler(ConstraintViolationException.class)@ResponseBodypublic ResponseBean ConstraintViolationExceptionHandler(ConstraintViolationException e) {String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());return ResponseBean.error(message);}*///處理請求參數格式錯誤 @RequestBody上validate失敗后拋出的異常是MethodArgumentNotValidException異常。@ExceptionHandler(MethodArgumentNotValidException.class)@ResponseBodypublic Result MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());return Result.error().message(message);}/*** 處理servlet異常* @param req* @param e* @return*/@ExceptionHandler(value = ServletException.class)@ResponseBodypublic Result servletExceptionHandler(HttpServletRequest req, ServletException e){log.error("web服務器異常 {}",e.getMessage());return Result.error().message(e.getMessage());}/*** 處理自定義的業務異常* @param req* @param e* @return*/@ExceptionHandler(value = BusinessException.class)@ResponseBodypublic Result bizExceptionHandler(HttpServletRequest req, BusinessException e){log.error("業務異常=>{}",e.getMessage());return Result.error().code(e.getCode()).message(e.getErrMsg());}/*** shiro的異常* @param e* @return*/ /* @ExceptionHandler(ShiroException.class)public ResponseBean handle401(ShiroException e) {log.error("shiro異常=>{}",e.getMessage());return new ResponseBean(401, e.getMessage(), null);}*//*** 獲取狀態碼* @param request* @return*/private HttpStatus getStatus(HttpServletRequest request) {Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");if (statusCode == null) {return HttpStatus.INTERNAL_SERVER_ERROR;}return HttpStatus.valueOf(statusCode);} }

返回狀態碼(自定義)

OrderStatus類

package com.leng.paymentdemo.enums;import lombok.AllArgsConstructor; import lombok.Getter;@AllArgsConstructor @Getter public enum OrderStatus {/*** 未支付*/NOTPAY("未支付"),/*** 支付成功*/SUCCESS("支付成功"),/*** 已關閉*/CLOSED("超時已關閉"),/*** 已取消*/CANCEL("用戶已取消"),/*** 退款中*/REFUND_PROCESSING("退款中"),/*** 已退款*/REFUND_SUCCESS("已退款"),/*** 退款異常*/REFUND_ABNORMAL("退款異常");/*** 類型*/private final String type; }

PayType

package com.leng.paymentdemo.enums;import lombok.AllArgsConstructor; import lombok.Getter;@AllArgsConstructor @Getter public enum PayType {/*** 微信*/WXPAY("微信"),/*** 支付寶*/ALIPAY("支付寶");/*** 類型*/private final String type; }

WxApiType

package com.leng.paymentdemo.enums.wxpay;import lombok.AllArgsConstructor; import lombok.Getter;@AllArgsConstructor @Getter public enum WxApiType {/*** Native下單*/NATIVE_PAY("/v3/pay/transactions/native"),/*** Native下單*/NATIVE_PAY_V2("/pay/unifiedorder"),/*** 查詢訂單*/ORDER_QUERY_BY_NO("/v3/pay/transactions/out-trade-no/%s"),/*** 關閉訂單*/CLOSE_ORDER_BY_NO("/v3/pay/transactions/out-trade-no/%s/close"),/*** 申請退款*/DOMESTIC_REFUNDS("/v3/refund/domestic/refunds"),/*** 查詢單筆退款*/DOMESTIC_REFUNDS_QUERY("/v3/refund/domestic/refunds/%s"),/*** 申請交易賬單*/TRADE_BILLS("/v3/bill/tradebill"),/*** 申請資金賬單*/FUND_FLOW_BILLS("/v3/bill/fundflowbill");/*** 類型*/private final String type; }

WxNotifyType

package com.leng.paymentdemo.enums.wxpay;import lombok.AllArgsConstructor; import lombok.Getter;@AllArgsConstructor @Getter public enum WxNotifyType {/*** 支付通知*/NATIVE_NOTIFY("/api/wx-pay/native/notify"),/*** 支付通知*/NATIVE_NOTIFY_V2("/api/wx-pay-v2/native/notify"),/*** 退款結果通知*/REFUND_NOTIFY("/api/wx-pay/refunds/notify");/*** 類型*/private final String type; }

WxRefundStatus

package com.leng.paymentdemo.enums.wxpay;import lombok.AllArgsConstructor; import lombok.Getter;@AllArgsConstructor @Getter public enum WxRefundStatus {/*** 退款成功*/SUCCESS("SUCCESS"),/*** 退款關閉*/CLOSED("CLOSED"),/*** 退款處理中*/PROCESSING("PROCESSING"),/*** 退款異常*/ABNORMAL("ABNORMAL");/*** 類型*/private final String type; }

WxTradeState

package com.leng.paymentdemo.enums.wxpay;import lombok.AllArgsConstructor; import lombok.Getter;@AllArgsConstructor @Getter public enum WxTradeState {/*** 支付成功*/SUCCESS("SUCCESS"),/*** 未支付*/NOTPAY("NOTPAY"),/*** 已關閉*/CLOSED("CLOSED"),/*** 轉入退款*/REFUND("REFUND");/*** 類型*/private final String type; }

utils工具類

HttpClientUtils

package com.leng.paymentdemo.util;import org.apache.http.Consts; import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.*; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLContextBuilder; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils;import javax.net.ssl.SSLContext; import java.io.IOException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.text.ParseException; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map;/*** http請求客戶端*/ public class HttpClientUtils {private String url;private Map<String, String> param;private int statusCode;private String content;private String xmlParam;private boolean isHttps;public boolean isHttps() {return isHttps;}public void setHttps(boolean isHttps) {this.isHttps = isHttps;}public String getXmlParam() {return xmlParam;}public void setXmlParam(String xmlParam) {this.xmlParam = xmlParam;}public HttpClientUtils(String url, Map<String, String> param) {this.url = url;this.param = param;}public HttpClientUtils(String url) {this.url = url;}public void setParameter(Map<String, String> map) {param = map;}public void addParameter(String key, String value) {if (param == null)param = new HashMap<String, String>();param.put(key, value);}public void post() throws ClientProtocolException, IOException {HttpPost http = new HttpPost(url);setEntity(http);execute(http);}public void put() throws ClientProtocolException, IOException {HttpPut http = new HttpPut(url);setEntity(http);execute(http);}public void get() throws ClientProtocolException, IOException {if (param != null) {StringBuilder url = new StringBuilder(this.url);boolean isFirst = true;for (String key : param.keySet()) {if (isFirst) {url.append("?");isFirst = false;}else {url.append("&");}url.append(key).append("=").append(param.get(key));}this.url = url.toString();}HttpGet http = new HttpGet(url);execute(http);}/*** set http post,put param*/private void setEntity(HttpEntityEnclosingRequestBase http) {if (param != null) {List<NameValuePair> nvps = new LinkedList<NameValuePair>();for (String key : param.keySet())nvps.add(new BasicNameValuePair(key, param.get(key))); // 參數http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 設置參數}if (xmlParam != null) {http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));}}private void execute(HttpUriRequest http) throws ClientProtocolException,IOException {CloseableHttpClient httpClient = null;try {if (isHttps) {SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {// 信任所有public boolean isTrusted(X509Certificate[] chain,String authType)throws CertificateException {return true;}}).build();SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();} else {httpClient = HttpClients.createDefault();}CloseableHttpResponse response = httpClient.execute(http);try {if (response != null) {if (response.getStatusLine() != null)statusCode = response.getStatusLine().getStatusCode();HttpEntity entity = response.getEntity();// 響應內容content = EntityUtils.toString(entity, Consts.UTF_8);}} finally {response.close();}} catch (Exception e) {e.printStackTrace();} finally {httpClient.close();}}public int getStatusCode() {return statusCode;}public String getContent() throws ParseException, IOException {return content;}}

HttpUtils

package com.leng.paymentdemo.util;import javax.servlet.http.HttpServletRequest; import java.io.BufferedReader; import java.io.IOException;public class HttpUtils {/*** 將通知參數轉化為字符串* @param request* @return*/public static String readData(HttpServletRequest request) {BufferedReader br = null;try {StringBuilder result = new StringBuilder();br = request.getReader();for (String line; (line = br.readLine()) != null; ) {if (result.length() > 0) {result.append("\n");}result.append(line);}return result.toString();} catch (IOException e) {throw new RuntimeException(e);} finally {if (br != null) {try {br.close();} catch (IOException e) {e.printStackTrace();}}}} }

OrderNoUtils

package com.leng.paymentdemo.util;import java.text.SimpleDateFormat; import java.util.Date; import java.util.Random;/*** 訂單號工具類** @author qy* @since 1.0*/ public class OrderNoUtils {/*** 獲取訂單編號* @return*/public static String getOrderNo() {return "ORDER_" + getNo();}/*** 獲取退款單編號* @return*/public static String getRefundNo() {return "REFUND_" + getNo();}/*** 獲取編號* @return*/public static String getNo() {SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");String newDate = sdf.format(new Date());String result = "";Random random = new Random();for (int i = 0; i < 3; i++) {result += random.nextInt(10);}return newDate + result;}}

使用

創建支付

官方接口文檔可以參考微信支付-開發者文檔 (qq.com)

新建一個WxPayController類,用來實現對下單,退款等操作

Native下單方法

/*** Native下單* @param productId* @return* @throws Exception*/ @ApiOperation("調用統一下單API,生成支付二維碼") @PostMapping("native/{productId}") public Result nativePay(@PathVariable Long productId) throws Exception {log.info("發起支付請求 v3.....................");//通過map接受返回的支付二維碼鏈接和訂單號Map<String, Object> map = wxPayService.nativePay(productId);return Result.ok().setData(map); }

service層

/*** 創建訂單,調用Native支付接口*/ Map<String, Object> nativePay(Long productId) throws Exception;

service實現層

/*** 創建訂單,調用Native支付接口*/ @Transactional(rollbackFor = Exception.class) @Override public Map<String, Object> nativePay(Long productId) throws Exception {log.info("生成訂單");//生成訂單并存入數據庫OrderInfo orderInfo = orderInfoService.createOrderByProductId(productId);String code_url = orderInfo.getCodeUrl();if (orderInfo != null && !StringUtils.isEmpty(code_url)) {log.info("訂單已存在,二維碼以保存");//創建返回值HashMap<String, Object> map = new HashMap<>();map.put("codeUrl", code_url);map.put("orderNo", orderInfo.getOrderNo());return map;}log.info("調用統一下單API");//調用統一下單APIHttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.NATIVE_PAY.getType()));// 請求body參數Gson gson = new Gson();Map paramsMap = new HashMap<>();paramsMap.put("appid", wxPayConfig.getAppid());//應用IDparamsMap.put("mchid", wxPayConfig.getMchId());//直連商戶號paramsMap.put("description", orderInfo.getTitle());//商品描述paramsMap.put("out_trade_no", orderInfo.getOrderNo());//商戶訂單號paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType()));//通知地址HashMap<String, Object> amountMap = new HashMap<>();amountMap.put("total", orderInfo.getTotalFee());amountMap.put("currency", "CNY");paramsMap.put("amount", amountMap);//將參數轉換成字符串形式String jsonParams = gson.toJson(paramsMap);log.info("請求參數" + jsonParams);StringEntity entity = new StringEntity(jsonParams,"utf-8");entity.setContentType("application/json");httpPost.setEntity(entity);httpPost.setHeader("Accept", "application/json");//完成簽名并執行請求CloseableHttpResponse response = wxPayClient.execute(httpPost);try {//響應體String bodyAsString = EntityUtils.toString(response.getEntity());//響應狀態碼int statusCode = response.getStatusLine().getStatusCode();//處理成功if (statusCode == 200) {log.info("成功,返回結果y = " + bodyAsString);//處理成功,無返回Body} else if (statusCode == 204) {log.info("成功");} else {log.error("Native下單失敗,響應碼 = " + statusCode + ",返回結果 = " + bodyAsString);throw new IOException("request failed");}//響應結果Map<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);//二維碼code_url = resultMap.get("code_url");//保存二維碼String orderNo = orderInfo.getOrderNo();orderInfoService.saveCodeUrl(orderNo, code_url);//創建返回值:二維碼Map<String, Object> map = new HashMap<>();map.put("codeUrl", code_url);map.put("orderNo", orderInfo.getOrderNo());return map;} finally {//釋放資源response.close();} }

生成訂單并存入數據庫

servcie層

/*** 生成訂單并存入數據庫*/ OrderInfo createOrderByProductId(Long productId);

service實現層

/*** 生成訂單并存入數據庫*/ @Override public OrderInfo createOrderByProductId(Long productId) {//查詢已存在但是未支付的訂單OrderInfo orderInfo = this.getNoPayOrderByProductId(productId);if (orderInfo != null) {return orderInfo;}//獲取商品信息Product product = productMapper.selectById(productId);//生成訂單orderInfo = new OrderInfo();orderInfo.setTitle(product.getTitle());//訂單標題orderInfo.setOrderNo(OrderNoUtils.getOrderNo());//訂單號orderInfo.setProductId(productId);//支付產品idorderInfo.setTotalFee(product.getPrice());//商品金額,單位是分orderInfo.setOrderStatus(OrderStatus.NOTPAY.getType());//訂單狀態baseMapper.insert(orderInfo);return orderInfo; }

存儲訂單二維碼

servcie層

/*** 存儲訂單二維碼*/ void saveCodeUrl(String orderNo, String codeUrl);

servcie實現層

/*** 存儲訂單二維碼*/ @Override public void saveCodeUrl(String orderNo, String codeUrl) {QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<OrderInfo>();queryWrapper.eq("order_no", orderNo);OrderInfo orderInfo = new OrderInfo();orderInfo.setCodeUrl(codeUrl);baseMapper.update(orderInfo, queryWrapper); }

支付通知

官方接口文檔:微信支付-開發者文檔 (qq.com)

支付通知方法

/*** 支付通知* 微信支付通過支付通知接口將用戶支付成功消息通知給商戶*/ @PostMapping("/native/notify") public String nativeNotify(HttpServletRequest request, HttpServletResponse response) {Gson gson = new Gson();//應答對象HashMap<String, String> map = new HashMap<>();try {//處理通知參數String body = HttpUtils.readData(request);log.info("支付通知的參數 ===> {}", body);Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);String requestId = (String) bodyMap.get("id");log.info("支付通知的id ===> {}", requestId);//簽名的驗證WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(verifier, requestId, body);if (!wechatPay2ValidatorForRequest.validate(request)) {log.error("驗簽失敗");//失敗應答response.setStatus(500);map.put("code", "ERROR");map.put("message", "驗簽失敗");return gson.toJson(map);}log.info("驗簽成功");//處理訂單wxPayService.processOrder(bodyMap);//應答超時//模擬接收微信端的重復通知//TimeUnit.SECONDS.sleep(5);//成功應答response.setStatus(200);map.put("code", "SUCCESS");map.put("message", "成功");return gson.toJson(map);} catch (Exception e) {e.printStackTrace();//失敗應答response.setStatus(500);map.put("code", "ERROR");map.put("message", "失敗");return gson.toJson(map);} }

處理訂單

service層

/*** 處理訂單*/ void processOrder(Map<String, Object> bodyMap) throws GeneralSecurityException;

service實現層

/*** 處理訂單*/ @Transactional(rollbackFor = Exception.class) @Override public void processOrder(Map<String, Object> bodyMap) throws GeneralSecurityException {log.info("處理訂單");//解密報文String plainText = decryptFromResource(bodyMap);//將明文轉換成mapGson gson = new Gson();HashMap hashMap = gson.fromJson(plainText, HashMap.class);String orderNo = (String) hashMap.get("out_trade_no");/*在對業務數據進行狀態檢查和處理之前,要采用數據鎖進行并發控制,以避免函數重入造成的數據混亂*///嘗試獲取鎖:// 成功獲取則立即返回true,獲取失敗則立即返回false。不必一直等待鎖的釋放if (lock.tryLock()) {try {//處理重復通知//保證接口調用的冪等性:無論接口被調用多少次,產生的結果是一致的String orderStatus = orderInfoService.getOrderStatus(orderNo);if (!OrderStatus.NOTPAY.getType().equals(orderStatus)) {return;}//更新訂單狀態orderInfoService.updateStatusByorderNo(orderNo, OrderStatus.SUCCESS);//記錄支付日志paymentInfoService.createPaymentInfo(plainText);} finally {//要主動釋放鎖lock.unlock();}} }

查詢訂單

官方接口文檔:微信支付-開發者文檔 (qq.com)

/*** 查詢訂單** @param orderNo* @return* @throws URISyntaxException* @throws IOException*/ @ApiOperation("查詢訂單:測試訂單狀態用") @GetMapping("query/{orderNo}") public Result queryOrder(@PathVariable String orderNo) throws Exception {log.info("查詢訂單");String result = wxPayService.queryOrder(orderNo);return Result.ok().setMessage("查詢成功").data("result", result); }

service層

/*** 查單接口調用*/ String queryOrder(String orderNo) throws Exception;

service實現層

/*** 根據訂單號查詢微信支付查單接口,核實訂單狀態* 如果訂單已支付,則更新商戶端訂單狀態,并記錄支付日志* 如果訂單未支付,則調用關單接口關閉訂單,并更新商戶端訂單狀態** @param orderNo*/ @Transactional(rollbackFor = Exception.class) @Override public void checkOrderStatus(String orderNo) throws Exception {log.warn("根據訂單號核實訂單狀態 ===> {}", orderNo);//調用微信支付查單接口String result = this.queryOrder(orderNo);Gson gson = new Gson();Map resultMap = gson.fromJson(result, HashMap.class);//獲取微信支付端的訂單狀態Object tradeState = resultMap.get("trade_state");//判斷訂單狀態if(WxTradeState.SUCCESS.getType().equals(tradeState)){log.warn("核實訂單已支付 ===> {}", orderNo);//如果確認訂單已支付則更新本地訂單狀態orderInfoService.updateStatusByorderNo(orderNo, OrderStatus.SUCCESS);//記錄支付日志paymentInfoService.createPaymentInfo(result);}if(WxTradeState.NOTPAY.getType().equals(tradeState)){log.warn("核實訂單未支付 ===> {}", orderNo);//如果訂單未支付,則調用關單接口this.closeOrder(orderNo);//更新本地訂單狀態orderInfoService.updateStatusByorderNo(orderNo, OrderStatus.CLOSED);} }

關單接口

/*** 關單接口的調用** @param orderNo*/ private void closeOrder(String orderNo) throws Exception {log.info("關單接口的調用,訂單號 ===> {}", orderNo);//創建遠程請求對象String url = String.format(WxApiType.CLOSE_ORDER_BY_NO.getType(), orderNo);url = wxPayConfig.getDomain().concat(url);HttpPost httpPost = new HttpPost(url);//組裝json請求體Gson gson = new Gson();Map<String, String> paramsMap = new HashMap<>();paramsMap.put("mchid", wxPayConfig.getMchId());String jsonParams = gson.toJson(paramsMap);log.info("請求參數 ===> {}", jsonParams);//將請求參數設置到請求對象中StringEntity entity = new StringEntity(jsonParams, "utf-8");entity.setContentType("application/json");httpPost.setEntity(entity);httpPost.setHeader("Accept", "application/json");//完成簽名并執行請求CloseableHttpResponse response = wxPayClient.execute(httpPost);try {int statusCode = response.getStatusLine().getStatusCode();//響應狀態碼if (statusCode == 200) { //處理成功log.info("成功200");} else if (statusCode == 204) { //處理成功,無返回Bodylog.info("成功204");} else {log.info("Native下單失敗,響應碼 = " + statusCode);throw new IOException("request failed");}} finally {response.close();} }

申請退款

/*** 申請退款*/@ApiOperation("申請退款")@PostMapping("/refunds/{orderNo}/{reason}")public Result refunds(@PathVariable String orderNo, @PathVariable String reason)throws Exception {log.info("申請退款");wxPayService.refund(orderNo, reason);return Result.ok();}

service層

/*** 退款*/ void refund(String orderNo, String reason) throws Exception;

service實現層

* 退款** @param orderNo* @param reason*/ @Transactional(rollbackFor = Exception.class) @Override public void refund(String orderNo, String reason) throws Exception {log.info("創建退款單記錄");//根據訂單編號創建退款單RefundInfo refundsInfo = refundsInfoService.createRefundByOrderNo(orderNo,reason);log.info("調用退款API");//調用統一下單APIString url =wxPayConfig.getDomain().concat(WxApiType.DOMESTIC_REFUNDS.getType());HttpPost httpPost = new HttpPost(url);// 請求body參數Gson gson = new Gson();Map paramsMap = new HashMap();paramsMap.put("out_trade_no", orderNo);//訂單編號paramsMap.put("out_refund_no", refundsInfo.getRefundNo());//退款單編號paramsMap.put("reason", reason);//退款原因paramsMap.put("notify_url",wxPayConfig.getNotifyDomain().concat(WxNotifyType.REFUND_NOTIFY.getType()));//退款通知地址Map amountMap = new HashMap();amountMap.put("refund", refundsInfo.getRefund());//退款金額amountMap.put("total", refundsInfo.getTotalFee());//原訂單金額amountMap.put("currency", "CNY");//退款幣種paramsMap.put("amount", amountMap);//將參數轉換成json字符串String jsonParams = gson.toJson(paramsMap);log.info("請求參數 ===> {}" + jsonParams);StringEntity entity = new StringEntity(jsonParams, "utf-8");entity.setContentType("application/json");//設置請求報文格式httpPost.setEntity(entity);//將請求報文放入請求對象httpPost.setHeader("Accept", "application/json");//設置響應報文格式//完成簽名并執行請求,并完成驗簽CloseableHttpResponse response = wxPayClient.execute(httpPost);try {//解析響應結果String bodyAsString = EntityUtils.toString(response.getEntity());int statusCode = response.getStatusLine().getStatusCode();if (statusCode == 200) {log.info("成功, 退款返回結果 = " + bodyAsString);} else if (statusCode == 204) {log.info("成功");} else {throw new RuntimeException("退款異常, 響應碼 = " + statusCode + ", 退款返回結果 = " + bodyAsString);}//更新訂單狀態orderInfoService.updateStatusByorderNo(orderNo,OrderStatus.REFUND_PROCESSING);//更新退款單refundsInfoService.updateRefund(bodyAsString);} finally {response.close();} }

創建退款訂單

service層

/*** 根據訂單號創建退款訂單*/ RefundInfo createRefundByOrderNo(String orderNo, String reason);

service實現層

/*** 根據訂單號創建退款訂單** @param orderNo* @param reason*/ @Override public RefundInfo createRefundByOrderNo(String orderNo, String reason) {//根據訂單號獲取訂單信息OrderInfo orderInfo = orderInfoService.getOrderByOrderNo(orderNo);//根據訂單號生成退款訂單RefundInfo refundInfo = new RefundInfo();refundInfo.setOrderNo(orderNo);//訂單編號refundInfo.setRefundNo(OrderNoUtils.getRefundNo());//退款單編號refundInfo.setTotalFee(orderInfo.getTotalFee());//原訂單金額(分)refundInfo.setRefund(orderInfo.getTotalFee());//退款金額(分)refundInfo.setReason(reason);//退款原因//保存退款訂單baseMapper.insert(refundInfo);return refundInfo; }

獲取訂單狀態

/*** 根據訂單號獲取訂單*/ OrderInfo getOrderByOrderNo(String orderNo); /*** 根據訂單號獲取訂單** @param orderNo*/ @Override public OrderInfo getOrderByOrderNo(String orderNo) {QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();queryWrapper.eq("order_no", orderNo);OrderInfo orderInfo = baseMapper.selectOne(queryWrapper);return orderInfo; }

根據退款單號核實退款單狀態

service層

/*** 根據退款單號核實退款單狀態*/ void checkRefundStatus(String refundNo) throws Exception;

service實現層

/*** 根據退款單號核實退款單狀態** @param refundNo*/ @Transactional(rollbackFor = Exception.class) @Override public void checkRefundStatus(String refundNo) throws Exception {log.warn("根據退款單號核實退款單狀態 ===> {}", refundNo);//調用查詢退款單接口String result = this.queryRefund(refundNo);//組裝json請求體字符串Gson gson = new Gson();Map<String, String> resultMap = gson.fromJson(result, HashMap.class);//獲取微信支付端退款狀態String status = resultMap.get("status");String orderNo = resultMap.get("out_trade_no");if (WxRefundStatus.SUCCESS.getType().equals(status)) {log.warn("核實訂單已退款成功 ===> {}", refundNo);//如果確認退款成功,則更新訂單狀態orderInfoService.updateStatusByorderNo(orderNo,OrderStatus.REFUND_SUCCESS);//更新退款單refundsInfoService.updateRefund(result);}if (WxRefundStatus.ABNORMAL.getType().equals(status)) {log.warn("核實訂單退款異常 ===> {}", refundNo);//如果確認退款成功,則更新訂單狀態orderInfoService.updateStatusByorderNo(orderNo,OrderStatus.REFUND_ABNORMAL);//更新退款單refundsInfoService.updateRefund(result);} }

更新退款狀態

service層

/*** 記錄退款記錄*/ void updateRefund(String content);

service實現層

/*** 記錄退款記錄** @param content*/ @Override public void updateRefund(String content) {//將json字符串轉換成MapGson gson = new Gson();Map<String, String> resultMap = gson.fromJson(content, HashMap.class);//根據退款單編號修改退款單QueryWrapper<RefundInfo> queryWrapper = new QueryWrapper<>();queryWrapper.eq("refund_no", resultMap.get("out_refund_no"));//設置要修改的字段RefundInfo refundInfo = new RefundInfo();refundInfo.setRefundId(resultMap.get("refund_id"));//微信支付退款單號//查詢退款和申請退款中的返回參數if(resultMap.get("status") != null){refundInfo.setRefundStatus(resultMap.get("status"));//退款狀態refundInfo.setContentReturn(content);//將全部響應結果存入數據庫的content字段}//退款回調中的回調參數if(resultMap.get("refund_status") != null){refundInfo.setRefundStatus(resultMap.get("refund_status"));//退款狀態refundInfo.setContentNotify(content);//將全部響應結果存入數據庫的content字段}//更新退款單baseMapper.update(refundInfo, queryWrapper); }

處理退款

service層

/*** 處理退款單*/ void processRefund(Map<String, Object> bodyMap) throws Exception;

service實現層

/*** 處理退款單** @param bodyMap*/ @Transactional(rollbackFor = Exception.class) @Override public void processRefund(Map<String, Object> bodyMap) throws Exception {log.info("退款單");//解密報文String plainText = decryptFromResource(bodyMap);//將明文轉換成mapGson gson = new Gson();HashMap plainTextMap = gson.fromJson(plainText, HashMap.class);String orderNo = (String) plainTextMap.get("out_trade_no");if (lock.tryLock()) {try {String orderStatus = orderInfoService.getOrderStatus(orderNo);if (!OrderStatus.REFUND_PROCESSING.getType().equals(orderStatus)) {return;}//更新訂單狀態orderInfoService.updateStatusByorderNo(orderNo,OrderStatus.REFUND_SUCCESS);//更新退款單refundsInfoService.updateRefund(plainText);} finally {//要主動釋放鎖lock.unlock();}} }

源碼

GitHub

Gitee

總結

以上是生活随笔為你收集整理的Java后端对接微信支付(微信公众号、PC端扫码)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

亚洲九九精品 | 91九色成人 | 天天操天天添天天吹 | 日韩精品久久中文字幕 | 国产美女视频 | 97超碰色偷偷 | 天天干天天操人体 | 激情五月开心 | 婷婷伊人综合亚洲综合网 | 91成版人在线观看入口 | 久久刺激视频 | 97人人超| 在线超碰av| 免费在线观看成年人视频 | 狠狠狠色丁香综合久久天下网 | 日本高清dvd| 日韩国产精品久久久久久亚洲 | 国产精品久久婷婷六月丁香 | 欧美久久久 | 欧美a√大片 | 久久免费毛片 | 免费亚洲一区二区 | 国产美女搞久久 | 久久一区二区三区超碰国产精品 | 国产午夜三级一区二区三桃花影视 | 欧美一区二区三区在线播放 | 亚洲国产天堂av | 亚洲一级电影在线观看 | av不卡网站 | 欧美乱码精品一区二区 | 中文字幕久久久精品 | 操操操操网 | 天堂网一区二区三区 | 一区二区视频免费在线观看 | 69av久久 | 亚洲精品一区中文字幕乱码 | 久久亚洲免费 | 国产黄色av| 五月激情六月丁香 | 亚洲精品字幕在线观看 | 亚洲成人av一区 | 91亚洲狠狠婷婷综合久久久 | 亚洲黄色免费网站 | 久久夜视频 | av亚洲产国偷v产偷v自拍小说 | 久久午夜国产 | 91免费高清视频 | 日韩在线大片 | 久久官网 | 97av在线视频 | 在线免费看黄网站 | 97精品国产97久久久久久春色 | 日日干天天干 | 久草在线视频资源 | 欧美91精品 | 成人四虎 | 在线观看精品黄av片免费 | 国产第一页在线观看 | 五月婷婷丁香 | 久久免费电影 | 91成人免费看 | 香蕉视频免费在线播放 | 色网站在线 | 欧美 日韩 国产 成人 在线 | 日韩欧美区 | 久久综合狠狠综合久久激情 | 欧美十八| 日韩视频区 | 日本中文字幕在线播放 | 欧美日韩亚洲第一页 | 久久在线视频在线 | 中文字幕在线观看不卡 | 麻豆国产露脸在线观看 | 国产+日韩欧美 | 欧美久久久久久久久久 | 国产成人一区二区在线观看 | 国产一区二区综合 | 亚洲免费在线观看视频 | 91在线观 | 成人黄色毛片 | 国产精品久久视频 | av网站在线观看播放 | 国产精品视频专区 | 香蕉影视在线观看 | 偷拍区另类综合在线 | 精品v亚洲v欧美v高清v | 日韩系列在线 | 全久久久久久久久久久电影 | 成人av一区二区兰花在线播放 | 亚洲欧美激情精品一区二区 | 亚州日韩中文字幕 | 天天爱av导航 | 色网址99| 久草免费看 | 久久亚洲欧美 | 免费看成人a | 激情久久久久久久久久久久久久久久 | 日本成人中文字幕在线观看 | 久久久久久蜜桃一区二区 | 亚洲国产欧美在线人成大黄瓜 | 开心丁香婷婷深爱五月 | 婷婷在线资源 | 又污又黄的网站 | 免费午夜av | 在线免费观看亚洲视频 | www.日本色 | 2017狠狠干 | 欧美a√在线 | 狠狠干综合 | 日韩精品一区电影 | 四虎永久网站 | 国产精品大尺度 | av在线免费在线观看 | av福利在线免费观看 | 久久99国产精品免费 | 国产精品一区二区免费在线观看 | 午夜精品久久久久久久99热影院 | 69av国产| 欧美成人按摩 | 精品国产免费av | 久久视| 欧美日韩综合在线观看 | av免费在线看网站 | 午夜91在线| 成年人在线免费看 | 久99视频| 91福利区一区二区三区 | 精品欧美一区二区精品久久 | 亚洲一区网站 | 天天玩天天干天天操 | 国产精品观看在线亚洲人成网 | 在线观看国产91 | 国产精品区在线观看 | 国产精品高清一区二区三区 | 国产精品欧美一区二区 | 国产精品99久久久久久武松影视 | 毛片网站观看 | 婷婷精品国产一区二区三区日韩 | 六月丁香综合 | 欧美日韩在线视频免费 | 超碰官网 | 亚洲午夜激情网 | 国产精品久久久久一区二区三区共 | 99久久国产免费,99久久国产免费大片 | 天天爽天天摸 | 伊人手机在线 | a黄色影院 | 亚洲黄色区 | 中文字幕影片免费在线观看 | www黄色大片 | 日韩av免费大片 | 免费观看www小视频的软件 | 最新国产一区二区三区 | 久久久高清视频 | 精品在线二区 | 在线观看色视频 | 国产精品va在线观看入 | 一区二区三区在线观看中文字幕 | 国产在线a不卡 | 一区二区视频在线免费观看 | 免费视频 三区 | 日韩黄色在线电影 | 麻豆视频观看 | 在线欧美中文字幕 | 色91av| 日韩在线观看电影 | 综合久久久久久久久 | 91av中文字幕 | 日日碰狠狠添天天爽超碰97久久 | 国产视频中文字幕 | 国产精品久久9 | 亚洲精品资源在线 | 午夜视频黄| 一区二区视频电影在线观看 | 国产福利在线免费观看 | 久久国产影院 | av色图天堂网 | 日本公妇色中文字幕 | 草久久久久 | 日韩欧美精品一区二区三区经典 | 亚洲精品视频在线观看免费 | 久草视频在线资源站 | 亚州av成人 | 国产成人av免费在线观看 | 欧美一区二区在线 | 91精品视频在线免费观看 | 日韩精品一区二区三区视频播放 | www在线免费观看 | 999国产| 国产高清在线免费观看 | 在线观看黄色免费视频 | 99国产在线 | 91视频免费网站 | 亚洲一区二区观看 | 久久婷婷一区二区三区 | 国产综合精品一区二区三区 | 天天色天天干天天色 | 欧美国产日韩一区二区三区 | 九九九视频精品 | 麻豆视频免费网站 | 免费特级黄色片 | 91亚洲狠狠婷婷综合久久久 | 国产成人精品一二三区 | 国产1区2区3区在线 亚洲自拍偷拍色图 | 欧美a免费 | 天天爽综合网 | 久久久久久久影视 | 波多野结衣在线视频一区 | 狠狠色丁香婷婷综合视频 | 亚洲精品乱码白浆高清久久久久久 | 黄色免费国产 | 国产电影黄色av | 日韩在线精品 | 五月天丁香 | 国产视频一 | 免费观看www视频 | 蜜桃视频在线观看一区 | 天天干夜夜操视频 | 欧美激情精品久久久久久免费 | 精品久久久久久久久久国产 | 91久久国产露脸精品国产闺蜜 | 久久九九精品久久 | 久久精品欧美一区二区三区麻豆 | 国产一区私人高清影院 | 午夜精品电影 | 免费在线观看成人小视频 | 成人午夜性影院 | 激情视频一区二区三区 | 国产免费区 | 欧美精品久久久久久久免费 | 国产精品美女久久久免费 | 亚洲精品一区中文字幕乱码 | 国产亚洲资源 | 五月婷婷综合久久 | 国产成人精品国内自产拍免费看 | 四虎成人av | 亚洲电影院 | 国产精品毛片网 | 狠狠天天 | 国产精品麻豆三级一区视频 | 日韩在线理论 | 亚洲 在线| 日韩天天操| 亚洲在线色 | 午夜10000| 欧美aaa大片 | 一区二区视频免费在线观看 | 亚洲在线观看av | 国产精品久久久久久久久久东京 | 国产精品大片免费观看 | 人人插人人爱 | 免费又黄又爽 | 久久精品亚洲精品国产欧美 | 日韩欧美极品 | 中文字幕丝袜 | 日韩理论视频 | 国产精品丝袜久久久久久久不卡 | 亚洲国产综合在线 | 亚洲va欧美va | 日本激情视频中文字幕 | 欧美日韩不卡一区 | 天天色婷婷 | av在线免费播放网站 | 一级理论片在线观看 | 九九视频这里只有精品 | 国内久久精品 | 在线视频区 | 欧美午夜精品久久久久 | 97精品欧美91久久久久久 | 天天躁日日躁狠狠躁 | 免费看一级一片 | 五月婷婷操 | 日韩av视屏在线观看 | 欧美人交a欧美精品 | 激情视频免费观看 | 成年人视频在线观看免费 | 在线天堂中文在线资源网 | 久草网站在线 | 91视频观看免费 | 美女免费视频一区 | 日韩黄色一级电影 | 国产精品1区2区3区 久久免费视频7 | 超碰.com| 免费观看一级一片 | 91福利试看 | 精品99999| 日韩在线影视 | 99视频国产精品免费观看 | av电影免费| 伊人电影在线观看 | 国产成人一级 | 婷婷国产v亚洲v欧美久久 | 99国产精品久久久久久久久久 | 精品国产一区二区三区四区在线观看 | 手机看片福利 | 亚洲在线黄色 | 99精品视频网站 | 欧美日韩午夜 | 日韩毛片精品 | 国产美女网站在线观看 | 日本性视频 | 国产福利不卡视频 | 91夜夜夜| 国产天天爽 | 成人午夜剧场在线观看 | 性色av香蕉一区二区 | 亚洲久草网 | 国产精品国产三级在线专区 | 日韩视频一 | 黄色av免费看 | 99视频99| 2022久久国产露脸精品国产 | 欧美激情第28页 | 最近中文字幕在线中文高清版 | 91视频免费看网站 | 美女视频网 | 欧美日韩国产一区 | 欧美一级看片 | 日韩精品视频网站 | 99视频这里只有 | 日韩国产欧美在线播放 | 婷婷丁香花五月天 | 国产91精品久久久久久 | 天天干夜夜爽 | 狠狠做六月爱婷婷综合aⅴ 日本高清免费中文字幕 | 国产情侣一区 | 久久爱综合| 永久免费看av| 久久精品国产亚洲精品 | 五月天色网站 | 日韩有码欧美 | 一级特黄av | 国产亚州精品视频 | 久久久久99精品成人片三人毛片 | 中文字幕在线观看你懂的 | 91精品一区二区三区蜜臀 | 精品99久久久久久 | 久久综合色8888 | 国产一级免费观看视频 | 日韩精品免费一线在线观看 | 中文字幕丝袜一区二区 | 97偷拍视频| 99精品观看| www黄com| 日本中文字幕在线看 | 精品一区免费 | 欧美精品免费在线观看 | 国产成人久久精品一区二区三区 | 亚洲伊人天堂 | 久久久高清一区二区三区 | 国产精品午夜久久久久久99热 | 亚洲精品国产成人av在线 | 亚洲精品综合在线 | 91精彩视频在线观看 | 五月婷婷视频 | 色婷婷国产 | 亚洲精品久久久久久中文传媒 | 国产精品淫 | 99一级片 | 在线视频久久 | 国产精品尤物视频 | 免费a网址 | 五月婷婷综合激情 | 日韩免费一区二区三区 | 99超碰在线播放 | 五月婷婷六月丁香 | 久久99视频精品 | 国产成人精品一二三区 | 国产97av | 欧美精品视 | 一区二区三区国产欧美 | 国产精品麻豆一区二区三区 | 精品亚洲免费视频 | 久久系列 | 麻豆91在线观看 | 黄色影院在线免费观看 | 国产视频欧美视频 | 视频成人永久免费视频 | 久久99亚洲精品久久 | 国产精品 9999 | 五月综合色婷婷 | 国产精品二区在线观看 | 国产在线不卡视频 | 手机成人在线电影 | 亚洲一级电影视频 | 中文字幕在线第一页 | 久精品视频在线 | 久久久久久久福利 | 成年人免费电影 | 999国产在线 | 欧美在线一二 | 91.精品高清在线观看 | 国产精品二区在线 | 99精品福利 | 黄色网址中文字幕 | 国产96在线 | 中文字幕精品一区久久久久 | 国产精品久久久久一区 | 在线中文字幕电影 | www激情网| 444av| 97热久久免费频精品99 | 狠狠色噜噜狠狠狠狠2021天天 | 久热精品国产 | 国产精品久久久久四虎 | 天天干夜夜想 | 中文在线免费观看 | 草久在线观看视频 | 亚洲精品成人av在线 | 色天堂在线视频 | 国产精品久久久久毛片大屁完整版 | 超碰人人草人人 | 久久精品国产v日韩v亚洲 | 中文字幕一区二区三区在线观看 | 在线观看一区二区精品 | 精品999| 中文字幕国语官网在线视频 | 国产a级精品 | 99精彩视频在线观看免费 | 亚洲丝袜中文 | 色五月激情五月 | 久青草视频 | 欧美精品一区二区三区四区在线 | 嫩草av影院 | 五月婷婷视频 | 国产在线观看一 | 成年一级片 | 国产99免费 | 国产精品破处视频 | 日韩欧美一区二区三区免费观看 | 一本之道乱码区 | 日日爽天天操 | 欧美色图视频一区 | 国产精品美女久久久久aⅴ 干干夜夜 | 狠狠久久婷婷 | 天天综合色天天综合 | 国产精品入口66mio女同 | 国产精品电影一区 | 中文字幕在线免费 | 亚洲精品国内 | 国产精品手机视频 | 蜜臀av性久久久久av蜜臀妖精 | 少妇av片 | 中文字幕在线观看的网站 | 欧美成人999| 九九视频免费观看视频精品 | 一 级 黄 色 片免费看的 | 欧美va天堂va视频va在线 | 免费观看成人av | 最近免费观看的电影完整版 | 久久精品香蕉 | 久久免费试看 | 狠狠干,狠狠操 | 色播99 | 激情欧美xxxx | 国产系列在线观看 | 色婷婷激情电影 | 91新人在线观看 | 99精品国产在热久久 | 午夜在线观看一区 | 国产成人精品a | 日韩欧美视频在线观看免费 | 热久久视久久精品18亚洲精品 | 欧美热久久 | 特级免费毛片 | 国产一级大片免费看 | 久久久久中文 | 欧美日韩综合在线观看 | 中文字幕一区二区三区在线播放 | av解说在线 | 亚洲天堂精品视频 | 日韩av三区 | 狠狠狠操 | 毛片网在线播放 | 在线观看视频免费大全 | 成 人 黄 色 视频 免费观看 | 免费看毛片网站 | 国产精品午夜在线观看 | 99久久国产免费,99久久国产免费大片 | 最新精品国产 | 国产在线观看xxx | 国产免费不卡 | 国产91勾搭技师精品 | 视频一区二区国产 | 午夜视频一区二区 | 久久视频99| 国产免费高清视频 | 免费视频黄 | 免费69视频 | 在线视频欧美日韩 | 亚洲欧美偷拍另类 | 久久久久久久久久久久久9999 | 探花视频在线版播放免费观看 | 久久精品首页 | 国产精品成人aaaaa网站 | 国产精品成人一区二区三区 | 日韩免费一区二区 | 伊人国产女 | 亚洲国产精品va在线看黑人 | 免费能看的av | 国产色中涩 | 久久综合影音 | 婷婷丁香av | 九九九电影免费看 | 日韩免费一区二区 | 黄色免费网| 国产高清精品在线观看 | 国产99久久久国产精品免费看 | 人人爽人人爽人人片 | 欧美性受极品xxxx喷水 | 中文成人字幕 | 国产97色在线 | 日韩在线观看的 | 亚洲成人精品久久 | 婷婷六月中文字幕 | 伊人五月天.com | 天堂网一区二区 | 亚洲成人免费在线 | 三级黄色免费 | 99精品国产成人一区二区 | 国产无套精品久久久久久 | 中文字幕a∨在线乱码免费看 | 2019天天干夜夜操 | 尤物九九久久国产精品的分类 | www.久久色 | 在线观看日本韩国电影 | av 在线观看 | 成人在线播放av | 一级片免费视频 | 亚洲欧美视频一区二区三区 | 96看片| 999久久| 亚洲国产精品久久久久婷婷884 | 99久久精品免费看国产一区二区三区 | 日日夜夜天天久久 | 久久久免费网站 | 欧美日韩一级在线 | 国产高清免费在线播放 | 亚洲丝袜一区二区 | 精品三级av | 狠狠操天天射 | 国产麻豆果冻传媒在线观看 | 日韩大片在线播放 | 韩国精品一区二区三区六区色诱 | 成人免费观看大片 | 免费国产在线视频 | 国产精品美女久久久久久久久 | 久久久久久久久久久久影院 | 激情综合色综合久久综合 | 人人干狠狠干 | 欧美伊人网 | 日韩天天操 | 香蕉在线视频播放网站 | 日本黄色免费网站 | 日韩sese | 久久视频免费观看 | 国产精品免费人成网站 | 久久国语 | 婷婷深爱五月 | av天天干| 国产精品乱码久久久久 | 91禁在线看 | 99久久久国产精品免费99 | 在线一区二区三区 | 日本久久久久久久久 | 精品v亚洲v欧美v高清v | 亚洲国产网站 | 欧美一区二区三区免费观看 | 日本最新高清不卡中文字幕 | 四虎在线免费观看 | 久久精品美女 | 天天透天天插 | 超碰97成人 | 色五月色开心色婷婷色丁香 | 久久久久免费精品国产小说色大师 | 91福利社区在线观看 | 丁香激情综合久久伊人久久 | 日韩精品欧美视频 | 最近中文字幕免费av | 亚洲精品福利在线观看 | 999一区二区三区 | 国产精品美女在线 | 91精品国产91热久久久做人人 | 久久精国产 | 亚洲高清在线观看视频 | 久久精品中文字幕免费mv | 波多野结衣久久精品 | 国产一二三在线视频 | 久久精品a| 狠狠操狠狠干2017 | 三上悠亚一区二区在线观看 | 日韩在线播放视频 | 亚洲高清视频在线观看免费 | 日韩精品一区二区三区第95 | 精品一区91| 91污在线观看| www色com | 成人黄色av免费在线观看 | 国产中文字幕一区二区 | 少妇bbbb揉bbbb日本 | 欧美一级久久久 | 五月天精品视频 | 五月婷婷六月丁香 | 天天操人人要 | 大荫蒂欧美视频另类xxxx | 黄色一级在线观看 | 国产特级毛片aaaaaaa高清 | 久久久久免费看 | 欧美一区二区在线免费看 | 国产手机在线精品 | 日韩欧美高清在线观看 | 精品人人人 | 日韩精品视频在线观看免费 | 99精品在线免费视频 | 99热国产在线观看 | 久草香蕉在线 | 丁香色婷| 国产一在线精品一区在线观看 | 99这里只有精品视频 | 天天干天天天 | 国产精品精品国产 | 2021国产在线| 天天插天天射 | 亚洲 在线 | 日韩电影在线视频 | 在线免费观看涩涩 | 免费a级黄色毛片 | 香蕉视频最新网址 | 国产精品久久久影视 | 久久久黄色av | 最近日本字幕mv免费观看在线 | 国产中文a | 国产日本在线播放 | 午夜精品一区二区三区四区 | 亚洲欧美国内爽妇网 | 成人影音在线 | 黄色片免费看 | 国产一线天在线观看 | 91pony九色丨交换 | 久久久久国产精品厨房 | 国产视频97| 99精品视频免费看 | 在线观看亚洲成人 | 久久久免费 | 日本中文字幕在线一区 | 久久免费国产视频 | 日韩精品黄 | 久久视频在线观看中文字幕 | 毛片久久久 | 91私密视频 | 91视频高清完整版 | 一级黄色大片在线观看 | 在线视频日韩欧美 | 97免费中文视频在线观看 | zzijzzij亚洲成熟少妇 | 波多野结衣在线中文字幕 | 免费色网 | 九九视频免费观看视频精品 | 日本一区二区高清不卡 | 免费看黄的视频 | 91视频91色 | 99国产成+人+综合+亚洲 欧美 | 色综合久久久久综合体桃花网 | 成人黄色电影在线观看 | 九九免费在线看完整版 | 亚洲午夜精品电影 | 国产成人精品在线 | 麻豆一二三精选视频 | 成年人免费看片 | 黄色国产区 | 久久99精品国产麻豆婷婷 | 午夜精品久久久久久 | 日本丶国产丶欧美色综合 | 91av在线国产 | 成人黄色大片网站 | 夜夜操狠狠操 | 久久天天躁夜夜躁狠狠85麻豆 | 国产专区精品视频 | 在线观看中文字幕2021 | 狠狠操在线 | 久久一区二区三区超碰国产精品 | 激情图片久久 | 日韩午夜电影 | 国产精品视频在线看 | 亚洲免费一级电影 | 九九久久国产精品 | 国产高清不卡av | 国产精品免费在线播放 | 天天摸天天舔 | 国产一区在线播放 | 三级a毛片 | 91免费版成人 | 最近中文字幕在线播放 | 成人av在线直播 | 精品视频久久 | 久久久久这里只有精品 | 久久国产网站 | 亚洲国产精品视频在线观看 | 狠狠干网站 | 日韩av片无码一区二区不卡电影 | 欧美韩国日本在线观看 | 在线黄av | 黄色a一级视频 | 国产精品欧美久久久久无广告 | 免费看片色 | 五月天婷亚洲天综合网精品偷 | 日韩精品欧美一区 | 91亚色在线观看 | 日日添夜夜添 | 夜夜高潮夜夜爽国产伦精品 | 色婷婷丁香 | 国产中文字幕网 | 国产精品久久久久永久免费观看 | 激情欧美一区二区三区免费看 | 亚洲国产97在线精品一区 | 日日干干夜夜 | 国产大尺度视频 | 91av蜜桃| 懂色av一区二区三区蜜臀 | 日韩精品一区二区三区电影 | 超碰在线亚洲 | 91网在线 | 成人福利在线 | 香蕉在线视频播放网站 | 色综合久久88色综合天天人守婷 | 国内久久精品 | 麻豆传媒视频在线免费观看 | 婷婷色婷婷 | 久久久网 | 日韩精品中文字幕在线播放 | 99久久精品免费一区 | 中文字幕免费高清av | 国产成人免费观看 | 国产精品黄网站在线观看 | 国产二区电影 | 欧美精品中文 | 国产电影一区二区三区四区 | 日韩精品一区二区三区在线播放 | 国产精品一区二区视频 | 在线免费观看视频一区二区三区 | 99热亚洲精品 | 国产一级视频在线 | 中文字幕国产一区二区 | 亚洲精品久久久蜜臀下载官网 | 人人澡av| 啪一啪在线 | 精品特级毛片 | 亚洲精品视频国产 | 国产精品热视频 | 激情网站免费观看 | 中文av一区二区 | 精品在线观看一区二区 | 91你懂的 | 四虎成人精品在永久免费 | 福利网址在线观看 | 91大神精品视频 | 国产成人三级 | 人人爽人人爽人人片av | 九九在线免费视频 | 久久影视中文字幕 | 国产又粗又猛又黄又爽的视频 | 日韩久久久久久久久 | 国产精品一区二区免费视频 | 深爱激情五月网 | 人人干天天干 | 99久久www免费| 免费看的黄色片 | 国产一性一爱一乱一交 | 91自拍成人 | 狠狠地日 | 麻豆国产在线播放 | 欧美激情视频一二区 | 欧美另类网站 | 中文在线亚洲 | 久久人人97超碰国产公开结果 | 91少妇精拍在线播放 | 不卡电影免费在线播放一区 | 国产精品video | 亚洲欧美国产视频 | 亚洲激情精品 | 九九热在线播放 | 视频三区在线 | 在线 国产一区 | 激情欧美丁香 | 久久久久久久久久久影视 | 96亚洲精品久久久蜜桃 | 日韩精品高清不卡 | 国产精品一区二区久久精品爱微奶 | 亚洲精品乱码久久 | 国产成人综合在线观看 | 99色视频 | 夜夜操天天摸 | 精品国产一区二区三区在线 | 成年人电影毛片 | 日韩网站免费观看 | 色综合久久久久综合体 | 美女免费网视频 | 免费看高清毛片 | 亚洲观看黄色网 | 国产精品va在线观看入 | 人人爽久久久噜噜噜电影 | 久久精品女人毛片国产 | 国产无套精品久久久久久 | 欧美日韩午夜爽爽 | 蜜臀av性久久久久蜜臀aⅴ四虎 | 国产麻豆传媒 | 午夜精品一区二区三区视频免费看 | 韩国av一区| 一区二区三区高清不卡 | 日本老少交| 中文在线中文a | 国模一区二区三区四区 | av高清在线 | 成人免费视频视频在线观看 免费 | 久草在线观看视频免费 | 免费看三级| 久久婷婷亚洲 | 久久高清av | 狠狠色狠狠色综合日日92 | 人人澡人人模 | 国内精品久久久久影院一蜜桃 | 西西4444www大胆视频 | 免费看黄网站在线 | 精品 一区 在线 | 天天色天天色天天色 | 久久久久久久久久伊人 | 午夜丁香网 | 精品美女久久久久 | 国产精品视频999 | 99久久精品一区二区成人 | 久久久久久高清 | 欧美日韩xx | 久久国内精品 | 欧美成年人在线视频 | 毛片在线播放网址 | 天天射综合网视频 | 正在播放国产91 | 亚洲激情精品 | 在线观看色网 | 超碰在线日本 | 国产精品久久久久免费观看 | 91精品国产麻豆国产自产影视 | 国产精品一区二区美女视频免费看 | 久久撸在线视频 | 欧美日韩视频一区二区 | 国产日韩欧美视频 | av黄色国产 | 99精品影视 | 国内视频在线 | 日韩中文字幕免费视频 | 狠狠色噜噜狠狠狠狠 | 国产麻豆剧果冻传媒视频播放量 | 激情视频二区 | 国产日韩欧美精品在线观看 | av在线网站观看 | 欧美大香线蕉线伊人久久 | 黄色在线免费观看网站 | 一区二区三区四区不卡 | 欧美一区二区三区在线播放 | 久久久国产精品视频 | 国产一区二区精品久久 | 亚洲三级在线免费观看 | 国内精品久久久久影院男同志 | 成年人在线免费看视频 | 国产一区二区高清不卡 | 黄色软件在线看 | 97在线播放视频 | 国产精品av在线免费观看 | 日日成人网 | 欧美一区二区视频97 | 久久久久久久国产精品视频 | 国产精品精品久久久久久 | 久久国产三级 | 中文字幕精品一区二区三区电影 | 国产性天天综合网 | 国产专区免费 | 中文字幕丝袜一区二区 | 亚洲精品一区中文字幕乱码 | 日韩视频一区二区三区 | 黄色不卡av | 成人黄色电影在线播放 | 久久视频免费在线观看 | 91亚洲国产成人久久精品网站 | 99re8这里有精品热视频免费 | 免费亚洲精品视频 | 干狠狠| 成人免费视频播放 | 欧美日韩免费网站 | 91在线资源 | 亚洲高清网站 | 成人黄色片在线播放 | 国产96精品 | 成人久久久久久久久 | 中文字幕色综合网 | 玖玖在线免费视频 | avwww在线观看 | 国产在线国产 | 精品日韩中文字幕 | 亚洲专区欧美 | 91av资源网| 在线中文字幕观看 | 91.dizhi永久地址最新 | 欧美a在线看 | 免费在线国产黄色 | 果冻av在线 | 日本精品一区二区三区在线播放视频 | 久久精品欧美一区二区三区麻豆 | 欧美乱熟臀69xxxxxx | 性色av一区二区 | 美女视频网站久久 | 西西4444www大胆无视频 | 欧美永久视频 | 国产午夜精品一区二区三区欧美 | 亚洲免费av片| 中文字幕字幕中文 | 久久精品综合网 | 久久久久久综合网天天 | 久久久久伦理电影 | 激情久久一区二区三区 | 日本超碰在线 | 91久久精品一区二区三区 | 99精品久久久久久久久久综合 | 亚洲国产欧洲综合997久久, | 中文字幕在线播放一区 | 日韩av女优视频 | 奇米影视999 | 婷婷免费在线视频 | 天天干天天爽 | 国产一区二区在线免费视频 | 久久国产精品小视频 | 欧美一级视频免费看 | 免费看黄在线看 | 日韩精品一区二区不卡 | 91在线视频免费观看 | 午夜.dj高清免费观看视频 | 六月婷操 | 午夜三级毛片 | 狠狠躁18三区二区一区ai明星 | 婷婷中文字幕在线观看 | 国产福利一区二区三区在线观看 | 国产中的精品av小宝探花 | 色av男人的天堂免费在线 | 日韩欧美综合 | 中文字幕国产视频 | 国产精品video爽爽爽爽 | 欧美不卡视频在线 | 一区二区三区在线影院 | 日韩av中文在线观看 | 97视频人人免费看 | 天天操操操操操操 | 免费人成网 | 久久成人高清视频 | 欧美狠狠色 | 亚洲精色 | 亚洲传媒在线 | 亚洲精品在线一区二区 | 国产久草在线 | 插久久| 91精品欧美一区二区三区 | 91亚洲网站| 国产亚洲精品女人久久久久久 | 亚洲三级黄 | 三级黄色在线观看 | 国产精品a久久久久 | 久久国内精品99久久6app | 日韩精品一区二区三区丰满 | 久久精品香蕉 | 中字幕视频在线永久在线观看免费 | 在线观看v片 | 日韩有码中文字幕在线 | 久久久免费 | 午夜影院在线观看18 | 中文字幕精品一区久久久久 | 在线观看免费国产小视频 | 性色大片在线观看 | 久久久av免费 | 国产在线精品国自产拍影院 | 成人一级电影在线观看 | 久久伦理影院 | 香蕉网在线播放 | 天天玩夜夜操 | 亚洲精品在线二区 | 99在线视频免费观看 | 久草视频在线播放 | 91精品伦理| 四虎在线免费 | 日韩毛片精品 | 伊甸园永久入口www 99热 精品在线 | www.色婷婷.com | 国产91精品欧美 | 亚洲va在线va天堂va偷拍 | 97超碰国产精品女人人人爽 | 美女免费黄视频网站 | 国产综合激情 | 中文字幕高清免费日韩视频在线 | 一区二区视频免费在线观看 | 最新av网址在线观看 | 成人国产精品一区二区 |