package com.hai.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hai.common.pay.util.sdk.WXPayConstants;
import com.hai.common.utils.HttpsUtils;
import org.apache.commons.lang3.StringUtils;

import javax.xml.bind.DatatypeConverter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.*;

/**
 * 银联用户信息
 * @author hurui
 */
public class UnionUserConfig {

    private static String requestUrl = "https://open.95516.com/open/access/1.0/backendToken";
    private static String appId = "1900bc84497cab3b";
    private static String secret = "665193ddd44248acb461594cfe0ded5b";

    /**
     * 获取应用访问令牌backendToken
     * @return
     */
    public static JSONObject getBackendToken() {
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("appId", appId);
        paramMap.put("nonceStr", createNonceStr());
        paramMap.put("timestamp", System.currentTimeMillis());
        paramMap.put("signature", generateSign(paramMap));
        return HttpsUtils.doPost(requestUrl, JSONObject.toJSONString(paramMap));
    }


    /**
     * 参数排序
     * @param param
     * @return
     */
    private static String paramSort(final Map<String, Object> param) {
        Set<String> keySet = param.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if (k.equals(WXPayConstants.FIELD_SIGN)) {
                continue;
            }
            if (StringUtils.isBlank(sb.toString())) {
                sb.append(k).append("=").append(param.get(k));
            } else {
                sb.append("&").append(k).append("=").append(param.get(k));
            }
        }
        param.remove("secret");
        return sb.toString();
    }

    /**
     * 生成签名
     * @param data
     * @return
     * @throws Exception
     */
    private static String generateSign(Map<String, Object> data){
        data.put("secret", secret);
        String sign = sha256(paramSort(data).getBytes());
        return sign;
    }

    /**
     * 生成随机16位随机字符串
     * @return
     */
    public static String createNonceStr(){
        String sl = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuilder sb = new StringBuilder();
        for(int i = 0 ; i < 16 ; i ++){
            sb.append(sl.charAt(new Random().nextInt(sl.length())));
        }
        return sb.toString();
    }

    public static String sha256(byte[] data) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            return bytesToHex(md.digest(data));
        } catch (Exception ex) {
            return null;
        }
    }

    public static String bytesToHex(byte[] bytes) {
        String hexArray = "0123456789abcdef";
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) {
            int bi = b & 0xff;
            sb.append(hexArray.charAt(bi >> 4));
            sb.append(hexArray.charAt(bi & 0xf));
        }
        return sb.toString();
    }

    public static Map<String, Object> generatorRSA(){
        KeyPairGenerator keyGen = null;
        try {
            keyGen = KeyPairGenerator.getInstance("RSA");
            keyGen.initialize(1024);
            KeyPair keyPair = keyGen.generateKeyPair();
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

            String publicKeyBase64 = DatatypeConverter.printBase64Binary(publicKey.getEncoded());
            String privateKeyBase64 = DatatypeConverter.printBase64Binary(privateKey.getEncoded());

            Map<String, Object> map = new HashMap<>();
            map.put("publicKey", publicKeyBase64);
            map.put("privateKey", privateKeyBase64);
            return map;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }
}
