API 对接文档
最后更新:2026-10-05 | 对接地址:https://jh.fzywl.cn
本平台把短信验证码、国际短信、语音验证码、人脸实名认证聚合为统一 RESTful API。所有接口统一返回:{"code":0,"msg":"success","data":{}},code=0 表示成功。
接口一览(先看这张表)
对接三步
| 步骤 | 操作 |
| 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 的所有调用都能识别 |
| 4 | Referer / Origin | 浏览器调用会自动带;服务端直连默认没有,这类调用记为「服务端直连 + IP」 |
2.5 状态查询 / 余额查询(只读,不计费不占限流)
GET/api/status?call_id=123 (别名 /api/sms/status)
用同一把 Key 鉴权;只能查自己账号下、且与 Key 产品类型一致的记录,否则返回 404 / 403。
| 返回字段 | 说明 |
| call_id | 调用记录 ID(发送接口返回的 data.call_id) |
| status | success / 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 参数说明
| 参数 | 类型 | 必填 | 说明 |
| phone | string | 是 | 接收手机号(仅支持中国大陆) |
| content | string | 是 | 验证码内容,直接传数字即可(如 123456) |
| callback_url | string | 否 | 本次发送结果的回执地址(覆盖 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 查询与对账 |
| status | success(已提交成功)/ 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-Type | application/json |
X-Webhook-Event | 事件名,当前为 send_result |
X-Webhook-Signature | sha256=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 | 发送成功 |
| 401 | API Key 无效或已禁用 |
| 402 | 额度不足,请先购买 |
| 403 | Key 类型不匹配 / IP 不在白名单 / 号码在退订名单 |
| 429 | 限流(Key 频次或同号频次) |
| 1101-1104 | 手机号为空 / 内容为空 / 号码格式不正确 / 内容过长 |
| 1109 | 内容含违规词,请修改后重试 |
四、国际短信(POST /api/sms/intl)
鉴权:API Key(sms_intl 类型,申请制) | 计费:按国家单价扣账户余额
发送国际号码(不含中国大陆)的验证码短信。产品与 Key 独立;计费方式与国内短信不同:按号码归属国家/地区单价,从账户余额实时扣费(不买条数套餐)。完整价目见 国际短信费率。
4.1 请求体
{
"mobile": "+93701234567",
"code": "1234"
}
4.2 参数说明
| 参数 | 类型 | 必填 | 说明 |
| mobile | string | 是 | 必须带国家码,如 +93701234567;不支持中国大陆(传 +86 返回 1107,改用 /api/sms/send) |
| code | string | 是 | 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/v1 | voice_v1 | 明文错误码 |
| v2 | POST /api/voice/v2 | voice_v2 | JSON(含 sid) |
⚠ v1 通道已暂停:上游通道故障(恢复时间待定),调用 /api/voice/v1 会直接返回 503「上游故障维护中」,不扣额度。请改用 v2,相关套餐也已在购买页下架。
在线测试:打开
语音验证码测试,填你自己的语音 API Key、手机号、验证码即可真实外呼一次。
测试接口要求先
认证手机号(平台会先发一条短信认证码,填回即加入白名单,以后不用再认证)——
该限制只作用于测试接口,正式调用不受影响。
5.1 请求体
{
"mobile": "13800138000",
"code": "123456"
}
5.2 参数说明
| 参数 | 类型 | 必填 | 说明 |
| mobile | string | 是 | 接收手机号。国内可传 11 位;国际号码带国家码,如 +8613800138000 |
| code | string | 是 | 要念出的验证码,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 | 余额不足,请先购买该通道额度 |
| 403 | Key 类型不匹配(v1 需 voice_v1,v2 同理) |
| 429 | 请求过于频繁 |
| 503 | v1 通道上游故障维护中(不扣费,请改用 v2) |
| 1103 / 1106 | 手机号格式不正确 / 验证码需为 4~6 位数字 |
六、人脸实名认证接口
两种通道,价格相同、共用一把 id_verify Key,但接口地址不同:
另有 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://你的回调地址"
}
| 参数 | 类型 | 必填 | 说明 |
| name | string | 是 | 真实姓名 |
| id_number | string | 是 | 身份证号 |
| callback_url | string | 否 | 认证结果异步回调地址(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"
}
| 参数 | 类型 | 必填 | 说明 |
| name | string | 是 | 模板名称 |
| template_content | string | 是 | 模板内容,变量用 {code} 或 ${code} 均可 |
| template_var | string | 否 | 模板变量名,默认 code |
| type | string | 否 | 场景:login / register / bind / reset / custom(默认 custom) |
| callback_url | string | 否 | 审核结果回调地址,状态变化时自动 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 |
| status | approved(已通过)/ rejected(已拒绝) |
| reject_info | 拒绝原因(rejected 时有值) |
回调地址需返回 HTTP 2xx,否则视为通知失败。签名由平台「签名管理」统一配置轮换,开发者无需配置;修改/删除模板请到控制台操作。
八、错误码
| code | 说明 |
| 0 | 成功 |
| 401 | 未授权 / API Key 无效或已禁用 |
| 402 | 额度或账户余额不足 |
| 403 | Key 与产品类型不匹配 / IP 不在白名单 / 号码在退订名单 / 国际短信未开通 |
| 404 | 接口不存在,或查询的记录不属于当前账号 |
| 409 | 相同 X-Request-Id 的请求正在处理中(幂等),请勿重复提交 |
| 429 | 触发限流(Key 频次 / 同号频次) |
| 503 | v1 语音通道上游故障维护中(不扣费) |
| 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}
字段说明
| 字段 | 说明 |
| type | login / 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 |
| 403 | Key 类型不是 oauth_login,或 IP 不在白名单 |
| 2001 | provider 不正确(只支持 wechat / alipay / douyin) |
| 2002 | redirect_uri 不正确(必须是完整 http/https 地址) |
| 2004 | 未给该 API Key 配置「回调地址」 |
| 2005 | redirect_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-02 | v1 语音通道暂停(上游故障,返回 503 且不扣额度,请改用 v2) |
| 2026-10-01 | 国际短信改为按「国家/地区单价」从账户余额实时扣费(详见「国际短信费率」) |
接口如有不兼容调整,会在此处同步说明。