微信小微商户进件(三):申请入驻

 

前面讲了,获取证书和获取证书和上传图片,现在我们进入主题,讲申请入驻。

 

首先打开官方文档:https://pay.weixin.qq.com/wiki/doc/api/xiaowei.php?chapter=19_2

接口链接

URL地址:https://api.mch.weixin.qq.com/applyment/micro/submit

是否需要证书

请求需要双向证书。 详见证书使用

 

1. 请求参数说明

平台证书序列号(cert_sn),请参考第一小节:获取证书

 

2. 敏感信息加密

我们先看一下官方的解释:

意思是说,我们还需要解密证书,才能得到证书内容,才能用他来加密。这里我们使用官方的例子:

package com.pay.wechat.util;

import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * 
 * @author libaibai
 * @version 1.0 2020年5月26日
 */
public class WxAesGcmExample {
	private static final String ALGORITHM = "AES/GCM/NoPadding";
	private static final int TAG_LENGTH_BIT = 128;
	// private static final int NONCE_LENGTH_BYTE = 12;

	// private static final String TRANSFORMATION_PKCS1Padding = "RSA/ECB/PKCS1Padding";

	public static String aesgcmDecrypt(String aad, String iv, String cipherText) throws Exception {
		final Cipher cipher = Cipher.getInstance(ALGORITHM, "SunJCE");
		SecretKeySpec key = new SecretKeySpec(Configure.AES_KEY_APIV3.getBytes(), "AES");
		GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, iv.getBytes());
		cipher.init(Cipher.DECRYPT_MODE, key, spec);
		cipher.updateAAD(aad.getBytes());
		return new String(cipher.doFinal(Base64.getDecoder().decode(cipherText)));
	}

	public static void main(String[] args) {
		final String associatedData = "certificate"; // encrypt_certificate.associated_data
		final String nonce = "6742f1f9f00e"; // encrypt_certificate.nonce
		final String cipherText = "PFyVCE8Uh3PXuvwhhP7/kQ5m0SlNtSCE1xFtFrFWxMjdbAnxZEOxRqkeJUM2G39p/+JtdkAg0VAJcZkJAhNcuQUYSJbybG/CWPt4Pqj+OounkXFD/7+/XEudx8/oW8KBV/WgvhGdRNWrDCqJBOiWYLt9YNOh0PHdcjY06QW0GGcqPjQ2I8NGNqX99Zh9ehI6xg69VGIV1nid7U5seRboYmYbf5nJtPHT1VJDCEUzgpQ1zag+U2tCmA+1udGMmMwn4VLGham06UmN0p350oCiOJw/Z6QpkX8v+WyufwWb5RgdjkOx4ymUm6K1l7HUD07T28O/Dsk6l/v0hnvWyNo/aM8NRYCFo6FL92ivIf/tQKnCmH302nx4Ex0e+wMuNLdZ8uMk+mLBThc7vIpo2KeUScHvEC4FBiFUBhnP92jEA+V17QEfzIRH9McGuN/Wj3agsE6P8f3ZoJ5PuHND6pKjycfATphUMx+goMvZ0vTwzPRkJjFd2d9xJSTNrpf0bZouEN73ubH7qhE481pxpGNZRrhRLYT7dry3LmZGSN+yKujo270FG1HD2sp4wZr0aODGxoX+YBlvkPANKlOcd9SsRb+SDMIplt+TtX3Is8BNQs4rcYnclm8PRcoHFgewVRrGhKc7BVOzc8MoTCmbiBX1bsaqCmax2wVkfr6joLqyMlYbu3aq4ECOdzxB7OovwRWcNhtdfmZSQfoH3OftgH0If6GvRogyLKR1yI+FkREf+DGLU7cqkYuQdLMfnB68GApWQTCb8XsECGNNFCbUQ/EOW8asv+B/ICqBh10kygndkU16XDuYa+9BmNplim1AFWr7NP26oaGGcklIRBLBTbw4/pwXpyxnsZfRrRtBTcm9YqmU6HTO17yFPLa15aJlKMzcebYkQWqoYKcnkTFSqAMN56sFB5FkEmUtn768x5aDRbqgAhZRVsXChjJcTZQRTPma3hvAjHGIKK1gLn4VsXl7g4dCBdzcboCNA1EYDTIjHr6iy+ya30qsxINfR6U/J9kVt/TMKEyAAHw9U60I/R2g6dPLu5jcFa9pHw2tsO1OCgzn45SbG/K6YM5tA0pawBgnJpljqiW6nVvvQacoMIuQaXfoJ5egJ66gd52Q0f4MVbc9Tikn+RX7kvcxLamDCksGPJqqvkL2AvWIwhvS0MWA0qUrJ/s3dpb7fz7bQ3Eh/oCMQBbPpQEEHr5v2l5rw+mRpc8xcrUfSG4hsomJR0Fa9CLoP467INw6W7n4vw3Sifo5SNKMxNXCGrbAe5/IJ2FdkdXPdYql+ckpUnkw7/FNnAer4e+w8qRBJx7rHygufGGlAUTVjOAKPHvjeXXHuNL3xHQkVvOq2VM5er4CBigTwbcA7p/k1z8JpUOEC6CRwO9ZDD04U2CACtDd+UN5QsETtFwW/UEd6JyTFhENG8wYitRLaI6gVo0zYoHUL98itozosO5gqc4wTwEJMsT6CUHYrVknSHWDvmHyu37r+w5SHCcwYx84BdHmkQcDjcRI/dggyrj1J5xsCjFaSUu+kAq97KciLIuv9RZejaMzgBh4QGcqBF6JxqK+da3sJTk75LVD2sfbRGGo9rmF2Ceazd7gGN5m55NeCwjDmSnqf8+Bk3tNd0n7d7wiKuUaWJh/UpqfSABQre7Aj9iTwuALpz8P2ZbQp/YwfJ9OIoAyk7j14m29fBrvcpaHLOpq1PoE3uI+2LLnWQQ9qIQiA1PN474YUbhX6VKnofkk1uxCM+B4U2DelrxCucjIJkOtEInaxpBuCznW339cGlrnM1Wd+H3hfiI3DwIK5Gvfctnox2uGBLMo/I961wGUdhfuv8wen934VqBhHGBNlQg0JgLwgfihRfo4RxrjlmmGLrduNzdLL2pfffDfValBZ2Ia6KrU+Al5RZ81WoGR4hW/4K83XEevA9hY"; // encrypt_certificate.ciphertext
		try {
			String wechatpayCert = aesgcmDecrypt(associatedData, nonce, cipherText);
			System.out.println("wechatpayCert=" + wechatpayCert);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

从以上代码可以看得出来,主要用到了4个参数

associatedData,nonce,cipherText,aes_key_apiv3

前三个参数都可以在“获取证书”接口的返回值的找到,apiv3则需要到商户平台里面去设备,如下图:

找到参数,直接运行main方法,得到证书明文。

 

然后就可以对商户的数据,敏感信息加密了,官方也提供了加密的示例:

WxRSAEncryptUtil .java

package com.pay.wechat.util;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.PublicKey;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.security.cert.X509Certificate;

/**
 * 
 * @author libaibai
 * @version 1.0 2020年5月26日
 */
public class WxRSAEncryptUtil {

	// private static final String ALGORITHOM = "RSA";// 固定值,无须修改
	private static final String CIPHER_PROVIDER = "SunJCE";
	private static final String TRANSFORMATION_PKCS1Paddiing = "RSA/ECB/PKCS1Padding";

	private static final String CHAR_ENCODING = "UTF-8";// 固定值,无须修改
	// private static final String PUBLIC_KEY_FILENAME = "/path/certificate";// 平台证书路径,开发人员需根据具体路径修改
	// private static final String PUBLIC_KEY_FILENAME =
	// "G:\\workspace\\dlys\\src\\main\\resources\\conf\\cert\\apiclient_cert.pem";//
	// 平台证书路径,开发人员需根据具体路径修改

	// 数据加密方法
	private static byte[] encryptPkcs1padding(PublicKey publicKey, byte[] data) throws Exception {
		Cipher ci = Cipher.getInstance(TRANSFORMATION_PKCS1Paddiing, CIPHER_PROVIDER);
		ci.init(Cipher.ENCRYPT_MODE, publicKey);
		return ci.doFinal(data);
	}

	// 加密后的秘文,使用base64编码方法
	private static String encodeBase64(byte[] bytes) throws Exception {
		return Base64.getEncoder().encodeToString(bytes);
	}

	/**
	 * 对敏感内容(入参Content)加密,其中PUBLIC_KEY_FILENAME为存放平台证书的路径,平台证书文件存放明文平台证书内容,且为pem格式的平台证书(平台证书的获取方式参照平台证书及序列号获取接口,通过此接口得到的参数certificates包含了加密的平台证书内容ciphertext,然后根据接口文档中平台证书解密指引,最终得到明文平台证书内容)
	 * 
	 * @param Content 内容
	 * @param certpath 平台序列号接口解密后的密钥 pem 路径
	 * @return
	 * @throws Exception
	 */
	public static String rsaEncrypt(String Content, String certpath) throws Exception {
		final byte[] PublicKeyBytes = Files.readAllBytes(Paths.get(certpath));
		X509Certificate certificate = X509Certificate.getInstance(PublicKeyBytes);
		PublicKey publicKey = certificate.getPublicKey();

		return encodeBase64(encryptPkcs1padding(publicKey, Content.getBytes(CHAR_ENCODING)));
	}

	/**
	 * 直接使用接口cert解密
	 * 
	 * @param Content
	 * @param certStr
	 * @return
	 * @throws Exception
	 */
	public static String rsaEncryptByCert(String Content, String certStr) throws Exception {
		X509Certificate certificate = X509Certificate.getInstance(certStr.getBytes());
		PublicKey publicKey = certificate.getPublicKey();
		return encodeBase64(encryptPkcs1padding(publicKey, Content.getBytes(CHAR_ENCODING)));
	}

	// 对“hello world进行加密”
	public static void main(String[] args) {
		try {
			// System.out.println("after encrypt: " + rsaEncrypt("hello world"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

最后直接调用,申请入驻接口

WxSmallModel .java

package com.pay.wechat.protocol;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import com.pay.wechat.util.Configure;
import com.pay.wechat.util.Signature;
import com.util.Config;
import com.util.UUIDUtil;

/**
 * 小微商户进件信息
 * 
 * @author libaibai
 * @version 1.0 2020年5月26日
 */
public class WxSmallModel {

	private String version = "3.0"; // 版本号
	private String cert_sn; // 平台证书序列号
	private String mch_id = Config.MCHIDSP; // 服务商商户号

	private String nonce_str = UUIDUtil.getUUID19(); // 随机字符串
	private String sign_type = "HMAC-SHA256";// 签名类型,仅支持HMAC-SHA256 。该字段需参与签名sign的计算。

	private String sign = ""; // 签名
	private String business_code = UUIDUtil.getUUID32(); // 业务申请编号,服务商自定义的商户唯一编号。每个编号对应一个申请单,每个申请单审核通过后会生成一个微信支付商户号。

	private String id_card_copy; // 请填写由图片上传接口预先上传图片生成好的media_id
	private String id_card_national; // 请填写由图片上传接口预先上传图片生成好的media_id

	private String id_card_name; // 身份证姓名,
	private String id_card_number; //
	private String id_card_valid_time; // 身份证有效期限,例如:["1970-01-01","长期"]

	private String account_bank; // 开户银行
	private String bank_address_code; // 开户银行省市编码

	private String account_number = "";// 银行账号

	private String store_name; // 门店名称
	private String store_address_code; // 门店省市编码
	private String store_street; // 门店街道名称

	private String store_entrance_pic; // 门店门口照片
	private String indoor_pic; // 店内环境照片

	private String merchant_shortname; // 商户简称
	private String service_phone; // 客服电话

	private String product_desc; // 售卖商品/提供服务描述
	private String rate = "0.6%"; // 费率

	private String contact; // 超级管理员姓名
	private String contact_phone; // 手机号码

	public WxSmallModel(String cert_sn, String id_card_copy, String id_card_national, String id_card_name, String id_card_number,
			String id_card_valid_time, String account_bank, String bank_address_code, String account_number, String store_name,
			String store_address_code, String store_street, String store_entrance_pic, String indoor_pic, String merchant_shortname,
			String service_phone, String product_desc, String contact, String contact_phone, String key) {
		this.cert_sn = cert_sn;
		this.id_card_copy = id_card_copy;
		this.id_card_national = id_card_national;
		this.id_card_name = id_card_name;
		this.id_card_number = id_card_number;
		this.id_card_valid_time = id_card_valid_time;
		this.account_bank = account_bank;
		this.bank_address_code = bank_address_code;
		this.account_number = account_number;
		this.store_name = store_name;
		this.store_address_code = store_address_code;
		this.store_street = store_street;
		this.store_entrance_pic = store_entrance_pic;
		this.indoor_pic = indoor_pic;
		this.merchant_shortname = merchant_shortname;
		this.service_phone = service_phone;
		this.product_desc = product_desc;
		this.contact = contact;
		this.contact_phone = contact_phone;
		this.sign = Signature.getSignSha(toMap(), key);
	}

	public String getVersion() {
		return version;
	}

	public void setVersion(String version) {
		this.version = version;
	}

	public String getCert_sn() {
		return cert_sn;
	}

	public void setCert_sn(String cert_sn) {
		this.cert_sn = cert_sn;
	}

	public String getMch_id() {
		return mch_id;
	}

	public void setMch_id(String mch_id) {
		this.mch_id = mch_id;
	}

	public String getNonce_str() {
		return nonce_str;
	}

	public void setNonce_str(String nonce_str) {
		this.nonce_str = nonce_str;
	}

	public String getSign_type() {
		return sign_type;
	}

	public void setSign_type(String sign_type) {
		this.sign_type = sign_type;
	}

	public String getSign() {
		return sign;
	}

	public void setSign(String sign) {
		this.sign = sign;
	}

	public String getBusiness_code() {
		return business_code;
	}

	public void setBusiness_code(String business_code) {
		this.business_code = business_code;
	}

	public String getId_card_copy() {
		return id_card_copy;
	}

	public void setId_card_copy(String id_card_copy) {
		this.id_card_copy = id_card_copy;
	}

	public String getId_card_national() {
		return id_card_national;
	}

	public void setId_card_national(String id_card_national) {
		this.id_card_national = id_card_national;
	}

	public String getId_card_name() {
		return id_card_name;
	}

	public void setId_card_name(String id_card_name) {
		this.id_card_name = id_card_name;
	}

	public String getId_card_number() {
		return id_card_number;
	}

	public void setId_card_number(String id_card_number) {
		this.id_card_number = id_card_number;
	}

	public String getId_card_valid_time() {
		return id_card_valid_time;
	}

	public void setId_card_valid_time(String id_card_valid_time) {
		this.id_card_valid_time = id_card_valid_time;
	}

	public String getAccount_bank() {
		return account_bank;
	}

	public void setAccount_bank(String account_bank) {
		this.account_bank = account_bank;
	}

	public String getBank_address_code() {
		return bank_address_code;
	}

	public void setBank_address_code(String bank_address_code) {
		this.bank_address_code = bank_address_code;
	}

	public String getAccount_number() {
		return account_number;
	}

	public void setAccount_number(String account_number) {
		this.account_number = account_number;
	}

	public String getStore_name() {
		return store_name;
	}

	public void setStore_name(String store_name) {
		this.store_name = store_name;
	}

	public String getStore_address_code() {
		return store_address_code;
	}

	public void setStore_address_code(String store_address_code) {
		this.store_address_code = store_address_code;
	}

	public String getStore_street() {
		return store_street;
	}

	public void setStore_street(String store_street) {
		this.store_street = store_street;
	}

	public String getStore_entrance_pic() {
		return store_entrance_pic;
	}

	public void setStore_entrance_pic(String store_entrance_pic) {
		this.store_entrance_pic = store_entrance_pic;
	}

	public String getIndoor_pic() {
		return indoor_pic;
	}

	public void setIndoor_pic(String indoor_pic) {
		this.indoor_pic = indoor_pic;
	}

	public String getMerchant_shortname() {
		return merchant_shortname;
	}

	public void setMerchant_shortname(String merchant_shortname) {
		this.merchant_shortname = merchant_shortname;
	}

	public String getService_phone() {
		return service_phone;
	}

	public void setService_phone(String service_phone) {
		this.service_phone = service_phone;
	}

	public String getProduct_desc() {
		return product_desc;
	}

	public void setProduct_desc(String product_desc) {
		this.product_desc = product_desc;
	}

	public String getRate() {
		return rate;
	}

	public void setRate(String rate) {
		this.rate = rate;
	}

	public String getContact() {
		return contact;
	}

	public void setContact(String contact) {
		this.contact = contact;
	}

	public String getContact_phone() {
		return contact_phone;
	}

	public void setContact_phone(String contact_phone) {
		this.contact_phone = contact_phone;
	}

	public Map<String, Object> toMap() {
		Map<String, Object> map = new HashMap<String, Object>();
		Field[] fields = this.getClass().getDeclaredFields();
		for (Field field : fields) {
			Object obj;
			try {
				obj = field.get(this);
				if (obj != null) {
					map.put(field.getName(), obj);
				}
			} catch (IllegalArgumentException e) {
			} catch (IllegalAccessException e) {
			}
		}
		return map;
	}
}

 

HttpsRequest .java

package com.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.commons.lang.StringEscapeUtils;
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.pay.wechat.protocol.pay_protocol.ScanPayReqDataSp;
import com.pay.wechat.util.xmlstream.XStreamFactory;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;

/**
 * HTTP 请求类
 *
 * @author libaibai
 * @version 1.0 2020年5月31日
 */
@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("-_", "_")));

		XStream xStream = XStreamFactory.getXStream(new XmlFriendlyNameCoder("_-", "_"));

		// 将要提交给API的数据对象转换成XML格式数据Post给API
		String postDataXML = xStream.toXML(xmlObj);
		LOG.info("请求微信接口->url=" + url + ",data=" + postDataXML);
		// LOG.info("data="+StringEscapeUtils.unescapeXml(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;
	}

	public static void main(String[] args) {

		String appid = "111";
		String mch_id = "2222";
		String sub_appid = "3333";
		String sub_mch_id = "4444";
		String key = "5555";
		String body = "aaaa";
		String detail = "dddd";
		String attach = "#*#{\"pn\":\"粤B12345\",\"aid\":\"123456789\", \"vm\":\"true\"}#*#";
		String out_trade_no = "ffffff";
		int total_fee = 100;
		String spbill_create_ip = "2222";
		String trade_type = "ggggg";
		String product_id = "hhhhh";
		String openid = "jjjjj";

		String sub_openid = null;
		ScanPayReqDataSp data = new ScanPayReqDataSp(appid, mch_id, sub_appid, sub_mch_id, key, body, detail, attach, out_trade_no, total_fee,
				spbill_create_ip, trade_type, product_id, openid, sub_openid);

		HttpsRequest request;
		try {
			request = new HttpsRequest();
			request.sendPost("", data);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

WxSmallSubmitBo .java

package com.pay.wechat.bo.small;

import org.springframework.stereotype.Component;

import com.pay.wechat.protocol.WxSmallModel;
import com.pay.wechat.util.HttpsRequest;
import com.pay.wechat.util.WxAesGcmExample;
import com.pay.wechat.util.WxRSAEncryptUtil;
import com.util.Config;

/**
 * 小微商户进件
 * 
 * @author libaibai
 * @version 1.0 2020年5月26日
 */
@Component
public class WxSmallSubmitBo {

	public void exe() {
		
		// 获取解密证书得到
		String associatedData = ""; // encrypt_certificate.associated_data
		String nonce = ""; // encrypt_certificate.nonce
		String cipherText = ""; // encrypt_certificate.ciphertext
		
		String wechatpayCert = null; // 证书
		try {
			wechatpayCert = WxAesGcmExample.aesgcmDecrypt(associatedData, nonce, cipherText);
			System.out.println("wechatpayCert=" + wechatpayCert);
		} catch (Exception e) {
			e.printStackTrace();
		}
		

		try {

			String key = Config.APIKEY;

			String cert_sn = ""; // 证书序列号

			String id_card_copy = "-BMpJciLVOAFz1iHGbR5fnI5rJC0K10Qz9KErNvvOsVYuSDBIjO-en4Z-dfzbOCpY0ldafxs"; // 请填写由图片上传接口预先上传图片生成好的media_id
			String id_card_national = "-hqdexrNmI5slGHj3QDW_E"; // 请填写由图片上传接口预先上传图片生成好的media_id

			String id_card_name = WxRSAEncryptUtil.rsaEncryptByCert("李百百", wechatpayCert); // 身份证姓名,
			String id_card_number = WxRSAEncryptUtil.rsaEncryptByCert("440523xxxxxxxxx", wechatpayCert); // 身份证号码
			String id_card_valid_time = "[\"2011-06-24\",\"2021-06-24\"]"; // 身份证有效期限,例如:["1970-01-01","长期"]

			String account_bank = WxRSAEncryptUtil.rsaEncryptByCert("李百百", wechatpayCert); // 开户银行
			String bank_address_code = "440300"; // 开户银行省市编码

			String account_number = WxRSAEncryptUtil.rsaEncryptByCert("6212265000004604312", wechatpayCert);// 银行账号

			String store_name = "生态园停车"; // 门店名称
			String store_address_code = "440300"; // 门店省市编码
			String store_street = "南山科技园园"; // 门店街道名称

			String store_entrance_pic = "-s4917roa97XFJf0GPdBNHEvkyf0XPzrOjeKjoBYmEL_eSk7I"; // 门店门口照片
			String indoor_pic = "-s4917roa97XFJf0GPdBNHEvkyf0XPzrOjeKjoBYmEL_eSk7I"; // 店内环境照片

			String merchant_shortname = "科技园停车"; // 商户简称
			String service_phone = "13666666666"; // 客服电话

			String product_desc = "停车缴费"; // 售卖商品/提供服务描述

			String contact = WxRSAEncryptUtil.rsaEncryptByCert("李百百", wechatpayCert); // 超级管理员姓名
			String contact_phone = WxRSAEncryptUtil.rsaEncryptByCert("13666666666", wechatpayCert); // 手机号码
			System.out.println("contact="+ contact);

			WxSmallModel small = new WxSmallModel(cert_sn, id_card_copy, id_card_national, id_card_name, id_card_number, id_card_valid_time,
					account_bank, bank_address_code, account_number, store_name, store_address_code, store_street, store_entrance_pic, indoor_pic,
					merchant_shortname, service_phone, product_desc, contact, contact_phone, key);

			HttpsRequest request = new HttpsRequest();
			String url = "https://api.mch.weixin.qq.com/applyment/micro/submit";
			String str = request.sendPost(url, small);
			System.out.println(str);
		} catch (Exception e) {
		}
	}

	public static void main(String[] args) {
		WxSmallSubmitBo bo = new WxSmallSubmitBo();
		bo.exe();
	}
}

运行main方法得到

 

虽然微信把小微商户进件api关闭了,但是听说有服务商还在使用。。。。

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