跳转到正文
图奕科技 开发文档 平台登录
接入指南 / 服务凭证与短信下载本章 Markdown ↓

本实例 Issuer https://platform.too1.net

图奕统一认证服务 API

本文面向网云穿、远程控制和异地组网的服务端。产品客户端、浏览器和桌面 Native Client 不得持有 Service Client Secret,也不得直接调用本 API。用户登录请看 OIDC,桌面不跳浏览器的边界见 Native。

外部短信是“模板发送服务”,不是“平台登录认证服务”。发送产品提供的六位数字不会创建平台登录挑战,也不能换取用户 Token。不要用该接口替代统一登录。

认证模型

用户登录与服务调用使用两套独立客户端:

  • OIDC Web/Native Client:只用于用户登录,Scope 为 openid profile phone offline_access。
  • Confidential Service Client:只部署在产品服务端,Scope 为 sms:send sms:read payments:create payments:read refunds:create 的授权子集。

获取 5 分钟服务令牌:

POST /oauth2/token HTTP/1.1
Host: platform.too1.net
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&scope=sms%3Asend%20payments%3Aread

成功响应为标准 OAuth JSON。Service Token 是不透明字符串,不包含用户身份、不签发 Refresh Token。产品应在到期前重新获取并只保存在服务端内存中。

Service Client 支持多个并行密钥。轮换后旧密钥默认保留 24 小时;调用方确认新密钥生效后,可在后台立即吊销旧密钥。可为客户端配置来源 CIDR 白名单。

通用约定

  • 基础地址:https://platform.too1.net
  • 所有请求与响应使用 UTF-8 JSON。
  • 金额使用整数分,首期币种固定为 CNY。
  • 所有写接口必须携带 Idempotency-Key,长度 1–64 字符,并在同一 Service Client 下唯一。
  • 推荐 Key 只用 ASCII,添加操作与资源前缀:sms:订单或操作编号、pay:订单号、close:平台支付ID、refund:退款号。Key 是该 Client 下跨接口共享的,不是每条路由独立;关闭不同订单不能重复使用同一个 Key。
  • 当前摘要按原始 JSON 请求字节计算,空格、字段顺序变化也可能冲突。重试必须复用同一份序列化结果,不能只保证 JSON 语义相同。
  • 幂等记录当前保存至少约 24 小时,过期由维护任务清理;不能依赖它永久防重,产品仍需唯一业务单号和可靠记录。
  • 同一幂等键和相同请求体会重放首次结果,并返回 Idempotent-Replayed: true。
  • 同一幂等键和不同请求体返回 HTTP 409 idempotency_conflict。
  • 成功响应:{"data": ...}。
  • 失败响应:{"error":{"code":"...","message":"...","request_id":"..."}}。
  • X-Request-ID 可用于后台和结构化日志定位,不要在日志中记录 Bearer Token 或请求中的短信参数。
  • JSON 请求体上限 64 KiB,仅接受单个 JSON 对象,不接受未定义字段。OIDC Token 端点仍是表单与标准 OAuth JSON,不使用平台 data 包装。

Scope 与 Token 缓存

Scope 可调用方法
sms:send POST 短信发送
sms:read GET 短信记录
payments:create POST 支付会话、关闭支付
payments:read GET 支付、GET 退款
refunds:create POST 退款申请

仅有 refunds:create 不代表可以查询退款,读取仍需 payments:read。省略 scope 时平台按 Client 授权集合发令牌;建议显式请求最小权限。

产品服务端按 Client 和 Scope 集合缓存 Token,依据 expires_in 提前约 30 秒更新;并发请求合并取 Token,避免每条业务请求重新获取。Client Credentials 没有 Refresh Token,到期重新申请。网络请求必须有超时,401 时先检查类型/禁用状态;不要盲目刷新并自动重放具有副作用的业务请求。

无副作用的取令牌示例(curl 会提示输入 Secret;避免把密码写进 shell 历史或 -v 日志;输出包含 Token,不要截图外发):

curl --fail-with-body --max-time 10 \
  --user wyc-service \
  --data-urlencode grant_type=client_credentials \
  --data-urlencode 'scope=sms:send sms:read' \
  https://platform.too1.net/oauth2/token

业务程序应使用 HTTP 客户端和内存缓存,不通过 shell 调用带 Token 的命令。Basic 认证按 OAuth 库编码,不把 Secret 放查询参数。CIDR 限制使用产品服务端真实出口地址,不使用用户电脑 IP。

短信

发送单号码事务短信:

POST /api/v1/sms/messages
Authorization: Bearer SERVICE_TOKEN
Idempotency-Key: wyc-login-20260902-000001
Content-Type: application/json

{
  "template_code": "login_code",
  "phone_e164": "+8613812345678",
  "params": {"code": "123456"}
}

平台模板代码会在后台映射到联麓 Template ID;产品看不到渠道模板 ID。参数名称、顺序、长度和正则由管理员登记的 Schema 决定。参数值只在本次渠道调用中使用,不落库、不写日志。

请求字段

字段 类型 规则
template_code string 后台已登记并授权给产品的模板代码,不是联麓模板 ID
phone_e164 string 当前仅中国大陆 +86 手机号,不接受数组
params object<string,string> 字段集合与模板 Schema 完全相同,不缺字段、不额外添加字段

例如 Schema 规定 code 为六位数字,必须传 {"code":"012345"},不能传数字 12345 丢掉前导零。参数顺序由后台 Schema 决定;前端页面不能任意选择模板或群发名单。

默认每产品 10 RPS、突发 20、每天 10,000 条;同手机号同模板 60 秒一次、每天 10 次,跨模板每天 20 次。管理员可调整授权额度;以实际限制及返回值为准。没有模板授权默认拒绝。

返回规则:

  • 201 accepted:渠道明确受理。
  • 202 unknown:连接超时或结果未知,平台不会自动重发;产品应查询消息状态并避免立即换幂等键重复发送。
  • 502 provider_rejected:渠道明确拒绝。
  • 403 template_not_granted:产品没有模板授权。
  • 429 quota_exceeded / rate_limited:额度或频率限制。

受理返回示例:

{
  "data": {
    "message_id": "00000000-0000-4000-8000-000000000030",
    "template_code": "login_code",
    "phone": "+86****0000",
    "parameter_names": ["code"],
    "status": "accepted",
    "provider": "lianlu",
    "provider_reference": "PROVIDER_TASK_REFERENCE",
    "latency_ms": 180,
    "created_at": "2026-09-03T00:00:00Z",
    "updated_at": "2026-09-03T00:00:00Z"
  }
}

示例脱敏格式不应作为解析协议;原样显示即可。可选字段可能省略。accepted 仅代表渠道受理,不代表手机已经收到;unknown 查询也可能仍是 unknown,当前没有向产品承诺最终送达回执。

失败与未知结果

同键重试只用于领取已经完成的原请求结果,不代表再次发送。收到明确拒绝需要修正原因后,若用户重新发起一次新的发送,使用新的操作 Key。遇到连接中断、202 unknown 或结果保存异常,应先按已知 message_id 查询;没有 ID 则根据请求编号联系运维,不能自动换 Key 重发。

发送按钮倒计时由产品界面负责,平台不会给产品页面自动加倒计时。建议默认 60 秒,处理 429/503/未知结果并禁用重复点击;不要在失败回调中立即再次发短信。需要产品自行验证的业务验证码应独立保存 HMAC/哈希、用途、过期、次数、单次消费,不能与平台登录验证码混用。

查询发送记录:

GET /api/v1/sms/messages/{message_id}
Authorization: Bearer SERVICE_TOKEN

记录仅返回脱敏手机号、模板代码、状态、渠道任务号和耗时,不返回模板参数值。

支付与退款

支付 API、收银台、状态机、回调核对和退款规则见 PAYMENTS.md。

Webhook

平台以至少一次语义投递产品事件。请求头:

  • X-Tuyi-Event-ID:产品幂等键。
  • X-Tuyi-Timestamp:Unix 秒时间戳。
  • X-Tuyi-Signature:sha256=HEX(HMAC-SHA256(secret, timestamp + "." + raw_body))。

支付事件包括 payment.succeeded、payment.closed、payment.duplicate_suspected、refund.pending_approval、refund.succeeded、refund.failed。账号事件包括 user.disabled、user.enabled、user.phone_changed、user.sessions_revoked 和 mapping.created;产品成员事件包括 product_membership.activated、product_membership.suspended、product_membership.reactivated。成员邀请与产品/代理职责边界见产品成员文档。

产品必须先验证时间窗口与签名,再按事件 ID 幂等入库,最后交付权益。平台返回支付成功不等于产品权益已交付;Webhook 失败会指数退避并在后台显示积压。

完整消息结构、Go 验签函数、数据库 inbox 幂等及乱序处理见 Webhook 详细文档。常见 HTTP 与业务错误见排障文档。

最小接入顺序

  1. 管理员创建产品并登记精确的 HTTPS 收银台返回地址。
  2. 创建 Service Client,仅授予产品需要的 Scope,并保存一次性显示的 Secret。
  3. 为产品授权短信模板、绑定支付账户并保持事故开关关闭。
  4. 产品服务端实现 Token 缓存、幂等键、Webhook 验签与事件幂等。
  5. 在 staging 使用模拟支付和假渠道完成闭环。
  6. 分别完成真实短信、微信/支付宝 0.01 元支付、查询、回调和退款后,才开启相应生产开关。