微信小微商戶進件:圖片上傳API

最近在開發微信的小微商戶進件,裏面需要用到圖片上傳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>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章