Files
banban/docs/设备直接绑定接口联调文档.md

266 lines
6.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 设备直接绑定接口联调文档
## 1. 接口说明
该接口用于设备无法正常获取绑定验证码时,由白名单来源的业务页面发起直接绑定。
接口完成的业务效果与验证码绑定一致:
- 创建当前程序用户与设备的有效绑定关系;
- 将设备绑定状态更新为 `bound`;
- 作废该设备尚未使用的绑定验证码;
- 清理绑定验证码缓存;
- 写入绑定审计记录。
接口不会自动创建不存在的 ICCID。调用前,设备必须已经登记在后端 `sim_card` 表中,并且设备状态为 `active`。
## 2. 接口地址
```http
POST /api/v1/program/bindings/by-iccid
```
生产环境示例:
```text
https://<traffic-api-domain>/api/v1/program/bindings/by-iccid
```
将 `<traffic-api-domain>` 替换为实际 4G 管理后端域名。
## 3. 调用前提
### 3.1 程序用户登录
调用方必须先通过程序用户登录接口获取 `PROGRAM_USER` 的 `accessToken`:
```http
POST /api/v1/program/auth/login
```
后续请求携带:
```http
Authorization: Bearer <accessToken>
```
不能使用 `SUPER_ADMIN`、`FACTORY_PROVISIONER` 或设备 Token 调用此接口。
### 3.2 来源白名单
当前默认允许以下 Origin:
```text
https://banban.api.talkingq.com
http://192.168.101.151
```
请求必须携带与页面实际来源完全一致的 `Origin` 请求头:
```http
Origin: https://banban.api.talkingq.com
```
或:
```http
Origin: http://192.168.101.151
```
白名单由环境变量配置:
```bash
BINDING_ALLOWED_ORIGINS=https://banban.api.talkingq.com,http://192.168.101.151
```
多个来源使用英文逗号分隔。来源匹配包含协议、主机和端口,不能只填写裸域名或裸 IP。
例如,下面这些值不是同一个 Origin:
```text
http://192.168.101.151
https://192.168.101.151
http://192.168.101.151:8080
```
如果页面实际通过 HTTPS 或非默认端口访问,需要把实际 Origin 加入 `BINDING_ALLOWED_ORIGINS` 后重启后端。
## 4. 请求格式
### 4.1 请求头
```http
Origin: https://banban.api.talkingq.com
Authorization: Bearer <PROGRAM_USER_ACCESS_TOKEN>
Content-Type: application/json
X-Request-Id: direct-bind-20260920-0001
```
`Origin` 是来源白名单校验字段;`Authorization` 是业务身份认证字段;`X-Request-Id` 用于日志追踪,建议每次请求使用唯一值。
### 4.2 请求体
```json
{
"iccid": "898604E91123D1334901",
"requestId": "direct-bind-20260920-0001"
}
```
字段说明:
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `iccid` | string | 是 | 设备 ICCID,18 至 22 位字母或数字,后端会统一转为大写 |
| `requestId` | string | 是 | 幂等请求号,最长 64 个字符;同一用户重试必须使用相同值 |
## 5. curl 联调示例
请将 Token 和 ICCID 替换为真实值,不要把 Token 提交到代码仓库或群聊。
```bash
curl -i -X POST \
"https://<traffic-api-domain>/api/v1/program/bindings/by-iccid" \
-H "Origin: https://banban.api.talkingq.com" \
-H "Authorization: Bearer <PROGRAM_USER_ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-H "X-Request-Id: direct-bind-20260920-0001" \
--data '{
"iccid": "898604E91123D1334901",
"requestId": "direct-bind-20260920-0001"
}'
```
使用 IP 来源联调时,将 `Origin` 改为:
```http
Origin: http://192.168.101.151
```
## 6. 成功响应
```json
{
"code": "OK",
"message": "success",
"data": {
"iccid": "898604E91123D1334901",
"bindingStatus": "active",
"idempotent": false,
"boundAt": "2026-09-20T15:30:00"
},
"requestId": "http-request-id",
"timestamp": "2026-09-20T07:30:00Z"
}
```
字段说明:
| 字段 | 说明 |
| --- | --- |
| `data.iccid` | 实际完成绑定的 ICCID |
| `data.bindingStatus` | 成功时为 `active`,表示用户绑定关系有效 |
| `data.idempotent` | `false` 表示本次新建绑定,`true` 表示重复请求已返回原绑定结果 |
| `data.boundAt` | 绑定时间 |
## 7. 幂等重试规则
请求超时或网络断开时,使用同一个 `requestId` 重试,不要生成新的请求号:
```json
{
"iccid": "898604E91123D1334901",
"requestId": "direct-bind-20260920-0001"
}
```
同一程序用户、同一 ICCID、同一 `requestId` 重试时,接口返回 `idempotent=true`。
同一 `requestId` 改用其他 ICCID 时,接口返回 `IDEMPOTENCY_CONFLICT`。
## 8. 常见失败响应
### 8.1 来源不在白名单
```http
HTTP/1.1 403 Forbidden
```
可能原因:
- 未携带 `Origin`;
- Origin 协议不一致,例如配置了 HTTPS 但请求使用 HTTP;
- IP 使用了非默认端口;
- 后端环境变量未更新或服务未重启。
### 8.2 未登录或 Token 无效
```json
{
"code": "UNAUTHORIZED"
}
```
请确认使用的是程序用户登录返回的 `accessToken`,并且 Token 尚未过期或撤销。
### 8.3 设备不存在
```json
{
"code": "DEVICE_NOT_FOUND"
}
```
表示 ICCID 尚未登记到后端。该接口不会自动创建设备档案,应先通过设备接入或预置流程登记设备。
### 8.4 设备已被其他用户绑定
```json
{
"code": "DEVICE_ALREADY_BOUND"
}
```
不能通过该接口覆盖其他用户的绑定关系,需要先由当前绑定用户解绑或由管理员执行解绑流程。
### 8.5 设备已禁用
```json
{
"code": "DEVICE_DISABLED"
}
```
需要先恢复设备状态为 `active`。
### 8.6 参数错误
```json
{
"code": "INVALID_REQUEST"
}
```
请检查 `iccid` 是否为 18 至 22 位字母数字,以及 `requestId` 是否为空或超过 64 个字符。
## 9. 浏览器联调注意事项
- 前端请求必须使用 `Authorization` 请求头携带 Token,不能只依赖 Cookie;
- 页面来源必须与白名单完全一致;
- 浏览器会先发送 CORS 预检请求,后端已经允许 `POST`、`OPTIONS` 以及 `Authorization`、`Content-Type`、`X-Request-Id` 请求头;
- 如果通过后端服务调用,HTTP 客户端通常不会自动添加 `Origin`,需要按接口要求主动设置;
- `Origin` 不是加密签名,不能替代登录 Token;
- 联调日志中可以使用响应里的 `requestId` 联系后端排查。
## 10. 验收检查
建议至少验证以下场景:
1. 使用 `https://banban.api.talkingq.com` 来源和有效程序用户 Token,绑定一个未绑定的 active ICCID,返回 `idempotent=false`。
2. 使用相同用户、相同 ICCID、相同 `requestId` 再次调用,返回 `idempotent=true`。
3. 使用其他 Origin 调用,返回 HTTP 403。
4. 不携带 `Authorization`,返回 `UNAUTHORIZED`。
5. 使用已绑定到其他用户的 ICCID,返回 `DEVICE_ALREADY_BOUND`。
6. 使用不存在的 ICCID,返回 `DEVICE_NOT_FOUND`。
7. 确认数据库中 `sim_card.binding_status` 为 `bound`,并且 `user_device_binding.status` 为 `active`。