EIOTCLUB Claude Analysis Material
这份文档是给 Claude 做进一步分析用的精简材料,只保留本轮明确需要的三部分:
- 签名算法(Signature Algorithm)
- Webhook 回调配置页对应的关键结构
- 单卡信息查询接口的完整参数和响应示例
来源主要整理自:
docs/integrations/eiotclub-apifox-export.mdopenapi/eiotclub-apifox-openapi.json
1. 签名算法
来源页:API接口 -> 签名(sign)算法
- 文档索引链接:
https://s.apifox.cn/166a9792-0aaf-4d87-a524-2279ef4788bd/2084440m0.md - 生产 base URL:
https://oapi.eiotclub.com
系统级参数
所有 API 请求都带这些系统参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
appkey | string | 是 | 应用身份标识 |
timestamp | long | 是 | 10 位时间戳 |
nonce | integer | 是 | 5 位随机正整数 |
sign | string | 是 | 签名结果 |
API 请求签名规则
- 将所有非空请求参数按参数名 ASCII 升序排列。
- 拼接成
key=value&key=value...的字符串,记为StringParm。 - 在字符串末尾拼接
secret,形成StringParmSign。 - 对
StringParmSign做sha1运算。 - 将结果转为大写,得到最终
sign。
关键注意事项
secret不参与排序。secret不直接作为请求字段传给 API,只用于签名。- API 调用签名需要包含
appkey。 - 回调通知签名计算不需要加入
appkey,这一点非常关键。
文档中的签名示例
假设系统参数和业务参数如下:
| 系统级参数 | 值 | 业务级参数 | 值 |
|---|---|---|---|
appkey | 000001 | userName | wx |
timestamp | 1556595508 | age | 24 |
nonce | 24523 | sex | 1 |
按 ASCII 升序拼接后:
age=24&appkey=000001&nonce=24523&sex=1×tamp=1556595508&userName=wx
假设 secret = a1b1c1d1,则参与签名的字符串为:
age=24&appkey=000001&nonce=24523&sex=1×tamp=1556595508&userName=wx&secret=a1b1c1d1
sha1 并转大写后示例结果:
963A56BAEBED746F2746E4D9B3B77BE0F2E171E7
请求示例
POST https://oapi.eiotclub.com/api/v3/xxx/xxx
Content-Type: application/json;charset=utf-8
{
"appkey": "000001",
"timestamp": 1556595508,
"nonce": 24523,
"sign": "963A56BAEBED746F2746E4D9B3B77BE0F2E171E7",
"userName": "wx",
"age": "24",
"sex": "1"
}
2. Webhook 回调配置相关内容
这里对应 EIOTCLUB Apifox 中的异步通知页面。当前这轮优先整理一个最典型、信息最完整的 webhook:订购通知-详细版。
来源页:API接口 -> 异步通知 -> 订购通知-详细版
- 文档索引链接:
https://s.apifox.cn/166a9792-0aaf-4d87-a524-2279ef4788bd/124594751e0.md - 路径:
POST /customerNotifyUrl - 含义:客户提供接收异步通知的地址(HTTP/HTTPS)
Webhook 请求体字段
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
timestamp | integer | 是 | 10 位时间戳 |
nonce | integer | 是 | 5 位随机正整数 |
sign | string | 是 | 通知签名 |
id | string | 是 | 请求唯一标识 |
event | string | 是 | 通知类型,例如 SubPkgList |
data | array<object> | 是 | 订购套餐数据 |
data[] 内字段
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
iccid | string | 是 | ICCID |
orderId | number | 是 | 套餐订单号 |
packageName | string | 是 | 套餐名称 |
packageCode | string | 是 | 套餐编码 |
state | integer | 是 | 套餐状态:0 待使用,1 使用中,2 已完成 |
gzhPackageName | string | 是 | 商品套餐名称 |
packageType | integer | 是 | 套餐类型:2 限量流量包,3 限时流量包,4 限时限速包 |
createDate | string | 是 | 订购时间 |
outTradeNo | string | 否 | API 调用方传入的唯一订单号标识,最大 32 位 |
fromIccid | string | 否 | 转移套餐来源卡号 |
fromOrderId | integer | 否 | 转移套餐来源订单号 |
salesChannel | string | 是 | 销售渠道,如 USER、SYSTEM、TRANSFER、PLATFORM、API |
customData | string | 否 | 客户白名单登录用户唯一标识,最大 125 位 |
Webhook 请求示例
{
"data": [
{
"iccid": "89423053323291099364",
"orderId": 10004728,
"packageName": "A-TM-50M-1天",
"packageCode": "A-TM-50M-1D-A-CN-TEST-2024052489FC722C",
"state": 0,
"gzhPackageName": "",
"createDate": "2024-05-28 09:34:47",
"packageType": 3,
"outTradeNo": "6300001983111426769635"
}
],
"event": "SubPkgList",
"id": "ue5Y0qNC8QQIRtUR3UgV4xzg",
"nonce": 40604,
"sign": "F0D19FA6945B21C0D61BDEFD4DCC41B64B29272B",
"timestamp": 1716860340
}
Webhook 成功响应
{
"status": "SUCCESS"
}
给 Claude 的注意点
- EIOTCLUB webhook 验签规则和 API 请求签名不同:回调不带
appkey参与签名。 id可以优先作为事件幂等键。event是本地路由事件处理器的重要分发字段。- 这个页面只代表一个典型 webhook,其他通知页(套餐生效、退款通知、达量到期、锁卡/解锁等)结构类似,但
data字段内容会不同。
3. 单卡信息查询接口
来源页:API接口 -> 卡业务接口 -> 单卡信息查询
- 文档索引链接:
https://s.apifox.cn/166a9792-0aaf-4d87-a524-2279ef4788bd/63600559e0.md - OpenAPI 路径:
POST /api/v3/card/getCardsInfo - 作用:根据卡号,获取单卡信息及流量使用信息。
完整请求参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
appkey | string | 是 | 应用身份标识 |
timestamp | integer | 是 | 当前时间戳,10 位 |
nonce | integer | 是 | 5 位随机正整数 |
sign | string | 是 | 请求签名 |
iccid | string | 是 | 卡片 ICCID |
请求示例
{
"appkey": "{{APPKEY}}",
"timestamp": "{{TIMESTAMP}}",
"nonce": 67958,
"sign": "{{SIGN}}",
"iccid": "89000123456789013802"
}
响应顶层结构
| 字段 | 类型 | 说明 |
|---|---|---|
code | string | 200 表示成功,其他表示失败 |
message | string | 成功或失败原因 |
data | object | 单卡详情 |
data 字段完整列表
| 字段 | 类型 | 说明 |
|---|---|---|
iccid | string | ICCID 卡号 |
imsi | string | IMSI 号 |
activateDate | string | 卡片激活时间 |
cardStatus | string | 卡状态,如 ACTIVATION_READY_NAME、NON_ACTIVATED_NAME、ACTIVATED_NAME、DEACTIVATED_NAME |
isRealName | integer | 是否实名:0 未实名,1 已实名 |
monthRemainFlow | number | 当前套餐剩余流量,单位 MB |
monthUseFlow | number | 当前套餐已用流量,单位 MB |
remainFlowType | number | 剩余流量类型:0 套餐流量,1 池剩余流量 |
productCode | string | 产品编码 |
packageEndDate | string | 当前套餐到期时间 |
dataFlow | number | 卡片总流量(包括未使用套餐),单位 MB |
remainFlow | number | 卡片总剩余流量(包括未使用套餐),单位 MB |
expectedEndDate | string | 卡片预计到期时间 |
imeiPoolStatus | integer | IMEI 池锁状态:0 未锁,1 锁住暂停卡 |
imeiPoolUnlockCount | integer | IMEI 池已解锁次数 |
isIMEIPool | integer | 是否归属池:0 不归属,1 归属池,2 临时归属池 |
network | string | 当前网络 |
totalUseFlow | number | 卡片已使用总流量,文档注明“暂时不精准” |
packageCode | string | 当前使用系统套餐简码 |
packageKind | integer | 套餐类型:0 限量套餐,1 限时套餐,2 限时限速套餐 |
eid | string | eSIM 卡号 |
remark | string | 当前客户备注 |
整理后的响应示例
下面这个示例不是 EIOTCLUB 页面原样 mock,而是根据 OpenAPI 字段整理成更适合 Claude 理解的实际结构示例:
{
"code": "200",
"message": "Success",
"data": {
"iccid": "89000123456789013802",
"eid": "89049032000000000000012345678901",
"imsi": "460011234567890",
"activateDate": "2025-02-25 10:12:00",
"cardStatus": "ACTIVATED_NAME",
"isRealName": 1,
"monthRemainFlow": 73.0,
"monthUseFlow": 27.0,
"remainFlowType": 0,
"productCode": "PROD_CN_4G_001",
"packageEndDate": "2025-06-04 23:59:59",
"dataFlow": 1024.0,
"remainFlow": 512.0,
"expectedEndDate": "2025-08-04 23:59:59",
"imeiPoolStatus": 0,
"imeiPoolUnlockCount": 0,
"isIMEIPool": 0,
"network": "CMCC",
"totalUseFlow": 2048.0,
"packageCode": "PKG-1GB-30D",
"packageKind": 0,
"remark": "AOVIS test device"
}
}
给 Claude 的注意点
- 这是单卡查询接口,不是分页列表接口。
- 入参核心业务字段只有
iccid,其余四个是系统签名参数。 totalUseFlow在文档里被注明“暂时不精准”,不要把它当绝对可信口径。- 流量类字段存在“当前套餐口径”和“卡片总口径”两套,需要在本地模型里区分:
- 当前套餐:
monthRemainFlow、monthUseFlow - 卡片累计/总量:
dataFlow、remainFlow、totalUseFlow
- 当前套餐:
4. 可直接发给 Claude 的提示词
请基于这份 EIOTCLUB 分析材料,重点分析三件事:
1. 如何正确实现 API 请求签名与 webhook 验签,并避免把 appkey 错误加入 webhook 签名。
2. 如何为 /api/v3/card/getCardsInfo 设计一个稳定的服务层封装、返回字段映射和错误处理。
3. 如何为 EIOTCLUB webhook(尤其是订购通知-详细版)设计幂等处理、事件类型分发和本地订单/卡状态同步策略。
要求:
- 输出推荐的 TypeScript 服务层结构。
- 给出 sign 生成函数和 webhook sign 验签函数的伪代码或正式代码。
- 说明单卡查询接口的本地 DTO / schema 应该如何定义。
- 说明 webhook payload 的关键字段如何映射到本地事件模型。