批量换货脚本
该脚本读取两列 CSV,逐行调用 POST /api/admin/exchanges 执行换货。脚本固定使用:
flow_type=direct:只支持直接换货,接口创建换货单后会立即完成换货。migrate_data=true:必须执行全量数据迁移,不能通过参数关闭。
全量迁移由现有换货接口在同一事务中执行,包括钱包余额、套餐使用记录、累计充值字段和资产标签。脚本仅使用 Python 标准库,不需要安装依赖。
默认只预演,必须增加 --execute 才会真实换货。
CSV 格式
首行表头可选,第一列填写旧资产标识,第二列填写新资产标识:
old_identifier,new_identifier
89860000000000000001,89860000000000000101
89860000000000000002,89860000000000000102
支持表头:
- 英文:
old_identifier,new_identifier或old_asset_identifier,new_asset_identifier - 中文:
旧资产标识,新资产标识或旧资产,新资产
旧、新资产标识均使用换货接口已有的识别规则:物联网卡支持 ICCID、接入号、虚拟号;设备支持虚拟号、IMEI、SN。
脚本会在请求前拦截:
- 列数不是两列,或任一列为空。
- 同一行新旧资产相同。
- 旧资产重复,或新资产重复。
- 同一资产在本批次中既作为旧资产又作为新资产。该情况会受到执行顺序影响,因此整批终止。
预演
物联网卡示例:
python3 scripts/batch_exchange/batch_exchange.py \
--base-url https://cmp-api.example.com \
--csv scripts/batch_exchange/exchanges.example.csv \
--asset-type iot_card
设备批次将 --asset-type 改为 device。同一个 CSV 批次只能使用一种资产类型;新资产必须与旧资产类型一致,否则接口会拒绝该行。
预演只校验 CSV 并展示最多五条请求示例,不需要 Token,也不会调用接口。输出中会明确显示 direct 和 migrate_data=true。
使用已有 Token 执行
推荐通过环境变量传递 Token,避免进入命令历史:
JUNHONG_ADMIN_TOKEN='<后台Access Token>' \
python3 scripts/batch_exchange/batch_exchange.py \
--base-url https://cmp-api.example.com \
--csv /path/to/exchanges.csv \
--asset-type iot_card \
--execute
使用账号自动登录后执行
未提供 Token 时,可以使用后台账号调用 /api/admin/login 自动获取 Token:
JUNHONG_ADMIN_USERNAME='<后台账号>' \
JUNHONG_ADMIN_PASSWORD='<后台密码>' \
python3 scripts/batch_exchange/batch_exchange.py \
--base-url https://cmp-api.example.com \
--csv /path/to/exchanges.csv \
--asset-type iot_card \
--execute
也可以使用 --token、--username、--password 参数。密码优先通过环境变量或交互输入,避免保存在 Shell 历史中。
换货原因和备注
脚本默认使用 批量直接换货 作为换货原因。可按整批覆盖原因和备注:
python3 scripts/batch_exchange/batch_exchange.py \
--base-url https://cmp-api.example.com \
--csv /path/to/exchanges.csv \
--asset-type iot_card \
--exchange-reason '故障卡批量换货' \
--remark '2026年7月批次' \
--execute
结果文件
默认在输入 CSV 同目录生成:
原文件名_换货结果_YYYYMMDD_HHMMSS.csv
结果包含新旧资产标识、成功或失败状态、HTTP 状态码、业务错误码、错误消息、换货单 ID、换货单号、迁移完成状态和迁移余额。每处理一条都会立即刷新文件,中途中断时已完成的结果不会丢失。
为避免覆盖历史结果,--output 指定的文件已经存在时脚本会直接报错。
其他参数和执行约束
--timeout:单次请求超时秒数,默认30。--interval:每次换货后的等待秒数,默认0.2。--execute:显式开启真实换货。
每组资产单独调用一次接口,脚本不会自动重试 POST 请求。接口可能已经成功提交事务但客户端没有收到响应,自动重试可能造成误判;失败项应先查询换货单或资产状态,再决定是否单独重跑。
脚本不会回滚前面已经成功的行。执行前应先预演并确认完整映射;执行后根据结果 CSV 逐条核对失败项。