317 lines
8.5 KiB
Markdown
317 lines
8.5 KiB
Markdown
# 多商户支付配置系统设计方案
|
||
|
||
## 📋 概述
|
||
|
||
将单商户硬编码的乐刷支付配置改造为支持多商户、可动态管理的数据库配置方案。
|
||
|
||
---
|
||
|
||
## 🎯 设计目标
|
||
|
||
✅ 支持多个乐刷商户号
|
||
✅ 支持不同业务场景使用不同商户
|
||
✅ 后台 GUI 管理(增删改查)
|
||
✅ 密钥加密存储(AES-256-GCM)
|
||
✅ 支持启用/禁用商户
|
||
✅ 支持设置默认商户
|
||
✅ 支持测试环境和生产环境
|
||
✅ 使用统计和审计日志
|
||
✅ 平滑迁移,向后兼容
|
||
|
||
---
|
||
|
||
## 📊 数据库设计
|
||
|
||
### 1. 支付商户配置表 `payment_merchant_configs`
|
||
|
||
```sql
|
||
CREATE TABLE payment_merchant_configs (
|
||
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
|
||
name VARCHAR(128) NOT NULL, -- 商户名称
|
||
provider VARCHAR(32) NOT NULL, -- leshua/mock
|
||
merchant_id VARCHAR(128) NOT NULL, -- 商户号
|
||
gateway_url VARCHAR(512) NOT NULL DEFAULT '', -- 网关地址
|
||
sign_key VARCHAR(512) NOT NULL DEFAULT '', -- 签名密钥(加密)
|
||
notify_key VARCHAR(512) NOT NULL DEFAULT '', -- 通知密钥(加密)
|
||
notify_url VARCHAR(512) NOT NULL DEFAULT '', -- 回调地址
|
||
jump_url VARCHAR(512) NOT NULL DEFAULT '', -- 跳转地址
|
||
pay_way VARCHAR(32) NOT NULL DEFAULT 'ZFBZF',
|
||
jspay_flag VARCHAR(8) NOT NULL DEFAULT '2',
|
||
sign_type VARCHAR(16) NOT NULL DEFAULT 'MD5',
|
||
extra_config JSON NULL, -- 扩展配置
|
||
is_default TINYINT(1) NOT NULL DEFAULT 0, -- 是否默认
|
||
status VARCHAR(32) NOT NULL DEFAULT 'active', -- active/disabled/testing
|
||
environment VARCHAR(16) NOT NULL DEFAULT 'production', -- production/sandbox
|
||
business_tags JSON NULL, -- 业务场景标签
|
||
total_transactions BIGINT NOT NULL DEFAULT 0,
|
||
total_amount_cent BIGINT NOT NULL DEFAULT 0,
|
||
last_used_at DATETIME NULL,
|
||
created_by BIGINT UNSIGNED NULL,
|
||
updated_by BIGINT UNSIGNED NULL,
|
||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
|
||
KEY idx_payment_merchant_configs_provider (provider, status),
|
||
KEY idx_payment_merchant_configs_default (provider, is_default)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||
```
|
||
|
||
### 2. 配置使用日志表 `payment_config_usage_logs`(可选)
|
||
|
||
用于审计和统计分析。
|
||
|
||
---
|
||
|
||
## 🏗️ 后端架构
|
||
|
||
### 目录结构
|
||
|
||
```
|
||
backend/internal/modules/paymentconfig/
|
||
├── dto.go # 数据传输对象、请求响应结构
|
||
├── encryptor.go # AES-GCM 加密器
|
||
├── repository.go # 数据库操作层
|
||
├── service.go # 业务逻辑层
|
||
└── handler.go # HTTP 处理层
|
||
```
|
||
|
||
### 核心功能
|
||
|
||
1. **加密存储**
|
||
- 使用 AES-256-GCM 对称加密
|
||
- 密钥从环境变量 `PAYMENT_CONFIG_ENCRYPTION_KEY` 读取(32字节)
|
||
- 自动加密 `sign_key` 和 `notify_key`
|
||
|
||
2. **权限控制**
|
||
- `payment_config:list` - 查看配置列表
|
||
- `payment_config:create` - 创建配置
|
||
- `payment_config:update` - 更新配置
|
||
- `payment_config:delete` - 删除配置
|
||
- `payment_config:view_secret` - 查看密钥明文
|
||
|
||
3. **默认商户管理**
|
||
- 每个 `provider` 只能有一个默认商户
|
||
- 设置新默认时自动取消旧默认
|
||
- 支付模块优先使用默认商户
|
||
|
||
4. **使用统计**
|
||
- 自动记录交易笔数、总金额
|
||
- 记录最后使用时间
|
||
- 可选:记录详细使用日志
|
||
|
||
---
|
||
|
||
## 🔌 API 接口
|
||
|
||
### 管理后台接口
|
||
|
||
```
|
||
GET /admin/payment-configs # 获取配置列表
|
||
GET /admin/payment-configs/:id # 获取单个配置
|
||
POST /admin/payment-configs # 创建配置
|
||
PUT /admin/payment-configs/:id # 更新配置
|
||
DELETE /admin/payment-configs/:id # 删除配置
|
||
```
|
||
|
||
### 请求示例
|
||
|
||
**创建配置**
|
||
```json
|
||
POST /admin/payment-configs
|
||
{
|
||
"name": "乐刷生产商户1",
|
||
"provider": "leshua",
|
||
"merchant_id": "123456789",
|
||
"gateway_url": "https://paygate.leshuazf.com/cgi-bin/lepos_pay_gateway.cgi",
|
||
"sign_key": "your-sign-key",
|
||
"notify_key": "your-notify-key",
|
||
"notify_url": "https://your-domain.com/api/payment/leshua/notify",
|
||
"jump_url": "https://your-domain.com/payment/result",
|
||
"pay_way": "ZFBZF",
|
||
"jspay_flag": "2",
|
||
"sign_type": "MD5",
|
||
"is_default": true,
|
||
"status": "active",
|
||
"environment": "production",
|
||
"business_tags": ["order_pay", "wallet_recharge"]
|
||
}
|
||
```
|
||
|
||
**查询配置(包含密钥)**
|
||
```
|
||
GET /admin/payment-configs/1?include_secret=true
|
||
```
|
||
|
||
---
|
||
|
||
## 🔄 支付模块集成
|
||
|
||
### 修改 payment 模块
|
||
|
||
1. **注入 paymentconfig.Service**
|
||
```go
|
||
type Repository struct {
|
||
db *gorm.DB
|
||
cfg config.PaymentConfig // 保留作为兜底
|
||
paymentConfigSvc *paymentconfig.Service // 新增
|
||
orderRepo *order.Repository
|
||
walletRepo *wallet.Repository
|
||
leshua *leshua.Client
|
||
provider string
|
||
isMockMode bool
|
||
}
|
||
```
|
||
|
||
2. **动态获取配置**
|
||
```go
|
||
func (r *Repository) getLeshuaConfig() (config.LeshuaPaymentConfig, error) {
|
||
// 优先从数据库获取默认配置
|
||
if r.paymentConfigSvc != nil {
|
||
dto, err := r.paymentConfigSvc.GetDefaultConfig("leshua")
|
||
if err == nil {
|
||
return config.LeshuaPaymentConfig{
|
||
GatewayURL: dto.GatewayURL,
|
||
MerchantID: dto.MerchantID,
|
||
SignKey: dto.SignKey,
|
||
NotifyKey: dto.NotifyKey,
|
||
NotifyURL: dto.NotifyURL,
|
||
JumpURL: dto.JumpURL,
|
||
PayWay: dto.PayWay,
|
||
JSPayFlag: dto.JSPayFlag,
|
||
SignType: dto.SignType,
|
||
}, nil
|
||
}
|
||
}
|
||
|
||
// 兜底:使用 .env 配置
|
||
return r.cfg.Leshua, nil
|
||
}
|
||
```
|
||
|
||
3. **支付时使用动态配置**
|
||
```go
|
||
func (r *Repository) Start(userID uint64, orderID uint64, req StartPaymentRequest, clientIP string) (*PaymentDTO, error) {
|
||
// ...
|
||
|
||
leshuaConfig, err := r.getLeshuaConfig()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
client := leshua.NewClient(leshuaConfig)
|
||
resp, rawReq, err := client.CreatePayment(ctx, ...)
|
||
|
||
// ...
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🎨 前端管理界面
|
||
|
||
### 功能列表
|
||
|
||
1. **配置列表**
|
||
- 显示所有支付配置
|
||
- 筛选:服务商、状态、环境
|
||
- 标识默认商户
|
||
- 显示使用统计
|
||
|
||
2. **创建/编辑配置**
|
||
- 表单验证
|
||
- 密钥输入(敏感)
|
||
- 默认商户切换
|
||
- 状态管理
|
||
|
||
3. **查看密钥**
|
||
- 需要 `payment_config:view_secret` 权限
|
||
- 点击"查看密钥"按钮后调用API
|
||
|
||
4. **删除配置**
|
||
- 确认对话框
|
||
- 检查是否正在使用
|
||
|
||
### 路由
|
||
|
||
```typescript
|
||
{
|
||
path: '/admin/payment-configs',
|
||
component: () => import('@/features/admin/views/AdminPaymentConfigsView.vue'),
|
||
meta: { requiresAuth: true, requiresAdmin: true }
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🔐 安全考虑
|
||
|
||
1. **密钥加密**
|
||
- 数据库存储加密密文
|
||
- 传输使用 HTTPS
|
||
- 日志不记录明文密钥
|
||
|
||
2. **权限控制**
|
||
- 只有财务和超管可以管理
|
||
- 查看密钥需要额外权限
|
||
|
||
3. **审计日志**
|
||
- 记录所有配置变更
|
||
- 记录查看密钥操作
|
||
|
||
---
|
||
|
||
## 🚀 部署步骤
|
||
|
||
### 1. 环境变量配置
|
||
|
||
```bash
|
||
# .env 添加加密密钥(32字节)
|
||
PAYMENT_CONFIG_ENCRYPTION_KEY=your-32-byte-key-here-abcdefgh
|
||
```
|
||
|
||
生成密钥:
|
||
```bash
|
||
openssl rand -hex 16
|
||
```
|
||
|
||
示例结果:`a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6`(32个十六进制字符)
|
||
|
||
### 2. 数据库迁移
|
||
|
||
```bash
|
||
./scripts/dev.sh --reset-db
|
||
# 或手动执行迁移
|
||
mysql < backend/migrations/000002_add_payment_merchant_configs.sql
|
||
```
|
||
|
||
### 3. 初始化配置
|
||
|
||
通过后台管理界面添加第一个商户配置,或者应用启动时自动从 `.env` 迁移。
|
||
|
||
### 4. 向后兼容
|
||
|
||
如果数据库中没有配置,支付模块会回退使用 `.env` 中的配置。
|
||
|
||
---
|
||
|
||
## ✅ 优势
|
||
|
||
1. **灵活性** - 支持多商户、多场景
|
||
2. **安全性** - 密钥加密存储
|
||
3. **可维护性** - GUI 管理,无需重启
|
||
4. **可扩展性** - 易于支持其他支付渠道
|
||
5. **可审计** - 完整的操作日志
|
||
6. **高可用** - 兜底机制保证服务不中断
|
||
|
||
---
|
||
|
||
## 📝 下一步工作
|
||
|
||
- [ ] 执行数据库迁移
|
||
- [ ] 注册路由和依赖注入
|
||
- [ ] 实现前端管理界面
|
||
- [ ] 集成到支付模块
|
||
- [ ] 测试多商户切换
|
||
- [ ] 编写单元测试
|
||
- [ ] 更新部署文档
|