From 950f8edf7eb6d4dfbf3cc5e1f770ecd1c46e5aed Mon Sep 17 00:00:00 2001 From: wuxicheng <1441859745@qq.com> Date: Thu, 15 Jun 2023 14:54:54 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0spring=E9=87=8D=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bnyer-common/bnyer-common-core/pom.xml | 6 + .../com/bnyer/pay/bean/vo/ThirdPayBaseVo.java | 3 + .../pay/design/strategy/DYPayStrategy.java | 6 +- .../pay/design/strategy/KSPayStrategy.java | 5 +- .../pay/design/strategy/WxPayStrategy.java | 6 +- .../com/bnyer/pay/manager/DyPayManager.java | 30 +-- .../bnyer/pay/manager/DyPayManagerBack.java | 182 ++++++++++++++++++ .../service/impl/UnifiedPayServiceImpl.java | 3 + 8 files changed, 210 insertions(+), 31 deletions(-) create mode 100644 bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/manager/DyPayManagerBack.java diff --git a/bnyer-common/bnyer-common-core/pom.xml b/bnyer-common/bnyer-common-core/pom.xml index d1d4b4c..24e6148 100644 --- a/bnyer-common/bnyer-common-core/pom.xml +++ b/bnyer-common/bnyer-common-core/pom.xml @@ -157,6 +157,12 @@ tencentcloud-sdk-java-aiart 3.1.715 + + + + org.springframework.retry + spring-retry + diff --git a/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/bean/vo/ThirdPayBaseVo.java b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/bean/vo/ThirdPayBaseVo.java index 37805b7..0920ad8 100644 --- a/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/bean/vo/ThirdPayBaseVo.java +++ b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/bean/vo/ThirdPayBaseVo.java @@ -13,6 +13,9 @@ import lombok.Setter; @Setter public class ThirdPayBaseVo { + @ApiModelProperty(value = "业务码 -1失败 0成功") + private String resultCode; + @ApiModelProperty(value="错误码") private String thirdCode; diff --git a/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/DYPayStrategy.java b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/DYPayStrategy.java index f4afffd..c4bee62 100644 --- a/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/DYPayStrategy.java +++ b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/DYPayStrategy.java @@ -123,7 +123,8 @@ public class DYPayStrategy extends AbstractPayStrategy{ } catch (PayException e) { log.error("抖音支付:支付异常,payId:{},error{}", bo.getPayId(), e.getMessage()); thirdUnifiedOrderVo.setThirdCode(e.getErrCode()); - thirdUnifiedOrderVo.setThirdMsg(StringUtils.isNoneBlank(e.getErrCodeDes())?e.getErrCodeDes():e.getCustomErrorMsg()); + thirdUnifiedOrderVo.setThirdMsg(StringUtils.isNotBlank(e.getErrCodeDes())?e.getErrCodeDes():e.getCustomErrorMsg()); + thirdUnifiedOrderVo.setResultCode("-1"); return thirdUnifiedOrderVo; } log.info("=================================="); @@ -140,6 +141,7 @@ public class DYPayStrategy extends AbstractPayStrategy{ log.error("抖音支付:统一下单接口调用失败,payId:{},result:{},error{}", bo.getPayId(),JSON.toJSONString(data), msg); thirdUnifiedOrderVo.setThirdCode(errNo); thirdUnifiedOrderVo.setThirdMsg(msg); + thirdUnifiedOrderVo.setResultCode("-1"); return thirdUnifiedOrderVo; } //保存预下单信息 @@ -153,7 +155,7 @@ public class DYPayStrategy extends AbstractPayStrategy{ thirdUnifiedOrderVo.setThirdNo(orderId); thirdUnifiedOrderVo.setThirdCode(errNo); thirdUnifiedOrderVo.setThirdMsg(errorMsg); - + thirdUnifiedOrderVo.setResultCode("0"); return thirdUnifiedOrderVo; } diff --git a/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/KSPayStrategy.java b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/KSPayStrategy.java index 483c6e6..1a267ca 100644 --- a/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/KSPayStrategy.java +++ b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/KSPayStrategy.java @@ -130,7 +130,8 @@ public class KSPayStrategy extends AbstractPayStrategy{ } catch (PayException e) { log.error("快手支付:支付异常,payId:{},error{}", bo.getPayId(), e); thirdUnifiedOrderVo.setThirdCode(e.getErrCode()); - thirdUnifiedOrderVo.setThirdMsg(StringUtils.isNoneBlank(e.getErrCodeDes())?e.getErrCodeDes():e.getCustomErrorMsg()); + thirdUnifiedOrderVo.setThirdMsg(StringUtils.isNotBlank(e.getErrCodeDes())?e.getErrCodeDes():e.getCustomErrorMsg()); + thirdUnifiedOrderVo.setResultCode("-1"); return thirdUnifiedOrderVo; } log.info("=================================="); @@ -147,6 +148,7 @@ public class KSPayStrategy extends AbstractPayStrategy{ log.error("快手支付:统一下单接口调用失败,payId:{},result:{},error{}", bo.getPayId(),JSON.toJSONString(data), msg); thirdUnifiedOrderVo.setThirdCode(resultCode); thirdUnifiedOrderVo.setThirdMsg(msg); + thirdUnifiedOrderVo.setResultCode("-1"); return thirdUnifiedOrderVo; } //保存预下单信息 @@ -160,6 +162,7 @@ public class KSPayStrategy extends AbstractPayStrategy{ thirdUnifiedOrderVo.setThirdNo(orderNo); thirdUnifiedOrderVo.setThirdCode(resultCode); thirdUnifiedOrderVo.setThirdMsg(errorMsg); + thirdUnifiedOrderVo.setResultCode("0"); return thirdUnifiedOrderVo; } diff --git a/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/WxPayStrategy.java b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/WxPayStrategy.java index c3c74e6..f43dca5 100644 --- a/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/WxPayStrategy.java +++ b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/WxPayStrategy.java @@ -125,12 +125,14 @@ public class WxPayStrategy extends AbstractPayStrategy { thirdUnifiedOrderVo.setThirdNo(wxPayUnifiedOrderV3Result.getPrepayId()); thirdUnifiedOrderVo.setWxThirdInOrderVo(wxThirdInOrderVo); + thirdUnifiedOrderVo.setResultCode("0"); return thirdUnifiedOrderVo; } catch (WxPayException e) { log.error("微信支付:统一下单接口调用失败,payId:{},error{}", bo.getPayId(), e.getMessage()); thirdUnifiedOrderVo.setAppId(wxPayConfig.getAppid()); thirdUnifiedOrderVo.setThirdCode(e.getErrCode()); - thirdUnifiedOrderVo.setThirdMsg(e.getErrCodeDes()); + thirdUnifiedOrderVo.setThirdMsg(StringUtils.isNotBlank(e.getErrCodeDes())?e.getErrCodeDes():e.getCustomErrorMsg()); + thirdUnifiedOrderVo.setResultCode("-1"); return thirdUnifiedOrderVo; } } @@ -260,7 +262,7 @@ public class WxPayStrategy extends AbstractPayStrategy { } catch (WxPayException e) { log.error("微信支付:退款调用异常,payId:{},refundNo:{},error{}", bo.getPayId(),bo.getRefundNo(),e.getMessage()); thirdRefundVo.setThirdCode(e.getErrCode()); - thirdRefundVo.setThirdMsg(e.getErrCodeDes()); + thirdRefundVo.setThirdMsg(StringUtils.isNoneBlank(e.getErrCodeDes())?e.getErrCodeDes():e.getCustomErrorMsg()); return thirdRefundVo; } } diff --git a/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/manager/DyPayManager.java b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/manager/DyPayManager.java index cfbb30c..50fc182 100644 --- a/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/manager/DyPayManager.java +++ b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/manager/DyPayManager.java @@ -16,6 +16,8 @@ import me.chanjar.weixin.common.util.json.GsonParser; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; +import org.springframework.retry.annotation.Backoff; +import org.springframework.retry.annotation.Retryable; import org.springframework.web.client.RestTemplate; import java.text.MessageFormat; @@ -54,6 +56,7 @@ public class DyPayManager { * * access_token 是小程序的全局唯一调用凭据,开发者调用小程序支付时需要使用 access_token。access_token 的有效期为 2 个小时,需要定时刷新 access_token,重复获取会导致之前一次获取的 access_token 的有效期缩短为 5 分钟。 */ + @Retryable(backoff = @Backoff(delay = 3000,multiplier = 1.5,maxDelay = 360000L)) public String getAccessToken(boolean isRefresh) throws PayException { if (!isRefresh){ Object cacheObject = redisService.getCacheObject(RedisKeyConstant.DY_ACCESS_TOKEN_KEY); @@ -129,7 +132,7 @@ public class DyPayManager { } //如果是access_token过期,刷新token在重试 if ("40004".equals(e.getErrCode())){ - String accessToken = refreshAccessToken(); + String accessToken = getAccessToken(true); JSONObject requestJsonObj = JSON.parseObject(requestStr); requestJsonObj.put("access_token",accessToken); requestStr = requestJsonObj.toJSONString(); @@ -140,31 +143,6 @@ public class DyPayManager { return resultStr; } - /** - * 刷新access_token - */ - public String refreshAccessToken() throws PayException { - return refreshAccessToken(0); - } - - /** - * 刷新access_token - * @param retryTimes - */ - public String refreshAccessToken(int retryTimes) throws PayException { - String accessToken = ""; - try { - accessToken = getAccessToken( true); - } catch (PayException e) { - if (retryTimes > MAX_RETRY_TIMES){ - throw new PayException("抖音接口获取AccessToken调用失败,已超过最大重试次数"); - } - retryTimes ++; - refreshAccessToken(retryTimes); - } - return accessToken; - } - /** * 转换异常 * @param jsonObject diff --git a/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/manager/DyPayManagerBack.java b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/manager/DyPayManagerBack.java new file mode 100644 index 0000000..eaa37d1 --- /dev/null +++ b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/manager/DyPayManagerBack.java @@ -0,0 +1,182 @@ +//package com.bnyer.pay.manager; +// +//import com.alibaba.fastjson.JSON; +//import com.alibaba.fastjson.JSONObject; +//import com.bnyer.common.core.constant.RedisKeyConstant; +//import com.bnyer.common.core.domain.DypayConfig; +//import com.bnyer.common.core.utils.SpringUtils; +//import com.bnyer.common.core.utils.StringUtils; +//import com.bnyer.common.redis.service.RedisService; +//import com.bnyer.pay.constant.DYPayConstants; +//import com.bnyer.pay.exception.PayException; +//import com.google.gson.JsonElement; +//import com.google.gson.JsonObject; +//import lombok.extern.slf4j.Slf4j; +//import me.chanjar.weixin.common.util.json.GsonParser; +//import org.springframework.http.HttpEntity; +//import org.springframework.http.HttpHeaders; +//import org.springframework.http.MediaType; +//import org.springframework.web.client.RestTemplate; +// +//import java.text.MessageFormat; +//import java.util.Objects; +//import java.util.concurrent.TimeUnit; +// +///** +// * @author :WXC +// * @Date :2023/04/24 +// * @description : +// */ +//@Slf4j +//public class DyPayManagerBack { +// +// private RestTemplate restTemplate; +// +// private RedisService redisService; +// +// private final DypayConfig dypayConfig; +// +// private final int MAX_RETRY_TIMES = 2; +// +// public DyPayManagerBack(DypayConfig dypayConfig){ +// this.dypayConfig = dypayConfig; +// init(); +// } +// +// private void init() { +// this.restTemplate = SpringUtils.getBean(RestTemplate.class); +// this.redisService = SpringUtils.getBean(RedisService.class); +// } +// +// /** +// * 抖音小程序获取accessToken +// * 为了保障应用的数据安全,只能在开发者服务器使用 AppSecret,如果小程序存在泄露 AppSecret 的问题,字节小程序平台将有可能下架该小程序,并暂停该小程序相关服务。 +// * +// * access_token 是小程序的全局唯一调用凭据,开发者调用小程序支付时需要使用 access_token。access_token 的有效期为 2 个小时,需要定时刷新 access_token,重复获取会导致之前一次获取的 access_token 的有效期缩短为 5 分钟。 +// */ +// public String getAccessToken(boolean isRefresh) throws PayException { +// if (!isRefresh){ +// Object cacheObject = redisService.getCacheObject(RedisKeyConstant.DY_ACCESS_TOKEN_KEY); +// if (Objects.nonNull(cacheObject)){ +// return cacheObject.toString(); +// } +// } +// String requestStr = ""; +// try { +// HttpHeaders headers = new HttpHeaders(); +// headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); +// HttpEntity formEntity = new HttpEntity<>(MessageFormat.format("app_id={0}&app_secret={1}&&grant_type={2}" +// , dypayConfig.getAppid(), dypayConfig.getAppSecret(), "client_credentials"), headers); +// String resultStr = restTemplate.postForObject(DYPayConstants.GET_ACCESS_TOKEN, formEntity, String.class); +// String url = DYPayConstants.GET_ACCESS_TOKEN; +// requestStr = formEntity.getBody(); +// if (StringUtils.isBlank(resultStr) || !resultStr.startsWith("{")){ +// log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, resultStr); +// throw new PayException("第三方返回格式有误!"); +// } +// JSONObject resultObj = JSONObject.parseObject(resultStr); +// String errNo = StringUtils.isNotBlank(resultObj.getString("err_no"))?resultObj.getString("err_no"):resultObj.getString("err_code"); +// if ("0".equals(errNo)) { +// log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, resultObj, resultStr); +// //存入redis +// String accessToken = resultObj.getJSONObject("data").getString("access_token"); +// String expiresIn = resultObj.getJSONObject("data").getString("expires_in"); +// redisService.setCacheObject(RedisKeyConstant.DY_ACCESS_TOKEN_KEY,accessToken,Long.parseLong(expiresIn), TimeUnit.SECONDS); +// return accessToken; +// }else { +// throw convertDyException(GsonParser.parse(resultStr)); +// } +// } catch (Exception e) { +// log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", DYPayConstants.GET_ACCESS_TOKEN, requestStr, e.getMessage()); +// throw (e instanceof PayException) ? (PayException) e : new PayException(e.getMessage(), e); +// } +// } +// +// /** +// * post请求 +// */ +// public String postRequest(String requestStr, String url) throws PayException { +// return postRequest(0,requestStr,url); +// } +// +// /** +// * post请求 +// */ +// public String postRequest(int retryTimes, String requestStr, String url) throws PayException { +// String resultStr = ""; +// try { +// HttpHeaders headers = new HttpHeaders(); +// //所有的请求需要用JSON格式发送 +// headers.setContentType(MediaType.APPLICATION_JSON); +// HttpEntity formEntity = new HttpEntity<>(requestStr, headers); +// resultStr = restTemplate.postForObject(url, formEntity, String.class); +// if (StringUtils.isBlank(resultStr) || !resultStr.startsWith("{")){ +// log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, resultStr); +// throw new PayException("第三方返回格式有误!"); +// } +// JSONObject resultObj = JSONObject.parseObject(resultStr); +// String errNo = StringUtils.isNotBlank(resultObj.getString("err_no"))?resultObj.getString("err_no"):resultObj.getString("err_code"); +// if ("0".equals(errNo)) { +// log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, resultObj, resultStr); +// return resultStr; +// }else { +// throw convertDyException(GsonParser.parse(resultStr)); +// } +// }catch (PayException e){ +// log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage()); +// if (retryTimes > MAX_RETRY_TIMES){ +// throw new PayException("抖音接口调用失败,已超过最大重试次数"); +// } +// //如果是access_token过期,刷新token在重试 +// if ("40004".equals(e.getErrCode())){ +// String accessToken = refreshAccessToken(); +// JSONObject requestJsonObj = JSON.parseObject(requestStr); +// requestJsonObj.put("access_token",accessToken); +// requestStr = requestJsonObj.toJSONString(); +// } +// retryTimes ++; +// postRequest(retryTimes,requestStr,url); +// } +// return resultStr; +// } +// +// /** +// * 刷新access_token +// */ +// public String refreshAccessToken() throws PayException { +// return refreshAccessToken(0); +// } +// +// /** +// * 刷新access_token +// * @param retryTimes +// */ +// public String refreshAccessToken(int retryTimes) throws PayException { +// String accessToken = ""; +// try { +// accessToken = getAccessToken( true); +// } catch (PayException e) { +// if (retryTimes > MAX_RETRY_TIMES){ +// throw new PayException("抖音接口获取AccessToken调用失败,已超过最大重试次数"); +// } +// retryTimes ++; +// refreshAccessToken(retryTimes); +// } +// return accessToken; +// } +// +// /** +// * 转换异常 +// * @param jsonObject +// * @return +// */ +// private PayException convertDyException(JsonObject jsonObject) { +// JsonElement codeElement = jsonObject.get("err_no") != null ? jsonObject.get("err_no"):jsonObject.get("err_code"); +// String code = codeElement == null ? null : codeElement.getAsString(); +// String message = jsonObject.get("error_msg").getAsString(); +// PayException payException = new PayException(message); +// payException.setErrCode(code); +// payException.setErrCodeDes(message); +// return payException; +// } +//} diff --git a/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/service/impl/UnifiedPayServiceImpl.java b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/service/impl/UnifiedPayServiceImpl.java index 546a549..76b5c4f 100644 --- a/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/service/impl/UnifiedPayServiceImpl.java +++ b/bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/service/impl/UnifiedPayServiceImpl.java @@ -120,6 +120,9 @@ public class UnifiedPayServiceImpl implements UnifiedPayService { throw new ServiceException("暂不支持该支付方式"); } ThirdUnifiedOrderVo thirdUnifiedOrderVo = payStrategy.unifiedOrder(unifiedOrderBo); + if ("-1".equals(thirdUnifiedOrderVo.getResultCode())){ + throw new ServiceException(ResponseEnum.PAY_FAILS); + } //构建支付订单完成入库 AddPayInfoDto addPayInfoDto = buildPayInfo(thirdUnifiedOrderVo, unifiedOrderBo,dto); payInfoService.addPayInfo(addPayInfoDto);