多模块重构 7:pay 模块的重构完成

This commit is contained in:
YunaiV
2022-01-31 22:14:35 +08:00
parent b757e1fccb
commit d45213fe2a
21 changed files with 271 additions and 148 deletions

View File

@ -0,0 +1,29 @@
package cn.iocoder.yudao.module.pay.dal.dataobject.merchant;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
import org.junit.jupiter.api.Test;
public class PayChannelDOTest {
@Test
public void testSerialization() {
PayChannelDO payChannelDO = new PayChannelDO();
// 创建配置
WXPayClientConfig config = new WXPayClientConfig();
config.setAppId("wx041349c6f39b268b");
config.setMchId("1545083881");
config.setApiVersion(WXPayClientConfig.API_VERSION_V2);
config.setMchKey("0alL64UDQdlCwiKZ73ib7ypaIjMns06p");
payChannelDO.setConfig(config);
// 序列化
String text = JsonUtils.toJsonString(payChannelDO);
System.out.println(text);
// 反序列化
payChannelDO = JsonUtils.parseObject(text, PayChannelDO.class);
System.out.println(payChannelDO.getConfig().getClass());
}
}

View File

@ -0,0 +1,82 @@
package cn.iocoder.yudao.module.pay.dal.mysql.merchant;
import cn.hutool.core.io.IoUtil;
import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import cn.iocoder.yudao.module.pay.test.BaseDbIntegrationTest;
import org.junit.jupiter.api.Test;
import javax.annotation.Resource;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List;
@Resource
public class PayChannelMapperIntegrationTest extends BaseDbIntegrationTest {
@Resource
private PayChannelMapper payChannelMapper;
/**
* 插入 {@link PayChannelEnum#WX_PUB} 初始配置
*/
@Test
public void testInsertWxPub() throws FileNotFoundException {
PayChannelDO payChannelDO = new PayChannelDO();
payChannelDO.setCode(PayChannelEnum.WX_PUB.getCode());
payChannelDO.setStatus(CommonStatusEnum.ENABLE.getStatus());
payChannelDO.setFeeRate(1D);
payChannelDO.setMerchantId(1L);
payChannelDO.setAppId(6L);
// 配置
WXPayClientConfig config = new WXPayClientConfig();
config.setAppId("wx041349c6f39b268b");
config.setMchId("1545083881");
config.setApiVersion(WXPayClientConfig.API_VERSION_V2);
config.setMchKey("0alL64UDQdlCwiKZ73ib7ypaIjMns06p");
config.setPrivateKeyContent(IoUtil.readUtf8(new FileInputStream("/Users/yunai/Downloads/wx_pay/apiclient_key.pem")));
config.setPrivateCertContent(IoUtil.readUtf8(new FileInputStream("/Users/yunai/Downloads/wx_pay/apiclient_cert.pem")));
config.setApiV3Key("joerVi8y5DJ3o4ttA0o1uH47Xz1u2Ase");
payChannelDO.setConfig(config);
// 执行插入
payChannelMapper.insert(payChannelDO);
}
// TODO @ouyangZfb 改成 AlipayQr
/**
* 插入 {@link PayChannelEnum#ALIPAY_QR} 初始配置
*/
@Test
public void testInsertZfb() {
PayChannelDO payChannelDO = new PayChannelDO();
payChannelDO.setCode(PayChannelEnum.ALIPAY_QR.getCode());
payChannelDO.setStatus(CommonStatusEnum.ENABLE.getStatus());
payChannelDO.setFeeRate(1D);
payChannelDO.setMerchantId(1L);
payChannelDO.setAppId(6L);
// 配置
AlipayPayClientConfig config = new AlipayPayClientConfig();
config.setAppId("2021000118634035");
config.setServerUrl(AlipayPayClientConfig.SERVER_URL_SANDBOX);
config.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT);
config.setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCHsEV1cDupwJv890x84qbppUtRIfhaKSwSVN0thCcsDCaAsGR5MZslDkO8NCT9V4r2SVXjyY7eJUZlZd1M0C8T01Tg4UOx5LUbic0O3A1uJMy6V1n9IyYwbAW3AEZhBd5bSbPgrqvmv3NeWSTQT6Anxnllf+2iDH6zyA2fPl7cYyQtbZoDJQFGqr4F+cGh2R6akzRKNoBkAeMYwoY6es2lX8sJxCVPWUmxNUoL3tScwlSpd7Bxw0q9c/X01jMwuQ0+Va358zgFiGERTE6yD01eu40OBDXOYO3z++y+TAYHlQQ2toMO63trepo88X3xV3R44/1DH+k2pAm2IF5ixiLrAgMBAAECggEAPx3SoXcseaD7rmcGcE0p4SMfbsUDdkUSmBBbtfF0GzwnqNLkWa+mgE0rWt9SmXngTQH97vByAYmLPl1s3G82ht1V7Sk7yQMe74lhFllr8eEyTjeVx3dTK1EEM4TwN+936DTXdFsr4TELJEcJJdD0KaxcCcfBLRDs2wnitEFZ9N+GoZybVmY8w0e0MI7PLObUZ2l0X4RurQnfG9ZxjXjC7PkeMVv7cGGylpNFi3BbvkRhdhLPDC2E6wqnr9e7zk+hiENivAezXrtxtwKovzCtnWJ1r0IO14Rh47H509Ic0wFnj+o5YyUL4LdmpL7yaaH6fM7zcSLFjNZPHvZCKPwYcQKBgQDQFho98QvnL8ex4v6cry4VitGpjSXm1qP3vmMQk4rTsn8iPWtcxPjqGEqOQJjdi4Mi0VZKQOLFwlH0kl95wNrD/isJ4O1yeYfX7YAXApzHqYNINzM79HemO3Yx1qLMW3okRFJ9pPRzbQ9qkTpsaegsmyX316zOBhzGRYjKbutTYwKBgQCm7phr9XdFW5Vh+XR90mVs483nrLmMiDKg7YKxSLJ8amiDjzPejCn7i95Hah08P+2MIZLIPbh2VLacczR6ltRRzN5bg5etFuqSgfkuHyxpoDmpjbe08+Q2h8JBYqcC5Nhv1AKU4iOUhVLHo/FBAQliMcGc/J3eiYTFC7EsNx382QKBgClb20doe7cttgFTXswBvaUmfFm45kmla924B7SpvrQpDD/f+VDtDZRp05fGmxuduSjYdtA3aVtpLiTwWu22OUUvZZqHDGruYOO4Hvdz23mL5b4ayqImCwoNU4bAZIc9v18p/UNf3/55NNE3oGcf/bev9rH2OjCQ4nM+Ktwhg8CFAoGACSgvbkShzUkv0ZcIf9ppu+ZnJh1AdGgINvGwaJ8vQ0nm/8h8NOoFZ4oNoGc+wU5Ubops7dUM6FjPR5e+OjdJ4E7Xp7d5O4J1TaIZlCEbo5OpdhaTDDcQvrkFu+Z4eN0qzj+YAKjDAOOrXc4tbr5q0FsgXscwtcNfaBuzFVTUrUkCgYEAwzPnMNhWG3zOWLUs2QFA2GP4Y+J8cpUYfj6pbKKzeLwyG9qBwF1NJpN8m+q9q7V9P2LY+9Lp9e1mGsGeqt5HMEA3P6vIpcqLJLqE/4PBLLRzfccTcmqb1m71+erxTRhHBRkGS+I7dZEb3olQfnS1Y1tpMBxiwYwR3LW4oXuJwj8=");
config.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnq90KnF4dTnlzzmxpujbI05OYqi5WxAS6cL0gnZFv2gK51HExF8v/BaP7P979PhFMgWTqmOOI+Dtno5s+yD09XTY1WkshbLk6i4g2Xlr8fyW9ODnkU88RI2w9UdPhQU4cPPwBNlrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB");
// 创建客户端
payChannelDO.setConfig(config);
// 执行插入
payChannelMapper.insert(payChannelDO);
}
/**
* 查询所有支付配置,看看是否都是 ok 的
*/
@Test
public void testSelectList() {
List<PayChannelDO> payChannels = payChannelMapper.selectList();
System.out.println(payChannels.size());
}
}

View File

@ -0,0 +1,51 @@
package cn.iocoder.yudao.module.pay.service.order;
import cn.iocoder.yudao.module.pay.service.merchant.PayAppServiceImpl;
import cn.iocoder.yudao.module.pay.service.merchant.PayChannelServiceImpl;
import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderCreateReqDTO;
import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitReqDTO;
import cn.iocoder.yudao.module.pay.test.BaseDbIntegrationTest;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.pay.config.YudaoPayAutoConfiguration;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import java.time.Duration;
@Import({PayOrderServiceImpl.class, PayAppServiceImpl.class,
PayChannelServiceImpl.class, YudaoPayAutoConfiguration.class})
public class PayOrderServiceIntegrationTest extends BaseDbIntegrationTest {
@Resource
private PayOrderService payOrderService;
@Test
public void testCreatePayOrder() {
// 构造请求
PayOrderCreateReqDTO reqDTO = new PayOrderCreateReqDTO();
reqDTO.setAppId(6L);
reqDTO.setUserIp("127.0.0.1");
reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis()));
reqDTO.setSubject("标题");
reqDTO.setBody("内容");
reqDTO.setAmount(100);
reqDTO.setExpireTime(DateUtils.addTime(Duration.ofDays(1)));
// 发起请求
payOrderService.createPayOrder(reqDTO);
}
@Test
public void testSubmitPayOrder() {
// 构造请求
PayOrderSubmitReqDTO reqDTO = new PayOrderSubmitReqDTO();
reqDTO.setId(10L);
reqDTO.setAppId(6L);
reqDTO.setChannelCode(PayChannelEnum.WX_PUB.getCode());
reqDTO.setUserIp("127.0.0.1");
// 发起请求
payOrderService.submitPayOrder(reqDTO);
}
}

View File

@ -0,0 +1 @@
package cn.iocoder.yudao.module.pay.service;

View File

@ -0,0 +1,38 @@
package cn.iocoder.yudao.module.pay.test;
import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import org.redisson.spring.starter.RedissonAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbAndRedisIntegrationTest.Application.class)
@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件
public class BaseDbAndRedisIntegrationTest {
@Import({
// DB 配置类
DynamicDataSourceAutoConfiguration.class, // Dynamic Datasource 配置类
YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类
DataSourceAutoConfiguration.class, // Spring DB 自动配置类
DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
// MyBatis 配置类
YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
// Redis 配置类
RedisAutoConfiguration.class, // Spring Redis 自动配置类
YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
RedissonAutoConfiguration.class, // Redisson 自动高配置类
})
public static class Application {
}
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.pay.test;
import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbIntegrationTest.Application.class)
@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件
public class BaseDbIntegrationTest {
@Import({
// DB 配置类
DynamicDataSourceAutoConfiguration.class, // Dynamic Datasource 配置类
YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类
DataSourceAutoConfiguration.class, // Spring DB 自动配置类
DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
// MyBatis 配置类
YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
})
public static class Application {
}
}

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.pay.test;
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
import org.redisson.spring.starter.RedissonAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseRedisIntegrationTest.Application.class)
@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件
public class BaseRedisIntegrationTest {
@Import({
// Redis 配置类
RedisAutoConfiguration.class, // Spring Redis 自动配置类
YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
RedissonAutoConfiguration.class, // Redisson 自动高配置类
})
public static class Application {
}
}

View File

@ -0,0 +1,96 @@
spring:
main:
lazy-initialization: true # 开启懒加载,加快速度
banner-mode: off # 单元测试,禁用 Banner
--- #################### 数据库相关配置 ####################
spring:
# 数据源配置项
autoconfigure:
exclude:
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
datasource:
druid: # Druid 【监控】相关的全局配置
web-stat-filter:
enabled: true
dynamic: # 多数据源配置
druid: # Druid 【连接池】相关的全局配置
initial-size: 5 # 初始连接数
min-idle: 10 # 最小连接池数量
max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true
test-on-borrow: false
test-on-return: false
primary: master
datasource:
master:
name: ruoyi-vue-pro
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
slave: # 模拟从库,可根据自己需要修改
name: ruoyi-vue-pro
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
redis:
host: 127.0.0.1 # 地址
port: 6379 # 端口
database: 0 # 数据库索引
mybatis:
lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
mybatis-plus:
configuration:
map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志
global-config:
db-config:
id-type: AUTO # 自增 ID
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
mapper-locations: classpath*:mapper/*.xml
type-aliases-package: ${yudao.core-service.base-package}.modules.*.dal.dataobject
--- #################### 定时任务相关配置 ####################
--- #################### 配置中心相关配置 ####################
--- #################### 服务保障相关配置 ####################
# Lock4j 配置项(单元测试,禁用 Lock4j
# Resilience4j 配置项
resilience4j:
ratelimiter:
instances:
backendA:
limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50
limit-refresh-period: 60s # 每个周期的时长,单位:微秒。默认为 500
timeout-duration: 1s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s
register-health-indicator: true # 是否注册到健康监测
--- #################### 监控相关配置 ####################
--- #################### 芋道相关配置 ####################
yudao:
info:
version: 1.0.0
base-package: cn.iocoder.yudao.adminserver
base-package2: cn.iocoder.yudao.module
core-service:
base-package: cn.iocoder.yudao.coreservice
pay:
pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify
refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.pay.service.merchant;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppCreateReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppExportReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppPageReqVO;
@ -30,11 +31,6 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link PayAppServiceImpl} 的单元测试类
*
* @author 芋艿
*/
@Import(PayAppServiceImpl.class)
public class PayAppServiceTest extends BaseDbUnitTest {

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.service.merchant;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
@ -14,9 +15,11 @@ import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayChannelMapper;
import cn.iocoder.yudao.module.pay.test.BaseDbUnitTest;
import com.alibaba.fastjson.JSON;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import javax.validation.Validator;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
@ -37,6 +40,11 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
@Resource
private PayChannelMapper channelMapper;
@MockBean
private PayClientFactory payClientFactory;
@MockBean
private Validator validator;
@Test
public void testCreateWechatVersion2Channel_success() {
// 准备参数

View File

@ -4,6 +4,8 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.pay.config.PayProperties;
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO;
@ -12,8 +14,12 @@ 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.PayOrderStatusEnum;
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum;
import cn.iocoder.yudao.module.pay.service.merchant.PayAppService;
import cn.iocoder.yudao.module.pay.service.merchant.PayChannelService;
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
import cn.iocoder.yudao.module.pay.test.BaseDbUnitTest;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
@ -30,7 +36,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
*
* @author 芋艿
*/
@Import(PayOrderServiceImpl.class)
@Import({PayOrderServiceImpl.class})
public class PayOrderServiceTest extends BaseDbUnitTest {
@Resource
@ -39,6 +45,17 @@ public class PayOrderServiceTest extends BaseDbUnitTest {
@Resource
private PayOrderMapper orderMapper;
@MockBean
private PayClientFactory payClientFactory;
@MockBean
private PayProperties properties;
@MockBean
private PayAppService appService;
@MockBean
private PayChannelService channelService;
@MockBean
private PayNotifyService notifyService;
public String generateNo() {
return DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomInt(100000, 999999);
}

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.service.refund;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO;
@ -10,8 +11,14 @@ 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.refund.PayRefundStatusEnum;
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum;
import cn.iocoder.yudao.module.pay.service.merchant.PayAppService;
import cn.iocoder.yudao.module.pay.service.merchant.PayChannelService;
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
import cn.iocoder.yudao.module.pay.service.order.PayOrderExtensionService;
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
import cn.iocoder.yudao.module.pay.test.BaseDbUnitTest;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
@ -22,12 +29,6 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* {@link PayRefundServiceImpl} 的单元测试类
*
* @author aquan
*/
@Import(PayRefundServiceImpl.class)
public class PayRefundServiceTest extends BaseDbUnitTest {
@ -37,6 +38,18 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
@Resource
private PayRefundMapper refundMapper;
@MockBean
private PayClientFactory payClientFactory;
@MockBean
private PayOrderService orderService;
@MockBean
private PayOrderExtensionService orderExtensionService;
@MockBean
private PayAppService appService;
@MockBean
private PayChannelService channelService;
@MockBean
private PayNotifyService notifyService;
@Test
public void testGetRefundPage() {

View File

@ -0,0 +1,54 @@
spring:
main:
lazy-initialization: true # 开启懒加载,加快速度
banner-mode: off # 单元测试,禁用 Banner
--- #################### 数据库相关配置 ####################
spring:
# 数据源配置项
datasource:
name: ruoyi-vue-pro
url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false; # MODE 使用 MySQL 模式DATABASE_TO_UPPER 配置表和字段使用小写
driver-class-name: org.h2.Driver
username: sa
password:
schema: classpath:sql/create_tables.sql # MySQL 转 H2 的语句,使用 https://www.jooq.org/translate/ 工具
druid:
async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
initial-size: 1 # 单元测试,配置为 1提升启动速度
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
redis:
host: 127.0.0.1 # 地址
port: 16379 # 端口(单元测试,使用 16379 端口)
database: 0 # 数据库索引
mybatis:
lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
--- #################### 定时任务相关配置 ####################
--- #################### 配置中心相关配置 ####################
--- #################### 服务保障相关配置 ####################
# Lock4j 配置项(单元测试,禁用 Lock4j
# Resilience4j 配置项
--- #################### 监控相关配置 ####################
--- #################### 芋道相关配置 ####################
# 芋道配置项,设置当前项目所有自定义的配置
yudao:
info:
base-package: cn.iocoder.yudao.module.member.dal.mysql
base-package2: cn.iocoder.yudao.module
core-service:
base-package: cn.iocoder.yudao.module.member.dal.mysql # TODO 芋艿:要清理掉
captcha:
timeout: 5m
width: 160
height: 60

View File

@ -0,0 +1,4 @@
<configuration>
<!-- 引用 Spring Boot 的 logback 基础配置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
</configuration>

View File

@ -0,0 +1,5 @@
DELETE FROM pay_merchant;
DELETE FROM pay_app;
DELETE FROM pay_channel;
DELETE FROM pay_order;
DELETE FROM pay_refund;

View File

@ -0,0 +1,115 @@
CREATE TABLE IF NOT EXISTS "pay_merchant"
(
"id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"no" varchar(32) NOT NULL,
"name" varchar(64) NOT NULL,
"short_name" varchar(64) NOT NULL,
"status" tinyint NOT NULL,
"remark" varchar(255) DEFAULT NULL,
"creator" varchar(64) DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit(1) NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT '支付商户信息';
CREATE TABLE IF NOT EXISTS "pay_app" (
"id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"name" varchar(64) NOT NULL,
"status" tinyint NOT NULL,
"remark" varchar(255) DEFAULT NULL,
`pay_notify_url` varchar(1024) NOT NULL,
`refund_notify_url` varchar(1024) NOT NULL,
`merchant_id` bigint(20) NOT NULL,
"creator" varchar(64) DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit(1) NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT = '支付应用信息';
CREATE TABLE IF NOT EXISTS "pay_channel" (
"id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"code" varchar(32) NOT NULL,
"status" tinyint(4) NOT NULL,
"remark" varchar(255) DEFAULT NULL,
"fee_rate" double NOT NULL DEFAULT 0,
"merchant_id" bigint(20) NOT NULL,
"app_id" bigint(20) NOT NULL,
"config" varchar(10240) NOT NULL,
"creator" varchar(64) NULL DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) NULL DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
"deleted" bit(1) NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT = '支付渠道';
CREATE TABLE IF NOT EXISTS `pay_order` (
"id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
`merchant_id` bigint(20) NOT NULL,
`app_id` bigint(20) NOT NULL,
`channel_id` bigint(20) DEFAULT NULL,
`channel_code` varchar(32) DEFAULT NULL,
`merchant_order_id` varchar(64) NOT NULL,
`subject` varchar(32) NOT NULL,
`body` varchar(128) NOT NULL,
`notify_url` varchar(1024) NOT NULL,
`notify_status` tinyint(4) NOT NULL,
`amount` bigint(20) NOT NULL,
`channel_fee_rate` double DEFAULT 0,
`channel_fee_amount` bigint(20) DEFAULT 0,
`status` tinyint(4) NOT NULL,
`user_ip` varchar(50) NOT NULL,
`expire_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
`success_time` datetime(0) DEFAULT CURRENT_TIMESTAMP,
`notify_time` datetime(0) DEFAULT CURRENT_TIMESTAMP,
`success_extension_id` bigint(20) DEFAULT NULL COMMENT '支付成功的订单拓展单编号',
`refund_status` tinyint(4) NOT NULL,
`refund_times` tinyint(4) NOT NULL,
`refund_amount` bigint(20) NOT NULL,
`channel_user_id` varchar(255) DEFAULT NULL,
`channel_order_no` varchar(64) DEFAULT NULL,
`creator` varchar(64) DEFAULT '',
`create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updater` varchar(64) DEFAULT '',
`update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted` bit(1) NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT = '支付订单';
CREATE TABLE IF NOT EXISTS `pay_refund` (
"id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
`merchant_id` bigint(20) NOT NULL,
`app_id` bigint(20) NOT NULL,
`channel_id` bigint(20) NOT NULL,
`channel_code` varchar(32) NOT NULL,
`order_id` bigint(20) NOT NULL,
`trade_no` varchar(64) NOT NULL,
`merchant_order_id` varchar(64) NOT NULL,
`merchant_refund_no` varchar(64) NOT NULL,
`notify_url` varchar(1024) NOT NULL,
`notify_status` tinyint(4) NOT NULL,
`status` tinyint(4) NOT NULL,
`type` tinyint(4) NOT NULL,
`pay_amount` bigint(20) NOT NULL,
`refund_amount` bigint(20) NOT NULL,
`reason` varchar(256) NOT NULL,
`user_ip` varchar(50) NULL DEFAULT NULL,
`channel_order_no` varchar(64) NOT NULL,
`channel_refund_no` varchar(64) NULL DEFAULT NULL,
`channel_error_code` varchar(128) NULL DEFAULT NULL,
`channel_error_msg` varchar(256) NULL DEFAULT NULL,
`channel_extras` varchar(1024) NULL DEFAULT NULL,
`expire_time` datetime(0) NULL DEFAULT NULL,
`success_time` datetime(0) NULL DEFAULT NULL,
`notify_time` datetime(0) NULL DEFAULT NULL,
`creator` varchar(64) NULL DEFAULT '',
`create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updater` varchar(64) NULL DEFAULT '',
`update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted` bit(1) NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT = '退款订单';