鉴权说明
所有 S2S 开放接口(/open/v1/...)均使用 AppKey + AppSecret MD5 签名方式鉴权,无需 OAuth2 流程。签名必须在服务端计算,禁止在客户端(App)中持有 AppSecret。
概述
每次 API 请求需在 HTTP Header 中携带三个字段:应用标识 X-App-Id、 时间戳 X-Timestamp、以及基于时间戳和请求体计算的签名 X-Signature。 平台校验签名有效性和时间戳时效后,才处理业务逻辑。
S2S 接口专为服务端对服务端(Server-to-Server)调用设计,适合合作方后端批量同步用户数据。 如需在移动端嵌入健康功能,请使用终端 SDK。
请求头字段
| Header | 类型 | 必填 | 说明 |
|---|---|---|---|
X-App-Id | string | 是 | 控制台「凭证管理」中的 App ID(数字字符串,如 100023) |
X-Timestamp | integer | 是 | Unix 秒级时间戳,服务端时区无关,有效窗口为 ±5 分钟 |
X-Signature | string | 是 | 32 位小写 MD5 签名,见签名算法章节 |
Content-Type | string | 是(POST/PATCH) | 固定为 application/json |
签名算法
算法细节
X-Signature = lowercase( MD5( app_key + timestamp + app_secret + request_body ) )各部分说明:
| 部分 | 来源 | 备注 |
|---|---|---|
app_key | 控制台 AppKey 原始字符串 | 不做任何编码处理 |
timestamp | 与 X-Timestamp 值完全相同 | 字符串形式,如 "1743494400" |
app_secret | 控制台 AppSecret 原始字符串 | 仅服务端使用,绝不外传 |
request_body | 请求体原始 JSON 字符串 | GET 请求传空字符串 "";字段顺序保持与发送一致 |
四段直接拼接(无分隔符),对结果字符串取 MD5,输出 32 位小写十六进制。
多语言示例
PHP
function makeSignature(string $appKey, string $appSecret, int $timestamp, string $body): string {
return md5($appKey . $timestamp . $appSecret . $body);
}
$ts = time();
$sig = makeSignature($appKey, $appSecret, $ts, $requestBody);
// 请求头
// X-App-Id: 100023
// X-Timestamp: {$ts}
// X-Signature: {$sig}Python
import hashlib, time
def make_signature(app_key: str, app_secret: str, timestamp: int, body: str) -> str:
raw = app_key + str(timestamp) + app_secret + body
return hashlib.md5(raw.encode("utf-8")).hexdigest()
ts = int(time.time())
sig = make_signature(app_key, app_secret, ts, request_body)Node.js
const crypto = require("crypto");
function makeSignature(appKey, appSecret, timestamp, body) {
const raw = appKey + timestamp + appSecret + body;
return crypto.createHash("md5").update(raw, "utf8").digest("hex");
}
const ts = Math.floor(Date.now() / 1000);
const sig = makeSignature(appKey, appSecret, ts, requestBody);Go
import (
"crypto/md5"
"fmt"
"strconv"
"time"
)
func makeSignature(appKey, appSecret string, timestamp int64, body string) string {
raw := appKey + strconv.FormatInt(timestamp, 10) + appSecret + body
return fmt.Sprintf("%x", md5.Sum([]byte(raw)))
}
ts := time.Now().Unix()
sig := makeSignature(appKey, appSecret, ts, requestBody)防重放机制
平台校验 X-Timestamp 与服务器当前时间的差值,超出 ±5 分钟窗口的请求将被拒绝, 返回 HTTP 401。
- 确保调用方服务器时钟与 NTP 同步,偏差控制在 1 分钟以内
- 每次请求使用当前时间戳,禁止重用历史时间戳
- 同一
(App-Id, Timestamp, Signature)组合在窗口内只允许一次成功请求
鉴权错误
| code | HTTP 状态 | 说明 | 处理建议 |
|---|---|---|---|
HTTP_401 | 401 | 签名校验失败或 App-Id 不存在 | 检查签名算法、AppKey / AppSecret 是否正确 |
HTTP_401 | 401 | 时间戳过期(超出 ±5 分钟窗口) | 检查服务器时钟同步,使用最新时间戳 |
HTTP_429 | 429 | 请求频率超过限制(默认 60 次/分钟/应用) | 降低调用频率,实现指数退避重试 |