Files
jnc-server/云印签支付流程检查.md

208 lines
7.2 KiB
Markdown
Raw Permalink Normal View History

2026-01-16 03:33:02 +08:00
# 云印签支付流程完整性检查
## 一、支付创建流程
### 1. 前端流程 ✅
- **位置**: `jnc-webview/src/components/Payment.vue`
- **步骤**:
1. 用户选择 `yunyinSignPay_wechat``yunyinSignPay_alipay`
2. 调用 `/pay/payment` 接口
3. 获取 `prepay_id``prepay_data`(支付链接)
4. 直接跳转到支付链接:`window.location.href = prepayUrl`
### 2. 后端流程 ✅
- **位置**: `jnc-server/app/main/api/internal/logic/pay/paymentlogic.go`
- **步骤**:
1. 接收支付请求
2. 从查询缓存获取用户姓名和手机号
3. **查询是否有未完成的签署**(复用逻辑)
4. 如果有未完成签署:
- 复用 `task_id``participant_id`
- 获取新的支付链接
5. 如果没有未完成签署:
- 获取 token 和操作ID带缓存
- 发起签署流程
- 获取支付链接
6. 创建订单记录(`order` 表)
7. 创建云印签订单记录(`yunyin_sign_pay_order` 表)
8. 返回支付链接(字符串类型,使用 `PrepayId` 字段)
### 3. 数据存储 ✅
- **订单表** (`order`):
- `order_no`: 订单号
- `payment_platform`: `yunyinSignPay_wechat``yunyinSignPay_alipay`
- `status`: `pending`
- **注意**: 不再在 `remark` 中存储云印签信息
- **云印签订单表** (`yunyin_sign_pay_order`):
- `order_id`: 关联订单ID
- `user_id`: 用户ID用于查询未完成签署
- `task_id`: 任务ID/流程ID唯一索引
- `participant_id`: 参与者ID
- `source_order_code`: 源订单号(用于查询支付状态)
- `amount`: 支付金额
- `pay_type`: 支付类型0=微信1=支付宝)
- `sign_status`: 签署状态0=待签署)
- `pay_status`: 支付状态0=待支付)
- `user_mobile`: 用户手机号(冗余字段)
- `user_name`: 用户姓名(冗余字段)
## 二、支付状态查询流程
### 1. 前端轮询 ✅
- **位置**: `jnc-webview/src/views/PaymentResult.vue`
- **步骤**:
1. 用户从支付页面返回后,进入支付结果页面
2. 从 URL 参数获取 `order_no``out_trade_no`
3. 首次调用 `/pay/check` 接口
4. 如果状态是 `pending`开始轮询每3秒一次最多30次
5. 如果状态变为 `paid``refunded`,停止轮询并跳转到结果页面
### 2. 后端主动查询 ✅
- **位置**: `jnc-server/app/main/api/internal/logic/pay/paymentchecklogic.go`
- **步骤**:
1. 查询订单状态
2. 如果订单状态是 `pending` 且支付平台是云印签:
- 调用 `QueryPayeeBill` 查询云印签平台
- 使用 `sourceOrderCode`(订单号)查询
3. 根据云印签返回的 `payStatus` 更新订单状态:
- `2` (支付成功) → `paid`
- `3` (支付失败) → `failed`
- `4` (已退款) → `refunded`
- `0, 1` (订单生成/支付中) → 保持 `pending`
4. 同步更新 `yunyin_sign_pay_order` 表的支付状态
5. 如果支付成功,发送异步任务处理后续流程
### 3. 状态映射 ✅
- **云印签 payStatus**:
- `0`: 订单生成
- `1`: 支付中
- `2`: 支付成功
- `3`: 支付失败
- `4`: 已退款
- **我们的订单状态**:
- `pending`: 待支付
- `paid`: 已支付
- `failed`: 支付失败
- `refunded`: 已退款
- **我们的支付状态** (`yunyin_sign_pay_order.pay_status`):
- `0`: 待支付
- `1`: 已支付
- `2`: 已退款
## 三、前后端数据字段一致性 ✅
### 1. 支付创建接口 (`/pay/payment`)
- **请求字段**: `pay_method` (支持 `yunyinSignPay_wechat`, `yunyinSignPay_alipay`)
- **响应字段**:
- `prepay_id`: 支付链接(字符串类型)
- `prepay_data`: 备用字段(对象类型)
- `order_no`: 订单号
- **前端读取**: `data.value.data.prepay_id || data.value.data.prepay_data`
### 2. 支付状态查询接口 (`/pay/check`)
- **请求字段**: `order_no`
- **响应字段**:
- `type`: `"query"`
- `status`: `"pending"` | `"paid"` | `"failed"` | `"refunded"`
- **前端处理**: 根据 `status` 判断是否继续轮询 ✅
## 四、潜在问题和改进建议
### ⚠️ 问题1: 支付完成后用户可能不会自动跳转
**现状**: 云印签支付完成后,用户可能不会自动跳转回我们的页面
**解决方案**:
- ✅ 已实现:前端通过轮询主动查询支付状态
- ✅ 已实现:用户手动返回后,支付结果页面会自动轮询
### ⚠️ 问题2: 订单状态更新需要检查并发
**现状**: 使用乐观锁更新订单状态,但需要确保不会重复更新
**检查**: ✅ 已实现:使用 `UpdateWithVersion` 和检查 `order.Status == "pending"`
### ⚠️ 问题3: 查询失败时的处理
**现状**: 如果查询云印签平台失败,会记录错误但继续返回当前状态
**检查**: ✅ 已实现:错误处理完善,不影响正常流程
### ⚠️ 问题4: 未找到收款单记录的处理
**现状**: 如果订单刚创建,云印签平台可能还没有记录
**检查**: ✅ 已实现:返回错误但不影响,继续返回 `pending` 状态,前端会继续轮询
## 五、完整流程验证
### 场景1: 首次支付(创建新签署流程)✅
1. 用户选择云印签支付
2. 后端查询无未完成签署
3. 创建新签署流程
4. 创建订单和云印签订单记录
5. 返回支付链接
6. 前端跳转到支付页面
7. 用户完成支付
8. 前端轮询查询状态
9. 后端主动查询云印签平台
10. 更新订单状态为 `paid`
11. 发送异步任务处理后续流程
12. 前端跳转到结果页面
### 场景2: 复用未完成签署 ✅
1. 用户之前创建了签署但未支付
2. 用户再次选择云印签支付
3. 后端查询到未完成签署
4. 复用 `task_id``participant_id`
5. 获取新的支付链接
6. 创建新订单和云印签订单记录(关联新的订单)
7. 返回支付链接
8. 后续流程同场景1
### 场景3: 支付失败 ✅
1. 用户支付失败
2. 前端轮询查询状态
3. 后端查询到 `payStatus = 3`
4. 更新订单状态为 `failed`
5. 前端显示支付失败提示
### 场景4: 退款 ✅
1. 订单已支付
2. 发生退款
3. 前端轮询查询状态
4. 后端查询到 `payStatus = 4`
5. 更新订单状态为 `refunded`
6. 更新退款时间
7. 前端显示退款状态
## 六、总结
### ✅ 已完成的流程
1. 支付创建流程(包括复用逻辑)
2. 支付状态主动查询
3. 订单状态自动更新
4. 云印签订单表数据同步
5. 前后端数据字段一致性
6. 错误处理和边界情况
### ✅ 代码质量
- 使用了事务保证数据一致性
- 使用了乐观锁避免并发问题
- 错误处理完善
- 日志记录详细
### ✅ 前后端联调
- API 接口定义清晰
- 数据字段命名一致
- 状态映射正确
- 轮询机制完善
## 七、建议测试点
1. **首次支付流程**: 验证创建新签署流程是否正常
2. **复用签署流程**: 验证复用逻辑是否正常工作
3. **支付成功**: 验证状态更新和后续流程是否正常
4. **支付失败**: 验证失败状态是否正确处理
5. **退款**: 验证退款状态是否正确处理
6. **网络异常**: 验证查询失败时的容错处理
7. **并发支付**: 验证同一用户多次支付的场景
8. **订单状态一致性**: 验证订单表和云印签订单表的状态是否同步