最近在開發微信的小微商戶進件,裏面需要用到圖片上傳API,在這裏記錄一下。
官方文檔:https://pay.weixin.qq.com/wiki/doc/api/xiaowei.php?chapter=19_9
上代碼
WxUploadMediaBo.java
package com.pay.wechat.bo.small;
import java.io.File;
import java.io.FileInputStream;
import java.util.UUID;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import com.dlys.pay.wechat.protocol.WxUploadMediaModel;
import com.dlys.pay.wechat.util.HttpsRequest;
import com.dlyspublic.util.Config;
/**
* 微信上傳文件工具
*
* @author libaibai
* @version 1.0 2020年5月26日
*/
@Component
public class WxUploadMediaBo {
public void exe(MultipartFile multipartFile) throws Exception {
File excelFile = File.createTempFile(UUID.randomUUID().toString(), ".jpg");
multipartFile.transferTo(excelFile);
FileBody bin = new FileBody(excelFile, ContentType.create("image/jpg", Consts.UTF_8));
String hash = DigestUtils.md5Hex(multipartFile.getBytes());
WxUploadMediaModel model = new WxUploadMediaModel(hash, Config.APIKEY);
String sign = model.getSign();
HttpEntity httpEntity = MultipartEntityBuilder.create().addPart("media", bin).addTextBody("mch_id", Config.MCHIDSP)
.addTextBody("media_hash", hash).addTextBody("sign", sign).addTextBody("sign_type", "HMAC-SHA256").build();
try {
String url = "https://api.mch.weixin.qq.com/secapi/mch/uploadmedia";
HttpsRequest request = new HttpsRequest();
String str = request.sendPostObject(url, httpEntity);
System.out.println(str);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
WxUploadMediaBo test = new WxUploadMediaBo();
String p = "C:\\Users\\lift.CHINATENET\\Desktop\\文檔\\停車場照片\\1.jpg";
try {
File file = new File(p);
MultipartFile multipartFile = new MockMultipartFile("file", new FileInputStream(file));
test.exe(multipartFile);
} catch (Exception e) {
e.printStackTrace();
}
}
}
HttpsReqest.java
package com.dlys.pay.wechat.util;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import net.sf.json.JSONObject;
/**
* HTTP 請求類
*
* @author libaibai
* @version 1.0 2020年5月26日
*/
@Component
public class HttpsRequest {
public interface ResultListener {
public void onConnectionPoolTimeoutError();
}
private static Logger LOG = LogManager.getLogger(HttpsRequest.class);
private boolean hasInit = false;
// 連接超時時間,默認10秒
private int socketTimeout = 10000;
// 傳輸超時時間,默認30秒
private int connectTimeout = 30000;
// 請求器的配置
private RequestConfig requestConfig;
// HTTP請求器
private CloseableHttpClient httpClient;
/**
* 證書初始化
*
* @throws UnrecoverableKeyException
* @throws KeyManagementException
* @throws NoSuchAlgorithmException
* @throws KeyStoreException
* @throws IOException
*/
public HttpsRequest() throws UnrecoverableKeyException, KeyManagementException,
NoSuchAlgorithmException, KeyStoreException, IOException {
init();
}
private void init() throws IOException, KeyStoreException, UnrecoverableKeyException,
NoSuchAlgorithmException, KeyManagementException {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
InputStream instream = HttpsRequest.class.getClassLoader().getResourceAsStream(
Configure.CERTLOCAL_PATHx);// 加載本地的證書進行https加密傳輸
try {
keyStore.load(instream, Configure.CERTPASSWORD.toCharArray());// 設置證書密碼
} catch (Exception e) {
LOG.error("加載證書異常", e);
} finally {
instream.close();
}
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, Configure.CERTPASSWORD.toCharArray()).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,
new String[] { "TLSv1" }, null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
// 根據默認超時限制初始化requestConfig
requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout)
.setConnectTimeout(connectTimeout).build();
hasInit = true;
}
/**
* 通過Https往API GET
*
* @param url API地址
* @return API回包的實際數據
* @throws IOException
* @throws KeyStoreException
* @throws UnrecoverableKeyException
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
public String sendGET(String url) throws IOException, KeyStoreException,
UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException {
if (!hasInit) {
init();
}
String result = null;
HttpGet httpGet = new HttpGet(url);
// 得指明使用UTF-8編碼,否則到API服務器XML的中文不能被成功識別
httpGet.addHeader("Content-Type", "text/xml");
// 設置請求器的配置
httpGet.setConfig(requestConfig);
try {
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
result = EntityUtils.toString(entity, "UTF-8");
} catch (Exception e) {
LOG.error("HTTP Get請示異常", e);
} finally {
httpGet.abort();
}
return result;
}
/**
* 通過Https往API post
*
* @param url API地址
* @param Object 要提交的Object數據對象
* @return API回包的實際數據
* @throws IOException
* @throws KeyStoreException
* @throws UnrecoverableKeyException
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
public String sendPostObject(String url, HttpEntity postEntity) throws IOException, KeyStoreException,
UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException {
if (!hasInit) {
init();
}
String result = null;
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.MULTIPART_FORM_DATA.getMimeType());
httpPost.setEntity(postEntity);
// 設置請求器的配置
httpPost.setConfig(requestConfig);
try {
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
result = EntityUtils.toString(entity, "UTF-8");
} catch (Exception e) {
LOG.error("HTTP POST 請求異常", e);
} finally {
httpPost.abort();
}
return result;
}
/**
* 通過Https往API post xml數據
*
* @param url API地址
* @param xmlObj 要提交的XML數據對象
* @return API回包的實際數據
* @throws IOException
* @throws KeyStoreException
* @throws UnrecoverableKeyException
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
public String sendPost(String url, Object xmlObj) throws IOException, KeyStoreException,
UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException {
if (!hasInit) {
init();
}
String result = null;
HttpPost httpPost = new HttpPost(url);
// 解決XStream對出現雙下劃線的bug
XStream xStreamForRequestPostData = new XStream(new DomDriver("UTF-8",
new XmlFriendlyNameCoder("-_", "_")));
// 將要提交給API的數據對象轉換成XML格式數據Post給API
String postDataXML = xStreamForRequestPostData.toXML(xmlObj);
// LOG.info("請求微信接口->url="+url+",data="+postDataXML);
// 得指明使用UTF-8編碼,否則到API服務器XML的中文不能被成功識別
StringEntity postEntity = new StringEntity(postDataXML, "UTF-8");
httpPost.addHeader("Content-Type", "text/xml");
httpPost.setEntity(postEntity);
// 設置請求器的配置
httpPost.setConfig(requestConfig);
try {
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
result = EntityUtils.toString(entity, "UTF-8");
} catch (Exception e) {
LOG.error("HTTP POST 請求異常", e);
} finally {
// httpPost.abort();
httpPost.releaseConnection();
}
return result;
}
/**
* 設置連接超時時間
*
* @param socketTimeout 連接時長,默認10秒
*/
public void setSocketTimeout(int socketTimeout) {
this.socketTimeout = socketTimeout;
resetRequestConfig();
}
/**
* 設置傳輸超時時間
*
* @param connectTimeout 傳輸時長,默認30秒
*/
public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
resetRequestConfig();
}
private void resetRequestConfig() {
requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout)
.setConnectTimeout(connectTimeout).build();
}
/**
* 允許商戶自己做更高級更復雜的請求器配置
*
* @param requestConfig 設置HttpsRequest的請求器配置
*/
public void setRequestConfig(RequestConfig requestConfig) {
this.requestConfig = requestConfig;
}
}
運行main方式得到返回結果
<xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<result_code><![CDATA[SUCCESS]]></result_code>
<media_id><![CDATA[HmddyW8NdBxhqQr_L1IEz6NiwSG6BzCCFVqsGKqO-d8mBsLI3KVj3Xwmixfqme-X7OeLHW0jrSBLEo3nCioKXqq6OQddGEj_SNRhd-5qI8I]]></media_id>
<sign><![CDATA[D0FF0FC24B6C51719A4D5CD4C95D721F]]></sign>
</xml>