今天我们来讲一下微信小微商户进件V3版本的接口对接。
首先我们来看一下官方的文档:
https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/applyment/chapter3_1.shtml
根据文档提示,小微商户进件对接协议和特约商户是一样的,只是参数不一样。我们这里以小微商户说明(主要是公司需要)。
首先引入JRE包,后面会用到。这里使用的是maven。
- <dependency>
- <groupId>com.github.wechatpay-apiv3</groupId>
- <artifactId>wechatpay-apache-httpclient</artifactId>
- <version>0.2.1</version>
- </dependency>
进件需要我们先上传身份证照片,请参考
上代码
ApplymentBo.java
- package com.pay.wechat.bo.small.v3;
- import java.io.ByteArrayInputStream;
- import java.security.cert.X509Certificate;
- import java.util.HashMap;
- import java.util.Map;
- import org.springframework.stereotype.Component;
- import com.util.OrderIDUtil;
- import com.pay.wechat.bo.small.v3.util.CertUtil;
- import com.pay.wechat.bo.small.v3.util.HttpUrlUtil;
- import com.pay.wechat.bo.small.v3.util.RsaEncryptUtil;
- import com.pay.contrib.apache.httpclient.util.PemUtil;
- import net.sf.json.JSONObject;
- /**
- * 小微商户进件V3版本<br>
- * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/applyment/chapter3_1.shtml
- *
- * @author libaibai@chinatenet.com
- * @version 1.0 2020年9月3日
- */
- @Component
- public class ApplymentBo {
- /**
- * 进件
- *
- * @param contactName 管理员姓名
- * @param contactIdNum 管理员身份证号码
- * @param contactMobile 管理员手机号码
- * @param contactMail 管理员邮箱
- * @param microName 门店名称
- * @param microAddressCode
- * 门店编码,参考:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter4_1.shtml
- * @param microAddress 门店地址
- * @param idCardCopy 身份证正面照片
- * @param idCardNational 身份证反面照片
- * @param cardPeriodBegin 身份证有效期开始时间,格式:2011-06-24
- * @param cardPeriodEnd 身份证有效期结束时间,格式:2011-06-24
- * @param servicePhone 客户电话
- * @param accountBank 开户行银行名称
- * @param bankAddressCode 开户行编码
- * @param bankName 开户银行全称(含支行] <pre>
- * 1、“开户银行”为17家直连银行无需填写
- * 2、“开户银行”为其他银行,则开户银行全称(含支行)和开户银行联行号二选一 //
- * 3、需填写银行全称,如"深圳农村商业银行XXX支行",详细参见《开户银行全称(含支行)对照表》
- * 示例值:施秉县农村信用合作联社城关信用社
- * </pre>
- *
- * @param accountNumber 银行卡号
- * @throws Exception
- */
- public void exe(String contactName, String contactIdNum, String contactMobile, String contactMail, String microName, String microAddressCode,
- String microAddress, String idCardCopy, String idCardNational, String cardPeriodBegin, String cardPeriodEnd, String servicePhone,
- String accountBank, String bankAddressCode, String bankName, String accountNumber) throws Exception {
- // 获取微信平台证书 并解析方法在后面
- String certString = CertUtil.getCertStr();
- ByteArrayInputStream stringStream = new ByteArrayInputStream(certString.getBytes());
- // 下面所有加密参数需要的对象
- X509Certificate certx = PemUtil.loadCertificate(stringStream);
- // 超级管理员信息
- Map<String, Object> contact_info = new HashMap<String, Object>();
- String contact_name = RsaEncryptUtil.rsaEncryptOAEP(contactName, certx); // 超级管理员姓名
- String contact_id_number = RsaEncryptUtil.rsaEncryptOAEP(contactIdNum, certx); // 超级管理员身份证件号码
- String mobile_phone = RsaEncryptUtil.rsaEncryptOAEP(contactMobile, certx);// 联系手机
- String contact_email = RsaEncryptUtil.rsaEncryptOAEP(contactMail, certx);// 联系邮箱
- contact_info.put("contact_name", contact_name);
- contact_info.put("contact_id_number", contact_id_number);
- contact_info.put("mobile_phone", mobile_phone);
- contact_info.put("contact_email", contact_email);
- // 主体资料
- String subject_type = "SUBJECT_TYPE_MICRO"; // 主体类型
- String micro_biz_type = "MICRO_TYPE_STORE"; // 小微经营类型
- String micro_name = microName; // 门店名称
- String micro_address_code = microAddressCode; // 门店省市编码
- String micro_address = microAddress; // 门店街道名称
- String store_entrance_pic = "oO5EoYZsdukezw2NXUxEkb9vTU7PgOu5GyMpNVdMVj5aJAwD85_8kNpakg-s4917roa97XFJf0GPdBNHEvkyf0XPzrOjeKjoBYmEL_eSk7I"; // 门店门口照片
- String micro_indoor_copy = "oO5EoYZsdukezw2NXUxEkb9vTU7PgOu5GyMpNVdMVj5aJAwD85_8kNpakg-s4917roa97XFJf0GPdBNHEvkyf0XPzrOjeKjoBYmEL_eSk7I"; // 店内环境照片
- // 证件类型,IDENTIFICATION_TYPE_IDCARD
- String id_doc_type = "IDENTIFICATION_TYPE_IDCARD";
- // String id_card_copy = idCardCopy; // 身份证人像面照片
- // String id_card_national = idCardNational; // 身份证国徽面照片
- String id_card_name = RsaEncryptUtil.rsaEncryptOAEP(contactName, certx); // 身份证姓名
- String id_card_number = RsaEncryptUtil.rsaEncryptOAEP(contactIdNum, certx); // 身份证号码
- // String card_period_begin = "2011-06-24"; // 身份证有效期开始时间示例值:2026-06-06
- // String card_period_end = "2021-06-24"; // 身份证有效期结束时间示例值:2026-06-06
- Map<String, Object> subject_info = new HashMap<String, Object>(); // 主体资料
- Map<String, Object> micro_biz_info = new HashMap<String, Object>(); // 小微商户辅助材料
- Map<String, Object> micro_store_info = new HashMap<String, Object>(); // 门店场所信息
- Map<String, Object> identity_info = new HashMap<String, Object>(); // 经营者身份证件
- Map<String, Object> id_card_info = new HashMap<String, Object>(); // 身份证信息
- micro_store_info.put("micro_name", micro_name);
- micro_store_info.put("micro_address_code", micro_address_code);
- micro_store_info.put("micro_address", micro_address);
- micro_store_info.put("store_entrance_pic", store_entrance_pic);
- micro_store_info.put("micro_indoor_copy", micro_indoor_copy);
- micro_biz_info.put("micro_biz_type", micro_biz_type);
- micro_biz_info.put("micro_store_info", micro_store_info);
- id_card_info.put("id_card_copy", idCardCopy);
- id_card_info.put("id_card_national", idCardNational);
- id_card_info.put("id_card_name", id_card_name);
- id_card_info.put("id_card_number", id_card_number);
- id_card_info.put("card_period_begin", cardPeriodBegin);
- id_card_info.put("card_period_end", cardPeriodEnd);
- identity_info.put("id_doc_type", id_doc_type);
- identity_info.put("id_card_info", id_card_info);
- subject_info.put("subject_type", subject_type);
- subject_info.put("micro_biz_info", micro_biz_info);
- subject_info.put("identity_info", identity_info);
- // 经营资料
- // String merchant_shortname = "张三停车场"; // 商户简称
- // String service_phone = "0755222222"; // 客服电话
- Map<String, Object> business_info = new HashMap<String, Object>();
- business_info.put("merchant_shortname", microName);
- business_info.put("service_phone", servicePhone);
- // 结算规则
- // 入驻结算规则ID;请选择结算规则ID,详细参见《费率结算规则对照表》 示例值:小微商户:703
- String settlement_id = "703";//
- String qualification_type = "停车缴费"; // 所属行业;请填写所属行业名称,建议参见《费率结算规则对照表》 示例值:餐饮
- Map<String, Object> settlement_info = new HashMap<String, Object>();
- settlement_info.put("settlement_id", settlement_id);
- settlement_info.put("qualification_type", qualification_type);
- // 收款银行卡
- // 账户类型 若主体为小微,可填写:经营者个人银行卡 枚举值:
- // BANK_ACCOUNT_TYPE_PERSONAL:经营者个人银行卡
- // 示例值:BANK_ACCOUNT_TYPE_CORPORATE
- String bank_account_type = "BANK_ACCOUNT_TYPE_PERSONAL";
- String account_name = RsaEncryptUtil.rsaEncryptOAEP(contactName, certx); // 开户名称(该字段需进行加密处理)
- // String account_bank = "建设银行"; // 开户银行开户银行,详细参见《开户银行对照表》 示例值:工商银行
- // String bank_address_code = "440300"; // 开户银行省市编码至少精确到市,详细参见《省市区编号对照表》 示例值:110000
- // 1、“开户银行”为17家直连银行无需填写
- // 2、“开户银行”为其他银行,则开户银行全称(含支行)和开户银行联行号二选一
- // 3、需填写银行全称,如"深圳农村商业银行XXX支行",详细参见《开户银行全称(含支行)对照表》
- // 示例值:施秉县农村信用合作联社城关信用社
- // String bank_name = ""; // 开户银行全称(含支行]
- String account_number = RsaEncryptUtil.rsaEncryptOAEP(accountNumber, certx); // 银行账号(该字段需进行加密处理)
- Map<String, Object> bank_account_info = new HashMap<String, Object>();
- bank_account_info.put("bank_account_type", bank_account_type);
- bank_account_info.put("account_name", account_name);
- bank_account_info.put("account_bank", accountBank);
- bank_account_info.put("bank_address_code", bankAddressCode);
- bank_account_info.put("bank_name", bankName);
- bank_account_info.put("account_number", account_number);
- String business_code = OrderIDUtil.getOrderID(null); // 申请单号
- Map<String, Object> map = new HashMap<String, Object>();
- map.put("business_code", business_code);
- map.put("contact_info", contact_info);
- map.put("subject_info", subject_info);
- map.put("business_info", business_info);
- map.put("settlement_info", settlement_info);
- map.put("bank_account_info", bank_account_info);
- try {
- String body = JSONObject.fromObject(map).toString();
- String str = HttpUrlUtil.sendPost(body);
- System.out.println(str);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- String contactName = "张**"; // 超级管理员姓名
- String contactIdNum = "520201************"; // 身份证号码
- String contactMobile = "139*********"; // 手机号码
- String contactMail = "3*******@qq.com"; // 联系邮箱
- String microName = "联运公司停车场"; // 门店名称(也用于简称)
- // 门店省市编码
- // 参考:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter4_1.shtml
- String microAddressCode = "520200";
- String microAddress = "**************路52号"; // 门店地址
- String idCardCopy = "eYjXW9AMg-***********************************************-w508XSWniUlM"; // 身份证正面照
- String idCardNational = "eYjXW9AMg-************************************-RPk8-eZ7PJvD8XBtaTZ1a1YEIN1PSeuRnkM"; // 身份证反面照
- String cardPeriodBegin = "2007-08-10"; // 身份证有效期开始时间2011-06-24
- String cardPeriodEnd = "2027-08-10";// 身份证有效期结束时间2011-06-24
- String servicePhone = "139*********";// 客服电话; 无特殊使用管理员手机号码
- String accountBank = "招商银行"; // 开户银行
- String bankAddressCode = "520200"; // 开户银行省市编码至少精确到市,详细参见《省市区编号对照表》 示例值:110000;
- // 1、“开户银行”为17家直连银行无需填写
- // 2、“开户银行”为其他银行,则开户银行全称(含支行)和开户银行联行号二选一
- // 3、需填写银行全称,如"深圳农村商业银行XXX支行",详细参见《开户银行全称(含支行)对照表》
- // 示例值:施秉县农村信用合作联社城关信用社
- String bankName = ""; // 开户银行全称(含支行]
- String accountNumber = "************************"; // 银行账号
- ApplymentBo t = new ApplymentBo();
- try {
- t.exe(contactName, contactIdNum, contactMobile, contactMail, microName, microAddressCode, microAddress, idCardCopy, idCardNational,
- cardPeriodBegin, cardPeriodEnd, servicePhone, accountBank, bankAddressCode, bankName, accountNumber);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
httpUrlUtil.java
- package com.pay.wechat.bo.small.v3.util;
- import java.security.PrivateKey;
- import java.security.Signature;
- import java.util.Base64;
- import javax.ws.rs.core.Response;
- import org.apache.cxf.jaxrs.client.WebClient;
- import com.util.Config;
- import com.util.UUIDUtil;
- import okhttp3.HttpUrl;
- /**
- * HttpUrl工具类
- *
- * @author libaibai
- * @version 1.0 2020年9月4日
- */
- public class HttpUrlUtil {
- public static String SCHEMA = "WECHATPAY2-SHA256-RSA2048";
- public static String merchantId = Config.MCHIDSP; // 服务商
- public static String POST = "POST";
- public static String GET = "GET";
- public static String host = "https://api.mch.weixin.qq.com";
- public static String APPLY_PATH = "/v3/applyment4sub/applyment/"; // 申请单url
- public static String CERT_PATH = "/v3/certificates"; // 获取微信平台证书url
- public static String APPLY_QUERY_PATH = "/v3/applyment4sub/applyment/applyment_id/"; // 查询申请状态
- /**
- * POST请求
- */
- public static String sendPost(String body) {
- String url = host + APPLY_PATH;
- try {
- // 获取微信平台商户证书序列号
- String wxSerialNo = CertUtil.getCertSerialNo();
- String authorization = getToken(POST, url, body);
- WebClient client = WebClient.create(host);
- client.reset();
- client.header("Content-Type", "application/json; charset=UTF-8");
- client.header("Accept", "application/json");
- client.header("user-agent", "application/json");
- client.header("Wechatpay-Serial", wxSerialNo);
- client.header("Authorization", authorization);
- client.path(APPLY_PATH);
- Response r = client.post(body);
- return r.readEntity(String.class);
- } catch (Exception e) {
- return null;
- }
- }
- /**
- * get请求
- */
- public static String sendGet() {
- // 请求URL
- String url = host + CERT_PATH;
- try {
- String authorization = getToken(GET, url, "");
- WebClient client = WebClient.create(host);
- client.reset();
- client.header("Content-Type", "application/json; charset=UTF-8");
- client.header("Accept", "application/json");
- client.header("User-Agent", "application/json");
- client.header("Authorization", authorization);
- client.path(CERT_PATH);
- Response r = client.get();
- return r.readEntity(String.class);
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
- /**
- * get请求
- */
- public static String sendGet(String applymentId) {
- // 请求URL
- String url = host + APPLY_QUERY_PATH + applymentId;
- try {
- String authorization = getToken(GET, url, "");
- WebClient client = WebClient.create(host);
- client.reset();
- client.header("Content-Type", "application/json; charset=UTF-8");
- client.header("Accept", "application/json");
- client.header("User-Agent", "application/json");
- client.header("Authorization", authorization);
- client.path(APPLY_QUERY_PATH + applymentId);
- Response r = client.get();
- return r.readEntity(String.class);
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
- /**
- * 获取加密串
- *
- * @param method
- * @param url
- * @param body
- * @return
- */
- public static String getToken(String method, String url, String body) {
- String nonceStr = UUIDUtil.getUUID32();
- long timestamp = System.currentTimeMillis() / 1000;
- HttpUrl httpUrl = HttpUrl.parse(url);
- String message = buildMessage(method, httpUrl, timestamp, nonceStr, body);
- String signature = null;
- String certificateSerialNo = null;
- try {
- signature = sign(message.getBytes("utf-8"));
- certificateSerialNo = CertUtil.getSerialNo("");
- } catch (Exception e) {
- e.printStackTrace();
- }
- return SCHEMA + " mchid=\"" + merchantId + "\"," + "nonce_str=\"" + nonceStr + "\"," + "timestamp=\"" + timestamp + "\"," + "serial_no=\""
- + certificateSerialNo + "\"," + "signature=\"" + signature + "\"";
- }
- /**
- * 得到签名字符串
- */
- public static String sign(byte[] message) throws Exception {
- Signature sign = Signature.getInstance("SHA256withRSA");
- PrivateKey privateKey = CertUtil.getPrivateKey();
- sign.initSign(privateKey);
- sign.update(message);
- return Base64.getEncoder().encodeToString(sign.sign());
- }
- public static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
- String canonicalUrl = url.encodedPath();
- if (url.encodedQuery() != null) {
- canonicalUrl += "?" + url.encodedQuery();
- }
- return method + "\n" + canonicalUrl + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n";
- }
- }
CertUtil.java
- package com.pay.wechat.bo.small.v3.util;
- import java.io.BufferedInputStream;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.nio.charset.StandardCharsets;
- import java.nio.file.Files;
- import java.nio.file.Paths;
- import java.security.KeyFactory;
- import java.security.NoSuchAlgorithmException;
- import java.security.PrivateKey;
- import java.security.cert.CertificateException;
- import java.security.cert.CertificateExpiredException;
- import java.security.cert.CertificateFactory;
- import java.security.cert.CertificateNotYetValidException;
- import java.security.cert.X509Certificate;
- import java.security.spec.InvalidKeySpecException;
- import java.security.spec.PKCS8EncodedKeySpec;
- import org.apache.commons.codec.binary.Base64;
- import net.sf.json.JSONArray;
- import net.sf.json.JSONObject;
- /**
- * 证书工具类
- *
- * @author libaibai
- * @version 1.0 2020年9月4日
- */
- public class CertUtil {
- // 微信证书私钥路径(从微信商户平台下载,保存在本地)
- public static String APICLIENT_KEY = "G:\\workspace\\dlysw\\src\\main\\resources\\conf\\cert\\apiclient_key.pem";
- // 微信商户证书路径(从微信商户平台下载,保存在本地)
- public static String APICLIENT_CERT = "G:\\workspace\\dlysw\\src\\main\\resources\\conf\\cert\\apiclient_cert.pem";
- /**
- * 获取私钥。
- *
- * @param apiclient_key 私钥文件路径 (required)
- * @return 私钥对象
- */
- public static PrivateKey getPrivateKey() throws IOException {
- String content = new String(Files.readAllBytes(Paths.get(APICLIENT_KEY)), StandardCharsets.UTF_8);
- try {
- String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", "");
- KeyFactory kf = KeyFactory.getInstance("RSA");
- return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey)));
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException("当前Java环境不支持RSA", e);
- } catch (InvalidKeySpecException e) {
- throw new RuntimeException("无效的密钥格式");
- }
- }
- /**
- * 获取商户证书。
- *
- * @param filename 证书文件路径 (required)
- * @return X509证书
- */
- public static X509Certificate getCertificate(String filename) throws IOException {
- InputStream fis = new FileInputStream(APICLIENT_CERT);
- try (BufferedInputStream bis = new BufferedInputStream(fis)) {
- CertificateFactory cf = CertificateFactory.getInstance("X509");
- X509Certificate cert = (X509Certificate) cf.generateCertificate(bis);
- cert.checkValidity();
- return cert;
- } catch (CertificateExpiredException e) {
- throw new RuntimeException("证书已过期", e);
- } catch (CertificateNotYetValidException e) {
- throw new RuntimeException("证书尚未生效", e);
- } catch (CertificateException e) {
- throw new RuntimeException("无效的证书文件", e);
- }
- }
- /**
- * 获取商户证书序列号
- *
- * @param certPath 获取商户证书序列号 传递商号证书路径 apiclient_cert
- * @return
- * @throws IOException
- */
- public static String getSerialNo(String certPath) throws IOException {
- X509Certificate certificate = getCertificate(certPath);
- return certificate.getSerialNumber().toString(16).toUpperCase();
- }
- /**
- * 获取微信平台证书序列号
- *
- * @return
- * @throws Exception
- */
- public static String getCertSerialNo() throws Exception {
- try {
- String str = HttpUrlUtil.sendGet();
- System.out.println(str);
- JSONObject json = JSONObject.fromObject(str);
- JSONArray jsonArray = JSONArray.fromObject(json.optString("data"));
- JSONObject jsonObject = jsonArray.getJSONObject(0);
- return jsonObject.optString("serial_no");
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * 获取微信平台证书
- *
- * @return
- * @throws Exception
- */
- public static String getCertStr() throws Exception {
- try {
- String str = HttpUrlUtil.sendGet();
- JSONObject json = JSONObject.fromObject(str);
- JSONArray jsonArray = JSONArray.fromObject(json.optString("data"));
- JSONObject jsonObject = jsonArray.getJSONObject(0);
- JSONObject jsonCert = JSONObject.fromObject(jsonObject.optString("encrypt_certificate"));
- //System.out.println(str);
- //System.out.println(jsonCert);
- String certKeyString = AesUtil.decryptToString(jsonCert.getString("associated_data").getBytes(),
- jsonCert.getString("nonce").getBytes(), jsonCert.getString("ciphertext"));
- return certKeyString;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- public static void main(String[] args) {
- try {
- System.out.println(CertUtil.getCertStr());
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
AesUtil.java
- package com.dlysw.pay.wechat.bo.small.v3.util;
- import java.security.InvalidAlgorithmParameterException;
- import java.security.InvalidKeyException;
- import java.security.NoSuchAlgorithmException;
- import java.util.Base64;
- import javax.crypto.Cipher;
- import javax.crypto.NoSuchPaddingException;
- import javax.crypto.spec.GCMParameterSpec;
- import javax.crypto.spec.SecretKeySpec;
- import com.dlyspublic.util.Config;
- /**
- *
- * @author libaibai
- * @version 1.0 2020年9月8日
- */
- public class AesUtil {
- public static final int TAG_LENGTH_BIT = 128;
- public static byte[] aesKey = Config.AES_KEY_APIV3.getBytes(); // APIv3密钥
- public static String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext) throws Exception {
- try {
- Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
- SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
- GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
- cipher.init(Cipher.DECRYPT_MODE, key, spec);
- cipher.updateAAD(associatedData);
- return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8");
- } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
- throw new IllegalStateException(e);
- } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
- throw new IllegalArgumentException(e);
- }
- }
- }
ok,直接运行ApplymentBo.java里面的main方法,得到返回结果
{"applyment_id": xxxxxxxxxxxxxx}
就表示进件成功了,我们登陆到商户平台看看。创建员工=API的就是刚才我们申请成功的。
最后,我们也把状态查询的代码也贴一下
ApplymentQueryBo.java
- package com.pay.wechat.bo.small.v3;
- import org.springframework.stereotype.Component;
- import com.pay.wechat.bo.small.v3.util.HttpUrlUtil;
- /**
- * 小微商户进件查询
- *
- * @author libaibai
- * @version 1.0 2020年9月8日
- */
- @Component
- public class ApplymentQueryBo {
- /**
- * 执行
- *
- * @param applymentId 申请单号
- * @return
- */
- public String query(String applymentId) {
- String str = HttpUrlUtil.sendGet(applymentId);
- System.out.println(str);
- return str;
- }
- public static void main(String[] args) {
- String applymentId = "200000xxxxxxxxxx";
- ApplymentQueryBo b = new ApplymentQueryBo();
- b.query(applymentId);
- }
- }
返回成功:
{"applyment_id":200000xxxxxxxxxx,"applyment_state":"APPLYMENT_STATE_TO_BE_SIGNED","applyment_state_msg":"请超级管理员使用微信打开返回的“签约链接”,根据页面指引完成签约","audit_detail":[],"business_code":"WEB|1590030703","sign_url":"https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQGb7zwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyeWZaMDl3b3JlUjIxbG9PLU52Y1YAAgRY5VZfAwQAjScA","sub_mchid":"15947111111"}
补充:
- package com.pay.wechat.bo.small.v3.util;
- import java.io.IOException;
- import java.security.InvalidKeyException;
- import java.security.NoSuchAlgorithmException;
- import java.security.PrivateKey;
- import java.security.cert.X509Certificate;
- import java.util.Base64;
- import javax.crypto.BadPaddingException;
- import javax.crypto.Cipher;
- import javax.crypto.IllegalBlockSizeException;
- import javax.crypto.NoSuchPaddingException;
- /**
- * 敏感信息加密
- *
- * @author libaibai
- * @version 1.0 2020年9月3日
- */
- public class RsaEncryptUtil {
- /**
- * 加密
- *
- * @param message
- * @param certificate
- * @return
- * @throws IllegalBlockSizeException
- * @throws IOException
- */
- public static String rsaEncryptOAEP(String message, X509Certificate certificate) throws IllegalBlockSizeException, IOException {
- try {
- Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
- cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey());
- byte[] data = message.getBytes("utf-8");
- byte[] cipherdata = cipher.doFinal(data);
- return Base64.getEncoder().encodeToString(cipherdata);
- } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
- throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
- } catch (InvalidKeyException e) {
- throw new IllegalArgumentException("无效的证书", e);
- } catch (IllegalBlockSizeException | BadPaddingException e) {
- throw new IllegalBlockSizeException("加密原串的长度不能超过214字节");
- }
- }
- /**
- * 解密
- *
- * @param ciphertext
- * @param privateKey
- * @return
- * @throws BadPaddingException
- * @throws IOException
- */
- public static String rsaDecryptOAEP(String ciphertext, PrivateKey privateKey) throws BadPaddingException, IOException {
- try {
- Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
- cipher.init(Cipher.DECRYPT_MODE, privateKey);
- byte[] data = Base64.getDecoder().decode(ciphertext);
- return new String(cipher.doFinal(data), "utf-8");
- } catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
- throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
- } catch (InvalidKeyException e) {
- throw new IllegalArgumentException("无效的私钥", e);
- } catch (BadPaddingException | IllegalBlockSizeException e) {
- throw new BadPaddingException("解密失败");
- }
- }
- }
联系客服