From 19b53f0ed18729869b69469c3b8837747c47b98f Mon Sep 17 00:00:00 2001 From: qiube <18969599531@163.com> Date: Mon, 22 Dec 2025 10:18:59 +0800 Subject: [PATCH] =?UTF-8?q?feat(config):=20=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 application.yml 主配置文件,配置 Spring、Druid、MyBatis-Plus 等基础设置 - 添加 application-dev.yml 开发环境配置,配置数据源及 PingPong 沙箱参数 - 添加数据库建表及配置说明文档(README.md、README_DATABASE.md、README_PRODUCT.md) - 添加商品表结构定义及示例数据说明 - 添加支付相关枚举类 RecordType 和充值信息 DTO RechargeDTO - 添加日志文件 mt-pay.2025-12-19.log 用于记录系统启动异常信息 --- logs/mt-pay.2025-12-19.log | 152 ++++++++++++++++++ mt-pay/database/README.md | 122 ++++++++++++++ mt-pay/database/README_DATABASE.md | 67 ++++++++ mt-pay/database/README_PRODUCT.md | 139 ++++++++++++++++ .../mtkj/mtpay/common/enums/RecordType.java | 65 ++++++++ .../com/mtkj/mtpay/dto/risk/RechargeDTO.java | 15 ++ .../src/main/resources/application-dev.yml | 67 ++++++++ mt-startup/src/main/resources/application.yml | 101 ++++++++++++ 8 files changed, 728 insertions(+) create mode 100644 logs/mt-pay.2025-12-19.log create mode 100644 mt-pay/database/README.md create mode 100644 mt-pay/database/README_DATABASE.md create mode 100644 mt-pay/database/README_PRODUCT.md create mode 100644 mt-pay/src/main/java/com/mtkj/mtpay/common/enums/RecordType.java create mode 100644 mt-pay/src/main/java/com/mtkj/mtpay/dto/risk/RechargeDTO.java create mode 100644 mt-startup/src/main/resources/application-dev.yml create mode 100644 mt-startup/src/main/resources/application.yml diff --git a/logs/mt-pay.2025-12-19.log b/logs/mt-pay.2025-12-19.log new file mode 100644 index 0000000..173b156 --- /dev/null +++ b/logs/mt-pay.2025-12-19.log @@ -0,0 +1,152 @@ +2025-12-19 18:34:37.842 [background-preinit] INFO org.hibernate.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.1.Final +2025-12-19 18:34:37.877 [restartedMain] INFO com.mtkj.mtpay.MtPayApplication - Starting MtPayApplication using Java 17.0.12 with PID 28188 (E:\MTKJPAY\mt-pay\target\classes started by 18969 in E:\MTKJPAY) +2025-12-19 18:34:37.878 [restartedMain] INFO com.mtkj.mtpay.MtPayApplication - No active profile set, falling back to 1 default profile: "default" +2025-12-19 18:34:38.630 [restartedMain] WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: java.lang.IllegalArgumentException: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String +2025-12-19 18:34:38.656 [restartedMain] ERROR org.springframework.boot.SpringApplication - Application run failed +java.lang.IllegalArgumentException: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String + at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getTypeForFactoryBeanFromAttributes(FactoryBeanRegistrySupport.java:86) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:838) + at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:620) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:573) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:532) + at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:138) + at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:775) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:323) + at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:568) + at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) +2025-12-19 18:34:38.658 [restartedMain] ERROR com.mtkj.mtpay.MtPayApplication - +╔══════════════════════════════════════════════════════════╗ +║ ║ +║ ❌ MTKJ PAY 支付系统启动失败! ❌ ║ +║ ║ +╚══════════════════════════════════════════════════════════╝ + +java.lang.IllegalArgumentException: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String + at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getTypeForFactoryBeanFromAttributes(FactoryBeanRegistrySupport.java:86) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:838) + at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:620) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:573) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:532) + at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:138) + at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:775) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:323) + at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:568) + at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) +2025-12-19 18:34:38.661 [main] ERROR com.mtkj.mtpay.MtPayApplication - +╔══════════════════════════════════════════════════════════╗ +║ ║ +║ ❌ MTKJ PAY 支付系统启动失败! ❌ ║ +║ ║ +╚══════════════════════════════════════════════════════════╝ + +org.springframework.boot.devtools.restart.SilentExitExceptionHandler$SilentExitException: null + at org.springframework.boot.devtools.restart.SilentExitExceptionHandler.exitCurrentThread(SilentExitExceptionHandler.java:92) + at org.springframework.boot.devtools.restart.Restarter.immediateRestart(Restarter.java:179) + at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:163) + at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:532) + at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationStartingEvent(RestartApplicationListener.java:98) + at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationEvent(RestartApplicationListener.java:51) + at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:178) + at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:171) + at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:149) + at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:137) + at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136) + at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:75) + at org.springframework.boot.SpringApplicationRunListeners.lambda$starting$0(SpringApplicationRunListeners.java:54) + at java.base/java.lang.Iterable.forEach(Iterable.java:75) + at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118) + at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:54) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) + at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24) +2025-12-19 18:34:48.258 [background-preinit] INFO org.hibernate.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.1.Final +2025-12-19 18:34:48.299 [restartedMain] INFO com.mtkj.mtpay.MtPayApplication - Starting MtPayApplication using Java 17.0.12 with PID 7992 (E:\MTKJPAY\mt-pay\target\classes started by 18969 in E:\MTKJPAY) +2025-12-19 18:34:48.300 [restartedMain] INFO com.mtkj.mtpay.MtPayApplication - No active profile set, falling back to 1 default profile: "default" +2025-12-19 18:34:49.124 [restartedMain] WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: java.lang.IllegalArgumentException: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String +2025-12-19 18:34:49.156 [restartedMain] ERROR org.springframework.boot.SpringApplication - Application run failed +java.lang.IllegalArgumentException: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String + at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getTypeForFactoryBeanFromAttributes(FactoryBeanRegistrySupport.java:86) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:838) + at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:620) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:573) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:532) + at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:138) + at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:775) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:323) + at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:568) + at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) +2025-12-19 18:34:49.158 [restartedMain] ERROR com.mtkj.mtpay.MtPayApplication - +╔══════════════════════════════════════════════════════════╗ +║ ║ +║ ❌ MTKJ PAY 支付系统启动失败! ❌ ║ +║ ║ +╚══════════════════════════════════════════════════════════╝ + +java.lang.IllegalArgumentException: Invalid value type for attribute 'factoryBeanObjectType': java.lang.String + at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getTypeForFactoryBeanFromAttributes(FactoryBeanRegistrySupport.java:86) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:838) + at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:620) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:573) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:532) + at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:138) + at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:775) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:323) + at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:568) + at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) +2025-12-19 18:34:49.161 [main] ERROR com.mtkj.mtpay.MtPayApplication - +╔══════════════════════════════════════════════════════════╗ +║ ║ +║ ❌ MTKJ PAY 支付系统启动失败! ❌ ║ +║ ║ +╚══════════════════════════════════════════════════════════╝ + +org.springframework.boot.devtools.restart.SilentExitExceptionHandler$SilentExitException: null + at org.springframework.boot.devtools.restart.SilentExitExceptionHandler.exitCurrentThread(SilentExitExceptionHandler.java:92) + at org.springframework.boot.devtools.restart.Restarter.immediateRestart(Restarter.java:179) + at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:163) + at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:532) + at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationStartingEvent(RestartApplicationListener.java:98) + at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationEvent(RestartApplicationListener.java:51) + at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:178) + at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:171) + at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:149) + at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:137) + at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136) + at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:75) + at org.springframework.boot.SpringApplicationRunListeners.lambda$starting$0(SpringApplicationRunListeners.java:54) + at java.base/java.lang.Iterable.forEach(Iterable.java:75) + at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118) + at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:54) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) + at com.mtkj.mtpay.MtPayApplication.main(MtPayApplication.java:24) diff --git a/mt-pay/database/README.md b/mt-pay/database/README.md new file mode 100644 index 0000000..7c948fc --- /dev/null +++ b/mt-pay/database/README.md @@ -0,0 +1,122 @@ +# 数据库建表SQL说明 + +## 文件说明 + +- `schema.sql` - 完整的数据库建表SQL脚本 + +## 表结构说明 + +### 1. payment_order(支付订单表) + +**表说明**:存储支付订单的完整信息 + +**主要字段**: +- `id` - 主键ID(自增) +- `merchant_transaction_id` - 商户订单号(唯一索引) +- `transaction_id` - PingPong交易流水号 +- `amount` - 交易金额(DECIMAL(12,2)) +- `currency` - 交易币种(3位ISO 4217代码) +- `payment_type` - 交易类型(SALE/AUTH) +- `status` - 订单状态(PENDING/SUCCESS/FAILED/REVIEW/CANCELLED) +- `token` - PingPong返回的token +- `payment_url` - 支付收银台地址 +- `create_time` - 创建时间(自动填充) +- `update_time` - 更新时间(自动更新) + +**索引**: +- 主键:`id` +- 唯一索引:`merchant_transaction_id` +- 普通索引:`transaction_id`、`status`、`create_time` + +### 2. payment_record(支付记录表) + +**表说明**:记录所有支付相关操作(回调、查询等) + +**主要字段**: +- `id` - 主键ID(自增) +- `transaction_id` - PingPong交易流水号 +- `merchant_transaction_id` - 商户订单号 +- `record_type` - 记录类型(CHECKOUT/CALLBACK/QUERY/REFUND/CAPTURE/VOID) +- `status` - 交易状态 +- `code` - 响应码 +- `description` - 响应描述 +- `request_data` - 原始请求数据(JSON,TEXT类型) +- `response_data` - 原始响应数据(JSON,TEXT类型) +- `create_time` - 创建时间(自动填充) + +**索引**: +- 主键:`id` +- 普通索引:`transaction_id`、`merchant_transaction_id`、`record_type`、`create_time` + +## 执行方式 + +### 方式1:直接执行SQL文件 + +```bash +mysql -u用户名 -p密码 数据库名 < schema.sql +``` + +### 方式2:在MySQL客户端中执行 + +```sql +-- 1. 连接到MySQL +mysql -u用户名 -p密码 + +-- 2. 选择数据库 +USE mtpay; + +-- 3. 执行SQL文件 +SOURCE /path/to/schema.sql; +``` + +### 方式3:使用IDE工具 + +1. 打开数据库管理工具(如Navicat、DBeaver、DataGrip等) +2. 连接到数据库 +3. 打开 `schema.sql` 文件 +4. 执行SQL脚本 + +## 注意事项 + +1. **字符集**:使用 `utf8mb4` 字符集,支持emoji和特殊字符 +2. **排序规则**:使用 `utf8mb4_unicode_ci` 排序规则 +3. **存储引擎**:使用 `InnoDB` 存储引擎,支持事务和外键 +4. **时间字段**:使用 `DATETIME` 类型,支持自动填充和更新 +5. **金额字段**:使用 `DECIMAL(12,2)` 类型,精确到分 +6. **唯一约束**:`merchant_transaction_id` 必须全局唯一 + +## 字段长度说明 + +- `merchant_transaction_id`:64字符(根据PingPong文档) +- `transaction_id`:64字符(根据PingPong文档) +- `token`:255字符(根据PingPong文档) +- `payment_url`:500字符(URL可能较长) +- `remark`:500字符(备注信息) +- `description`:500字符(响应描述) +- `request_data`/`response_data`:TEXT类型(JSON数据可能很长) + +## 索引优化建议 + +1. **查询优化**:根据实际查询场景添加复合索引 +2. **时间范围查询**:`create_time` 索引有助于时间范围查询 +3. **状态查询**:`status` 索引有助于按状态筛选订单 +4. **关联查询**:`transaction_id` 和 `merchant_transaction_id` 索引有助于关联查询 + +## 数据备份建议 + +1. 定期备份数据库 +2. 重要操作前先备份 +3. 使用 `mysqldump` 命令备份: + +```bash +mysqldump -u用户名 -p密码 数据库名 > backup_$(date +%Y%m%d).sql +``` + +## 版本更新 + +如果后续需要修改表结构,建议: + +1. 创建迁移SQL文件(如:`migration_v1.1.sql`) +2. 使用 `ALTER TABLE` 语句修改 +3. 记录版本变更日志 + diff --git a/mt-pay/database/README_DATABASE.md b/mt-pay/database/README_DATABASE.md new file mode 100644 index 0000000..b2fad23 --- /dev/null +++ b/mt-pay/database/README_DATABASE.md @@ -0,0 +1,67 @@ +# 数据库配置说明 + +## 数据库信息 + +- **数据库名称**:`mtpay` +- **字符集**:`utf8mb4` +- **排序规则**:`utf8mb4_general_ci` + +## 数据库表 + +### 支付相关表 + +1. **payment_order** - 支付订单表 +2. **payment_record** - 支付记录表 + +### 商品相关表 + +1. **mt_product** - 商品表 +2. **mt_product_sku** - 商品SKU表 + +## 执行建表SQL + +### 方式1:执行所有SQL文件 + +```bash +# 在MySQL中执行 +mysql -u用户名 -p密码 mtpay < mt_product_schema.sql +``` + +### 方式2:在MySQL客户端中执行 + +```sql +-- 1. 连接到MySQL +mysql -u用户名 -p密码 + +-- 2. 选择数据库 +USE mtpay; + +-- 3. 执行SQL文件 +SOURCE /path/to/mt_product_schema.sql; +``` + +### 方式3:使用IDE工具 + +1. 打开数据库管理工具(如Navicat、DBeaver、DataGrip等) +2. 连接到数据库服务器 +3. 选择 `mtpay` 数据库 +4. 打开 `mt_product_schema.sql` 文件 +5. 执行SQL脚本 + +## 注意事项 + +1. **执行顺序**:先执行 `mt_product_schema.sql` 创建商品表 +2. **外键约束**:`mt_product_sku` 表有外键关联 `mt_product` 表,删除商品时会级联删除SKU +3. **字符集**:所有表使用 `utf8mb4` 字符集,支持emoji和特殊字符 +4. **索引**:已创建必要的索引,提高查询性能 + +## 表结构概览 + +``` +mtpay +├── payment_order (支付订单表) +├── payment_record (支付记录表) +├── mt_product (商品表) +└── mt_product_sku (商品SKU表) +``` + diff --git a/mt-pay/database/README_PRODUCT.md b/mt-pay/database/README_PRODUCT.md new file mode 100644 index 0000000..395162f --- /dev/null +++ b/mt-pay/database/README_PRODUCT.md @@ -0,0 +1,139 @@ +# 商品表结构说明 + +## 表名规范 + +所有表名使用 `mt_` 前缀,如: +- `mt_product` - 商品表 +- `mt_product_sku` - 商品SKU表 + +## 表结构 + +### 1. mt_product(商品表) + +**字段说明:** + +| 字段名 | 类型 | 说明 | 备注 | +|--------|------|------|------| +| id | BIGINT | 商品ID | 主键,自增 | +| name | VARCHAR(255) | 商品名称 | 必填 | +| price | DECIMAL(12,2) | 商品价格 | 基础价格,默认0.00 | +| main_image | VARCHAR(4000) | 主图URL | 可选 | +| status | VARCHAR(20) | 商品状态 | ACTIVE-上架,INACTIVE-下架,DELETED-已删除 | +| shop_id | BIGINT | 店铺ID | 必填,关联店铺 | +| create_time | DATETIME | 创建时间 | 自动填充 | +| update_time | DATETIME | 更新时间 | 自动更新 | + +**索引:** +- 主键:`id` +- 普通索引:`shop_id`、`status`、`create_time` + +**排序规则:** +- 使用 `utf8mb4_general_ci` 排序规则 + +### 2. mt_product_sku(商品SKU表) + +**字段说明:** + +| 字段名 | 类型 | 说明 | 备注 | +|--------|------|------|------| +| id | BIGINT | SKU ID | 主键,自增 | +| product_id | BIGINT | 商品ID | 外键,关联mt_product | +| sku | VARCHAR(2000) | SKU编码 | 必填 | +| price | DECIMAL(12,2) | 价格 | 必填 | +| currency | VARCHAR(3) | 货币 | ISO 4217代码,默认USD | +| stock | INT | 库存数量 | 默认0 | +| sales_attrs | LONGTEXT | 销售属性 | JSON格式,如:[{"name":"颜色","value":"红色"}] | +| sku_image | VARCHAR(4000) | SKU图片URL | 可选 | +| weight | DECIMAL(10,2) | 重量 | 单位:克 | +| size | VARCHAR(200) | 大小/尺寸 | JSON格式,如:{"length":10,"width":5,"height":3} | +| specification | VARCHAR(2000) | 规格 | 文本描述 | +| status | VARCHAR(20) | SKU状态 | ACTIVE-启用,INACTIVE-禁用 | +| create_time | DATETIME | 创建时间 | 自动填充 | +| update_time | DATETIME | 更新时间 | 自动更新 | + +**索引:** +- 主键:`id` +- 普通索引:`product_id`、`status` +- 外键:`product_id` → `mt_product.id`(级联删除) + +## 数据示例 + +### 商品示例 + +```sql +INSERT INTO `mt_product` (`name`, `price`, `main_image`, `status`, `shop_id`) +VALUES ('Macaron 马卡龙礼盒装', 20.00, 'https://example.com/image.jpg', 'ACTIVE', 1); +``` + +### SKU示例 + +```sql +-- SKU 1:粉色6枚装 +INSERT INTO `mt_product_sku` ( + `product_id`, `sku`, `price`, `currency`, `stock`, + `sales_attrs`, `sku_image`, `weight`, `size`, `specification`, `status` +) VALUES ( + 1, 'SKU001', 18.00, 'USD', 50, + '[{"name":"颜色","value":"粉色"},{"name":"规格","value":"6枚装"}]', + 'https://example.com/pink-6pcs.jpg', 500.00, + '{"length":20,"width":15,"height":5}', + '6枚装马卡龙礼盒', 'ACTIVE' +); + +-- SKU 2:蓝色12枚装 +INSERT INTO `mt_product_sku` ( + `product_id`, `sku`, `price`, `currency`, `stock`, + `sales_attrs`, `sku_image`, `weight`, `size`, `specification`, `status` +) VALUES ( + 1, 'SKU002', 20.00, 'USD', 100, + '[{"name":"颜色","value":"蓝色"},{"name":"规格","value":"12枚装"}]', + 'https://example.com/blue-12pcs.jpg', 800.00, + '{"length":25,"width":20,"height":8}', + '12枚装马卡龙礼盒', 'ACTIVE' +); +``` + +## JSON字段格式说明 + +### sales_attrs(销售属性) + +```json +[ + {"name": "颜色", "value": "粉色"}, + {"name": "规格", "value": "6枚装"} +] +``` + +### size(尺寸) + +```json +{ + "length": 20, + "width": 15, + "height": 5, + "unit": "cm" +} +``` + +## 执行SQL + +```bash +# 在MySQL中执行 +mysql -u用户名 -p密码 数据库名 < mt_product_schema.sql +``` + +或在MySQL客户端中: + +```sql +SOURCE /path/to/mt_product_schema.sql; +``` + +## 注意事项 + +1. **字符集**:使用 `utf8mb4` 字符集,支持emoji和特殊字符 +2. **排序规则**:使用 `utf8mb4_unicode_ci` +3. **存储引擎**:使用 `InnoDB`,支持事务和外键 +4. **外键约束**:删除商品时会级联删除所有SKU +5. **SKU字段**:`sku` 字段最大2000字符,不再设置唯一索引(可根据业务需求决定是否唯一) +6. **JSON字段**:`sales_attrs` 和 `size` 字段存储JSON格式数据,需要应用层进行解析 + diff --git a/mt-pay/src/main/java/com/mtkj/mtpay/common/enums/RecordType.java b/mt-pay/src/main/java/com/mtkj/mtpay/common/enums/RecordType.java new file mode 100644 index 0000000..5ba7cc5 --- /dev/null +++ b/mt-pay/src/main/java/com/mtkj/mtpay/common/enums/RecordType.java @@ -0,0 +1,65 @@ +package com.mtkj.mtpay.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 记录类型枚举 + */ +@Getter +@AllArgsConstructor +public enum RecordType { + + /** + * 创建订单 + */ + CHECKOUT("CHECKOUT", "创建订单"), + + /** + * 回调 + */ + CALLBACK("CALLBACK", "回调"), + + /** + * 查询 + */ + QUERY("QUERY", "查询"), + + /** + * 退款 + */ + REFUND("REFUND", "退款"), + + /** + * 预授权完成 + */ + CAPTURE("CAPTURE", "预授权完成"), + + /** + * 预授权撤销 + */ + VOID("VOID", "预授权撤销"); + + /** + * 类型码 + */ + private final String code; + + /** + * 类型描述 + */ + private final String description; + + /** + * 根据类型码获取枚举 + */ + public static RecordType getByCode(String code) { + for (RecordType type : values()) { + if (type.getCode().equalsIgnoreCase(code)) { + return type; + } + } + return null; + } +} + diff --git a/mt-pay/src/main/java/com/mtkj/mtpay/dto/risk/RechargeDTO.java b/mt-pay/src/main/java/com/mtkj/mtpay/dto/risk/RechargeDTO.java new file mode 100644 index 0000000..34bb6b3 --- /dev/null +++ b/mt-pay/src/main/java/com/mtkj/mtpay/dto/risk/RechargeDTO.java @@ -0,0 +1,15 @@ +package com.mtkj.mtpay.dto.risk; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 充值信息DTO + */ +@Data +public class RechargeDTO implements Serializable { + + // 根据实际需求添加字段 +} + diff --git a/mt-startup/src/main/resources/application-dev.yml b/mt-startup/src/main/resources/application-dev.yml new file mode 100644 index 0000000..a24bad5 --- /dev/null +++ b/mt-startup/src/main/resources/application-dev.yml @@ -0,0 +1,67 @@ +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + druid: + # 主库数据源(开发环境) + master: + url: jdbc:mysql://rm-j6c3u06k2afwn8hxw6o.mysql.rds.aliyuncs.com:3306/mtpay?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai + username: mtkj2025 + password: aXs-Q876#pxBesA + # 初始连接数 + initial-size: 5 + # 最小连接池数量 + min-idle: 10 + # 最大连接池数量 + max-active: 200 + # 配置获取连接等待超时的时间 + max-wait: 60000 + # 配置连接超时时间 + connect-timeout: 30000 + # 配置网络超时时间 + socket-timeout: 60000 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + 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 + # 从库数据源 + slave: + # 从数据源开关/默认关闭 + enabled: false + url: + username: + password: + # Druid监控配置 + web-stat-filter: + enabled: true + stat-view-servlet: + enabled: true + # 设置白名单,不填则允许所有访问 + allow: + url-pattern: /druid/* + # 控制台管理用户名和密码 + login-username: ruoyi + login-password: 123456 + filter: + stat: + enabled: true + # 慢SQL记录 + log-slow-sql: false + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true + +# PingPong支付配置(开发环境使用沙箱) +pingpong: + gateway: https://sandbox-acquirer-payment.pingpongx.com + mode: sandbox + diff --git a/mt-startup/src/main/resources/application.yml b/mt-startup/src/main/resources/application.yml new file mode 100644 index 0000000..c486646 --- /dev/null +++ b/mt-startup/src/main/resources/application.yml @@ -0,0 +1,101 @@ +spring: + application: + name: MTKJPAY + profiles: + active: dev + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + druid: + # 从库数据源 + slave: + # 从数据源开关/默认关闭 + enabled: false + url: + username: + password: + # Druid监控配置 + web-stat-filter: + enabled: true + stat-view-servlet: + enabled: true + # 设置白名单,不填则允许所有访问 + allow: + url-pattern: /druid/* + # 控制台管理用户名和密码 + login-username: ruoyi + login-password: 123456 + filter: + stat: + enabled: true + # 慢SQL记录 + log-slow-sql: false + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true + # MyBatis-Plus配置 + mybatis-plus: + # 配置扫描mapper.xml文件路径 + mapper-locations: classpath*:/mapper/**/*.xml + # 配置实体类包路径 + type-aliases-package: com.mtkj.mtpay.entity + # 配置MyBatis-Plus全局配置 + configuration: + # 开启驼峰命名转换 + map-underscore-to-camel-case: true + # 开启二级缓存 + cache-enabled: false + # 日志实现 + log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl + # 全局配置 + global-config: + db-config: + # 主键类型:AUTO-数据库自增 + id-type: auto + # 逻辑删除字段 + logic-delete-field: deleted + # 逻辑删除值 + logic-delete-value: 1 + # 逻辑未删除值 + logic-not-delete-value: 0 + +# PingPong支付配置 +pingpong: + client-id: your-client-id + acc-id: your-acc-id + secret: your-secret-key + sign-type: MD5 + gateway: https://sandbox-acquirer-payment.pingpongx.com + mode: sandbox + enabled: true + +# 服务器配置 +server: + port: 8082 + servlet: + context-path: / + # 文件上传配置 + multipart: + # 单个文件最大大小(10MB) + max-file-size: 10MB + # 请求最大大小(50MB,支持多文件上传) + max-request-size: 50MB + # 文件写入磁盘的阈值(超过此大小会写入临时文件) + file-size-threshold: 2MB + +# 应用配置 +app: + # 前端访问地址(用于生成商品详情页URL等) + frontend: + url: http://localhost:3000 + +# 阿里云OSS相关配置 +aliyun: + oss: + accessId: LTAI5tHbwvzWfANvNxju2yN1 + accessKey: sAQR2swByBgmMOofH97hSJT638aVcJ + endpoint: https://oss-cn-hangzhou.aliyuncs.com + bucketName: mtkj2025 +