将 onemall 老代码,统一到归档目录,后续不断迁移移除
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
package cn.iocoder.mall.pay.api;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.pay.api.bo.refund.PayRefundPageBO;
|
||||
import cn.iocoder.mall.pay.api.bo.refund.PayRefundSubmitBO;
|
||||
import cn.iocoder.mall.pay.api.dto.refund.PayRefundPageDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.refund.PayRefundSubmitDTO;
|
||||
|
||||
public interface PayRefundService {
|
||||
|
||||
CommonResult<PayRefundSubmitBO> submitRefund(PayRefundSubmitDTO payRefundSubmitDTO);
|
||||
|
||||
/**
|
||||
* 更新退款支付成功
|
||||
*
|
||||
* 该接口用于不同支付平台,退款成功后,回调该接口
|
||||
*
|
||||
* @param payChannel 支付渠道
|
||||
* @param params 回调参数。
|
||||
* 因为不同平台,能够提供的参数不同,所以使用 String 类型统一接收,然后在使用不同的 AbstractPaySDK 进行处理。
|
||||
* @return 是否支付成功
|
||||
*/
|
||||
CommonResult<Boolean> updateRefundSuccess(Integer payChannel, String params);
|
||||
|
||||
PayRefundPageBO getRefundPage(PayRefundPageDTO payRefundPageDTO);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package cn.iocoder.mall.pay.api.bo.refund;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 支付退款 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayRefundBO {
|
||||
|
||||
/**
|
||||
* 编号,自增
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 支付交易编号
|
||||
*/
|
||||
private Integer transactionId;
|
||||
/**
|
||||
* 生成传输给第三方的退款号
|
||||
*
|
||||
* 唯一索引
|
||||
*/
|
||||
private String refundCode;
|
||||
/**
|
||||
* 应用编号
|
||||
*
|
||||
* 不同业务线分配不同的 appId
|
||||
* 举个例子,
|
||||
* 1. 电商系统的订单,appId = 1024
|
||||
* 2. 活动系统的订单,appId = 2048
|
||||
*/
|
||||
private String appId;
|
||||
/**
|
||||
* 业务线的订单编号
|
||||
*
|
||||
* 1. 使用 String 的原因是,业务线可能使用 String 做为编号
|
||||
* 2. 每个 appId 下,orderId 唯一
|
||||
*/
|
||||
private String orderId;
|
||||
/**
|
||||
* 发起交易的 IP
|
||||
*/
|
||||
private String createIp;
|
||||
/**
|
||||
* 业务退款描述
|
||||
*/
|
||||
private String orderDescription;
|
||||
/**
|
||||
* 退款金额,单位:分。
|
||||
*
|
||||
* TODO 暂时不考虑货币类型。
|
||||
*/
|
||||
private Integer price;
|
||||
/**
|
||||
* 退款状态
|
||||
*
|
||||
* @see cn.iocoder.mall.pay.api.constant.PayRefundStatus
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 回调业务线完成时间
|
||||
*/
|
||||
private Date finishTime;
|
||||
/**
|
||||
* 异步通知地址
|
||||
*/
|
||||
private String notifyUrl;
|
||||
/**
|
||||
* 扩展内容
|
||||
*
|
||||
* 异步通知的时候填充回调的数据
|
||||
*/
|
||||
private String extensionData;
|
||||
/**
|
||||
* 退款渠道
|
||||
*/
|
||||
private Integer refundChannel;
|
||||
/**
|
||||
* 第三方退款成功的时间
|
||||
*/
|
||||
private Date refundTime;
|
||||
/**
|
||||
* 收到第三方系统通知的时间
|
||||
*
|
||||
* 一般情况下,即第三方系统的异步通知
|
||||
*/
|
||||
private Date notifyTime;
|
||||
/**
|
||||
* 第三方的流水号
|
||||
*/
|
||||
private String tradeNo;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.mall.pay.api.bo.refund;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 支付退款 Page BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayRefundPageBO implements Serializable {
|
||||
|
||||
/**
|
||||
* 支付退款数组
|
||||
*/
|
||||
private List<PayRefundBO> list;
|
||||
/**
|
||||
* 总量
|
||||
*/
|
||||
private Integer total;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package cn.iocoder.mall.pay.api.bo.refund;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 退款单结果 BO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayRefundSubmitBO {
|
||||
|
||||
/**
|
||||
* 退款
|
||||
*/
|
||||
private Integer id;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package cn.iocoder.mall.pay.api.dto.refund;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 支付退款分页 DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayRefundPageDTO {
|
||||
|
||||
/**
|
||||
* 创建时间(开始)
|
||||
*/
|
||||
private Date createBeginTime;
|
||||
/**
|
||||
* 创建时间(结束)
|
||||
*/
|
||||
private Date createEndTime;
|
||||
/**
|
||||
* 完成时间(开始)
|
||||
*/
|
||||
private Date finishBeginTime;
|
||||
/**
|
||||
* 完成时间(结束)
|
||||
*/
|
||||
private Date finishEndTime;
|
||||
/**
|
||||
* 退款状态
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 支付渠道
|
||||
*/
|
||||
private Integer payChannel;
|
||||
|
||||
@NotNull(message = "页码不能为空")
|
||||
private Integer pageNo;
|
||||
@NotNull(message = "每页条数不能为空")
|
||||
private Integer pageSize;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package cn.iocoder.mall.pay.api.dto.refund;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.DecimalMin;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 支付退款创建 DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayRefundSubmitDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 应用编号
|
||||
*/
|
||||
@NotEmpty(message = "应用编号不能为空")
|
||||
private String appId;
|
||||
/**
|
||||
* 发起交易的 IP
|
||||
*/
|
||||
@NotEmpty(message = "IP 不能为空")
|
||||
private String createIp;
|
||||
/**
|
||||
* 业务线的订单编号
|
||||
*/
|
||||
@NotEmpty(message = "订单号不能为空")
|
||||
private String orderId;
|
||||
/**
|
||||
* 退款描述
|
||||
*/
|
||||
@NotEmpty(message = "退款描述不能为空")
|
||||
@Length(max = 128, message = "退款描述长度不能超过128")
|
||||
private String orderDescription;
|
||||
/**
|
||||
* 支付金额,单位:分。
|
||||
*/
|
||||
@NotNull(message = "金额不能为空")
|
||||
@DecimalMin(value = "0", inclusive = false, message = "金额必须大于零")
|
||||
private Integer price;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package cn.iocoder.mall.pay.application.controller.admins;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.pay.api.PayRefundService;
|
||||
import cn.iocoder.mall.pay.api.PayTransactionService;
|
||||
import cn.iocoder.mall.pay.api.bo.refund.PayRefundBO;
|
||||
import cn.iocoder.mall.pay.api.bo.refund.PayRefundPageBO;
|
||||
import cn.iocoder.mall.pay.api.bo.transaction.PayTransactionBO;
|
||||
import cn.iocoder.mall.pay.api.dto.refund.PayRefundPageDTO;
|
||||
import cn.iocoder.mall.pay.application.convert.PayRefundConvert;
|
||||
import cn.iocoder.mall.pay.application.vo.admins.AdminsPayRefundPageVO;
|
||||
import org.apache.dubbo.config.annotation.Reference;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.common.framework.vo.CommonResult.success;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("admins/refund")
|
||||
public class AdminsPayRefundController {
|
||||
|
||||
@Reference(validation = "true", version = "${dubbo.provider.PayRefundService.version}")
|
||||
private PayRefundService payRefundService;
|
||||
@Reference(validation = "true", version = "${dubbo.provider.PayTransactionService.version}")
|
||||
private PayTransactionService payTransactionService;
|
||||
|
||||
@GetMapping("/page")
|
||||
public CommonResult<AdminsPayRefundPageVO> page(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@RequestParam(value = "createBeginTime", required = false) Date createBeginTime,
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@RequestParam(value = "createEndTime", required = false) Date createEndTime,
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@RequestParam(value = "finishBeginTime", required = false) Date finishBeginTime,
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@RequestParam(value = "finishEndTime", required = false) Date finishEndTime,
|
||||
@RequestParam(value = "status", required = false) Integer status,
|
||||
@RequestParam(value = "payChannel", required = false) Integer payChannel,
|
||||
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
|
||||
PayRefundPageDTO payRefundPageDTO = new PayRefundPageDTO()
|
||||
.setCreateBeginTime(createBeginTime).setCreateEndTime(createEndTime)
|
||||
.setFinishBeginTime(finishBeginTime).setFinishEndTime(finishEndTime)
|
||||
.setStatus(status).setPayChannel(payChannel)
|
||||
.setPageNo(pageNo).setPageSize(pageSize);
|
||||
// 执行查询
|
||||
PayRefundPageBO refundBOPage = payRefundService.getRefundPage(payRefundPageDTO);
|
||||
AdminsPayRefundPageVO result = new AdminsPayRefundPageVO()
|
||||
.setList(PayRefundConvert.INSTANCE.convertList(refundBOPage.getList()))
|
||||
.setTotal(refundBOPage.getTotal());
|
||||
if (result.getList().isEmpty()) {
|
||||
return success(result);
|
||||
}
|
||||
// 拼接结果
|
||||
Map<Integer, PayTransactionBO> transactionMap = payTransactionService.getTransactionList(
|
||||
result.getList().stream().map(PayRefundBO::getTransactionId).collect(Collectors.toSet()))
|
||||
.stream().collect(Collectors.toMap(PayTransactionBO::getId, transaction -> transaction));
|
||||
result.getList().forEach(refund -> refund.setTransaction(transactionMap.get(refund.getTransactionId())));
|
||||
return success(result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package cn.iocoder.mall.pay.application.vo.admins;
|
||||
|
||||
import cn.iocoder.mall.pay.api.bo.refund.PayRefundBO;
|
||||
import cn.iocoder.mall.pay.api.bo.transaction.PayTransactionBO;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 支付退款详细 VO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminsPayRefundDetailVO extends PayRefundBO { // TODO 芋艿,暂时偷懒下
|
||||
|
||||
/**
|
||||
* 支付交易
|
||||
*/
|
||||
private PayTransactionBO transaction;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.mall.pay.application.vo.admins;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 支付退款 Page VO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AdminsPayRefundPageVO implements Serializable {
|
||||
|
||||
/**
|
||||
* 支付退款数组
|
||||
*/
|
||||
private List<AdminsPayRefundDetailVO> list;
|
||||
/**
|
||||
* 总量
|
||||
*/
|
||||
private Integer total;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
package cn.iocoder.mall.pay.biz.service;
|
||||
|
||||
import cn.iocoder.common.framework.util.DateUtil;
|
||||
import cn.iocoder.common.framework.util.MathUtil;
|
||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.pay.api.PayRefundService;
|
||||
import cn.iocoder.mall.pay.api.bo.refund.PayRefundPageBO;
|
||||
import cn.iocoder.mall.pay.api.bo.refund.PayRefundSubmitBO;
|
||||
import cn.iocoder.mall.pay.api.constant.PayErrorCodeEnum;
|
||||
import cn.iocoder.mall.pay.api.constant.PayRefundStatus;
|
||||
import cn.iocoder.mall.pay.api.constant.PayTransactionStatusEnum;
|
||||
import cn.iocoder.mall.pay.api.dto.refund.PayRefundPageDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.refund.PayRefundSubmitDTO;
|
||||
import cn.iocoder.mall.pay.biz.client.AbstractPaySDK;
|
||||
import cn.iocoder.mall.pay.biz.client.PaySDKFactory;
|
||||
import cn.iocoder.mall.pay.biz.client.RefundSuccessBO;
|
||||
import cn.iocoder.mall.pay.biz.convert.PayRefundConvert;
|
||||
import cn.iocoder.mall.pay.biz.dao.PayRefundMapper;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayAppDO;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayRefundDO;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayTransactionDO;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayTransactionExtensionDO;
|
||||
import org.apache.rocketmq.spring.core.RocketMQTemplate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
|
||||
@Service
|
||||
@org.apache.dubbo.config.annotation.Service(validation = "true", version = "${dubbo.provider.PayRefundService.version}")
|
||||
public class PayRefundServiceImpl implements PayRefundService {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Autowired
|
||||
private PayRefundMapper payRefundMapper;
|
||||
|
||||
@Autowired
|
||||
private PayAppServiceImpl payAppService;
|
||||
@Autowired
|
||||
private PayNotifyServiceImpl payNotifyService;
|
||||
@Autowired
|
||||
private PayTransactionServiceImpl payTransactionService;
|
||||
|
||||
@Resource
|
||||
private RocketMQTemplate rocketMQTemplate;
|
||||
|
||||
@Override
|
||||
public CommonResult<PayRefundSubmitBO> submitRefund(PayRefundSubmitDTO payRefundSubmitDTO) {
|
||||
// 校验 App 是否有效
|
||||
PayAppDO payAppDO = payAppService.validPayApp(payRefundSubmitDTO.getAppId());
|
||||
// 获得 PayTransactionDO ,并校验其是否存在
|
||||
PayTransactionDO payTransaction = payTransactionService.getTransaction(payRefundSubmitDTO.getAppId(), payRefundSubmitDTO.getOrderId());
|
||||
if (payTransaction == null) { // 是否存在
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
|
||||
}
|
||||
if (!PayTransactionStatusEnum.SUCCESS.getValue().equals(payTransaction.getStatus())) { // 校验状态,必须是待支付
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_STATUS_IS_NOT_SUCCESS.getCode());
|
||||
}
|
||||
if (payRefundSubmitDTO.getPrice() > payTransaction.getPrice() - payTransaction.getRefundTotal()) { // 金额校验
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_REFUND_PRICE_EXCEED.getCode());
|
||||
}
|
||||
// 获得 PayTransactionExtensionDO ,并校验其是否存在
|
||||
PayTransactionExtensionDO payTransactionExtension = payTransactionService.getPayTransactionExtension(payTransaction.getExtensionId());
|
||||
if (payTransactionExtension == null) { // 是否存在
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_EXTENSION_NOT_FOUND.getCode());
|
||||
}
|
||||
if (!PayTransactionStatusEnum.SUCCESS.getValue().equals(payTransactionExtension.getStatus())) { // 校验状态,必须是待支付
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_EXTENSION_STATUS_IS_NOT_SUCCESS.getCode());
|
||||
}
|
||||
// 插入 PayTransactionExtensionDO
|
||||
PayRefundDO payRefundDO = PayRefundConvert.INSTANCE.convert(payRefundSubmitDTO)
|
||||
.setTransactionId(payTransaction.getId())
|
||||
.setRefundCode(generateTransactionCode()) // TODO 芋艿,后续调整
|
||||
.setStatus(PayRefundStatus.WAITING.getValue())
|
||||
.setNotifyUrl(payAppDO.getRefundNotifyUrl())
|
||||
.setRefundChannel(payTransaction.getPayChannel());
|
||||
payRefundDO.setCreateTime(new Date());
|
||||
payRefundMapper.insert(payRefundDO);
|
||||
// 调用三方接口
|
||||
AbstractPaySDK paySDK = PaySDKFactory.getSDK(payTransaction.getPayChannel());
|
||||
CommonResult<String> invokeResult = paySDK.submitRefund(payRefundDO, payTransactionExtension, null); // TODO 暂时传入 extra = null
|
||||
if (invokeResult.isError()) {
|
||||
return CommonResult.error(invokeResult);
|
||||
}
|
||||
// 返回成功
|
||||
PayRefundSubmitBO payRefundSubmitBO = new PayRefundSubmitBO()
|
||||
.setId(payRefundDO.getId());
|
||||
return CommonResult.success(payRefundSubmitBO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CommonResult<Boolean> updateRefundSuccess(Integer payChannel, String params) {
|
||||
// TODO 芋艿,记录回调日志
|
||||
// 解析传入的参数,成 TransactionSuccessBO 对象
|
||||
AbstractPaySDK paySDK = PaySDKFactory.getSDK(payChannel);
|
||||
CommonResult<RefundSuccessBO> paySuccessResult = paySDK.parseRefundSuccessParams(params);
|
||||
if (paySuccessResult.isError()) {
|
||||
return CommonResult.error(paySuccessResult);
|
||||
}
|
||||
// TODO 芋艿,先最严格的校验。即使调用方重复调用,实际哪个订单已经被重复回调的支付,也返回 false 。也没问题,因为实际已经回调成功了。
|
||||
// 1.1 查询 PayRefundDO
|
||||
PayRefundDO payRefund = payRefundMapper.selectByRefundCode(paySuccessResult.getData().getRefundCode());
|
||||
if (payRefund == null) {
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_REFUND_NOT_FOUND.getCode());
|
||||
}
|
||||
if (!PayRefundStatus.WAITING.getValue().equals(payRefund.getStatus())) { // 校验状态,必须是待支付
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_REFUND_STATUS_NOT_WAITING.getCode());
|
||||
}
|
||||
// 1.2 更新 PayRefundDO
|
||||
Integer status = paySuccessResult.getData().getSuccess() ? PayRefundStatus.SUCCESS.getValue() : PayRefundStatus.FAILURE.getValue();
|
||||
PayRefundDO updatePayRefundDO = new PayRefundDO()
|
||||
.setId(payRefund.getId())
|
||||
.setStatus(status)
|
||||
.setTradeNo(paySuccessResult.getData().getTradeNo())
|
||||
.setExtensionData(params);
|
||||
int updateCounts = payRefundMapper.update(updatePayRefundDO, PayRefundStatus.WAITING.getValue());
|
||||
if (updateCounts == 0) { // 校验状态,必须是待支付
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_REFUND_STATUS_NOT_WAITING.getCode());
|
||||
}
|
||||
// 2.1 判断 PayTransactionDO ,增加已退款金额
|
||||
PayTransactionDO payTransaction = payTransactionService.getTransaction(payRefund.getTransactionId());
|
||||
if (payTransaction == null) {
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
|
||||
}
|
||||
if (!PayTransactionStatusEnum.SUCCESS.getValue().equals(payTransaction.getStatus())) { // 校验状态,必须是已支付
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_STATUS_IS_NOT_SUCCESS.getCode());
|
||||
}
|
||||
if (payRefund.getPrice() + payTransaction.getRefundTotal() > payTransaction.getPrice()) {
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_REFUND_PRICE_EXCEED.getCode());
|
||||
}
|
||||
// 2.2 更新 PayTransactionDO
|
||||
updateCounts = payTransactionService.updateTransactionPriceTotalIncr(payRefund.getTransactionId(), payRefund.getPrice());
|
||||
if (updateCounts == 0) { // 保证不超退 TODO 这种类型,需要思考下。需要返回错误,但是又要保证事务回滚
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_REFUND_PRICE_EXCEED.getCode());
|
||||
}
|
||||
// 3 新增 PayNotifyTaskDO
|
||||
payNotifyService.addRefundNotifyTask(payRefund);
|
||||
// 返回结果
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayRefundPageBO getRefundPage(PayRefundPageDTO payRefundPageDTO) {
|
||||
PayRefundPageBO payRefundPageBO = new PayRefundPageBO();
|
||||
// 查询分页数据
|
||||
int offset = (payRefundPageDTO.getPageNo() - 1) * payRefundPageDTO.getPageSize();
|
||||
payRefundPageBO.setList(PayRefundConvert.INSTANCE.convertList(payRefundMapper.selectListByPage(
|
||||
payRefundPageDTO.getCreateBeginTime(), payRefundPageDTO.getCreateEndTime(),
|
||||
payRefundPageDTO.getFinishBeginTime(), payRefundPageDTO.getFinishEndTime(),
|
||||
payRefundPageDTO.getStatus(), payRefundPageDTO.getPayChannel(),
|
||||
offset, payRefundPageDTO.getPageSize())));
|
||||
// 查询分页总数
|
||||
payRefundPageBO.setTotal(payRefundMapper.selectCountByPage(
|
||||
payRefundPageDTO.getCreateBeginTime(), payRefundPageDTO.getCreateEndTime(),
|
||||
payRefundPageDTO.getFinishBeginTime(), payRefundPageDTO.getFinishEndTime(),
|
||||
payRefundPageDTO.getStatus(), payRefundPageDTO.getPayChannel()));
|
||||
return payRefundPageBO;
|
||||
}
|
||||
|
||||
private String generateTransactionCode() {
|
||||
// wx
|
||||
// 2014
|
||||
// 10
|
||||
// 27
|
||||
// 20
|
||||
// 09
|
||||
// 39
|
||||
// 5522657
|
||||
// a690389285100
|
||||
// 目前的算法
|
||||
// 时间序列,年月日时分秒 14 位
|
||||
// 纯随机,6 位 TODO 此处估计是会有问题的,后续在调整
|
||||
return DateUtil.format(new Date(), "yyyyMMddHHmmss") + // 时间序列
|
||||
MathUtil.random(100000, 999999) // 随机。为什么是这个范围,因为偷懒
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package cn.iocoder.mall.pay.biz.service;
|
||||
|
||||
import cn.iocoder.common.framework.util.DateUtil;
|
||||
import cn.iocoder.common.framework.util.MathUtil;
|
||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.pay.api.PayTransactionService;
|
||||
import cn.iocoder.mall.pay.api.bo.transaction.PayTransactionBO;
|
||||
import cn.iocoder.mall.pay.api.bo.transaction.PayTransactionPageBO;
|
||||
import cn.iocoder.mall.pay.api.bo.transaction.PayTransactionSubmitBO;
|
||||
import cn.iocoder.mall.pay.api.constant.PayErrorCodeEnum;
|
||||
import cn.iocoder.mall.pay.api.constant.PayTransactionStatusEnum;
|
||||
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionCreateDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionGetDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionPageDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionSubmitDTO;
|
||||
import cn.iocoder.mall.pay.biz.client.AbstractPaySDK;
|
||||
import cn.iocoder.mall.pay.biz.client.PaySDKFactory;
|
||||
import cn.iocoder.mall.pay.biz.client.TransactionSuccessBO;
|
||||
import cn.iocoder.mall.pay.biz.convert.PayTransactionConvert;
|
||||
import cn.iocoder.mall.pay.biz.dao.PayNotifyTaskMapper;
|
||||
import cn.iocoder.mall.pay.biz.dao.PayTransactionExtensionMapper;
|
||||
import cn.iocoder.mall.pay.biz.dao.PayTransactionMapper;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayAppDO;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayTransactionDO;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayTransactionExtensionDO;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@org.apache.dubbo.config.annotation.Service(validation = "true", version = "${dubbo.provider.PayTransactionService.version}")
|
||||
public class PayTransactionServiceImpl implements PayTransactionService {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package cn.iocoder.mall.pay.biz.service;
|
||||
|
||||
import cn.iocoder.mall.pay.api.PayRefundService;
|
||||
import cn.iocoder.mall.pay.api.dto.refund.PayRefundSubmitDTO;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
public class PayRefundServiceImplTest {
|
||||
|
||||
@Autowired
|
||||
private PayRefundService payRefundService;
|
||||
|
||||
@Test
|
||||
public void testSubmitRefund() {
|
||||
PayRefundSubmitDTO payRefundSubmitDTO = new PayRefundSubmitDTO()
|
||||
.setAppId("POd4RC6a")
|
||||
.setCreateIp("127.0.0.1")
|
||||
.setOrderId("13500000")
|
||||
.setOrderDescription("测试下退款")
|
||||
.setPrice(1);
|
||||
payRefundService.submitRefund(payRefundSubmitDTO);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user