微信企业转账到银行卡

  • 微信官方文档
    • 调用获取RSA公钥API
      • 1.获取PKCS#1格式的公钥
      • 2.返回示例
      • 3.转换PKCS公钥格式
      • 4.将得到的PKCS#8公钥转换为base64
      • 5.调用https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank 接口实现微信支付到银行卡
      • 6.工具类

微信官方文档

https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_2

调用获取RSA公钥API

https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_7

1.获取PKCS#1格式的公钥

public static void getPublicKey() throws Exception {String nonce_str= MD5Utils.getMessageDigest(String.valueOf(new Random().nextInt(10000)).getBytes());//随机数//签名数据Map<String, String> packageParams = new HashMap<>();packageParams.put("mch_id", MERID);//微信支付分配的商户号packageParams.put("nonce_str",nonce_str);//随机字符串,不长于32位。推荐随机数生成算法packageParams.put("sign_type", "MD5");//签名类型,目前支持HMAC-SHA256和MD5,默认为MD5// 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串String prestr = PayUtil.createLinkString(packageParams);//MD5运算生成签名,这里是第一次签名,用于调用统一下单接口String sign = PayUtil.sign(prestr, SIGNKEY, "utf-8").toUpperCase();//封装xml报文String xml="<xml>"+"<mch_id>"+MERID+"</mch_id>"+"<nonce_str>"+nonce_str+"</nonce_str>"+"<sign>"+sign+"</sign>"+"<sign_type>"+"MD5"+"</sign_type>"+"</xml>";String createOrderURL = "https://fraud.mch.weixin.qq.com/risk/getpublickey";//获取RSA加密公钥API//调用统一下单接口,并接受返回的结果System.out.println(xml);String post = ClientCustomSSL.paybank(createOrderURL, xml);System.out.println(post);String postString = XML.toJSONObject(post).toString();String wxinfo = postString.substring(postString.indexOf(":") + 1, postString.length() - 1);System.out.println(wxinfo);
}

2.返回示例

<xml>
<return_code>SUCCESS</return_code>
<return_msg>OK</return_msg>
<result_code>SUCCESS</result_code>
<mch_id>mch_id</mch_id>
<pub_key>
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAv9Iax/6EJejGtrqgf0Eglzj3TJj7m/RmRm0oOfEEkl+CbRWytTna
hXSSiMYDSUIiAo9Twr/xcCM54dNnnD4SHx757NrtWJ6dKNvF/FhM/NOUTrA0BTV/
JeNECY8K1MoiyO/v9Zo7ekdadusjEEdsasdah7xs0M1eG8I8JfbOLuAYP23nXzUa
Aa8tROWF79aaSvFiHGEpPtZQGPv34vmYTm5rFYQwrLVqBV42MpUxmjD0oknf+prT
1u80w4NwraZkrnI5bNk6Z2DwabVUMZpLu7gv6A/1C2P90WS6wfckZTOUpmZdFgyy
nGS4VfQIrDAQAB
-----END RSA PUBLIC KEY-----
</pub_key>
</xml>

3.转换PKCS公钥格式

filename :为public.pem地址
PKCS#1 转 PKCS#8:
openssl rsa -RSAPublicKey_in -in <filename> -pubout
PKCS#8 转 PKCS#1:
openssl rsa -pubin -in <filename> -RSAPublicKey_out
需要安装openSSL,配置环境变量 需要区分系统

4.将得到的PKCS#8公钥转换为base64

public static String getRsa() throws Exception {String encBankAcctNo = "夏天"; //加密的银行账号、或者名称String keyfile = "C:\\Users\\o\\Desktop\\WXCertUtil\\cert\\15********91_20191223_cert\\pksc8_public.pem"; //读取PKCS8密钥文件PublicKey pub=RSAUtil.getPubKey(keyfile,"RSA");//用标准的RSA加密库对敏感信息进行加密,选择RSA_PKCS1_OAEP_PADDING填充模式(eg:Java的填充方式要选 " RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING")String rsa ="RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING";byte[] estr=RSAUtil.encrypt(encBankAcctNo.getBytes(),pub,2048, 11,rsa);   //对银行账号进行加密encBankAcctNo =Base64.encode(estr);//并转为base64格式return encBankAcctNo;
}

5.调用https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank 接口实现微信支付到银行卡

@PostMapping("/paybankcard")
@ApiOperation("微信账户付款到银行卡")
public Result<String> payBankCard() throws Exception {String nonce_str= MD5Utils.getMessageDigest(String.valueOf(new Random().nextInt(10000)).getBytes());//随机数int randomNum  = (int) (Math.random() * 1999+5000);//"商户企业付款单号";String partner_trade_no = TimeUtils.getSysTime("yyyyMMddHHmmss") + randomNum;//生成订单号String enc_bank_no = "UsMdYrKvO+2BNN0T3eaasx5u+ZhJfGu3YGMREgdasdashjMDKFo+ggS6fA9Tdadafg46rp3njZBeho917DeOMSSCompY78bDSQvwHd4IlJ6WffTuAKb*****************P9qKlpv55S0YsqY/kFJaeXvD0c8RkpHlCziTd7fy3vzAKQZAV4A+EOOu/q+OUa0XkveQ2fRtooN8L1GU0XTbOCFqfPrUX988vTA4O4kA7y5iG1TAGV5bTWRg==";String enc_true_name = "MNhk2Bu7KnaD3Kmsd4jqfA9rWFVsdasdakArWzmOCRufFXEcj4XMqbS9GdadadaWyuNKxtifwc6HyMPVxx51jw8i0Aj1puMC890s86MUSg+ryGsSns/as*****************UGGbUvzDfPz5l1Pz4qUp1hSZrHPPuJmXYy0km86SYbRrOPATMov+muDIfnpMP3mm3Pzd9WXTq3TAc2VWk/lhMDAiaHf+EBmFTM4Zh9L7TxRf3/PJxGlTjb1R7TN/0fEVdQkdhSFWaKyt60R2jc28xI2DBYhODQINOnhjKNKe0NGvYgObnkEeM9LzkF8gMdCvPC/JWz6YUuSZfteQ==";String bank_code = "1005";int amount = 100;String desc = "测试到账";//签名数据Map<String, String> packageParams = new HashMap<>();packageParams.put("mch_id",MERID);packageParams.put("partner_trade_no",partner_trade_no);packageParams.put("nonce_str",nonce_str);packageParams.put("enc_bank_no",enc_bank_no);packageParams.put("enc_true_name",enc_true_name);packageParams.put("bank_code", bank_code);packageParams.put("amount",String.valueOf(amount));packageParams.put("desc", desc);// 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串String prestr = PayUtil.createLinkString(packageParams);//MD5运算生成签名,这里是第一次签名,用于调用统一下单接口String sign = PayUtil.sign(prestr, SIGNKEY, "utf-8").toUpperCase();LOGGER.info("sign="+sign);//封装xml报文String xml="<xml>"+"<amount>"+amount+"</amount>"+"<bank_code>"+bank_code+"</bank_code>"+"<desc>"+desc+"</desc>"+"<enc_bank_no>"+enc_bank_no+"</enc_bank_no>"+"<enc_true_name>"+enc_true_name+"</enc_true_name>"+"<mch_id>"+ MERID+"</mch_id>"+"<nonce_str>"+nonce_str+"</nonce_str>"+"<partner_trade_no>"+ partner_trade_no+"</partner_trade_no>"+"<sign>"+sign+"</sign>"+"</xml>";String createOrderURL = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";//微信统一下单接口//调用统一下单接口,并接受返回的结果System.out.println(xml);String post = ClientCustomSSL.doRefund(createOrderURL,xml);String postString = XML.toJSONObject(post).toString();String wxinfo = postString.substring(postString.indexOf(":") + 1, postString.length() - 1);System.out.println(wxinfo);return Result.success();
}

6.工具类

package com.qiouou.common.util.wxH5Pay;/*** @program: guidePlus* @description* @author: Joker* @create: 2021-04-15 11:50**/
public class Base64 {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) {if (binaryData == null) {return null;}int lengthDataBits = binaryData.length * EIGHTBIT;if (lengthDataBits == 0) {return "";}int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;char encodedData[] = null;encodedData = new char[numberQuartet * 4];byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;int encodedIndex = 0;int dataIndex = 0;if (fDebug) {System.out.println("number of triplets = " + numberTriplets);}for (int i = 0; i < numberTriplets; i++) {b1 = binaryData[dataIndex++];b2 = binaryData[dataIndex++];b3 = binaryData[dataIndex++];if (fDebug) {System.out.println("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3);}l = (byte) (b2 & 0x0f);k = (byte) (b1 & 0x03);byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);if (fDebug) {System.out.println("val2 = " + val2);System.out.println("k4   = " + (k << 4));System.out.println("vak  = " + (val2 | (k << 4)));}encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];}// form integral number of 6-bit groupsif (fewerThan24bits == EIGHTBIT) {b1 = binaryData[dataIndex];k = (byte) (b1 & 0x03);if (fDebug) {System.out.println("b1=" + b1);System.out.println("b1<<2 = " + (b1 >> 2));}byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];encodedData[encodedIndex++] = PAD;encodedData[encodedIndex++] = PAD;} else if (fewerThan24bits == SIXTEENBIT) {b1 = binaryData[dataIndex];b2 = binaryData[dataIndex + 1];l = (byte) (b2 & 0x0f);k = (byte) (b1 & 0x03);byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];encodedData[encodedIndex++] = PAD;}return new String(encodedData);}/*** Decodes Base64 data into octects** @param encoded string containing Base64 data* @return Array containind decoded data.*/public static byte[] decode(String encoded) {if (encoded == null) {return null;}char[] base64Data = encoded.toCharArray();// remove white spacesint len = removeWhiteSpace(base64Data);if (len % FOURBYTE != 0) {return null;//should be divisible by four}int numberQuadruple = (len / FOURBYTE);if (numberQuadruple == 0) {return new byte[0];}byte decodedData[] = null;byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;char d1 = 0, d2 = 0, d3 = 0, d4 = 0;int i = 0;int encodedIndex = 0;int dataIndex = 0;decodedData = new byte[(numberQuadruple) * 3];for (; i < numberQuadruple - 1; i++) {if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))|| !isData((d3 = base64Data[dataIndex++]))|| !isData((d4 = base64Data[dataIndex++]))) {return null;}//if found "no data" just return nullb1 = base64Alphabet[d1];b2 = base64Alphabet[d2];b3 = base64Alphabet[d3];b4 = base64Alphabet[d4];decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);}if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) {return null;//if found "no data" just return null}b1 = base64Alphabet[d1];b2 = base64Alphabet[d2];d3 = base64Data[dataIndex++];d4 = base64Data[dataIndex++];if (!isData((d3)) || !isData((d4))) {//Check if they are PAD charactersif (isPad(d3) && isPad(d4)) {if ((b2 & 0xf) != 0)//last 4 bits should be zero{return null;}byte[] tmp = new byte[i * 3 + 1];System.arraycopy(decodedData, 0, tmp, 0, i * 3);tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);return tmp;} else if (!isPad(d3) && isPad(d4)) {b3 = base64Alphabet[d3];if ((b3 & 0x3) != 0)//last 2 bits should be zero{return null;}byte[] tmp = new byte[i * 3 + 2];System.arraycopy(decodedData, 0, tmp, 0, i * 3);tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));return tmp;} else {return null;}} else { //No PAD e.g 3cQlb3 = base64Alphabet[d3];b4 = base64Alphabet[d4];decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);}return decodedData;}/*** remove WhiteSpace from MIME containing encoded Base64 data.** @param data  the byte array of base64 data (with WS)* @return      the new length*/private static int removeWhiteSpace(char[] data) {if (data == null) {return 0;}// count characters that's not whitespaceint newSize = 0;int len = data.length;for (int i = 0; i < len; i++) {if (!isWhiteSpace(data[i])) {data[newSize++] = data[i];}}return newSize;}
}
package com.qiouou.common.util.wxH5Pay;import javax.crypto.Cipher;
import java.io.*;
import java.lang.reflect.Method;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;/*** @program: guidePlus* @description* @author: Joker* @create: 2021-04-15 11:50**/
public class RSAUtil {public static byte[] decrypt(byte[] encryptedBytes, PrivateKey privateKey, int keyLength, int reserveSize, String cipherAlgorithm) throws Exception {int keyByteSize = keyLength / 8;int decryptBlockSize = keyByteSize - reserveSize;int nBlock = encryptedBytes.length / keyByteSize;ByteArrayOutputStream outbuf = null;try {Cipher cipher = Cipher.getInstance(cipherAlgorithm);cipher.init(Cipher.DECRYPT_MODE, privateKey);outbuf = new ByteArrayOutputStream(nBlock * decryptBlockSize);for (int offset = 0; offset < encryptedBytes.length; offset += keyByteSize) {int inputLen = encryptedBytes.length - offset;if (inputLen > keyByteSize) {inputLen = keyByteSize;}byte[] decryptedBlock = cipher.doFinal(encryptedBytes, offset, inputLen);outbuf.write(decryptedBlock);}outbuf.flush();return outbuf.toByteArray();} catch (Exception e) {throw new Exception("DEENCRYPT ERROR:", e);} finally {try{if(outbuf != null){outbuf.close();}}catch (Exception e){outbuf = null;throw new Exception("CLOSE ByteArrayOutputStream ERROR:", e);}}}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);}}}public static PrivateKey getPriKey(String privateKeyPath,String keyAlgorithm){PrivateKey privateKey = null;InputStream inputStream = null;try {if(inputStream==null){System.out.println("hahhah1!");}inputStream = new FileInputStream(privateKeyPath);System.out.println("hahhah2!");privateKey = getPrivateKey(inputStream,keyAlgorithm);System.out.println("hahhah3!");} catch (Exception e) {System.out.println("加载私钥出错!");} finally {if (inputStream != null){try {inputStream.close();}catch (Exception e){System.out.println("加载私钥,关闭流时出错!");}}}return privateKey;}public static PublicKey getPubKey(String publicKeyPath,String keyAlgorithm){PublicKey publicKey = null;InputStream inputStream = null;try{System.out.println("getPubkey 1......");inputStream = new FileInputStream(publicKeyPath);System.out.println("getPubkey 2......");publicKey = getPublicKey(inputStream,keyAlgorithm);System.out.println("getPubkey 3......");} catch (Exception e) {e.printStackTrace();//EAD PUBLIC KEY ERRORSystem.out.println("加载公钥出错!");} finally {if (inputStream != null){try {inputStream.close();}catch (Exception e){System.out.println("加载公钥,关闭流时出错!");}}}return publicKey;}public static PublicKey getPublicKey(InputStream inputStream, String keyAlgorithm) throws Exception {try{System.out.println("b1.........");BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));System.out.println("b2.........");StringBuilder sb = new StringBuilder();String readLine = null;System.out.println("b3.........");while ((readLine = br.readLine()) != null) {if (readLine.charAt(0) == '-') {continue;} else {sb.append(readLine);sb.append('\r');}}System.out.println("b4.........");X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(decodeBase64(sb.toString()));System.out.println("b5.........");KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);System.out.println("b6.........");//下行出错  java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=127, too big.PublicKey publicKey = keyFactory.generatePublic(pubX509);System.out.println("b7.........");return publicKey;} catch (Exception e) {e.printStackTrace();System.out.println("b8.........");throw new Exception("READ PUBLIC KEY ERROR:", e);} finally {try {if (inputStream != null) {inputStream.close();}} catch (IOException e) {inputStream = null;throw new Exception("INPUT STREAM CLOSE ERROR:", e);}}}public static PrivateKey getPrivateKey(InputStream inputStream, String keyAlgorithm) throws Exception {try {BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));StringBuilder sb = new StringBuilder();String readLine = null;while ((readLine = br.readLine()) != null) {if (readLine.charAt(0) == '-') {continue;} else {sb.append(readLine);sb.append('\r');}}System.out.println("hahhah4!"+decodeBase64(sb.toString()));PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(decodeBase64(sb.toString()));System.out.println("hahhah5!");KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);System.out.println("hahhah6!");PrivateKey privateKey = keyFactory.generatePrivate(priPKCS8);System.out.println("hahhah7!");return privateKey;} catch (Exception e) {throw new Exception("READ PRIVATE KEY ERROR:" ,e);}  finally {try {if (inputStream != null) {inputStream.close();}} catch (IOException e) {inputStream = null;throw new Exception("INPUT STREAM CLOSE ERROR:", e);}}}//一下面是base64的编码和解码public static String encodeBase64(byte[]input) throws Exception{Class clazz=Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");Method mainMethod= clazz.getMethod("encode", byte[].class);mainMethod.setAccessible(true);Object retObj=mainMethod.invoke(null, new Object[]{input});return (String)retObj;}/**** decode by Base64*/public static byte[] decodeBase64(String input) throws Exception{Class clazz=Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");Method mainMethod= clazz.getMethod("decode", String.class);mainMethod.setAccessible(true);Object retObj=mainMethod.invoke(null, input);return (byte[])retObj;}}
package com.qiouou.common.util.wxH5Pay;import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
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.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;public class ClientCustomSSL {public static final  String URL = "C:\\Users\\o\\Desktop\\WXCertUtil\\cert\\15******91_20191223_cert\\apiclient_cert.p12";public static final String MERID = "15******91";public static String doRefund(String url,String data) throws Exception {/*** 注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的*/KeyStore keyStore  = KeyStore.getInstance("PKCS12");FileInputStream instream = new FileInputStream(new File(URL));//P12文件目录try {/*** 此处要改* */keyStore.load(instream, MERID.toCharArray());//这里写密码..默认是你的MCHID} finally {instream.close();}// Trust own CA and all self-signed certs/*** 此处要改* */SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, MERID.toCharArray())//这里也是写密码的.build();// Allow TLSv1 protocol onlySSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[] { "TLSv1" },null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();try {HttpPost httpost = new HttpPost(url); // 设置响应头信息httpost.addHeader("Connection", "keep-alive");httpost.addHeader("Accept", "*/*");httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");httpost.addHeader("Host", "api.mch.weixin.qq.com");httpost.addHeader("X-Requested-With", "XMLHttpRequest");httpost.addHeader("Cache-Control", "max-age=0");httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");httpost.setEntity(new StringEntity(data, "UTF-8"));CloseableHttpResponse response = httpclient.execute(httpost);try {HttpEntity entity = response.getEntity();String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");EntityUtils.consume(entity);return jsonStr;} finally {response.close();}} finally {httpclient.close();}}/*** 企业微信支付到银行卡* @param url* @param data* @return* @throws Exception*/public static String paybank(String url,String data) throws Exception {/*** 注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的*/KeyStore keyStore  = KeyStore.getInstance("PKCS12");FileInputStream instream = new FileInputStream(new File(URL));//P12文件目录try {/*** 此处要改* */keyStore.load(instream, MERID.toCharArray());//这里写密码..默认是你的MCHID} finally {instream.close();}// Trust own CA and all self-signed certs/*** 此处要改* */SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, MERID.toCharArray())//这里也是写密码的.build();// Allow TLSv1 protocol onlySSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[] { "TLSv1" },null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();try {HttpPost httpost = new HttpPost(url); // 设置响应头信息httpost.addHeader("Connection", "keep-alive");httpost.addHeader("Accept", "*/*");httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");httpost.addHeader("Host", "fraud.mch.weixin.qq.com");httpost.addHeader("X-Requested-With", "XMLHttpRequest");httpost.addHeader("Cache-Control", "max-age=0");httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");httpost.setEntity(new StringEntity(data, "UTF-8"));CloseableHttpResponse response = httpclient.execute(httpost);try {HttpEntity entity = response.getEntity();String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");EntityUtils.consume(entity);return jsonStr;} finally {response.close();}} finally {httpclient.close();}}
}
package com.qiouou.common.util.Wechat;import org.apache.commons.codec.digest.DigestUtils;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;public class PayUtil {/*** 签名字符串** @param text          需要签名的字符串* @param key           密钥* @param input_charset 编码格式* @return 签名结果*/public static String sign(String text, String key, String input_charset) {text = text + "&key=" + key;return DigestUtils.md5Hex(getContentBytes(text, input_charset));}/*** 签名字符串** @param text          需要签名的字符串* @param sign          签名结果* @param key           密钥* @param input_charset 编码格式* @return 签名结果*/public static boolean verify(String text, String sign, String key, String input_charset) {text = text + key;String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset));if (mysign.equals(sign)) {return true;} else {return false;}}/*** @param content* @param charset* @return* @throws java.security.SignatureException* @throws UnsupportedEncodingException*/public static byte[] getContentBytes(String content, String charset) {if (charset == null || "".equals(charset)) {return content.getBytes();}try {return content.getBytes(charset);} catch (UnsupportedEncodingException e) {throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);}}private static boolean isValidChar(char ch) {if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))return true;if ((ch >= 0x4e00 && ch <= 0x7fff) || (ch >= 0x8000 && ch <= 0x952f))return true;// 简体中文汉字编码return false;}/*** 除去数组中的空值和签名参数** @param sArray 签名参数组* @return 去掉空值与签名参数后的新签名参数组*/public static Map<String, String> paraFilter(Map<String, String> sArray) {Map<String, String> result = new HashMap<String, String>();if (sArray == null || sArray.size() <= 0) {return result;}for (String key : sArray.keySet()) {String value = sArray.get(key);if (value == null || value.equals("") || key.equalsIgnoreCase("Sign")|| key.equalsIgnoreCase("sign_type")) {continue;}result.put(key, value);}return result;}/*** 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串** @param params 需要排序并参与字符拼接的参数组* @return 拼接后字符串*/public static String createLinkString(Map<String, String> params) {List<String> keys = new ArrayList<>(params.keySet());Collections.sort(keys);String prestr = "";for (int i = 0; i < keys.size(); i++) {String key = keys.get(i);String value = params.get(key);if (i == keys.size() - 1) {// 拼接时,不包括最后一个&字符prestr = prestr + key + "=" + value;} else {prestr = prestr + key + "=" + value + "&";}}return prestr;}/*** @param requestUrl    请求地址* @param requestMethod 请求方法* @param outputStr     参数*/public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {// 创建SSLContextStringBuffer buffer = null;try {URL url = new URL(requestUrl);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod(requestMethod);conn.setDoOutput(true);conn.setDoInput(true);conn.connect();//往服务器端写内容if (null != outputStr) {OutputStream os = conn.getOutputStream();os.write(outputStr.getBytes("utf-8"));os.close();}// 读取服务器端返回的内容InputStream is = conn.getInputStream();InputStreamReader isr = new InputStreamReader(is, "utf-8");BufferedReader br = new BufferedReader(isr);buffer = new StringBuffer();String line = null;while ((line = br.readLine()) != null) {buffer.append(line);}br.close();} catch (Exception e) {e.printStackTrace();}return buffer.toString();}public static String urlEncodeUTF8(String source) {String result = source;try {result = java.net.URLEncoder.encode(source, "UTF-8");} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}return result;}/*** 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。** @param strxml* @return* @throws org.jdom2.JDOMException* @throws IOException*/public static Map doXMLParse(String strxml) throws Exception {if (null == strxml || "".equals(strxml)) {return null;}Map m = new HashMap();InputStream in = String2Inputstream(strxml);SAXBuilder builder = new SAXBuilder();Document doc = builder.build(in);Element root = doc.getRootElement();List list = root.getChildren();Iterator it = list.iterator();while (it.hasNext()) {Element e = (Element) it.next();String k = e.getName();String v = "";List children = e.getChildren();if (children.isEmpty()) {v = e.getTextNormalize();} else {v = getChildrenText(children);}m.put(k, v);}//关闭流in.close();return m;}/*** 获取子结点的xml** @param children* @return String*/public static String getChildrenText(List children) {StringBuffer sb = new StringBuffer();if (!children.isEmpty()) {Iterator it = children.iterator();while (it.hasNext()) {Element e = (Element) it.next();String name = e.getName();String value = e.getTextNormalize();List list = e.getChildren();sb.append("<" + name + ">");if (!list.isEmpty()) {sb.append(getChildrenText(list));}sb.append(value);sb.append("</" + name + ">");}}return sb.toString();}public static InputStream String2Inputstream(String str) {return new ByteArrayInputStream(str.getBytes());}
}
package com.qiouou.common.util.wxH5Pay;import java.security.MessageDigest;public class MD5Utils {/*** MD5* @param buffer* @return*/public final static String getMessageDigest(byte[] buffer) {char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };try {MessageDigest mdTemp = MessageDigest.getInstance("MD5");mdTemp.update(buffer);byte[] md = mdTemp.digest();int j = md.length;char str[] = new char[j * 2];int k = 0;for (int i = 0; i < j; i++) {byte byte0 = md[i];str[k++] = hexDigits[byte0 >>> 4 & 0xf];str[k++] = hexDigits[byte0 & 0xf];}return new String(str);} catch (Exception e) {return null;}}
}

微信企业转账到银行卡相关推荐

  1. 微信企业转账JAVA版(包括:1,转账个人零钱;2,转账个人银行卡;3,微信官网的SDK3.0.9存在的支付问题)

    前言: 最近公司做产品,有这样几个需求 微信退款 微信企业给用户转账到零钱 通过微信给用户转账到银行卡 支付宝退款 支付宝转账到余额 根据上述需求,本人呢,做了几天的研究与学习,在此期间不免会出现摇头 ...

  2. 微信企业付款至银行卡 设置转账备注信息问题

    最近发现一个问题,还是用户反馈的,就是我们调起微信企业付款的接口,按照API中的参数都赋予响应的值之后,发现在一个参数desc(转账备注)中添加文字说明后,转账到微信零钱,收款方上面有我的备注信息,但 ...

  3. 微信支付转账到银行卡 加密问题解决方法

    @[TOC]微信支付转账到银行卡 加密问题解决方法 java.lang.NoClassDefFoundError: org/bouncycastle/jce/provider/BouncyCastle ...

  4. 微信企业付款到银行卡

    第一次做微信企业付款到银行卡,特地记录下来,因为这个功能自己用了2-3天,这中间的坑主要是再rsa加密那块.自己记录下来,供朋友参考.自己用的php开发 第一,首先你需要开通企业的微信认证公众号平台, ...

  5. 微信企业付款到银行卡(微信转账)(Java完整版)

    业务介绍 微信付款到银行卡,也就是转账.需要将银行卡号.卡主真实姓名按照微信支付制定的加密规则进行加密,(开发完感觉加密比转账复杂,哈哈哈).加密的秘钥,也就是钥匙,也要通过请求向微信获取,重点是获取 ...

  6. weixin4j-pay~最简单的微信企业付款到银行卡SDK

    估计大家搜到这里,已经是看了不少文档了,我这边背景就不多说了,直接上干货~~! 先睹为快,直接上调用方法 企业付款到银行卡 public static void main(String[] args) ...

  7. java实现微信企业付款到银行卡_微信企业付款到银行卡实现方式 - 黎明互联-官方博客 - 黎明互联 - 区块链培训,PHP培训,IT培训,职业技能培训,追求极致!改变您的职业生涯!...

    首先说一下微信支付已上线企业付款至银行卡功能.商户可以将商户号余额付款至指定的收款银行账户.通过指定收款银行账户户名.卡号,以及收款银行信息即可实现付款.但是功能目前为灰度开放,已灰度新资金流直连普通 ...

  8. 微信企业转账实例之理论介绍

    最近在搞公司的电商项目时,客户要求加上一个微信转账的功能.由于项目中并没有对应的插件,没法,只有现学现用.我先去微信商户平台官网上读取各种文档,最终做了一个demo.最后集成到了公司的项目中,大功告成 ...

  9. java微信--企业付款到银行卡

    企业付款到银行卡其实就是企业付款到到零钱的进价版,只不过比到零钱多了一个RSA加密.只要加密好了,根据官方提供的参数,直接请求即可. 首先就是通过官方提供的接口https://fraud.mch.we ...

  10. 微信商户转账到银行卡-java

    这个注意写在最前面是因为微信获取公钥以后的格式问题推荐  http://www.ssleye.com/web/pkcs PKCS#1转成PKCS#8 不然会一直提示公钥不正确 ------------ ...

最新文章

  1. Redis哨兵主备切换的数据丢失及Redis数据持久化
  2. node --- 在node中使用mongoosemongoDB的安装
  3. jgroups_JGroups:无需额外基础架构的领导人选举
  4. 如何利用phpize在生产环境中为php添加新的扩展php-bcmath
  5. 专题:CentOS社区企业操作系统
  6. MVC 之Action
  7. 关于asp.net C# 导出Excel文件 打开Excel文件格式与扩展名指定格式不一致的解决办法...
  8. msysgit中文问题
  9. 常用图片jpg png jpeg gif等格式介绍
  10. 4K显示器在M1上打开HiDPI
  11. 域名注册网站服务比较
  12. python爬虫爬取雪球网_Python爬虫:Selenium+ BeautifulSoup 爬取JS渲染的动态内容(雪球网新闻)...
  13. Oracle数据库上机练习6
  14. 5个免费GitHub最强前端学习资源 程序员不花一分钱也能变很强
  15. Java Future详解与使用
  16. linux wine运行效率,Linux 使用 Wine 运行 TIM 简明教程
  17. 标准差详解-一文搞懂标准差的含义
  18. Android总结(基础篇)-骚人文客
  19. 双向视频会议系统的需求分析
  20. java中怎么通过日期算出天数_Java如何通过计算两个日期的时间差来算出天数

热门文章

  1. 一本书读懂财报 | 现金流量表剖析
  2. 蓝桥:8皇后·改(⼋皇后问题)
  3. PythonSPSS完成空气质量状况的指数(AQI)分析
  4. ubuntu服务器网站备份,备份云服务器ubuntu系统
  5. 基于UMeng消息推送测试-demo教程(iOS版)
  6. 博士生导师谈他如何检索文献
  7. 2021-04-20 m_map的几个地形水深数据库安装步骤
  8. 23andMe宣称其基因报告可以检测2型糖尿病患病风险
  9. 【pygame小游戏】摸鱼系列:”躲避粒子“小游戏在线玩,看谁才是”最强王者“?
  10. 泛泛而谈的菜鸟学习记录(六)—— 贴花