银行卡四要素详版接口文档
所有文档
menu

号码认证服务 PNVS

银行卡四要素详版接口文档

产品详情立即开通

接口描述

本文档为银行卡四要素详版接口文档

接口地址

见已购列表

返回格式:json

请求方式:post

接口签名说明

准备签名参数字符串str_for_sign:

请求参数按参数名字典排序(字典序)后,按name1=value1&name2=value2&… 字典序:在英文字典中,排列单词的顺序是先按照第一个字母以升序排列(即a、b、c……z 的顺序);如果第一个字母一样,那么比较第二个、第三个乃至后面的字母。如果比到最后两个单词不一样长(比如,sigh 和 sight),那么把短者排在前。

准备签名参数字符串paramEncrypt:

该字符串是加密所得,比如reqEncryptType为1时,意味着AES加密(目前只支持AES加密) 使用secretKey作为加密密钥,加密前字符串为parameters中的所需参数,如"{"mobile":"xxxxxxxx"}" (根据接口不一样,参数也不一样)
AES加密的密钥长度:32位字符串,对应128位二进制数据;

AES加密的加密模式:aes-128-ecb

JAVA AES加密示例:

Map<String, Object> paramMap = new HashMap<>();
paramMap.put("mobile", mobile);
String s = JSON.toJSONString(paramMap);
String encrypt = AesEncryptUtil.encrypt(s, {secretKey});

public static String encrypt(String content, String encryptKey) {
    String key = encryptKey;
    if (encryptKey.length() > 64) {
        key = encryptKey.substring(0, DEFAULT_KEY_LEN);
    }
    try {
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes("utf-8"), "AES"));
        byte[] b = cipher.doFinal(content.getBytes("utf-8"));
        return Base64.encodeBase64String(b);
    } catch (Exception e) {
        log.info("AesEncryptUtil encrypt catch e: {}", e);
        return null;
    }

}

signature= Md5((str_for_sign+'&')+(paramEncrypt+'&')+timestamp+'&'+secretKey),其中secretKey 是系统获取的sk 注意:参数值为空不需要参与签名,如str_for_sign为空字符串,则直接省去(str_for_sign+'&') 如果采用aes加密,则不需要(str_for_sign+'&'),如果不采用aes加密,则不需要(paramEncrypt+'&')

请求头Header参数

参数名称 类型 是否必选 参数描述 示例
appkey String 应用key,在控制台中查看,不可以直接用示例 207xxx
timestamp String 时间戳,单位秒 1667810816
signature String 签名 e06fa22f57fd5c9e9138f183d59b18a

请求体Body参数

参数名称 类型 是否必选 参数描述 示例
parameters JSON 如果新增paramEncrypt、reqEncryptType参数,则不需要传该参数 "parameters": {"name":"xxx","idNum":"xxx","mobile":"xxx"}
paramEncrypt String 加密后的请求参数(就是将就是将上述的{"name":"xxx","idNum":"xxx","mobile":"xxx"}进行一次加密,并放入paramEncrypt属性中,详见上文准备签名参数字符串paramEncrypt) Ht8YMQtfxHplmfPn2BcXXZtE0lN2NGHKEgQrHO5W1/qREKpHOmj21N8uInLRDLxx
reqEncryptType String 入参加密类型 默认为0-不加密;1-AES加密 0

注意事项

请注意,以上参数,假设paramEncrypt+reqEncryptType为A组,parameters为B组,A B组必须存在其一,且不可同时存在

  1. 如果采取入参aes加密,则reqEncryptType、paramEncrypt都需要传递,且reqEncryptType为1;parameters参数不需要传递
  2. 如果不需要采用入参加密,则传递parameters参数,reqEncryptType、paramEncrypt不需要传递

请求体中parameters参数

参数名称 类型 是否必选 参数描述 示例
name String 姓名 王xx
idNum String 身份证号码,限单个 xxxxxxxxx
mobile String 银行预留手机号,仅支持国内11位号码 188xxxxxxx
cardNo String 银行卡号,限单个 xxxxxxx

请求体示例

#明文请求
{
     "parameters": {"name":"{姓名}","idNum":"{身份证号}","cardNo":"{银行卡号}","mobile":"{手机号}"}
}
#AES加密请求(就是将上述的就是将上述的{"name":"{姓名}","idNum":"{身份证号}","cardNo":"{银行卡号}","mobile":"{手机号}"}进行一次加密,并放入paramEncrypt属性中,详见上文 准备签名参数字符串paramEncrypt 章节)
{
 "paramEncrypt":"Ht8YMQtfxHplmfPn2BcXXZtE0lN2NGHKEgQrHO5W1/qREKpHOmj21N8uInLRDLeO",
 "reqEncryptType":1
}

响应参数

参数名称 类型 是否存在 参数描述 示例
code String 响应码 01
data json 响应数据 xxxxxxxxx
message String 响应详细 成功

data参数

参数名称 类型 是否存在 参数描述 示例
id String pnvs响应id 971961d8ffce4669b75c35fb46738843
responseParams json 响应参数(非必传,字段可能会变化,建议不要使用)
statusType String 业务状态 “业务成功”

响应体示例

{
   "code":"01",
   "data":{
               "id":"896487b984e14a9382b384a5d37f7fa5",
               "statusType":"业务成功"
          },
   "message":"验证成功,一致"
}

调用示例(AES版)

@Test
public void testTelecomApi() {
    String localUrl = "见已购列表";
    InvokeRequest invokeRequest = new InvokeRequest();
    // appKey
    Long timestamp = System.currentTimeMillis() / 1000;
    Map<String, Object> paramMap = new HashMap<>();

    String mobile = "手机号";
    String name = "姓名";
    String idNum = "身份证号";
    String cardNo = "银行卡号";
    paramMap.put("mobile", mobile);
    paramMap.put("name", name);
    paramMap.put("idNum", idNum);
    paramMap.put("cardNo", cardNo);

    String encrypt = AesEncryptUtil.encrypt(JSON.toJSONString(paramMap), "sk");
    invokeRequest.setParamEncrypt(encrypt);
    invokeRequest.setReqEncryptType(1);
    String secretKey = "sk";
    StringBuilder assemble = AssembleUtil.assembleParameters(new HashMap<>());
    if (StringUtils.isNotEmpty(invokeRequest.getParamEncrypt())) {
        assemble.append(invokeRequest.getParamEncrypt()).append("&");
    }
    assemble.append(timestamp).append("&").append(secretKey);
    System.out.println("assemble:" + assemble.toString());
    String signature = MD5Util.md5Encode(assemble.toString());
    String bodyJson = JSON.toJSONString(invokeRequest);
    List<Header> headers = new ArrayList<>();
    Header appKeyHeader = new BasicHeader("appkey", "ak");
    Header timeStampHeader = new BasicHeader("timestamp",
            String.valueOf(timestamp));
    Header msgEncryptionHeader = new BasicHeader("signature", signature);
    headers.add(appKeyHeader);
    headers.add(timeStampHeader);
    headers.add(msgEncryptionHeader);
    System.out.println(bodyJson);
    System.out.println(HttpsUtil.post(localUrl, headers.toArray(new Header[]{}), bodyJson,
            2000, 30000));
}

// assemble方法
public class AssembleUtil {
    public static <T> StringBuilder assembleParameters(Map<String, T> paramMap) {
        StringBuilder result = new StringBuilder();
        if (paramMap == null || paramMap.isEmpty()) {
            return result;
        }

        paramMap.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEach(entry ->
                result.append(entry.getKey()).append("=").append(entry.getValue()).append("&"));
        return result;
    }
}

// md5方法
public static String md5Encode(String plainText) {
    byte[] secretBytes;
    try {
        secretBytes = MessageDigest.getInstance("md5").digest(plainText
                .getBytes());
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException("无此md5算法");
    }
    String md5code = (new BigInteger(1, secretBytes)).toString(16);
    return StringUtils.leftPad(md5code, 32, "0");
}
上一篇
银行卡四要素简版接口文档
下一篇
运营商二要素简版(手机号+身份证号)