回顾

第一步:平台序列号获取

开始图片上传

微信官方图片上传文档 阅读文档可知

  • 请求的url: api.mch.weixin.qq.com/secapi/mch/…
  • 提交方式: multipart/form-data
  • 是否需要证书: 是

参数了解

  • mch_id : 商户号
  • media : 媒体文件(form-data中媒体文件标识,有filename、filelength、content-type等信息。不参与签名计算)
  • media_hash : 媒体文件内容hash值(根据媒体文件内容进行MD5计算后的值,注意小写)
  • sign : 签名
  • sign_type : 签名方式( HMAC-SHA256加密方式,其他或者不填为MD5方式)

证书获取

微信官方证书使用

最终有个apiclient_cert.p12 文件

呃。。。。。。。。。先丢个pom文件,防止童鞋们乱找一通

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.li</groupId><artifactId>micro-merchant</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.8.RELEASE</version></parent><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.6</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpmime</artifactId><version>4.5.3</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.18</version><scope>provided</scope></dependency> <dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.1</version></dependency><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><dependency><groupId>jaxen</groupId><artifactId>jaxen</artifactId><version>1.1.6</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>${java.version}</source><target>${java.version}</target></configuration></plugin></plugins></build></project>复制代码

代码:

package com.li.utils;import org.apache.http.ssl.SSLContexts;
import org.apache.tomcat.util.http.fileupload.IOUtils;import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;public class SSLContextUtils {/*** 获取证书内容* @param certPath 证书地址* @param mchId 商户号* @return*/public static SSLContext getSSLContext(String certPath, String mchId) {InputStream inputStream;try {inputStream = new FileInputStream(new File(certPath));} catch (Exception e) {throw new RuntimeException(e);}try {KeyStore keystore = KeyStore.getInstance("PKCS12");char[] partnerId2charArray = mchId.toCharArray();keystore.load(inputStream, partnerId2charArray);return SSLContexts.custom().loadKeyMaterial(keystore, partnerId2charArray).build();} catch (Exception var9) {throw new RuntimeException("证书文件有问题,请核实!", var9);} finally {IOUtils.closeQuietly(inputStream);}}
}复制代码
  • certPath : 证书地址
  • mchId : 商户号

第二步 httpClient上传图片至微信官方

package com.li.upload.service.impl;import com.li.upload.service.UploadService;
import com.li.utils.SSLContextUtils;
import com.li.utils.SignUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;@Service
@Slf4j
public class UploadServiceImpl implements UploadService{@Overridepublic String uploadFile(MultipartFile multipartFile) {HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/secapi/mch/uploadmedia");httpPost.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.MULTIPART_FORM_DATA.getMimeType());CloseableHttpClient client = null;File excelFile = null;String error = null;try {client = HttpClients.custom().setSSLContext(SSLContextUtils.getSSLContext("证书地址","商户号")).build();// 生成签名和图片md5加密String hash = DigestUtils.md5Hex(multipartFile.getBytes());Map<String, String> param = new HashMap<>(3);param.put("media_hash", hash);param.put("mch_id", "商户号");param.put("sign_type", "HMAC-SHA256");// 配置post图片上传// 用uuid作为文件名,防止生成的临时文件重复excelFile = File.createTempFile(UUID.randomUUID().toString(), ".jpg");multipartFile.transferTo(excelFile);FileBody bin = new FileBody(excelFile, ContentType.create("image/jpg", Consts.UTF_8));HttpEntity build = MultipartEntityBuilder.create().setCharset(Charset.forName("utf-8")).addTextBody("media_hash", hash).addTextBody("mch_id", "商户号").addTextBody("sign_type", "HMAC-SHA256").addTextBody("sign", SignUtil.wechatCertficatesSignBySHA256(param, "api密钥")).addPart("media", bin).build();httpPost.setEntity(build);HttpResponse httpResponse = client.execute(httpPost);if (httpResponse != null && httpResponse.getStatusLine().getStatusCode() == 200) {String responseEntity = EntityUtils.toString(httpResponse.getEntity());log.info("upload response {}", responseEntity);Document document = DocumentHelper.parseText(responseEntity);if ("SUCCESS".equalsIgnoreCase(document.selectSingleNode("//return_code").getStringValue())) {if ("SUCCESS".equalsIgnoreCase(document.selectSingleNode("//result_code").getStringValue())) {return document.selectSingleNode("//media_id").getStringValue();}}log.error("上传图片失败,异常信息 code ={} des = {}", document.selectSingleNode("//err_code").getStringValue(), document.selectSingleNode("//err_code_de").getStringValue());error = document.selectSingleNode("//err_code_de").getStringValue();}} catch (Exception e) {log.error("微信图片上传异常 , e={}", e);} finally {if (client != null) {try {client.close();} catch (IOException e) {log.warn("关闭资源httpclient失败 {}", e);}}if (excelFile != null) {deleteFile(excelFile);}}return error;}/*** 删除临时文件** @param files*/private void deleteFile(File... files) {for (File file : files) {if (file.exists()) {file.delete();}}}
}复制代码

第三步,编写controller

package com.li.upload.controller;import com.li.upload.service.UploadService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;/*** 小微商户*/
@Slf4j
@RequestMapping("/microMerchant")
@RestController
public class MicroMerchantUploadController {@Autowiredprivate UploadService uploadService;/*** 上传小微商户图片** @param multipartFile* @return*/@PostMapping("/upload")public String upload(@RequestParam(value = "file", required = false) MultipartFile multipartFile) {log.info("图片大小 {}", multipartFile.getSize());return uploadService.uploadFile(multipartFile);}
}复制代码

第四步 测试

你可以使用postman测试,我这边写了个单元测试进行测试

package com.li.upload;import com.li.upload.service.UploadService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.FileInputStream;@RunWith(SpringRunner.class)
@SpringBootTest
public class UploadServiceImplTest {@Autowiredprivate UploadService uploadService;@Testpublic void uploadFile() throws Exception {File file = new File("图片路径");MultipartFile multipartFile = new MockMultipartFile("file", new FileInputStream(file));String s = uploadService.uploadFile(multipartFile);System.out.println(s);}
}复制代码

返回结果

<xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<result_code><![CDATA[SUCCESS]]></result_code>
<media_id><![CDATA[kYCkWJ1W0i8M1XytDfoSbnyQHmE5VCW2xxxlaDOzMkzN0-kFj5NleA1tYJGZYU3b1SF_61-33CAv8YCkWJ1W0i8M1XytDfoSbnyQHmE5VCW2xxxlaDOzMkzN0-kFj5NleA1tYJGZYU3b1SF_61-33CAv8]]></media_id>
<sign><![CDATA[292F505745839F140B35C6552647C135]]></sign>
</xml>复制代码

最终得到media_id

源代码

github.com/bertonlee/m… 分支为upload

如果帮助到您,欢迎star

个人博客地址

www.ccode.live/bertonlee/l…

欢迎关注公众号“码上开发”,每天分享最新技术资讯

微信支付:小微商户申请入驻第二步:图片上传相关推荐

  1. nodejs实现微信支付小微商户申请入驻接口

    微信支付小微商户可以通过小程序<微信买单服务商助手>来进件,也可以通过API接口来进件(详情可查阅小微商户专属接口文档). 2种方式进件后的商户是有区别的 不同进件方式下的小微商户对比   ...

  2. nodejs微信支付小微商户申请入驻时,如何实现图片上传接口

    微信支付小微商户可以通过小程序<微信买单服务商助手>来进件,也可以通过API接口来进件(详情可查阅小微商户专属接口文档). 通过API接口进件前需要先在商户资料中的身份证照片和门店照片通过 ...

  3. 微信支付:小微商户申请入驻第三步:平台证书序列号解密和敏感词加密

    首先,还是上微信官方链接 微信官方平台证书解密指引 微信官方敏感词加密指引 平台证书解密 定义接口 首先,由于平台证书获取,跟解密,都是平台证书这货的,那就放在同一个service吧.pom文件之前文 ...

  4. 个人免费申请微信支付小微商户指南

    什么是小微商户 小微商户是指依据法律法规和相关监管规定免于办理工商注册登记.无营业执照的实体特约商户. 微信小微商户 微信支付商户申请面向线下小微商户开放,符合条件的微信支付服务商可为小微商户发起接入 ...

  5. 小微商户申请php,微信小微商户申请入驻 - osc_r8q2esik的个人空间 - OSCHINA - 中文开源技术交流社区...

    public static string ApplyEnter(string Data) { if (string.IsNullOrWhiteSpace(Data)) return ProtocolM ...

  6. 微信小程序之Array操作、图片上传

    一.Array操作 1,渲染 Array 对象数组多用于列表渲染,对于列表中的数据,能够进行十分便捷有效的存储. .wxml<view class='clazz-item' bindtap='s ...

  7. JAVA微信公众号开发第8篇JSSDK图片上传预览

    简介 博主微信JSSDK&图片上传预览基于微信分享做拓展,所以一些配置操作请点击查阅JAVA微信公众号开发第7篇JSSDK&微信分享博文 页面 <html><head ...

  8. uni-app - 头像图片裁剪组件(支持多种裁剪,手势控制旋转或缩放、内外部控制图片移动、提供上传后端接口方案、头像图片美化)全端完美兼容 H5 App 小程序,最好用的图片上传后裁剪插件教程源代码

    前言 网上的教程代码非常乱且都有 BUG 存在,非常难移植到自己的项目中,而且很难. 实现了 完美兼容 H5 App 小程序,选取手机本地相册或拍照,图片上传裁切内置多种方案,样式随便改, 本文代码干 ...

  9. 微信公众号调用手机相册并将图片上传到本地服务器

    最近有一个需求,用公众号调用本地相册,并将图片上传到本地服务器(不是微信服务器). 步骤一:引入JS文件 在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq ...

最新文章

  1. 微软正式发布Azure Storage上的静态网站
  2. 01-html介绍和head标签
  3. python基础-字符串
  4. Chrome报错:Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.
  5. T5 PEGASUS:开源一个中文生成式预训练模型
  6. VMware10.0.4下 CentOS 6.5 cmake安装 MySQL 5.5.32
  7. CNN结构:SPP-Net为CNNs添加空间尺度卷积-神经元层
  8. 马尔可夫网络,(马尔可夫随机场、无向图模型)(Markov Random Field)
  9. 待支付取件费用是什么意思_1元保管费与直接取件,你赞赏丰巢快递柜了吗?...
  10. RMAN-06023: no backup or copy of datafile 6 found to restore
  11. leetcode题解20-有效的括号
  12. bzoj 1124: [POI2008]枪战Maf(贪心)
  13. Multipart生成的临时文件
  14. 为了战略发展,Adobe推出自己浏览器?
  15. windows转换U盘格式
  16. jQuery动画入门--顺序执行
  17. (新手向)零基础探究机器学习Crime_Prediction
  18. k8s报错1 node(s) had taints that the pod didn‘t tolerate
  19. click和on click区别
  20. goldengate——简介

热门文章

  1. BZOJ 1370: [Baltic2003]Gang团伙 [并查集 拆点 | 种类并查集WA]
  2. 详解Linux Initrd
  3. 存储过程里output的使用总结
  4. 基本类型和操作之富包装器
  5. Xamarin.FormsShell基础教程(8)Shell的模版构成
  6. 爆炸销毁动画组件Explosions
  7. 网络协议图形化分析工具EtherApe
  8. Arduino可穿戴开发入门教程Windows平台下安装Arduino IDE
  9. python 英语翻译 excel_python批量将excel内容进行翻译写入功能
  10. java 二维数组内存溢出_模拟Java内存溢出