实名认证平台提供标准 RESTful API,支持二要素身份校验、人脸核身和企业三要素认证三大核心能力,以及邮件推送通信服务。本文档将帮助您快速完成 API 对接。
| 项目 | 说明 |
|---|---|
| 接口地址 | https://sms.sumingyun.cn/api/{action} |
| 请求方式 | POST |
| 数据格式 | 请求:application/x-www-form-urlencoded,响应:application/json |
| 字符编码 | UTF-8 |
| 签名算法 | MD5 |
| 时间窗口 | 请求 timestamp 与服务器时间差不超过 ±300 秒 |
所有接口(除特殊说明外)均需携带以下公共参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
appid | string | 是 | 应用 AppID,在控制台创建应用后获取 |
timestamp | string | 是 | Unix 时间戳(秒级),与服务器时间差不超过 300 秒 |
nonce | string | 是 | 随机字符串,建议 16-32 位,防重放攻击 |
sign | string | 是 | 请求签名,算法见下方签名认证章节 |
{
"code": 0,
"msg": "success",
"data": { ... }
}
系统支持两种 URL 格式访问 API,效果完全一致:
https://sms.sumingyun.cn/api/{action}
需要 Nginx 配置 try_files 伪静态规则,路径更简洁美观。
https://sms.sumingyun.cn/?route=api/{action}
无需任何服务器配置即可使用,兼容性最佳。
所有 API 请求必须携带签名参数,用于验证请求合法性。签名算法如下:
appid、timestamp、nonce、appsecret 四个值按顺序拼接为一个字符串sign = md5(appid + timestamp + nonce + appsecret)
// 假设参数如下: appid = "app_abc123" timestamp = "1700000000" nonce = "a1b2c3d4e5f6" appsecret = "secret_xyz789" // 拼接字符串: raw = "app_abc1231700000000a1b2c3d4e5f6secret_xyz789" // MD5 哈希: sign = md5(raw) = "e10adc3949ba59abbe56e057f20f883e"
appsecret 仅用于服务端签名计算,切勿在客户端代码或前端页面中暴露。
可在控制台为应用配置 IP 白名单。配置后,仅白名单内的 IP 可调用该应用的 API。白名单为空时不做限制。
当请求失败时,响应中的 code 字段为非零值。以下是完整的错误码列表:
| 错误码 | 含义 | 说明 |
|---|---|---|
| 0 | 成功 | 请求处理成功 |
| 1001 | 签名校验失败 | sign 参数不正确,请检查签名算法和 appsecret |
| 1002 | IP 受限 | 请求 IP 不在应用白名单中 |
| 1003 | 请求频率超限 | 触发速率限制,请降低请求频率 |
| 1004 | 应用无效 | AppID 不存在、应用已停用、未通过审核或账号被封禁 |
| 2001 | 余额不足 | 账户余额不足以支付本次调用费用 |
| 2002 | 参数错误 | 缺少必要参数或参数格式不正确 |
| 2003 | 服务未启用 | 企业三要素认证等增值服务未启用,请联系管理员 |
| 3001 | 上游接口异常 | 百度云等上游服务调用失败 |
| 3002 | 认证失败 | 身份校验未通过(姓名与身份证号不匹配等) |
| 3003 | 等待中 | 人脸核身场景下,用户尚未完成操作 |
校验姓名与身份证号是否匹配,实时调用百度云二要素认证接口。
https://sms.sumingyun.cn/api/check2factor
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
appid | string | 是 | 应用 AppID |
timestamp | string | 是 | Unix 时间戳 |
nonce | string | 是 | 随机字符串 |
sign | string | 是 | 请求签名 |
real_name | string | 是 | 真实姓名 |
id_card | string | 是 | 身份证号码(18 位) |
out_order_no | string | 是 | 商户订单号,用于对账和防重复提交 |
{
"code": 0,
"msg": "认证成功",
"data": {
"score": 100
}
}
{
"code": 3002,
"msg": "认证失败",
"data": null
}
校验企业名称、统一社会信用代码与法人姓名三要素是否一致,适用于企业入驻审核、供应商资质核验等 B 端场景。
https://sms.sumingyun.cn/api/check_enterprise_3factor
2003。
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
appid | string | 是 | 应用 AppID |
timestamp | string | 是 | Unix 时间戳 |
nonce | string | 是 | 随机字符串 |
sign | string | 是 | 请求签名 |
company_name | string | 是 | 企业名称 |
credit_code | string | 是 | 统一社会信用代码(18 位) |
legal_person | string | 是 | 法定代表人姓名 |
out_order_no | string | 是 | 商户订单号,用于对账和防重复提交 |
{
"code": 0,
"msg": "企业三要素验证一致",
"data": {
"creditNo": true,
"companyName": true,
"legalPerson": true
}
}
{
"code": 3002,
"msg": "企业三要素验证不一致",
"data": {
"creditNo": true,
"companyName": true,
"legalPerson": false
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
creditNo | boolean | 信用代码是否匹配 |
companyName | boolean | 企业名称是否匹配 |
legalPerson | boolean | 法人姓名是否匹配 |
true 时返回 code: 0,任一字段为 false 时返回 code: 3002。无论验证结果如何,均会产生调用费用。
创建一个人脸核身会话,返回人脸采集页面 URL。将该 URL 发送给终端用户,用户在页面上完成人脸采集后,通过查询结果接口获取核身结果。
https://sms.sumingyun.cn/api/face_init
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
appid | string | 是 | 应用 AppID |
timestamp | string | 是 | Unix 时间戳 |
nonce | string | 是 | 随机字符串 |
sign | string | 是 | 请求签名 |
real_name | string | 是 | 真实姓名 |
id_card | string | 是 | 身份证号码(18 位) |
out_order_no | string | 是 | 商户订单号 |
{
"code": 0,
"msg": "人脸核身会话创建成功",
"data": {
"verify_url": "https://sms.sumingyun.cn/?route=api/face_capture&token=xxxx",
"verify_id": "xxxx",
"log_id": 123
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
verify_url | string | 人脸采集页面地址,需发送给终端用户在浏览器中打开 |
verify_id | string | 核身会话标识,查询结果时使用 |
log_id | int | 认证记录 ID,查询结果时使用 |
verify_url 需要在移动端浏览器中打开(需要调用摄像头)。建议通过短信、微信等方式将链接发送给用户。
查询人脸核身会话的处理结果。建议在创建会话后轮询此接口(间隔 3-5 秒),直到获取到最终结果。
https://sms.sumingyun.cn/api/face_result
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
appid | string | 是 | 应用 AppID |
timestamp | string | 是 | Unix 时间戳 |
nonce | string | 是 | 随机字符串 |
sign | string | 是 | 请求签名 |
verify_id | string | 是 | 核身会话标识(face_init 返回的 verify_id) |
log_id | int | 是 | 认证记录 ID(face_init 返回的 log_id) |
{
"code": 0,
"msg": "人脸核身通过",
"data": {
"score": 80
}
}
{
"code": 3002,
"msg": "人脸核身未通过",
"data": null
}
{
"code": 3003,
"msg": "用户尚未完成人脸核身",
"data": null
}
code: 3003 表示用户尚未完成人脸采集,请继续轮询。建议设置最大轮询时间为 5 分钟,超时后提示用户重新发起。
人脸核身采用异步模式,完整对接流程如下:
服务端携带 real_name、id_card、out_order_no 调用 /api/face_init,获取 verify_url、verify_id、log_id。
通过短信、微信、App 内嵌 WebView 等方式将人脸采集链接发送给用户。
用户在浏览器中打开链接,授权摄像头,完成活体检测和人脸拍照。系统自动将人脸照片与身份证信息进行比对。
服务端以 3-5 秒间隔轮询 /api/face_result,传入 verify_id 和 log_id。当 code 为 0(通过)或 3002(未通过)时停止轮询。
根据核身结果执行后续业务操作(如开通服务、完成注册等)。
查询当前应用配置的认证模式。可用于客户端动态判断应该调用二要素还是人脸核身接口。
https://sms.sumingyun.cn/api/verify_mode
仅需携带公共参数(appid、timestamp、nonce、sign),无额外业务参数。
{
"code": 0,
"msg": "ok",
"data": {
"mode": "2factor"
}
}
| 值 | 说明 |
|---|---|
2factor | 二要素身份校验(姓名 + 身份证号) |
face | 人脸核身(姓名 + 身份证号 + 人脸比对) |
enterprise_3factor | 企业三要素认证(企业名称 + 信用代码 + 法人姓名) |
<?php function callApi(string $action, array $params): array { $appId = 'your_app_id'; $appSecret = 'your_app_secret'; $timestamp = (string)time(); $nonce = bin2hex(random_bytes(16)); $sign = md5($appId . $timestamp . $nonce . $appSecret); $data = array_merge([ 'appid' => $appId, 'timestamp' => $timestamp, 'nonce' => $nonce, 'sign' => $sign, ], $params); $ch = curl_init("https://sms.sumingyun.cn/api/{$action}"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query($data), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, ]); $resp = curl_exec($ch); curl_close($ch); return json_decode($resp, true) ?: []; } // 二要素校验 $result = callApi('check2factor', [ 'real_name' => '张三', 'id_card' => '110101199001011234', 'out_order_no' => 'ORDER_001', ]); print_r($result);
import java.security.MessageDigest; import java.net.http.*; import java.net.URI; import java.util.UUID; public class ApiClient { private static final String APP_ID = "your_app_id"; private static final String APP_SECRET = "your_app_secret"; private static final String BASE_URL = "https://sms.sumingyun.cn/api/"; public static 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(); } public static String check2factor(String realName, String idCard, String orderNo) throws Exception { String timestamp = String.valueOf(System.currentTimeMillis() / 1000); String nonce = UUID.randomUUID().toString().replace("-", ""); String sign = md5(APP_ID + timestamp + nonce + APP_SECRET); String body = "appid=" + APP_ID + "×tamp=" + timestamp + "&nonce=" + nonce + "&sign=" + sign + "&real_name=" + java.net.URLEncoder.encode(realName, "UTF-8") + "&id_card=" + idCard + "&out_order_no=" + orderNo; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(BASE_URL + "check2factor")) .header("Content-Type", "application/x-www-form-urlencoded") .POST(HttpRequest.BodyPublishers.ofString(body)) .build(); HttpResponse<String> resp = client.send(request, HttpResponse.BodyHandlers.ofString()); return resp.body(); } }
import hashlib, time, uuid, requests APP_ID = 'your_app_id' APP_SECRET = 'your_app_secret' BASE_URL = 'https://sms.sumingyun.cn/api/' def call_api(action: str, params: dict) -> dict: timestamp = str(int(time.time())) nonce = uuid.uuid4().hex sign = hashlib.md5( (APP_ID + timestamp + nonce + APP_SECRET).encode() ).hexdigest() data = { 'appid': APP_ID, 'timestamp': timestamp, 'nonce': nonce, 'sign': sign, **params, } resp = requests.post(BASE_URL + action, data=data, timeout=30) return resp.json() # 二要素校验 result = call_api('check2factor', { 'real_name': '张三', 'id_card': '110101199001011234', 'out_order_no': 'ORDER_001', }) print(result)
const crypto = require('crypto'); const { URLSearchParams } = require('url'); const APP_ID = 'your_app_id'; const APP_SECRET = 'your_app_secret'; const BASE_URL = 'https://sms.sumingyun.cn/api/'; async function callApi(action, params) { const timestamp = String(Math.floor(Date.now() / 1000)); const nonce = crypto.randomBytes(16).toString('hex'); const sign = crypto.createHash('md5') .update(APP_ID + timestamp + nonce + APP_SECRET) .digest('hex'); const body = new URLSearchParams({ appid: APP_ID, timestamp, nonce, sign, ...params, }); const resp = await fetch(BASE_URL + action, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: body.toString(), }); return resp.json(); } // 二要素校验 callApi('check2factor', { real_name: '张三', id_card: '110101199001011234', out_order_no: 'ORDER_001', }).then(console.log);
平台采用预付费 + 按次扣费模式:
| 接口 | 说明 | 计费规则 |
|---|---|---|
check2factor | 二要素身份校验 | 按次计费,单价由管理员在后台配置 |
check_enterprise_3factor | 企业三要素认证 | 按次计费,单价由管理员在后台配置 |
face_init | 人脸核身 | 按次计费,单价由管理员在后台配置 |
face_result | 查询核身结果 | 免费,不产生费用 |
verify_mode | 查询认证模式 | 免费,不产生费用 |
SMTP 邮件推送服务采用独立计费模式,按发送邮件数量计费:
| 服务 | 说明 | 计费规则 |
|---|---|---|
| SMTP 邮件推送 | 通过 SMTP 协议发送邮件 | 按封计费,单价由管理员在后台配置 |
2001,请确保账户余额充足。
| 日期 | 版本 | 更新内容 |
|---|---|---|
| 2026-02-28 | v1.3 | 新增企业三要素认证接口(check_enterprise_3factor),新增 SMTP 邮件推送计费说明,verify_mode 新增 enterprise_3factor 模式 |
| 2026-02-24 | v1.2 | 新增卡密充值功能,新增 Node.js 签名示例,完善人脸核身对接时序文档 |
| 2026-02-23 | v1.1 | 新增人脸核身接口(face_init / face_result),新增 verify_mode 接口 |
| 2026-02-20 | v1.0 | 初始版本,支持二要素身份校验 |