mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-01-31 09:30:05 +08:00
mall + pay:
1. 完成支付宝的退款重构 2. 完成 demo 模块的退款接入
This commit is contained in:
parent
518e89dc4b
commit
c44ace6011
@ -20,6 +20,13 @@ public class PayRefundRespDTO {
|
|||||||
*/
|
*/
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部退款号
|
||||||
|
*
|
||||||
|
* 对应 PayRefundDO 的 no 字段
|
||||||
|
*/
|
||||||
|
private String outRefundNo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渠道退款单号
|
* 渠道退款单号
|
||||||
*
|
*
|
||||||
|
@ -68,7 +68,6 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
|
|||||||
model.setOutTradeNo(reqDTO.getOutTradeNo());
|
model.setOutTradeNo(reqDTO.getOutTradeNo());
|
||||||
model.setOutRequestNo(reqDTO.getOutRefundNo());
|
model.setOutRequestNo(reqDTO.getOutRefundNo());
|
||||||
model.setRefundAmount(formatAmount(reqDTO.getPrice()));
|
model.setRefundAmount(formatAmount(reqDTO.getPrice()));
|
||||||
// model.setRefundAmount(formatAmount(reqDTO.getPrice() / 2));
|
|
||||||
model.setRefundReason(reqDTO.getReason());
|
model.setRefundReason(reqDTO.getReason());
|
||||||
// 1.2 构建 AlipayTradePayRequest 请求
|
// 1.2 构建 AlipayTradePayRequest 请求
|
||||||
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
|
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
|
||||||
@ -77,6 +76,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
|
|||||||
// 2.1 执行请求
|
// 2.1 执行请求
|
||||||
AlipayTradeRefundResponse response = client.execute(request);
|
AlipayTradeRefundResponse response = client.execute(request);
|
||||||
PayRefundRespDTO refund = new PayRefundRespDTO()
|
PayRefundRespDTO refund = new PayRefundRespDTO()
|
||||||
|
.setOutRefundNo(reqDTO.getOutRefundNo())
|
||||||
.setRawData(response);
|
.setRawData(response);
|
||||||
// 支付宝只要退款调用返回 success,就认为退款成功,不需要回调。具体可见 parseNotify 方法的说明。
|
// 支付宝只要退款调用返回 success,就认为退款成功,不需要回调。具体可见 parseNotify 方法的说明。
|
||||||
// 另外,支付宝没有退款单号,所以不用设置
|
// 另外,支付宝没有退款单号,所以不用设置
|
||||||
|
@ -27,26 +27,32 @@ public class PayRefundCreateReqDTO {
|
|||||||
private String userIp;
|
private String userIp;
|
||||||
|
|
||||||
// ========== 商户相关字段 ==========
|
// ========== 商户相关字段 ==========
|
||||||
|
/**
|
||||||
|
* 商户订单编号
|
||||||
|
*/
|
||||||
|
@NotEmpty(message = "商户订单编号不能为空")
|
||||||
|
private String merchantOrderId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户退款编号
|
||||||
|
*/
|
||||||
|
@NotEmpty(message = "商户退款编号不能为空")
|
||||||
|
private String merchantRefundId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款描述
|
* 退款描述
|
||||||
*/
|
*/
|
||||||
@NotEmpty(message = "退款描述不能为空")
|
@NotEmpty(message = "退款描述不能为空")
|
||||||
@Length(max = 128, message = "退款描述长度不能超过128")
|
@Length(max = 128, message = "退款描述长度不能超过 128")
|
||||||
private String reason;
|
private String reason;
|
||||||
|
|
||||||
// ========== 订单相关字段 ==========
|
// ========== 订单相关字段 ==========
|
||||||
|
|
||||||
/**
|
|
||||||
* 支付单号
|
|
||||||
*/
|
|
||||||
@NotNull(message = "支付单号不能为空")
|
|
||||||
private Long payOrderId;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款金额,单位:分
|
* 退款金额,单位:分
|
||||||
*/
|
*/
|
||||||
@NotNull(message = "退款金额不能为空")
|
@NotNull(message = "退款金额不能为空")
|
||||||
@Min(value = 1, message = "退款金额必须大于零")
|
@Min(value = 1, message = "退款金额必须大于零")
|
||||||
private Integer price;
|
private Integer price;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,11 +33,12 @@ public interface ErrorCodeConstants {
|
|||||||
ErrorCode PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付");
|
ErrorCode PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING = new ErrorCode(1007003001, "支付交易拓展单不处于待支付");
|
||||||
|
|
||||||
// ========== 支付模块(退款) 1007006000 ==========
|
// ========== 支付模块(退款) 1007006000 ==========
|
||||||
ErrorCode PAY_PRICE_PRICE_EXCEED = new ErrorCode(1007006000, "退款金额超过订单可退款金额");
|
ErrorCode PAY_REFUND_PRICE_EXCEED = new ErrorCode(1007006000, "退款金额超过订单可退款金额");
|
||||||
ErrorCode PAY_REFUND_ALL_REFUNDED = new ErrorCode(1007006001, "订单已经全额退款");
|
ErrorCode PAY_REFUND_ALL_REFUNDED = new ErrorCode(1007006001, "订单已经全额退款");
|
||||||
ErrorCode PAY_REFUND_CHN_ORDER_NO_IS_NULL = new ErrorCode(1007006002, "该订单的渠道订单为空");
|
ErrorCode PAY_REFUND_HAS_REFUNDING = new ErrorCode(1007006002, "已经有退款在处理中");
|
||||||
ErrorCode PAY_REFUND_SUCCEED = new ErrorCode(1007006003, "已经退款成功");
|
ErrorCode PAY_REFUND_EXISTS = new ErrorCode(1007006003, "已经存在退款单");
|
||||||
ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在");
|
ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在");
|
||||||
|
ErrorCode PAY_REFUND_STATUS_IS_NOT_WAITING = new ErrorCode(1007006005, "支付退款单不处于待退款");
|
||||||
|
|
||||||
// ========== 示例订单 1007900000 ==========
|
// ========== 示例订单 1007900000 ==========
|
||||||
ErrorCode PAY_DEMO_ORDER_NOT_FOUND = new ErrorCode(1007900000, "示例订单不存在");
|
ErrorCode PAY_DEMO_ORDER_NOT_FOUND = new ErrorCode(1007900000, "示例订单不存在");
|
||||||
|
@ -38,4 +38,14 @@ public enum PayOrderStatusEnum implements IntArrayValuable {
|
|||||||
return Objects.equals(status, SUCCESS.getStatus());
|
return Objects.equals(status, SUCCESS.getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否支付关闭
|
||||||
|
*
|
||||||
|
* @param status 状态
|
||||||
|
* @return 是否支付关闭
|
||||||
|
*/
|
||||||
|
public static boolean isClosed(Integer status) {
|
||||||
|
return Objects.equals(status, CLOSED.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ public class PayOrderApiImpl implements PayOrderApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long createOrder(PayOrderCreateReqDTO reqDTO) {
|
public Long createOrder(PayOrderCreateReqDTO reqDTO) {
|
||||||
return payOrderService.createPayOrder(reqDTO);
|
return payOrderService.createOrder(reqDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.api.refund;
|
|||||||
|
|
||||||
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
|
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
|
||||||
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
|
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.pay.convert.refund.PayRefundConvert;
|
||||||
import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
|
import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@ -27,8 +28,7 @@ public class PayRefundApiImpl implements PayRefundApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PayRefundRespDTO getPayRefund(Long id) {
|
public PayRefundRespDTO getPayRefund(Long id) {
|
||||||
// TODO 芋艿:暂未实现
|
return PayRefundConvert.INSTANCE.convert02(payRefundService.getRefund(id));
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -65,12 +65,12 @@ public class PayNotifyController {
|
|||||||
// 3. 处理通知
|
// 3. 处理通知
|
||||||
// 3.1:退款通知
|
// 3.1:退款通知
|
||||||
if (notify instanceof PayRefundRespDTO) {
|
if (notify instanceof PayRefundRespDTO) {
|
||||||
refundService.notifyPayRefund(channelId, (PayRefundRespDTO) notify);
|
refundService.notifyRefund(channelId, (PayRefundRespDTO) notify);
|
||||||
return "success";
|
return "success";
|
||||||
}
|
}
|
||||||
// 3.2:支付通知
|
// 3.2:支付通知
|
||||||
if (notify instanceof PayOrderRespDTO) {
|
if (notify instanceof PayOrderRespDTO) {
|
||||||
orderService.notifyPayOrder(channelId, (PayOrderRespDTO) notify);
|
orderService.notifyOrder(channelId, (PayOrderRespDTO) notify);
|
||||||
return "success";
|
return "success";
|
||||||
}
|
}
|
||||||
throw new UnsupportedOperationException("未知通知:" + toJsonString(notify));
|
throw new UnsupportedOperationException("未知通知:" + toJsonString(notify));
|
||||||
|
@ -86,7 +86,7 @@ public class PayOrderController {
|
|||||||
@PostMapping("/submit")
|
@PostMapping("/submit")
|
||||||
@Operation(summary = "提交支付订单")
|
@Operation(summary = "提交支付订单")
|
||||||
public CommonResult<PayOrderSubmitRespVO> submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) {
|
public CommonResult<PayOrderSubmitRespVO> submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) {
|
||||||
PayOrderSubmitRespVO respVO = payOrderService.submitPayOrder(reqVO, getClientIP());
|
PayOrderSubmitRespVO respVO = payOrderService.submitOrder(reqVO, getClientIP());
|
||||||
return success(respVO);
|
return success(respVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ public class AppPayOrderController {
|
|||||||
@PostMapping("/submit")
|
@PostMapping("/submit")
|
||||||
@Operation(summary = "提交支付订单")
|
@Operation(summary = "提交支付订单")
|
||||||
public CommonResult<AppPayOrderSubmitRespVO> submitPayOrder(@RequestBody AppPayOrderSubmitReqVO reqVO) {
|
public CommonResult<AppPayOrderSubmitRespVO> submitPayOrder(@RequestBody AppPayOrderSubmitReqVO reqVO) {
|
||||||
PayOrderSubmitRespVO respVO = payOrderService.submitPayOrder(reqVO, getClientIP());
|
PayOrderSubmitRespVO respVO = payOrderService.submitOrder(reqVO, getClientIP());
|
||||||
return success(PayOrderConvert.INSTANCE.convert3(respVO));
|
return success(PayOrderConvert.INSTANCE.convert3(respVO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
package cn.iocoder.yudao.module.pay.convert.refund;
|
package cn.iocoder.yudao.module.pay.convert.refund;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
|
||||||
|
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
|
||||||
import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.*;
|
import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.*;
|
||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
|
|
||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.Mapping;
|
|
||||||
import org.mapstruct.Mappings;
|
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@ -44,8 +43,6 @@ public interface PayRefundConvert {
|
|||||||
|
|
||||||
PageResult<PayRefundRespVO> convertPage(PageResult<PayRefundDO> page);
|
PageResult<PayRefundRespVO> convertPage(PageResult<PayRefundDO> page);
|
||||||
|
|
||||||
List<PayRefundExcelVO> convertList02(List<PayRefundDO> list);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款订单DO 转 导出excel VO
|
* 退款订单DO 转 导出excel VO
|
||||||
*
|
*
|
||||||
@ -67,7 +64,6 @@ public interface PayRefundConvert {
|
|||||||
payRefundExcelVO.setNotifyUrl(bean.getNotifyUrl());
|
payRefundExcelVO.setNotifyUrl(bean.getNotifyUrl());
|
||||||
payRefundExcelVO.setNotifyStatus(bean.getNotifyStatus());
|
payRefundExcelVO.setNotifyStatus(bean.getNotifyStatus());
|
||||||
payRefundExcelVO.setStatus(bean.getStatus());
|
payRefundExcelVO.setStatus(bean.getStatus());
|
||||||
payRefundExcelVO.setType(bean.getType());
|
|
||||||
payRefundExcelVO.setReason(bean.getReason());
|
payRefundExcelVO.setReason(bean.getReason());
|
||||||
payRefundExcelVO.setUserIp(bean.getUserIp());
|
payRefundExcelVO.setUserIp(bean.getUserIp());
|
||||||
payRefundExcelVO.setChannelOrderNo(bean.getChannelOrderNo());
|
payRefundExcelVO.setChannelOrderNo(bean.getChannelOrderNo());
|
||||||
@ -84,12 +80,8 @@ public interface PayRefundConvert {
|
|||||||
return payRefundExcelVO;
|
return payRefundExcelVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO 太多需要处理了, 暂时不用
|
PayRefundDO convert(PayRefundCreateReqDTO bean);
|
||||||
@Mappings(value = {
|
|
||||||
@Mapping(source = "price", target = "payPrice"),
|
PayRefundRespDTO convert02(PayRefundDO bean);
|
||||||
@Mapping(source = "id", target = "orderId"),
|
|
||||||
@Mapping(target = "status",ignore = true)
|
|
||||||
})
|
|
||||||
PayRefundDO convert(PayOrderDO orderDO);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
|
|||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
|
import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
|
||||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum;
|
import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum;
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
@ -127,7 +127,7 @@ public class PayOrderDO extends BaseDO {
|
|||||||
/**
|
/**
|
||||||
* 退款状态
|
* 退款状态
|
||||||
*
|
*
|
||||||
* 枚举 {@link PayRefundTypeEnum}
|
* 枚举 {@link PayOrderRefundStatusEnum}
|
||||||
*/
|
*/
|
||||||
private Integer refundStatus;
|
private Integer refundStatus;
|
||||||
/**
|
/**
|
||||||
@ -137,7 +137,7 @@ public class PayOrderDO extends BaseDO {
|
|||||||
/**
|
/**
|
||||||
* 退款总金额,单位:分
|
* 退款总金额,单位:分
|
||||||
*/
|
*/
|
||||||
private Long refundPrice;
|
private Integer refundPrice;
|
||||||
|
|
||||||
// ========== 渠道相关字段 ==========
|
// ========== 渠道相关字段 ==========
|
||||||
/**
|
/**
|
||||||
|
@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
|
|||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
|
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
|
||||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum;
|
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
@ -104,12 +103,6 @@ public class PayRefundDO extends BaseDO {
|
|||||||
*/
|
*/
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
/**
|
|
||||||
* 退款类型(部分退款,全部退款)
|
|
||||||
*
|
|
||||||
* 枚举 {@link PayRefundTypeEnum}
|
|
||||||
*/
|
|
||||||
private Integer type;
|
|
||||||
/**
|
/**
|
||||||
* 支付金额,单位:分
|
* 支付金额,单位:分
|
||||||
*/
|
*/
|
||||||
@ -157,12 +150,6 @@ public class PayRefundDO extends BaseDO {
|
|||||||
*/
|
*/
|
||||||
private String channelErrorMsg;
|
private String channelErrorMsg;
|
||||||
|
|
||||||
/**
|
|
||||||
* 支付渠道的额外参数
|
|
||||||
*
|
|
||||||
* 参见 <a href="https://www.pingxx.com/api/支付渠道%20extra%20参数说明.html">参数说明</>
|
|
||||||
*/
|
|
||||||
private String channelExtras;
|
|
||||||
/**
|
/**
|
||||||
* 支付渠道异步通知的内容
|
* 支付渠道异步通知的内容
|
||||||
*
|
*
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package cn.iocoder.yudao.module.pay.dal.mysql.refund;
|
package cn.iocoder.yudao.module.pay.dal.mysql.refund;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO;
|
|
||||||
import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO;
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||||
|
import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO;
|
||||||
|
import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO;
|
||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -13,6 +15,34 @@ import java.util.List;
|
|||||||
@Mapper
|
@Mapper
|
||||||
public interface PayRefundMapper extends BaseMapperX<PayRefundDO> {
|
public interface PayRefundMapper extends BaseMapperX<PayRefundDO> {
|
||||||
|
|
||||||
|
default Long selectCountByAppId(Long appId) {
|
||||||
|
return selectCount(PayRefundDO::getAppId, appId);
|
||||||
|
}
|
||||||
|
|
||||||
|
default PayRefundDO selectByAppIdAndMerchantRefundId(Long appId, String merchantRefundId) {
|
||||||
|
return selectOne(new LambdaQueryWrapperX<PayRefundDO>()
|
||||||
|
.eq(PayRefundDO::getAppId, appId)
|
||||||
|
.eq(PayRefundDO::getMerchantRefundId, merchantRefundId));
|
||||||
|
}
|
||||||
|
|
||||||
|
default Long selectCountByAppIdAndOrderId(Long appId, Long orderId, Integer status) {
|
||||||
|
return selectCount(new LambdaQueryWrapperX<PayRefundDO>()
|
||||||
|
.eq(PayRefundDO::getAppId, appId)
|
||||||
|
.eq(PayRefundDO::getOrderId, orderId)
|
||||||
|
.eq(PayRefundDO::getStatus, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
default PayRefundDO selectByAppIdAndNo(Long appId, String no) {
|
||||||
|
return selectOne(new LambdaQueryWrapperX<PayRefundDO>()
|
||||||
|
.eq(PayRefundDO::getAppId, appId)
|
||||||
|
.eq(PayRefundDO::getNo, no));
|
||||||
|
}
|
||||||
|
|
||||||
|
default int updateByIdAndStatus(Long id, Integer status, PayRefundDO update) {
|
||||||
|
return update(update, new LambdaQueryWrapper<PayRefundDO>()
|
||||||
|
.eq(PayRefundDO::getId, id).eq(PayRefundDO::getStatus, status));
|
||||||
|
}
|
||||||
|
|
||||||
default PageResult<PayRefundDO> selectPage(PayRefundPageReqVO reqVO) {
|
default PageResult<PayRefundDO> selectPage(PayRefundPageReqVO reqVO) {
|
||||||
return selectPage(reqVO, new QueryWrapperX<PayRefundDO>()
|
return selectPage(reqVO, new QueryWrapperX<PayRefundDO>()
|
||||||
.eqIfPresent("app_id", reqVO.getAppId())
|
.eqIfPresent("app_id", reqVO.getAppId())
|
||||||
@ -37,18 +67,4 @@ public interface PayRefundMapper extends BaseMapperX<PayRefundDO> {
|
|||||||
.orderByDesc("id"));
|
.orderByDesc("id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
default Long selectCountByApp(Long appId) {
|
|
||||||
return selectCount(PayRefundDO::getAppId, appId);
|
|
||||||
}
|
|
||||||
|
|
||||||
default PayRefundDO selectByReqNo(String reqNo) {
|
|
||||||
return selectOne("req_no", reqNo);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO 芋艿:要重构
|
|
||||||
default PayRefundDO selectByTradeNoAndMerchantRefundNo(String tradeNo, String merchantRefundNo){
|
|
||||||
// return selectOne("trade_no", tradeNo, "merchant_refund_no", merchantRefundNo);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package cn.iocoder.yudao.module.pay.enums.refund;
|
package cn.iocoder.yudao.module.pay.enums.order;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@ -11,10 +11,10 @@ import lombok.Getter;
|
|||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public enum PayRefundTypeEnum implements IntArrayValuable {
|
public enum PayOrderRefundStatusEnum implements IntArrayValuable {
|
||||||
|
|
||||||
NO(0, "未退款"),
|
NO(0, "未退款"),
|
||||||
SOME(10, "部分退款"),
|
PART(10, "部分退款"),
|
||||||
ALL(20, "全部退款")
|
ALL(20, "全部退款")
|
||||||
;
|
;
|
||||||
|
|
@ -184,12 +184,17 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
|
|||||||
// 1. 校验订单是否可以退款
|
// 1. 校验订单是否可以退款
|
||||||
PayDemoOrderDO order = validateDemoOrderCanRefund(id);
|
PayDemoOrderDO order = validateDemoOrderCanRefund(id);
|
||||||
|
|
||||||
// 2.1 创建退款单
|
// 2.1 生成退款单号
|
||||||
|
// 一般来说,用户发起退款的时候,都会单独插入一个售后维权表,然后使用该表的 id 作为 refundId
|
||||||
|
// 这里我们是个简单的 demo,所以没有售后维权表,直接使用订单 id + "-refund" 来演示
|
||||||
|
String refundId = order.getId() + "-refund";
|
||||||
|
// 2.2 创建退款单
|
||||||
Long payRefundId = payRefundApi.createPayRefund(new PayRefundCreateReqDTO()
|
Long payRefundId = payRefundApi.createPayRefund(new PayRefundCreateReqDTO()
|
||||||
.setAppId(PAY_APP_ID).setUserIp(getClientIP()) // 支付应用
|
.setAppId(PAY_APP_ID).setUserIp(getClientIP()) // 支付应用
|
||||||
.setPayOrderId(order.getPayOrderId()) // 支付单号
|
.setMerchantOrderId(String.valueOf(order.getId())) // 支付单号
|
||||||
|
.setMerchantRefundId(refundId)
|
||||||
.setReason("想退钱").setPrice(order.getPrice()));// 价格信息
|
.setReason("想退钱").setPrice(order.getPrice()));// 价格信息
|
||||||
// 2.2 更新退款单到 demo 订单
|
// 2.3 更新退款单到 demo 订单
|
||||||
payDemoOrderMapper.updateById(new PayDemoOrderDO().setId(id)
|
payDemoOrderMapper.updateById(new PayDemoOrderDO().setId(id)
|
||||||
.setPayRefundId(payRefundId).setRefundPrice(order.getPrice()));
|
.setPayRefundId(payRefundId).setRefundPrice(order.getPrice()));
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import java.util.Collection;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
// TODO 芋艿:合并到 PayOrder 里;
|
||||||
/**
|
/**
|
||||||
* 支付订单 Service 接口
|
* 支付订单 Service 接口
|
||||||
*
|
*
|
||||||
|
@ -31,6 +31,15 @@ public interface PayOrderService {
|
|||||||
*/
|
*/
|
||||||
PayOrderDO getOrder(Long id);
|
PayOrderDO getOrder(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得支付订单
|
||||||
|
*
|
||||||
|
* @param appId 应用编号
|
||||||
|
* @param merchantOrderId 商户订单编号
|
||||||
|
* @return 支付订单
|
||||||
|
*/
|
||||||
|
PayOrderDO getOrder(Long appId, String merchantOrderId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得指定应用的订单数量
|
* 获得指定应用的订单数量
|
||||||
*
|
*
|
||||||
@ -70,11 +79,11 @@ public interface PayOrderService {
|
|||||||
/**
|
/**
|
||||||
* 根据订单 ID 集合获取订单商品名称Map集合
|
* 根据订单 ID 集合获取订单商品名称Map集合
|
||||||
*
|
*
|
||||||
* @param idList 订单 ID 集合
|
* @param ids 订单 ID 集合
|
||||||
* @return 订单商品 map 集合
|
* @return 订单商品 map 集合
|
||||||
*/
|
*/
|
||||||
default Map<Long, PayOrderDO> getOrderSubjectMap(Collection<Long> idList) {
|
default Map<Long, PayOrderDO> getOrderSubjectMap(Collection<Long> ids) {
|
||||||
List<PayOrderDO> list = getOrderSubjectList(idList);
|
List<PayOrderDO> list = getOrderSubjectList(ids);
|
||||||
return CollectionUtils.convertMap(list, PayOrderDO::getId);
|
return CollectionUtils.convertMap(list, PayOrderDO::getId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +93,7 @@ public interface PayOrderService {
|
|||||||
* @param reqDTO 创建请求
|
* @param reqDTO 创建请求
|
||||||
* @return 支付单编号
|
* @return 支付单编号
|
||||||
*/
|
*/
|
||||||
Long createPayOrder(@Valid PayOrderCreateReqDTO reqDTO);
|
Long createOrder(@Valid PayOrderCreateReqDTO reqDTO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提交支付
|
* 提交支付
|
||||||
@ -94,8 +103,8 @@ public interface PayOrderService {
|
|||||||
* @param userIp 提交 IP
|
* @param userIp 提交 IP
|
||||||
* @return 提交结果
|
* @return 提交结果
|
||||||
*/
|
*/
|
||||||
PayOrderSubmitRespVO submitPayOrder(@Valid PayOrderSubmitReqVO reqVO,
|
PayOrderSubmitRespVO submitOrder(@Valid PayOrderSubmitReqVO reqVO,
|
||||||
@NotEmpty(message = "提交 IP 不能为空") String userIp);
|
@NotEmpty(message = "提交 IP 不能为空") String userIp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知支付单成功
|
* 通知支付单成功
|
||||||
@ -103,6 +112,14 @@ public interface PayOrderService {
|
|||||||
* @param channelId 渠道编号
|
* @param channelId 渠道编号
|
||||||
* @param notify 通知
|
* @param notify 通知
|
||||||
*/
|
*/
|
||||||
void notifyPayOrder(Long channelId, PayOrderRespDTO notify);
|
void notifyOrder(Long channelId, PayOrderRespDTO notify);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新支付订单的退款金额
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
* @param incrRefundPrice 增加的退款金额
|
||||||
|
*/
|
||||||
|
void updateOrderRefundPrice(Long id, Integer incrRefundPrice);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,11 +26,10 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
|
|||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
|
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
|
||||||
import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderExtensionMapper;
|
import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderExtensionMapper;
|
||||||
import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper;
|
import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper;
|
||||||
import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants;
|
|
||||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
|
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum;
|
||||||
|
import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum;
|
|
||||||
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
|
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
|
||||||
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
||||||
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
||||||
@ -48,6 +47,7 @@ import java.util.Objects;
|
|||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
|
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
|
||||||
|
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付订单 Service 实现类
|
* 支付订单 Service 实现类
|
||||||
@ -82,6 +82,11 @@ public class PayOrderServiceImpl implements PayOrderService {
|
|||||||
return orderMapper.selectById(id);
|
return orderMapper.selectById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PayOrderDO getOrder(Long appId, String merchantOrderId) {
|
||||||
|
return orderMapper.selectByAppIdAndMerchantOrderId(appId, merchantOrderId);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long getOrderCountByAppId(Long appId) {
|
public Long getOrderCountByAppId(Long appId) {
|
||||||
return orderMapper.selectCountByAppId(appId);
|
return orderMapper.selectCountByAppId(appId);
|
||||||
@ -104,7 +109,7 @@ public class PayOrderServiceImpl implements PayOrderService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long createPayOrder(PayOrderCreateReqDTO reqDTO) {
|
public Long createOrder(PayOrderCreateReqDTO reqDTO) {
|
||||||
// 校验 App
|
// 校验 App
|
||||||
PayAppDO app = appService.validPayApp(reqDTO.getAppId());
|
PayAppDO app = appService.validPayApp(reqDTO.getAppId());
|
||||||
|
|
||||||
@ -112,7 +117,7 @@ public class PayOrderServiceImpl implements PayOrderService {
|
|||||||
PayOrderDO order = orderMapper.selectByAppIdAndMerchantOrderId(
|
PayOrderDO order = orderMapper.selectByAppIdAndMerchantOrderId(
|
||||||
reqDTO.getAppId(), reqDTO.getMerchantOrderId());
|
reqDTO.getAppId(), reqDTO.getMerchantOrderId());
|
||||||
if (order != null) {
|
if (order != null) {
|
||||||
log.warn("[createPayOrder][appId({}) merchantOrderId({}) 已经存在对应的支付单({})]", order.getAppId(),
|
log.warn("[createOrder][appId({}) merchantOrderId({}) 已经存在对应的支付单({})]", order.getAppId(),
|
||||||
order.getMerchantOrderId(), toJsonString(order)); // 理论来说,不会出现这个情况
|
order.getMerchantOrderId(), toJsonString(order)); // 理论来说,不会出现这个情况
|
||||||
return order.getId();
|
return order.getId();
|
||||||
}
|
}
|
||||||
@ -124,16 +129,16 @@ public class PayOrderServiceImpl implements PayOrderService {
|
|||||||
// 订单相关字段
|
// 订单相关字段
|
||||||
.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||||
// 退款相关字段
|
// 退款相关字段
|
||||||
.setRefundStatus(PayRefundTypeEnum.NO.getStatus()).setRefundTimes(0).setRefundPrice(0L);
|
.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus()).setRefundTimes(0).setRefundPrice(0);
|
||||||
orderMapper.insert(order);
|
orderMapper.insert(order);
|
||||||
return order.getId();
|
return order.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public PayOrderSubmitRespVO submitPayOrder(PayOrderSubmitReqVO reqVO, String userIp) {
|
public PayOrderSubmitRespVO submitOrder(PayOrderSubmitReqVO reqVO, String userIp) {
|
||||||
// 1. 获得 PayOrderDO ,并校验其是否存在
|
// 1. 获得 PayOrderDO ,并校验其是否存在
|
||||||
PayOrderDO order = validatePayOrderCanSubmit(reqVO.getId());
|
PayOrderDO order = validateOrderCanSubmit(reqVO.getId());
|
||||||
// 1.2 校验支付渠道是否有效
|
// 1.2 校验支付渠道是否有效
|
||||||
PayChannelDO channel = validatePayChannelCanSubmit(order.getAppId(), reqVO.getChannelCode());
|
PayChannelDO channel = validatePayChannelCanSubmit(order.getAppId(), reqVO.getChannelCode());
|
||||||
PayClient client = payClientFactory.getPayClient(channel.getId());
|
PayClient client = payClientFactory.getPayClient(channel.getId());
|
||||||
@ -167,16 +172,16 @@ public class PayOrderServiceImpl implements PayOrderService {
|
|||||||
return PayOrderConvert.INSTANCE.convert(order, unifiedOrderRespDTO);
|
return PayOrderConvert.INSTANCE.convert(order, unifiedOrderRespDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PayOrderDO validatePayOrderCanSubmit(Long id) {
|
private PayOrderDO validateOrderCanSubmit(Long id) {
|
||||||
PayOrderDO order = orderMapper.selectById(id);
|
PayOrderDO order = orderMapper.selectById(id);
|
||||||
if (order == null) { // 是否存在
|
if (order == null) { // 是否存在
|
||||||
throw exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND);
|
throw exception(PAY_ORDER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付
|
if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付
|
||||||
throw exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING);
|
throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING);
|
||||||
}
|
}
|
||||||
if (LocalDateTimeUtils.beforeNow(order.getExpireTime())) { // 校验是否过期
|
if (LocalDateTimeUtils.beforeNow(order.getExpireTime())) { // 校验是否过期
|
||||||
throw exception(ErrorCodeConstants.PAY_ORDER_IS_EXPIRED);
|
throw exception(PAY_ORDER_IS_EXPIRED);
|
||||||
}
|
}
|
||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
@ -184,14 +189,12 @@ public class PayOrderServiceImpl implements PayOrderService {
|
|||||||
private PayChannelDO validatePayChannelCanSubmit(Long appId, String channelCode) {
|
private PayChannelDO validatePayChannelCanSubmit(Long appId, String channelCode) {
|
||||||
// 校验 App
|
// 校验 App
|
||||||
appService.validPayApp(appId);
|
appService.validPayApp(appId);
|
||||||
|
|
||||||
// 校验支付渠道是否有效
|
// 校验支付渠道是否有效
|
||||||
PayChannelDO channel = channelService.validPayChannel(appId, channelCode);
|
PayChannelDO channel = channelService.validPayChannel(appId, channelCode);
|
||||||
// 校验支付客户端是否正确初始化
|
|
||||||
PayClient client = payClientFactory.getPayClient(channel.getId());
|
PayClient client = payClientFactory.getPayClient(channel.getId());
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
log.error("[validatePayChannelCanSubmit][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
|
log.error("[validatePayChannelCanSubmit][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
|
||||||
throw exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND);
|
throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
|
||||||
}
|
}
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
@ -226,28 +229,55 @@ public class PayOrderServiceImpl implements PayOrderService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void notifyPayOrder(Long channelId, PayOrderRespDTO notify) {
|
public void notifyOrder(Long channelId, PayOrderRespDTO notify) {
|
||||||
// 校验支付渠道是否有效
|
// 校验支付渠道是否有效
|
||||||
PayChannelDO channel = channelService.validPayChannel(channelId);
|
PayChannelDO channel = channelService.validPayChannel(channelId);
|
||||||
// 更新支付订单为已支付
|
// 更新支付订单为已支付
|
||||||
TenantUtils.execute(channel.getTenantId(), () -> notifyPayOrder(channel, notify));
|
TenantUtils.execute(channel.getTenantId(), () -> notifyPayOrder(channel, notify));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateOrderRefundPrice(Long id, Integer incrRefundPrice) {
|
||||||
|
PayOrderDO order = orderMapper.selectById(id);
|
||||||
|
if (order == null) {
|
||||||
|
throw exception(PAY_ORDER_NOT_FOUND);
|
||||||
|
}
|
||||||
|
if (!PayOrderStatusEnum.isSuccess(order.getStatus())) {
|
||||||
|
throw exception(PAY_REFUND_PRICE_EXCEED);
|
||||||
|
}
|
||||||
|
if (order.getRefundPrice() + incrRefundPrice > order.getPrice()) {
|
||||||
|
throw exception(PAY_REFUND_PRICE_EXCEED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新订单
|
||||||
|
PayOrderDO updateObj = new PayOrderDO()
|
||||||
|
.setRefundPrice(order.getRefundPrice() + incrRefundPrice)
|
||||||
|
.setRefundTimes(order.getRefundTimes() + 1);
|
||||||
|
if (Objects.equals(updateObj.getRefundPrice(), order.getPrice())) {
|
||||||
|
updateObj.setStatus(PayOrderStatusEnum.CLOSED.getStatus())
|
||||||
|
.setRefundStatus(PayOrderRefundStatusEnum.ALL.getStatus());
|
||||||
|
} else {
|
||||||
|
updateObj.setStatus(PayOrderStatusEnum.CLOSED.getStatus())
|
||||||
|
.setRefundStatus(PayOrderRefundStatusEnum.PART.getStatus());
|
||||||
|
}
|
||||||
|
orderMapper.updateByIdAndStatus(id, PayOrderStatusEnum.SUCCESS.getStatus(), updateObj);
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyPayOrder(PayChannelDO channel, PayOrderRespDTO notify) {
|
private void notifyPayOrder(PayChannelDO channel, PayOrderRespDTO notify) {
|
||||||
// 情况一:支付成功的回调
|
// 情况一:支付成功的回调
|
||||||
if (PayOrderStatusRespEnum.isSuccess(notify.getStatus())) {
|
if (PayOrderStatusRespEnum.isSuccess(notify.getStatus())) {
|
||||||
notifyPayOrderSuccess(channel, notify);
|
notifyOrderSuccess(channel, notify);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 情况二:非支付成功的回调,进行忽略
|
// 情况二:非支付成功的回调,进行忽略
|
||||||
log.info("[notifyPayOrder][非支付成功的回调({}),直接忽略]", toJsonString(notify));
|
log.info("[notifyPayOrder][非支付成功的回调({}),直接忽略]", toJsonString(notify));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyPayOrderSuccess(PayChannelDO channel, PayOrderRespDTO notify) {
|
private void notifyOrderSuccess(PayChannelDO channel, PayOrderRespDTO notify) {
|
||||||
// 1. 更新 PayOrderExtensionDO 支付成功
|
// 1. 更新 PayOrderExtensionDO 支付成功
|
||||||
PayOrderExtensionDO orderExtension = updatePayOrderExtensionSuccess(notify);
|
PayOrderExtensionDO orderExtension = updateOrderExtensionSuccess(notify);
|
||||||
// 2. 更新 PayOrderDO 支付成功
|
// 2. 更新 PayOrderDO 支付成功
|
||||||
Pair<Boolean, PayOrderDO> order = updatePayOrderSuccess(channel, orderExtension, notify);
|
Pair<Boolean, PayOrderDO> order = updateOrderExtensionSuccess(channel, orderExtension, notify);
|
||||||
if (order.getKey()) { // 如果之前已经成功回调,则直接返回,不用重复记录支付通知记录;例如说:支付平台重复回调
|
if (order.getKey()) { // 如果之前已经成功回调,则直接返回,不用重复记录支付通知记录;例如说:支付平台重复回调
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -263,27 +293,27 @@ public class PayOrderServiceImpl implements PayOrderService {
|
|||||||
* @param notify 通知
|
* @param notify 通知
|
||||||
* @return PayOrderExtensionDO 对象
|
* @return PayOrderExtensionDO 对象
|
||||||
*/
|
*/
|
||||||
private PayOrderExtensionDO updatePayOrderExtensionSuccess(PayOrderRespDTO notify) {
|
private PayOrderExtensionDO updateOrderExtensionSuccess(PayOrderRespDTO notify) {
|
||||||
// 1. 查询 PayOrderExtensionDO
|
// 1. 查询 PayOrderExtensionDO
|
||||||
PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(notify.getOutTradeNo());
|
PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(notify.getOutTradeNo());
|
||||||
if (orderExtension == null) {
|
if (orderExtension == null) {
|
||||||
throw exception(ErrorCodeConstants.PAY_ORDER_EXTENSION_NOT_FOUND);
|
throw exception(PAY_ORDER_EXTENSION_NOT_FOUND);
|
||||||
}
|
}
|
||||||
if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) { // 如果已经是成功,直接返回,不用重复更新
|
if (PayOrderStatusEnum.isSuccess(orderExtension.getStatus())) { // 如果已经是成功,直接返回,不用重复更新
|
||||||
log.info("[updatePayOrderSuccess][支付拓展单({}) 已经是已支付,无需更新为已支付]", orderExtension.getId());
|
log.info("[updateOrderExtensionSuccess][支付拓展单({}) 已经是已支付,无需更新为已支付]", orderExtension.getId());
|
||||||
return orderExtension;
|
return orderExtension;
|
||||||
}
|
}
|
||||||
if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付
|
if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付
|
||||||
throw exception(ErrorCodeConstants.PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING);
|
throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 更新 PayOrderExtensionDO
|
// 2. 更新 PayOrderExtensionDO
|
||||||
int updateCounts = orderExtensionMapper.updateByIdAndStatus(orderExtension.getId(), PayOrderStatusEnum.WAITING.getStatus(),
|
int updateCounts = orderExtensionMapper.updateByIdAndStatus(orderExtension.getId(), orderExtension.getStatus(),
|
||||||
PayOrderExtensionDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(toJsonString(notify)).build());
|
PayOrderExtensionDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(toJsonString(notify)).build());
|
||||||
if (updateCounts == 0) { // 校验状态,必须是待支付
|
if (updateCounts == 0) { // 校验状态,必须是待支付
|
||||||
throw exception(ErrorCodeConstants.PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING);
|
throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING);
|
||||||
}
|
}
|
||||||
log.info("[updatePayOrderSuccess][支付拓展单({}) 更新为已支付]", orderExtension.getId());
|
log.info("[updateOrderExtensionSuccess][支付拓展单({}) 更新为已支付]", orderExtension.getId());
|
||||||
return orderExtension;
|
return orderExtension;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,20 +326,20 @@ public class PayOrderServiceImpl implements PayOrderService {
|
|||||||
* @return key:是否之前已经成功回调
|
* @return key:是否之前已经成功回调
|
||||||
* value:PayOrderDO 对象
|
* value:PayOrderDO 对象
|
||||||
*/
|
*/
|
||||||
private Pair<Boolean, PayOrderDO> updatePayOrderSuccess(PayChannelDO channel, PayOrderExtensionDO orderExtension,
|
private Pair<Boolean, PayOrderDO> updateOrderExtensionSuccess(PayChannelDO channel, PayOrderExtensionDO orderExtension,
|
||||||
PayOrderRespDTO notify) {
|
PayOrderRespDTO notify) {
|
||||||
// 1. 判断 PayOrderDO 是否处于待支付
|
// 1. 判断 PayOrderDO 是否处于待支付
|
||||||
PayOrderDO order = orderMapper.selectById(orderExtension.getOrderId());
|
PayOrderDO order = orderMapper.selectById(orderExtension.getOrderId());
|
||||||
if (order == null) {
|
if (order == null) {
|
||||||
throw exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND);
|
throw exception(PAY_ORDER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
if (PayOrderStatusEnum.isSuccess(order.getStatus()) // 如果已经是成功,直接返回,不用重复更新
|
if (PayOrderStatusEnum.isSuccess(order.getStatus()) // 如果已经是成功,直接返回,不用重复更新
|
||||||
&& Objects.equals(order.getSuccessExtensionId(), orderExtension.getId())) {
|
&& Objects.equals(order.getSuccessExtensionId(), orderExtension.getId())) {
|
||||||
log.info("[updatePayOrderSuccess][支付订单({}) 已经是已支付,无需更新为已支付]", order.getId());
|
log.info("[updateOrderExtensionSuccess][支付订单({}) 已经是已支付,无需更新为已支付]", order.getId());
|
||||||
return Pair.of(true, order);
|
return Pair.of(true, order);
|
||||||
}
|
}
|
||||||
if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付
|
if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付
|
||||||
throw exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING);
|
throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 更新 PayOrderDO
|
// 2. 更新 PayOrderDO
|
||||||
@ -320,9 +350,9 @@ public class PayOrderServiceImpl implements PayOrderService {
|
|||||||
.channelOrderNo(notify.getChannelOrderNo()).channelUserId(notify.getChannelUserId())
|
.channelOrderNo(notify.getChannelOrderNo()).channelUserId(notify.getChannelUserId())
|
||||||
.notifyTime(LocalDateTime.now()).build());
|
.notifyTime(LocalDateTime.now()).build());
|
||||||
if (updateCounts == 0) { // 校验状态,必须是待支付
|
if (updateCounts == 0) { // 校验状态,必须是待支付
|
||||||
throw exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING);
|
throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING);
|
||||||
}
|
}
|
||||||
log.info("[updatePayOrderSuccess][支付订单({}) 更新为已支付]", order.getId());
|
log.info("[updateOrderExtensionSuccess][支付订单({}) 更新为已支付]", order.getId());
|
||||||
return Pair.of(false, order);
|
return Pair.of(false, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +62,6 @@ public interface PayRefundService {
|
|||||||
* @param channelId 渠道编号
|
* @param channelId 渠道编号
|
||||||
* @param notify 通知
|
* @param notify 通知
|
||||||
*/
|
*/
|
||||||
void notifyPayRefund(Long channelId, PayRefundRespDTO notify);
|
void notifyRefund(Long channelId, PayRefundRespDTO notify);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package cn.iocoder.yudao.module.pay.service.refund;
|
package cn.iocoder.yudao.module.pay.service.refund;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.util.RandomUtil;
|
import cn.hutool.core.util.RandomUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.pay.config.PayProperties;
|
import cn.iocoder.yudao.framework.pay.config.PayProperties;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
||||||
@ -10,22 +9,23 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
|||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum;
|
import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum;
|
||||||
|
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
||||||
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
|
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
|
||||||
import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO;
|
import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO;
|
||||||
import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO;
|
import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.pay.convert.refund.PayRefundConvert;
|
||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
|
import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
|
||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
|
import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
|
||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
|
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
|
||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
|
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
|
||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
||||||
import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper;
|
|
||||||
import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper;
|
import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper;
|
||||||
import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants;
|
import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants;
|
||||||
|
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
|
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum;
|
|
||||||
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
|
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
|
||||||
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
||||||
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
||||||
@ -38,8 +38,11 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款订单 Service 实现类
|
* 退款订单 Service 实现类
|
||||||
@ -59,8 +62,6 @@ public class PayRefundServiceImpl implements PayRefundService {
|
|||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private PayRefundMapper refundMapper;
|
private PayRefundMapper refundMapper;
|
||||||
@Resource
|
|
||||||
private PayOrderMapper orderMapper; // TODO @jason:需要改成不直接操作 db;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private PayOrderService orderService;
|
private PayOrderService orderService;
|
||||||
@ -80,7 +81,7 @@ public class PayRefundServiceImpl implements PayRefundService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long getRefundCountByAppId(Long appId) {
|
public Long getRefundCountByAppId(Long appId) {
|
||||||
return refundMapper.selectCountByApp(appId);
|
return refundMapper.selectCountByAppId(appId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -96,82 +97,82 @@ public class PayRefundServiceImpl implements PayRefundService {
|
|||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Long createPayRefund(PayRefundCreateReqDTO reqDTO) {
|
public Long createPayRefund(PayRefundCreateReqDTO reqDTO) {
|
||||||
// 获得 PayOrderDO
|
// 1.1 校验 App
|
||||||
PayOrderDO order = orderService.getOrder(reqDTO.getPayOrderId());
|
PayAppDO app = appService.validPayApp(reqDTO.getAppId());
|
||||||
// 校验订单是否存在
|
// 1.2 校验支付订单
|
||||||
if (Objects.isNull(order) ) {
|
PayOrderDO order = validatePayOrderCanRefund(reqDTO);
|
||||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND);
|
// 1.3 校验支付渠道是否有效
|
||||||
}
|
|
||||||
// 校验 App
|
|
||||||
PayAppDO app = appService.validPayApp(order.getAppId());
|
|
||||||
// 校验支付渠道是否有效
|
|
||||||
PayChannelDO channel = channelService.validPayChannel(order.getChannelId());
|
PayChannelDO channel = channelService.validPayChannel(order.getChannelId());
|
||||||
// 校验支付客户端是否正确初始化
|
|
||||||
PayClient client = payClientFactory.getPayClient(channel.getId());
|
PayClient client = payClientFactory.getPayClient(channel.getId());
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
log.error("[refund][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
|
log.error("[refund][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
|
||||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND);
|
throw exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND);
|
||||||
|
}
|
||||||
|
// 1.4 校验退款订单是否已经存在
|
||||||
|
PayRefundDO refund = refundMapper.selectByAppIdAndMerchantRefundId(
|
||||||
|
app.getId(), reqDTO.getMerchantRefundId());
|
||||||
|
if (refund != null) {
|
||||||
|
throw exception(ErrorCodeConstants.PAY_REFUND_EXISTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 芋艿:待实现
|
// 2.1 插入退款单
|
||||||
String merchantRefundId = "rrr" + RandomUtil.randomNumbers(16);
|
refund = PayRefundConvert.INSTANCE.convert(reqDTO)
|
||||||
|
.setNo(generateRefundNo()).setOrderId(order.getId())
|
||||||
// 校验退款的条件
|
.setChannelId(order.getChannelId()).setChannelCode(order.getChannelCode())
|
||||||
validatePayRefund(reqDTO, order);
|
// 商户相关的字段
|
||||||
// 退款类型
|
.setNotifyUrl(app.getRefundNotifyUrl()).setNotifyStatus(PayNotifyStatusEnum.WAITING.getStatus())
|
||||||
PayRefundTypeEnum refundType = PayRefundTypeEnum.SOME;
|
// 渠道相关字段
|
||||||
if (Objects.equals(reqDTO.getPrice(), order.getPrice())) {
|
.setChannelOrderNo(order.getChannelOrderNo())
|
||||||
refundType = PayRefundTypeEnum.ALL;
|
// 退款相关字段
|
||||||
}
|
.setStatus(PayRefundStatusEnum.WAITING.getStatus())
|
||||||
PayOrderExtensionDO orderExtensionDO = orderExtensionService.getOrderExtension(order.getSuccessExtensionId());
|
.setPayPrice(order.getPrice()).setRefundPrice(reqDTO.getPrice());
|
||||||
PayRefundDO payRefundDO = refundMapper.selectByTradeNoAndMerchantRefundNo(orderExtensionDO.getNo(),
|
refundMapper.insert(refund);
|
||||||
merchantRefundId); // TODO 芋艿:需要优化
|
// 2.2 向渠道发起退款申请
|
||||||
if (Objects.nonNull(payRefundDO)) {
|
PayOrderExtensionDO orderExtension = orderExtensionService.getOrderExtension(order.getSuccessExtensionId());
|
||||||
// 退款订单已经提交过。
|
|
||||||
//TODO 校验相同退款单的金额
|
|
||||||
// TODO @jason:咱要不封装一个 ObjectUtils.equalsAny
|
|
||||||
if (Objects.equals(PayRefundStatusEnum.SUCCESS.getStatus(), payRefundDO.getStatus())) {
|
|
||||||
//已成功退款
|
|
||||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_SUCCEED);
|
|
||||||
}
|
|
||||||
//可以重复提交,保证 退款请求号 一致,由渠道保证幂等
|
|
||||||
} else {
|
|
||||||
// 成功,插入退款单 状态为生成.没有和渠道交互
|
|
||||||
// TODO @jason:搞到 convert 里。一些额外的自动,手动 set 下;
|
|
||||||
payRefundDO = PayRefundDO.builder()
|
|
||||||
.appId(order.getAppId())
|
|
||||||
.channelOrderNo(order.getChannelOrderNo())
|
|
||||||
.channelCode(order.getChannelCode())
|
|
||||||
.channelId(order.getChannelId())
|
|
||||||
.orderId(order.getId())
|
|
||||||
.merchantRefundId(merchantRefundId)
|
|
||||||
.notifyUrl(app.getRefundNotifyUrl())
|
|
||||||
.payPrice(order.getPrice())
|
|
||||||
.refundPrice(reqDTO.getPrice())
|
|
||||||
.userIp(reqDTO.getUserIp())
|
|
||||||
.merchantOrderId(order.getMerchantOrderId())
|
|
||||||
.no(orderExtensionDO.getNo())
|
|
||||||
.status(PayRefundStatusEnum.WAITING.getStatus())
|
|
||||||
.reason(reqDTO.getReason())
|
|
||||||
.notifyStatus(PayOrderNotifyStatusEnum.NO.getStatus())
|
|
||||||
.type(refundType.getStatus())
|
|
||||||
.build();
|
|
||||||
refundMapper.insert(payRefundDO);
|
|
||||||
}
|
|
||||||
// TODO @jason:搞到 convert 里。一些额外的自动,手动 set 下;
|
|
||||||
PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO();
|
PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO();
|
||||||
unifiedReqDTO.setPrice(reqDTO.getPrice())
|
unifiedReqDTO.setPrice(reqDTO.getPrice())
|
||||||
.setOutTradeNo(orderExtensionDO.getNo())
|
.setOutTradeNo(orderExtension.getNo())
|
||||||
.setOutRefundNo(merchantRefundId) // TODO 芋艿:需要优化
|
.setOutRefundNo(refund.getNo())
|
||||||
.setNotifyUrl(genChannelPayNotifyUrl(channel)) // TODO 芋艿:优化下 notifyUrl
|
.setNotifyUrl(genChannelPayNotifyUrl(channel)) // TODO 芋艿:优化下 notifyUrl
|
||||||
.setReason(reqDTO.getReason());
|
.setReason(reqDTO.getReason());
|
||||||
// 向渠道发起退款申请
|
PayRefundRespDTO refundRespDTO = client.unifiedRefund(unifiedReqDTO); // TODO 增加一个 channelErrorCode、channelErrorMsg 字段
|
||||||
client.unifiedRefund(unifiedReqDTO);
|
// 2.3 处理退款返回
|
||||||
// 检查是否失败,失败抛出业务异常。
|
notifyRefund(channel, refundRespDTO);
|
||||||
// TODO 渠道的异常记录。
|
|
||||||
// TODO @jason:可以先打个 warn log 哈;
|
|
||||||
// 成功在 退款回调中处理
|
// 成功在 退款回调中处理
|
||||||
return payRefundDO.getId();
|
return refund.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验支付订单是否可以退款
|
||||||
|
*
|
||||||
|
* @param reqDTO 退款申请信息
|
||||||
|
* @return 支付订单
|
||||||
|
*/
|
||||||
|
private PayOrderDO validatePayOrderCanRefund(PayRefundCreateReqDTO reqDTO) {
|
||||||
|
PayOrderDO order = orderService.getOrder(reqDTO.getAppId(), reqDTO.getMerchantOrderId());
|
||||||
|
if (order == null) {
|
||||||
|
throw exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND);
|
||||||
|
}
|
||||||
|
// 校验状态,必须是支付状态
|
||||||
|
if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) {
|
||||||
|
throw exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否已经全额退款
|
||||||
|
if (PayOrderRefundStatusEnum.ALL.getStatus().equals(order.getRefundStatus())) {
|
||||||
|
throw exception(ErrorCodeConstants.PAY_REFUND_ALL_REFUNDED);
|
||||||
|
}
|
||||||
|
// 校验金额 退款金额不能大于原定的金额
|
||||||
|
if (reqDTO.getPrice() + order.getRefundPrice() > order.getPrice()){
|
||||||
|
throw exception(ErrorCodeConstants.PAY_REFUND_PRICE_EXCEED);
|
||||||
|
}
|
||||||
|
// 是否有退款中的订单
|
||||||
|
if (refundMapper.selectCountByAppIdAndOrderId(reqDTO.getAppId(), order.getId(),
|
||||||
|
PayRefundStatusEnum.WAITING.getStatus()) > 0) {
|
||||||
|
throw exception(ErrorCodeConstants.PAY_REFUND_HAS_REFUNDING);
|
||||||
|
}
|
||||||
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -184,88 +185,80 @@ public class PayRefundServiceImpl implements PayRefundService {
|
|||||||
return payProperties.getCallbackUrl() + "/" + channel.getId();
|
return payProperties.getCallbackUrl() + "/" + channel.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String generateRefundNo() {
|
||||||
|
// wx
|
||||||
|
// 2014
|
||||||
|
// 10
|
||||||
|
// 27
|
||||||
|
// 20
|
||||||
|
// 09
|
||||||
|
// 39
|
||||||
|
// 5522657
|
||||||
|
// a690389285100
|
||||||
|
// 目前的算法
|
||||||
|
// 时间序列,年月日时分秒 14 位
|
||||||
|
// 纯随机,6 位 TODO 芋艿:此处估计是会有问题的,后续在调整
|
||||||
|
return DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmss") + // 时间序列
|
||||||
|
RandomUtil.randomInt(100000, 999999) // 随机。为什么是这个范围,因为偷懒
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void notifyPayRefund(Long channelId, PayRefundRespDTO notify) {
|
public void notifyRefund(Long channelId, PayRefundRespDTO notify) {
|
||||||
|
// 校验支付渠道是否有效
|
||||||
|
channelService.validPayChannel(channelId);
|
||||||
|
// 通知结果
|
||||||
|
|
||||||
// 校验支付渠道是否有效
|
// 校验支付渠道是否有效
|
||||||
// TODO 芋艿:需要重构下这块的逻辑
|
|
||||||
PayChannelDO channel = channelService.validPayChannel(channelId);
|
PayChannelDO channel = channelService.validPayChannel(channelId);
|
||||||
if (PayRefundStatusRespEnum.isSuccess(notify.getStatus())) {
|
|
||||||
payRefundSuccess(notify);
|
|
||||||
} else {
|
|
||||||
// TODO @jason:那这里可以考虑打个 error logger @芋艿 微信是否存在支付异常通知
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void payRefundSuccess(PayRefundRespDTO refundNotify) {
|
|
||||||
// 校验退款单存在
|
|
||||||
PayRefundDO refundDO = null; // TODO 芋艿:临时注释
|
|
||||||
// PayRefundDO refundDO = refundMapper.selectByTradeNoAndMerchantRefundNo(refundNotify.getTradeNo(),
|
|
||||||
// refundNotify.getReqNo());
|
|
||||||
if (refundDO == null) {
|
|
||||||
// TODO 芋艿:临时注释
|
|
||||||
// log.error("[payRefundSuccess][不存在 seqNo 为{} 的支付退款单]", refundNotify.getReqNo());
|
|
||||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_NOT_FOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 得到已退金额
|
|
||||||
PayOrderDO payOrderDO = orderService.getOrder(refundDO.getOrderId());
|
|
||||||
Long refundedAmount = payOrderDO.getRefundPrice();
|
|
||||||
|
|
||||||
PayOrderStatusEnum orderStatus = PayOrderStatusEnum.SUCCESS;
|
|
||||||
if(Objects.equals(payOrderDO.getPrice(), refundedAmount+ refundDO.getRefundPrice())){
|
|
||||||
//支付金额 = 已退金额 + 本次退款金额。
|
|
||||||
orderStatus = PayOrderStatusEnum.CLOSED;
|
|
||||||
}
|
|
||||||
// 更新支付订单
|
|
||||||
PayOrderDO updateOrderDO = new PayOrderDO();
|
|
||||||
updateOrderDO.setId(refundDO.getOrderId())
|
|
||||||
.setRefundPrice(refundedAmount + refundDO.getRefundPrice())
|
|
||||||
.setStatus(orderStatus.getStatus())
|
|
||||||
.setRefundTimes(payOrderDO.getRefundTimes() + 1)
|
|
||||||
.setRefundStatus(refundDO.getType());
|
|
||||||
orderMapper.updateById(updateOrderDO);
|
|
||||||
|
|
||||||
// 更新退款订单
|
// 更新退款订单
|
||||||
PayRefundDO updateRefundDO = new PayRefundDO();
|
TenantUtils.execute(channel.getTenantId(), () -> notifyRefund(channel, notify));
|
||||||
updateRefundDO.setId(refundDO.getId())
|
|
||||||
.setSuccessTime(refundNotify.getSuccessTime())
|
|
||||||
// TODO 芋艿:如下两行,临时注释
|
|
||||||
// .setChannelRefundNo(refundNotify.getChannelOrderNo())
|
|
||||||
// .setNo(refundNotify.getTradeNo())
|
|
||||||
.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
|
|
||||||
refundMapper.updateById(updateRefundDO);
|
|
||||||
|
|
||||||
// 插入退款通知记录
|
|
||||||
// TODO 通知商户成功或者失败. 现在通知似乎没有实现, 只是回调
|
|
||||||
notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
|
|
||||||
.type(PayNotifyTypeEnum.REFUND.getType()).dataId(refundDO.getId()).build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void notifyRefund(PayChannelDO channel, PayRefundRespDTO notify) {
|
||||||
* 校验是否进行退款
|
if (PayRefundStatusRespEnum.isSuccess(notify.getStatus())) {
|
||||||
*
|
notifyRefundSuccess(channel, notify);
|
||||||
* @param reqDTO 退款申请信息
|
} else {
|
||||||
* @param order 原始支付订单信息
|
notifyRefundFailure(channel, notify);
|
||||||
*/
|
|
||||||
private void validatePayRefund(PayRefundCreateReqDTO reqDTO, PayOrderDO order) {
|
|
||||||
// 校验状态,必须是支付状态
|
|
||||||
if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) {
|
|
||||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
// 是否已经全额退款
|
}
|
||||||
if (PayRefundTypeEnum.ALL.getStatus().equals(order.getRefundStatus())) {
|
|
||||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_ALL_REFUNDED);
|
private void notifyRefundSuccess(PayChannelDO channel, PayRefundRespDTO notify) {
|
||||||
|
// 1.1 查询 PayRefundDO
|
||||||
|
PayRefundDO refund = refundMapper.selectByAppIdAndNo(
|
||||||
|
channel.getAppId(), notify.getOutRefundNo());
|
||||||
|
if (refund == null) {
|
||||||
|
throw exception(ErrorCodeConstants.PAY_REFUND_NOT_FOUND);
|
||||||
}
|
}
|
||||||
// 校验金额 退款金额不能大于 原定的金额
|
if (PayRefundStatusEnum.isSuccess(refund.getStatus())) { // 如果已经是成功,直接返回,不用重复更新
|
||||||
if (reqDTO.getPrice() + order.getRefundPrice() > order.getPrice()){
|
return;
|
||||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_PRICE_PRICE_EXCEED);
|
|
||||||
}
|
}
|
||||||
// 校验渠道订单号
|
if (!PayRefundStatusEnum.WAITING.getStatus().equals(refund.getStatus())) {
|
||||||
if (StrUtil.isEmpty(order.getChannelOrderNo())) {
|
throw exception(ErrorCodeConstants.PAY_REFUND_STATUS_IS_NOT_WAITING);
|
||||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_CHN_ORDER_NO_IS_NULL);
|
|
||||||
}
|
}
|
||||||
//TODO 退款的期限 退款次数的控制
|
|
||||||
|
// 1.2 更新 PayRefundDO
|
||||||
|
PayRefundDO updateRefundObj = new PayRefundDO()
|
||||||
|
.setSuccessTime(notify.getSuccessTime())
|
||||||
|
.setChannelRefundNo(notify.getChannelRefundNo())
|
||||||
|
.setStatus(PayRefundStatusEnum.SUCCESS.getStatus())
|
||||||
|
.setChannelNotifyData(toJsonString(notify));
|
||||||
|
int updateCounts = refundMapper.updateByIdAndStatus(refund.getId(), refund.getStatus(), updateRefundObj);
|
||||||
|
if (updateCounts == 0) { // 校验状态,必须是等待状态
|
||||||
|
throw exception(ErrorCodeConstants.PAY_REFUND_STATUS_IS_NOT_WAITING);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 更新订单
|
||||||
|
orderService.updateOrderRefundPrice(refund.getOrderId(), refund.getRefundPrice());
|
||||||
|
|
||||||
|
// 3. 插入退款通知记录
|
||||||
|
notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
|
||||||
|
.type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) {
|
||||||
|
// TODO 芋艿:未实现
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
|
|||||||
import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper;
|
import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper;
|
||||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum;
|
import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
|
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
|
||||||
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
||||||
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
||||||
@ -85,7 +85,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest {
|
|||||||
o.setSuccessTime(LocalDateTime.of(2018, 1, 1, 10, 10, 2));
|
o.setSuccessTime(LocalDateTime.of(2018, 1, 1, 10, 10, 2));
|
||||||
o.setNotifyTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15));
|
o.setNotifyTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15));
|
||||||
o.setSuccessExtensionId(1L);
|
o.setSuccessExtensionId(1L);
|
||||||
o.setRefundStatus(PayRefundTypeEnum.NO.getStatus());
|
o.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus());
|
||||||
o.setRefundTimes(0);
|
o.setRefundTimes(0);
|
||||||
o.setRefundPrice(0L);
|
o.setRefundPrice(0L);
|
||||||
o.setChannelUserId("1008611");
|
o.setChannelUserId("1008611");
|
||||||
@ -106,7 +106,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest {
|
|||||||
// 测试 status 不匹配
|
// 测试 status 不匹配
|
||||||
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus())));
|
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus())));
|
||||||
// 测试 refundStatus 不匹配
|
// 测试 refundStatus 不匹配
|
||||||
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayRefundTypeEnum.ALL.getStatus())));
|
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayOrderRefundStatusEnum.ALL.getStatus())));
|
||||||
// 测试 createTime 不匹配
|
// 测试 createTime 不匹配
|
||||||
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(LocalDateTime.of(2019, 1, 1, 10, 10,
|
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(LocalDateTime.of(2019, 1, 1, 10, 10,
|
||||||
1))));
|
1))));
|
||||||
@ -118,7 +118,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest {
|
|||||||
reqVO.setMerchantOrderId(merchantOrderId);
|
reqVO.setMerchantOrderId(merchantOrderId);
|
||||||
reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
|
reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
|
||||||
reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus());
|
reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus());
|
||||||
reqVO.setRefundStatus(PayRefundTypeEnum.NO.getStatus());
|
reqVO.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus());
|
||||||
reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2018, 1, 1, 10, 1, 0), LocalDateTime.of(2018, 1, 1, 10, 1, 0)}));
|
reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2018, 1, 1, 10, 1, 0), LocalDateTime.of(2018, 1, 1, 10, 1, 0)}));
|
||||||
// 调用
|
// 调用
|
||||||
PageResult<PayOrderDO> pageResult = orderService.getOrderPage(reqVO);
|
PageResult<PayOrderDO> pageResult = orderService.getOrderPage(reqVO);
|
||||||
@ -153,7 +153,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest {
|
|||||||
o.setSuccessTime(LocalDateTime.of(2018, 1, 1, 10, 10, 2));
|
o.setSuccessTime(LocalDateTime.of(2018, 1, 1, 10, 10, 2));
|
||||||
o.setNotifyTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15));
|
o.setNotifyTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15));
|
||||||
o.setSuccessExtensionId(1L);
|
o.setSuccessExtensionId(1L);
|
||||||
o.setRefundStatus(PayRefundTypeEnum.NO.getStatus());
|
o.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus());
|
||||||
o.setRefundTimes(0);
|
o.setRefundTimes(0);
|
||||||
o.setRefundPrice(0L);
|
o.setRefundPrice(0L);
|
||||||
o.setChannelUserId("1008611");
|
o.setChannelUserId("1008611");
|
||||||
@ -175,7 +175,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest {
|
|||||||
// 测试 status 不匹配
|
// 测试 status 不匹配
|
||||||
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus())));
|
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setStatus(PayOrderStatusEnum.CLOSED.getStatus())));
|
||||||
// 测试 refundStatus 不匹配
|
// 测试 refundStatus 不匹配
|
||||||
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayRefundTypeEnum.ALL.getStatus())));
|
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setRefundStatus(PayOrderRefundStatusEnum.ALL.getStatus())));
|
||||||
// 测试 createTime 不匹配
|
// 测试 createTime 不匹配
|
||||||
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(LocalDateTime.of(2019, 1, 1, 10, 10,
|
orderMapper.insert(cloneIgnoreId(dbOrder, o -> o.setCreateTime(LocalDateTime.of(2019, 1, 1, 10, 10,
|
||||||
1))));
|
1))));
|
||||||
@ -187,7 +187,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest {
|
|||||||
reqVO.setMerchantOrderId(merchantOrderId);
|
reqVO.setMerchantOrderId(merchantOrderId);
|
||||||
reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
|
reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
|
||||||
reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus());
|
reqVO.setStatus(PayOrderStatusEnum.SUCCESS.getStatus());
|
||||||
reqVO.setRefundStatus(PayRefundTypeEnum.NO.getStatus());
|
reqVO.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus());
|
||||||
reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2018, 1, 1, 10, 1, 0), LocalDateTime.of(2018, 1, 1, 10, 1, 0)}));
|
reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2018, 1, 1, 10, 1, 0), LocalDateTime.of(2018, 1, 1, 10, 1, 0)}));
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
|
@ -11,7 +11,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
|||||||
import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper;
|
import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper;
|
||||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum;
|
import cn.iocoder.yudao.module.pay.enums.order.PayOrderRefundStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
|
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
|
||||||
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
||||||
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
|
||||||
@ -64,11 +64,11 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
|
|||||||
o.setOrderId(1L);
|
o.setOrderId(1L);
|
||||||
o.setNo("OT0000001");
|
o.setNo("OT0000001");
|
||||||
o.setMerchantOrderId("MOT0000001");
|
o.setMerchantOrderId("MOT0000001");
|
||||||
o.setMerchantRefundNo("MRF0000001");
|
o.setMerchantRefundId("MRF0000001");
|
||||||
o.setNotifyUrl("https://www.cancanzi.com");
|
o.setNotifyUrl("https://www.cancanzi.com");
|
||||||
o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
|
o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
|
||||||
o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
|
o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
|
||||||
o.setType(PayRefundTypeEnum.SOME.getStatus());
|
o.setType(PayOrderRefundStatusEnum.PART.getStatus());
|
||||||
o.setPayPrice(100);
|
o.setPayPrice(100);
|
||||||
o.setRefundPrice(500);
|
o.setRefundPrice(500);
|
||||||
o.setReason("就是想退款了,你有意见吗");
|
o.setReason("就是想退款了,你有意见吗");
|
||||||
@ -77,10 +77,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
|
|||||||
o.setChannelRefundNo("CHR0000001");
|
o.setChannelRefundNo("CHR0000001");
|
||||||
o.setChannelErrorCode("");
|
o.setChannelErrorCode("");
|
||||||
o.setChannelErrorMsg("");
|
o.setChannelErrorMsg("");
|
||||||
o.setChannelExtras("");
|
|
||||||
o.setExpireTime(LocalDateTime.of(2021, 1, 1, 10, 10, 30));
|
|
||||||
o.setSuccessTime(LocalDateTime.of(2021, 1, 1, 10, 10, 15));
|
o.setSuccessTime(LocalDateTime.of(2021, 1, 1, 10, 10, 15));
|
||||||
o.setNotifyTime(LocalDateTime.of(2021, 1, 1, 10, 10, 20));
|
|
||||||
o.setCreateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 10));
|
o.setCreateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 10));
|
||||||
o.setUpdateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 35));
|
o.setUpdateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 35));
|
||||||
});
|
});
|
||||||
@ -90,14 +87,14 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
|
|||||||
// 测试 channelCode 不匹配
|
// 测试 channelCode 不匹配
|
||||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())));
|
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())));
|
||||||
// 测试 merchantRefundNo 不匹配
|
// 测试 merchantRefundNo 不匹配
|
||||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundNo("MRF1111112")));
|
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundId("MRF1111112")));
|
||||||
// 测试 notifyStatus 不匹配
|
// 测试 notifyStatus 不匹配
|
||||||
refundMapper.insert(
|
refundMapper.insert(
|
||||||
cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus())));
|
cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus())));
|
||||||
// 测试 status 不匹配
|
// 测试 status 不匹配
|
||||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.CLOSE.getStatus())));
|
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.FAILURE.getStatus())));
|
||||||
// 测试 type 不匹配
|
// 测试 type 不匹配
|
||||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setType(PayRefundTypeEnum.ALL.getStatus())));
|
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setType(PayOrderRefundStatusEnum.ALL.getStatus())));
|
||||||
// 测试 createTime 不匹配
|
// 测试 createTime 不匹配
|
||||||
refundMapper.insert(cloneIgnoreId(dbRefund, o ->
|
refundMapper.insert(cloneIgnoreId(dbRefund, o ->
|
||||||
o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10))));
|
o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10))));
|
||||||
@ -108,7 +105,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
|
|||||||
reqVO.setMerchantRefundNo("MRF0000001");
|
reqVO.setMerchantRefundNo("MRF0000001");
|
||||||
reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
|
reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
|
||||||
reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
|
reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
|
||||||
reqVO.setType(PayRefundTypeEnum.SOME.getStatus());
|
reqVO.setType(PayOrderRefundStatusEnum.PART.getStatus());
|
||||||
reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2021, 1, 1, 10, 10, 10), LocalDateTime.of(2021, 1, 1, 10, 10, 12)}));
|
reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2021, 1, 1, 10, 10, 10), LocalDateTime.of(2021, 1, 1, 10, 10, 12)}));
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
@ -129,11 +126,11 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
|
|||||||
o.setOrderId(1L);
|
o.setOrderId(1L);
|
||||||
o.setNo("OT0000001");
|
o.setNo("OT0000001");
|
||||||
o.setMerchantOrderId("MOT0000001");
|
o.setMerchantOrderId("MOT0000001");
|
||||||
o.setMerchantRefundNo("MRF0000001");
|
o.setMerchantRefundId("MRF0000001");
|
||||||
o.setNotifyUrl("https://www.cancanzi.com");
|
o.setNotifyUrl("https://www.cancanzi.com");
|
||||||
o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
|
o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
|
||||||
o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
|
o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
|
||||||
o.setType(PayRefundTypeEnum.SOME.getStatus());
|
o.setType(PayOrderRefundStatusEnum.PART.getStatus());
|
||||||
o.setPayPrice(100);
|
o.setPayPrice(100);
|
||||||
o.setRefundPrice(500);
|
o.setRefundPrice(500);
|
||||||
o.setReason("就是想退款了,你有意见吗");
|
o.setReason("就是想退款了,你有意见吗");
|
||||||
@ -142,10 +139,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
|
|||||||
o.setChannelRefundNo("CHR0000001");
|
o.setChannelRefundNo("CHR0000001");
|
||||||
o.setChannelErrorCode("");
|
o.setChannelErrorCode("");
|
||||||
o.setChannelErrorMsg("");
|
o.setChannelErrorMsg("");
|
||||||
o.setChannelExtras("");
|
|
||||||
o.setExpireTime(LocalDateTime.of(2021, 1, 1, 10, 10, 30));
|
|
||||||
o.setSuccessTime(LocalDateTime.of(2021, 1, 1, 10, 10, 15));
|
o.setSuccessTime(LocalDateTime.of(2021, 1, 1, 10, 10, 15));
|
||||||
o.setNotifyTime(LocalDateTime.of(2021, 1, 1, 10, 10, 20));
|
|
||||||
o.setCreateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 10));
|
o.setCreateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 10));
|
||||||
o.setUpdateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 35));
|
o.setUpdateTime(LocalDateTime.of(2021, 1, 1, 10, 10, 35));
|
||||||
});
|
});
|
||||||
@ -155,14 +149,14 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
|
|||||||
// 测试 channelCode 不匹配
|
// 测试 channelCode 不匹配
|
||||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())));
|
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setChannelCode(PayChannelEnum.ALIPAY_APP.getCode())));
|
||||||
// 测试 merchantRefundNo 不匹配
|
// 测试 merchantRefundNo 不匹配
|
||||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundNo("MRF1111112")));
|
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantRefundId("MRF1111112")));
|
||||||
// 测试 notifyStatus 不匹配
|
// 测试 notifyStatus 不匹配
|
||||||
refundMapper.insert(
|
refundMapper.insert(
|
||||||
cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus())));
|
cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus())));
|
||||||
// 测试 status 不匹配
|
// 测试 status 不匹配
|
||||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.CLOSE.getStatus())));
|
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.FAILURE.getStatus())));
|
||||||
// 测试 type 不匹配
|
// 测试 type 不匹配
|
||||||
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setType(PayRefundTypeEnum.ALL.getStatus())));
|
refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setType(PayOrderRefundStatusEnum.ALL.getStatus())));
|
||||||
// 测试 createTime 不匹配
|
// 测试 createTime 不匹配
|
||||||
refundMapper.insert(cloneIgnoreId(dbRefund, o ->
|
refundMapper.insert(cloneIgnoreId(dbRefund, o ->
|
||||||
o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10))));
|
o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10))));
|
||||||
@ -174,7 +168,7 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
|
|||||||
reqVO.setMerchantRefundNo("MRF0000001");
|
reqVO.setMerchantRefundNo("MRF0000001");
|
||||||
reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
|
reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
|
||||||
reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
|
reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
|
||||||
reqVO.setType(PayRefundTypeEnum.SOME.getStatus());
|
reqVO.setType(PayOrderRefundStatusEnum.PART.getStatus());
|
||||||
reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2021, 1, 1, 10, 10, 10), LocalDateTime.of(2021, 1, 1, 10, 10, 12)}));
|
reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2021, 1, 1, 10, 10, 10), LocalDateTime.of(2021, 1, 1, 10, 10, 12)}));
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
|
Loading…
Reference in New Issue
Block a user