认证
Owem Pay 外部 API 采用三层安全模型:API Key + Secret、逐请求 HMAC-SHA512 签名和强制 IP 白名单。
安全层概览
HTTP 请求
│
├─ 1. IP 白名单 ─── IP 未授权? → 403 Forbidden
│
├─ 2. API Key + Secret ─── 凭证无效? → 401 Unauthorized
│
└─ 3. HMAC-SHA512 ─── 签名无效? → 401 Unauthorized
│
└─ 请求被接受 → 业务逻辑第一层 -- API Key + Secret
所有请求必须包含 Authorization 头:
Authorization: ApiKey {client_id}:{client_secret}| 组件 | 描述 | 前缀 |
|---|---|---|
client_id | API Key 的公开标识符 | cli_ |
client_secret | 密钥(我们仅存储哈希值) | sk_ |
Secret 从不以明文存储。当请求到达时,发送的 secret 会与存储的哈希进行比对。如果不匹配,请求会在到达业务逻辑之前被拒绝。
替代格式 -- 使用 base64 的 Basic Auth:
Authorization: Basic {base64(client_id:client_secret)}第二层 -- HMAC-SHA512
交易类请求(POST、PUT、PATCH)要求在 hmac 头中提供请求体的 HMAC-SHA512 签名。验证使用恒定时间比较(constant-time comparison)以防止时序攻击。
请参阅 HMAC-SHA512 获取 6 种编程语言的实现示例。
第三层 -- IP 白名单
每个 API Key 必须在白名单中至少有一个 IP。来自未授权 IP 的请求将被以 403 Forbidden 拒绝,即使凭证有效。请在 Merchant Portal 中创建或编辑 API Key 时配置白名单。
支持单个 IP 和 CIDR 表示法(如:172.20.16.0/20)。
必需的请求头
| 头 | 值 | 是否必需 |
|---|---|---|
Authorization | ApiKey {client_id}:{client_secret} | 是 -- 所有请求 |
Content-Type | application/json | 是 -- 带请求体的请求 |
hmac | 十六进制格式的 HMAC-SHA512 签名 | 是 -- 仅 POST/PUT/PATCH |
Idempotency-Key | 去重唯一密钥(最大 256 字符) | 可选 -- 仅 POST |
完整示例
bash
CLIENT_ID="cli_a1b2c3d4e5f6"
CLIENT_SECRET="sk_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01"
# 余额查询(GET -- 无需 HMAC)
curl -X GET https://api.owem.com.br/api/external/balance \
-H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET"
# PIX Cash-Out(POST -- 需要 HMAC + Idempotency-Key)
BODY='{"amount":3000,"pix_key":"12345678901","pix_key_type":"cpf","description":"Pagamento"}'
HMAC=$(echo -n "$BODY" | openssl dgst -sha512 -hmac "$CLIENT_SECRET" | awk '{print $2}')
curl -X POST https://api.owem.com.br/api/external/pix/cash-out \
-H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-H "hmac: $HMAC" \
-H "Idempotency-Key: cashout-order-9876" \
-d "$BODY"附加保护
| 保护措施 | 描述 |
|---|---|
| 频率限制 | 每 IP 60,000 次/分钟(已认证)。5 次/分钟(未认证) |
| Cloud Armor (WAF) | 保护集群的应用防火墙 |
| HTTPS + TLS 1.2+ | 所有连接强制加密 |
| HSTS | 浏览器强制使用 HTTPS |
为什么选择 HMAC-SHA512 而非 mTLS?
mTLS(双向 TLS)认证的是连接,而非内容。如果连接已认证,所有请求都会直接通过而无需逐一验证。
HMAC 逐请求单独验证。即使在有效的连接中,载荷的任何更改都会导致请求被拒绝。
| 方面 | mTLS | HMAC-SHA512 |
|---|---|---|
| 验证对象 | TLS 通道 | 请求载荷 |
| 管理 | X.509 证书(签发、轮换、吊销、CRL/OCSP) | 生成密钥对、更新、废止 |
| 运维风险 | 证书过期 -- 常见事故原因 | 密钥是简单字符串 |
| 内容完整性 | 否 | 是 |
TLS 已保证传输加密。HMAC 添加了载荷的完整性和真实性验证 -- 这是 mTLS 本身无法覆盖的。
错误响应
401 -- 缺少凭证
json
{
"error": {
"status": 401,
"message": "Missing API key credentials. Use Authorization: ApiKey <client_id>:<client_secret>"
}
}403 -- IP 未授权
json
{
"error": {
"status": 403,
"message": "Request IP not in API key whitelist"
}
}429 -- 超出频率限制
json
{
"error": {
"status": 429,
"message": "Too Many Requests"
}
}安全提示
- 切勿在前端代码或公共仓库中暴露
client_secret - 请在服务器中使用环境变量
- API Key 是永久的 -- 不会过期,但可在 Merchant Portal 中吊销
- 在白名单中配置允许的 IP