# 用户端结算流程扩展 操作时间:2026-09-07。操作类型:扩展。影响模块:商城结算、库存事务与幂等恢复。 ## 操作前后 原商城只能单件购买,以弹窗确认地址和金额。本次接入 `/checkout/:identity` 独立提交订单页面,选择地址、调整数量、填写配送备注、查看商品金额及合计,提交成功进入商城订单列表。游客登录回跳保留商品公开标识。图 12、14 原稿均已检查;本轮实现图 14 的基础结算链路,图 12 仍未实现,不能将商品摘要称作商品详情页。 ## 关键代码 - `apps/user_app/lib/ui/features/shop/checkout_page.dart`:按标识加载商品和默认地址,数量范围 1 至 min(库存,999),提交前不写订单;结果未知时冻结原数量、地址、备注,重试沿用原请求号。价格或库存明确变化时允许刷新后再确认。 - `shop_page.dart`、`app/router.dart`:购买进入独立结算页,路由继续受登录保护。 - `data/repositories/client_repository.dart`:新增 `submitShopOrder`,保留旧 `createShopOrder` 方法兼容调用。 - `backend/api/internal/logic/client/user/shop.go`:可选 expected_payable_amount;依据数据库价格计算,报价不符回滚库存。校验单项数量 ≤999、最多100项及备注长度。乘加之前检查整数溢出。优先查找本人同请求号订单,地址随后归档或库存归零不影响成功请求的恢复。 - `backend/api/internal/logic/client/user/checkout_test.go`:金额按数量结算、报价变化回滚、溢出不扣库存、已创建订单不再依赖地址。 - `apps/user_app/test/ui/shop_address_selection_test.dart`:确认前不下单、选择地址联系人、数量两件与金额一致、失败冻结输入、同请求号重试。 ## 接口兼容与环境 原 `POST /heqi/client/v1/user/shop/orders` 接受新增可选 `expected_payable_amount`(整数分);旧客户端可省略。客户端传入金额只用于确认,不代替服务端计算。错误 2401 表示价格变化,2402 表示库存不足或商品下架。错误对象在包初始化注册,避免并发请求修改 SDK 全局错误表。 本轮不修改数据库表,不运行迁移或 seed。本机 API 继续使用远程 PostgreSQL、Redis;没有启动本机数据库/缓存容器。 ## 验证 - Go 结算专项通过,SQL Mock 验证失败时回滚,不连接真实数据库。 - 远程指定开发账户对 `MOCK-EC-PRODUCT-010` 验证错误报价拒绝、两件金额、备注持久化、重复提交恢复同一订单及库存只扣一次。临时订单已取消,库存恢复,未支付或配送。 - Widget 结算流程通过;图 14 已生成四种手机宽度与两种文字缩放的 8 张截图,检查滚动后无溢出。 - 用户端全量 53 项测试、Flutter 静态检查、Go 全量测试及 vet 通过;Web 最新构建成功。[图 14 对照](视觉验收/A1/14_并排对照.png)继续用于记录缺项,不是通过证明。 - 浏览器验证登录回到指定商品结算、数量由1变2时金额由105元变210元、打开地址选择后返回仍保留数量;390×844实际页面已核对。真实创建/取消验证由 API 完成,浏览器未再次创建订单。结算页285行、后端结算专项68行;无新增依赖。 ## 未完成项与风险 图 14 中的预约配送、押金、优惠券、发票、结算前支付方式选择和多商品合并仍未接入。本页没有把设计示例金额当作真实收费规则。商品原图缺失仍需后台素材补齐;当前截图不通过严格 1:1。订单创建与付款分开,成功后进入既有订单页付款,不代表付款或配送已经成功。 单项数量/条目上限是本次输入保护,可能拒绝旧客户端超过上限的超大请求;正常用户端购买不受影响。后续购物车接入必须继续服务端计算总额,保留事务回滚与请求幂等测试。