# 云印签支付流程完整性检查 ## 一、支付创建流程 ### 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. **订单状态一致性**: 验证订单表和云印签订单表的状态是否同步