通过对比权威数据源,对用户上传的姓名、身份证号、银行卡号、手机号进行验证,校验是否一致 ## 接口说明 该接口返回结果状态分以下两种: - 银行卡认证不通过会返回相应原因,包括信息不一致、身份证格式不正确,银行卡卡号不存在等 - 银行卡认证后通过后会返回对应的认证结果 - 同一信息一天最多校验10次,超过会触发银行风控,导致校验失败 ### 鉴权说明 易盾信息认证服务使用签名方法对接口进行鉴权,所有接口每一次请求都需要包含签名信息(signature参数),以验证用户身份,防止信息被恶意篡改。目前支持MD5,SHA1,SHA256,SM3几种加密算法,详细信息,请参见接口鉴权 (https://support.dun.163.com/documents/391676076156063744?docId=622572798032863232) ## 请求 ### 请求地址 名称 | 值 HTTP URL | http://verify.dun.163.com/v1/bankcard/check (http://verify.dun.163.com/v1/bankcard/check) HTTP Method | POST ### 请求头 名称 | 类型 | 必填 | 描述 Content-Type | String | 是 | 固定值:"application/x-www-form-urlencoded" ### 请求参数 请求参数由请求公共参数和请求业务参数两部分组成,通用参数见请求通用字段 (https://support.dun.163.com/documents/391676076156063744?docId=622573136165068800) 名称 | 类 型 | 必填 | 是否支持加密 | 最大长度 | 描述 bankCardNo | String | 是 | 是 | 32 | 用户银行卡卡号 name | String | 是 | 是 | 32 | 用户真实姓名,以身份证上姓名为准 idCardType | String | 否 | 否 | 32 | 证件类型(默认为身份证),02:军官证,03:护照,05:士兵证,06:内地居民来往港澳通行证,07:台湾同胞来往内地通行证,09: 外国人永久居住证,10:警官证,15:港澳居民来往内地通行证(回乡证),18:台湾居民居住证,19:港澳居民居住证,20:外国护照。 idCardNo | String | 是 | 是 | 18 | 用户身份证号码,目前支持一代/二代身份证,号码必须为18位或15位,末尾为x的需要大写为X phone | String | 否 | 是 | 18 | 用户该银行卡的预留手机号码。 注意:若使用银行卡四要素业务该字段必填否则会调用失败 dataId | String | 否 | 否 | 64 | 数据标识,可传入用户标识等数据,便于数据查询 encryptType | String | 否 | 否 | 否 | 加密方式 "3"-SM4加密 "4"-AES加密(目前只支持SM4加密和AES加密,若添加了此字段,则必须将可加密的字段全部加密,不可只对部分字段加密) ### 请求体示例 Code: bankCardNo=6222123412343569&name=张三&idCardNo=341622123456784317&phone=13358123456&version=v1&businessId=xxx×tamp=1638180222235&nonce=xxx&secretId=xxx&signature=xxx ## 响应 ### 响应结果 响应字段如下,响应通用字段已省略,详细见响应公共字段 (https://support.dun.163.com/documents/391676076156063744?docId=624032228347863040) 名称 | 类型 | 必须返回 | 描述 status | Number | 是 | 认证结果,1-通过 2-不通过(原因见reasonType) 0-待定 reasonType | Number | 否 | 原因详情 2-持卡人信息与输入信息不一致;3-无效卡或者卡号不存在;4-查无此身份证;5-手机号码格式不正确;6-银行卡号不正确;7-其他出错,请联系客服; 8-此卡受限制或状态异常,建议持卡人与发卡行联系;100-交易次数超限或查询过于频繁,请稍后重试 taskId | String | 是 | 本次请求数据标识,可以根据该标识在控制台 (https://dun.163.com/dashboard#/m/idauth/data/auth/)进行数据查询 isPayed | Number | 是 | 本次请求是否收费标识,1代表收费,0代表不收费 ### 响应体示例 Code (json): { "code": 200, "msg": "ok", "result": { "status": 1, "taskId": "xxxxxxxxxxxxxx", "reasonType": 2, "isPayed": 1 } } ### 响应返回码 响应返回码见:响应返回码 (https://support.dun.163.com/documents/391676076156063744?docId=624032338595143680) ## 加密代码示例 ### AES加密代码示例 Code (java): import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.Key; public class AESUtils { /** * 加密 * * @param key 密钥 * @param data 待加密的明文 * @return * @throws Exception */ public static String encrypt(String key, String data) throws Exception { try { Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding"); Key aesKey = getAesKey(key.getBytes(StandardCharsets.UTF_8)); c.init(Cipher.ENCRYPT_MODE, aesKey); byte[] decValue = c.doFinal(data.getBytes(StandardCharsets.UTF_8)); return bytesToHex(decValue); } catch (Exception e) { throw new Exception("encrypt error!", e); } } public static String encrypt(String key, byte[] data) throws Exception { Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding"); Key aesKey = getAesKey(key.getBytes("UTF-8")); c.init(Cipher.ENCRYPT_MODE, aesKey); byte[] bytes = c.doFinal(data); return bytesToHex(bytes); } /** * 解密 * * @param key 密钥 * @param data 待解密的密文 * @return * @throws Exception */ public static byte[] decrypt(String key, String data) throws Exception { try { byte[] decryptData = hexToBytes(data); Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding"); Key aesKey = getAesKey(key.getBytes(StandardCharsets.UTF_8)); c.init(Cipher.DECRYPT_MODE, aesKey); return c.doFinal(decryptData); } catch (Exception e) { throw new Exception("decrypt error!", e); } } private static Key getAesKey(byte[] key) { return new SecretKeySpec(key, "AES"); } private static String bytesToHex(byte[] bArray) { StringBuilder sb = new StringBuilder(bArray.length); String sTemp; for (int i = 0; i < bArray.length; i++) { sTemp = Integer.toHexString(0xFF & bArray[i]); if (sTemp.length() < 2) { sb.append(0); } sb.append(sTemp.toUpperCase()); } return sb.toString(); } private static byte[] hexToBytes(String str) { if (str == null) { return null; } char[] hex = str.toCharArray(); int length = hex.length / 2; byte[] raw = new byte[length]; for (int i = 0; i < length; i++) { int high = Character.digit(hex[i * 2], 16); int low = Character.digit(hex[i * 2 + 1], 16); int value = (high << 4) | low; if (value > 127) { value -= 256; } raw[i] = (byte) value; } return raw; } public static void main(String[] args) throws Exception { String key = "12345678912345678912345678912345"; // 易盾分配的密钥 String data = "12345678912"; // 需要被加密的内容 String enStr = encrypt(key, data);//加密 System.out.println(enStr); } } ### SM4加密代码示例 Code (java): import org.apache.commons.codec.binary.Hex; import org.bouncycastle.jce.provider.BouncyCastleProvider; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.*; import java.security.spec.KeySpec; import java.util.Base64; public class SM4Util { public static final String ALGORITHM_NAME = "SM4"; public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding"; static { Security.addProvider(new BouncyCastleProvider()); } /** * 加密 * * @param data 需要加密的内容 * @param key 密钥 * @return */ public static String encrypt(String data, String key) { try { byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8); Base64.Decoder decoder = Base64.getDecoder(); byte[] keyBytes = decoder.decode(key); SMS4KeySpec sms4KeySpec = new SMS4KeySpec(keyBytes); Cipher cipher = generateECBCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, sms4KeySpec.getKey()); String encodeSource = Hex.encodeHexString(cipher.doFinal(dataBytes)); return encodeSource; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 解密 * * @param encrypted 需要解密的内容 * @param key 密钥 * @return * @throws Exception */ public static String decrypt(String encrypted, String key) throws Exception { byte[] cipherText = Hex.decodeHex(encrypted.toCharArray()); Base64.Decoder decoder = Base64.getDecoder(); byte[] keyBytes = decoder.decode(key); SMS4KeySpec sms4KeySpec = new SMS4KeySpec(keyBytes); Cipher cipher = generateECBCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, sms4KeySpec.getKey()); return new String(cipher.doFinal(cipherText), StandardCharsets.UTF_8); } private static Cipher generateECBCipher(String algorithmName, int mode, byte[] key) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException { Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME); Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME); cipher.init(mode, sm4Key); return cipher; } static class SMS4KeySpec implements KeySpec { private byte[] key; public SMS4KeySpec(byte[] key) throws InvalidKeyException { this(key, 0); } public SMS4KeySpec(byte[] key, int offset) throws InvalidKeyException { if (key.length - offset < 16) { throw new InvalidKeyException("Wrong key size"); } else { this.key = new byte[16]; System.arraycopy(key, offset, this.key, 0, 16); } } public byte[] getKey() { return (byte[]) ((byte[]) this.key.clone()); } } public static void main(String[] args) throws Exception { String key = "12345678912345678912345678912345"; // 易盾分配的密钥 String data = "12345678912"; // 需要被加密的内容 String enStr = encrypt(data, key);//加密 System.out.println(enStr); } }