1. 迁移支付交易的提交 RPC 接口

2. 迁移支付交易的获取 RPC 接口
This commit is contained in:
YunaiV
2020-11-29 01:43:30 +08:00
parent d1b6118052
commit c60f9c71bf
79 changed files with 628 additions and 496 deletions

View File

@@ -14,10 +14,6 @@ import java.util.List;
public interface PayTransactionService {
PayTransactionBO getTransaction(PayTransactionGetDTO payTransactionGetDTO);
PayTransactionSubmitBO submitTransaction(PayTransactionSubmitDTO payTransactionSubmitDTO);
/**
* 更新交易支付成功
*

View File

@@ -1,72 +0,0 @@
package cn.iocoder.mall.pay.application.controller.users;
import cn.iocoder.common.framework.util.HttpUtil;
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.PayTransactionSubmitBO;
import cn.iocoder.mall.pay.api.constant.PayChannelEnum;
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionGetDTO;
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionSubmitDTO;
import cn.iocoder.mall.user.sdk.context.UserSecurityContextHolder;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.dubbo.config.annotation.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import static cn.iocoder.common.framework.vo.CommonResult.success;
@RestController
@RequestMapping("users/transaction")
@Api("【用户】支付交易 API")
public class UsersPayTransactionController {
private Logger logger = LoggerFactory.getLogger(getClass());
@Reference(validation = "true", version = "${dubbo.provider.PayTransactionService.version}")
private PayTransactionService payTransactionService;
@GetMapping("/get")
@ApiOperation("获得支付交易")
public CommonResult<PayTransactionBO> get(PayTransactionGetDTO payTransactionGetDTO) {
payTransactionGetDTO.setUserId(UserSecurityContextHolder.getContext().getUserId());
return success(payTransactionService.getTransaction(payTransactionGetDTO));
}
@PostMapping("/submit")
@ApiOperation("提交支付交易")
public CommonResult<PayTransactionSubmitBO> submit(HttpServletRequest request,
PayTransactionSubmitDTO payTransactionSubmitDTO) {
payTransactionSubmitDTO.setCreateIp(HttpUtil.getIp(request));
// 提交支付提交
return success(payTransactionService.submitTransaction(payTransactionSubmitDTO));
}
@PostMapping(value = "pingxx_pay_success", consumes = MediaType.APPLICATION_JSON_VALUE)
// @GetMapping(value = "pingxx_pay_success")
public String pingxxPaySuccess(HttpServletRequest request) throws IOException {
logger.info("[pingxxPaySuccess][被回调]");
// 读取 webhook
StringBuilder sb = new StringBuilder();
try (BufferedReader reader = request.getReader()) {
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
}
// JSONObject bodyObj = JSON.parseObject(sb.toString());
// bodyObj.put("webhookId", bodyObj.remove("id"));
// String body = bodyObj.toString();
payTransactionService.updateTransactionPaySuccess(PayChannelEnum.PINGXX.getId(), sb.toString());
return "success";
}
}

View File

@@ -79,39 +79,6 @@ public class PayTransactionServiceImpl implements PayTransactionService {
return PayTransactionConvert.INSTANCE.convert(payTransaction);
}
@Override
@SuppressWarnings("Duplicates")
public PayTransactionSubmitBO submitTransaction(PayTransactionSubmitDTO payTransactionSubmitDTO) {
// TODO 校验支付渠道是否有效
// 校验 App 是否有效
payAppService.validPayApp(payTransactionSubmitDTO.getAppId());
// 获得 PayTransactionDO 并校验其是否存在
PayTransactionDO payTransaction = payTransactionMapper.selectByAppIdAndOrderId(
payTransactionSubmitDTO.getAppId(), payTransactionSubmitDTO.getOrderId());
if (payTransaction == null) { // 是否存在
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
}
if (!PayTransactionStatusEnum.WAITING.getValue().equals(payTransaction.getStatus())) { // 校验状态必须是待支付
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_STATUS_IS_NOT_WAITING.getCode());
}
// 插入 PayTransactionExtensionDO
PayTransactionExtensionDO payTransactionExtensionDO = PayTransactionConvert.INSTANCE.convert(payTransactionSubmitDTO)
.setTransactionId(payTransaction.getId())
.setTransactionCode(generateTransactionCode())
.setStatus(PayTransactionStatusEnum.WAITING.getValue());
payTransactionExtensionMapper.insert(payTransactionExtensionDO);
// 调用三方接口
AbstractPaySDK paySDK = PaySDKFactory.getSDK(payTransactionSubmitDTO.getPayChannel());
CommonResult<String> invokeResult = paySDK.submitTransaction(payTransaction, payTransactionExtensionDO, null); // TODO 暂时传入 extra = null
if (invokeResult.isError()) {
throw ServiceExceptionUtil.exception(invokeResult.getCode(), invokeResult.getMessage());
}
// TODO 轮询三方接口是否已经支付的任务
// 返回成功
return new PayTransactionSubmitBO().setId(payTransactionExtensionDO.getId())
.setInvokeResponse(invokeResult.getData());
}
@Override
@Transactional
public Boolean updateTransactionPaySuccess(Integer payChannel, String params) {
@@ -199,23 +166,7 @@ public class PayTransactionServiceImpl implements PayTransactionService {
return null;
}
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) // 随机为什么是这个范围因为偷懒
;
}
}

View File

@@ -9,20 +9,6 @@
notify_time, trade_no, refund_total, create_time
</sql>
<insert id="insert" parameterType="PayTransactionDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
INSERT INTO transaction (
app_id, create_ip, order_id, order_subject,
order_description, order_memo, price, status, expire_time,
finish_time, notify_url, extension_id, pay_channel, payment_time,
notify_time, trade_no, create_time
) VALUES (
#{appId}, #{createIp}, #{orderId}, #{orderSubject},
#{orderDescription}, #{orderMemo}, #{price}, #{status}, #{expireTime},
#{finishTime}, #{notifyUrl}, #{extensionId}, #{payChannel}, #{paymentTime},
#{notifyTime}, #{tradeNo}, #{createTime}
)
</insert>
<update id="update">
UPDATE transaction
<set>
@@ -68,23 +54,6 @@
AND order_id = #{orderId}
</select>
<select id="selectById" parameterType="Integer" resultType="PayTransactionDO">
SELECT
<include refid="FIELDS"/>
FROM transaction
WHERE id = #{id}
</select>
<select id="selectListByIds" resultType="PayTransactionDO">
SELECT
<include refid="FIELDS" />
FROM transaction
WHERE id IN
<foreach item="id" collection="ids" separator="," open="(" close=")" index="">
#{id}
</foreach>
</select>
<select id="selectListByPage" resultType="PayTransactionDO">
SELECT
<include refid="FIELDS"/>

View File

@@ -1,21 +0,0 @@
package cn.iocoder.mall.pay.api.bo.transaction;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@ApiModel("支付交易提交结果 BO")
@Data
@Accessors(chain = true)
public class PayTransactionSubmitBO implements Serializable {
@ApiModelProperty(value = "支付交易拓展单编号", required = true, example = "1")
private Integer id;
@ApiModelProperty(value = "调用三方平台的响应结果", required = true)
private String invokeResponse;
}

View File

@@ -1,28 +0,0 @@
package cn.iocoder.mall.pay.api.dto.transaction;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@ApiModel("支付交易获得 DTO")
@Data
@Accessors(chain = true)
public class PayTransactionGetDTO {
@ApiModelProperty(value = "用户编号", required = true, example = "1", hidden = true) // hidden 的原因是Service DTO 自己传入,无需暴露的 Controller API 里
@NotNull(message = "用户编号不能为空")
private Integer userId;
@ApiModelProperty(value = "应用编号", required = true, example = "POd4RC6a")
@NotEmpty(message = "应用编号不能为空")
private String appId;
@ApiModelProperty(value = "订单号不能为空", required = true, example = "1024")
@NotEmpty(message = "订单号不能为空")
private String orderId;
}

View File

@@ -1,35 +0,0 @@
package cn.iocoder.mall.pay.api.dto.transaction;
import cn.iocoder.common.framework.validator.InEnum;
import cn.iocoder.mall.pay.api.constant.PayChannelEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@ApiModel("支付交易提交 DTO")
@Data
@Accessors(chain = true)
public class PayTransactionSubmitDTO {
@ApiModelProperty(value = "应用编号", required = true, example = "POd4RC6a")
@NotEmpty(message = "应用编号不能为空")
private String appId;
@ApiModelProperty(value = "发起交易的 IP", required = true, example = "192.168.10.1", hidden = true) // hidden 的原因是Service DTO 自己传入,无需暴露的 Controller API 里
@NotEmpty(message = "IP 不能为空")
private String createIp;
@ApiModelProperty(value = "订单号", required = true, example = "1024")
@NotEmpty(message = "订单号不能为空")
private String orderId;
@ApiModelProperty(value = "支付渠道", required = true, example = "1", notes = "参见 PayChannelEnum 枚举")
@InEnum(value = PayChannelEnum.class, message = "支付渠道必须是 {value}")
@NotNull(message = "支付渠道")
private Integer payChannel;
}

View File

@@ -1,136 +0,0 @@
<?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</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pay-service-impl</artifactId>
<dependencies>
<!-- Mall 相关 -->
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>common-framework</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>system-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>pay-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!-- RPC 相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<!-- Registry 和 Config 相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Transaction 相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-seata</artifactId>
</dependency>
<!-- MQ 相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
</dependency>
<!-- Job 相关 -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<!-- 云服务相关 -->
<dependency>
<groupId>Pingplusplus</groupId>
<artifactId>pingpp-java</artifactId>
<version>2.2.4</version>
<type>jar</type>
</dependency>
<!-- 测试相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId> <!-- 引入该包,为了写单元测试用 -->
<artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 提供给 mapstruct 使用 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>bintray</name>
<url>http://jcenter.bintray.com</url>
</repository>
</repositories>
</project>

View File

@@ -1,19 +0,0 @@
package cn.iocoder.mall.pay.biz.dao;
import cn.iocoder.mall.pay.biz.dataobject.PayTransactionExtensionDO;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Repository
public interface PayTransactionExtensionMapper {
void insert(PayTransactionExtensionDO entity);
int update(@Param("entity") PayTransactionExtensionDO entity,
@Param("whereStatus") Integer whereStatus);
PayTransactionExtensionDO selectByTransactionCode(@Param("transactionCode") String transactionCode);
PayTransactionExtensionDO selectById(@Param("id") Integer id);
}

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 使用驼峰命名法转换字段。 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeAliases>
<typeAlias alias="Integer" type="java.lang.Integer"/>
<typeAlias alias="Long" type="java.lang.Long"/>
<typeAlias alias="HashMap" type="java.util.HashMap"/>
<typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap"/>
<typeAlias alias="ArrayList" type="java.util.ArrayList"/>
<typeAlias alias="LinkedList" type="java.util.LinkedList"/>
</typeAliases>
</configuration>

View File

@@ -1,7 +0,0 @@
package cn.iocoder.mall.pay.biz;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = {"cn.iocoder.mall.pay"})
public class Application {
}

View File

@@ -1,13 +0,0 @@
package cn.iocoder.mall.pay.biz.service;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class PayTransactionServiceImplTest {
}

View File

@@ -1,32 +0,0 @@
<?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>onemall</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pay</artifactId>
<packaging>pom</packaging>
<modules>
<module>pay-application</module>
<module>pay-service-api</module>
<module>pay-service-impl</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>mall-dependencies</artifactId>
<version>1.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>