Air
2024-11-04 29c405353029f033e187e8dc033b93385365ee43
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package com.nova.sankuai.infra.utils.chuxin;
 
import com.alibaba.fastjson.JSON;
import com.nova.sankuai.domain.dto.chuxin.ChuxinData;
import com.nova.sankuai.domain.dto.chuxin.ChuxinResult;
import com.nova.sankuai.infra.config.CommonException;
import com.nova.sankuai.infra.utils.ResultJson;
import com.nova.sankuai.security.HttpClientUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
 
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
 
/**
 * 储信数据·身份认证
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class ChuxinDataUtil {
    /**
     * 登录管理平台应用管理可查看获取appId和appSecret
     */
    private final static String appId = "1754b210";
    private final static String tokenId = "82808081914b210201914b2102930000";
 
    public ResultJson getRemoteResult(String idcard, String name) {
        // 接口地址,具体接口参见接口文档,每个接口有不同的url地址
        String url = "https://kyc.chuxindata.com/identity/verifyIdcard";
 
        Map<String, String> param = new HashMap<String, String>();
 
        // 所需入参,请参照具体接口文档调整入参, 请注意区分大小写
        param.put("name", name);
        param.put("idcard", idcard);
 
 
        // 生成TokenKey
        // 注意:进行MD5摘要时,不能传入appId参数
        String tokenKey = getTokenKey(url, tokenId, param);
        param.put("tokenKey", tokenKey);
 
        // 注意:appId参数需要在请求的时候作为入参传入,appId不参与MD5摘要
        param.put("appId", appId);
 
        // http的post请求
        String result = HttpClientUtil.doPostChuxin(url, param);
        if (StringUtils.isBlank(result)) {
            log.error("储信数据·身份证二要素认证发生错误,icCard:{} name:{},发生错误,返回参数为:{}", idcard, name, result);
            throw new CommonException("服务器发生异常!");
        }
        ChuxinData chuxinData = JSON.parseObject(result, ChuxinData.class);
        if (Objects.isNull(chuxinData)) {
            log.error("储信数据·身份证二要素认证发生错误,icCard:{} name:{},发生错误,返回参数为:{}", idcard, name, result);
            throw new CommonException("服务器发生异常!");
        }
        if (chuxinData.getStatus().intValue() != 0) {
            log.info("储信数据·身份证二要素认证失败,icCard:{} name:{},返回参数为:{}", idcard, name, result);
            throw new CommonException("身份证和姓名不匹配!");
        }
        ChuxinResult cr = chuxinData.getData();
        if (Objects.isNull(cr)) {
            log.error("储信数据·身份证二要素认证发生错误,icCard:{} name:{},返回参数为:{}", idcard, name, result);
            throw new CommonException("服务器发生异常!");
        }
 
        if (!"1".equals(cr.getResult())) {
            log.info("储信数据·身份证二要素认证失败,icCard:{} name:{},返回参数为:{}", idcard, name, result);
            throw new CommonException("身份证和姓名不匹配!");
        }
        log.info("储信数据·身份证二要素认证成功,icCard:{} name:{},返回参数为:{}", idcard, name, result);
        return ResultJson.ok("ok");
    }
 
    /**
     * 生成TokenKey
     *
     * @param url
     * @param tokenId
     * @param param
     * @return
     */
    public String getTokenKey(String url, String tokenId, Map<String, String> param) {
        String paramStr = sortParam(param);
        return md5Hex(url + tokenId + paramStr);
    }
 
    /**
     * 生成参数字符串,参数key按字典序排列
     *
     * @param param
     * @return
     */
    public String sortParam(Map<String, String> param) {
        if (null == param || 0 == param.size()) {
            return "";
        }
        // 排序键,按照字母先后进行排序
        Iterator<String> iterator = param.keySet().iterator();
        String[] arr = new String[param.size()];
        for (int i = 0; iterator.hasNext(); i++) {
            arr[i] = iterator.next();
        }
        Arrays.sort(arr);
        // 生成进行MD5摘要的字符串
        StringBuffer sb = new StringBuffer();
        for (String key : arr) {
            String value = param.get(key);
            if (StringUtils.isNotBlank(value)) {
                sb.append(key).append("=").append(value).append(",");
            }
        }
        // 检查结果
        if (sb.length() > 0) {
            return sb.substring(0, sb.length() - 1);
        } else {
            return "";
        }
    }
 
    /**
     * 对字符串进行md5摘要,然后转化成16进制字符串
     * 使用标准的md5摘要算法
     *
     * @param text
     * @return
     */
    public String md5Hex(String text) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] bytes = md5.digest(text.trim().getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < bytes.length; i++) {
                int high = (bytes[i] >> 4) & 0x0f;
                int low = bytes[i] & 0x0f;
                sb.append(high > 9 ? (char) ((high - 10) + 'a') : (char) (high + '0'));
                sb.append(low > 9 ? (char) ((low - 10) + 'a') : (char) (low + '0'));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            log.error("储信数据·身份班证二要素认证:{},系统不支持MD5算法:", text, e);
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            log.error("储信数据·身份班证二要素认证:{},系统不支持指定的编码格式:", text, e);
        }
        return null;
    }
}