package com.framework.loippi.plugins.wxapppay.withdrawalbank;
import com.framework.loippi.cache.ConfigCache;
import com.framework.loippi.plugins.wxapppay.MD5;
import com.framework.loippi.plugins.wxapppay.MD5Util;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
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.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.jdom.Document;
import org.jdom.input.SAXBuilder;
import org.springframework.util.ResourceUtils;
import javax.net.ssl.SSLContext;
import java.io.*;
import java.math.BigDecimal;
import java.security.KeyStore;
import java.security.PublicKey;
import java.util.*;
public class WeChatWithdrawalBankUtil {
private static final String TRANS_URL = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
// 微信商户appkey
private static String appKey = ConfigCache.getConfig("wx.pay.key");
// 微信商户证书路径
private static String certPath = ConfigCache.getConfig("wx.pay.ssl.pkcs12File");
// 微信支付分配的商户号
private static String mchId = ConfigCache.getConfig("wx.pay.mchId");
//证书密码
private static String sslPassword = ConfigCache.getConfig("wx.pay.ssl.password");
//pkcs1公钥路径
private static String keyfile = ConfigCache.getConfig("wx.pay.ssl.publicFile");
// 请求器的配置
private static RequestConfig requestConfig;
// 连接超时时间,默认10秒
private static int socketTimeout = 10000;
// 传输超时时间,默认30秒
private static int connectTimeout = 30000;
/**
*银行卡提现
* @param partnerTradeNo 商户订单号,需保持唯一性(只能是字母或者数字,不能包含有其他字符) 必填
* @param encBankNo 收款方银行卡号
* @param encTrueName 收款方用户名
* @param bankCode 银行卡所在开户行编号 t_system_bank的bank_id字段
* @param amount 付款金额 单位为元 必填
* @param desc 付款备注 必填
* @return result 返回结果列子(是一个xml字符串):
*
*
*
*
*
*
*
*
*
* 500
*
* 0
*
*判断 失败:result.contains("CDATA[FAIL]") 返回true 失败 false成功
* SAXBuilder saxBuilder = new SAXBuilder();
* Document doc = saxBuilder.build(new StringReader(result));
* 获取错误原因:return doc.getRootElement().getChild("err_code_des").getValue();
* 成功 获取交易单号:return doc.getRootElement().getChild("payment_no").getValue();
*/
public static String doTransfers(String partnerTradeNo, String encBankNo, String encTrueName,String bankCode,BigDecimal amount, String desc){
String result ="success";
try
{
String nonceStr = genNonceStr();
String rsa ="RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING";
StringBuffer pkcs1Path = new StringBuffer();
pkcs1Path.append("classpath:").append(keyfile);
PublicKey pub=RSAUtils.getPubKey(pkcs1Path.toString(),"RSA");
byte[] estr=RSAUtils.encrypt(encBankNo.getBytes(),pub,2048, 11,rsa); //对银行账号进行加密
encBankNo =WxBase64.encode(estr);//并转为base64格式
byte[] estr2=RSAUtils.encrypt(encTrueName.getBytes(),pub,2048, 11,rsa); //对银行账号进行加密
encTrueName=WxBase64.encode(estr2);//并转为base64格式
SortedMap parameters = new TreeMap();
parameters.put("amount", amount.multiply(new BigDecimal("100")).intValue()+"");
parameters.put("desc", desc);
parameters.put("mch_id", mchId);
parameters.put("nonce_str", nonceStr);
parameters.put("enc_bank_no", encBankNo);
parameters.put("enc_true_name", encTrueName);
parameters.put("bank_code", bankCode);
parameters.put("partner_trade_no", partnerTradeNo);
parameters.put("sign", createSign(parameters, appKey));
String data = SortedMaptoXml(parameters);
// 3.加载证书请求接口
System.out.println(data);
result = weChatWithdrawal(data);
System.out.println("------aaaaa------"+result);
}
catch (Exception e)
{
e.printStackTrace();
return "银行卡提现失败";
}
return result;
}
/**
* 证书使用
* 微信提现
*/
@SuppressWarnings("deprecation")
public static String weChatWithdrawal(String data) throws Exception {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
StringBuffer pkcsPath = new StringBuffer();
pkcsPath.append("classpath:").append(certPath);
System.out.println("certPath"+certPath);
InputStream instream = null;
try {
instream = ResourceUtils.getURL(pkcsPath.toString()).openStream();
} catch (IOException var10) {
}
if (instream == null) {
return null;
}
String result = "";
try {
keyStore.load(instream, sslPassword.toCharArray());
} finally {
instream.close();
}
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, sslPassword.toCharArray())
.build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[]{"TLSv1"},
null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
try {
HttpPost httppost = new HttpPost(TRANS_URL);
StringEntity entitys = new StringEntity(data,"UTF-8");
httppost.setEntity((HttpEntity) entitys);
// 根据默认超时限制初始化requestConfig
requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
// 设置请求器的配置
httppost.setConfig(requestConfig);
CloseableHttpResponse response = httpclient.execute(httppost);
try {
HttpEntity entity = response.getEntity();
result = EntityUtils.toString(entity,"UTF-8");
} finally {
response.close();
}
} finally {
httpclient.close();
}
return result;
}
/**
* 生成32位随机数字
*/
public static String genNonceStr() {
Random random = new Random();
return MD5.getMessageDigest(String.valueOf(random.nextInt(1000