前面讲了,获取证书和获取证书和上传图片,现在我们进入主题,讲申请入驻。
首先打开官方文档: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关闭了,但是听说有服务商还在使用。。。。