结论:消费首次完整读卡后已强制按读卡账号查询一卡通单人信息,并以服务端卡号、卡序号、卡状态和姓名作为后续消费权威数据;仅状态 1 可继续,状态 3、4 及其他状态均在扣款前拦截。查询失败提示“同步人员卡信息失败”,确认可对仍在位的原卡重新请求。
UC-CONSUMPTION-CARD-VERIFY-001 / Implemented / READYCustomerID 调用 GetInfoByCustID → 校验返回账号及关键字段 → 更新卡号、卡序号、状态和姓名 → 状态为 1 时继续零元核验或扣款 → 消费后复读继承已验证人员身份。3 为挂失、4 为冻结、其他为异常,均不可消费;网络、SOAP Fault、返回失败、查无人员、账号不一致或关键字段异常统一按同步失败处理,不发送扣款指令。确认弹框可安全重试,取消后保留订单并等待移卡换卡。ServerCustomerInfo、ServerCustomerInfoParser 和 OnecardCardInfoVerifier,集中完成单人字段解析、SOAP 成功校验、账号一致性校验和错误归类。OnecardWebServiceClient 新增无状态单人查询入口,直接调用 GetInfoByCustID,不会为单次消费额外探测 GetCustomerCount。CardInfo 增加 holderName 及 readerCardNumber/readerCardSerialNumber/readerStatus;业务字段使用服务端结果,读卡器原始字段只用于诊断。消费后快照保留第二次读卡余额和计数,同时继承首次已验证人员身份。ConsumptionCardTransactionExecutor 把服务端查询放在首次读卡和零元/扣款分支之间;查询失败、挂失、冻结和未知状态均不调用消费。ConsumptionCardSearchManager 保存当前在位卡的定位结果,提供受交易门禁保护的显式重试入口;确认或移卡要求跨页面停启保留,防止原卡在恢复前台时被自动重试。ConsumptionActivity 使用服务端姓名展示持卡人;同步失败落库、记录结构化日志并展示确认弹框,确认重试,取消后等待移卡。reader* 原始诊断字段;现有 SQLite before_result_json/after_result_json 通过扩展后的 CardInfo 自动记录增项,无需数据库迁移。GetInfoByCustIDResult 复杂对象直接子字段读取,响应对象外同名字段不能混入,重复结果字段会被拒绝;全量人员接口的重复复杂记录结构保持兼容。1/3/4/其他、查询失败禁止扣款、零元订单门禁、消费后身份继承、重试门禁、结构化日志及 SQLite JSON 快照。JAVA_HOME=$(/usr/libexec/java_home -v 1.8) bash gradlew :app:testDebugUnitTest --rerun-tasks,共 235 项,232 项通过、3 项失败。3 项失败均位于既有 CustomerFullFetchServiceTest:测试断言仍按每页 1000 人,而当前未修改的 CustomerFullFetchService.SOURCE_PAGE_SIZE 已为 2000;与本次消费前单人查询链路无关,本次未扩大范围修改。
JAVA_HOME=$(/usr/libexec/java_home -v 1.8) bash gradlew :app:assembleDebug,构建成功。app/build/outputs/apk/debug/app-debug.apk,大小 66832146 字节,SHA-256 5830468d6cfe9423d76813cca85cc52386028486f4a14b15e2292cd090672f25。本次未执行暂存、提交、推送、拉取、分支切换、合并、变基、重置或清理。当前分支为 order_upload_to_onecard,工作区原有修改和未跟踪文件均保留。