1. 迁移支付交易的提交 RPC 接口
2. 迁移支付交易的获取 RPC 接口
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.mall.payservice.rpc.transaction;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionCreateReqDTO;
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.*;
|
||||
|
||||
/**
|
||||
* 支付交易单 RPC 接口
|
||||
@@ -16,4 +16,20 @@ public interface PayTransactionRpc {
|
||||
*/
|
||||
CommonResult<Integer> createPayTransaction(PayTransactionCreateReqDTO createReqDTO);
|
||||
|
||||
/**
|
||||
* 提交支付交易单
|
||||
*
|
||||
* @param submitReqDTO 提交信息
|
||||
* @return 提交响应,包含三方支付的响应
|
||||
*/
|
||||
CommonResult<PayTransactionSubmitRespDTO> submitPayTransaction(PayTransactionSubmitReqDTO submitReqDTO);
|
||||
|
||||
/**
|
||||
* 获得当支付交易单
|
||||
*
|
||||
* @param getReqDTO 获得条件
|
||||
* @return 支付交易单
|
||||
*/
|
||||
CommonResult<PayTransactionRespDTO> getPayTransaction(PayTransactionGetReqDTO getReqDTO);
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,12 @@ import java.util.Date;
|
||||
@Accessors(chain = true)
|
||||
public class PayTransactionCreateReqDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Integer userId;
|
||||
|
||||
/**
|
||||
* 应用编号
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.iocoder.mall.payservice.rpc.transaction.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* 支付交易获得 Request DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayTransactionGetReqDTO {
|
||||
|
||||
/**
|
||||
* 应用编号
|
||||
*/
|
||||
@NotEmpty(message = "应用编号不能为空")
|
||||
private String appId;
|
||||
|
||||
/**
|
||||
* 订单号
|
||||
*/
|
||||
@NotEmpty(message = "订单号不能为空")
|
||||
private String orderId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package cn.iocoder.mall.payservice.rpc.transaction.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 支付交易 Response DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayTransactionRespDTO {
|
||||
|
||||
/**
|
||||
* 编号,自增
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Integer userId;
|
||||
/**
|
||||
* 应用编号
|
||||
*/
|
||||
private String appId;
|
||||
/**
|
||||
* 发起交易的 IP
|
||||
*/
|
||||
private String createIp;
|
||||
/**
|
||||
* 业务线的订单编号
|
||||
*/
|
||||
private String orderId;
|
||||
/**
|
||||
* 订单商品名
|
||||
*/
|
||||
private String orderSubject;
|
||||
/**
|
||||
* 订单商品描述
|
||||
*/
|
||||
private String orderDescription;
|
||||
/**
|
||||
* 订单备注
|
||||
*/
|
||||
private String orderMemo;
|
||||
/**
|
||||
* 支付金额,单位:分。
|
||||
*/
|
||||
private Integer price;
|
||||
/**
|
||||
* 订单状态
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 交易过期时间
|
||||
*/
|
||||
private Date expireTime;
|
||||
/**
|
||||
* 回调业务线完成时间
|
||||
*/
|
||||
private Date finishTime;
|
||||
/**
|
||||
* 异步通知地址
|
||||
*/
|
||||
private String notifyUrl;
|
||||
/**
|
||||
* 成功支付的交易拓展编号
|
||||
*/
|
||||
private Integer extensionId;
|
||||
/**
|
||||
* 支付成功的支付渠道
|
||||
*/
|
||||
private Integer payChannel;
|
||||
/**
|
||||
* 第三方支付成功的时间
|
||||
*/
|
||||
private Date paymentTime;
|
||||
/**
|
||||
* 收到第三方系统通知的时间
|
||||
*/
|
||||
private Date notifyTime;
|
||||
/**
|
||||
* 第三方的流水号
|
||||
*/
|
||||
private String tradeNo;
|
||||
/**
|
||||
* 退款总金额
|
||||
*/
|
||||
private Integer refundTotal;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package cn.iocoder.mall.payservice.rpc.transaction.dto;
|
||||
|
||||
import cn.iocoder.common.framework.validator.InEnum;
|
||||
import cn.iocoder.mall.payservice.enums.PayChannelEnum;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 支付交易提交 Request VO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayTransactionSubmitReqDTO {
|
||||
|
||||
/**
|
||||
* 应用编号
|
||||
*/
|
||||
@NotEmpty(message = "应用编号不能为空")
|
||||
private String appId;
|
||||
|
||||
/**
|
||||
* 发起交易的 IP
|
||||
*/
|
||||
@NotEmpty(message = "IP 不能为空")
|
||||
private String createIp;
|
||||
|
||||
/**
|
||||
* 订单号
|
||||
*/
|
||||
@NotEmpty(message = "订单号不能为空")
|
||||
private String orderId;
|
||||
|
||||
/**
|
||||
* 支付渠道
|
||||
*/
|
||||
@InEnum(value = PayChannelEnum.class, message = "支付渠道必须是 {value}")
|
||||
@NotNull(message = "支付渠道")
|
||||
private Integer payChannel;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.mall.payservice.rpc.transaction.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 支付交易提交 Response DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayTransactionSubmitRespDTO {
|
||||
|
||||
/**
|
||||
* 支付交易拓展单编号
|
||||
*/
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 调用三方平台的响应结果
|
||||
*/
|
||||
private String invokeResponse;
|
||||
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import cn.iocoder.mall.payservice.enums.PayChannelEnum;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class PaySDKFactory {
|
||||
public class ThirdPayClientFactory {
|
||||
|
||||
private static Map<Integer, AbstractThirdPayClient> CLIENTS = new HashMap<>();
|
||||
|
||||
@@ -13,7 +13,7 @@ public class PaySDKFactory {
|
||||
CLIENTS.put(PayChannelEnum.PINGXX.getId(), new PingxxThirdPayClient());
|
||||
}
|
||||
|
||||
public static AbstractThirdPayClient getSDK(Integer payChannel) {
|
||||
public static AbstractThirdPayClient getThirdPayClient(Integer payChannel) {
|
||||
AbstractThirdPayClient client = CLIENTS.get(payChannel);
|
||||
if (client == null) {
|
||||
throw new NullPointerException("找不到合适的 ThirdPayClient :" + payChannel);
|
||||
@@ -1,7 +1,10 @@
|
||||
package cn.iocoder.mall.payservice.convert.transaction;
|
||||
|
||||
import cn.iocoder.mall.payservice.dal.mysql.dataobject.transaction.PayTransactionDO;
|
||||
import cn.iocoder.mall.payservice.dal.mysql.dataobject.transaction.PayTransactionExtensionDO;
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionCreateReqDTO;
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionRespDTO;
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionSubmitReqDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@@ -12,4 +15,8 @@ public interface PayTransactionConvert {
|
||||
|
||||
PayTransactionDO convert(PayTransactionCreateReqDTO bean);
|
||||
|
||||
PayTransactionExtensionDO convert(PayTransactionSubmitReqDTO bean);
|
||||
|
||||
PayTransactionRespDTO convert(PayTransactionDO bean);
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,10 @@ public class PayRefundDO extends DeletableDO {
|
||||
* 编号,自增
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Integer userId;
|
||||
/**
|
||||
* 支付交易编号
|
||||
*/
|
||||
|
||||
@@ -23,6 +23,10 @@ public class PayTransactionDO extends DeletableDO {
|
||||
*/
|
||||
@TableId
|
||||
private Integer id;
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Integer userId;
|
||||
/**
|
||||
* 应用编号
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package cn.iocoder.mall.payservice.dal.mysql.mapper.transaction;
|
||||
|
||||
import cn.iocoder.mall.payservice.dal.mysql.dataobject.transaction.PayTransactionExtensionDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface PayTransactionExtensionMapper extends BaseMapper<PayTransactionExtensionDO> {
|
||||
|
||||
default int update(PayTransactionExtensionDO entity, Integer whereStatus) {
|
||||
return update(entity, new QueryWrapper<PayTransactionExtensionDO>()
|
||||
.eq("id", entity.getId()).eq("status", whereStatus));
|
||||
}
|
||||
|
||||
default PayTransactionExtensionDO selectByTransactionCode(String transactionCode) {
|
||||
return selectOne(new QueryWrapper<PayTransactionExtensionDO>()
|
||||
.eq("transaction_code", transactionCode));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.mall.payservice.rpc.transaction;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionCreateReqDTO;
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.*;
|
||||
import cn.iocoder.mall.payservice.service.transaction.PayTransactionService;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -19,4 +19,14 @@ public class PayTransactionRpcImpl implements PayTransactionRpc {
|
||||
return success(payTransactionService.createPayTransaction(createReqDTO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<PayTransactionSubmitRespDTO> submitPayTransaction(PayTransactionSubmitReqDTO submitReqDTO) {
|
||||
return success(payTransactionService.submitPayTransaction(submitReqDTO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<PayTransactionRespDTO> getPayTransaction(PayTransactionGetReqDTO getReqDTO) {
|
||||
return success(payTransactionService.getPayTransaction(getReqDTO));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package cn.iocoder.mall.payservice.service.transaction;
|
||||
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionCreateReqDTO;
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.*;
|
||||
|
||||
/**
|
||||
* 支付交易单 Service 接口
|
||||
@@ -15,4 +15,20 @@ public interface PayTransactionService {
|
||||
*/
|
||||
Integer createPayTransaction(PayTransactionCreateReqDTO createReqDTO);
|
||||
|
||||
/**
|
||||
* 提交支付交易单
|
||||
*
|
||||
* @param submitReqDTO 提交信息
|
||||
* @return 提交响应,包含三方支付的响应
|
||||
*/
|
||||
PayTransactionSubmitRespDTO submitPayTransaction(PayTransactionSubmitReqDTO submitReqDTO);
|
||||
|
||||
/**
|
||||
* 获得当支付交易单
|
||||
*
|
||||
* @param getReqDTO 获得条件
|
||||
* @return 支付交易单
|
||||
*/
|
||||
PayTransactionRespDTO getPayTransaction(PayTransactionGetReqDTO getReqDTO);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
package cn.iocoder.mall.payservice.service.transaction.impl;
|
||||
|
||||
import cn.iocoder.common.framework.exception.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.common.framework.util.DateUtil;
|
||||
import cn.iocoder.common.framework.util.MathUtil;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.payservice.client.thirdpay.AbstractThirdPayClient;
|
||||
import cn.iocoder.mall.payservice.client.thirdpay.ThirdPayClientFactory;
|
||||
import cn.iocoder.mall.payservice.convert.transaction.PayTransactionConvert;
|
||||
import cn.iocoder.mall.payservice.dal.mysql.dataobject.transaction.PayTransactionDO;
|
||||
import cn.iocoder.mall.payservice.dal.mysql.dataobject.transaction.PayTransactionExtensionDO;
|
||||
import cn.iocoder.mall.payservice.dal.mysql.mapper.transaction.PayTransactionExtensionMapper;
|
||||
import cn.iocoder.mall.payservice.dal.mysql.mapper.transaction.PayTransactionMapper;
|
||||
import cn.iocoder.mall.payservice.enums.transaction.PayTransactionStatusEnum;
|
||||
import cn.iocoder.mall.payservice.rpc.app.dto.PayAppRespDTO;
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionCreateReqDTO;
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.*;
|
||||
import cn.iocoder.mall.payservice.service.app.PayAppService;
|
||||
import cn.iocoder.mall.payservice.service.transaction.PayTransactionService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -13,6 +21,11 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static cn.iocoder.mall.payservice.enums.PayErrorCodeConstants.PAY_TRANSACTION_NOT_FOUND;
|
||||
import static cn.iocoder.mall.payservice.enums.PayErrorCodeConstants.PAY_TRANSACTION_STATUS_IS_NOT_WAITING;
|
||||
|
||||
/**
|
||||
* 支付交易单 Service 实现类
|
||||
*/
|
||||
@@ -23,6 +36,8 @@ public class PayTransactionServiceImpl implements PayTransactionService {
|
||||
|
||||
@Autowired
|
||||
private PayTransactionMapper payTransactionMapper;
|
||||
@Autowired
|
||||
private PayTransactionExtensionMapper payTransactionExtensionMapper;
|
||||
|
||||
@Autowired
|
||||
private PayAppService payAppService;
|
||||
@@ -50,4 +65,60 @@ public class PayTransactionServiceImpl implements PayTransactionService {
|
||||
return payTransaction.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayTransactionSubmitRespDTO submitPayTransaction(PayTransactionSubmitReqDTO submitReqDTO) {
|
||||
// TODO 校验支付渠道是否有效
|
||||
// 校验 App 是否有效
|
||||
payAppService.validPayApp(submitReqDTO.getAppId());
|
||||
|
||||
// 获得 PayTransactionDO ,并校验其是否存在
|
||||
PayTransactionDO payTransaction = payTransactionMapper.selectByAppIdAndOrderId(
|
||||
submitReqDTO.getAppId(), submitReqDTO.getOrderId());
|
||||
if (payTransaction == null) { // 是否存在
|
||||
throw ServiceExceptionUtil.exception(PAY_TRANSACTION_NOT_FOUND);
|
||||
}
|
||||
if (!PayTransactionStatusEnum.WAITING.getValue().equals(payTransaction.getStatus())) { // 校验状态,必须是待支付
|
||||
throw ServiceExceptionUtil.exception(PAY_TRANSACTION_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
|
||||
// 插入 PayTransactionExtensionDO
|
||||
PayTransactionExtensionDO payTransactionExtensionDO = PayTransactionConvert.INSTANCE.convert(submitReqDTO)
|
||||
.setTransactionId(payTransaction.getId()).setTransactionCode(generateTransactionCode())
|
||||
.setStatus(PayTransactionStatusEnum.WAITING.getValue());
|
||||
payTransactionExtensionMapper.insert(payTransactionExtensionDO);
|
||||
|
||||
// 调用三方接口
|
||||
AbstractThirdPayClient thirdPayClient = ThirdPayClientFactory.getThirdPayClient(submitReqDTO.getPayChannel());
|
||||
CommonResult<String> invokeResult = thirdPayClient.submitTransaction(payTransaction, payTransactionExtensionDO, null); // TODO 暂时传入 extra = null
|
||||
invokeResult.checkError();
|
||||
|
||||
// TODO 轮询三方接口,是否已经支付的任务
|
||||
// 返回成功
|
||||
return new PayTransactionSubmitRespDTO().setId(payTransactionExtensionDO.getId()).setInvokeResponse(invokeResult.getData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayTransactionRespDTO getPayTransaction(PayTransactionGetReqDTO getReqDTO) {
|
||||
return PayTransactionConvert.INSTANCE.convert(payTransactionMapper.selectByAppIdAndOrderId(
|
||||
getReqDTO.getAppId(), getReqDTO.getOrderId()));
|
||||
}
|
||||
|
||||
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) // 随机。为什么是这个范围,因为偷懒
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
29
pay-service-project/pay-service-integration-test/pom.xml
Normal file
29
pay-service-project/pay-service-integration-test/pom.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>pay-service-project</artifactId>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>pay-service-integration-test</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>pay-service-app</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Test 相关 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.iocoder.mall.payservice.service.transaction.impl;
|
||||
|
||||
import cn.iocoder.mall.payservice.enums.PayChannelEnum;
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionSubmitReqDTO;
|
||||
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.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class PayTransactionServiceImplTest {
|
||||
|
||||
@Autowired
|
||||
private PayTransactionServiceImpl payTransactionService;
|
||||
|
||||
@Test
|
||||
public void testSubmitPayTransaction() {
|
||||
payTransactionService.submitPayTransaction(new PayTransactionSubmitReqDTO()
|
||||
.setAppId("POd4RC6a")
|
||||
.setCreateIp("127.0.0.1")
|
||||
.setOrderId("239")
|
||||
.setPayChannel(PayChannelEnum.PINGXX.getId()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package cn.iocoder.mall.payservice.service.transaction;
|
||||
@@ -15,6 +15,7 @@
|
||||
<modules>
|
||||
<module>pay-service-api</module>
|
||||
<module>pay-service-app</module>
|
||||
<module>pay-service-integration-test</module>
|
||||
</modules>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user