Commit 67aaf28832bd86a75e6fd9b54e286f7a94768428
1 parent
d556eae5
code review 退款逻辑
Showing
10 changed files
with
67 additions
and
52 deletions
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/convert/order/PayRefundCoreConvert.java
| ... | ... | @@ -12,8 +12,6 @@ public interface PayRefundCoreConvert { |
| 12 | 12 | |
| 13 | 13 | PayRefundCoreConvert INSTANCE = Mappers.getMapper(PayRefundCoreConvert.class); |
| 14 | 14 | |
| 15 | - | |
| 16 | - | |
| 17 | 15 | //TODO 太多需要处理了, 暂时不用 |
| 18 | 16 | @Mappings(value = { |
| 19 | 17 | @Mapping(source = "amount", target = "payAmount"), |
| ... | ... | @@ -21,4 +19,5 @@ public interface PayRefundCoreConvert { |
| 21 | 19 | @Mapping(target = "status",ignore = true) |
| 22 | 20 | }) |
| 23 | 21 | PayRefundDO convert(PayOrderDO orderDO); |
| 22 | + | |
| 24 | 23 | } | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/order/PayRefundDO.java
| ... | ... | @@ -3,6 +3,8 @@ package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order; |
| 3 | 3 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; |
| 4 | 4 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; |
| 5 | 5 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; |
| 6 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum; | |
| 7 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum; | |
| 6 | 8 | import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; |
| 7 | 9 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 8 | 10 | import com.baomidou.mybatisplus.annotation.TableId; |
| ... | ... | @@ -79,7 +81,6 @@ public class PayRefundDO extends BaseDO { |
| 79 | 81 | */ |
| 80 | 82 | private Long orderId; |
| 81 | 83 | |
| 82 | - | |
| 83 | 84 | /** |
| 84 | 85 | * 交易订单号,根据规则生成 |
| 85 | 86 | * 调用支付渠道时,使用该字段作为对接的订单号。 |
| ... | ... | @@ -110,7 +111,6 @@ public class PayRefundDO extends BaseDO { |
| 110 | 111 | * 防止该笔交易重复退款。支付宝会保证同样的退款请求号多次请求只会退一次。 |
| 111 | 112 | * 退款单请求号,根据规则生成 |
| 112 | 113 | * 例如说,R202109181134287570000 |
| 113 | - * | |
| 114 | 114 | */ |
| 115 | 115 | private String merchantRefundNo; |
| 116 | 116 | |
| ... | ... | @@ -129,19 +129,22 @@ public class PayRefundDO extends BaseDO { |
| 129 | 129 | /** |
| 130 | 130 | * 退款状态 |
| 131 | 131 | * |
| 132 | + * 枚举 {@link PayRefundStatusEnum} | |
| 132 | 133 | */ |
| 133 | 134 | private Integer status; |
| 134 | 135 | |
| 135 | 136 | /** |
| 136 | 137 | * 退款类型(部分退款,全部退款) |
| 138 | + * | |
| 139 | + * 枚举 {@link PayRefundTypeEnum} | |
| 137 | 140 | */ |
| 138 | 141 | private Integer type; |
| 139 | 142 | /** |
| 140 | - * 支付金额,单位分 | |
| 143 | + * 支付金额,单位:分 | |
| 141 | 144 | */ |
| 142 | 145 | private Long payAmount; |
| 143 | 146 | /** |
| 144 | - * 退款金额,单位分 | |
| 147 | + * 退款金额,单位:分 | |
| 145 | 148 | */ |
| 146 | 149 | private Long refundAmount; |
| 147 | 150 | |
| ... | ... | @@ -150,7 +153,6 @@ public class PayRefundDO extends BaseDO { |
| 150 | 153 | */ |
| 151 | 154 | private String reason; |
| 152 | 155 | |
| 153 | - | |
| 154 | 156 | /** |
| 155 | 157 | * 用户 IP |
| 156 | 158 | */ | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/order/PayRefundCoreMapper.java
| ... | ... | @@ -17,6 +17,7 @@ public interface PayRefundCoreMapper extends BaseMapperX<PayRefundDO> { |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | 19 | default PayRefundDO selectByTradeNoAndMerchantRefundNo(String tradeNo, String merchantRefundNo){ |
| 20 | - return selectOne("trade_no", tradeNo, "merchant_refund_no", merchantRefundNo); | |
| 20 | + return selectOne("trade_no", tradeNo, "merchant_refund_no", merchantRefundNo); | |
| 21 | 21 | } |
| 22 | + | |
| 22 | 23 | } | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayRefundStatusEnum.java
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayRefundReqDTO.java
| ... | ... | @@ -16,8 +16,9 @@ import lombok.experimental.Accessors; |
| 16 | 16 | @AllArgsConstructor |
| 17 | 17 | public class PayRefundReqDTO { |
| 18 | 18 | |
| 19 | + // TODO @jason:增加下 validation 注解哈 | |
| 19 | 20 | /** |
| 20 | - * 支付订单编号自增 | |
| 21 | + * 支付订单编号 | |
| 21 | 22 | */ |
| 22 | 23 | private Long payOrderId; |
| 23 | 24 | |
| ... | ... | @@ -31,10 +32,10 @@ public class PayRefundReqDTO { |
| 31 | 32 | */ |
| 32 | 33 | private String reason; |
| 33 | 34 | |
| 34 | - | |
| 35 | 35 | /** |
| 36 | 36 | * 商户退款订单号 |
| 37 | 37 | */ |
| 38 | + // TODO @jason:merchantRefundNo=》merchantRefundId,保持和 PayOrder 的 merchantOrderId 一致哈 | |
| 38 | 39 | private String merchantRefundNo; |
| 39 | 40 | |
| 40 | 41 | /** | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayRefundRespDTO.java
| ... | ... | @@ -21,10 +21,11 @@ public class PayRefundRespDTO { |
| 21 | 21 | * 退款处理中和退款成功 返回 1 |
| 22 | 22 | * 失败和其他情况 返回 2 |
| 23 | 23 | */ |
| 24 | + // TODO @jason:这个 result,可以使用 CommonResult 里呢 | |
| 24 | 25 | private Integer channelReturnResult; |
| 25 | 26 | |
| 26 | 27 | /** |
| 27 | - * 渠道返回code | |
| 28 | + * 渠道返回 code | |
| 28 | 29 | */ |
| 29 | 30 | private String channelReturnCode; |
| 30 | 31 | |
| ... | ... | @@ -34,7 +35,8 @@ public class PayRefundRespDTO { |
| 34 | 35 | private String channelReturnMsg; |
| 35 | 36 | |
| 36 | 37 | /** |
| 37 | - * 支付退款单编号, 自增 | |
| 38 | + * 支付退款单编号,自增 | |
| 38 | 39 | */ |
| 39 | 40 | private Long refundId; |
| 41 | + | |
| 40 | 42 | } | ... | ... |
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayRefundCoreServiceImpl.java
| ... | ... | @@ -11,20 +11,20 @@ import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderExtensio |
| 11 | 11 | import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayRefundCoreMapper; |
| 12 | 12 | import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyTypeEnum; |
| 13 | 13 | import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum; |
| 14 | -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService; | |
| 15 | -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; | |
| 16 | -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundReqDTO; | |
| 17 | -import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundNotifyDTO; | |
| 18 | -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum; | |
| 19 | 14 | import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum; |
| 20 | 15 | import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum; |
| 16 | +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum; | |
| 21 | 17 | import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayAppCoreService; |
| 22 | 18 | import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayChannelCoreService; |
| 19 | +import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService; | |
| 20 | +import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; | |
| 23 | 21 | import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundCoreService; |
| 22 | +import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundReqDTO; | |
| 24 | 23 | import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundRespDTO; |
| 25 | 24 | import cn.iocoder.yudao.framework.pay.core.client.PayClient; |
| 26 | 25 | import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; |
| 27 | 26 | import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; |
| 27 | +import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundNotifyDTO; | |
| 28 | 28 | import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedReqDTO; |
| 29 | 29 | import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedRespDTO; |
| 30 | 30 | import cn.iocoder.yudao.framework.pay.core.enums.PayChannelRefundRespEnum; |
| ... | ... | @@ -34,7 +34,8 @@ import org.springframework.stereotype.Service; |
| 34 | 34 | import org.springframework.transaction.annotation.Transactional; |
| 35 | 35 | |
| 36 | 36 | import javax.annotation.Resource; |
| 37 | -import java.util.*; | |
| 37 | +import java.util.Date; | |
| 38 | +import java.util.Objects; | |
| 38 | 39 | |
| 39 | 40 | import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*; |
| 40 | 41 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| ... | ... | @@ -90,17 +91,19 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService { |
| 90 | 91 | |
| 91 | 92 | PayOrderExtensionDO orderExtensionDO = payOrderExtensionCoreMapper.selectById(order.getSuccessExtensionId()); |
| 92 | 93 | PayRefundDO payRefundDO = payRefundCoreMapper.selectByTradeNoAndMerchantRefundNo(orderExtensionDO.getNo(), req.getMerchantRefundNo()); |
| 93 | - //构造渠道的统一的退款请求参数 | |
| 94 | + // 构造渠道的统一的退款请求参数 | |
| 94 | 95 | PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO(); |
| 95 | 96 | if(Objects.nonNull(payRefundDO)){ |
| 96 | - //退款订单已经提交过。 | |
| 97 | + // 退款订单已经提交过。 | |
| 97 | 98 | //TODO 校验相同退款单的金额 |
| 98 | - if(Objects.equals(PayRefundStatusEnum.SUCCESS.getStatus(), payRefundDO.getStatus()) | |
| 99 | - || Objects.equals(PayRefundStatusEnum.CLOSE.getStatus(), payRefundDO.getStatus())){ | |
| 99 | + // TODO @jason:咱要不封装一个 ObjectUtils.equalsAny | |
| 100 | + if (Objects.equals(PayRefundStatusEnum.SUCCESS.getStatus(), payRefundDO.getStatus()) | |
| 101 | + || Objects.equals(PayRefundStatusEnum.CLOSE.getStatus(), payRefundDO.getStatus())) { | |
| 100 | 102 | //已成功退款 |
| 101 | 103 | throw exception(PAY_REFUND_SUCCEED); |
| 102 | - }else{ | |
| 103 | - //保证商户退款单不变,重复向渠道发起退款。渠道保持幂等 | |
| 104 | + } else{ | |
| 105 | + // TODO @jason:这里不用 else,简洁一些 | |
| 106 | + // 保证商户退款单不变,重复向渠道发起退款。渠道保持幂等 | |
| 104 | 107 | unifiedReqDTO.setUserIp(req.getUserIp()) |
| 105 | 108 | .setAmount(payRefundDO.getRefundAmount()) |
| 106 | 109 | .setChannelOrderNo(payRefundDO.getChannelOrderNo()) |
| ... | ... | @@ -109,7 +112,8 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService { |
| 109 | 112 | .setReason(payRefundDO.getReason()); |
| 110 | 113 | } |
| 111 | 114 | }else{ |
| 112 | - //新生成退款单。 退款单入库 退款单状态:生成 | |
| 115 | + // 新生成退款单。 退款单入库 退款单状态:生成 | |
| 116 | + // TODO @jason:封装一个小方法。插入退款单 | |
| 113 | 117 | payRefundDO = PayRefundDO.builder().channelOrderNo(order.getChannelOrderNo()) |
| 114 | 118 | .appId(order.getAppId()) |
| 115 | 119 | .channelOrderNo(order.getChannelOrderNo()) |
| ... | ... | @@ -130,6 +134,7 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService { |
| 130 | 134 | .type(refundType.getStatus()) |
| 131 | 135 | .build(); |
| 132 | 136 | payRefundCoreMapper.insert(payRefundDO); |
| 137 | + // TODO @jason:这块的逻辑,和已存在的这块,貌似是统一的? | |
| 133 | 138 | unifiedReqDTO.setUserIp(req.getUserIp()) |
| 134 | 139 | .setAmount(payRefundDO.getRefundAmount()) |
| 135 | 140 | .setChannelOrderNo(payRefundDO.getChannelOrderNo()) |
| ... | ... | @@ -137,19 +142,20 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService { |
| 137 | 142 | .setRefundReqNo(payRefundDO.getMerchantRefundNo()) |
| 138 | 143 | .setReason(req.getReason()); |
| 139 | 144 | } |
| 140 | - //向渠道发起退款申请 | |
| 145 | + // 向渠道发起退款申请 | |
| 141 | 146 | PayRefundUnifiedRespDTO refundUnifiedRespDTO = client.unifiedRefund(unifiedReqDTO); |
| 142 | - //构造退款申请返回对象 | |
| 147 | + // 构造退款申请返回对象 | |
| 143 | 148 | PayRefundRespDTO respDTO = new PayRefundRespDTO(); |
| 144 | - if(refundUnifiedRespDTO.getChannelResp() == PayChannelRefundRespEnum.SUCCESS | |
| 145 | - ||refundUnifiedRespDTO.getChannelResp() == PayChannelRefundRespEnum.PROCESSING ){ | |
| 146 | - //成功处理, 在退款通知中处理, 这里不处理 | |
| 149 | + if (refundUnifiedRespDTO.getChannelResp() == PayChannelRefundRespEnum.SUCCESS | |
| 150 | + ||refundUnifiedRespDTO.getChannelResp() == PayChannelRefundRespEnum.PROCESSING) { | |
| 151 | + // 成功处理,在退款通知中处理, 这里不处理 | |
| 147 | 152 | respDTO.setChannelReturnResult(PayChannelRefundRespEnum.SUCCESS.getStatus()); |
| 148 | 153 | respDTO.setRefundId(payRefundDO.getId()); |
| 149 | 154 | }else { |
| 150 | - //失败返回错误给前端,可以重新发起退款,保证退款请求号(这里是商户退款单号), 避免重复退款。 | |
| 155 | + // 失败返回错误给前端,可以重新发起退款,保证退款请求号(这里是商户退款单号), 避免重复退款。 | |
| 156 | + // TODO @jason:失败的话,是不是可以跑出 ServiceException 业务异常。这样就是成功返回 refundId,失败业务异常 | |
| 151 | 157 | respDTO.setChannelReturnResult(PayChannelRefundRespEnum.FAILURE.getStatus()); |
| 152 | - //更新退款单状态 | |
| 158 | + // 更新退款单状态 | |
| 153 | 159 | PayRefundDO updatePayRefund = new PayRefundDO(); |
| 154 | 160 | updatePayRefund.setId(payRefundDO.getId()) |
| 155 | 161 | .setChannelErrorMsg(refundUnifiedRespDTO.getChannelMsg()) |
| ... | ... | @@ -181,35 +187,37 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService { |
| 181 | 187 | payRefundSuccess(refundNotify); |
| 182 | 188 | } else { |
| 183 | 189 | //TODO 支付异常, 支付宝似乎没有支付异常的通知。 |
| 190 | + // TODO @jason:那这里可以考虑打个 error logger | |
| 184 | 191 | } |
| 185 | 192 | } |
| 186 | 193 | |
| 187 | 194 | private void payRefundSuccess(PayRefundNotifyDTO refundNotify) { |
| 195 | + // 校验退款单存在 | |
| 188 | 196 | PayRefundDO refundDO = payRefundCoreMapper.selectByTradeNoAndMerchantRefundNo(refundNotify.getTradeNo(), refundNotify.getReqNo()); |
| 189 | 197 | if (refundDO == null) { |
| 190 | - log.error("不存在 seqNo 为{} 的支付退款单",refundNotify.getReqNo()); | |
| 198 | + log.error("[payRefundSuccess][不存在 seqNo 为{} 的支付退款单]", refundNotify.getReqNo()); | |
| 191 | 199 | throw exception(PAY_REFUND_NOT_FOUND); |
| 192 | 200 | } |
| 193 | - Long refundAmount = refundDO.getRefundAmount(); | |
| 201 | + | |
| 202 | + // 计算订单的状态。如果全部退款,则订单处于关闭。TODO @jason:建议这里按照金额来判断,因为可能退款多次 | |
| 194 | 203 | Integer type = refundDO.getType(); |
| 195 | 204 | PayOrderStatusEnum orderStatus = PayOrderStatusEnum.SUCCESS; |
| 196 | - if(PayRefundTypeEnum.ALL.getStatus().equals(type)){ | |
| 205 | + if (PayRefundTypeEnum.ALL.getStatus().equals(type)){ | |
| 197 | 206 | orderStatus = PayOrderStatusEnum.CLOSED; |
| 198 | 207 | } |
| 199 | - // 更新支付订单 | |
| 200 | - PayOrderDO payOrderDO = payOrderCoreMapper.selectById(refundDO.getOrderId()); | |
| 201 | 208 | // 需更新已退金额 |
| 209 | + PayOrderDO payOrderDO = payOrderCoreMapper.selectById(refundDO.getOrderId()); | |
| 202 | 210 | Long refundedAmount = payOrderDO.getRefundAmount(); |
| 211 | + // 更新支付订单 | |
| 203 | 212 | PayOrderDO updateOrderDO = new PayOrderDO(); |
| 204 | 213 | updateOrderDO.setId(refundDO.getOrderId()) |
| 205 | - .setRefundAmount(refundedAmount + refundAmount) | |
| 214 | + .setRefundAmount(refundedAmount + refundDO.getRefundAmount()) | |
| 206 | 215 | .setStatus(orderStatus.getStatus()) |
| 207 | - .setRefundTimes(payOrderDO.getRefundTimes()+1) | |
| 216 | + .setRefundTimes(payOrderDO.getRefundTimes() + 1) | |
| 208 | 217 | .setRefundStatus(type); |
| 209 | - | |
| 210 | 218 | payOrderCoreMapper.updateById(updateOrderDO); |
| 211 | 219 | |
| 212 | - // 跟新退款订单 | |
| 220 | + // 更新退款订单 | |
| 213 | 221 | PayRefundDO updateRefundDO = new PayRefundDO(); |
| 214 | 222 | updateRefundDO.setId(refundDO.getId()) |
| 215 | 223 | .setSuccessTime(refundNotify.getRefundSuccessTime()) |
| ... | ... | @@ -219,7 +227,7 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService { |
| 219 | 227 | .setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); |
| 220 | 228 | payRefundCoreMapper.updateById(updateRefundDO); |
| 221 | 229 | |
| 222 | - //插入退款通知记录 | |
| 230 | + // 插入退款通知记录 | |
| 223 | 231 | // TODO 通知商户成功或者失败. 现在通知似乎没有实现, 只是回调 |
| 224 | 232 | payNotifyCoreService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() |
| 225 | 233 | .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refundDO.getId()).build()); |
| ... | ... | @@ -235,12 +243,12 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService { |
| 235 | 243 | if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) { |
| 236 | 244 | throw exception(PAY_ORDER_STATUS_IS_NOT_SUCCESS); |
| 237 | 245 | } |
| 238 | - //是否已经全额退款 | |
| 246 | + // 是否已经全额退款 | |
| 239 | 247 | if (PayRefundTypeEnum.ALL.getStatus().equals(order.getRefundStatus())) { |
| 240 | 248 | throw exception(PAY_REFUND_ALL_REFUNDED); |
| 241 | 249 | } |
| 242 | 250 | // 校验金额 退款金额不能大于 原定的金额 |
| 243 | - if(req.getAmount() + order.getRefundAmount() > order.getAmount()){ | |
| 251 | + if (req.getAmount() + order.getRefundAmount() > order.getAmount()){ | |
| 244 | 252 | throw exception(PAY_REFUND_AMOUNT_EXCEED); |
| 245 | 253 | } |
| 246 | 254 | // 校验渠道订单号 | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundUnifiedReqDTO.java
| ... | ... | @@ -28,6 +28,7 @@ public class PayRefundUnifiedReqDTO { |
| 28 | 28 | */ |
| 29 | 29 | private String userIp; |
| 30 | 30 | |
| 31 | + // TODO @jason:这个是否为非必传字段呀,只需要传递 payTradeNo 字段即可。尽可能精简 | |
| 31 | 32 | /** |
| 32 | 33 | * https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 transaction_id |
| 33 | 34 | * https://opendocs.alipay.com/apis alipay.trade.refund 中的 trade_no |
| ... | ... | @@ -35,7 +36,6 @@ public class PayRefundUnifiedReqDTO { |
| 35 | 36 | */ |
| 36 | 37 | private String channelOrderNo; |
| 37 | 38 | |
| 38 | - | |
| 39 | 39 | /** |
| 40 | 40 | * https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_trade_no |
| 41 | 41 | * https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_trade_no |
| ... | ... | @@ -43,24 +43,22 @@ public class PayRefundUnifiedReqDTO { |
| 43 | 43 | */ |
| 44 | 44 | private String payTradeNo; |
| 45 | 45 | |
| 46 | - | |
| 46 | + // TODO @jason:这个字段,要不就使用 merchantRefundId,更直接 | |
| 47 | 47 | /** |
| 48 | 48 | * https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_refund_no |
| 49 | - * https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_request_no | |
| 49 | + * https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_trade_no | |
| 50 | 50 | * 退款请求单号 同一退款请求单号多次请求只退一笔。 |
| 51 | 51 | * 使用 商户的退款单号。{PayRefundDO 字段 merchantRefundNo} |
| 52 | 52 | */ |
| 53 | 53 | @NotEmpty(message = "退款请求单号") |
| 54 | 54 | private String refundReqNo; |
| 55 | 55 | |
| 56 | - | |
| 57 | 56 | /** |
| 58 | 57 | * 退款原因 |
| 59 | 58 | */ |
| 60 | 59 | @NotEmpty(message = "退款原因不能为空") |
| 61 | 60 | private String reason; |
| 62 | 61 | |
| 63 | - | |
| 64 | 62 | /** |
| 65 | 63 | * 退款金额,单位:分 |
| 66 | 64 | */ |
| ... | ... | @@ -68,12 +66,10 @@ public class PayRefundUnifiedReqDTO { |
| 68 | 66 | @DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零") |
| 69 | 67 | private Long amount; |
| 70 | 68 | |
| 71 | - | |
| 72 | - | |
| 73 | - | |
| 74 | 69 | /** |
| 75 | 70 | * 退款结果 notify 回调地址, 支付宝退款不需要回调地址, 微信需要 |
| 76 | 71 | */ |
| 77 | 72 | @URL(message = "支付结果的 notify 回调地址必须是 URL 格式") |
| 78 | 73 | private String notifyUrl; |
| 74 | + | |
| 79 | 75 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundUnifiedRespDTO.java
| ... | ... | @@ -17,11 +17,14 @@ import lombok.experimental.Accessors; |
| 17 | 17 | @AllArgsConstructor |
| 18 | 18 | @Data |
| 19 | 19 | public class PayRefundUnifiedRespDTO { |
| 20 | + | |
| 21 | + // TODO @jason:可以合并下。退款处理中、成功,都是成功;其它就业务失败。这样,可以复用 PayCommonResult;这个 RespDTO 可以返回渠道的退款编号 | |
| 20 | 22 | /** |
| 21 | 23 | * 渠道的退款结果 |
| 22 | 24 | */ |
| 23 | 25 | private PayChannelRefundRespEnum channelResp; |
| 24 | 26 | |
| 27 | + // TODO @json:channelReturnCode 和 channelReturnMsg 放到 PayCommonResult 里噶 | |
| 25 | 28 | /** |
| 26 | 29 | * 渠道返回码 |
| 27 | 30 | */ | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelRefundRespEnum.java
| ... | ... | @@ -11,6 +11,7 @@ import lombok.Getter; |
| 11 | 11 | @Getter |
| 12 | 12 | @AllArgsConstructor |
| 13 | 13 | public enum PayChannelRefundRespEnum { |
| 14 | + | |
| 14 | 15 | SUCCESS(1, "退款成功"), |
| 15 | 16 | FAILURE(2, "退款失败"), |
| 16 | 17 | PROCESSING(3,"退款处理中"), |
| ... | ... | @@ -18,4 +19,5 @@ public enum PayChannelRefundRespEnum { |
| 18 | 19 | |
| 19 | 20 | private final Integer status; |
| 20 | 21 | private final String name; |
| 22 | + | |
| 21 | 23 | } | ... | ... |