微信支付V3图片上传API 实现和 微信文档的大坑

如果 你照着微信文档  做 一直报签名失败 ,但是你敢肯定签名正确,那么 问题出在哪呢, 如上图 红色框所示,这个地方微信文档写错了, 应该 为 boundary=boundary     不加双引号     后面boundary 为任意值 ,比如  boundary=111111 ,具体看下面代码示例。

package com.fykj.web.rest.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fykj.tool.document.AuthorizationUtil;
import com.fykj.tool.document.PrivateKeyUtil;
import okhttp3.HttpUrl;
import org.apache.commons.codec.digest.DigestUtils;
import org.junit.Test;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SignatureException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class UploadImageTest2 {
    @Test
    public void test(){
        String privateKeyContent="";
        String merchantId="";
        String serinalNo="";
        String url="https://api.mch.weixin.qq.com/v3/merchant/media/upload";
        File file = new File("C:\\Users\\Administrator\\Desktop\\icon.png");
        String name = file.getName();
        String schema="WECHATPAY2-SHA256-RSA2048";
        try {
            String boundary="11111111";
            System.out.println(boundary);
            HttpUrl httpUrl = HttpUrl.get(url);
            FileInputStream fileInputStream = new FileInputStream( file);
            String sha256Content = DigestUtils.sha256Hex(fileInputStream);
            Map<String,Object> map = new HashMap<>();
            map.put("filename",name);
            map.put("sha256",sha256Content);
            ObjectMapper objectMapper = new ObjectMapper();
            String json = objectMapper.writeValueAsString(map);
            PrivateKey privateKey = PrivateKeyUtil.getPrivateKeyByContent(privateKeyContent);
            String encryContent = AuthorizationUtil.getToken("POST", httpUrl, json, privateKey, merchantId, serinalNo);
            String authorization=schema+" "+encryContent;
            System.out.println(authorization);
            URL urlObj = new URL(url);
            HttpURLConnection con = (HttpURLConnection)urlObj.openConnection();
            //设置请求头
            con.setRequestMethod("POST");
            con.setDoInput(true);
            con.setDoOutput(true);
            con.setUseCaches(false); //post 方式 不能使用缓存
            con.setRequestProperty("Connection", "Keep-Alive");
            con.setRequestProperty("Charset", "UTF-8");
           // con.setRequestProperty("Content-type","multipart/form-data");
            con.setRequestProperty("Authorization",authorization);
            con.setRequestProperty("Content-Type","multipart/form-data;boundary="+boundary);
            //请求正文  第一部分
            StringBuffer stringBuffer  =new StringBuffer();
            stringBuffer.append("--"+boundary+"\r\n");
            stringBuffer.append("Content-Disposition: form-data; name=\"meta\";"+"\r\n");
            stringBuffer.append("Content-Type: application/json"+"\r\n");
            stringBuffer.append("\r\n");
            stringBuffer.append(json+"\r\n");
            stringBuffer.append("--"+boundary+"\r\n");
            OutputStream out = new DataOutputStream(con.getOutputStream());
            out.write(stringBuffer.toString().getBytes());
            out.flush();
            //第二部分
            StringBuffer stringFileBuffer  =new StringBuffer();
            stringFileBuffer.append("Content-Disposition: form-data; name=\"file\"; filename=\""+name+"\";"+"\r\n");
            stringFileBuffer.append("Content-Type: image/jpg");
            stringFileBuffer.append("\r\n");
            out.write(stringFileBuffer.toString().getBytes());
            out.flush();
            // 二进制内容
            DataInputStream  in  = new DataInputStream(fileInputStream);
            int length=0;
            byte[] bytes = new byte[1024];
            while((length=in.read(bytes))!=-1){
                out.write(bytes,0,length);
            }
            in.close();
            fileInputStream.close();
            String foot ="\r\n"+"--"+boundary+"--"+"\r\n";
            out.write(foot.getBytes("utf-8"));
            out.flush();
            out.close();
            String rescontent ="";
            Map<String, List<String>> responseHeader = con.getHeaderFields();
            for (Map.Entry<String, List<String>> entry : responseHeader.entrySet()) {
                System.out.println(entry.getKey()+":" + entry.getValue());
            }
            int responseCode = con.getResponseCode();
            System.out.println(responseCode);
            InputStream errorStream = con.getErrorStream();


                int BUFFER_SIZE =4096;
                ByteArrayOutputStream outStream =new ByteArrayOutputStream();
                byte[] data =new byte[BUFFER_SIZE];
                int count = -1;

                while((count = errorStream.read(data,0,BUFFER_SIZE)) != -1)
                    outStream.write(data,0, count);

                data =null;
                byte[] outByte = outStream.toByteArray();
                outStream.close();


            rescontent =new String(outByte);
            System.out.println("图片上传失败:"+rescontent);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
    }


}

package com.fykj.tool.document;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

public class PrivateKeyUtil {
    /**
     * 获取私钥。
     *
     * @param filename 私钥文件路径  (required)
     * @return 私钥对象
     */
    public static PrivateKey getPrivateKey(String filename) throws IOException {

        String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");

            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }
    /**
     * 获取私钥。
     *
     * @param content 私钥文件路径  (required)
     * @return 私钥对象
     */
    public static PrivateKey getPrivateKeyByContent(String content) throws IOException {


        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");

            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }
}

 

package com.fykj.tool.document;

import okhttp3.HttpUrl;

import java.io.UnsupportedEncodingException;
import java.security.*;
import java.util.Base64;
import java.util.Random;

public class AuthorizationUtil {
   public static  String getToken(String method, HttpUrl url, String body,PrivateKey yourPrivateKey,String yourMerchantId,String yourCertificateSerialNo) throws UnsupportedEncodingException, NoSuchAlgorithmException, SignatureException, InvalidKeyException {
        String nonceStr = "abcdefgh";
        long timestamp = System.currentTimeMillis() / 1000;
        String message = buildMessage(method, url, timestamp, nonceStr, body);
        System.out.println("message===="+message);
        String signature = sign(message.getBytes("utf-8"),yourPrivateKey);
       return "mchid=\"" + yourMerchantId + "\","
           + "nonce_str=\"" + nonceStr + "\","
           + "timestamp=\"" + timestamp + "\","
           + "serial_no=\"" + yourCertificateSerialNo + "\","
           + "signature=\"" + signature + "\"";

    }

   private static String sign(byte[] message, PrivateKey yourPrivateKey) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException {
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(yourPrivateKey);
        sign.update(message);

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

   private static 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"
            + canonicalUrl + "\n"
            + timestamp + "\n"
            + nonceStr + "\n"
            + body + "\n";
    }
    private static String getRandomStringByLength(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }
}

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值