菜单消费账单核对与并行支付设计
1. 目标
将 CusumptionMachine 菜单消费页点击支付后的交互,由“选择支付方式弹框”调整为“账单核对弹框”:主屏展示已选菜品明细和订单总金额,同时监听刷卡与扫码,先取得有效支付凭证的一路发起支付;弹框内保留人脸支付入口,人脸识别成功后继续使用菜单消费现有刷脸支付链路。
2. 已确认范围
- 保留购物车为空校验。
- 删除订单金额大于 100 元时的限制和确认弹框。
- 账单核对弹框只显示在主屏,不新增或同步客屏账单界面。
- 客屏现有支付结果展示保持不变。
- 设备类型 4(伟邦双屏)、5(伟邦壁挂)、7(优卡特双屏)使用各自现有硬件驱动,同时监听刷卡和扫码。
- 设备类型 1、2、3 保留现有扫码能力,并在账单核对弹框中保留人脸支付入口;不新增这些设备当前不具备的刷卡能力。
- 支付请求参数、HTTP/MQTT 分流、离线记账、成功失败提示、订单落库和购物车清理继续复用菜单消费现有逻辑。
3. 方案比较
方案 A:新增菜单消费专用账单核对弹框(采用)
新增一个以菜单菜品为数据源的账单核对弹框,并通过设备类型创建对应的卡、码监听器。弹框负责账单展示、支付会话互斥、硬件资源释放和人脸入口;MainActivity 继续负责卡号校验、付款码清洗、人脸识别和支付请求。
优点:职责清晰,不污染称重商品模型,不复制 SellWeight 已知有问题的刷脸请求代码,也能保留 CusumptionMachine 的多设备适配。
方案 B:扩展现有支付方式选择弹框
在 PaymentWayChoosePop 内增加账单和硬件监听。缺点:该弹框原本负责手动选择支付方式,改造后同时承担账单、串口和会话协调,职责冲突且容易影响其他调用方。
方案 C:直接复制 SellWeight 的 BillCheckPop
缺点:SellWeight 使用 ProductBean 和固定称重设备串口,无法直接承载菜单 DishBean,也不适配当前项目的多设备驱动,且其刷脸链路存在金额和请求分流问题。
4. 主流程
- 用户点击菜单消费支付按钮。
- 如果购物车为空,提示先选择菜品并结束;不再进行 100 元金额预警。
- 主屏打开账单核对弹框,展示当前已选菜品和总金额。
- 弹框进入单次支付会话:设备 4、5、7 同时启动各自刷卡和扫码监听;设备 1、2、3 启动现有扫码流程,不创建不支持的刷卡监听;人脸支付按钮按现有支付开关控制显示。
- 卡号或付款码先到达并通过基础校验的一路获得本次会话处理权。
- 弹框立即标记会话结束,关闭所有已启动的监听器并关闭自身,迟到回调直接丢弃。
MainActivity按凭证类型继续处理:刷卡先查本地人员库,存在后调用现有requestPayment("", "", cardCode);扫码清洗并去除支付码前缀,调用现有requestPayment(payCode, "", "")。- 支付成功或失败后的行为沿用现有菜单消费逻辑。
5. 人脸支付流程
- 用户点击账单核对弹框中的人脸支付按钮。
- 弹框先结束当前卡码监听会话并释放硬件资源。
- 主屏打开菜单消费现有
FaceRecognitionPop,不复制SellWeight的刷脸实现。 - 识别成功后使用
user.getUserId()调用现有requestPayment("", userId, "")。 - 识别失败、超时或取消时沿用现有提示,并且不自动恢复已关闭的账单弹框。
6. 组件职责
菜单账单核对弹框
- 接收菜品列表、总金额和允许的支付能力,并展示账单明细。
- 管理单次支付会话状态,启动和释放当前设备支持的卡码监听器。
- 将首个有效凭证或人脸按钮事件回调给页面。
- 取消或销毁时兜底释放全部硬件资源。
MainActivity
- 负责购物车为空校验和打开账单弹框。
- 负责本地卡号校验、付款码清洗以及人脸识别弹框。
- 复用现有支付请求和结果处理。
- 不再展示
PaymentWayChoosePop,也不再执行 100 元金额预警。
设备监听适配层
- 根据
DeviceTypeUtils选择现有伟邦、优卡特或其他扫码实现。 - 对弹框提供统一的刷卡、扫码成功和错误回调。
- 串口路径、波特率和协议继续由现有设备类维护,不在新弹框中重复硬编码。
7. 异常与资源释放
- 卡码任一路成功后必须先关闭另一路,再向页面回调。
- 会话状态使用一次性标记保护,迟到回调不得再次发起支付。
- 卡号为空、付款码为空或付款码格式不正确时不发起支付;允许用户继续在当前弹框中重新刷卡或扫码。
- 某一路硬件初始化失败时提示对应异常;另一路可用时继续等待。
- 用户取消、弹框销毁、页面退出时必须释放监听器和读线程。
- 人脸按钮点击后必须先释放卡码监听,避免人脸识别期间收到串口凭证。
8. 界面范围
- 新增主屏账单核对弹框布局,包含标题、菜品明细、合计金额、操作提示、取消按钮和人脸支付按钮。
- 不修改客屏布局,不在客屏展示账单明细或支付方式选择。
- 客屏原有扫码提示、人脸提示和支付结果行为不做功能扩展;如主屏新流程不再触发旧支付选择弹框,对应旧客屏选择界面也不主动显示。
9. 验收标准
- 购物车为空时无法打开账单核对弹框。
- 任意金额均不再触发 100 元限制弹框。
- 主屏账单菜品、数量、单价和总金额与购物车一致。
- 设备 4、5、7 打开弹框后可同时等待刷卡和扫码,先成功的一路只发起一次支付。
- 设备 1、2、3 保留现有扫码能力,不出现不支持的刷卡入口或监听。
- 卡码监听期间点击人脸按钮,会先关闭卡码监听,再打开现有人脸识别弹框。
- 人脸识别成功后正确携带用户 UUID 发起支付。
- 取消弹框、页面销毁和支付凭证命中后均无残留串口线程或重复回调。
- HTTP/MQTT、离线记账、成功失败提示和订单落库结果与改造前一致。
- 客屏不新增账单界面,现有支付结果展示不受影响。
10. 不在本次范围
- 不修改服务端接口或支付请求协议。
- 不修改客屏账单展示。
- 不为设备 1、2、3 新增刷卡硬件能力。
- 不重构菜单消费支付结果、离线订单上传或订单管理模块。
- 不提交、推送或创建 Git 分支。