微信/v3/merchant/media/upload 网络图片上传到微信接口java代码

bianmaren 发布于 2020-03-25 08:04:17    访问

标签 : JAVA 微信服务商

WX20200325-080349@2x.png

接口文档

https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/chapter3_1.shtml


代码

/**
 * v3 图片资料上传
 * @Param fileNetUrl 网络图片地址
 * @return
 */
public static String mediaUploadV3(String fileNetUrl){

   try {

      //商户号
      String mchid = "";
      //微信支付平台公钥
      String rsaPublicKeyFile = "";
      // 公钥文件路径
      String pubilcKeyPath = ""
      // 私钥文件路径
      String privageKeyPath = ""
      
    
      //证书序列号
      String serial_no = getSerialNo(pubilcKeyPath);

      //时间戳
      String timestamp = Long.toString(System.currentTimeMillis()/1000);
      //随机数
      String nonce_str = randomString(32).toUpperCase();

      //图片文件
      String filename = getFileNameUrl(fileNetUrl);//文件名
      byte[] fileBytes = getImageFromNetByUrl(fileNetUrl);
      String fileSha256 = DigestUtils.sha256Hex(new ByteArrayInputStream(fileBytes));//文件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(),privageKeyPath)));
      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("Accept","application/json");
      httpPost.addHeader("Content-Type","multipart/form-data");
      httpPost.addHeader("Authorization", authorization);

      //创建MultipartEntityBuilder
      MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
      //设置boundary
      multipartEntityBuilder.setBoundary("boundary");
      multipartEntityBuilder.setCharset(StandardCharsets.UTF_8);
      //设置meta内容
      multipartEntityBuilder.addTextBody("meta","{\"filename\":\""+filename+"\",\"sha256\":\""+fileSha256+"\"}", ContentType.APPLICATION_JSON);
      //设置图片内容
      multipartEntityBuilder.addBinaryBody("file", fileBytes, ContentType.create("image/jpg"), filename);
      //放入内容
      httpPost.setEntity(multipartEntityBuilder.build());

      //获取返回内容
      CloseableHttpResponse response = httpclient.execute(httpPost);
      HttpEntity httpEntity = response.getEntity();
      String rescontent =new String(readInputStream(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();

      return rescontent;

   }catch (Exception e){
      
   }

   return null;

}

public static byte[] signRSA(String data,privageKeyPath) throws Exception {
   //签名的类型
   Signature sign = Signature.getInstance("SHA256withRSA");
   sign.initSign(getPrivateKey(privageKeyPath));
   sign.update(data.getBytes(StandardCharsets.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(StandardCharsets.UTF_8));
   return signature.verify(sign);

}

/**
 * 获取私钥。
 *
 * @param filename 私钥文件路径  (required)
 * @return 私钥对象
 */
public static PrivateKey getPrivateKey(String filename) throws IOException {
    String content = new String(Files.readAllBytes(Paths.get(filename)), StandardCharsets.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.decodeBase64(privateKey)));
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException("当前Java环境不支持RSA", e);
    } catch (InvalidKeySpecException e) {
        throw new RuntimeException("无效的密钥格式");
    }
}

/**
 * 获取证书序列号
 *
 * @param certPath 获取商户证书序列号 传递商号证书路径 apiclient_cert
 * @return
 * @throws IOException
 */
public static String getSerialNo(String certPath) throws IOException {
    X509Certificate certificate = getCertificate(certPath);
    return certificate.getSerialNumber().toString(16).toUpperCase();
}


public static String getFileNameUrl(String url) {
    try {
        String[] url_split = url.split("/");
        String name = url_split[url_split.length - 1];
        String suffixes = name.split("\\.")[name.split("\\.").length - 1];
        return getFileNameNoEx(name) + "." + suffixes;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}


/**
 * 根据地址获得数据的字节流
 *
 * @param strUrl 网络连接地址
 * @return
 */
public static byte[] getImageFromNetByUrl(String strUrl) {
    try {
        URL url = new URL(strUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(5 * 1000);
        InputStream inStream = conn.getInputStream();// 通过输入流获取图片数据
        return readInputStream(inStream);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

/**
 * @Function: 从输入流中获取数据
 * @param inStream - 输入流
 * @throws IOException
 */
public static byte[] readInputStream(InputStream inStream) throws IOException {
    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int len = 0;
    while ((len = inStream.read(buffer)) != -1) {
        outStream.write(buffer, 0, len);
    }
    inStream.close();
    return outStream.toByteArray();
}

/**
 * 
 * @Description: 随机字符串
 * @author 441889070@qq.com
 * @date 2015年11月12日 下午1:55:21
 * @param
 */
 public static String randomString(int length)
 {
     String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
     Random random = new Random();
     StringBuffer buf = new StringBuffer();
     for(int i = 0 ;i < length ; i ++)
     {
         int num = random.nextInt(62);
         buf.append(str.charAt(num));
     }
     return buf.toString();
 }