微信支付专题——获取平台证书时生成签名的一个坑,报错401签名错误

        下载平台证书的时候,返回的状态码是401,错误信息如下图所示:

在这里插入图片描述
        可以看到错误信息提示是错误的签名,于是就检查关于签名部分的代码,下面是从官网copy的生成签名的代码。

/**
     * @Decription   计算签名值
     *     Authorization: <schema> <token>
     *     GET - getToken("GET", httpurl, "")
     *     POST - getToken("POST", httpurl, json)
     * @Param   null
     * @Return  java.lang.String
     * @Author  lmh
     * @Date    2022/1/5 17:13
     */
    String getToken(String method, HttpUrl url, String body){
    
    
        String nonceStr = null;
        long timestamp = 0;
        String signature = null;
        try {
    
    
            nonceStr = "593BEC0C930BF1AFEB90B4A08C8FB242";
            timestamp = System.currentTimeMillis() / 1000;
            String message = buildMessage(method, url, timestamp, nonceStr, body);
            System.out.println(message);
            signature = sign(message.getBytes("utf-8"));
        } catch (UnsupportedEncodingException e) {
    
    
            e.printStackTrace();
        }
        return "mchid=\"" + 商户号 + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + 商户证书序列号 + "\","
                + "signature=\"" + signature + "\"";
    }

    /**
     * @Decription 使用商户私钥对签名串进行SHA256 with RSA签名,base64编码之后
     * @Param   null
     * @Return  java.lang.String
     * @Author  lmh
     * @Date    2022/1/6 18:07
     */
    String sign(byte[] message) {
    
    
        Signature sign = null;
        String s = null;
        try {
    
    
            PrivateKey privateKey = this.getPrivateKey();
            sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(privateKey);
            sign.update(message);
            s = Base64.getEncoder().encodeToString(sign.sign());
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return s;
    }
    /**
     * @Decription 生成签名串
     * @Param   null
     * @Return  java.lang.String
     * @Author  lmh
     * @Date    2022/1/6 18:06
     */
    String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
    
    
        String canonicalUrl = url.encodedPath();
        if (url.encodedQuery() != null) {
    
    
            canonicalUrl += "?" + url.encodedQuery();
        }

        return method +"\\n"+"\n"
                + canonicalUrl+"\\n"+ "\n"
                + timestamp +"\\n"+ "\n"
                + nonceStr +"\\n"+ "\n"
                + body +"\\n";
    }

        上面就是完整的代码了,防止公司信息泄露,梦梦就把关键信息换成了文字代替。代码也是复制官网的,为什么还能出错,于是就开启了debug。
在这里插入图片描述

        debug的时候,才发现原来是生成签名串部分写错了,多生成了一个“\n”。这才明白了,官网说的以“\n”结尾,不是看控制台打印出来的效果,我以为官网demo上的示例“\n”是idea的换行符,然后就再需要转义打印一个“\n”字符串,原来理解错了,debug的时候,发现就多了一个“\n”。
在这里插入图片描述

        所以,以后建议小伙伴们,copy 官网代码的时候尽量不修改。
        

猜你喜欢

转载自blog.csdn.net/qq_46540738/article/details/122361106