天音实名认证 · API 文档

天音实名认证 API 文档

天音实名认证平台提供标准 RESTful API,支持二要素身份校验和人脸核身两大核心能力。本文档将帮助您快速完成 API 对接。

接口概述

基础信息

项目说明
接口地址https://您的域名/?route=api/{action}
请求方式POST
数据格式请求:application/x-www-form-urlencoded,响应:application/json
字符编码UTF-8
签名算法MD5
时间窗口请求 timestamp 与服务器时间差不超过 ±300 秒

通用请求参数

所有接口(除特殊说明外)均需携带以下公共参数:

参数名类型必填说明
appidstring应用 AppID,在控制台创建应用后获取
timestampstringUnix 时间戳(秒级),与服务器时间差不超过 300 秒
noncestring随机字符串,建议 16-32 位,防重放攻击
signstring请求签名,算法见下方签名认证章节

通用响应格式

{
    "code": 0,          // 0 表示成功,非 0 为错误码
    "msg": "success",   // 结果描述
    "data": { ... }     // 业务数据,失败时可能为 null
}

签名认证

所有 API 请求必须携带签名参数,用于验证请求合法性。签名算法如下:

签名生成规则

签名公式:sign = md5(appid + timestamp + nonce + appsecret)
将 appid、timestamp、nonce、appsecret 四个字符串按顺序直接拼接,然后取 MD5 哈希值(32 位小写)。

签名步骤

  1. 获取当前 Unix 时间戳(秒级)作为 timestamp
  2. 生成一个随机字符串作为 nonce(建议 16-32 位字母数字)
  3. appid + timestamp + nonce + appsecret 拼接成一个字符串
  4. 对拼接后的字符串计算 MD5,得到 32 位小写哈希值即为 sign

示例

// 假设参数如下:
appid     = "a1b2c3d4e5f6g7h8"
timestamp = "1700000000"
nonce     = "abcdef1234567890"
appsecret = "s3cr3tk3y1234567890abcdef12345678"

// 拼接字符串:
raw = "a1b2c3d4e5f6g7h81700000000abcdef1234567890s3cr3tk3y1234567890abcdef12345678"

// 计算 MD5:
sign = md5(raw) = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
注意:AppSecret 仅用于服务端签名计算,严禁在客户端(浏览器、APP)中暴露。所有 API 调用必须从您的服务端发起。

错误码

错误码含义说明
0成功请求处理成功
1001签名校验失败sign 参数错误或 timestamp 超出有效窗口
1002IP 受限请求 IP 不在应用白名单中
1003请求频率限制请求过于频繁,请稍后重试
1004应用无效AppID 不存在、应用已停用或账号被封禁
2001余额不足账户余额不足且无可用流量包
2002参数错误缺少必要参数或参数格式不正确
3001上游接口异常认证服务商接口调用失败
3002认证失败身份信息不匹配或人脸核身未通过
3003等待中用户尚未完成人脸核身操作

二要素身份校验

通过姓名和身份证号实时比对权威数据库,验证身份信息是否一致。

POST /?route=api/check2factor

请求参数

参数名类型必填说明
appidstring应用 AppID
timestampstringUnix 时间戳(秒)
noncestring随机字符串
signstring请求签名
real_namestring真实姓名
id_cardstring身份证号码(18位)
out_order_nostring外部订单号,由调用方生成,用于对账

成功响应

{
    "code": 0,
    "msg": "认证成功",
    "data": {
        "score": 100
    }
}

失败响应

{
    "code": 3002,
    "msg": "认证失败",
    "data": null
}
计费说明:调用成功(code=0)时扣费,调用失败不扣费。优先消耗流量包额度,流量包用完后从余额扣除。

人脸核身 - 创建会话

创建一个人脸核身会话,获取人脸采集页面 URL。将该 URL 提供给终端用户在浏览器中打开,完成活体检测和人脸比对。

POST /?route=api/face_init

请求参数

参数名类型必填说明
appidstring应用 AppID
timestampstringUnix 时间戳(秒)
noncestring随机字符串
signstring请求签名
real_namestring真实姓名
id_cardstring身份证号码(18位)
out_order_nostring外部订单号

成功响应

{
    "code": 0,
    "msg": "人脸核身会话创建成功",
    "data": {
        "verify_url": "https://您的域名/?route=api/face_capture&token=xxx",
        "verify_id": "xxxxxxxxxxxxxxxx",
        "log_id": 123
    }
}

对接流程

  1. 服务端调用本接口,获取 verify_urlverify_idlog_id
  2. verify_url 返回给前端,引导用户在浏览器中打开(支持 H5 / 微信内置浏览器)
  3. 用户完成人脸采集后,服务端轮询「查询结果」接口获取核身结果
人脸核身会话有效期为 5 分钟,超时未完成将自动退款。请在创建会话后及时引导用户完成操作。

人脸核身 - 查询结果

查询人脸核身会话的处理结果。建议在创建会话后,以 2-3 秒间隔轮询本接口。

POST /?route=api/face_result

请求参数

参数名类型必填说明
appidstring应用 AppID
timestampstringUnix 时间戳(秒)
noncestring随机字符串
signstring请求签名
verify_idstring人脸核身会话 ID(face_init 返回的 verify_id)
log_idint认证记录 ID(face_init 返回的 log_id)

响应状态

code含义说明
0核身通过人脸比对成功,data 中包含 score
3002核身未通过人脸比对失败
3003等待中用户尚未完成人脸采集,请继续轮询

成功响应

{
    "code": 0,
    "msg": "人脸核身通过",
    "data": {
        "score": 80
    }
}

查询认证模式

查询当前应用配置的认证模式,用于前端动态展示对应的认证流程。

POST /?route=api/verify_mode

请求参数

仅需公共参数(appid, timestamp, nonce, sign),无额外业务参数。

成功响应

{
    "code": 0,
    "msg": "ok",
    "data": {
        "mode": "2factor"   // 可选值: 2factor | face | both
    }
}
mode 值说明
2factor仅二要素校验
face仅人脸核身
both二要素 + 人脸核身

签名示例代码

PHP

<?php
function callApi(string $url, string $appId, string $appSecret, array $params): array
{
    $timestamp = (string)time();
    $nonce = bin2hex(random_bytes(16));
    $sign = md5($appId . $timestamp . $nonce . $appSecret);

    $postData = array_merge($params, [
        'appid'     => $appId,
        'timestamp' => $timestamp,
        'nonce'     => $nonce,
        'sign'      => $sign,
    ]);

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => http_build_query($postData),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 10,
        CURLOPT_SSL_VERIFYPEER => true,
    ]);
    $response = curl_exec($ch);
    curl_close($ch);

    return json_decode($response, true) ?: [];
}

// 调用二要素校验
$result = callApi(
    'https://您的域名/?route=api/check2factor',
    '您的AppID',
    '您的AppSecret',
    [
        'real_name'    => '张三',
        'id_card'      => '110101199001011234',
        'out_order_no' => 'ORDER_' . time(),
    ]
);
print_r($result);

Java

import java.net.http.*;
import java.security.MessageDigest;
import java.util.UUID;

public class TianyinClient {
    private final String appId;
    private final String appSecret;
    private final String baseUrl;

    public TianyinClient(String baseUrl, String appId, String appSecret) {
        this.baseUrl = baseUrl;
        this.appId = appId;
        this.appSecret = appSecret;
    }

    public String check2Factor(String realName, String idCard, String outOrderNo) throws Exception {
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        String nonce = UUID.randomUUID().toString().replace("-", "");
        String sign = md5(appId + timestamp + nonce + appSecret);

        String body = "appid=" + appId
            + "×tamp=" + timestamp
            + "&nonce=" + nonce
            + "&sign=" + sign
            + "&real_name=" + URLEncoder.encode(realName, "UTF-8")
            + "&id_card=" + idCard
            + "&out_order_no=" + outOrderNo;

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + "/?route=api/check2factor"))
            .header("Content-Type", "application/x-www-form-urlencoded")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());
        return response.body();
    }

    private String md5(String input) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] digest = md.digest(input.getBytes("UTF-8"));
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) sb.append(String.format("%02x", b));
        return sb.toString();
    }
}

Python

import hashlib, time, secrets, requests

class TianyinClient:
    def __init__(self, base_url, app_id, app_secret):
        self.base_url = base_url
        self.app_id = app_id
        self.app_secret = app_secret

    def _sign(self, timestamp, nonce):
        raw = self.app_id + timestamp + nonce + self.app_secret
        return hashlib.md5(raw.encode()).hexdigest()

    def check_2factor(self, real_name, id_card, out_order_no):
        timestamp = str(int(time.time()))
        nonce = secrets.token_hex(16)
        sign = self._sign(timestamp, nonce)

        resp = requests.post(
            f"{self.base_url}/?route=api/check2factor",
            data={
                "appid": self.app_id,
                "timestamp": timestamp,
                "nonce": nonce,
                "sign": sign,
                "real_name": real_name,
                "id_card": id_card,
                "out_order_no": out_order_no,
            },
            timeout=10
        )
        return resp.json()

# 使用示例
client = TianyinClient("https://您的域名", "您的AppID", "您的AppSecret")
result = client.check_2factor("张三", "110101199001011234", f"ORDER_{int(time.time())}")
print(result)

更新日志

日期版本更新内容
2026-02-23v1.0发布二要素身份校验、人脸核身、查询认证模式接口