SpringBoot 微信支付V3接口图片上传工具类

本文介绍了如何使用微信V3接口进行图片上传,并详细展示了Token的生成过程,包括nonce_str、timestamp、signature的构建及私钥的使用。同时提供了上传工具示例和HttpUtils方法,帮助开发者快速集成微信支付图片上传功能。
摘要由CSDN通过智能技术生成

微信V3接口 图片上传API

准备一个V3接口Token生成工具

package com.youjia.datacenter.base.util.pay.wxPay;

import com.youjia.datacenter.util.RandomUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

public class WxV3TokenUtil {
    private final static Logger logger = LoggerFactory.getLogger(WxV3TokenUtil.class);



    public static String getToken(String method, String url, String body) throws Exception {
        String nonceStr = RandomUtil.str_(32);
        long timestamp = System.currentTimeMillis() / 1000;
        String message = buildMessage(method, url, timestamp, nonceStr, body);
        String signature = sign(message.getBytes("UTF-8"));
        return "mchid=\"" + WxConfig.INSTANCE.getMchId() + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + WxConfig.INSTANCE.getApiCertSerialNumber() + "\","
                + "signature=\"" + signature + "\"";
    }

    private static String sign(byte[] message) throws Exception {

        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(getPrivateKey());
        sign.update(message);

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

    private static String buildMessage(String method, String url, long timestamp, String nonceStr, String body) throws Exception{
        return method + "\n"
                + url + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }

    private static PrivateKey getPrivateKey() throws IOException {
        //privateKeyData 是微信支付证书中的 apiclient_key.pem
        String content = new String(WxConfig.INSTANCE.getPrivateKeyData(), "UTF-8");
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");
            logger.info("privateKey:" + privateKey);
            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) {
            logger.info("异常:" + e);
            throw new RuntimeException("无效的密钥格式");
        }

    }
}

编写上传工具

package com.youjia.datacenter.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.youjia.datacenter.base.config.SysConfig.MpConstants;
import com.youjia.datacenter.base.util.pay.wxPay.WxConfig;
import com.youjia.datacenter.base.util.pay.wxPay.WxV3TokenUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.FormBodyPart;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.AbstractContentBody;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.StringBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class WxMediaUploadUtil {
    private final static Logger logger = LoggerFactory.getLogger(WxMediaUploadUtil.class);
    /**
     * 上传图片文件至微信服务器
     * @param fileName
     * @Param filePath
     * @return 微信mediaId
     */
    public static String uploadMediaFile(String fileName,String filePath){
        if(StringUtils.isBlank(filePath)){
            return null;
        }
        File file = new File(filePath);
        if(!file.exists()){
            return null;
        }
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(file);
            String sha256 = DigestUtils.sha256Hex(fileInputStream);
            String url = MpConstants.WX_UPLOAD_FILE_URL;
            String signUrl = url.replace("https://api.mch.weixin.qq.com","");

            //根属性
            JSONObject root = new JSONObject();

            //mate
            JSONObject meta = new JSONObject();
            meta.put("filename",fileName);
            meta.put("sha256",sha256);
            String json = root.toJSONString();
            //获取签名字符串
            String sign = WxV3TokenUtil.getToken("POST",signUrl,meta.toJSONString());
            Map<String,String> headers = new HashMap<>();
            String authorization  = "WECHATPAY2-SHA256-RSA2048 "+sign;
            headers.put("Authorization",authorization);
            headers.put("Content-Type","multipart/form-data");
            headers.put("Accept", "application/json");
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().addBinaryBody("file",file).addPart("meta",new StringBody(meta.toJSONString(),ContentType.APPLICATION_JSON)).setContentType(ContentType.MULTIPART_FORM_DATA);
            String res = HttpUtils.httpsPostFile(url,multipartEntityBuilder,headers);
            logger.info(">>>>>提交微信图片 res={"+res+"}");
            JSONObject result = JSON.parseObject(res);
            if(result.containsKey("media_id")){
                return result.getString("media_id");
            }
            logger.error(">>>>>上传文件到微信未成功,res={"+res+"}");
            return null;
        } catch (Exception e) {
            logger.error(">>>>>上传图片到微信出现错误",e);
        }finally {
            try {
                fileInputStream.close();
            } catch (IOException e) {
                logger.error(">>>>>>");
            }
        }
        return null;
    }
}

代码中使用的HttpUtils

此工具类在此博客 HttpUtils

将此方法添加至HttpUtils中

public static String httpsPostFile(String url, MultipartEntityBuilder multipartEntityBuilder,Map<String,String> headers) throws Exception {
        CloseableHttpClient hp = createSSLClientDefault();
        HttpPost httpPost = new HttpPost(url);
        Iterator<Map.Entry<String, String>> iterator = headers.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            httpPost.setHeader(entry.getKey(), entry.getValue());
        }
        //httpPost.setHeader("Content-Type","application/json");
        multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        HttpEntity httpEntity = multipartEntityBuilder.build();
        httpPost.setEntity(httpEntity);
        CloseableHttpResponse response = hp.execute(httpPost);
        HttpEntity entity = response.getEntity();
        String content = EntityUtils.toString(entity, "UTF-8");
        hp.close();
        return content;
    }

测试

在这里插入图片描述
在这里插入图片描述
打印出微信返回的media_id

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值