收藏
回答

V3图片上传API,提示签名错误,找不到问题所在

public String postFileMultiPart(String data,Map<String, ContentBody> reqParam) throws IOException {
    HttpPost httpPost = new HttpPost(
            "https://api.mch.weixin.qq.com/v3/merchant/media/upload");

    StringEntity strEntity = new StringEntity(
            data, ContentType.create("application/json", "utf-8"));
    httpPost.setEntity(strEntity);
    MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
    for(Map.Entry<String,ContentBody> param : reqParam.entrySet()){
        multipartEntityBuilder.addPart(param.getKey(), param.getValue());
    }
    HttpEntity reqEntity = multipartEntityBuilder.build();
    httpPost.setEntity(reqEntity);
  //  httpPost.addHeader("Accept", "application/json");
    httpPost.addHeader("Accept", "application/json");
    CloseableHttpResponse response = httpClient.execute(httpPost);
    assertTrue(response.getStatusLine().getStatusCode() != 401);
    try {
        HttpEntity entity2 = response.getEntity();
        // do something useful with the response body
        // and ensure it is fully consumed
        EntityUtils.consume(entity2);
        if (entity2 != null) {
            String res=EntityUtils.toString(entity2, Charset.forName("UTF-8"));
            System.out.println(res);
            return res;
        }

    } finally {
        response.close();
    }
    return null;
}


public static void main(String[] args) {
    try {
      //  WxHttpClient.getInstance().postNonRepeatableEntityTest();
        File file = new File("D:\\HomeLogoA.png");

        FileInputStream fileInputStream = new FileInputStream(file);
        String hex = new DigestUtils("SHA-256").digestAsHex(file);

        System.out.println(hex);
        String localFileName = "E:/2.jpg";
        String data = "{\n"
                + "\"filename\": \"HomeLogoA.png\",\n"
                + "\"sha256\": \"367a353ff0a7777f1a122dc9576460fbb662434d7f83d514f585df667b8a6015\"\n"
                + "}";
        Map<String,ContentBody> reqParam = new HashMap<String,ContentBody>();
        reqParam.put("meta", new StringBody(data, ContentType.APPLICATION_JSON));
        reqParam.put("file", new FileBody(file));


        WxHttpClient.getInstance().postFileMultiPart(data,reqParam);

      //  WxHttpClient.getInstance().postNonRepeatableEntityTest();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

"{"code":"SIGN_ERROR","detail":{"detail":{"issue":"sign not match"},"field":"signature","location":"authorization","sign_information":{"method":"POST","sign_message_length":185,"truncated_sign_message":"POST\n/v3/merchant/media/upload\n1585041402\ncVPpueKiBckXFwPpCOCoeQTPvIdPmy1Z\n{\n\"filen\n","url":"/v3/merchant/media/upload"}},"message":"[0xe9][0x94][0x99][0xe8][0xaf][0xaf][0xe7][0x9a][0x84][0xe7][0xad][0xbe][0xe5][0x90][0x8d][0xef][0xbc][0x8c][0xe9][0xaa][0x8c][0xe7][0xad][0xbe][0xe5][0xa4][0xb1][0xe8][0xb4][0xa5]"}"

401错误代码

回答关注问题邀请回答
收藏

2 个回答

  • 支付技术助手8
    支付技术助手8
    03-25

    参照这个写就行了。

    03-25
    赞同
    回复
  • L-J-L
    L-J-L
    03-24
    public static void main(String[] args) {
        try {
            //商户号
            String mchid = "";
            //证书序列号
            String serial_no = "";
            //商户私钥(拷贝apiclient_key.pem文件里-----BEGIN PRIVATE KEY-----和-----END PRIVATE KEY-----之间的内容)
            String rsaPrivateKey = "";
            //微信支付平台公钥
            String rsaPublicKeyFile = "";
            //时间戳
            String timestamp = Long.toString(System.currentTimeMillis()/1000);
            //随机数
            String nonce_str = "liujinliang8848";
    
            //图片文件
            String filePath = "";//文件路径
    
            String boundary = "";
    
            File file = new File(filePath);
            String filename = file.getName();//文件名
            String fileSha256 = DigestUtils.sha256Hex(new FileInputStream(file));//文件sha256
    
            //拼签名串
            StringBuffer sb = new StringBuffer();
            sb.append("POST").append("\n");
            sb.append("/v3/merchant/media/upload").append("\n");
            sb.append(timestamp).append("\n");
            sb.append(nonce_str).append("\n");
            sb.append("{\"filename\":\""+filename+"\",\"sha256\":\""+fileSha256+"\"}").append("\n");
            System.out.println("签名原串:"+sb.toString());
    
            //计算签名
            String sign = new String(Base64.encodeBase64(signRSA(sb.toString(),rsaPrivateKey)));
            System.out.println("签名sign值:"+sign);
    
            //拼装http头的Authorization内容
            String authorization ="WECHATPAY2-SHA256-RSA2048 mchid=\""+mchid+"\",nonce_str=\""+nonce_str+"\",signature=\""+sign+"\",timestamp=\""+timestamp+"\",serial_no=\""+serial_no+"\"";
            System.out.println("authorization值:"+authorization);
    
            //接口URL
            String url = "https://api.mch.weixin.qq.com/v3/merchant/media/upload";
            CloseableHttpClient httpclient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
    
            //设置头部
            httpPost.addHeader("Charset", "UTF-8");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-Type", "multipart/form-data; boundary =" + boundary);
            httpPost.addHeader("Authorization", authorization);
    
            //创建MultipartEntityBuilder
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
            //设置boundary
            multipartEntityBuilder.setBoundary("boundary");
            multipartEntityBuilder.setCharset(Charset.forName("UTF-8"));
            //设置meta内容
            multipartEntityBuilder.addTextBody("meta", "{\"filename\":\""+filename+"\",\"sha256\":\""+fileSha256+"\"}", ContentType.APPLICATION_JSON);
            //设置图片内容
            multipartEntityBuilder.addBinaryBody("file", file, ContentType.create("image/jpg"), filename);
            //放入内容
            httpPost.setEntity(multipartEntityBuilder.build());
    
            //获取返回内容
            CloseableHttpResponse response = httpclient.execute(httpPost);
            HttpEntity httpEntity = response.getEntity();
            String rescontent = new String(InputStreamTOByte(httpEntity.getContent()));
            System.out.println("返回内容:" + rescontent);
            //获取返回的http header
            Header headers[] = response.getAllHeaders();
            int i = 0;
            while (i < headers.length) {
                System.out.println(headers[i].getName() + ":  " + headers[i].getValue());
                i++;
            }
    
            //验证微信支付返回签名
            String Wtimestamp = response.getHeaders("Wechatpay-Timestamp")[0].getValue();
            String Wnonce = response.getHeaders("Wechatpay-Nonce")[0].getValue();
            String Wsign = response.getHeaders("Wechatpay-Signature")[0].getValue();
            //拼装待签名串
            StringBuffer ss = new StringBuffer();
            ss.append(Wtimestamp).append("\n");
            ss.append(Wnonce).append("\n");
            ss.append(rescontent).append("\n");
            //验证签名
            if(verifyRSA(ss.toString(), Base64.decodeBase64(Wsign.getBytes()), rsaPublicKeyFile)) {
                System.out.println("签名验证成功");
            } else {
                System.out.println("签名验证失败");
            }
    
            EntityUtils.consume(httpEntity);
            response.close();
    
        } catch (Exception e) {
            System.out.println("发送POST请求异常!" + e);
            e.printStackTrace();
        }
    }
    
    public static byte[] InputStreamTOByte(InputStream in) throws IOException {
    
        int BUFFER_SIZE = 4096;
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] data = new byte[BUFFER_SIZE];
        int count = -1;
    
        while((count = in.read(data,0,BUFFER_SIZE)) != -1)
            outStream.write(data, 0, count);
    
        data = null;
        byte[] outByte = outStream.toByteArray();
        outStream.close();
    
        return outByte;
    }
    
    
    public static byte[] signRSA(String data, String priKey) throws Exception {
        //签名的类型
        Signature sign = Signature.getInstance("SHA256withRSA");
        //读取商户私钥,该方法传入商户私钥证书的内容即可
        byte[] keyBytes = Base64.decodeBase64(priKey);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        sign.initSign(privateKey);
        sign.update(data.getBytes("UTF-8"));
        return sign.sign();
    }
    
    public static boolean verifyRSA(String data, byte[] sign, String pubKey) throws Exception{
        if(data == null || sign == null || pubKey == null){
            return false;
        }
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        FileInputStream in = new FileInputStream(pubKey);
        Certificate c = cf.generateCertificate(in);
        in.close();
        PublicKey publicKey = c.getPublicKey();
        Signature signature = Signature.getInstance("SHA256WithRSA");
        signature.initVerify(publicKey);
        signature.update(data.getBytes("UTF-8"));
        return signature.verify(sign);
    }
    


    03-24
    赞同
    回复 1
    • 微笑生活
      微笑生活
      03-24
      多谢大神!获取到上传的图片返回的内容了,另外想问下,verifyRSA验证签名的目的是啥,验证失败了,我看注释是验证微信支付返回的签名
      03-24
      回复
登录 后发表内容
问题标签