DishRecognitionActivity 刷卡/扫码支付完整业务流

1. 目标

DishRecognitionActivity 内把刷卡、扫码支付能力收口到识别页本身,形成一套稳定的单页流程:

2. 状态拆分

建议把识别页支付相关状态拆成三层:

2.1 支付可用状态

2.2 支付输入监听状态

注意:

2.3 可支付阈值配置

说明:

2.4 支付流程状态

3. 页面初始化

进入 DishRecognitionActivity 后,除现有识别页初始化外,还需要增加:

  1. 初始化扫码能力
  1. 初始化刷卡能力
  1. 生命周期管理

初始化完成后的页面默认状态:

4. 支付状态从“不可支付”进入“可支付”

当识别结果满足“连续稳定达到当前配置阈值”的条件后:

  1. 页面支付状态切到“可支付”
  2. 立即暂停预览和菜品识别
  3. 预览区保留进入可支付状态时的最后一帧画面
  4. 同步开启支付输入监听
  5. 如果设置中开启了刷卡支付,且设备 NFC 可用,则允许刷卡结果生效
  6. 如果设置中开启了扫码支付,则启动扫码等待
  7. 当前识别结果、金额、加菜内容保持不变

说明:

5. 刷卡 / 扫码竞争规则

进入 WAITING_INPUT 状态后:

具体执行顺序:

  1. 收到刷卡结果或扫码结果
  2. 校验当前仍处于 WAITING_INPUT
  3. 立即停止刷卡监听
  4. 立即停止扫码监听
  5. 固定当前订单金额、菜品列表和支付介质数据
  6. 切到 PAYING
  7. PaymentManager.requestPayment()

这样可以避免:

6. 支付中展示规则

autoPayReady == true 开始,到支付结果返回前:

也就是说,用户看到的页面仍然是:

同时内部已经锁单,不再允许新输入、不再继续识别和新支付。

7. 支付结果展示规则

支付结果返回后:

7.1 成功

7.2 失败

7.3 弹框显示期间

以下状态都不允许变化:

对应状态:

8. 何时恢复到下一单

不是拿到支付结果就立刻恢复,而是:

复位动作:

  1. 关闭支付结果展示态
  2. 清掉本单支付上下文
  3. 清空识别结果
  4. 清空加菜
  5. 清空固定金额
  6. 清空稳定识别计数
  7. 清空上次识别快照
  8. 停止刷卡监听
  9. 停止扫码监听
  10. 恢复为:

9. 关键边界

9.1 订单内容变化

以下任一变化都要立刻取消“可支付”资格,并停止卡/码监听:

处理方式:

补充:

9.2 页面切后台

9.3 支付中防重入

当处于以下任一状态时,必须拦截新的支付:

9.4 人脸支付兼容

底部按钮仍可保留“人脸支付”入口:

10. 建议代码落点

10.1 DishRecognitionActivity

负责:

补充:

10.2 UsbHidScannerHelper

负责:

10.3 CustomNfcUtils

负责:

10.4 PaymentManager

负责:

11. 最终用户视角业务流

  1. 进入识别页
  2. 刷卡、扫码能力已初始化,但此时不可用
  3. 识别结果持续稳定,并达到支付设置页配置的阈值
  4. autoPayReady = true,页面进入“可支付”
  5. 立即暂停预览和菜品识别,锁住当前订单
  6. 界面保留进入可支付状态时的那一帧画面
  7. 开始等待刷卡或扫码
  8. 任一先出结果
  9. 立即停止刷卡和扫码
  10. 发起支付
  11. 支付中继续保持预览暂停、识别暂停,并保留最后一帧
  12. 显示支付成功 / 记账成功 / 支付失败弹框
  13. 弹框显示期间页面仍保持暂停
  14. 弹框消失
  15. 页面恢复为“可预览 / 不可支付”
  16. 等待下一次识别