Java微信小微/特约商户进件:图片上传

官方文档:https://pay.weixin.qq.com/wiki/doc/api/xiaowei.php?chapter=19_9
在这里插入图片描述
代码实现
控制层

@ApiOperation(value = "微信图片上传", notes = "微信图片上传")
    @PostMapping("/uploadWxImg")
    public Result uploadWxImg(MultipartFile file) {
        try {
            String mch_id = "*******";//微信服务商商户号
            String payKey = "****************";//服务商商户号对应的商户密钥
            File file1 = new File(file.getOriginalFilename());
            FileUtils.copyInputStreamToFile(file.getInputStream(), file1);
            //D:\\666\\apiclient_cert.p12 证书存放位置
            String str = UploadDemo.upload(file1, mch_id, "D:\\666\\apiclient_cert.p12",
                    "https://api.mch.weixin.qq.com/secapi/mch/uploadmedia", payKey);
            // 会在本地产生临时文件,用完后需要删除 如果发现代码不完整的qq1023732997
            if (file1.exists()) {
                file1.delete();
            }
            return Result.success(str);
        } catch (Exception e) {
            log.error("系统出错:{}", e);
            return Result.fail();
        }
    }

UploadDemo类

package com.shifen.manager.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class UploadDemo {
    private static final Logger logger = LoggerFactory.getLogger(UploadDemo.class);


    /**
     * 真实上传方法
     *
     * @param file
     * @param mch_id
     * @param keyStoreUrl
     * @param requestUrl
     * @param payKey      <p>
     *                    对上次文件进行MD5获取其Hash
     * @param payKey      签名密钥
     * @return 待签名字符串
     */

    public static String upload(File file, String mch_id, String keyStoreUrl, String requestUrl, String payKey) {

        try {

            String media_hash = md5HashCode(new FileInputStream(file));
            String sign_type = "HMAC-SHA256";
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("mch_id", mch_id);
            paramMap.put("media_hash", media_hash);
            paramMap.put("sign_type", sign_type);
            String sign = sha256Sign(paramMap, payKey);

            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            multipartEntityBuilder.addTextBody("mch_id", mch_id, ContentType.MULTIPART_FORM_DATA);
            multipartEntityBuilder.addBinaryBody("media", file, ContentType.create("image/jpg"), file.getName());
            multipartEntityBuilder.addTextBody("media_hash", media_hash, ContentType.MULTIPART_FORM_DATA);
            multipartEntityBuilder.addTextBody("sign_type", sign_type, ContentType.MULTIPART_FORM_DATA);
            multipartEntityBuilder.addTextBody("sign", sign, ContentType.MULTIPART_FORM_DATA);

            FileInputStream instream = null;
            SSLContext sslcontext = null;
            try {
                KeyStore keyStore = KeyStore.getInstance("PKCS12");
                instream = new FileInputStream(new File(keyStoreUrl));
                keyStore.load(instream, mch_id.toCharArray());// 这里写密码..默认是你的MCHID
                sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mch_id.toCharArray()).build();
            } catch (Exception e) {
                logger.error("官方微信--证书加载失败!{}", e);
            } finally {
                try {
                    if (instream != null) {
                        instream.close();
                    }
                } catch (IOException e) {
                    logger.error("官方微信--证书加载失败!{}", e);
                }
            }
            @SuppressWarnings("deprecation")
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
            try {
                HttpPost httpPost = new HttpPost(requestUrl);
                RequestConfig config = RequestConfig.custom().setConnectTimeout(10000).setConnectionRequestTimeout(10000).setSocketTimeout(10000).build();
                httpPost.setConfig(config);
                这里的Content-type要设置为"multipart/form-data",否则返回“参数填写有误,请检查后重试”
                httpPost.addHeader(HTTP.CONTENT_TYPE, "multipart/form-data; charset=UTF-8");
                httpPost.addHeader(HTTP.USER_AGENT, "wxpay sdk java v1.0 " + mch_id);
                httpPost.setEntity(multipartEntityBuilder.build());
                CloseableHttpResponse response = httpclient.execute(httpPost);
                String result = EntityUtils.toString(response.getEntity(), "UTF-8");
                logger.info("官方微信--请求返回结果:{}", result);
                return result;
            } catch (Exception e) {
                logger.error("官方微信--请求失败!{}", e);
            }


        } catch (Exception e) {
            log.error("系统出错:{}", e);
        }
        return null;
    }

    /**
     * 对上次文件进行MD5获取其Hash值
     *
     * @param fis
     * @return
     */

    public static String md5HashCode(InputStream fis) {
        try {
            MessageDigest MD5 = MessageDigest.getInstance("MD5");
            byte[] buffer = new byte[8192];
            int length;
            while ((length = fis.read(buffer)) != -1) {
                MD5.update(buffer, 0, length);
            }
            return new String(Hex.encodeHex(MD5.digest()));
        } catch (Exception e) {
            log.error("系统出错:{}", e);
            return null;
        }
    }

    /**
     * 获取HMAC-SHA256签名
     *
     * @param paramMap 签名参数(sign不参与签名)
     * @param key      签名密钥
     * @param paramMap 签名参数(sign字段不参与签名)
     * @param
     * @param paramMap 签名参数(sign字段不参与签名)
     * @param paramMap 签名参数(sign字段不参与签名
     * @return 待签名字符串
     */

    public final static String sha256Sign(Map<String, Object> paramMap, String key) {
        try {
            String payParam = getSignTemp(paramMap, key);
            logger.info("签名原文:{}", payParam);
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
            sha256_HMAC.init(secret_key);
            byte[] array = sha256_HMAC.doFinal(payParam.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
            }
            String sign = sb.toString().toUpperCase();
            logger.info("签名结果:{}", sign);
            return sign;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取签名参数字符串
     *
     * @param paramMap 签名参数(sign字段不参与签名)
     * @param payKey   签名密钥
     * @return 待签名字符串
     */

    private final static String getSignTemp(Map<String, Object> paramMap, String payKey) {
        ArrayList<String> keyList = new ArrayList<>(paramMap.keySet());
        Collections.sort(keyList);
        StringBuilder signParam = new StringBuilder();
        for (String key : keyList) {
            if ("sign".equals(key) && !CommonUtils.isNullOrEmpty(paramMap.get(key))) {
                signParam.append(key).append("=").append(paramMap.get(key)).append("&");
            }
        }
        System.out.println(signParam.length());
        signParam.delete(signParam.length() - 1, signParam.length());
        signParam.append("&key=").append(payKey);
        //注意这里返回的值 一定是把mch_id等拼接起来的一大串
        return signParam.toString();
    }
}

依赖

<repositories>
        <repository>
            <id>jitpack.io</id>
            <url>https://jitpack.io</url>
        </repository>
    </repositories>
<dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.57</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.3.0</version>
        </dependency>

结果:
在这里插入图片描述
在这里插入图片描述
想学更多内容关注我

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云上上云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值