3.4 KiB
Why
当前系统存在两个关联缺陷,且缺陷 A 的影响远不止套餐激活本身:
缺陷 A:代理商先给设备/卡实名,再购买 expiry_base=from_activation 的套餐,系统未检查当前实名状态,无条件将套餐标记为 pending_realname_activation=true(待生效,status=0)。这不仅导致套餐永久无法激活,还连带阻断了购买后的自动复机链路:tryResumeAfterPayment 在检查到 activatedCount=0 时直接跳过,即使卡此前因无套餐而停机,购买成功后也不会自动开机。
缺陷 B:卡首次实名(0→1)时,实名轮询处理器只触发卡级套餐激活,不处理该卡所属设备的设备级套餐,导致设备级套餐在"购买后某张卡实名"场景下永不激活,同样无法触发设备下绑定卡的复机。
修复后的规则:from_activation 套餐在购买时检查实名状态,已实名则直接激活(同时保障复机链路正常触发);卡首次实名时同时触发其所属设备的设备级套餐激活与复机。
What Changes
- 购买时实名状态检查:在
activateMainPackage中,当判断expiry_base != "from_purchase"时,额外检查载体当前实名状态:iot_card:查询该卡的real_name_statusdevice:通过tb_device_sim_binding查询是否存在任意已实名的绑定卡- 已实名 → 直接激活(
status=Active),tryResumeAfterPayment检查到activatedCount>0后正常触发复机链路 - 未实名 → 保持原有逻辑等待实名触发
- 实名轮询触发设备级激活与复机:在
PollingRealnameHandler的卡首次实名(0→1)路径中,额外查询该卡所属设备,若设备存在则同时提交carrier_type=device的TaskTypePackageFirstActivation任务;任务执行后ActivateByRealname内部会调用ResumeCardIfStopped("device", deviceID)触发设备下符合条件卡的复机 NewPollingRealnameHandler构造函数新增*postgres.DeviceSimBindingStore参数
复机行为说明:自动复机仅针对由轮询系统引起的停机(stop_reason 为 no_package、traffic_exhausted、not_realname),手动停机(manual)不受影响,设备下每张卡独立判断实名状态后再决定是否复机。
Capabilities
New Capabilities
无新能力,均为现有逻辑的修正。
Modified Capabilities
package-realname-activation:补充"购买时载体已实名则直接激活"的决策分支,以及"设备下卡实名时触发设备级套餐激活"的联动规则polling-task-handlers:PollingRealnameHandler新增DeviceSimBindingStore依赖,新增triggerDeviceRealnameActivation函数
Impact
涉及文件:
internal/service/order/service.go(activateMainPackage函数,~1782-1807 行)internal/task/polling_realname_handler.go(结构体、构造函数、新增函数)pkg/queue/handler.go(registerPollingHandlers中的构造调用)
数据库:无 schema 变更,无迁移
API:无接口变更,对外透明
当前问题设备的直接影响:设备 862639076038233 的套餐(tb_package_usage.id=1)需要手动修复(修改 pending_realname_activation=false、激活套餐),代码修复仅防止新订单再次陷入同样问题。手动修复套餐后,还需手动触发设备复机(或等待轮询系统下次评估),因为历史停机事件不会被追溯重放。