API 对接文档

最后更新:2026-10-05 | 对接地址:https://jh.fzywl.cn

本平台把短信验证码、国际短信、语音验证码、人脸实名认证聚合为统一 RESTful API。所有接口统一返回:{"code":0,"msg":"success","data":{}},code=0 表示成功。

接口一览(先看这张表)

接口方法Key 类型计费
/api/sms/send 短信验证码POSTsms扣 1 条额度
/api/sms/intl 国际短信POSTsms_intl按国家单价扣账户余额
/api/voice/v2 语音验证码POSTvoice_v2扣 1 条额度
/api/voice/v1 语音验证码(已暂停)POSTvoice_v1调用返回 503、不扣费
/api/id/verify/h5、/api/id/verify/alipay 人脸实名POSTid_verify免费次数内不扣,超出扣 1 次
/api/oauth/authorize-url、/api/oauth/token 第三方登录POSToauth_login成功换码扣 1 次
/api/sms/templates 短信模板(提交/查询)POST / GETsms不计费
/api/status 发送状态查询GET对应产品不计费、不占限流
/api/account/balance 余额/额度查询GET对应产品不计费、不占限流

对接三步

步骤操作
1注册账号(手机号或邮箱),购买对应产品套餐获得额度(国际短信用账户余额,需先充值)
2控制台「API Key」页生成对应产品类型的 Key(类型必须与接口匹配,否则 403)
3按下方接口调用;建议同时配置回执推送(见 3.4),免轮询拿结果

使用前须知

项说明
短信范围国内短信仅支持中国大陆手机号;国际号码请用 /api/sms/intl
语音范围国内可传 11 位;国际号码带国家码(如 +8613800138000),实际可达以通道为准
Key 安全Key 仅创建时完整显示一次;建议配置 IP 白名单与频次限制(控制台「API Key」页)
鉴权方式请求头 Authorization: Bearer {API_KEY}

一、快速开始(5 分钟跑通)

1 注册并登录控制台 → 2 到「API Key」页生成一个 sms 类型的 Key → 3 用下面任一示例发一条短信。

cURL

curl -X POST https://jh.fzywl.cn/api/sms/send \
 -H "Authorization: Bearer 你的API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"phone":"13800138000","content":"123456"}'

PHP

<?php
$ch = curl_init('https://jh.fzywl.cn/api/sms/send');
curl_setopt_array($ch, [
  CURLOPT_POST      => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER   => [
    'Authorization: Bearer 你的API_KEY',
    'Content-Type: application/json',
  ],
  CURLOPT_POSTFIELDS   => json_encode([
    'phone'  => '13800138000',
    'content' => '123456',
  ]),
]);
$res = curl_exec($ch);
curl_close($ch);
echo $res;  // {"code":0,"msg":"success","data":{...}}

Python

import requests

r = requests.post(
  "https://jh.fzywl.cn/api/sms/send",
  headers={
    "Authorization": "Bearer 你的API_KEY",
    "Content-Type": "application/json",
  },
  json={"phone": "13800138000", "content": "123456"},
  timeout=10,
)
print(r.json())  # {"code":0,"msg":"success","data":{...}}

更多语言的示例(Java / Node.js / Go)见「插件下载」页,或直接参考上面的 cURL 写法。

二、鉴权与通用规则

2.1 鉴权

Authorization: Bearer {API_KEY}

Key 在控制台「API Key」页生成,产品类型必须与接口一致;可另外配置 IP 白名单(留空=不限制),不在白名单内返回 403。

2.2 幂等:防重复发送 / 重复扣费

请求头带 X-Request-Id(或 X-Idempotency-Key,也可以放 body 的 request_id)时,同一个 request_id 只会真正发送一次:重复请求直接返回上次结果,并带 data.duplicated = true、data.deducted = false。

curl -X POST https://jh.fzywl.cn/api/sms/send \
 -H "Authorization: Bearer 你的API_KEY" \
 -H "Content-Type: application/json" \
 -H "X-Request-Id: order-20261005-0001" \
 -d '{"phone":"13800138000","content":"123456"}'

推荐每笔业务给一个唯一 ID(如订单号),避免网络重试导致重复发送/重复扣费。

2.3 限流与响应头

响应头说明
X-RateLimit-Limit / -Remaining / -Reset本分钟该 Key 的限额、剩余次数、重置秒数
X-Quota-Remaining / X-Quota-Unit剩余额度(国际短信为账户余额,单位 CNY)

限额按 Key 维度(默认 20/分钟、200/小时、800/天),可在控制台「API Key → 限流」自助调整;填 0 表示该周期不限。超限返回 429。

2.4 调用网站(便于你排查 / 与客服对账)

后台调用日志会记录每次调用来自哪个网站,取值优先级:

优先级来源说明
1请求头 X-Site显式声明你的站点,如 X-Site: https://你的域名。服务端对接推荐用这个
2本次请求的 callback_url回执地址里带着你的域名(见 3.4)
3该 API Key 上配置的默认 callback_url控制台「API Key → 回调」配一次,这把 Key 的所有调用都能识别
4Referer / Origin浏览器调用会自动带;服务端直连默认没有,这类调用记为「服务端直连 + IP」

2.5 状态查询 / 余额查询(只读,不计费不占限流)

GET/api/status?call_id=123  (别名 /api/sms/status)

用同一把 Key 鉴权;只能查自己账号下、且与 Key 产品类型一致的记录,否则返回 404 / 403。

返回字段说明
call_id调用记录 ID(发送接口返回的 data.call_id)
statussuccess / failed / processing / unknown
plugin_status上游受理状态
third_party_id / third_party_code上游流水号 / 上游错误码
error_message失败原因(成功为 null)
response_time本次调用耗时(毫秒)
created_at调用时间
GET/api/account/balance
返回字段说明
product_type / product_name该 Key 对应的产品类型与名称
balance / unit该产品剩余额度(条/次)
money / money_unit账户余额(元,国际短信从这里扣)

可用于程序化做低额度告警 / 自动充值。

三、短信发送接口

POST/api/sms/send

鉴权:API Key(sms 类型) | 计费:成功扣 1 条额度

3.1 请求体

{
 "phone": "13800138000",
 "content": "123456",
 "callback_url": "https://你的域名/webhook"
}

3.2 参数说明

参数类型必填说明
phonestring是接收手机号(仅支持中国大陆)
contentstring是验证码内容,直接传数字即可(如 123456)
callback_urlstring否本次发送结果的回执地址(覆盖 Key 上配置的默认地址),见 3.4
对接提示:签名由平台「签名管理」统一配置和轮换,开发者无需配置签名。发送前建议先用「短信模板管理」(见第七节)提交模板并审核通过,系统会优先使用你已通过的模板;未提交则使用平台默认模板。

3.3 响应示例

{
 "code": 0,
 "msg": "success",
 "data": {
  "call_id": 123,
  "status": "success",
  "deducted": true,
  "third_party_id": "xxx",
  "response_time": 4
 }
}
返回字段说明
call_id调用记录 ID,用于 /api/status 查询与对账
statussuccess(已提交成功)/ failed(失败)/ unknown(上游未明确返回)
deducted本次是否扣费(失败的默认不扣)
error_message失败原因(成功为 null)
duplicated带 X-Request-Id 且为重复请求时返回 true

3.4 发送结果回执推送(Webhook,免轮询)

配置回执地址后,每次调用的结果会自动 POST(JSON)到你的地址,无需轮询 /api/status。地址优先级:单次请求的 callback_url > 该 Key 上配置的默认地址(控制台「API Key → 回调」设置)。

推送内容

{
 "event": "send_result",
 "call_id": 123,
 "product_type": "sms",
 "status": "success",
 "third_party_id": "xxx",
 "third_party_code": "OK",
 "error_message": null,
 "phone_masked": "138****8000",
 "deducted": true,
 "charged": 0,
 "request_id": null,
 "timestamp": 1790976000
}

请求头

请求头说明
Content-Typeapplication/json
X-Webhook-Event事件名,当前为 send_result
X-Webhook-Signaturesha256=HMAC-SHA256(原始请求体, 回执密钥),密钥在控制台「API Key → 回调」查看

验签示例(务必校验,防止伪造回调)

// PHP
$raw  = file_get_contents('php://input');      // 原始 body,不要重新 json_encode
$secret = '你的回执密钥';
$expect = 'sha256=' . hash_hmac('sha256', $raw, $secret);
$got  = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
if (!hash_equals($expect, $got)) { http_response_code(403); exit('bad sign'); }
$data = json_decode($raw, true);           // 验签通过再解析
// ...按 $data['call_id'] 更新你的业务状态
// Node.js (Express)
const crypto = require('crypto');
app.post('/webhook', express.raw({type: '*/*'}), (req, res) => {
 const raw = req.body.toString('utf8');
 const expect = 'sha256=' + crypto.createHmac('sha256', process.env.HOOK_SECRET).update(raw).digest('hex');
 if (req.get('X-Webhook-Signature') !== expect) return res.status(403).end('bad sign');
 const data = JSON.parse(raw);
 res.status(200).end('ok');             // 返回 2xx 才算投递成功
});
# Python (Flask)
import hmac, hashlib, json
from flask import request
@app.route('/webhook', methods=['POST'])
def hook():
  raw = request.get_data()             # 原始字节
  expect = 'sha256=' + hmac.new(b'你的回执密钥', raw, hashlib.sha256).hexdigest()
  if request.headers.get('X-Webhook-Signature') != expect:
    return 'bad sign', 403
  data = json.loads(raw)
  return 'ok', 200
投递规则:你的地址返回 HTTP 2xx 即视为成功;否则自动重试(最多 6 次、间隔递增),仍失败则进平台失败队列(可联系客服排查/重投)。推送是异步的,不影响接口响应速度。

3.5 内容与频率限制

限制说明
敏感词预检发送前本地预检违规词,命中返回 1109(不下发、不扣费)
同一号码频次同一账号对同一个号码有上限(默认 3 条/分钟、10 条/小时、20 条/天),超限返回 429
退订 / 黑名单号码在退订名单中不再下发,返回 403;可在控制台「API Key → 号码退订 / 黑名单」自行维护

3.6 错误码(常用)

code说明
0发送成功
401API Key 无效或已禁用
402额度不足,请先购买
403Key 类型不匹配 / IP 不在白名单 / 号码在退订名单
429限流(Key 频次或同号频次)
1101-1104手机号为空 / 内容为空 / 号码格式不正确 / 内容过长
1109内容含违规词,请修改后重试

四、国际短信(POST /api/sms/intl)

鉴权:API Key(sms_intl 类型,申请制) | 计费:按国家单价扣账户余额

发送国际号码(不含中国大陆)的验证码短信。产品与 Key 独立;计费方式与国内短信不同:按号码归属国家/地区单价,从账户余额实时扣费(不买条数套餐)。完整价目见 国际短信费率。

4.1 请求体

{
 "mobile": "+93701234567",
 "code": "1234"
}

4.2 参数说明

参数类型必填说明
mobilestring是必须带国家码,如 +93701234567;不支持中国大陆(传 +86 返回 1107,改用 /api/sms/send)
codestring是4~8 位数字或字母。正文固定为平台已报备的英文模板,暂不支持自定义文案

4.3 响应示例

{
 "code": 0,
 "msg": "success",
 "data": {
  "call_id": 321,
  "status": "success",
  "deducted": true,
  "third_party_id": "xxx",
  "response_time": 120,
  "country": "菲律宾",
  "unit_price": 0.35,
  "charged": 0.35
 }
}
返回字段说明
country号码归属国家/地区
unit_price该国家单价(元/条)
charged本次实扣金额(元)= unit_price

4.4 注意事项

· 开通方式:国际短信为申请制 —— 控制台「API Key → 国际短信申请」提交后,审核通过才能生成 sms_intl 类型 Key;未通过时生成 Key 与调用都会被拦。
· 正文固定:Your verification code is {code}, please do not share it with anyone.(暂不支持自定义文案)
· 计费:按国家单价从账户余额扣,成功才扣、失败不扣;余额不足返回 402,未开通返回 403,号码国家码未开通返回 1108。
· 各国落地以通道为准;部分国家需先完成模板报备(美国、加拿大、台湾、马来西亚等地约 2~5 个工作日)。

五、语音验证码接口

把验证码用电话语音念给用户,适合用户收不到短信的场景。两个通道各自独立接口、独立产品与 Key 类型:

通道接口地址产品 / Key 类型上游响应
v1 (已暂停)POST /api/voice/v1voice_v1明文错误码
v2POST /api/voice/v2voice_v2JSON(含 sid)
⚠ v1 通道已暂停:上游通道故障(恢复时间待定),调用 /api/voice/v1 会直接返回 503「上游故障维护中」,不扣额度。请改用 v2,相关套餐也已在购买页下架。
在线测试:打开 语音验证码测试,填你自己的语音 API Key、手机号、验证码即可真实外呼一次。 测试接口要求先认证手机号(平台会先发一条短信认证码,填回即加入白名单,以后不用再认证)——该限制只作用于测试接口,正式调用不受影响。

5.1 请求体

{
 "mobile": "13800138000",
 "code": "123456"
}

5.2 参数说明

参数类型必填说明
mobilestring是接收手机号。国内可传 11 位;国际号码带国家码,如 +8613800138000
codestring是要念出的验证码,4~6 位数字。验证码由你生成、你校验,平台只负责念出,不存储不校验

5.3 响应示例

{
 "code": 0,
 "msg": "success",
 "data": {
  "call_id": 456,
  "status": "success",
  "deducted": true,
  "third_party_id": "3375655611",
  "response_time": 5
 }
}
提醒你的用户关闭电话拦截:语音是陌生来电,被手机管家/运营商拦截时不会响铃,而语音按条计费——接不到一样扣费。

5.4 通道限制(上游原样返回,失败不扣费)

通道限制
v1已暂停(返回 503、不扣费)
v2同一号码 30 秒 1 条 / 1 小时 3 条 / 24 小时 5 条;中国大陆号码每天 22:00~次日 7:30 禁止发送

5.5 错误码(常用)

code说明
0已受理(是否真正接通看 data.status)
402余额不足,请先购买该通道额度
403Key 类型不匹配(v1 需 voice_v1,v2 同理)
429请求过于频繁
503v1 通道上游故障维护中(不扣费,请改用 v2)
1103 / 1106手机号格式不正确 / 验证码需为 4~6 位数字

六、人脸实名认证接口

两种通道,价格相同、共用一把 id_verify Key,但接口地址不同:

通道接口地址Key 类型说明
H5 刷脸POST /api/id/verify/h5id_verify网页刷脸活体检测
支付宝认证POST /api/id/verify/alipayid_verify(共用)支付宝扫码刷脸

另有 POST /api/id/verify(等价于 h5)、POST /api/id/verify/init、GET /api/id/verify/result、GET /api/id/verify/status。

6.1 请求体(两种通道通用)

{
 "name": "张三",
 "id_number": "110101199001011234",
 "callback_url": "https://你的回调地址"
}
参数类型必填说明
namestring是真实姓名
id_numberstring是身份证号
callback_urlstring否认证结果异步回调地址(POST JSON)
支付宝通道注意:需使用已完成实名、且姓名与被认证人一致的支付宝账号扫码,否则无法完成核身。

6.2 响应示例(创建认证)

{
 "code": 0,
 "msg": "认证已创建",
 "data": {
  "order_no": "202608151200001234",
  "verify_url": "https://jh.fzywl.cn/verify.html?orderNo=202608151200001234"
 }
}
// 把 verify_url 给终端用户打开(或转成二维码),用户完成扫脸

6.3 查询认证结果

GET/api/id/verify/result?order_no=202608151200001234
{
 "code": 0,
 "data": {
  "order_no": "202608151200001234",
  "status": "passed",
  "result": { "passed": true, "sub_code": "Z5050", "material_info": "" }
 }
}

6.4 异步回调(配置了 callback_url 时)

{
 "order_no": "202608151200001234",
 "status": "passed",
 "passed": true,
 "sub_code": "Z5050"
}

6.5 认证状态说明

status说明
pending已发起,等待用户扫脸
processing已初始化,扫脸进行中
passed认证通过
failed认证未通过
expired已过期(30 分钟内未完成),冻结的额度自动退还

计费:每个账号有后台配置的免费次数,超出后每次认证扣 1 次额度;认证失败/过期会退还。

七、短信模板管理

鉴权:API Key(sms 类型) | 不计费

对接流程:1. 提交模板(名称、内容),系统自动提交平台审核;2. 通过「查询模板」看审核状态,通过后即可用于发送;3. 发送时自动使用已通过的模板,签名由平台统一提供;4. 相同内容的模板自动复用,不会重复申请({code} 与 ${code} 视为相同)。

7.1 提交模板

POST/api/sms/templates
{
 "name": "登录验证码",
 "template_content": "您的验证码是{code},5分钟内有效",
 "template_var": "code",
 "type": "login",
 "callback_url": "https://your-site.com/callback"
}
参数类型必填说明
namestring是模板名称
template_contentstring是模板内容,变量用 {code} 或 ${code} 均可
template_varstring否模板变量名,默认 code
typestring否场景:login / register / bind / reset / custom(默认 custom)
callback_urlstring否审核结果回调地址,状态变化时自动 POST 通知

7.2 响应示例(申请成功 / 自动复用)

{
 "code": 0,
 "msg": "模板已提交,等待审核",
 "data": {
  "id": 1,
  "name": "登录验证码",
  "template_code": "SMS_20250820_001",
  "status": 2,
  "status_text": "审核中"
 }
}

7.3 查询我的模板

GET/api/sms/templates
{
 "code": 0,
 "data": [
  {
   "id": 1,
   "name": "登录验证码",
   "type": "login",
   "template_content": "您的验证码是{code},5分钟内有效",
   "template_code": "SMS_20250820_001",
   "status": 1,
   "status_text": "已通过",
   "created_at": "2026-08-20 12:00:00"
  }
 ]
}

7.4 模板状态

status说明
0已禁用
1已通过(可用于发送)
2审核中
3已拒绝(未通过平台审核)
4待重试(提交失败,可重新提交)

7.5 审核结果回调通知

{
 "event": "template_audit",
 "template_id": 1,
 "template_name": "登录验证码",
 "template_code": "SMS_20250820_001",
 "status": "approved",
 "status_text": "已通过",
 "reject_info": "",
 "timestamp": 1724150400
}
字段说明
event固定为 template_audit
statusapproved(已通过)/ rejected(已拒绝)
reject_info拒绝原因(rejected 时有值)

回调地址需返回 HTTP 2xx,否则视为通知失败。签名由平台「签名管理」统一配置轮换,开发者无需配置;修改/删除模板请到控制台操作。

八、错误码

要看全部错误码?这里只列常用码,点这里看完整错误码查询表(按模块分组、可搜索)。
code说明
0成功
401未授权 / API Key 无效或已禁用
402额度或账户余额不足
403Key 与产品类型不匹配 / IP 不在白名单 / 号码在退订名单 / 国际短信未开通
404接口不存在,或查询的记录不属于当前账号
409相同 X-Request-Id 的请求正在处理中(幂等),请勿重复提交
429触发限流(Key 频次 / 同号频次)
503v1 语音通道上游故障维护中(不扣费)
1101-1109短信/国际短信参数与内容类错误(含 1109 敏感词)
1311-1315 / 1321-1325实名认证初始化 / 查询类错误

九、常见问题与排查

现象怎么查 / 怎么处理
返回 402 额度不足 国内短信/语音扣「额度」,去控制台「计费与套餐」购买;国际短信扣「账户余额」,去「余额明细」充值。可用 /api/account/balance 程序化查询。
返回 429 两种可能:① 该 Key 触发频次限制 → 控制台「API Key → 限流」调整;② 同一号码触发频次限制(防轰炸)→ 换号或联系客服放宽。响应头会带剩余次数。
返回 403 ① Key 类型和接口不匹配(如用 sms Key 调国际短信);② 调用 IP 不在该 Key 的白名单内;③ 号码在退订/黑名单;④ 国际短信未开通(需先申请并审核)。
返回 1109 内容命中本地违规词预检(不下发、不扣费)。改内容后重试;如属正常业务词被误拦,联系客服加白。
调用成功但用户没收到 ① 用 /api/status?call_id= 或回执推送看最终状态;② 验证码类短信可能被手机「骚扰拦截」;③ 号码停机/空号;④ 运营商通道波动(可重试一次)。语音同理,务必提醒用户关闭拦截。
重复发送 / 重复扣费 给每笔业务带上 X-Request-Id(业务唯一 ID),重复请求会返回上次结果且不重复扣费。
想知道是哪个网站在调用 请求带 X-Site 头,或在控制台给 Key 配置默认回执地址;后台「日志中心 → 调用日志」有「调用网站」列。
本地调试最快的方式 用「短信测试」「语音测试」「人脸测试」页面(顶部导航),填自己的 Key 直接发;生产环境建议先发给自己号码验证。
还没解决?把你的 调用时间 + call_id + 返回的完整 JSON 发给客服,我们能直接定位上游返回。

附录:用户端控制台接口(JWT)

鉴权:用户登录后拿到的 JWT Token(请求头 Authorization: Bearer {token}),不是 API Key,仅用于控制台页面。

提交模板审核

POST/api/user/sms-templates/submit
{
 "name": "登录验证码",
 "type": "login",
 "template_code": "",
 "template_content": "您的验证码是code,请5分钟内使用",
 "template_var": "code"
}
// sign_name 由平台统一(昭通市昭阳区互动游戏乐园),无需也不允许自定义

提交后模板状态为 2(待审核),管理员审核通过后变为 1(启用);template_code 可留空,审核通过后由管理员填入。客户短信与客户模板的签名由平台统一为「昭通市昭阳区互动游戏乐园」,客户无需填写。

查询 / 编辑 / 删除

GET/api/user/sms-templates
POST/api/user/sms-templates/update  {"id":1,"name":"新名称","template_code":"SMS_yyyy"}
POST/api/user/sms-templates/delete  {"id":1}

字段说明

字段说明
typelogin / register / bind / reset / custom
sign_name平台统一签名:昭通市昭阳区互动游戏乐园。无需填写(传了也会被平台覆盖)
template_code模板 ID(如 SMS_xxxx),可留空
template_content / template_var模板内容 / 变量名(默认 code)

十、第三方登录 API(微信 / 支付宝 / 抖音)

让你的网站 / APP 支持「微信、支付宝、抖音」扫码登录:用户在我们这边完成授权,你的服务端拿一次性 code 换取用户身份。全程用你现有的 API Key 鉴权,不需要另外申请应用。

10.0 接口地址(完整)

用途地址
获取授权页地址POST https://jh.fzywl.cn/api/oauth/authorize-url
code 换用户身份POST https://jh.fzywl.cn/api/oauth/token
授权页(接口返回,用户打开)GET https://jh.fzywl.cn/oauth/authorize.html?token=...
鉴权方式Authorization: Bearer {API_KEY}

10.1 前提

项说明
API Key 类型必须是 oauth_login(控制台「API Key」页生成时选「登录 API」)
回调地址在该 Key 的「回调」里配置你的域名(如 https://your-site.com/oauth/callback);登录回调的域名必须与它一致
免费额度每个账号默认 9999 次;仅「成功换码」扣 1 次
用户前提不会创建方栀云账号:授权页只做第三方登录代理,只显示发起时指定的那个平台(provider)的登录入口,登录结果(open_id / 昵称 / 头像)通过 code 返回给你的站点

10.2 流程

步骤谁做什么
1你的服务端POST /api/oauth/authorize-url → 拿到授权页地址
2终端用户打开授权页 → 页内只出现该 provider 的登录入口(不跳平台登录页 / 首页,也不罗列其它平台)→ 扫码 / 登录完成后显示「你已登录,是否授权该应用使用你的账号登录?」→ 点同意授权 → 跳回你的 redirect_uri?code=...(全程不注册、不登录方栀云账号)
3你的服务端POST /api/oauth/token 用 code 换用户身份(成功扣 1 次)

10.3 获取授权页地址

POST https://jh.fzywl.cn/api/oauth/authorize-url
Authorization: Bearer {API_KEY}
Content-Type: application/json

{
  "provider": "wechat",              // wechat / alipay / douyin
  "redirect_uri": "https://your-site.com/oauth/callback",
  "state": "随机串(可选,会原样回传)"
}
返回字段说明
url让用户在浏览器打开这个地址:https://jh.fzywl.cn/oauth/authorize.html?token=...
expire_in授权请求有效期(秒,默认 600)

10.4 用 code 换用户身份

POST https://jh.fzywl.cn/api/oauth/token
Authorization: Bearer {API_KEY}
Content-Type: application/json

{ "code": "回调里拿到的 code" }
{
  "code": 0,
  "msg": "success",
  "data": {
    "provider": "wechat",
    "open_id": "该平台用户唯一 ID",
    "union_id": "",
    "nickname": "昵称",
    "avatar": "头像 URL",
    "user_id": 0
  }
}

user_id 固定为 0:登录 API 只返回第三方身份,不会在你的调用下创建方栀云账号。

10.5 错误码

code含义
401缺少 / 无效的 API Key
403Key 类型不是 oauth_login,或 IP 不在白名单
2001provider 不正确(只支持 wechat / alipay / douyin)
2002redirect_uri 不正确(必须是完整 http/https 地址)
2004未给该 API Key 配置「回调地址」
2005redirect_uri 的域名与回调地址不一致
2011–2014授权请求不存在 / 已过期 / 已完成 / 账号未绑定该平台(仅旧的登录态路径)
2015 / 2016未获取到第三方身份 / 授权平台与请求不一致
2021–2025缺少 code / code 无效 / 不属于该 Key / 已使用 / 已过期
402登录次数已用完

10.6 注意事项

项说明
授权确认扫码 / 登录完成后必须由用户点「同意授权」才签发 code;已登录用户打开授权页同样需要确认,不会自动放行
code 一次性有效期 5 分钟,且只能被签发它的 API Key 换取
扣费时机只有 /api/oauth/token 成功才扣 1 次;授权失败 / 不换码不扣
state原样回传,用于防 CSRF,建议每次随机生成
账号隔离授权流程不读写本平台用户表:不创建账号、不写绑定关系,客户站点的用户不会出现在方栀云后台
抖音 / 支付宝(电脑)直接跳转官方授权页(抖音、支付宝官方页面自带二维码),扫码后自动回到授权页确认;微信仍是页内二维码(内容为小程序跳转链接)
回跳位置抖音 / 支付宝授权完成后会回到授权页继续「同意授权」确认(即使回调发生在抖音、支付宝内置浏览器里也一样),不会进入本平台的登录 / 注册页
额度清零额度不足时返回 402,购买/补额度后即可继续

10.7 如何绑定回调域(控制台操作)

步骤操作
1登录控制台 → 左侧菜单「API Key」
2找到类型为「登录 API」的 Key → 点该行的「回调」按钮
3弹窗标题是「登录回调地址(回调域)」→ 填你的站点域名,如 https://your-site.com/oauth/callback → 保存
4之后发起授权时,redirect_uri 的域名必须与它一致,否则返回 2005

回调域是按 API Key 配置的:同一账号下不同 Key 可以配不同域名,互不影响。

更新日志

日期变更
2026-10-23电脑端抖音 / 支付宝改为直接跳官方授权页(不再自己渲染二维码);微信仍为页内二维码
2026-10-23修复:抖音/支付宝授权回调落在内置浏览器时会被送到本站登录页并注册账号——现改为回调直接回授权页确认,全程不建号
2026-10-23抖音电脑端二维码改为「先打开授权页」:避开抖音内置浏览器对授权链接的拦截,抖音内打开时提示切到系统浏览器
2026-10-23登录 API 授权页改为页内登录:只显示本次调用的平台(微信 / 支付宝 / 抖音),不再跳平台登录页 / 首页,也不再罗列其它登录方式;扫码 / 登录完成后增加「是否授权」确认步骤,点同意才签发 code;登录 API 不再创建方栀云账号(纯代理授权,只回传第三方身份)
2026-10-23新增「十、第三方登录 API(微信 / 支付宝 / 抖音)」:authorize-url + token 两步换用户身份,按账号 9999 次免费额度
2026-10-05文档重构:新增「接口一览」「回执验签示例」「状态/余额查询字段」「常见问题」;章节重新编号、左侧常驻目录
2026-10-05调用日志支持调用网站识别(X-Site / 回执地址 / Referer)
2026-10-03新增「发送结果回执推送(Webhook)」;内容与频率限制说明
2026-10-02v1 语音通道暂停(上游故障,返回 503 且不扣额度,请改用 v2)
2026-10-01国际短信改为按「国家/地区单价」从账户余额实时扣费(详见「国际短信费率」)

接口如有不兼容调整,会在此处同步说明。