package com.fzm.mall.server.front.order.controller.weixinPay;
import com.fzm.mall.server.front.order.model.vo.WCPayResultVo;
import com.fzm.mall.server.front.util.UUIdUtil;
import okhttp3.HttpUrl;
import org.bouncycastle.jcajce.provider.digest.MD5;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Decoder;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;

@Component
public class CreateSign {
    WCPayResultVo getToken(String method, HttpUrl url, String body, Long timeStamp, String uuid, WCPayResultVo wcPayResultVo) throws IOException, SignatureException, NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException {
        //随机字符串
        String nonceStr = uuid;//真！随机字符串
        //从下往上依次生成
        String message = buildMessage(method, url, timeStamp, nonceStr, body);
        System.out.println("message:"+message);
        //签名
        String signature = sign(message.getBytes("utf-8"));
        System.out.println("signature:"+signature);
        System.out.println("nonceStr:"+nonceStr);
        wcPayResultVo.setSign("mchid=\"" + WeiXinProties.getMERC_ID() + "\","
                + "nonce_str=\"" + nonceStr + "\","//真！随机自传承
                + "timestamp=\"" + timeStamp + "\","//时间戳
                + "serial_no=\"" + WeiXinProties.getSERIAL_NO() + "\","
                + "signature=\"" + signature + "\"");
        wcPayResultVo.setSignature(signature);
        return  wcPayResultVo;
    }

    String sign(byte[] message) throws NoSuchAlgorithmException, SignatureException, IOException, InvalidKeyException, InvalidKeySpecException {
        //加密方式
        Signature sign = Signature.getInstance("SHA256withRSA");
        //私钥，通过MyPrivateKey来获取，这是个静态类可以接调用方法 ，需要的是_key.pem文件的绝对路径配上文件名
     /*  sign.initSign(MyPrivateKey.getPrivateKey("C:\\Users\\logan\\Desktop\\1604477044_20211012_cert\\apiclient_key.pem"));
        sign.update(message);
        return Base64.getEncoder().encodeToString(sign.sign());*/
       byte[] keyBytes =new BASE64Decoder().decodeBuffer(WeiXinProties.getPRIVATE_KEY());
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(spec);
        sign.initSign(privateKey);
        sign.update(message);

        return Base64.getEncoder().encodeToString(sign.sign());
    }

    String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
        String canonicalUrl = url.encodedPath();
        if (url.encodedQuery() != null) {    //get请求自动做了校验，会把空字符串进行识别，注意是空字符串！！！！！
            canonicalUrl += "?" + url.encodedQuery();
        }
        //官方的方法自动做了换行的所有动作，注意唤起支付的参数不一样需要更换（这里是统一下单所以直接照搬即可）
        return method + "\n"
                + canonicalUrl + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }

    String sign(String nonceStr,String timeStamp,String str) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {

        String stringA="appId="+WeiXinProties.getAPP_ID()+"&nonceStr="+nonceStr+"&signType="+"MD5"+"&str:"+str+"&timeStamp="+timeStamp;
        String stringSignTemp=stringA+"&key="+WeiXinProties.getPRIVATE_KEY();//注：key为商户平台设置的密钥key
        SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
        parameters.put("appId", WeiXinProties.getAPP_ID());
        parameters.put("timeStamp", timeStamp);
        parameters.put("nonceStr", nonceStr);
        parameters.put("package", str);
        parameters.put("signType", "MD5");
        //加密方式
        return createSign("UTF-8",parameters);
    }

    public  String createSign(String characterEncoding, SortedMap<Object,Object> parameters){
        StringBuffer sb = new StringBuffer();
        Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序（升序）
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            Object v = entry.getValue();
            if(null != v && !"".equals(v)
                    && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        //sb.append("key=" + parameters.get());
        String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;
    }

    WCPayResultVo getToken(WCPayResultVo wcPayResultVo) throws IOException, SignatureException, NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException {
        //随机字符串
        String nonceStr = wcPayResultVo.getNoncestr();//真！随机字符串
        //从下往上依次生成
        String message = handle(WeiXinProties.getAPP_ID(),Long.valueOf(wcPayResultVo.getTimeStamp()),wcPayResultVo.getNoncestr(),wcPayResultVo.getPrePayId());
        System.out.println("message:"+message);
        //签名
        String signature = sign(message.getBytes("utf-8"));
        System.out.println("signature:"+signature);
        System.out.println("nonceStr:"+nonceStr);
        wcPayResultVo.setSign("mchid=\"" + WeiXinProties.getMERC_ID() + "\","
                + "nonce_str=\"" + nonceStr + "\","//真！随机自传承
                + "timestamp=\"" + wcPayResultVo.getTimeStamp() + "\","//时间戳
                + "serial_no=\"" + WeiXinProties.getSERIAL_NO() + "\","
                + "signature=\"" + signature + "\"");
        wcPayResultVo.setSignature(signature);
        return  wcPayResultVo;
    }

    WCPayResultVo getWxToken(WCPayResultVo wcPayResultVo) throws IOException, SignatureException, NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException {
        //随机字符串
        String nonceStr = wcPayResultVo.getNoncestr();//真！随机字符串
        //从下往上依次生成
        String message = handle(WeiXinProties.getWX_APP_ID(),Long.valueOf(wcPayResultVo.getTimeStamp()),wcPayResultVo.getNoncestr(),wcPayResultVo.getPrePayId());
        System.out.println("message:"+message);
        //签名
        String signature = sign(message.getBytes("utf-8"));
        System.out.println("signature:"+signature);
        System.out.println("nonceStr:"+nonceStr);
        wcPayResultVo.setSign("mchid=\"" + WeiXinProties.getMERC_ID() + "\","
                + "nonce_str=\"" + nonceStr + "\","//真！随机自传承
                + "timestamp=\"" + wcPayResultVo.getTimeStamp() + "\","//时间戳
                + "serial_no=\"" + WeiXinProties.getSERIAL_NO() + "\","
                + "signature=\"" + signature + "\"");
        wcPayResultVo.setSignature(signature);
        return  wcPayResultVo;
    }

    private String handle(String app_id, Long timeStamp, String noncestr, String prePayId) {
        return app_id + "\n"
                + timeStamp + "\n"
                + noncestr + "\n"
                + prePayId + "\n";
    }

}