韩国实名认证 (手机号+身份证实名认证)niceApi

这是一个实名认证的对接api,是nice提供的,因为国内社区并不多,把自己对接国外实名认证的实现分享给社区,简单记录一下。
韩国大概是这样子的一个认证方式

然后我这里给一下官网的文档(我有翻译好的)https://www.niceapi.co.kr/#/apis/guide?ctgrCd=0100&prdId=31&prdNm=%EB%B3%B8%EC%9D%B8%ED%99%95%EC%9D%B8%28%ED%86%B5%ED%95%A9%ED%98%95%29

直接上代码吧,以上的秘钥都是处理了的,实际根据自己申请的为准



@RestController
@RequestMapping("/niceApi")
@Api(tags = "NICE API实名认证相关api")
@Slf4j
public class NiceAPIController extends BaseController {

    @Autowired
    private RedisCache    redisCache;
    private static final Logger logger = LoggerFactory.getLogger(FaceBookLoginController.class);
    private static final String clientId = "1b9dd185-f0cb-212133-b6f22283d2269ff6";


    private static final String clientSecret = "d4d1012646242121e7a1bd515e7e71ea6f12";


    private static final String accessToken = "6f90befd-2aa9-41212-1c837740c41";

    //获取全局token的url
    private static final String niceApiGetAccessTokenUrl = "https://svc.niceapi.co.kr:22001/digital/niceid/oauth/oauth/token";


    private static final String requestCryptoUrl = "https://svc.niceapi.co.kr:22001/digital/niceid/api/v1.0/common/crypto/token"; // API请求URL


    private static final Integer productId = 2101979031;


    /**
     * nice获取全局token
     *
     * @return
     */
    @PostMapping("/accessToken")
    public static AjaxResult accessTokenTwo(){
        // 构建请求URL和连接对象
        HttpURLConnection connection = null;
        try {
            URL url = new URL(niceApiGetAccessTokenUrl);
            connection = (HttpURLConnection) url.openConnection();

            // 设置请求方法为POST
            connection.setRequestMethod("POST");

            // 设置请求头信息
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");

            // 构建授权信息
            String credentials = clientId + ":" + clientSecret;
            String encodedCredentials = Base64.getEncoder().encodeToString(credentials.getBytes(StandardCharsets.UTF_8));
            connection.setRequestProperty("Authorization", "Basic " + encodedCredentials);

            // 构建POST数据
            String postData = "grant_type=client_credentials&scope=default";

            // 发送请求
            connection.setDoOutput(true);
            try (OutputStream outputStream = connection.getOutputStream()) {
                byte[] postDataBytes = postData.getBytes(StandardCharsets.UTF_8);
                outputStream.write(postDataBytes);
                outputStream.flush();
            }

            // 获取响应
            int responseCode = connection.getResponseCode();
            String responseData;
            if (responseCode >= 200 && responseCode < 300) {
                // 读取响应数据
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                reader.close();
                // 处理响应数据
                responseData = response.toString();
            } else {
                // 读取错误响应数据
                BufferedReader errorReader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
                StringBuilder errorResponse = new StringBuilder();
                String errorLine;
                while ((errorLine = errorReader.readLine()) != null) {
                    errorResponse.append(errorLine);
                }
                errorReader.close();
                // 处理错误响应数据
                responseData = errorResponse.toString();
            }
            return new AjaxResult(responseCode, responseData);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
        return new AjaxResult(500, "操作失败");
    }


    /**
     * 获取token加密请求
     *
     * @param
     * @return
     */
    public static String getTokenCrypto(String req_dtim, String req_no) {
        String token = generateToken();
        String requestPayload = "{\n" +
                "  \"dataHeader\": {\n" +
                "    \"CNTY_CD\": \"ko\"\n" +
                "  },\n" +
                "  \"dataBody\": {\n" +
                "    \"req_dtim\": \"" + req_dtim + "\",\n" +
                "    \"req_no\": \"" + req_no + "\",\n" +
                "    \"enc_mode\": \"1\"\n" +
                "  }\n" +
                "}";
        try {
            URL url = new URL(requestCryptoUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("Authorization", "bearer " + token);
            conn.setRequestProperty("ProductID", productId.toString());
            conn.setDoOutput(true);

            OutputStream os = conn.getOutputStream();
            os.write(requestPayload.getBytes(StandardCharsets.UTF_8));
            os.flush();

            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String responseLine;
                StringBuilder responseBuilder = new StringBuilder();
                while ((responseLine = br.readLine()) != null) {
                    responseBuilder.append(responseLine.trim());
                }
                br.close();

                String response = responseBuilder.toString();
                conn.disconnect();
                return response;
            } else {
                System.out.println("API请求失败,响应码:" + conn.getResponseCode());
                conn.disconnect();
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * token加密请求  "bearer " +  Base64Encoding(access_token:current_timestamp:client_id")
     *
     * @return
     */
    private static String generateToken() {

        // 计算当前时间戳
        Date currentDate = new Date();
        long current_timestamp = currentDate.getTime() / 1000;

        // 构造token字符串
        String tokenString = accessToken + ":" + current_timestamp + ":" + clientId;

        // 对token进行Base64编码
        byte[] tokenBytes = tokenString.getBytes(StandardCharsets.UTF_8);
        String encodedToken = Base64.getEncoder().encodeToString(tokenBytes);
        return encodedToken;
    }


    /**
     * 创建密钥对 key  vi  hmac_key resultVal
     *
     * @param
     * @throws NoSuchAlgorithmException
     */
    public static KeyViEntity creatKeyAndVi(String req_dtim, String req_no, String token_val) throws NoSuchAlgorithmException {
        KeyViEntity keyViEntity = new KeyViEntity();
        // 获取"token加密请求"API请求和响应值,此处仅作示例,实际情况应根据API的实际返回值来获取req_dtim、req_no和token_val的值
        // 生成对称密钥
        String resultVal = generateHmacKey(req_dtim, req_no, token_val);
        System.out.println("resultVal:" + resultVal);
        //获取密钥对key  vi
        // 截取前16位
        String key = resultVal.substring(0, 16);
        System.out.println("前16位:" + key);
        keyViEntity.setKey(key);
        // 截取前32位
        String hmac_key = resultVal.substring(0, 32);
        System.out.println("前32位:" + hmac_key);
        keyViEntity.setHmacKey(hmac_key);
        // 截取后六位
        String vi = resultVal.substring(resultVal.length() - 16);
        System.out.println("后16位:" + vi);
        keyViEntity.setVi(vi);
        return keyViEntity;
    }


    /**
     * 实名认证跳转接口
     *
     */
    @GetMapping(value = "/getNiceApiUrl")
    public String   getNiceApiUrl(NiceApiDTO niceApiDTO) throws NoSuchAlgorithmException {
        // 获取当前时间的LocalDateTime对象
        LocalDateTime now = LocalDateTime.now();

        // 创建DateTimeFormatter对象,使用指定的格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss");

        // 使用DateTimeFormatter对象对LocalDateTime对象进行格式化
        String formattedDateTime = now.format(formatter);

        // 去除格式化后字符串中的非数字字符,得到"20230725162601"格式
        String reqDtim   = formattedDateTime.replaceAll("\\D", "");
        System.out.println(reqDtim);
        String reqNo = String.valueOf(System.currentTimeMillis());
        System.out.println(reqNo);



        //2.token加密请求
        String tokenCrypto = getTokenCrypto(reqDtim, reqNo);

        //解析token加密请求的返回结果
        // 使用Gson库解析JSON字符串为Map
        Gson gson = new Gson();
        Map<String, Object> jsonDataMap = gson.fromJson(tokenCrypto, Map.class);
        Map<String, Object> dataBodyMap =null;
        // 检查GW_RSLT_CD是否等于"1200"
        Map<String, Object> dataHeaderMap = (Map<String, Object>) jsonDataMap.get("dataHeader");
        String gwRsltCd = (String) dataHeaderMap.get("GW_RSLT_CD");
        if ("1200".equals(gwRsltCd)) {
            // 如果GW_RSLT_CD等于"1200",则获取dataBody部分并转换为Map
            dataBodyMap = (Map<String, Object>) jsonDataMap.get("dataBody");
            System.out.println("dataBody转换为Map:" + dataBodyMap);
        } else {
            System.out.println("GW_RSLT_CD不等于1200,无法转换dataBody为Map。");
        }
        //3.获取token加密请求得到的token_version_id   site_code  token_val
        String tokenVersionId = dataBodyMap.get("token_version_id").toString();

        String siteCode = dataBodyMap.get("site_code").toString();

        String tokenVal = dataBodyMap.get("token_val").toString();
        //4.创建对称密钥  得到密钥对
        KeyViEntity keyViEntity = creatKeyAndVi(reqDtim, reqNo, tokenVal);
        String key=keyViEntity.getKey();

        String hmacKey = keyViEntity.getHmacKey();

        String iv = keyViEntity.getVi();


        //5.加密数据请求
        String requestNo = niceApiDTO.getSuperUserId();
        NiceKeyAndVI niceKeyAndVI = new NiceKeyAndVI();
        niceKeyAndVI.setKey(key);
        niceKeyAndVI.setVi(iv);

        redisCache.setCacheObject("niceAPI:"+niceApiDTO.getGameId()+":"+niceApiDTO.getSuperUserId(),niceKeyAndVI);

      /*  String s = MD5Utils.MD5(userId);*/
        String returnUrl = "https://q33.com/isCardReal?superUserId="+niceApiDTO.getSuperUserId()+"&gameId="+niceApiDTO.getGameId()+"&userId="+niceApiDTO.getUserId();
        logger.info("[returnUrl]<result> ======> " + returnUrl);
        String authType = "M";
        String mobileEco = "S";
        String businessNo = "xxxxdddeee";
        String methodType = "get";
        String popupYn = "Y";
        String receiveData = "xxxxdddeee";

        String jsonData = createRequestData(requestNo, returnUrl, siteCode, authType, mobileEco, businessNo, methodType, popupYn, receiveData);
        System.out.println("请求数据(reqData)的JSON构成:\n" + jsonData);

        String encryptedData = encryptRequestData(jsonData, key, iv);
        System.out.println("JSON形态的请求数据加密:\n" + encryptedData);

        String integrityValue = generateHmacIntegrityValue(encryptedData, hmacKey);
        System.out.println("生成Hmac完整校验值(integrity_value):\n" + integrityValue);
        //转义
        integrityValue=integrityValue.replace("+","%2B");

        String  niceApi ="https://nice.checkplus.co.kr/CheckPlusSafeModel/service.cb";
        String lastUrl =niceApi+"?"+"m=service"+"&token_version_id="+tokenVersionId+"&enc_data="+encryptedData+"&integrity_value="+integrityValue;
        logger.info("[access_token]<result> ======> " + lastUrl);
        return  lastUrl;

    }




    public static void main(String[] args) throws NoSuchAlgorithmException {
        // 获取当前时间的LocalDateTime对象
        LocalDateTime now = LocalDateTime.now();

        // 创建DateTimeFormatter对象,使用指定的格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss");

        // 使用DateTimeFormatter对象对LocalDateTime对象进行格式化
        String formattedDateTime = now.format(formatter);

        // 去除格式化后字符串中的非数字字符,得到"20230725162601"格式
        String reqDtim   = formattedDateTime.replaceAll("\\D", "");
        System.out.println(reqDtim);
        String reqNo = String.valueOf(System.currentTimeMillis());
        System.out.println(reqNo);



        //2.token加密请求
        String tokenCrypto = getTokenCrypto(reqDtim, reqNo);

        //解析token加密请求的返回结果
        // 使用Gson库解析JSON字符串为Map
        Gson gson = new Gson();
        Map<String, Object> jsonDataMap = gson.fromJson(tokenCrypto, Map.class);
        Map<String, Object> dataBodyMap =null;
        // 检查GW_RSLT_CD是否等于"1200"
        Map<String, Object> dataHeaderMap = (Map<String, Object>) jsonDataMap.get("dataHeader");
        String gwRsltCd = (String) dataHeaderMap.get("GW_RSLT_CD");
        if ("1200".equals(gwRsltCd)) {
            // 如果GW_RSLT_CD等于"1200",则获取dataBody部分并转换为Map
             dataBodyMap = (Map<String, Object>) jsonDataMap.get("dataBody");
            System.out.println("dataBody转换为Map:" + dataBodyMap);
        } else {
            System.out.println("GW_RSLT_CD不等于1200,无法转换dataBody为Map。");
        }
        //3.获取token加密请求得到的token_version_id   site_code  token_val
        String tokenVersionId = dataBodyMap.get("token_version_id").toString();

        String siteCode = dataBodyMap.get("site_code").toString();

        String tokenVal = dataBodyMap.get("token_val").toString();

        //4.创建对称密钥  得到密钥对
        KeyViEntity keyViEntity = creatKeyAndVi(reqDtim, reqNo, tokenVal);
        String key=keyViEntity.getKey();

        String hmacKey = keyViEntity.getHmacKey();

        String iv = keyViEntity.getVi();


/*        String tokenVersionId="20230727130110GF-NC49CB567-2B1HD-219H5H84A8";
        String  siteCode="Q0I1Njc=";
        String key="euAKqLokm8nOajen";
        String  hmacKey="euAKqLokm8nOajenHqhlvKxQVmo9Q8W5";
        String  iv="Q8W55Mj7LrJjW6M=";*/



        //5.加密数据请求
        String requestNo = "REQ2021123199";
        String returnUrl = "https://papasg-korea.g-m-store.com/";
        String authType = "M";
        String mobileEco = "S";
        String businessNo = "xxxxdddeee";
        String methodType = "get";
        String popupYn = "Y";
        String receiveData = "xxxxdddeee";

        String jsonData = createRequestData(requestNo, returnUrl, siteCode, authType, mobileEco, businessNo, methodType, popupYn, receiveData);
        System.out.println("请求数据(reqData)的JSON构成:\n" + jsonData);

        String encryptedData = encryptRequestData(jsonData, key, iv);
        System.out.println("JSON形态的请求数据加密:\n" + encryptedData);
        String integrityValue = generateHmacIntegrityValue(encryptedData, hmacKey);
        System.out.println("生成Hmac完整校验值(integrity_value):\n" + integrityValue);
        String  niceApi ="https://nice.checkplus.co.kr/CheckPlusSafeModel/service.cb";
        String lastUrl =niceApi+"?"+"m=service"+"&token_version_id="+tokenVersionId+"&enc_data="+encryptedData+"&integrity_value="+integrityValue;
        System.out.println(lastUrl);
    }







    // 请求数据加密
    public static String encryptRequestData(String reqData, String key, String iv) {
        try {
            SecretKeySpec secureKey = new SecretKeySpec(key.getBytes(), "AES");
            Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
            c.init(Cipher.ENCRYPT_MODE, secureKey, new IvParameterSpec(iv.getBytes()));
            byte[] encrypted = c.doFinal(reqData.trim().getBytes());
            return Base64.getEncoder().encodeToString(encrypted);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    // 生成Hmac完整校验值
    public static String generateHmacIntegrityValue(String encData, String hmacKey) {
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec sks = new SecretKeySpec(hmacKey.getBytes(), "HmacSHA256");
            mac.init(sks);
            byte[] hmacSha256 = mac.doFinal(encData.getBytes());
            return Base64.getEncoder().encodeToString(hmacSha256);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    // 封装请求数据为JSON格式
    public static String createRequestData(String requestNo, String returnUrl, String siteCode, String authType,
                                           String mobileEco, String businessNo, String methodType, String popupYn,
                                           String receiveData) {
        StringBuilder jsonBuilder = new StringBuilder();
        jsonBuilder.append("{")
                .append("\"requestno\":\"").append(requestNo).append("\",")
                .append("\"returnurl\":\"").append(returnUrl).append("\",")
                .append("\"sitecode\":\"").append(siteCode).append("\",")
                .append("\"authtype\":\"").append("M").append("\"")
                .append("}");
        return jsonBuilder.toString();
    }




    private static String generateHmacKey(String req_dtim, String req_no, String token_val) throws NoSuchAlgorithmException {
        String value = req_dtim.trim() + req_no.trim() + token_val.trim();
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(value.getBytes());
        byte[] arrHashValue = md.digest();
        return Base64.getEncoder().encodeToString(arrHashValue);
    }
}

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值