9.4 KiB
9.4 KiB
id, title, phase, deps, status, created, vikunja_task_id, context_ref, work_branch, needs_device, needs_human_review, write_paths
| id | title | phase | deps | status | created | vikunja_task_id | context_ref | work_branch | needs_device | needs_human_review | write_paths | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| T-402 | 待付款人工收口与付款事实记录 | 4 |
|
TODO | 2026-08-04 | 51 | 8600c33 |
task/t-402-payment-closure | false | true |
|
背景
T-208 已冻结创建待付款订单后的 WAITING_PAYMENT 事实:仅当提交记录为 SUBMITTED,或管理员调和结论为 CONFIRMED_CREATED 时,系统才知道订单已创建。T-403 负责展示这些既有事实。本任务只记录管理员已经在拼多多人工完成真实付款这一外部事实,并把任务收口为成功;系统本身没有付款,也不得验证或自动执行付款。
关联
- Feature:F011
- Story:US006
- Integration:IX006
- 前置任务:T-403
- 后续消费者:T-404
实现方案
- 新增唯一迁移
00009_payment_closure.sql,建立追加式payment_closures:绑定同一 lineage 的 task、submission、attempt、authorization,以及管理员 actor、服务端 UTC 记录时间、幂等键与规范化请求摘要。唯一约束保证同一任务/提交只能收口一次,并保证同一管理员幂等键不可复用为不同请求;外键/约束必须阻止跨 lineage 事实。不得保存付款方式、账户、卡号、订单凭据、地址、手机号或截图/XML。migration down 只允许在payment_closures为空时执行;存在任意事实必须在删除表或约束前原子拒绝,禁止丢失付款审计事实。 - 在任务详情的
WAITING_PAYMENT区域明确显示“订单已创建,系统尚未付款”,同时展示商品、规格、数量、金额上限,以及 T-208/T-403 已有提交、调和和三道闸门证据。不得暗示系统已付款。 - 管理员必须先在拼多多外部人工完成真实付款,再完成三个且仅三个确认组:
goods_spec_quantity_confirmed表示商品/规格/数量已核对,amount_within_cap_confirmed表示订单金额未超过授权上限,externally_paid_confirmed表示管理员已在拼多多人工完成真实付款。三项 wire 值必须全部严格为true;任一缺失、为false或无法严格解析均返回 400 且零写入。按钮文案明确为“记录人工付款并标记完成(不执行付款)”。 POST /tasks/{id}/mark-paid仅接受管理员会话与 CSRF,通过严格表单读取 UUIDv4 幂等键、expected task version、当前 submission id 和上述三个固定布尔确认组,不接受别名或额外确认字段。actor 只能来自会话,时间只能来自服务端 UTC。- 在单一事务和写锁内重新读取 task、submission、attempt、authorization:四者必须属于同一 lineage;任务必须正好是
WAITING_PAYMENT,submission 必须正好是该任务当前唯一提交且关联同一 attempt/authorization,authorization 必须正好是CONSUMED。submission 必须为SUBMITTED,或为已有 T-208CONFIRMED_CREATED最终调和事实的MANUAL_RESOLVED。旧 task version、错误/过期 submission 固定返回 409 且零写入;任一 lineage、authorization、submission 或 task 状态冲突也必须返回 409、零写入,并让详情进入只读安全核查,绝不能推进为SUCCEEDED。 - 所有检查通过后,同一事务追加 payment closure,并将任务从
WAITING_PAYMENT单向推进到SUCCEEDED、version + 1。submission、attempt、authorization 和已消费的提交围栏永久不可变,不得重开、释放、重置、重新授权或重新提交。 - 幂等性必须先查事实:同 key、同规范化 payload 在响应丢失和进程重启后稳定重放同一结果;同 key、不同 payload 返回 409;不同 key 在任务已收口后返回
payment_already_recorded409。规范化 payload 必须包含 task、submission、expected version 和三个固定确认组。不得仅因任务已是SUCCEEDED就伪造成功响应。 - 成功页/详情页显示记录 actor、服务端时间和“仅记录人工付款事实,系统未执行付款”。失败保留用户输入并给出可操作提示,焦点回到错误摘要;事实冲突时只显示安全核查,不提供重试提交、释放或重新授权动作。
- 自动化测试只使用本地数据库夹具构造
WAITING_PAYMENT和既有提交事实,覆盖事务、冲突、幂等、重启与 UI;不得连接拼多多、请求真实资金、模拟付款控件或要求测试人员实际付款。needs_human_review只验收语义、权限和交互,不代表测试中发生真实付款。
验收
- 三个且仅三个 wire 确认组固定为
goods_spec_quantity_confirmed、amount_within_cap_confirmed、externally_paid_confirmed;三项全部严格为true才能继续,逐项覆盖缺失、false、非法值和额外别名,均返回 400 且零写入。 - 只有管理员、有效 CSRF、精确 task version、精确当前 submission、同 lineage 的 task/submission/attempt/authorization 和
CONSUMEDauthorization 能写入;旧版本和错误/过期 submission 稳定返回 409 且零写入。 - 覆盖
SUBMITTED与CONFIRMED_CREATED两条允许路径,以及跨 task/attempt/authorization、authorization 非CONSUMED、其它任务/提交状态和事实冲突;冲突均返回 409、零写入、进入只读安全核查且绝不SUCCEEDED。 - 覆盖并发双击、同键同载荷重放、同键异载荷冲突、不同键重复收口和进程重启;事实表和任务状态在同一事务提交或回滚。
- migration 覆盖 up、重开、外键/唯一/lineage/append-only 约束、空表 down 成功、存在任意 payment closure 时 down 在删表前原子拒绝,以及
foreign_key_check。 - 页面显著显示“系统尚未付款”和“不执行付款”,键盘操作、焦点、错误摘要、安全核查态及移动宽度可用。
- 自动测试不需要真实付款,不访问手机或拼多多;代码不得包含任何支付、免密、先用后付或扣款控件操作。
- 运行
go test ./...、go test -race ./...、go vet ./...、go build ./...、前端交互检查、根目录初始化门禁、上下文校验、导出校验和git diff --check。
执行记录
(暂无)
边界
mark-paid只记录管理员已经在拼多多外部人工完成真实付款的事实;系统没有执行付款,也不得发起、 验证、模拟或自动化支付,不得读取或保存付款方式、账户、卡号、订单凭据、地址或手机号。- 三个且仅三个确认组固定为
goods_spec_quantity_confirmed、amount_within_cap_confirmed、externally_paid_confirmed;三项 wire 值必须全部严格为true。任一缺失、为false、非法值或 别名返回 400 且零写入;旧 task version 与错误/过期 submission 固定返回 409。 - 只允许精确处于
WAITING_PAYMENT的任务和精确当前 submission 收口。事务必须确认 task、 submission、attempt、authorization 属于同一 lineage,authorization 正好为CONSUMED; submission 必须是SUBMITTED,或已有 T-208CONFIRMED_CREATED最终调和事实。任一归属、 状态或事实冲突都返回 409、零写入并进入只读安全核查,绝不能推进为SUCCEEDED。 - actor 只能取自已认证管理员会话,记录时间只能取服务端 UTC。幂等事实必须在任何状态短路前检查:
同 key 同规范化载荷稳定重放,同 key 异载荷返回 409;不同 key 重复收口返回
payment_already_recorded409,不得仅因任务已是SUCCEEDED就伪造成功响应。 - payment closure 事实与 task
WAITING_PAYMENT → SUCCEEDED、version + 1 必须在同一事务内原子 提交或回滚。submission、authorization 和已消费围栏永久不可变,不得重开、释放、重置、重新授权、 重新领取或重新提交。 - 本任务唯一新增 migration 是
00009_payment_closure.sql;事实表只保存同一 lineage 的 task、 submission、attempt、authorization、actor、服务端时间、幂等键和请求摘要,不保存截图、XML、 支付凭据或新的 evidence kind。payment_closures为空时才允许 migration down;存在任意事实时 必须在删表或约束前原子拒绝,禁止丢失付款审计事实。 - 自动化测试只使用本地数据库夹具,不访问手机或拼多多,不请求真实资金,也不要求测试人员真实付款。
needs_human_review只验收管理 UI 的未付款语义、权限、确认和无障碍交互。 - 本任务不修改
client/或拼多多页面判据,不点击支付、免密支付、先用后付或任何扣款控件。