多语言示例与错误码

多语言示例与错误码

Python 签名与请求

import hashlib, hmac, json, secrets, time, urllib.request

app_id = "your_app_id"
secret = "your_app_secret"
method = "POST"
path = "/api/v1/messages"
body = {
    "channel_id": 1,
    "receiver": "+8613800000001",
    "template_params": {"code": "123456", "minutes": "5"},
    "signature_name": "木雷演示",
}
timestamp = int(time.time())
nonce = secrets.token_hex(16)
canonical = json.dumps(body, ensure_ascii=False, sort_keys=True, separators=(",", ":"))
text = f"{method}{path}{canonical}{timestamp}{nonce}"
signature = hmac.new(secret.encode(), text.encode(), hashlib.sha256).hexdigest()

request = urllib.request.Request(
    "http://localhost:8080" + path,
    data=canonical.encode(),
    method=method,
    headers={
        "Content-Type": "application/json",
        "X-App-Id": app_id,
        "X-Timestamp": str(timestamp),
        "X-Nonce": nonce,
        "X-Signature": signature,
    },
)
print(urllib.request.urlopen(request).read().decode())

JavaScript 签名核心(Node.js)

import crypto from 'node:crypto';

const sortObject = (value) => {
  if (Array.isArray(value)) return value.map(sortObject);
  if (value && typeof value === 'object') {
    return Object.fromEntries(Object.keys(value).sort().map((k) => [k, sortObject(value[k])]));
  }
  return value;
};
const canonical = JSON.stringify(sortObject(body));
const text = method + path + canonical + timestamp + nonce;
const signature = crypto.createHmac('sha256', secret).update(text).digest('hex');

常用错误码

代码 含义 排查方向
10001–10006 请求、JSON、接收者或模板参数错误 对照通道类型和系统模板变量
20001 缺少认证信息 检查四个 X-* 请求头
20002 App ID 无效 应用是否存在
20003 签名不一致 比较方法、路径、规范 JSON、时间戳、nonce
20004 时间戳无效 Unix 秒且与服务端相差不超过 300 秒
20005 IP 不在白名单 检查反向代理后的客户端 IP
20006 应用已停用 后台启用应用
30001 / 30002 限流 / 配额超限 降低 QPS 或调整配额
30003–30006 通道、模板或可用路径异常 查看发送准备台和通道详情
40002–40007 数据库、Redis、队列、服务商、网络或熔断异常 查看健康检查和发送日志

业务错误通常使用 HTTP 200 携带非零 code,调用方必须同时判断 HTTP 状态与响应 code