|
@@ -0,0 +1,256 @@
|
|
|
|
|
+# Story 004.003: 集成额度支付到现有支付流程
|
|
|
|
|
+
|
|
|
|
|
+## Status
|
|
|
|
|
+Draft
|
|
|
|
|
+
|
|
|
|
|
+## Story
|
|
|
|
|
+**As a** 小程序用户,
|
|
|
|
|
+**I want** 可以使用信用额度进行支付,
|
|
|
|
|
+**so that** 在余额不足时也能完成购买
|
|
|
|
|
+
|
|
|
|
|
+## Acceptance Criteria
|
|
|
|
|
+1. 在支付页面增加"额度支付"选项
|
|
|
|
|
+2. 实现额度支付订单处理逻辑
|
|
|
|
|
+3. 额度为0的用户无法使用额度支付
|
|
|
|
|
+4. 支付成功后更新用户已用额度和可用额度
|
|
|
|
|
+5. 实现额度恢复机制:
|
|
|
|
|
+ - 结账时恢复相应额度(订单完成)
|
|
|
|
|
+ - 取消订单时恢复全额额度
|
|
|
|
|
+ - 退款时恢复相应额度
|
|
|
|
|
+6. 在小程序个人中心显示累计欠款
|
|
|
|
|
+7. 确保与现有微信支付流程并行工作,互不干扰
|
|
|
|
|
+
|
|
|
|
|
+## Tasks / Subtasks
|
|
|
|
|
+- [ ] **扩展订单模块支持额度支付类型** (AC: 1, 2, 3, 4, 7)
|
|
|
|
|
+ - [ ] 检查`orders_mt`表的`pay_type`字段,确认现有支付类型
|
|
|
|
|
+ - [ ] 扩展`pay_type`枚举,新增`CREDIT`额度支付类型
|
|
|
|
|
+ - [ ] 更新订单实体类型定义,支持额度支付类型
|
|
|
|
|
+ - [ ] 更新订单创建schema,验证额度支付相关参数
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **在支付模块中集成额度支付逻辑** (AC: 1, 2, 3, 4, 7)
|
|
|
|
|
+ - [ ] 检查`@d8d/mini-payment-mt`支付模块结构
|
|
|
|
|
+ - [ ] 在支付模块中添加额度支付处理逻辑
|
|
|
|
|
+ - [ ] 实现额度支付检查:验证用户可用额度
|
|
|
|
|
+ - [ ] 实现额度扣减逻辑:调用`CreditBalanceService.payment()`方法
|
|
|
|
|
+ - [ ] 更新支付创建流程,支持额度支付类型
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **实现额度恢复机制** (AC: 5)
|
|
|
|
|
+ - [ ] **结账恢复**:在信用管理UI中已实现`/api/credit-balance/checkout`接口调用
|
|
|
|
|
+ - [ ] **取消订单恢复**:在订单模块取消订单时调用`CreditBalanceService.restoreBalanceForCancelOrder()`方法
|
|
|
|
|
+ - [ ] **退款恢复**:在支付模块退款处理时调用`CreditBalanceService.restoreBalanceForRefund()`方法
|
|
|
|
|
+ - [ ] 确保恢复操作的幂等性:同一订单只能恢复一次额度
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **更新小程序支付页面** (AC: 1, 3, 7)
|
|
|
|
|
+ - [ ] 检查小程序支付页面组件结构
|
|
|
|
|
+ - [ ] 在支付选项中添加"额度支付"按钮
|
|
|
|
|
+ - [ ] 实现额度支付选择逻辑:检查用户可用额度
|
|
|
|
|
+ - [ ] 额度为0的用户禁用额度支付选项
|
|
|
|
|
+ - [ ] 保持与微信支付选项的并行工作
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **在小程序个人中心显示欠款信息** (AC: 6)
|
|
|
|
|
+ - [ ] 检查小程序个人中心页面结构
|
|
|
|
|
+ - [ ] 添加欠款信息显示组件
|
|
|
|
|
+ - [ ] 调用额度查询API获取用户欠款信息
|
|
|
|
|
+ - [ ] 设计欠款信息显示样式(总额度、已用额度、可用额度、欠款金额)
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **编写集成测试** (AC: 1, 2, 3, 4, 5, 6, 7)
|
|
|
|
|
+ - [ ] **支付流程测试**:测试额度支付完整流程
|
|
|
|
|
+ - [ ] **额度恢复测试**:测试结账、取消订单、退款时的额度恢复
|
|
|
|
|
+ - [ ] **额度检查测试**:测试额度为0用户无法使用额度支付
|
|
|
|
|
+ - [ ] **并发测试**:测试额度支付与微信支付的并行工作
|
|
|
|
|
+ - [ ] **欠款显示测试**:测试小程序个人中心欠款信息显示
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **验证模块间集成** (AC: 7)
|
|
|
|
|
+ - [ ] 验证订单模块与额度模块的集成
|
|
|
|
|
+ - [ ] 验证支付模块与额度模块的集成
|
|
|
|
|
+ - [ ] 验证小程序前端与后端API的集成
|
|
|
|
|
+ - [ ] 确保所有模块间调用类型安全
|
|
|
|
|
+
|
|
|
|
|
+## Dev Notes
|
|
|
|
|
+
|
|
|
|
|
+### 技术栈信息 [Source: architecture/tech-stack.md]
|
|
|
|
|
+- **前端框架**: React 19.1.0 + TypeScript
|
|
|
|
|
+- **后端框架**: Hono 4.8.5 + TypeScript
|
|
|
|
|
+- **数据库**: PostgreSQL 17 + TypeORM 0.3.25
|
|
|
|
|
+- **支付模块**: `@d8d/mini-payment` (微信小程序支付模块)
|
|
|
|
|
+- **额度模块**: `@d8d/credit-balance-module-mt` (多租户信用额度模块)
|
|
|
|
|
+- **订单模块**: `@d8d/orders-module-mt` (多租户订单管理模块)
|
|
|
|
|
+
|
|
|
|
|
+### 项目结构信息 [Source: architecture/source-tree.md]
|
|
|
|
|
+- **包管理**: 使用pnpm workspace管理多包依赖关系
|
|
|
|
|
+- **包架构层次**:
|
|
|
|
|
+ - **基础设施层**: shared-types → shared-utils → shared-crud
|
|
|
|
|
+ - **测试基础设施**: shared-test-util
|
|
|
|
|
+ - **业务模块层**: 多租户模块包(-mt后缀),支持租户数据隔离
|
|
|
|
|
+ - **前端界面层**: 共享UI组件包 + 单租户管理界面包 + 多租户管理界面包
|
|
|
|
|
+ - **应用层**: server (重构后)
|
|
|
|
|
+- **多租户架构**:
|
|
|
|
|
+ - **包复制策略**: 基于Epic-007方案,通过复制单租户包创建多租户版本
|
|
|
|
|
+ - **租户隔离**: 通过租户ID实现数据隔离,支持多租户部署
|
|
|
|
|
+ - **前端包**: 10个多租户管理界面包,支持租户上下文管理
|
|
|
|
|
+ - **后端包**: 10个多租户模块包,支持租户数据隔离
|
|
|
|
|
+- **文件命名**: 保持现有kebab-case命名约定
|
|
|
|
|
+- **模块化架构**: 采用分层包结构,支持按需安装和独立开发
|
|
|
|
|
+
|
|
|
|
|
+### 从故事004.001和004.002学到的经验教训
|
|
|
|
|
+1. **PostgreSQL类型兼容性**: PostgreSQL不支持`tinyint`类型,需要改为`smallint`
|
|
|
|
|
+2. **集成测试数据库连接**: 使用`IntegrationTestDatabase`类替代`createIntegrationTestDb`函数
|
|
|
|
|
+3. **路由架构**: 参照订单模块采用链式聚合模式,使用独立路由文件聚合导出
|
|
|
|
|
+4. **测试写法**: 使用真实JWT令牌和RPC风格API调用
|
|
|
|
|
+5. **类型检查**: 注意分页参数类型、枚举使用、referenceId类型等问题
|
|
|
|
|
+6. **小数精度**: TypeORM decimal字段返回字符串,在服务中需要转换为数字
|
|
|
|
|
+7. **数据库索引**: 避免重复创建相同索引名称
|
|
|
|
|
+8. **认证失败**: 创建测试数据工厂,使用真实用户实体生成JWT令牌
|
|
|
|
|
+9. **Zod验证**: 将Schema中的`z.number()`改为`z.coerce.number()`
|
|
|
|
|
+10. **表单验证**: 为Zod schema字段添加中文错误消息,使用`z.coerce.number()`支持类型转换
|
|
|
|
|
+11. **组件集成**: 信用额度管理对话框已集成到用户管理UI包中
|
|
|
|
|
+
|
|
|
|
|
+### 数据模型设计 [Source: docs/prd/epic-004-credit-payment.md#数据库设计]
|
|
|
|
|
+**credit_balance_mt表结构**:
|
|
|
|
|
+```sql
|
|
|
|
|
+CREATE TABLE credit_balance_mt (
|
|
|
|
|
+ id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
|
|
|
|
|
+ tenant_id INT UNSIGNED NOT NULL COMMENT '租户ID',
|
|
|
|
|
+ user_id INT UNSIGNED NOT NULL COMMENT '用户ID',
|
|
|
|
|
+ total_limit DECIMAL(10,2) DEFAULT 0.00 COMMENT '总额度',
|
|
|
|
|
+ used_amount DECIMAL(10,2) DEFAULT 0.00 COMMENT '已用额度',
|
|
|
|
|
+ available_amount DECIMAL(10,2) GENERATED ALWAYS AS (total_limit - used_amount) STORED COMMENT '可用额度',
|
|
|
|
|
+ is_enabled TINYINT DEFAULT 1 COMMENT '是否启用(0:禁用,1:启用)',
|
|
|
|
|
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
|
|
|
+ UNIQUE KEY uk_tenant_user (tenant_id, user_id),
|
|
|
|
|
+ INDEX idx_tenant_id (tenant_id),
|
|
|
|
|
+ INDEX idx_user_id (user_id)
|
|
|
|
|
+) COMMENT='用户信用额度表';
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**credit_balance_log_mt表结构**:
|
|
|
|
|
+```sql
|
|
|
|
|
+CREATE TABLE credit_balance_log_mt (
|
|
|
|
|
+ id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
|
|
|
|
|
+ tenant_id INT UNSIGNED NOT NULL COMMENT '租户ID',
|
|
|
|
|
+ user_id INT UNSIGNED NOT NULL COMMENT '用户ID',
|
|
|
|
|
+ change_type VARCHAR(20) NOT NULL COMMENT '变更类型: SET_LIMIT(设置额度), PAYMENT(支付扣减), CHECKOUT(结账恢复), CANCEL_ORDER(取消订单恢复), REFUND(退款恢复), ADJUST(调整额度)',
|
|
|
|
|
+ change_amount DECIMAL(10,2) NOT NULL COMMENT '变更金额(正数表示增加额度,负数表示减少额度)',
|
|
|
|
|
+ before_total DECIMAL(10,2) COMMENT '变更前总额度',
|
|
|
|
|
+ after_total DECIMAL(10,2) COMMENT '变更后总额度',
|
|
|
|
|
+ before_used DECIMAL(10,2) COMMENT '变更前已用额度',
|
|
|
|
|
+ after_used DECIMAL(10,2) COMMENT '变更后已用额度',
|
|
|
|
|
+ reference_id VARCHAR(100) COMMENT '关联ID(订单号等)',
|
|
|
|
|
+ remark VARCHAR(500) COMMENT '备注',
|
|
|
|
|
+ operator_id INT UNSIGNED COMMENT '操作人ID',
|
|
|
|
|
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
|
+ INDEX idx_tenant_user (tenant_id, user_id),
|
|
|
|
|
+ INDEX idx_reference (reference_id),
|
|
|
|
|
+ INDEX idx_created (created_at)
|
|
|
|
|
+) COMMENT='额度变更记录表';
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### API设计 [Source: docs/prd/epic-004-credit-payment.md#API设计]
|
|
|
|
|
+**额度模块对外API(已实现)**:
|
|
|
|
|
+1. `GET /api/credit-balance/{userId}` - 查询用户额度
|
|
|
|
|
+2. `PUT /api/credit-balance/{userId}` - 设置用户额度
|
|
|
|
|
+3. `POST /api/credit-balance/{userId}/adjust` - 调整用户额度
|
|
|
|
|
+4. `GET /api/credit-balance/{userId}/logs` - 查询额度变更记录
|
|
|
|
|
+5. `POST /api/credit-balance/payment` - 额度支付
|
|
|
|
|
+6. `POST /api/credit-balance/checkout` - 结账恢复额度
|
|
|
|
|
+
|
|
|
|
|
+**额度模块服务接口(供其他模块调用)**:
|
|
|
|
|
+1. `CreditBalanceService.restoreBalanceForCancelOrder(orderId, userId, amount)` - 取消订单恢复额度
|
|
|
|
|
+2. `CreditBalanceService.restoreBalanceForRefund(orderId, userId, refundAmount)` - 退款恢复额度
|
|
|
|
|
+
|
|
|
|
|
+**设计说明**:
|
|
|
|
|
+- **结账恢复**: 需要人工确认,因此通过信用管理UI手动触发,调用`/api/credit-balance/checkout`接口
|
|
|
|
|
+- **取消订单恢复**: 自动触发,订单模块在取消订单时直接调用`CreditBalanceService.restoreBalanceForCancelOrder()`方法
|
|
|
|
|
+- **退款恢复**: 自动触发,支付模块在退款处理时直接调用`CreditBalanceService.restoreBalanceForRefund()`方法
|
|
|
|
|
+- **模块间调用**: 使用PNPM工作空间,通过`@d8d/credit-balance-module-mt`包名导入服务类进行直接调用
|
|
|
|
|
+
|
|
|
|
|
+### 文件位置和命名约定
|
|
|
|
|
+- **额度模块包**: `packages/credit-balance-module-mt/`
|
|
|
|
|
+- **额度管理UI模块包**: `packages/credit-balance-management-ui-mt/`
|
|
|
|
|
+- **支付模块包**: `packages/mini-payment-mt/` (需要检查是否存在多租户版本)
|
|
|
|
|
+- **订单模块包**: `packages/orders-module-mt/`
|
|
|
|
|
+- **小程序项目**: `mini/` 目录下
|
|
|
|
|
+- **测试文件**: 各包的`tests/`目录下
|
|
|
|
|
+
|
|
|
|
|
+### 集成点要求
|
|
|
|
|
+1. **订单模块集成**:
|
|
|
|
|
+ - 扩展`orders_mt`表的`pay_type`字段,新增额度支付类型
|
|
|
|
|
+ - 订单模块导入`@d8d/credit-balance-module-mt`包
|
|
|
|
|
+ - 在取消订单逻辑中调用`CreditBalanceService.restoreBalanceForCancelOrder()`方法
|
|
|
|
|
+
|
|
|
|
|
+2. **支付模块集成**:
|
|
|
|
|
+ - 在`@d8d/mini-payment-mt`中新增额度支付处理逻辑
|
|
|
|
|
+ - 支付模块导入`@d8d/credit-balance-module-mt`包
|
|
|
|
|
+ - 在退款处理逻辑中调用`CreditBalanceService.restoreBalanceForRefund()`方法
|
|
|
|
|
+
|
|
|
|
|
+3. **小程序集成**:
|
|
|
|
|
+ - 更新支付页面,增加"额度支付"选项
|
|
|
|
|
+ - 更新个人中心页面,显示累计欠款信息
|
|
|
|
|
+ - 调用额度查询API获取用户额度信息
|
|
|
|
|
+
|
|
|
|
|
+4. **额度恢复逻辑**:
|
|
|
|
|
+ - **幂等性保证**: 同一订单只能恢复一次额度,防止重复恢复
|
|
|
|
|
+ - **金额验证**: 恢复金额不能超过原支付金额
|
|
|
|
|
+ - **状态检查**: 只有特定订单状态才能触发恢复
|
|
|
|
|
+ - **日志记录**: 每次恢复都记录详细的变更日志
|
|
|
|
|
+ - **事务处理**: 额度恢复与订单状态更新在同一事务中
|
|
|
|
|
+
|
|
|
|
|
+### 技术约束
|
|
|
|
|
+- **多租户支持**: 所有模块需要支持多租户上下文,通过租户ID进行数据隔离
|
|
|
|
|
+- **API集成**: 使用RPC风格的Hono Client进行API调用,确保类型安全
|
|
|
|
|
+- **状态管理**: 使用React Query进行服务端状态管理,确保数据同步
|
|
|
|
|
+- **错误处理**: 完整的错误处理机制,显示友好的错误提示
|
|
|
|
|
+- **事务处理**: 额度扣减和恢复操作使用数据库事务确保数据一致性
|
|
|
|
|
+- **并发控制**: 处理额度支付时的并发请求,防止超额支付
|
|
|
|
|
+
|
|
|
|
|
+### 没有在架构文档中找到的特定指导
|
|
|
|
|
+- 具体的支付模块实现细节
|
|
|
|
|
+- 具体的订单模块支付类型扩展实现
|
|
|
|
|
+- 具体的小程序支付页面修改示例
|
|
|
|
|
+- 具体的额度恢复幂等性实现示例
|
|
|
|
|
+
|
|
|
|
|
+## Testing
|
|
|
|
|
+### 测试标准 [Source: architecture/testing-strategy.md]
|
|
|
|
|
+- **测试文件位置**: 各包的`tests/`目录下
|
|
|
|
|
+- **单元测试位置**: `tests/unit/**/*.test.tsx`
|
|
|
|
|
+- **集成测试位置**: `tests/integration/**/*.test.tsx`
|
|
|
|
|
+- **测试框架**: Vitest + Testing Library + React Testing Library
|
|
|
|
|
+- **覆盖率要求**: 单元测试 ≥ 80%,集成测试 ≥ 60%
|
|
|
|
|
+- **测试模式**: 使用测试数据工厂模式,避免硬编码测试数据
|
|
|
|
|
+- **API模拟**: 使用MSW或Vitest的mock功能模拟API调用
|
|
|
|
|
+
|
|
|
|
|
+### 测试策略要求
|
|
|
|
|
+- **单元测试**: 验证单个组件功能、hooks逻辑、工具函数
|
|
|
|
|
+- **集成测试**: 验证API集成、权限控制、组件间协作
|
|
|
|
|
+- **支付流程测试**: 测试额度支付完整流程,包括额度检查、扣减、订单创建
|
|
|
|
|
+- **额度恢复测试**: 测试结账、取消订单、退款时的额度恢复逻辑
|
|
|
|
|
+- **并发测试**: 测试额度支付与微信支付的并行工作
|
|
|
|
|
+- **错误处理测试**: 测试各种错误场景和异常情况(额度不足、额度为0等)
|
|
|
|
|
+- **幂等性测试**: 测试额度恢复的幂等性,防止重复恢复
|
|
|
|
|
+
|
|
|
|
|
+### 测试数据管理
|
|
|
|
|
+- 使用测试数据工厂模式创建测试数据
|
|
|
|
|
+- 模拟API响应,避免真实API调用
|
|
|
|
|
+- 使用唯一标识符确保测试数据隔离
|
|
|
|
|
+- 模拟用户认证和权限状态
|
|
|
|
|
+- 创建测试用户额度数据(不同额度状态:正常、额度为0、额度不足)
|
|
|
|
|
+
|
|
|
|
|
+## Change Log
|
|
|
|
|
+| Date | Version | Description | Author |
|
|
|
|
|
+|------|---------|-------------|--------|
|
|
|
|
|
+| 2025-12-04 | 1.0 | 初始故事创建 | Bob (Scrum Master) |
|
|
|
|
|
+
|
|
|
|
|
+## Dev Agent Record
|
|
|
|
|
+*此部分由开发代理在实现过程中填写*
|
|
|
|
|
+
|
|
|
|
|
+### Agent Model Used
|
|
|
|
|
+
|
|
|
|
|
+### Debug Log References
|
|
|
|
|
+
|
|
|
|
|
+### Completion Notes List
|
|
|
|
|
+
|
|
|
|
|
+### File List
|
|
|
|
|
+
|
|
|
|
|
+## QA Results
|
|
|
|
|
+*此部分由QA代理在审查完成后填写*
|