微信企业付款至银行卡 详细Demo 独立封装

微信企业付款至银行卡 详细Demo 独立封装

大家好,我是梦辛工作室的灵,在最近的开发项目中,需要用到微信的企业付款至银行卡,在有过之前的企业付款到零钱包的封装好,就变的简单了许多,不过我还是在采用RSA加密银行卡 和 真实姓名的步骤上卡了许久,经过我不断地尝试还是搞定了这个功能,为了以后方便使用 顺便封装了下,WxPayUtilV1.0.2版,下面是如何使用:

	/**
	 * 企业付款到银行卡示例
	 */
	public static void compayWxPayBank() {

		try {
			// 获取公钥
			String key = getWxPayPublicKey();

			CompanyWxPayBankBuilder wxPayBankBuilder = new CompanyWxPayBankBuilder("证书路径", key); // key 为微信返回的公钥

			wxPayBankBuilder.setMch_id("商户号");
			wxPayBankBuilder.setAPI_KEY("APIKEY");
			wxPayBankBuilder.setAmount(200); // 支付金额
			wxPayBankBuilder.setDesc("支付描述");
			wxPayBankBuilder.setEnc_bank_no("银行卡卡号");
			wxPayBankBuilder.setEnc_true_name("真实姓名");
			wxPayBankBuilder.setBank_code("银行编码");

			wxPayBankBuilder.build();// 验证数据
			System.out.println(wxPayBankBuilder.hand());// 发送处理
		} catch (LackParamExceptions e) {
			e.printStackTrace();
		}
	}
	/**
	 * 获取公钥
	 */
	public static String getWxPayPublicKey() {

		try {
			GetPublicKeyBuilder builder = new GetPublicKeyBuilder("证书路径");
			builder.setAPI_KEY("APIKEY");
			builder.setmch_id("微信商户号");
			builder.build();// 验证数据
			JSONObject result = builder.hand();
			System.out.println(result);// 发送处理
			return result.getString("pub_key");
		} catch (LackParamExceptions e) {
			e.printStackTrace();
		}
		return null;
	}
	/**
	 * 企业付款到银行卡查询示例
	 */
	public static void compayWxPayBankQuery() {

		try {

			CompanyWxPayBankQueryBuilder wxPayBankQueryBuilder = new CompanyWxPayBankQueryBuilder("支付证书路径",
					"交易订单号(商家,不是微信的)");

			wxPayBankQueryBuilder.setMch_id("商户号");
			wxPayBankQueryBuilder.setAPI_KEY("APIKEY");

			wxPayBankQueryBuilder.build();// 验证数据
			System.out.println(wxPayBankQueryBuilder.hand());// 发送处理
		} catch (LackParamExceptions e) {
			e.printStackTrace();
		}
	}

有了这个我集成好的工具后,是不是就简单了很多,没有其余更多的复杂逻辑,hand()后就可以拿到对应的处理数据,该工具项目 我还集成了 微信JSAPI付款 发送模板消息 微信退款 微信退款查询 微信企业付款至零钱包 付款至银行卡 等功能,
下面讲一下我企业付款至银行卡步骤(不感兴趣的同学可直接到底部,github去下载源代码):

在拿到商户号秘钥和支付证书的基础上,需先获取到公钥

在这里插入图片描述
在这里插入图片描述
将以上信息按照ASCII码顺序拼接成以下格式:

mch_id=&nonce_str=&key=

然后MD5拿到sign,最后拼接成xml格式:
在这里插入图片描述
最后带证书访问值地址:https://fraud.mch.weixin.qq.com/risk/getpublickey
带证书访问代码如下:

public static String httpClientResultGetPublicKey(String url, String xml, String mch_id, String path)
			throws Exception {

		StringBuffer reultBuffer = new StringBuffer();

		KeyStore keyStore = KeyStore.getInstance("PKCS12");

		FileInputStream instream = new FileInputStream(new File(path));
		try {

			keyStore.load(instream, mch_id.toCharArray());
		} finally {
			instream.close();
		}

		SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mch_id.toCharArray()).build();

		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
				SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

		HttpPost httpPost = new HttpPost(url);
		CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
		StringEntity myEntity = new org.apache.http.entity.StringEntity(xml);
		myEntity.setContentType("text/xml;charset=UTF-8");
		myEntity.setContentEncoding("utf-8");
		httpPost.setHeader("Content-Type", "text/xml; charset=UTF-8");
		httpPost.setEntity(myEntity);

		CloseableHttpResponse response = null;
		InputStream inputStream = null;
		InputStreamReader inputStreamReader = null;
		BufferedReader bufferedReader = null;
		try {
			response = httpclient.execute(httpPost);
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				inputStream = entity.getContent();
				inputStreamReader = new InputStreamReader(inputStream);
				bufferedReader = new BufferedReader(inputStreamReader);
				String str = null;
				while ((str = bufferedReader.readLine()) != null) {
					reultBuffer.append(str);
				}
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {

			httpclient.close();
			response.close();
			bufferedReader.close();
			inputStreamReader.close();
			inputStream.close();
			inputStream = null;
		}

		return reultBuffer.toString();
	}

访问成功后可以拿到公钥,格式如下:
在这里插入图片描述
需要注意的是,这里获取到的秘钥格式是PKCS#1, 我们在用JAVA代码进行RSA加密的时候回报错,这是因为需要将格式转换为PKCS#8才可以,等下后面会讲到

进行企业付款至银行卡

在我们拿到公钥后,就按照以下参数请求,请求格式和加密方法和上面的一样,所需参数为:
在这里插入图片描述
这里需要对 银行卡 和真实姓名进行RSA加密,JAVA需要采用 " RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING" 填充方式,(需要将公钥格式转换为PKCS#8),加密代码如下(注意,这里的公钥需将头和尾去掉,即不要 “-----BEGIN RSA PUBLIC KEY-----” 和 “-----END RSA PUBLIC KEY-----”),需要为UTF-8格式:

	try {
			enc_bank_no_pwd = RSAEncryp.encrypt(enc_bank_no.getBytes("utf-8"), pub_key, 11,
					"RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING");
		} catch (Exception e) {
			e.printStackTrace();
			enc_bank_no_pwd = "";
		}
		try {
			enc_true_name_pwd = RSAEncryp.encrypt(enc_true_name.getBytes("utf-8"), pub_key, 11,
					"RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING");
		} catch (Exception e) {
			e.printStackTrace();
			enc_true_name_pwd = "";
		}
		public static String encrypt(byte[] plainBytes, String pub_Key, int reserveSize, String cipherAlgorithm)
			throws Exception {
		PublicKey publicKey = getPublicKey(pub_Key, "RSA");
		byte[] estr = encrypt(plainBytes, publicKey, pub_Key.length(), reserveSize, cipherAlgorithm);
		return new String(Base64.getEncoder().encode(estr));
	}
	
public static PublicKey getPublicKey(String key, String keyAlgorithm) throws Exception {
		try {
		//在这里做的秘钥格式转换
			org.bouncycastle.asn1.pkcs.RSAPublicKey rsaPublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey
					.getInstance(org.bouncycastle.util.encoders.Base64.decode(key));
			java.security.spec.RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(
					rsaPublicKey.getModulus(), rsaPublicKey.getPublicExponent());
			KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);
			PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

			return publicKey;
		} catch (Exception e) {
			throw new Exception("READ PUBLIC KEY ERROR:", e);
		} finally {

		}
	}
public static byte[] encrypt(byte[] plainBytes, PublicKey publicKey, int keyLength, int reserveSize,
			String cipherAlgorithm) throws Exception {
		int keyByteSize = keyLength / 8;
		int encryptBlockSize = keyByteSize - reserveSize;
		int nBlock = plainBytes.length / encryptBlockSize;
		if ((plainBytes.length % encryptBlockSize) != 0) {
			nBlock += 1;
		}
		ByteArrayOutputStream outbuf = null;
		try {
			Cipher cipher = Cipher.getInstance(cipherAlgorithm);
			cipher.init(Cipher.ENCRYPT_MODE, publicKey);

			outbuf = new ByteArrayOutputStream(nBlock * keyByteSize);
			for (int offset = 0; offset < plainBytes.length; offset += encryptBlockSize) {
				int inputLen = plainBytes.length - offset;
				if (inputLen > encryptBlockSize) {
					inputLen = encryptBlockSize;
				}
				byte[] encryptedBlock = cipher.doFinal(plainBytes, offset, inputLen);
				outbuf.write(encryptedBlock);
			}
			outbuf.flush();
			return outbuf.toByteArray();
		} catch (Exception e) {
			throw new Exception("ENCRYPT ERROR:", e);
		} finally {
			try {
				if (outbuf != null) {
					outbuf.close();
				}
			} catch (Exception e) {
				outbuf = null;
				throw new Exception("CLOSE ByteArrayOutputStream ERROR:", e);
			}
		}
	}

然后将这些参数按照ASCII码顺序排序凭借为以下字符串:

amount=&bank_code=&desc=&enc_bank_no=&enc_true_name=&mch_id=&nonce_str=&partner_trade_no=&key=

然后MD5拿到sign
然后拼接为以下格式:
在这里插入图片描述
然后带证书post到接口地址:https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank
然后就可以啦,企业付款到银行卡查询比较简单,且没有什么需要注意的,我就不说啦,格式和 获取公钥一样,仅是参数不同而已

github入口,记得打个start https://github.com/wintton/MxWxPayUtil

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灵神翁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值