场景介绍:
做电商项目的时候,经常会接触到提现。一般会在第三方支付比如通联代付,现说说微信商户平台 有个 企业付款到个人银行卡功能。
前期准备:
就是开通公众号和商户平台,这些百度会有一大堆。 企业付款到个人银行卡 在 商户平台,产品中心 点击申请开通即可。
企业付款微信支付API地址:
https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_2
那么现在开始动手开发。
1、证书:需要让微信交钱到 用户手头上的 功能 基本都需要 证书
下载:商户平台,账户中心,API安全,下载。 压缩包cert 中 apiclient_cert.p12 则是 本功能需要用到的证书,将此证书 放到随意硬盘 (D:/zs/apiclient_cert.p12)
2、收款方银行卡和收款方用户名加密(最坑,最难,真想揍写这开发文档这人)
根据API文档上 描述, 银行卡号和用户名 是需要 采用 RSA 公钥加密后再传过去的。而在微信 获取RAS 加密公钥API 文档中,他们的接口默认输出的是 PKCS#1公钥。因为使用的是JAVA 环境,一定要将 PKCS#1转换成 PKCS#8。 API文档又提供了 PKCS#1和PKCS#8互转的 命令,这让给我这种菜鸡 能看得懂???????openssl。。什么鬼。于是,百度找了很多,一搜一大片,请得不清不楚的,一群坑货。推荐一个简单的方法:
a) 先根据API 获取 RSA加密公钥(https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_7&index=4)
获取的PKCS#1公钥格式:
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEArT82k67xybiJS9AD8nNAeuDYdrtCRaxkS6cgs8L9h83eqlDTlrdw
zBVSv5V4imTq/URbXn4K0V/KJ1TwDrqOI8hamGB0fvU13WW1NcJuv41RnJVua0QA
lS3tS1JzOZpMS9BEGeFvyFF/epbi/m9+2kUWG94FccArNnBtBqqvFncXgQsm98JB
3a62NbS1ePP/hMI7Kkz+JNMyYsWkrOUFDCXAbSZkWBJekY4nGZtK1erqGRve8Jbx
TWirAm/s08rUrjOuZFA21/EI2nea3DidJMTVnXVPY2qcAjF+595shwUKyTjKB8v1
REPB3hPF1Z75O6LwuLfyPiCrCTmVoyfqjwIDAQAB
-----END RSA PUBLIC KEY-----
b)接下来是 PKCS#1转成PKCS#8,网上找了个在线工具 网址:http://www.ssleye.com/web/pkcs,可以在线转在PKCS#8,当然如果有其他简单的办法希望可以在评论里告诉我,谢谢。
生成的PKCS#8公钥格式:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArT82k67xybiJS9AD8nNA
euDYdrtCRaxkS6cgs8L9h83eqlDTlrdwzBVSv5V4imTq/URbXn4K0V/KJ1TwDrqO
I8hamGB0fvU13WW1NcJuv41RnJVua0QAlS3tS1JzOZpMS9BEGeFvyFF/epbi/m9+
2kUWG94FccArNnBtBqqvFncXgQsm98JB3a62NbS1ePP/hMI7Kkz+JNMyYsWkrOUF
DCXAbSZkWBJekY4nGZtK1erqGRve8JbxTWirAm/s08rUrjOuZFA21/EI2nea3Did
JMTVnXVPY2qcAjF+595shwUKyTjKB8v1REPB3hPF1Z75O6LwuLfyPiCrCTmVoyfq
jwIDAQAB
-----END PUBLIC KEY-----
c) 将生成的PKCS#8公钥 保存在文件中,比如 pkcs8_pubkey.pem
3、将银行卡和用户名加密,(加密使用的类是网上找的)
a) base64 工具类
package com.aq.utils;
/**
* base64加密工具类
*/
public class WxBase64 {
static private final int BASELENGTH = 128;
static private final int LOOKUPLENGTH = 64;
static private final int TWENTYFOURBITGROUP = 24;
static private final int EIGHTBIT = 8;
static private final int SIXTEENBIT = 16;
static private final int FOURBYTE = 4;
static private final int SIGN = -128;
static private final char PAD = '=';
static private final boolean fDebug = false;
static final private byte[] base64Alphabet = new byte[BASELENGTH];
static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];
static {
for (int i = 0; i < BASELENGTH; ++i) {
base64Alphabet[i] = -1;
}
for (int i = 'Z'; i >= 'A'; i--) {
base64Alphabet[i] = (byte) (i - 'A');
}
for (int i = 'z'; i >= 'a'; i--) {
base64Alphabet[i] = (byte) (i - 'a' + 26);
}
for (int i = '9'; i >= '0'; i--) {
base64Alphabet[i] = (byte) (i - '0' + 52);
}
base64Alphabet['+'] = 62;
base64Alphabet['/'] = 63;
for (int i = 0; i <= 25; i++) {
lookUpBase64Alphabet[i] = (char) ('A' + i);
}
for (int i = 26, j = 0; i <= 51; i++, j++) {
lookUpBase64Alphabet[i] = (char) ('a' + j);
}
for (int i = 52, j = 0; i <= 61; i++, j++) {
lookUpBase64Alphabet[i] = (char) ('0' + j);
}
lookUpBase64Alphabet[62] = (char) '+';
lookUpBase64Alphabet[63] = (char) '/';
}
private static boolean isWhiteSpace(char octect) {
return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
}
private static boolean isPad(char octect) {
return (octect == PAD);
}
private static boolean isData(char octect) {
return (octect < BASELENGTH && base64Alphabet[octect] != -1);
}
/**
* Encodes hex octects into Base64
*
* @param binaryData Array containing binaryData
* @return Encoded Base64 array
*/
public static String encode(byte[] binaryData) {
i