Browse Source

Merge remote-tracking branch 'origin/feature-1.1-bnyer-order' into feature-1.1-dev

feature-1.1
Penny 3 years ago
parent
commit
a28996ee99
  1. 2
      bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/domain/R.java
  2. 32
      bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/enums/EnumRefundStatus.java
  3. 3
      bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/enums/ResponseEnum.java
  4. 4
      bnyer-services/bnyer-img/src/main/java/com/bnyer/img/query/UserVipRecordQuery.java
  5. 2
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/annotation/LimitRepeatRequest.java
  6. 39
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/aop/LimitRepeatRequestAspect.java
  7. 2
      bnyer-services/bnyer-order/src/main/java/com/bnyer/order/service/impl/VipOrderServiceImpl.java
  8. 2
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/annotation/LimitRepeatRequest.java
  9. 37
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/aop/LimitRepeatRequestAspect.java
  10. 25
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/bean/bo/RefundBo.java
  11. 27
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/bean/vo/ThirdPayBaseVo.java
  12. 61
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/bean/vo/ThirdRefundVo.java
  13. 14
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/bean/vo/ThirdUnifiedOrderVo.java
  14. 2
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/bean/vo/UnifiedOrderVo.java
  15. 4
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/DYPayStrategy.java
  16. 56
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/WxPayStrategy.java
  17. 2
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/enums/EnumVerificationKey.java
  18. 16
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/service/impl/PayInfoServiceImpl.java
  19. 87
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/service/impl/UnifiedPayServiceImpl.java
  20. 8
      bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/utils/PaymentRefundUtil.java

2
bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/domain/R.java

@ -83,7 +83,7 @@ public class R<T> implements Serializable
* @return
*/
public R<T> buildRepeatRequest(int time){
return restResult(null,ResponseEnum.REPEAT_REQUEST_ERROR.getCode(),time+"分钟内"+ResponseEnum.REPEAT_REQUEST_ERROR.getMsg());
return restResult(null,ResponseEnum.REPEAT_REQUEST_ERROR.getCode(),time+"内"+ResponseEnum.REPEAT_REQUEST_ERROR.getMsg());
}
private static <T> R<T> restResult(T data, int code, String msg)

32
bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/enums/EnumRefundStatus.java

@ -0,0 +1,32 @@
package com.bnyer.common.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* @author :WXC
* @description :
*/
@Getter
@AllArgsConstructor
public enum EnumRefundStatus {
NO_REFUND(1000,"未退款"),
FAILS(1001,"退款失败"),
SUCCESS(1002,"退款成功"),
PROCESS(1003,"退款中"),
;
private final int status;
private final String name;
public static EnumRefundStatus getEnumStatusByStatus(int status) {
return Arrays.stream(values())
.filter(payStatus -> payStatus.getStatus() == status)
.findFirst().orElseThrow(() -> new SecurityException("status 未匹配上对应的支付状态"));
}
}

3
bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/enums/ResponseEnum.java

@ -10,7 +10,7 @@ public enum ResponseEnum {
//======================系统异常========================,
SERVER_ERROR(500, "系统繁忙,请稍候重试!"),
NOT_AUTH(500, "未登录!"),
REPEAT_REQUEST_ERROR(500, "请勿重复请求"),
REPEAT_REQUEST_ERROR(500, "请勿重复提交"),
PARAM_ERROR(400, "参数异常!"),
@ -30,6 +30,7 @@ public enum ResponseEnum {
//======================第三方接口调用异常========================
PAY_FAILS(220001,"支付失败,请稍后重试"),
ORDER_QUERY_FAILS(220002,"订单查询失败,请稍后重试"),
REFUND_FAILS(220003,"退款失败,请稍后重试"),
;

4
bnyer-services/bnyer-img/src/main/java/com/bnyer/img/query/UserVipRecordQuery.java

@ -17,7 +17,9 @@ public class UserVipRecordQuery {
@ApiModelProperty(value = "id")
private Long id;
@ApiModelProperty(value = "用户id")
/**
* 用户id
*/
private Long userId;
/**
* 用户客户端类型

2
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/annotation/LimitRepeatRequest.java

@ -31,7 +31,7 @@ public @interface LimitRepeatRequest {
* 当前时间内 api 只能请求一次单位秒
* @return
*/
int time() default 5;
long time() default 5;
/**
* 对部分参数做重复请求限制

39
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/aop/LimitRepeatRequestAspect.java

@ -1,14 +1,15 @@
package com.bnyer.order.aop;
package com.bnyer.pay.aop;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bnyer.common.core.domain.R;
import com.bnyer.common.core.enums.ResponseEnum;
import com.bnyer.common.core.exception.ServiceException;
import com.bnyer.common.core.utils.MD5Util;
import com.bnyer.common.core.utils.StringUtils;
import com.bnyer.common.core.vo.UserInfoVo;
import com.bnyer.common.redis.service.RedisService;
import com.bnyer.common.redis.service.RedissonService;
import com.bnyer.common.security.utils.SecurityUtils;
import com.bnyer.order.annotation.LimitRepeatRequest;
import lombok.extern.slf4j.Slf4j;
@ -17,9 +18,10 @@ import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.redisson.api.RLock;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@ -34,25 +36,24 @@ import java.util.concurrent.TimeUnit;
@Component
public class LimitRepeatRequestAspect {
@Autowired
private RedisService redisService;
@Resource
private RedissonService redissonService;
@Around("@annotation(limitRepeatRequest)")
public Object around(ProceedingJoinPoint joinPoint, LimitRepeatRequest limitRepeatRequest) throws Throwable{
String key = getKey(joinPoint,limitRepeatRequest);
Object cacheObject = redisService.getCacheObject(key);
Object message;
if (Objects.nonNull(cacheObject)){
RLock rLock = redissonService.getRLock(key);
boolean flag = rLock.tryLock(0,limitRepeatRequest.time(), TimeUnit.SECONDS);
if (!flag){
if (StringUtils.isNotBlank(limitRepeatRequest.message())){
message = limitRepeatRequest.message();
throw new ServiceException(limitRepeatRequest.message(),ResponseEnum.REPEAT_REQUEST_ERROR.getCode());
}else {
message = new R().buildRepeatRequest(limitRepeatRequest.time());
throw new ServiceException(limitRepeatRequest.time()+"秒内"+ResponseEnum.REPEAT_REQUEST_ERROR.getMsg(),
ResponseEnum.REPEAT_REQUEST_ERROR.getCode());
}
}else {
redisService.setCacheObject(key,"1",(long)limitRepeatRequest.time(), TimeUnit.SECONDS);
message = joinPoint.proceed();
}
return message;
Object proceed = joinPoint.proceed();
return proceed;
}
/**
@ -63,13 +64,13 @@ public class LimitRepeatRequestAspect {
* @return
*/
private String getKey(ProceedingJoinPoint joinPoint, LimitRepeatRequest limitRepeatRequest) {
UserInfoVo userInfo = SecurityUtils.getUserInfo();
Method currentMethod = getCurrentMethod(joinPoint);
//最后拼接好的key
StringBuilder key = new StringBuilder("LimitRepeatRequestAspect#" + currentMethod.getName());
//限制范围
String userRange = limitRepeatRequest.userRange();
if (LimitRepeatRequest.SELF.equals(userRange)){
UserInfoVo userInfo = SecurityUtils.getUserInfo();
key.append("#");
key.append(userInfo.getUserClientType());
key.append("#");
@ -97,7 +98,7 @@ public class LimitRepeatRequestAspect {
String value = requestParams.containsKey(param)?requestParams.getString(param):"";
key.append(value);
}else if(obj instanceof Integer){
String value = requestParams.containsKey(param)?requestParams.getString(param):"";
String value = requestParams.containsKey(param)?String.valueOf(requestParams.getInteger(param)):"";
key.append(value);
}
}
@ -120,9 +121,7 @@ public class LimitRepeatRequestAspect {
private JSONObject getRequestParams(ProceedingJoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
if (args != null && args.length != 0){
String jsonString = JSON.toJSONString(args);
JSONArray parseArray = JSON.parseArray(jsonString);
return parseArray.getJSONObject(0);
return JSON.parseObject(args[0].toString());
}
return null;
}

2
bnyer-services/bnyer-order/src/main/java/com/bnyer/order/service/impl/VipOrderServiceImpl.java

@ -124,7 +124,7 @@ public class VipOrderServiceImpl extends ServiceImpl<VipOrderMapper, VipOrder> i
//查询会员信息
R<UserVipVo> userVipResult = remoteUserVipService.queryUserVip(addVipOrderDto.getVipId());
if (!userVipResult.isSuccess()){
log.error("内部接口调用异常:url:{}request{},result{},error:{}","queryUserVipList", addVipOrderDto.getVipId(),JSON.toJSONString(userVipResult),userVipResult.getMsg());
log.error("内部接口调用异常:url:{}request{},result{},error:{}","queryUserVip", addVipOrderDto.getVipId(),JSON.toJSONString(userVipResult),userVipResult.getMsg());
throw new ServiceException(userVipResult.getMsg());
}
UserVipVo userVipVo = userVipResult.getData();

2
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/annotation/LimitRepeatRequest.java

@ -31,7 +31,7 @@ public @interface LimitRepeatRequest {
* 当前时间内 api 只能请求一次单位秒
* @return
*/
int time() default 5;
long time() default 5;
/**
* 对部分参数做重复请求限制

37
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/aop/LimitRepeatRequestAspect.java

@ -4,11 +4,12 @@ import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bnyer.common.core.domain.R;
import com.bnyer.common.core.enums.ResponseEnum;
import com.bnyer.common.core.exception.ServiceException;
import com.bnyer.common.core.utils.MD5Util;
import com.bnyer.common.core.utils.StringUtils;
import com.bnyer.common.core.vo.UserInfoVo;
import com.bnyer.common.redis.service.RedisService;
import com.bnyer.common.redis.service.RedissonService;
import com.bnyer.common.security.utils.SecurityUtils;
import com.bnyer.pay.annotation.LimitRepeatRequest;
import lombok.extern.slf4j.Slf4j;
@ -17,9 +18,10 @@ import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.redisson.api.RLock;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@ -34,25 +36,24 @@ import java.util.concurrent.TimeUnit;
@Component
public class LimitRepeatRequestAspect {
@Autowired
private RedisService redisService;
@Resource
private RedissonService redissonService;
@Around("@annotation(limitRepeatRequest)")
public Object around(ProceedingJoinPoint joinPoint, LimitRepeatRequest limitRepeatRequest) throws Throwable{
String key = getKey(joinPoint,limitRepeatRequest);
Object cacheObject = redisService.getCacheObject(key);
Object message;
if (Objects.nonNull(cacheObject)){
RLock rLock = redissonService.getRLock(key);
boolean flag = rLock.tryLock(0,limitRepeatRequest.time(), TimeUnit.SECONDS);
if (!flag){
if (StringUtils.isNotBlank(limitRepeatRequest.message())){
message = limitRepeatRequest.message();
throw new ServiceException(limitRepeatRequest.message(),ResponseEnum.REPEAT_REQUEST_ERROR.getCode());
}else {
message = new R().buildRepeatRequest(limitRepeatRequest.time());
throw new ServiceException(limitRepeatRequest.time()+"秒内"+ResponseEnum.REPEAT_REQUEST_ERROR.getMsg(),
ResponseEnum.REPEAT_REQUEST_ERROR.getCode());
}
}else {
redisService.setCacheObject(key,"1",(long)limitRepeatRequest.time(), TimeUnit.SECONDS);
message = joinPoint.proceed();
}
return message;
Object proceed = joinPoint.proceed();
return proceed;
}
/**
@ -63,13 +64,13 @@ public class LimitRepeatRequestAspect {
* @return
*/
private String getKey(ProceedingJoinPoint joinPoint, LimitRepeatRequest limitRepeatRequest) {
UserInfoVo userInfo = SecurityUtils.getUserInfo();
Method currentMethod = getCurrentMethod(joinPoint);
//最后拼接好的key
StringBuilder key = new StringBuilder("LimitRepeatRequestAspect#" + currentMethod.getName());
//限制范围
String userRange = limitRepeatRequest.userRange();
if (LimitRepeatRequest.SELF.equals(userRange)){
UserInfoVo userInfo = SecurityUtils.getUserInfo();
key.append("#");
key.append(userInfo.getUserClientType());
key.append("#");
@ -97,7 +98,7 @@ public class LimitRepeatRequestAspect {
String value = requestParams.containsKey(param)?requestParams.getString(param):"";
key.append(value);
}else if(obj instanceof Integer){
String value = requestParams.containsKey(param)?requestParams.getString(param):"";
String value = requestParams.containsKey(param)?String.valueOf(requestParams.getInteger(param)):"";
key.append(value);
}
}
@ -120,9 +121,7 @@ public class LimitRepeatRequestAspect {
private JSONObject getRequestParams(ProceedingJoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
if (args != null && args.length != 0){
String jsonString = JSON.toJSONString(args);
JSONArray parseArray = JSON.parseArray(jsonString);
return parseArray.getJSONObject(0);
return JSON.parseObject(args[0].toString());
}
return null;
}

25
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/bean/bo/RefundBo.java

@ -14,4 +14,29 @@ import lombok.Setter;
@NoArgsConstructor
public class RefundBo {
/**
* 应用id
*/
private String appId;
/**
* 支付单号
*/
private String payId;
/**
* 退款单号
*/
private String refundNo;
/**
* 退款金额
*/
private String refundAmount;
/**
* 退款原因
*/
private String reason;
}

27
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/bean/vo/ThirdPayBaseVo.java

@ -0,0 +1,27 @@
package com.bnyer.pay.bean.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
* @author :WXC
* @Date :2023/05/15
* @description :
*/
@Getter
@Setter
public class ThirdPayBaseVo {
@ApiModelProperty(value="错误码")
private String thirdCode;
@ApiModelProperty(value="错误信息")
private String thirdMsg;
@ApiModelProperty(value="流水号")
private String thirdNo;
@ApiModelProperty(value = "完成时间")
private String successTime;
}

61
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/bean/vo/ThirdRefundVo.java

@ -1,10 +1,67 @@
package com.bnyer.pay.bean.vo;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
/**
* @author :WXC
* @Date :2023/05/08
* @description :
* @description :第三方支付退款信息
*/
@Getter
@Setter
public class ThirdRefundVo extends ThirdPayBaseVo{
/**
* 微信退款信息
*/
private WxRefundVo wxRefundVo;
/**
* 支付宝退款信息
*/
private AliRefundVo aliRefundVo;
/**
* 抖音退款信息
*/
public class ThirdRefundVo {
private DyRefundVo dyRefundVo;
/**
* 快手退款信息
*/
private KsRefundVo ksRefundVo;
@Data
public static class WxRefundVo{
/**
* 退款状态
* SUCCESS退款成功
* CLOSED退款关闭
* PROCESSING退款处理中
* ABNORMAL退款异常
*/
private String status;
/**
* 退款渠道
* ORIGINAL原路退款
* BALANCE退回到余额
* OTHER_BALANCE原账户异常退到其他余额账户
* OTHER_BANKCARD原银行卡异常退到其他银行卡
* 示例值ORIGINAdL
*/
private String channel;
}
@Data
public static class AliRefundVo{}
@Data
public static class DyRefundVo{}
@Data
public static class KsRefundVo{}
}

14
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/bean/vo/ThirdUnifiedOrderVo.java

@ -11,23 +11,15 @@ import java.io.Serializable;
* @Date :2023/04/03
* @description :统一第三方支付下单返回参数
*/
@Data
@Getter
@Setter
@NoArgsConstructor
public class ThirdUnifiedOrderVo implements Serializable {
public class ThirdUnifiedOrderVo extends ThirdPayBaseVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "应用id")
private String appId;
@ApiModelProperty(value="调用第三方下单返回")
private String thirdCode;
@ApiModelProperty(value="调用第三方下单返回")
private String thirdMsg;
@ApiModelProperty(value="调用第三方下单返回")
private String thirdNo;
@ApiModelProperty(value = "内部系统支付单号/开发者测单号")
private String outOrderNo;

2
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/bean/vo/UnifiedOrderVo.java

@ -38,7 +38,7 @@ public class UnifiedOrderVo {
private String nonceStr;
@ApiModelProperty(value = "会话标识")
private String packageValue;
@ApiModelProperty(value = "微信返回的字段")
@ApiModelProperty(value = "签名类型")
private String signType;
@ApiModelProperty(value = "签名")
private String paySign;

4
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/DYPayStrategy.java

@ -161,7 +161,7 @@ public class DYPayStrategy extends AbstractPayStrategy{
//保存预下单信息
ThirdUnifiedOrderVo.DyThirdInOrderVo dyThirdInOrderVo = new ThirdUnifiedOrderVo.DyThirdInOrderVo();
thirdUnifiedOrderVo.setOutOrderNo(bo.getPayId());
//把order_no和order_info_token返回前端用于调起收银台
//把order_id和order_token返回前端用于调起收银台
dyThirdInOrderVo.setOrderId(orderId);
dyThirdInOrderVo.setOrderToken(orderToken);
thirdUnifiedOrderVo.setDyThirdInOrderVo(dyThirdInOrderVo);
@ -188,7 +188,7 @@ public class DYPayStrategy extends AbstractPayStrategy{
//订单信息的json字符串
String message = object.getString("msg");
JSONObject msgJsonObj = JSON.parseObject(message);
log.info("快手支付:统一回调处理,params:{}",message);
log.info("抖音支付:统一回调处理,params:{}",message);
if (StringUtils.isBlank(msgSignature)) {
log.info("抖音支付回调参数丢失,payId:{}",object.getString("cp_orderno"));
return super.buildNotifyCheckResultMsg(EnumPayType.DY_PAY,false,"trade fail");

56
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/design/strategy/WxPayStrategy.java

@ -1,6 +1,7 @@
package com.bnyer.pay.design.strategy;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.bnyer.common.core.domain.WxpayConfig;
@ -15,22 +16,24 @@ import com.bnyer.pay.bean.bo.RefundBo;
import com.bnyer.pay.bean.bo.UnifiedOrderBo;
import com.bnyer.pay.bean.dto.EditPayInfoNotifyDto;
import com.bnyer.pay.bean.dto.PayNotifyCheckDto;
import com.bnyer.pay.bean.vo.ThirdQueryOrderVo;
import com.bnyer.pay.bean.vo.ThirdRefundVo;
import com.bnyer.pay.bean.vo.ThirdUnifiedOrderVo;
import com.bnyer.pay.enums.EnumPayChannel;
import com.bnyer.pay.enums.EnumTradeType;
import com.bnyer.pay.enums.EnumWxPayStatus;
import com.bnyer.pay.manager.WxPayManager;
import com.bnyer.pay.service.PayInfoService;
import com.bnyer.pay.utils.WXPayUtil;
import com.bnyer.pay.bean.vo.ThirdRefundVo;
import com.bnyer.pay.bean.vo.ThirdUnifiedOrderVo;
import com.bnyer.pay.bean.vo.ThirdQueryOrderVo;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryRequest;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.exception.WxPayException;
@ -39,7 +42,6 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.Map;
/**
@ -127,8 +129,8 @@ public class WxPayStrategy extends AbstractPayStrategy {
} catch (WxPayException e) {
log.error("微信支付:统一下单接口调用失败,payId:{},error{}", bo.getPayId(), e.getMessage());
thirdUnifiedOrderVo.setAppId(wxPayConfig.getAppid());
thirdUnifiedOrderVo.setThirdCode(e.getResultCode());
thirdUnifiedOrderVo.setThirdMsg(e.getMessage());
thirdUnifiedOrderVo.setThirdCode(e.getErrCode());
thirdUnifiedOrderVo.setThirdMsg(e.getErrCodeDes());
return thirdUnifiedOrderVo;
}
}
@ -227,6 +229,46 @@ public class WxPayStrategy extends AbstractPayStrategy {
@Override
public ThirdRefundVo refund(RefundBo bo) {
return null;
WxpayConfig config = wxPayManager.getWxPayConfigByAppId(bo.getAppId());
WxPayService wxPayService = wxPayManager.getWxPayService(config);
ThirdRefundVo thirdRefundVo = new ThirdRefundVo();
try {
WxPayRefundV3Request wxPayRefundV3Request = new WxPayRefundV3Request();
//退款金额
WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
amount.setRefund(Integer.parseInt(bo.getRefundAmount()));
wxPayRefundV3Request.setAmount(amount);
//退款单号
wxPayRefundV3Request.setOutRefundNo(bo.getRefundNo());
//退款原因
wxPayRefundV3Request.setReason(bo.getReason());
//支付单号
wxPayRefundV3Request.setOutTradeNo(bo.getPayId());
WxPayRefundV3Result wxPayRefundV3Result = wxPayService.refundV3(wxPayRefundV3Request);
//第三方返回
thirdRefundVo.setThirdCode("0");
thirdRefundVo.setThirdMsg("ok");
ThirdRefundVo.WxRefundVo wxRefundVo = new ThirdRefundVo.WxRefundVo();
wxRefundVo.setChannel(wxPayRefundV3Result.getChannel());
wxRefundVo.setStatus(wxPayRefundV3Result.getStatus());
thirdRefundVo.setThirdNo(wxPayRefundV3Result.getRefundId());
DateTime successTime = DateUtil.parse(wxPayRefundV3Result.getSuccessTime(), DatePattern.UTC_WITH_XXX_OFFSET_PATTERN);
thirdRefundVo.setSuccessTime(DateUtil.formatDateTime(successTime));
thirdRefundVo.setWxRefundVo(wxRefundVo);
return thirdRefundVo;
} catch (WxPayException e) {
log.error("微信支付:退款调用异常,payId:{},refundNo:{},error{}", bo.getPayId(),bo.getRefundNo(),e.getMessage());
thirdRefundVo.setThirdCode(e.getErrCode());
thirdRefundVo.setThirdMsg(e.getErrCodeDes());
return thirdRefundVo;
}
}
public static void main(String[] args) {
String st = "2020-12-01T16:18:12+08:00";
DateTime dateTime = DateUtil.parse(st, DatePattern.UTC_WITH_XXX_OFFSET_PATTERN);
System.out.println(DateUtil.format(dateTime, DatePattern.NORM_DATETIME_PATTERN));
}
}

2
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/enums/EnumVerificationKey.java

@ -13,7 +13,7 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
public enum EnumVerificationKey {
VIP("vip", "VipInOrder20230512Key"),
BNYER("bnyer", "BnyerInOrder20230512Key"),
;
private String key;
private String value;

16
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/service/impl/PayInfoServiceImpl.java

@ -48,22 +48,8 @@ public class PayInfoServiceImpl extends ServiceImpl<PayInfoMapper, PayInfo> impl
*/
@Override
public void addPayInfo(AddPayInfoDto dto) {
PayInfo oldPayInfo = payInfoMapper.selectOne(new LambdaQueryWrapper<PayInfo>().eq(PayInfo::getPayId, dto.getPayId()));
if (Objects.nonNull(oldPayInfo) && EnumPayStatus.SUCCESS.getStatus() == oldPayInfo.getPayStatus()){
throw new ServiceException(ResponseEnum.ORDER_REPEAT_PAY);
}
PayInfo payInfo;
if (Objects.isNull(oldPayInfo)){
payInfo = dto.toEntity();
}else {
payInfo = dto.toEntity();
payInfo.setId(oldPayInfo.getId());
}
if (payInfo.getId() == null){
PayInfo payInfo = dto.toEntity();
payInfoMapper.insert(payInfo);
}else {
payInfoMapper.updateById(payInfo);
}
}
/**

87
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/service/impl/UnifiedPayServiceImpl.java

@ -1,5 +1,8 @@
package com.bnyer.pay.service.impl;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bnyer.common.core.domain.PayInfo;
import com.bnyer.common.core.domain.R;
@ -15,6 +18,7 @@ import com.bnyer.order.api.bean.query.VipOrderExtQuery;
import com.bnyer.order.api.bean.vo.VipOrderVo;
import com.bnyer.order.api.remote.RemoteVipOrderService;
import com.bnyer.pay.bean.bo.QueryOrderBo;
import com.bnyer.pay.bean.bo.RefundBo;
import com.bnyer.pay.bean.bo.UnifiedOrderBo;
import com.bnyer.pay.bean.dto.AddPayInfoDto;
import com.bnyer.pay.bean.dto.QueryOrderDto;
@ -31,6 +35,7 @@ import com.bnyer.pay.enums.EnumWxPayStatus;
import com.bnyer.pay.mapper.PayInfoMapper;
import com.bnyer.pay.service.PayInfoService;
import com.bnyer.pay.service.UnifiedPayService;
import com.bnyer.pay.utils.MoneyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -169,7 +174,7 @@ public class UnifiedPayServiceImpl implements UnifiedPayService {
private UnifiedOrderBo buildUnifiedOrderDto(UnifiedOrderDto dto, String goodsDesc, int goodsType, String payAmount, String payId, HttpServletRequest request) {
UserInfoVo userInfo = SecurityUtils.getUserInfo();
String openId = dto.getOpenId();
if (StringUtils.isBlank(dto.getOpenId())){
if (StringUtils.isBlank(openId)){
openId = userInfo.getOpenId();
}
//当前时间
@ -249,9 +254,89 @@ public class UnifiedPayServiceImpl implements UnifiedPayService {
}
}
/**
* 退款
* @param dto
*/
@Override
public void refund(RefundDto dto) {
String payId = dto.getPayId();
PayInfo payInfo = getPayInfoByPayId(payId);
if (Objects.isNull(payInfo) || EnumPayStatus.FAILS.getStatus() == payInfo.getPayStatus()){
throw new ServiceException("支付订单数据有误,请联系管理员!");
}
int refundFen = Integer.parseInt(MoneyUtil.yuanToFen(dto.getRefundAmount().toString()));
int payAmountFen = Integer.parseInt(MoneyUtil.yuanToFen(payInfo.getPayAmount().toString()));
if (refundFen > payAmountFen){
throw new ServiceException("退款金额大于支付金额,无法退款,请联系管理员!");
}
String refundNo = dto.getPayId() + "Re";
PayInfo refundOrder = getPayInfoByPayId(refundNo);
if (Objects.nonNull(refundOrder) && EnumRefundStatus.SUCCESS.getStatus() == refundOrder.getRefundStatus()){
throw new ServiceException("该订单已退款,请勿重复操作!");
}
//调用第三方退款接口
IPayStrategy strategy = PayFactory.getInstance().getConcreteStrategy(payInfo.getPayType());
if (Objects.isNull(strategy)){
throw new ServiceException("暂不支持该支付方式的退款!");
}
RefundBo refundBo = buildUnifiedRefundBo(payInfo);
ThirdRefundVo thirdRefundVo = strategy.refund(refundBo);
//保存退款单信息
if (Objects.isNull(refundOrder)){
refundOrder = buildRefundOrder(thirdRefundVo,payInfo,dto);
}
//第三方下单返回
refundOrder.setThirdCode(thirdRefundVo.getThirdCode());
refundOrder.setThirdMsg(thirdRefundVo.getThirdMsg());
refundOrder.setThirdNo(thirdRefundVo.getThirdNo());
refundOrder.setRefundStatus(ObjectUtil.equal(thirdRefundVo.getThirdCode(),"0")?1002:1000);
payInfoMapper.insert(refundOrder);
if (!"0".equals(thirdRefundVo.getThirdCode())){
throw new ServiceException(thirdRefundVo.getThirdMsg());
}
}
/**
* 构建退款订单
* @param thirdRefundVo
* @param payInfo
* @param refundDto
*/
private PayInfo buildRefundOrder(ThirdRefundVo thirdRefundVo, PayInfo payInfo, RefundDto refundDto) {
PayInfo refundOrder = new PayInfo();
refundOrder.setRefundNo(refundDto.getPayId() + "Re");
refundOrder.setOrderNo(payInfo.getOrderNo());
refundOrder.setPayId(payInfo.getPayId());
refundOrder.setAppid(payInfo.getAppid());
refundOrder.setPayAmount(payInfo.getPayAmount());
refundOrder.setRefundAmount(refundDto.getRefundAmount());
if (StringUtils.isNotBlank(thirdRefundVo.getSuccessTime())){
refundOrder.setRefundTime(DateUtil.parse(thirdRefundVo.getSuccessTime(), DatePattern.NORM_DATETIME_PATTERN));
}
return refundOrder;
}
/**
* 构建统一退款请求实体
* @param payInfo
* @return
*/
private RefundBo buildUnifiedRefundBo(PayInfo payInfo) {
RefundBo refundBo = new RefundBo();
refundBo.setAppId(payInfo.getAppid());
return refundBo;
}
/**
* 通过支付单号/退款单号查询订单
* @param payId
* @return
*/
private PayInfo getPayInfoByPayId(String payId) {
PayInfo payInfo = payInfoMapper.selectOne(new LambdaQueryWrapper<PayInfo>().eq(PayInfo::getPayId, payId));
return payInfo;
}
}

8
bnyer-services/bnyer-pay/src/main/java/com/bnyer/pay/utils/PaymentRefundUtil.java

@ -17,7 +17,7 @@ public class PaymentRefundUtil {
* @return
*/
public static String getSign(RefundDto dto) {
return MD5Util.getMD5String(dto.getPayId() + EnumVerificationKey.VIP.getValue());
return MD5Util.getMD5String(dto.getPayId() + EnumVerificationKey.BNYER.getValue());
}
/**
@ -27,13 +27,13 @@ public class PaymentRefundUtil {
*/
public static boolean checkSign(RefundDto dto) {
return MD5Util.getMD5String(dto.getPayId() + EnumVerificationKey.VIP.getValue()).equals(dto.getSign());
return MD5Util.getMD5String(dto.getPayId() + EnumVerificationKey.BNYER.getValue()).equals(dto.getSign());
}
public static void main(String[] args) {
String sign = MD5Util.getMD5String("RVWU202305121022211042" + EnumVerificationKey.VIP.getValue());
String sign = MD5Util.getMD5String("RVWU202305121022211042" + EnumVerificationKey.BNYER.getValue());
System.out.println(sign);
System.out.println(MD5Util.getMD5String("RVWU202305121022211042" + EnumVerificationKey.VIP.getValue()).equals(sign));
System.out.println(MD5Util.getMD5String("RVWU202305121022211042" + EnumVerificationKey.BNYER.getValue()).equals(sign));
}
}

Loading…
Cancel
Save