一、接口总览

API 总入口:POST /api/ocr/{apicode},请求与响应均为 JSON。所有识别接口按次消耗积分。

通用识别

接口编码接口名称接口地址积分/次状态
sfz身份证识别/api/ocr/sfz1已上线
yhk银行卡识别/api/ocr/yhk1已上线
xsz行驶证识别/api/ocr/xsz1已上线
jsz驾驶证识别/api/ocr/jsz1已上线
yyzz营业执照识别/api/ocr/yyzz1已上线
mp名片识别/api/ocr/mp1已上线
jdcdjz机动车登记证书识别/api/ocr/jdcdjz1已上线

专用类别

接口编码接口名称接口地址积分/次状态
jzxwx集装箱尾箱识别/api/ocr/jzxwx1已上线

二、公共参数

每次调用需在请求体 JSON 中携带以下公共参数:

参数类型必填说明
SecretIdstring调用者身份标识,个人中心获取
timestampstringUnix 秒级时间戳,与服务器时间偏差超过 300 秒将被拒绝
signstring请求签名,见下文签名算法
imagestring二选一图片 base64 字符串(可带 data:image/xxx;base64, 前缀)
imageUrlstring二选一图片 http(s) 访问地址

注意:所有参数值一律为字符串;除 sign 外的全部参数(含公共参数与业务参数)均参与签名。

三、签名算法

步骤 1:参数排序

取全部请求参数(sign 除外),按参数名的 ASCII 码字典序升序排序。只按参数名排序,参数值保持对应即可,不参与比较大小。

步骤 2:拼接签名原文

将排序后的参数拼接为 key1=value1&key2=value2&... 形式(参数名与参数值原样拼接,不做 URL 编码)。

步骤 3:HMAC-SHA1 + Base64

以 SecretKey 作为密钥,对签名原文使用 HMAC-SHA1 算法计算摘要,再对摘要结果做 Base64 编码,得到 sign。

# 伪代码
params = {SecretId, timestamp, 业务参数...}   # 不含 sign
keys = sort_by_ascii(params.keys())
plain = '&'.join(k + '=' + params[k] for k in keys)
sign = base64(hmac_sha1(key=SecretKey, message=plain))

四、请求示例

Python

import time, hmac, hashlib, base64, json, requests

SECRET_ID = '你的SecretId'
SECRET_KEY = '你的SecretKey'

def sign(params, secret_key):
    items = sorted((k, v) for k, v in params.items() if k != 'sign')
    plain = '&'.join(f'{k}={v}' for k, v in items)
    return base64.b64encode(hmac.new(secret_key.encode(),
        plain.encode(), hashlib.sha1).digest()).decode()

params = {
    'SecretId': SECRET_ID,
    'timestamp': str(int(time.time())),
    'image': 'data:image/jpeg;base64,/9j/4AAQ...'   # 图片base64
}
params['sign'] = sign(params, SECRET_KEY)

resp = requests.post('https://ocr.jmdz.online/api/ocr/sfz', json=params)
print(resp.json())

Java

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.*;

Map<String, Object> params = new HashMap<>();
params.put("SecretId", "你的SecretId");
params.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
params.put("image", "data:image/jpeg;base64,/9j/4AAQ...");

String plain = params.entrySet().stream()
        .filter(e -> !"sign".equals(e.getKey()) && e.getValue() != null)
        .sorted(Map.Entry.comparingByKey())
        .map(e -> e.getKey() + "=" + e.getValue())
        .reduce((a, b) -> a + "&" + b).orElse("");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), "HmacSHA1"));
String sign = Base64.getEncoder().encodeToString(mac.doFinal(plain.getBytes(StandardCharsets.UTF_8)));
params.put("sign", sign);

五、响应说明

识别成功时返回:

{
  "code": 0,
  "message": "识别成功",
  "data": {
    "SecretId": "S-XXXX...",
    "timestamp": "20260913223000",
    "requestId": "uuid",
    "points": 999,
    "name": "张三",
    "sex": "男",
    "idNumber": "350102199001011234",
    "sign": "Base64(HMAC-SHA1)"   # 响应签名:覆盖 data 中除 sign 外的全部字段
  }
}

data 中的业务字段随接口类型不同而不同(身份证:name/sex/nation/birth/address/idNumber/issuedBy/validDate)。响应签名规则与请求一致:将 data 内除 sign 外字段按 ASCII 排序拼接后,用 SecretKey 做 HMAC-SHA1 再 Base64,可与返回值中的 sign 比对,用于校验响应确由本平台返回。

六、错误码

code说明
0识别成功
4001积分不足,请先充值
4002接口未开通
4003签名校验失败
4004参数错误(缺少公共参数 / JSON 非法 / 图片无效)
4005timestamp 已过期
4006识别失败
4007认证失败(SecretId 无效或账号被禁用)
401Web 端未登录(仅个人中心接口使用)
500系统繁忙

七、积分与限额