对接调试一共分为两部分,一部分为安卓应用对接的SDK,另一部分为应用服务器与商米服务器直接的云对接API。
应用软件集成身份证识别sdk,应用软件后端服务器集成云端api(集成云端api用于保护用户身份信息,保证整个数据链路中,只有应用软件可获取身份证明文信息)

1、终端发起身份证请求,并发送身份证卡片信息到应用软件后台服务器
2、服务器验证卡片真伪,如果为真,返回reqid
3、应用软件收到reqid后,把reqid发送给应用后台服务器
4、应用后台服务器通过openapi把数据发送给商米服务器
5、商米服务器向解码服务器请求解析身份证信息
6、身份证解码服务器返回身份证全部信息的加密数据
7、商米服务器将加密数据返回应用软件后台服务器
8、应用软件服务器解密加密数据后,得到身份证明文数据
9、将明文数据返回应用软件
注:身份证云识别依赖网络,要求每次网络交互过程不得超过200ms,数据交互延迟高于110ms会降低解码成功率(sdk返回9100X错误),高于200ms会造成读卡失败。使用前请确定网络环境满足要求,sdk提供了延迟检测接口,用户可使用延迟检测接口测试网络。不建议使用物联网卡。
1、APP设计和开发
APP设计
APP设计注意要点:android NFC或者读卡器识别到卡片后会有声音提示,身份证读卡操作是个耗时操作,当声音提示后,不能直接拿走卡片,需要等到读卡成功或者失败再拿开卡片。界面上需要提示用户在有明确反馈前不要拿走卡片,建议:loading+文字提示
APP开发
身份证云识别的Android SDK 的集成、初始化、使用流程、网络延迟检测等。
应用发布前,请确保现场网络环境已达要求,否则将影响识别成功率。
1.1、集成
- 资源文件(AAR文件)
1.2、导入AAR包
- 打开项目后:File -> New -> New Module…

- 在新的对话框:New Module -> Import .JAR/.AAR Package -> Next

- 下一步:Import Module from Library -> 选择 aar 文件夹下的 SunmiEID-SDK_vX.X.X-release/tes.aar 文件 -> Finish

- 完成:

1.3、app 模块引用
- 点击-打开模块设置:

- 设置对话框:选择“app” -> 点击“+”号 -> 选择“Module Dependency”

- 显示:勾选上对应的模块(SunmiEID-SDK_vX.X.X-release/tes)-> 点击“OK”,相关SDK引用成功。

1.4、接口文档
1.4.1、初始化
- 推荐在Application实现SDK初始化实现:
public class IApp extends Application implements EidCall {
@Override
public void onCreate() {
super.onCreate();
try {
EidSDK.init(this, "appid", this);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onTerminate() {
super.onTerminate();
EidSDK.destroy();
}
@Override
public void onCallData(int code, String msg) {
Log.d("app", "onCallData: code:" + code + ", msg:" + msg);
}
}
1.4.2、获取 EidReader 实例
private void initEidReader() {
Log.d("Eid", String.format("商米SDK.Ver:%s, 读卡模块Ver:%s", EidSDK.getSunmiEidSDKVersion(), EidSDK.getEidSDKVersion()));
EidPic.init(this, fileNameBase);
eid = EidSDK.getEidReaderForNfc(1, this);
}
1.4.3、实现 EidCall 接口
@Override
public void onCallData(int code, String msg) {
switch (code) {
case EidConstants.READ_CARD_START:
mState.setText("开始读卡,请勿移动");
Log.i(TAG, "开始读卡,请勿移动");
break;
case EidConstants.READ_CARD_SUCCESS:
closeNFCReader();//电子身份证需要关闭
Log.e("TAG", String.format(Locale.getDefault(), "正在获取身份信息(%s),请稍等.....", msg));
mState.setText(String.format(Locale.getDefault(), "正在获取身份信息(%s),请稍等.....", msg));
File file = new File(fileNameBase, "zp.bmp");
if (file.exists()) {
file.deleteOnExit();
}
getIDCardInfo(msg); //通过card_id请求识读卡片的信息
break;
case EidConstants.READ_CARD_FAILED:
closeNFCReader();//电子身份证需要关闭
Log.i(TAG, String.format(Locale.getDefault(), "读卡错误,请重新贴卡:%s", msg));
mState.setText(String.format(Locale.getDefault(), "读卡错误,请重新贴卡:%s", msg));
break;
case EidConstants.READ_CARD_DELAY:
Log.e("TAG", String.format(Locale.getDefault(), "延迟 %sms", msg));
mState.setText(String.format(Locale.getDefault(), "延迟 %sms", msg));
break;
default:
break;
}
}
1.4.4、调用NFC识读卡片
- 识读身份证:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
eid.nfcReadCard(intent);
}
- 识读电子身份证:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
try {
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
try {
isodep = IsoDep.get(tagFromIntent);
isodep.connect();
if (isodep.isConnected()) {
eid.readCard(IDCardType.ECCARD, new EidReadCardCallBack() {
@Override
public byte[] transceiveTypeB(byte[] data) {
return data;
}
@Override
public byte[] transceiveTypeA(byte[] data) {
byte[] outData = new byte[data.length];
try {
outData = isodep.transceive(data);
} catch (Exception e) {
e.printStackTrace();
}
return outData;
}
});
} else {
closeNFCReader()
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void closeNFCReader() {
if (isodep != null) {
try {
isodep.close();
isodep = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
1.5、NFC、金融设备读卡及动态授权相关
- 详细处理参考:EidCardDemo
- 直连商米 Open Api 接口:EidCardDemo-OpenApi (直连商米open api服务器,不推荐使用该方式,该用法可能会导致appid与appkey同时泄漏,造成损失将由应用商自己承担)
1.6、详细接口说明
- 详细接口文档:
1.7、错误码ErrorCode

2、身份证服务 API 接口
2.1、公共参数说明
2.1.1、概要
请求地址:https://openapi.sunmi.com
应用服务器demo:
商米身份证服务的接口采用 HTTPS 协议,参数通过 form 方式传递,使用 POST 方式发送到请求地址。
- 商米身份证服务的接口采用 HTTPS 协议
- 参数通过 form 方式传递,返回结果为 JSON 格式
- 接口只支持 POST 方式请求
- HTTP header 设为 application/x-www-form-urlencoded;charset=utf-8
2.1.2、公共参数说明
- 每个接口请求参数包括公共参数和私有参数
- 返回结果均为 JSON 格式
请求公共参数
参数名 | 类型 | 说明 |
sign | string | 签名(32位大写),参考签名生成方式 |
app_id | string | 商米提供的 app_id |
返回公共参数
参数名 | 类型 | 说明 |
code | string | 返回码,参见常用错误码表 |
data | object | 正常返回,如有错误不返回 |
msg | string | 错误提示信息,如有错误此字段返回错误描述 |
2.1.3、签名生成说明
签名算法:MD5
签名生成方式:
- 参数名称 ASCII 字典顺序排序(sign 除外)
- 以键值对的方式拼接(即 key1=value1&key2=value2&key3=value3)
- 拼接 app_key 到字符串最后(即 key1=value1&key2=value2&key3=value3$appkey)
- 对字符串进行 MD5 加密得到最终的 sign 值(32位大写)
2.1.4、常见错误码
返回码 | 说明 |
10000 | 成功返回 |
20001 | 授权失败 |
20002 | 服务不可用 |
40001 | 缺少必要参数 |
40002 | 非法参数 |
2.2、身份证云识别接口
- 接口地址:/v1/eid/decode
- 请求方式:POST
2.2.1、请求参数
参数名 | 类型 | 说明 |
app_id | string | 商米提供的 app_id |
sign | string | 签名(32位大写),参考签名生成方式 |
request_id | string | android端生成的 request_id |
encrypt_factor | string | 加密因子(8 位大小写字母和数字组成的的随机字符串,建议每次访问随机生成) |
2.2.2、返回参数
成功返回
参数名 | 类型 | 说明 |
code | string | 返回码,参见常用错误码表 |
data | object | 返回身份证信息,参见下方 data 域内容 |
msg | string | 错误提示信息,如有错误此字段返回错误描述 |
成功返回 data 域内容
参数名 | 类型 | 说明 |
info | string | 身份证信息密文,解密方式参见解密说明 |
示例:
{
"code": "10000",
"data": {
"info": "xxxxxxxxxxxxx"
},
"msg": ""
}
失败返回
参数名 | 类型 | 说明 |
code | string | 返回码,参见常用错误码表 |
data | object | 错误返回时,包含业务错误信息,参见下方 data 域内容 |
msg | string | 错误提示信息,如有错误此字段返回错误描述 |
失败返回 data 域内容
参数名 | 类型 | 说明 |
sub_code | string | 业务错误码 |
sub_msg | string | 业务错误返回信息 |
示例:
{
"code": "10000",
"data": {
"sub_code": "50001",
"sub_msg": "xxxxxxxxxx"
},
"msg": ""
}
2.2.3、解密说明
- 加密方式:DES_CBC_PKCS5Padding 加密
- 加密因子:传入的 encrypt_factor
解密流程:
- 对 info 字符串 base64 解码(standard 标准解码),解码完为 stringA
- 对 stringA 字符串进行 des 解密,密钥 key 和向量 iv 均为 encrypt_factor 加密因子,解密完为 stringB
- stringB 即是身份证信息的 json 格式,内容参见下方身份证云解码信息
身份证云解码信息:
参数名 | 类型 | 说明 |
base_info | object | 身份证基础信息,参见下方身份证基础信息说明 |
dn | string | 指纹信息 |
picture | string | 身份证头像照片 |
appeidcode | string | 应用网络身份标记,同一个身份有一个编码 |
身份证基础信息:
参数名 | 类型 | 说明 |
name | string | 姓名 |
nation | string | 民族(如:汉) |
sex | string | 性别(如:男) |
idnum | string | 身份证号码 |
idType | string | 证件类型,见下方证件类型说明 |
birthDate | string | 出生年月日(如:20010305) |
address | string | 身份证住址 |
beginTime | string | 身份证有效期限开始时间(如:20180305) |
endTime | string | 身份证有效期限结束时间(如:20180305) |
signingOrganization | string | 签发机关 |
示例:
"base_info": {
"address": "xx省xx市xxxx路xx号",
"beginTime": "20180305",
"endTime": "20180305",
"birthDate": "20010305",
"idType": "01",
"idnum": "xxxxxxx",
"name": "孙小红",
"nation": "汉",
"sex": "男",
"signingOrganization": "xx市xx公安局"
},
"dn": "xxxxxxxxxx",
"picture": "xxxxxxxxx",
"appeidcode": "xxxxxxxxx",