Palm 掌纹识别开放 API 对接文档
面向对象:接入方后端开发工程师
本文档帮助您完成 后端业务接口 对接,以及 SDK 用户 Token 签发。
一、快速开始
对接分为 3 步:
- 申请 API Key(一次性)—— 前往开发者控制台创建应用并生成
api_key。 - 服务端调用接口 —— 通过 HTTPS 携带
Authorization: Bearer <api_key>调用业务接口。 - 处理业务响应 —— 按统一响应结构
{code, message, requestId, data}判断结果。
┌─────────────────┐ HTTPS + Bearer <api_key> ┌────────────────────────────────┐
│ 您的后端服务 │ ─────────────────────────▶ │ open.intl.palm.tencent.com │
│ │ │ /palm/openai/* │
│ │ ◀───────────────────────── │ (Palm 开放平台网关) │
└─────────────────┘ JSON 响应 └────────────────────────────────┘
│
│ 服务端替终端用户签发
│ CreateSdkUserToken → sdk_user_token(sut_xxx)
▼
┌─────────────────┐ HTTPS + Bearer <sdk_user_token> ┌──────────────────────────┐
│ 终端 SDK/客户端│ ──────────────────────────────▶ │ open.intl.palm.tencent.com│
│ (App / 小程序)│ │ /palm/openai/* │
└─────────────────┘ 仅能操作该用户数据 └──────────────────────────┘
🔐 两种凭证的分工
api_key(ak_前缀)—— 服务端专用、权限最大,可访问全部接口与全部用户数据;不得下发到端。sdk_user_token(sut_前缀)—— 绑定到单个用户的受限凭证,通过 §5.1 CreateSdkUserToken 由业务方后端替某个UserId签发;只能操作该用户自己的数据,有过期时间。业务方既可以在自己的 Web 后端直接使用,也可以下发给移动端 SDK / 小程序 / 桌面客户端使用。
二、Token 申请(API Key)
2.1 申请入口
前往官网开发者控制台申请 API Key:
2.2 申请流程
- 使用您的账号登录官网。
- 进入 开发者中心 → API Keys。
- 点击 「创建应用」,填写应用名称、选择产品类型(掌纹管理)。
- 应用创建成功后,点击 「生成 API Key」。
- 立即复制并妥善保存明文
api_key(形如ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxx)—— 明文仅本次一次性返回,后续控制台只展示脱敏串(如ak_abcd******wxyz),若丢失只能删除后重新生成。
2.3 使用方式
在每次 HTTP 请求头中加入:
Authorization: Bearer ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
⚠️ 安全注意事项
api_key属于服务端凭证,严禁放到前端页面 / App 客户端 / 移动端源码 / 公开仓库;仅可保存在您服务端环境变量或密钥管理服务(KMS)中。- 一旦泄露,请立即到控制台删除并重新生成。
- 每个应用至多 1 把有效
api_key;如需轮换,先创建新 key,再删除旧 key。
三、通用约定
3.1 接口域名
| 环境 | 域名 |
|---|---|
| 正式环境(海外) | https://open.intl.palm.tencent.com |
所有业务接口均使用 HTTPS + POST + JSON。
3.2 URL 前缀
业务接口的路径统一以 /palm/openai/ 开头(CreateSdkUserToken 除外,见 §5.1):
POST https://open.intl.palm.tencent.com/palm/openai/<接口名>
3.3 请求头(HTTP Headers)
| 字段 | 是否必填 | 说明 |
|---|---|---|
Content-Type | 是 | 固定为 application/json; charset=utf-8 |
Authorization | 是 | 固定格式 Bearer <credential>,其中 <credential> 为 api_key(ak_ 前缀,见 §2)或 sdk_user_token(sut_ 前缀,见 §5.1) |
X-TraceId | 否 | 32 位小写 hex 字符串。用于全链路追踪,若不传由网关自动生成;建议接入方自行生成并记录,便于排障 |
3.4 请求体(Body)
- 均为 JSON 对象。
- 字段名统一使用 首字母大写驼峰(PascalCase),如
UserId、RgbImage。 - 图片二进制数据字段
Data使用 Base64 编码字符串。
3.5 通用响应结构
所有接口成功时统一返回如下 JSON 结构:
{
"code": 0,
"message": "ok",
"requestId": "4d5912a82af144f8a982c2da031c1035",
"data": {}
}
(data 字段的具体业务字段见各接口小节。)
| 字段 | 类型 | 说明 |
|---|---|---|
code | Integer | 业务错误码。0 表示成功;非 0 表示失败,请对照 §6 错误码表 |
message | String | 错误描述(成功时为 "ok") |
requestId | String | 服务端请求唯一 ID,排障时请提供 |
data | Object | 业务数据;失败时可能为空对象 {} |
3.6 频率限制
- 默认:20 次/秒 / 凭证(
api_key与sdk_user_token独立计数)。 - 超限返回 HTTP 429,请合理控制并发或联系官方申请提额。
四、公共数据类型
以下类型在多个接口中复用,统一说明。
4.1 PalmDirectionType 枚举
| 枚举值 | 含义 |
|---|---|
1 | LEFT_PALM(左手掌) |
2 | RIGHT_PALM(右手掌) |
4.2 PalmState 枚举(掌纹状态)
| 枚举值 | 常量名 | 含义 |
|---|---|---|
1 | ACTIVATED | 绑定成功,可用于比对 / 检索 |
2 | HIGH_SIMILARITY | 高相似(与其他用户存在高相似风险,暂不可用) |
五、业务接口
接口一览
| 序号 | 能力 | 接口名 | Method | Path | 支持的凭证 |
|---|---|---|---|---|---|
| 1 | 令牌鉴权 | CreateSdkUserToken | POST | /palm/openai/x/oauth/sdk/usertoken/create | 仅 api_key |
| 2 | 掌纹注册查询 | GetPalm | POST | /palm/openai/get_palm | api_key / sdk_user_token |
| 3 | 1:1 核验 | GetSessionResult | POST | /palm/openai/get_session_result | api_key / sdk_user_token |
| 4 | 手掌删除 | DeletePalm | POST | /palm/openai/delete_palm | api_key / sdk_user_token |
使用
sdk_user_token调用接口时,请求体中的UserId必须等于签发该 token 时传入的UserId(服务端会把签发时的UserId作为该 token 的绑定用户),否则将返回403。
5.1 令牌鉴权(签发 SDK 用户 Token,CreateSdkUserToken)
🔗 路径特别说明:本接口路径为
/palm/openai/x/oauth/sdk/usertoken/create,与其他业务接口(/palm/openai/<接口名>)不同,请勿写错。
接口描述
为业务方指定的最终用户签发一枚受限的 sdk_user_token(JWT,sut_ 前缀)。得到的 token 既可以由业务方自己在 Web 后端 直接使用,也可以下发给 移动端 SDK / 小程序 / 桌面客户端(特别适用于无法安全保管 api_key 的端侧场景)。
签发后的 sdk_user_token:
- 只能操作该用户自己的数据:调用 §5.2 / §5.3 / §5.4 时,请求体中的
UserId必须等于签发时传入的UserId;不匹配一律返回403。 - 有过期时间:默认 30 分钟(1800 秒),最长 24 小时(86400 秒);
TtlSeconds传0或缺省即取默认。 - 明文仅本次一次性返回:请由业务方后端下发到端上使用,不要持久化到不受信任的存储。
- 可撤销:
api_key被吊销 / 应用被禁用后即失效;异常情况下平台可通过后台密钥轮换一刀切吊销所有已签发的sdk_user_token(业务方需重新签发)。
⚠️ 本接口必须由业务方服务端调用:仅接受
api_key鉴权。严禁将本接口(包括api_key)暴露到端侧,否则等同于把api_key泄露。
- 默认频率限制:20 次/秒。
请求参数
| 参数 | 必填 | 类型 | 说明 |
|---|---|---|---|
UserId | 是 | String | 业务方最终用户标识(业务方自定义命名空间,Palm 侧不落表;与其他业务接口中的 UserId 同一个取值空间),长度 ≤ 64 |
TtlSeconds | 否 | Integer | Token 有效期(秒)。0 或缺省 → 默认 1800(30 分钟);硬上限 86400(24 小时),超出直接返回错误码 2090021(不会静默截断) |
Scope | 否 | Array<String> | 预留权限点数组,v1 不校验,仅回填到 JWT,可传空 [] 或不传 |
响应参数(data)
| 参数 | 类型 | 说明 |
|---|---|---|
Token | String | 签发的 sdk_user_token,形如 sut_xxxxxxxxxxxxxxxx(内部为 JWT)。明文仅本次返回,请立即保存或下发给对应终端 |
ExpiresAt | Integer | Token 过期时间戳(Unix 秒,UTC) |
示例
请求
POST /palm/openai/x/oauth/sdk/usertoken/create HTTP/1.1
Host: open.intl.palm.tencent.com
Content-Type: application/json; charset=utf-8
Authorization: Bearer ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
{
"UserId": "user001",
"TtlSeconds": 1800,
"Scope": []
}
响应
{
"code": 0,
"message": "ok",
"requestId": "4d5912a82af144f8a982c2da031c1035",
"data": {
"Token": "sut_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxx.yyy",
"ExpiresAt": 1783691400
}
}
cURL
curl -X POST "https://open.intl.palm.tencent.com/palm/openai/x/oauth/sdk/usertoken/create" \
-H "Content-Type: application/json; charset=utf-8" \
-H "Authorization: Bearer ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-d '{
"UserId": "user001",
"TtlSeconds": 1800,
"Scope": []
}'
使用拿到的 sdk_user_token 调用业务接口(后端 Web / SDK / 小程序 均适用)
拿到 sdk_user_token 后,调用方式和 api_key 完全一致,只是把 Header 中的 ak_xxx 换成 sut_xxx:
POST /palm/openai/get_palm HTTP/1.1
Host: open.intl.palm.tencent.com
Content-Type: application/json; charset=utf-8
Authorization: Bearer sut_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxx.yyy
{
"UserId": "user001"
}
服务端会自动从 sdk_user_token 反解出所绑定的 UserId(即请求体中的 UserId),并执行下列校验:
sdk_user_token签名有效、未过期。- 请求体中的
UserId必须等于 token 绑定的UserId,否则返回403。 - 调用的接口在
sdk_user_token允许清单内(§5.2GetPalm/ §5.3GetSessionResult/ §5.4DeletePalm)。
✅ 推荐做法(特别针对 SDK / 端侧):端上每次冷启动 / token 剩余寿命不足 20% 时,向业务方自己的后端请求最新
sdk_user_token;由业务方后端在内部登录态校验通过后,再调用本接口签发。这样即便 token 被抓包也仅影响该用户,且很快过期。
5.2 掌纹注册查询(GetPalm)
接口描述
查询指定用户当前已注册的左/右手掌纹信息,用于业务侧展示"是否已开通刷掌 / 什么时候注册的 / 状态是否正常"等。
- 默认频率限制:20 次/秒。
- 只读接口,不会修改任何数据。
- 若用户从未注册过某一方向的掌纹,则该方向对应的
PalmInfo字段将被省略或为空对象。
请求参数
| 参数 | 必填 | 类型 | 说明 |
|---|---|---|---|
UserId | 是 | String | 用户唯一标识(与 §5.1 中的 UserId 语义一致) |
响应参数(data)
顶层:
| 参数 | 类型 | 说明 |
|---|---|---|
LeftPalm | PalmInfo | 左手掌纹信息 |
RightPalm | PalmInfo | 右手掌纹信息 |
PalmInfo 结构:
| 参数 | 类型 | 说明 |
|---|---|---|
PalmState | Integer | 掌纹状态,见 §4.2;1 表示绑定成功、可用于比对 |
PalmDirection | PalmDirectionType | 手掌方向,见 §4.1 |
RegisterTime | Integer | 首次注册时间(Unix 秒,UTC) |
示例
请求
POST /palm/openai/get_palm HTTP/1.1
Host: open.intl.palm.tencent.com
Content-Type: application/json; charset=utf-8
Authorization: Bearer ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
{
"UserId": "user001"
}
响应(用户仅开通左手)
{
"code": 0,
"message": "ok",
"requestId": "4d5912a82af144f8a982c2da031c1035",
"data": {
"LeftPalm": {
"PalmState": 1,
"PalmDirection": 1,
"RegisterTime": 1783600000
},
"RightPalm": {
"PalmState": 0,
"PalmDirection": 0,
"RegisterTime": 0
}
}
}
cURL
curl -X POST "https://open.intl.palm.tencent.com/palm/openai/get_palm" \
-H "Content-Type: application/json; charset=utf-8" \
-H "Authorization: Bearer ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-d '{
"UserId": "user001"
}'
5.3 查询识别结果(GetSessionResult)
接口描述
查询客户端/SDK 完成 1:1 比对后生成的临时识别结果详情。比对完成后,palm_mgr 会返回一个临时 SessionId(UUID,有效期 2 小时),业务方后端凭该 SessionId 查询本次比对的目标用户 ID、掌纹 ID、手掌方向、是否命中、分数与算法版本,避免识别结果详情被直接暴露。
- 默认频率限制:20 次/秒。
- 只读接口,不会修改任何数据。
SessionId有效期为 2 小时,过期后需重新发起比对获取新的SessionId。- 该接口无需在请求中指定
UserId,服务端根据SessionId反查出对应的识别结果。
请求参数
| 参数 | 必填 | 类型 | 说明 |
|---|---|---|---|
SessionId | 是 | String | 识别结果临时查询凭据,即比对接口响应中的 SessionId |
响应参数(data)
| 参数 | 类型 | 说明 |
|---|---|---|
UserId | String | 本次识别的目标用户 ID |
PalmId | String | 参与识别的掌纹 ID |
PalmDirection | PalmDirectionType | 参与识别的手掌方向,见 §4.1 |
SearchResult | Object | 识别结果(识别类 session 返回),结构见下表 |
RegisterResult | Object | 注册结果(注册类 session 返回),当前无额外字段 |
SearchResult 结构:
| 字段 | 类型 | 说明 |
|---|---|---|
IsMatch | Boolean | 是否命中(1:1 比对为是否同一人;1:N 检索为是否检索到) |
Score | Integer | 识别分数 |
AlgorithmVersion | String | 本次识别使用的算法版本 |
示例
请求
POST /palm/openai/get_session_result HTTP/1.1
Host: open.intl.palm.tencent.com
Content-Type: application/json; charset=utf-8
Authorization: Bearer ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
{
"SessionId": "3f2b1a6d-8c4e-4b7a-9d5f-1e2c3a4b5c6d"
}
响应
{
"code": 0,
"message": "ok",
"requestId": "4d5912a82af144f8a982c2da031c1035",
"data": {
"UserId": "user001",
"PalmId": "8db884f9-1fb8-44f5-bdaa-f98fdcb3cd47",
"PalmDirection": 1,
"SearchResult": {
"IsMatch": true,
"Score": 92,
"AlgorithmVersion": "rgb_v3"
}
}
}
cURL
curl -X POST "https://open.intl.palm.tencent.com/palm/openai/get_session_result" \
-H "Content-Type: application/json; charset=utf-8" \
-H "Authorization: Bearer ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-d '{
"SessionId": "3f2b1a6d-8c4e-4b7a-9d5f-1e2c3a4b5c6d"
}'
5.4 手掌删除(DeletePalm)
接口描述
删除指定用户的掌纹信息。支持按左/右手方向单独删除,也可以同时删除双手。删除后该用户对应方向的掌纹将无法再被比对命中。
- 默认频率限制:20 次/秒。
- 删除是幂等的:对不存在的方向重复删除不会报错。
请求参数
| 参数 | 必填 | 类型 | 说明 |
|---|---|---|---|
UserId | 是 | String | 用户唯一标识 |
PalmDirectionList | 是 | Array<PalmDirectionType> | 要删除的手掌方向列表。可以同时传入左右手,或仅左手/仅右手。见 §4.1 |
响应参数(data)
无业务字段,data 为空对象 {}。
示例
请求(同时删除双手)
POST /palm/openai/delete_palm HTTP/1.1
Host: open.intl.palm.tencent.com
Content-Type: application/json; charset=utf-8
Authorization: Bearer ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
{
"UserId": "user001",
"PalmDirectionList": [1, 2]
}
响应
{
"code": 0,
"message": "ok",
"requestId": "4d5912a82af144f8a982c2da031c1035",
"data": {}
}
六、错误码
除业务错误码外,也可能返回 HTTP 层的状态码,请按下表处理。
6.1 HTTP 状态码
| HTTP Code | 含义 | 处理建议 |
|---|---|---|
200 | 请求已抵达业务层 | 请解析 body 中的 code 字段判断是否真正成功 |
401 | 未授权 | 检查 Authorization 头是否携带、api_key 是否已被删除或格式错误 |
403 | 无权限 | 检查该应用是否被禁用、api_key 是否被吊销 |
429 | 请求过快 | 降低 QPS,或联系官方申请提额 |
5xx | 服务端异常 | 携带 requestId 联系官方支持 |
6.2 业务错误码(code 字段)
响应体中 code 为业务错误码:0 表示成功;非 0 表示失败,请按下表定位原因,并结合 message 字段与 requestId 排障。
错误码采用 7 位十进制编码,格式为 XXX YYYY:前 3 位为模块号(标识错误来源),后 4 位为模块内序号。PaaS 接口涉及以下 4 段:
1000xxx通用兜底:参数校验、内部异常等所有接口都可能返回。2060xxx凭证/鉴权(网关层):所有接口在鉴权阶段都可能返回。2080xxx掌纹业务(palm_mgr):接口业务逻辑本身抛出的错误。2090xxxOAuth / SDK 凭证签发:仅 §5.1CreateSdkUserToken场景可能返回。
6.2.1 通用错误码
| code | message | 含义 / 排查建议 |
|---|---|---|
0 | ok | 请求成功。 |
1000000 | invalid param | 请求参数校验失败(必填字段缺失 / 格式非法 / 长度超限等)。请对照各接口"请求参数"表核对。 |
1000001 | internal error | 服务端内部异常,请携带 requestId 联系官方支持。 |
1000011 | database operation failed | 数据库操作失败(超时 / 连接异常等)。可稍后重试;持续复现请携带 requestId 反馈。 |
1000013 | forbidden | 无操作权限(应用被禁用 / 凭证被吊销等)。请核对应用状态。 |
6.2.2 凭证与鉴权错误码
由网关层在鉴权阶段返回;出现此段错误时业务逻辑尚未执行。
| code | message | 含义 / 排查建议 |
|---|---|---|
2060000 | unauthorized | 未携带 Authorization 头、api_key/sdk_user_token 无效或已过期。请检查 §3.3 请求头格式与凭证有效性。 |
2060002 | too many requests | 触发调用频率限制。请降低 QPS,或联系官方申请提额。 |
2060200 | openapi credential not found | 凭证不存在。可能已被删除,请到控制台确认或重新生成。 |
2060201 | openapi credential of this type already exists | 同一类型凭证已存在(api_key 按 app_id 唯一,sdk_user_token 按用户唯一)。仅在 §5.1 CreateSdkUserToken 场景可能出现,需先删除旧凭证。 |
2060202 | openapi credential revoked | 凭证已被吊销。请到控制台重新生成。 |
2060203 | openapi credential invalid | 凭证格式非法或签名校验失败;或凭证类型对应的必填字段(如 user_token 的 uid、sdk_user_token 的 userid/app_id)为空。请核对复制的 api_key/sdk_user_token 是否完整。 |
2060204 | openapi credential type invalid | 凭证类型非法:Authorization: Bearer <credential> 中的 <credential> 前缀非 ak_ / ut_ / sut_(例如误把控制台 JWT 当作 OpenAPI 凭证使用);或 §5.1 签发场景请求的凭证类型不在 api_key / user_token 白名单内。 |
2060205 | openapi credential not allowed for this path | sdk_user_token 的 scope 未覆盖当前接口路径。仅 sut_ 前缀凭证可能出现,请核对签发时的 scope 配置。 |
2060207 | OpenAPI app not configured | 凭证对应的应用未在平台完成配置。请联系官方开通。 |
2090021 | sdk user token ttl exceeds max limit | §5.1 CreateSdkUserToken 请求的 TtlSeconds 超过硬上限(默认 86400,即 24 小时)。平台直接拒绝而非静默截断,请将 TtlSeconds 调整到 1~86400 范围内后重试。 |
6.2.3 业务错误码(掌纹业务)
由 palm_mgr 业务层返回;code 与接口的对应关系见每条备注。
| code | message | 含义 / 排查建议 |
|---|---|---|
2080000 | no available version | 无可用算法/掌纹版本。请联系官方确认应用是否已正确开通产品版本。 |
2080001 | unknown image type | 未知图片类型。请确认 RgbImage.Data 为合法的 Base64 编码 JPG/PNG 图片。 |
2080002 | image MD5 mismatch | 图片 MD5 校验失败,通常为传输过程中数据被截断或篡改。建议客户端重试。 |
2080003 | liveness check failed | 活体检测未通过。可能采集时用户使用了照片/翻拍;请引导用户重新采集清晰的真实手掌图像。 |
2080004 | quality check failed | 图像质量检测未通过(模糊 / 手掌不完整 / 光线差等)。请引导用户按 SDK 提示重新采集。 |
2080005 | liveness video check failed | 视频活体检测未通过(ActionLiveness 场景)。请引导用户按 SDK 指引重新录制动作视频。 |
2080006 | palmId does not exist, please re-record the palm | PalmId 已过期或不存在,需重新录掌。 |
2080007 | already bound | 该 UserId + PalmDirection 已注册过掌纹。若确需覆盖,请使用强制覆盖方式重新注册。 |
2080008 | palmId may have been bound by someone else | 检索到的 PalmId 已被其他用户绑定,通常出现在异常并发场景。请携带 requestId 联系官方核查。 |
2080009 | data not found | 数据不存在。§5.2 GetPalm 场景下表示指定 UserId/PalmDirection 尚未注册。 |
2080010 | user not found in search | 1:N 检索未在掌库中匹配到任何用户。属于业务正常返回,非系统错误。 |
2080011 | table capacity full | 掌库分表容量已满。请联系官方扩容。 |
2080012 | user's assistant image count exceeds limit | 用户辅助图片数量超限。 |
2080013 | verification id expired | 验证 ID 已过期。请重新走完整流程。 |
2080014 | palm capacity full | 掌纹容量已满(应用维度)。请联系官方扩容或先删除历史掌纹。 |
2080015 | user has been deleted | 用户已删除(仅空中开掌场景使用)。 |
2080016 | user does not exist in DB | 用户不存在。请确认用户已成功注册掌纹后再调用比对/删除类接口。 |
2080017 | user palm direction does not exist in DB | 用户指定手掌方向对应掌纹不存在。请核对 PalmDirection 参数或先完成注册。 |
2080018 | concurrent operation in DB, please retry | 并发操作冲突。请客户端稍后重试;同一用户避免并行调用注册/删除类接口。 |
2080019 | insertFeatureCurrentSyncIndex already exists | 特征同步索引冲突(内部一致性错误)。请携带 requestId 联系官方核查。 |
2080020 | palm capacity quota exceeded | 掌库特征配额超限(平台总配额不足)。请联系官方申请扩容。 |
2080021 | palm mobile (online register) not supported by platform license | 当前平台 License 未授权空中开掌功能。请联系官方开通。 |
2080022 | palm capacity cannot be less than current usage | 配额调整时低于当前已使用量。 |
2080023 | app does not exist | 应用不存在(应用维度接口)。请核对凭证对应的应用是否已正确创建。 |
2080024 | compare session expired or not exist | 比对结果 SessionId 不存在或已过期(有效期 2 小时)。请重新发起比对获取新的 SessionId。 |
📌 排障建议:
- 务必保留
requestId:所有响应都会返回,是官方定位问题的核心线索。- 遇到未列在本表的
code或不确定的错误,请携带requestId、接口名、请求时间联系官方支持。1000xxx段属于服务端通用兜底错误,若频繁出现请优先检查请求参数与网络状况;持续复现请上报。
七、集成示例(Go)
下面以一个 掌纹注册查询(GetPalm) 为例,演示 Go 服务端的完整调用流程。其余接口调用方式一致,只需替换请求路径与请求体字段(各接口字段见 §五)。
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
const baseURL = "https://open.intl.palm.tencent.com"
// commonResp 通用响应包装。
type commonResp struct {
Code int `json:"code"`
Message string `json:"message"`
RequestID string `json:"requestId"`
Data json.RawMessage `json:"data"`
}
// call 发起一次 POST 请求,返回 requestId(用于排障)。
func call(apiKey, path string, reqBody, out any) (string, error) {
body, _ := json.Marshal(reqBody)
req, _ := http.NewRequest("POST", baseURL+path, bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.Header.Set("Authorization", "Bearer "+apiKey)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
raw, _ := io.ReadAll(resp.Body)
var wrap commonResp
if err := json.Unmarshal(raw, &wrap); err != nil {
return "", fmt.Errorf("decode resp: %w, raw=%s", err, string(raw))
}
if wrap.Code != 0 {
return wrap.RequestID, fmt.Errorf("api error code=%d message=%s requestId=%s", wrap.Code, wrap.Message, wrap.RequestID)
}
if out != nil && len(wrap.Data) > 0 {
if err := json.Unmarshal(wrap.Data, out); err != nil {
return wrap.RequestID, err
}
}
return wrap.RequestID, nil
}
func main() {
apiKey := "ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
reqBody := map[string]any{
"UserId": "user001",
}
var out struct {
LeftPalm struct {
PalmState int `json:"PalmState"`
PalmDirection int `json:"PalmDirection"`
RegisterTime int64 `json:"RegisterTime"`
} `json:"LeftPalm"`
RightPalm struct {
PalmState int `json:"PalmState"`
PalmDirection int `json:"PalmDirection"`
RegisterTime int64 `json:"RegisterTime"`
} `json:"RightPalm"`
}
requestID, err := call(apiKey, "/palm/openai/get_palm", reqBody, &out)
if err != nil {
fmt.Printf("get palm failed: %v (requestId=%s)\n", err, requestID)
return
}
fmt.Printf("LeftPalm=%+v RightPalm=%+v\n", out.LeftPalm, out.RightPalm)
}