多语言示例与错误码
多语言示例与错误码
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。