v1.0

📚 API Wiki 开发注意事项

接入 TIB IoT API 前必读的开发指南和认证说明

1. 域名配置

  • 接口请求基础地址:https://oac.tibiot.com/
  • 注意:生成签名时不需要拼接 BaseURL,仅使用请求路径(URI)参与签名计算。

2. 应用凭证与 SDK 获取

2.1 创建应用

访问:https://dmc.tibiot.com/ApplicationCenter

  • 点击「添加应用」,创建成功后系统将分配:
    • APP ID:企业编码,用于标识调用方身份
    • APP Secret:加密密钥,请妥善保管,切勿泄露

2.2 SDK 下载

在应用管理平台中可直接下载对应语言的 SDK,推荐使用 SDK 进行接口调用,以简化签名生成与请求处理。

3. 签名生成规则

所有 API 请求(包括 GET 与 POST)必须携带签名,签名通过 ApiSignUtils.generateClientSign 方法生成。

3.1 签名参数说明

参数名 类型 说明
appId String 应用中心分配的应用 ID
secret String 应用中心分配的 Secret
uri String 请求路径(不包含 BaseURL),如 /api/v1/order
bodyParams Map POST 请求体参数(GET 请求传空 Map)
timestamp long 当前毫秒级时间戳,用于防重放攻击
nonce String 随机字符串,建议使用 UUID,每次请求不同

3.2 签名生成步骤

  1. 若 URI 包含查询参数,按参数名 ASCII 升序排序后拼接为 key1=value1&key2=value2 格式,并对 value 进行 URL 编码(空格编码为 %20)。
  2. POST 请求体参数(JSON 或 Form)同样按 key 升序排序,拼接为 key1=value1&key2=value2 格式,并对 value 进行 URL 编码。
  3. 将以下字段按顺序用竖线 | 连接:
    • 若某个字段为空,则跳过该字段及其前后分隔符(即不出现连续的 ||)。
  4. 使用 3DES(DESede) 算法对上一步生成的字符串进行加密,密钥为 secret(不足24位补足,超过24位截取前24位)。
  5. 加密后得到 Base64 字符串,即为最终签名。

3.3 签名示例代码(Java)

DES3Util.java Java
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class DES3Util {
    private DES3Util() {}

    public static String encrypt(String content, String desKey, String charset) throws Exception {
        if (desKey == null || desKey.length() < 24) {
            throw new Exception("3des key's length must be 24");
        }
        if (desKey.length() > 24) {
            desKey = desKey.substring(0, 24);
        }
        if (content == null || content.isEmpty()) {
            return "";
        }
        SecretKeySpec key = new SecretKeySpec(desKey.getBytes(charset), "DESede");
        Cipher cipher = Cipher.getInstance("DESede");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] encryptBytes = cipher.doFinal(content.getBytes(charset));
        return Base64.getEncoder().encodeToString(encryptBytes);
    }
}
ApiSignUtils.java Java
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

public class ApiSignUtils {
    public static String generateClientSign(String appId, String secret, String uri,
                                            Map<String, Object> bodyParams, long timestamp, String nonce) throws Exception {
        String[] path = uri.split("\\?", 2);
        String queryParamsStr = parseQueryParams(path);
        String postParamsStr = parsePostParams(bodyParams);
        List<String> joinParams = Arrays.asList(appId, secret, path[0], String.valueOf(timestamp), nonce, queryParamsStr, postParamsStr);
        joinParams = joinParams.stream().filter(s -> s != null && !s.isEmpty()).collect(Collectors.toList());
        String signData = String.join("|", joinParams);
        return DES3Util.encrypt(signData, secret, StandardCharsets.UTF_8.name());
    }

    private static String parsePostParams(Map<String, Object> bodyParams) {
        if (bodyParams == null || bodyParams.isEmpty()) {
            return "";
        }
        Map<String, Object> params = new TreeMap<>(bodyParams);
        return params.entrySet().stream()
                .filter(entry -> entry.getValue() != null)
                .map(entry -> entry.getKey() + "=" + urlEncode(String.valueOf(entry.getValue())))
                .collect(Collectors.joining("&"));
    }

    private static String parseQueryParams(String[] query) {
        if (query == null || query.length <= 1) {
            return "";
        }
        Map<String, String> params = new TreeMap<>();
        String pathParams = query[1];
        Arrays.stream(pathParams.split("&"))
                .map(pair -> pair.split("="))
                .forEach(pair -> params.put(pair[0], urlEncode(pair.length > 1 ? pair[1] : "")));
        return params.entrySet().stream()
                .map(entry -> entry.getKey() + "=" + entry.getValue())
                .collect(Collectors.joining("&"));
    }

    private static String urlEncode(String val) {
        return URLEncoder.encode(val, StandardCharsets.UTF_8).replace("+", "%20");
    }
}

📱 卡接口

物联网卡管理相关接口,包括卡详情查询、网络操作、使用量统计等功能

卡详情

GET /agw/api/v1/card/detail

查询单张物联网卡的详细信息,包括 ICCID、IMEI、IMSI、流量使用情况、卡状态等

Request Headers
参数名 类型 必填 说明
X-App-Id string ● 是 应用ID
X-Sign string ● 是 请求签名
X-Timestamp long ● 是 时间戳(毫秒)
X-Nonce string ● 是 随机字符串
Query Parameters
参数名 类型 必填 说明
iccid string ● 是 物联网卡 ICCID 号码
Response Body
参数名 类型 说明
code number 响应状态码,200 表示成功
message string 响应消息
traceId string 请求追踪ID
data.iccid string 物联网卡 ICCID 号码
data.imei string 设备 IMEI 号
data.imsi string SIM 卡 IMSI 号
data.msisdn string 卡号
data.totalFlow number 总流量(字节)
data.useMonthFlow number 本月已用流量(字节)
data.useFlow number 累计已用流量(字节)
data.billingMethod number 计费方式
data.apn string 接入点名称
data.cardStatus number 卡状态:1-沉默期,4-停机,8-正常,12-测试期,16-停机保号,18-清算,99-异常
Response Example JSON
{
  "code": 200,
  "message": "success",
  "traceId": "abc123def456",
  "data": {
    "iccid": "89860000000000000000",
    "imei": "860000000000000",
    "imsi": "460000000000000",
    "msisdn": "13800138000",
    "totalFlow": 1073741824,
    "useMonthFlow": 104857600,
    "useFlow": 524288000,
    "billingMethod": 1,
    "apn": "cmiot",
    "cardStatus": 8
  }
}

操作卡网络

POST /agw/api/v1/card/operation/network

批量操作物联网卡网络状态,支持开通或关闭网络,最多支持 10 张卡同时操作

Request Headers
参数名 类型 必填 说明
X-App-Id string ● 是 应用ID
X-Sign string ● 是 请求签名
X-Timestamp long ● 是 时间戳(毫秒)
X-Nonce string ● 是 随机字符串
Content-Type string ● 是 application/json
Request Body
参数名 类型 必填 说明
iccids string[] ● 是 ICCID 数组,最多 10 个
switchOn boolean ● 是 true 开通,false 关闭
Response Body
参数名 类型 说明
code number 响应状态码,200 表示成功
message string 响应消息
traceId string 链路追踪 ID
data.batchCode string 批次编码,用于查询操作状态
data.successCount number 切换检查成功数量
data.errorInfo array 切换检查失败详细列表
data.errorInfo[].iccid string ICCID
data.errorInfo[].infoMessage string 详细信息
Request Example JSON
{
  "iccids": [
    "89860000000000000001",
    "89860000000000000002"
  ],
  "switchOn": true
}
Response Example JSON
{
  "code": 200,
  "message": "success",
  "traceId": "abc123def456",
  "data": {
    "batchCode": "BATCH202504220001",
    "successCount": 2,
    "errorInfo": []
  }
}

获取卡历史12月的某一月的使用量

GET /agw/api/v1/card/getCardMonthUsage

查询物联网卡在指定月份的使用量统计

Request Headers
参数名 类型 必填 说明
X-App-Id string ● 是 应用ID
X-Sign string ● 是 请求签名
X-Timestamp long ● 是 时间戳(毫秒)
X-Nonce string ● 是 随机字符串
Query Parameters
参数名 类型 必填 说明
iccid string ● 是 ICCID 号码
queryMonth string ● 是 查询月份,格式:2025-04
Response Body
参数名 类型 说明
code number 响应状态码
message string 响应消息
traceId string 链路追踪 ID
data.iccid string ICCID 号码
data.month string 日期,格式:yyyy-MM
data.useFlowKb number 使用量,单位 KB
Response Example JSON
{
  "code": 200,
  "message": "success",
  "traceId": "abc123def456",
  "data": {
    "iccid": "89860000000000000001",
    "month": "2025-04",
    "useFlowKb": 102400
  }
}

获取卡近30天的某一天的使用量

GET /agw/api/v1/card/getCardDayUsage

查询物联网卡在指定日期的使用量统计

Request Headers
参数名 类型 必填 说明
X-App-Id string ● 是 应用ID
X-Sign string ● 是 请求签名
X-Timestamp long ● 是 时间戳(毫秒)
X-Nonce string ● 是 随机字符串
Query Parameters
参数名 类型 必填 说明
iccid string ● 是 ICCID 号码
queryDay string ● 是 查询日期,格式:2025-04-01
Response Body
参数名 类型 说明
code number 响应状态码
message string 响应消息
traceId string 请求追踪ID
data.iccid string ICCID 号码
data.day string 日期,格式 yyyy-MM-dd
data.useFlowKb number 使用量,单位 KB
Response Example
{
  "code": 200,
  "message": "success",
  "traceId": "abc123def456",
  "data": {
    "iccid": "89860000000000000001",
    "day": "2025-04-01",
    "useFlowKb": 5120
  }
}

🔄 操作批次查询

查询批量操作的执行状态和结果

检查卡操作完成状态

GET /agw/api/v1/operation/batch/query/status

根据批次编码查询批量操作的执行状态

Request Headers
参数名 类型 必填 说明
X-App-Id string ● 是 应用ID
X-Sign string ● 是 请求签名
X-Timestamp long ● 是 时间戳(毫秒)
X-Nonce string ● 是 随机字符串
Query Parameters
参数名 类型 必填 说明
batchCode string ● 是 批次编码
Response Body
参数名 类型 说明
code number 响应状态码
message string 消息提示
traceId string 链路编码
data[].iccid string ICCID 号码
data[].msisdn string 卡号
data[].operationCardStatus number 操作卡状态:2-操作完成
Response Example JSON
{
  "code": 200,
  "message": "success",
  "traceId": "abc123def456",
  "data": [
    {
      "iccid": "89860000000000000001",
      "msisdn": "13800138000",
      "operationCardStatus": 2
    }
  ]
}

🌊 流量池接口

流量池管理和使用量统计相关接口

池详情

GET /agw/api/v1/pool/detail

查询流量池详细信息,包括池类型、流量使用情况、绑定卡数量等

Request Headers
参数名 类型 必填 说明
X-App-Id string ● 是 应用ID
X-Sign string ● 是 请求签名
X-Timestamp long ● 是 时间戳(毫秒)
X-Nonce string ● 是 随机字符串
Query Parameters
参数名 类型 必填 说明
poolCode string ● 是 流量池编码
Response Body
参数名 类型 说明
code integer 返回状态码
message string 消息提示
traceId string 链路编码
data.upoolCode string 流量池code
data.upoolName string 流量池名称
data.enUpoolName string 流量池名称(英语)
data.poolType number 池类型:1.用户池,2.使用量计费池,3.统付池
data.useFlow number 使用量 KB
data.totalFlow number 总流量 KB(对于 poolType = 2 的,此字段不做使用)
data.billingCycle number 周期类型: 计费周期(1.月度套餐 3.季度 6.半年 12.一年)
data.totalCard integer 总卡数
data.rawAddTime string 创建时间
data.poolStatus number 池状态:1.有效,2.无效
data.bindCardStatusCount object[] 卡状态统计数组
data.bindCardStatusCount[].cardStatus number 卡状态
data.bindCardStatusCount[].total integer 总量
data.packageInfo object 企业资费包信息
data.packageInfo.flowPackageType number 资费包类型:1普通套餐流量包;2按量计费流量包;3统付池
data.packageInfo.clientFlowPackageName string 客户端流量包名称,用于展示给客户
data.packageInfo.channelName string 通道名称
data.epiConfigs object[] 当前资费包的配置列表
data.epiConfigs[].epiConfigCode string 企业资费包配置业务code
data.epiConfigs[].epiCode string 企业资费包code
data.epiConfigs[].standardCharge number 企业资费包(实际服务费,单位元)
data.epiConfigs[].realFenStandardCharge number 企业资费包(实际资费,单位分)
data.epiConfigs[].epiConfigType number 企业资费包类型:1.购卡,2.续费,3.叠加
data.unit string 单位 KB MB GB TB(使用量计费池)
data.startTime string 池开始时间(统付池)
data.endTime string 池结束时间(统付池)
data.upoolStatus number 池状态:1.有效,2.无效
Response Example
{
  "code": 200,
  "message": "success",
  "traceId": "a1b2c3d4e5f6g7h8",
  "data": {
    "upoolCode": "POOL202504220001",
    "upoolName": "测试流量池",
    "enUpoolName": "Test Data Pool",
    "poolType": 1,
    "useFlow": 1024000,
    "totalFlow": 10485760,
    "billingCycle": 1,
    "totalCard": 100,
    "rawAddTime": "2025-01-15 10:30:00",
    "poolStatus": 1,
    "upoolStatus": 1,
    "unit": "KB",
    "startTime": "2025-01-01",
    "endTime": "2025-12-31",
    "bindCardStatusCount": [
      {
        "cardStatus": 8,
        "total": 80
      },
      {
        "cardStatus": 4,
        "total": 20
      }
    ],
    "packageInfo": {
      "flowPackageType": 1,
      "clientFlowPackageName": "企业标准套餐100M",
      "channelName": "中国移动"
    },
    "epiConfigs": [
      {
        "epiConfigCode": "EPC001",
        "epiCode": "EP001",
        "standardCharge": 100.00,
        "realFenStandardCharge": 10000,
        "epiConfigType": 1
      }
    ]
  }
}

获取池历史12月的某一月的使用量

GET /agw/api/v1/pool/getPoolMonthUsage

查询流量池在指定月份的使用量统计

Request Headers
参数名 类型 必填 说明
X-App-Id string ● 是 应用ID
X-Sign string ● 是 请求签名
X-Timestamp long ● 是 时间戳(毫秒)
X-Nonce string ● 是 随机字符串
Query Parameters
参数名 类型 必填 说明
poolCode string ● 是 流量池编码
queryMonth string ● 是 查询月份,格式:2025-04
Response Body
参数名 类型 说明
code number 响应状态码
message string 响应消息
traceId string 请求追踪ID
data.poolCode string 流量池编码
data.month string 日期,格式 yyyy-MM
data.useFlowKb number 使用量,单位 KB
Response Example
{
  "code": 200,
  "message": "success",
  "traceId": "abc123def456",
  "data": {
    "poolCode": "POOL001",
    "month": "2025-04",
    "useFlowKb": 204800
  }
}

获取池近30天的某一天的使用量

GET /agw/api/v1/pool/getPoolDayUsage

查询流量池在指定日期的使用量统计

Request Headers
参数名 类型 必填 说明
X-App-Id string ● 是 应用ID
X-Sign string ● 是 请求签名
X-Timestamp long ● 是 时间戳(毫秒)
X-Nonce string ● 是 随机字符串
Query Parameters
参数名 类型 必填 说明
poolCode string ● 是 流量池编码
queryDay string ○ 否 查询日期,格式:2025-04-01
Response Body
参数名 类型 说明
code number 响应状态码
message string 响应消息
traceId string 请求追踪ID
data.poolCode string 流量池编码
data.day string 日期,格式 yyyy-MM-dd
data.useFlowKb number 使用量,单位 KB
Response Example
{
  "code": 200,
  "message": "success",
  "traceId": "abc123def456",
  "data": {
    "poolCode": "POOL001",
    "day": "2025-04-01",
    "useFlowKb": 10240
  }
}

💬 短信服务

短信发送、查询和状态追踪相关接口

上行回复记录查询

POST /agw/ioc/api/v1/sms/record/uplinkResp

分页查询用户回复的短信记录

Request Headers
参数名 类型 必填 说明
X-App-Id string ● 是 应用ID
X-Sign string ● 是 请求签名
X-Timestamp long ● 是 时间戳(毫秒)
X-Nonce string ● 是 随机字符串
Content-Type string ● 是 application/json
Request Body
参数名 类型 必填 说明
page integer ○ 否 页码,默认 1
pageSize integer ○ 否 每页数量,默认 20
iccid string ○ 否 ICCID 号码(ICCID 和卡号至少需要填写一个)
msisdn string ○ 否 卡号(ICCID 和卡号至少需要填写一个)
Response Body
参数名 类型 说明
code integer 返回状态码
message string 消息提示
traceId string 链路编码
total integer 总数
pageSize integer 页大小
totalPage integer 总页数
page integer 当前页
data array 返回数据数组
data[].id integer 主键 ID
data[].smsMsgCode string 短信消息记录业务主键
data[].iccid string ICCID
data[].msisdn string 卡号
data[].content string 短信内容
data[].sendReplyTime string 发送/回复时间
data[].statusReplyTime string 发送成功时间
data[].smsMsgState number 消息状态:0-未发送,1-发送中,2-发送失败,3-成功,4-重试中
Response Example
{
  "code": 200,
  "message": "success",
  "traceId": "abc123def456",
  "total": 100,
  "pageSize": 20,
  "totalPage": 5,
  "page": 1,
  "data": [
    {
      "id": 1,
      "smsMsgCode": "SMS001",
      "iccid": "89860000000000000001",
      "msisdn": "13800138000",
      "content": "测试短信",
      "sendReplyTime": "2025-04-01 10:00:00",
      "statusReplyTime": "2025-04-01 10:00:05",
      "smsMsgState": 3
    }
  ]
}

发送短信

POST /agw/ioc/api/v1/sms/send/content

批量发送短信到指定的卡号列表,最多支持 50 个号码

Body Parameters
参数名 类型 必填 说明
cardNumber string[] ● 是 卡号集合,最大 50 个
content string ● 是 短信内容,最大 150 字符
cardNumberType number ● 是 1-ICCID,2-卡号
Response Parameters
参数名 类型 说明
code number 响应状态码
message string 响应消息
traceId string 链路编码
data object 返回数据
data.errorMessageInfoResponses array 发送失败结果记录数组
data.errorMessageInfoResponses[].errorCode string 错误码
data.errorMessageInfoResponses[].errorVal string 错误值
data.errorMessageInfoResponses[].errorMessage string 错误信息
data.successMessageInfoResponses array 发送成功结果记录数组
data.successMessageInfoResponses[].iccid string ICCID
data.successMessageInfoResponses[].msisdn string 卡号
data.successMessageInfoResponses[].smsMsgCode string 短信消息id
Request Example JSON
{
  "cardNumber": [
    "89860000000000000001",
    "89860000000000000002"
  ],
  "content": "您的设备已激活,请查收。",
  "cardNumberType": 1
}
Response Example JSON
{
  "code": 200,
  "message": "success",
  "traceId": "abc123def456",
  "data": {
    "errorMessageInfoResponses": [],
    "successMessageInfoResponses": [
      {
        "iccid": "89860000000000000001",
        "msisdn": "13800138000",
        "smsMsgCode": "SMS20250401001"
      }
    ]
  }
}

短信状态查询

GET /agw/ioc/api/v1/sms/record/smsState

根据短信消息编码查询短信发送结果

Request Headers
参数名 类型 必填 说明
X-App-Id string ● 是 应用ID
X-Sign string ● 是 请求签名
X-Timestamp long ● 是 时间戳(毫秒)
X-Nonce string ● 是 随机字符串
Query Parameters
参数名 类型 必填 说明
smsMsgCode string ● 是 短信消息编码
Response Body
参数名 类型 说明
code number 响应状态码
message string 响应消息
traceId string 链路编码
data object 返回数据
data.id integer 主键 ID
data.smsMsgCode string 短信消息记录业务主键
data.iccid string ICCID
data.msisdn string 卡号
data.content string 短信内容
data.sendReplyTime string 发送/回复时间
data.statusReplyTime string 发送成功时间
data.smsMsgState number 消息状态:0-未发送,1-发送中,2-发送失败,3-成功,4-重试中
Response Example
{
  "code": 200,
  "message": "success",
  "traceId": "abc123def456",
  "data": {
    "id": 1,
    "smsMsgCode": "SMS001",
    "iccid": "89860000000000000001",
    "msisdn": "13800138000",
    "content": "测试短信内容",
    "sendReplyTime": "2025-04-01 10:00:00",
    "statusReplyTime": "2025-04-01 10:00:05",
    "smsMsgState": 3
  }
}