1、因token and jsapi_ticket 调用次数有限,缓存token jsapi_ticke
,data工具为hotool可自行引入 /**
* @Description:获取access_toke 有效期7200s
*/
public String getAccessToken(String appId, String appSecret) {
WxToken wxToken = (WxToken) redisUtil.get("base_info:access_token:" + appId);
Date date = DateUtil.date();
String token = "";
if (null != wxToken && date.before(wxToken.getExpiresIn())) {
token = wxToken.getAccessToken();
} else {
String resultInfo = WxCommonUtil.doGet(WxToken_url.replace("APPID",
appId).replace("APPSECRET", appSecret));
JSONObject result = JSONObject.parseObject(resultInfo);
token = result.getString("access_token");
if (StringUtils.isNotBlank(result.getString("errcode"))) {
throw new BaseServiceException("get access_token error");
} else if (StringUtils.isNotBlank(token)) {
Date newDate = DateUtil.offset(date, DateField.SECOND, result.getInteger("expires_in") - 500);
WxToken token1 = new WxToken();
token1.setAccessToken(token);
token1.setExpiresIn(newDate);
redisUtil.set("base_info:access_token:" + appId, token1);
}
}
return token;
}
/**
* @Description: 获取wxConifg签名所需jsapi_ticket 凭证 有效期为7200s
*/
public String getJsapiTickets(String ticketUrl, String token, String appId) {
WxToken wxToken = (WxToken) redisUtil.get("base_info:ticket:" + appId);
Date date = DateUtil.date();
String ticket = null;
if (null != wxToken && date.before(wxToken.getExpiresIn())) {
ticket = wxToken.getTicket();
} else {
String ticktresult = WxCommonUtil.doGet(ticketUrl + token);
JSONObject jsonresult = JSONObject.parseObject(ticktresult);
ticket = jsonresult.getString("ticket");
if (!jsonresult.getString("errmsg").equals("ok")) {
throw new BaseServiceException("get ticket error");
} else if (StringUtils.isNotBlank(ticket)) {
Date newDate = DateUtil.offset(date, DateField.SECOND, jsonresult.getInteger("expires_in") - 500);
WxToken wxToken1 = new WxToken();
wxToken1.setTicket(ticket);
wxToken1.setExpiresIn(newDate);
redisUtil.set("base_info:ticket:" + appId, wxToken1);
}
}
return ticket;
}
2、获取前端调起微信支付所需参数 @Override
public Map getWxConfigInfo(PaySetDTO paySetDTO) {
PaySetVO ps = paySetMapper.findAll(paySetDTO.getSrcId());
String token = authGeneral.getAccessToken(ps.getAppId(), ps.getAppSecret());
if (StringUtils.isBlank(token)) {
throw new BaseServiceException("get token error");
}
String jsapi_ticket = authGeneral.getJsapiTickets(GET_TICKET_URL, token, ps.getAppId());
if (StringUtils.isBlank(jsapi_ticket)) {
throw new BaseServiceException("get ticket error");
}
//封装签名所需数据
SortedMap<Object, Object> configMap = new TreeMap<Object, Object>();
String noncestr = WxCommonUtil.getUUID();
String timestamp = System.currentTimeMillis() / 1000 + "";
configMap.put("noncestr", noncestr);
configMap.put("jsapi_ticket", jsapi_ticket);
configMap.put("timestamp", timestamp);
configMap.put("url", paySetDTO.getClientUrl());
//生成签名
String config_sign = WxCommonUtil.createSignSHA1("UTF-8", configMap);
SortedMap<Object, Object> params = new TreeMap<Object, Object>();
params.put("appId", ps.getAppId());
params.put("config_nonceStr", noncestr);
params.put("config_timestamp", timestamp);
params.put("config_sign", config_sign);
return params;
}
3、微信常用接口集锦(返回类型可自行封装)
/** * @author : nyl * create at: 2020/1/17 上午11:48 *
@description: 支付退款 */ @Slf4j public class RechargeOperation {
//请求下单接口
private static final String UNI_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//微信企业付款到个人零钱
private static final String transferUrl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
//微信转转账到银行
private static final String wxToBank = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
//微信退款
private static final String wxToRefund = "https://api.mch.weixin.qq.com/secapi/pay/refund";
//查询订单
private static final String ORDER_QUERY_URL = "https://api.mch.weixin.qq.com/pay/orderquery";
//查询退款订单
private static final String REFUND_QUERY_URL = "https://api.mch.weixin.qq.com/pay/refundquery";
//查询企业付款订单
private static final String ORDER_PAYMENT_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo";
//查询企业到银行卡
private static final String QUERY_BANK_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo";
/**
* @Description:微信jsapi支付
*/
public static SortedMap<Object, Object> toPay(String appId, String mchId, String paySecret, String openId, String orderNum,
double money, String title, String clientip, String paynotify,
HttpServletRequest request) {
try {
SortedMap<Object, Object> params = new TreeMap<Object, Object>();
//公众账号ID
params.put("appid", appId);
//商户号
params.put("mch_id", mchId);
//随机字符串,不能大于32位
params.put("nonce_str", WxCommonUtil.getUUID());
//支付时订单描述
params.put("body", title);
//支付时订单详情
//params.put("detail", descript);
//调用方平台的订单号
params.put("out_trade_no", orderNum);
//调用方平台的订单总金额,单位:元
params.put("total_fee", String.valueOf(Double.valueOf(WxCommonUtil.mul(money,
100)).intValue()));
//调用接口机器ip
params.put("spbill_create_ip", clientip);
//支付完成后的异步回调地址
params.put("notify_url", paynotify);
// 支付方式为JSAPI支付 JSAPI, NATIVE, APP, WAP, MWEB
params.put("trade_type", "JSAPI");
//微信用户openid,JSAPI支付必填参数
params.put("openid", openId);
//生成签名
String sign = WxCommonUtil.createSignMD5(params, paySecret);
log.info("微信请求支付接口签名:" + sign);
params.put("sign", sign);
log.info("微信请求支付接口参数:" + params);
//生成xml结构的数据,用于统一下单请求的xml请求数据
String requestXML = WxCommonUtil.getRequestXml(params);
log.info("请求统一支付requestXML:" + requestXML);
//1、使用POST请求统一下单接口,获取预支付单号prepay_id
//2.请求下单接口
String result = WxCommonUtil.httpsRequestString(UNI_URL, "POST", requestXML);
log.error("微信请求支付接口返回:" + result);
//解析微信返回的信息,以Map形式存储便于取值
Map<String, String> map = WxCommonUtil.doXMLParse(result);
// String return_code = map.get("return_code");//返回状态码
SortedMap<Object, Object> sortedMap = new TreeMap<Object, Object>();
//全局map,该map存放前端ajax请求的返回值信息,包括wx.config中的配置参数值,也包括wx.chooseWXPay中的配置参数值
sortedMap.put("appId", appId);
sortedMap.put("timeStamp", System.currentTimeMillis() / 1000 + ""); //时间戳
sortedMap.put("nonceStr", WxCommonUtil.getUUID()); //随机字符串
sortedMap.put("package", "prepay_id=" + map.get("prepay_id")); //预支付单号,格式为 prepay_id=***
sortedMap.put("signType", "MD5"); //签名的方式必须是MD5
//获取预支付prepay_id后,需要再次签名,此次签名是用于前端js中的wx.chooseWXPay中的paySign
//appId、timeStamp、nonceStr、package、signType
String paySign = WxCommonUtil.createSignMD5(sortedMap, paySecret);
//支付签名
sortedMap.put("paySign", paySign);
//获取到微信版本号是否高于或者等于5.0
String userAgent = request.getHeader("user-agent");
char agent = userAgent.charAt(userAgent.indexOf("MicroMessenger") + 15);
sortedMap.put("agent", new String(new char[]{agent}));
return sortedMap;
} catch (Exception e) {
log.error("微信支付异常" + e.getMessage());
return null;
}
}
/**
* @Description: 微信企业付款到个人零钱
*/
public static WxCommonNotify toTransfer(Map<String, String> map) {
try {
SortedMap<Object, Object> params = new TreeMap<Object, Object>();
//商户账号appid
params.put("mch_appid", map.get("appid"));
//商户号
params.put("mchid", map.get("mch_id"));
//随机字符串
params.put("nonce_str", WxCommonUtil.getUUID());
//商户订单号,需保持唯一性只能是字母或者数字,不能包含有其它字符
params.put("partner_trade_no", map.get("orderNum"));
//用户openid
params.put("openid", map.get("openid"));
//校验用户姓名选项 NO_CHECK:不校验真实姓名 FORCE_CHECK:强校验真实姓名
params.put("check_name", "NO_CHECK");
//收款用户真实姓名,如果check_name设置为FORCE_CHECK,则必填用户真实姓名
//params.put("re_user_name", realName);
//金额
params.put("amount", String.valueOf(Double.valueOf(WxCommonUtil.mul(Double.valueOf(map.get("money")),
100)).intValue()));
//企业付款备注
params.put("desc", map.get("desc"));
//ip地址
params.put("spbill_create_ip", WxCommonUtil.localIp());
//MD5签名
params.put("sign", WxCommonUtil.createSignMD5(params, map.get("paySecret")));
log.error("~~~~~~~~~微信请求企业付款接口参数:" + params);
String data = WxCommonUtil.getRequestXml(params);
String result = WxCommonUtil.withdrawalPost(transferUrl, data, map.get("mch_id"), map.get("certPath"));
log.error("~~~~~~~微信请求企业付款接口返回:" + result);
Map<String, String> resultMap = WxCommonUtil.doXMLParse(result);
String return_code = resultMap.get("return_code");
if (StringUtils.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
return new WxCommonNotify(false, resultMap.get("return_msg"));
}
String result_code = resultMap.get("result_code");
if (StringUtils.isBlank(result_code) || !"SUCCESS".equals(result_code)) {
return new WxCommonNotify(false, resultMap.get("err_code_des"));
}
//返回付款单号 付款时间
return new WxCommonNotify(true, resultMap.get("payment_no") + "," + resultMap.get("payment_time"));
} catch (Exception e) {
log.error("企业付款到零钱异常" + e.getMessage());
return new WxCommonNotify(false, e.getMessage());
}
}
/**
* @Description: 原路退回 没有手续费
*/
public static WxCommonNotify toRefund(String appid, String mchid, String secret, String certPath, String refundNum, String
orderNum, String tradeNo, double totalAmount, double refundAmount) {
try {
//1.将参数封装map
SortedMap<Object, Object> params = new TreeMap<>();
//公众账号ID
params.put("appid", appid);
//商户号
params.put("mch_id", mchid);
//随机字符串
params.put("nonce_str", WxCommonUtil.getUUID());
//原订单号(与原付款微信交易号二选一不可为空)
params.put("out_trade_no", orderNum);
//退款单号
params.put("out_refund_no", refundNum);
//原订单总金额,单位:分
params.put("total_fee", String.valueOf(Double.valueOf(WxCommonUtil.mul(totalAmount,
100)).intValue()));
//退款金额,单位:分
params.put("refund_fee", String.valueOf(Double.valueOf(WxCommonUtil.mul(refundAmount,
100)).intValue()));
//原付款微信交易号(与原订单号二选一不可为空)
//params.put("transaction_id", tradeNo);
//签名算法
params.put("sign", WxCommonUtil.createSignMD5(params, secret));
log.info("请求结果集:" + params);
//2.请求接口
String result = WxCommonUtil.withdrawalPost(wxToRefund, WxCommonUtil.getRequestXml(params), mchid, certPath);
log.info("请求微信原路退款结果集:" + result);
Map<String, String> resultMap = WxCommonUtil.doXMLParse(result);
String return_code = resultMap.get("return_code");
if (StringUtils.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
return new WxCommonNotify(false, resultMap.get("return_msg"));
}
String result_code = resultMap.get("result_code");
if (StringUtils.isBlank(result_code) || !"SUCCESS".equals(result_code)) {
return new WxCommonNotify(false, resultMap.get("err_code_des"));
}
return new WxCommonNotify(true);
} catch (Exception e) {
log.error("微信原路退回异常" + e.getMessage());
return new WxCommonNotify(false, e.getMessage());
}
}
/**
* @Description: 提现到银行卡
*/
public static WxCommonNotify wxToBank(Map<String, String> map) {
try {
//将参数封装map
SortedMap<Object, Object> params = new TreeMap<>();
//微信支付分配的商户号
params.put("mch_id", map.get("mch_id"));
//商户订单号,需保持唯一
params.put("partner_trade_no", map.get("orderNum"));
//随机字符串,不长于32位
params.put("nonce_str", WxCommonUtil.getUUID());
//收款方银行卡号
params.put("enc_bank_no", WechatUtil.rsaEncryption(map.get("cardNum"), map.get("pemUrl")));
//收款方用户名
params.put("enc_true_name", WechatUtil.rsaEncryption(map.get("userName"), map.get("pemUrl")));
//银行卡所在开户行编号
params.put("bank_code", map.get("bankCode"));
//转账金额
params.put("amount", String.valueOf(Double.valueOf(WxCommonUtil.mul(Double.valueOf(map.get("money")),
100)).intValue()));
//说明
params.put("desc", map.get("desc"));
//通过MD5签名算法计算得出的签名值
params.put("sign", WxCommonUtil.createSignMD5(params, map.get("paySecret")));
log.error("微信请求企业付款接口参数:" + params);
//请求微信接口并拿到返回数据
String result = WxCommonUtil.withdrawalPost(wxToBank, WxCommonUtil.getRequestXml(params), map.get("mch_id"),
map.get("certPath"));
log.error("微信请求企业付款接口返回:" + result);
Map<String, String> resultMap = WxCommonUtil.doXMLParse(result);
String return_code = resultMap.get("return_code");
if (StringUtils.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
return new WxCommonNotify(false, resultMap.get("return_msg"));
}
String result_code = resultMap.get("result_code");
if (StringUtils.isBlank(result_code) || !"SUCCESS".equals(result_code)) {
return new WxCommonNotify(false, resultMap.get("err_code_des"));
}
//返回付款单号 手续费cmms_amt 单位:分
return new WxCommonNotify(true, resultMap.get("payment_no") + "," + resultMap.get("cmms_amt"));
} catch (Exception e) {
log.error("提现到银行卡异常" + e.getMessage());
return new WxCommonNotify(false, e.getMessage());
}
}
/**
* @Description: 查询支付订单
*/
public static HttpResult orderQuery(String appId, String mchId, String paySecret, String transaction_id, String orderNum) {
try {
SortedMap<Object, Object> params = new TreeMap<Object, Object>();
//公众账号ID
params.put("appid", appId);
//商户号
params.put("mch_id", mchId);
//随机字符串,不能大于32位
params.put("nonce_str", WxCommonUtil.getUUID());
//支付单号 二选一
//params.put("transaction_id", transaction_id);
//商户订单号 二选一
params.put("out_trade_no", orderNum);
//生成签名
String sign = WxCommonUtil.createSignMD5(params, paySecret);
log.info("微信请求支付接口签名:" + sign);
params.put("sign", sign);
log.info("微信请求支付接口参数:" + params);
//生成xml结构的数据,用于统一下单请求的xml请求数据
String requestXML = WxCommonUtil.getRequestXml(params);
//log.info("请求统一支付requestXML:" + requestXML);
//1、使用POST请求统一下单接口,获取预支付单号prepay_id
//2.请求下单接口
String result = WxCommonUtil.httpsRequestString(ORDER_QUERY_URL, "POST",
requestXML);
log.error("微信请求支付接口返回:" + result);
//解析微信返回的信息,以Map形式存储便于取值
Map<String, String> resultMap = WxCommonUtil.doXMLParse(result);
String return_code = resultMap.get("return_code");
if (StringUtils.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
return HttpResult.error(resultMap.get("return_msg"));
}
String result_code = resultMap.get("result_code");
if (StringUtils.isBlank(result_code) || !"SUCCESS".equals(result_code)) {
return HttpResult.error(resultMap.get("err_code_des"));
}
return HttpResult.ok(resultMap);
} catch (Exception e) {
log.error("支付订单查询异常" + e.getMessage());
return null;
}
}
/**
* @Description: 查询企业付款订单
*/
public static Map queryPaymentOrder(String appId, String mchId, String paySecret, String orderNum, String certPath) {
Map<String, String> map = new HashMap<>();
try {
SortedMap<Object, Object> params = new TreeMap<Object, Object>();
//公众账号ID
params.put("appid", appId);
//商户号
params.put("mch_id", mchId);
//随机字符串,不能大于32位
params.put("nonce_str", WxCommonUtil.getUUID());
//商户订单号
params.put("partner_trade_no", orderNum);
//生成签名
String sign = WxCommonUtil.createSignMD5(params, paySecret);
log.info("微信请求支付接口签名:" + sign);
params.put("sign", sign);
log.info("微信请求支付接口参数:" + params);
String requestXML = WxCommonUtil.getRequestXml(params);
String result = WxCommonUtil.withdrawalPost(ORDER_PAYMENT_URL, requestXML, mchId,
certPath);
log.error("微信请求支付接口返回:" + result);
Map<String, String> resultMap = WxCommonUtil.doXMLParse(result);
String return_code = resultMap.get("return_code");
String result_code = resultMap.get("result_code");
String status = resultMap.get("status");
if (StringUtils.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
map.put("errorMsg", resultMap.get("return_msg"));
} else if (StringUtils.isBlank(result_code) || !"SUCCESS".equals(result_code)) {
map.put("errorMsg", resultMap.get("err_code_des"));
} else if ("FAILED".equals(status)) {
map.put("errorMsg", resultMap.get("reason"));
} else if ("SUCCESS".equals(status) || "PROCESSING".equals(status)) {
map.put("status", status);
} else {
map.put("errorMsg", "未知错误");
}
} catch (Exception e) {
log.error("企业付款到个人订单查询异常" + e.getMessage());
map.put("errorMsg", e.getMessage());
}
return map;
}
/**
* @Description: 查询企业付款到银行
*/
public static Map<String, String> queryBank(String mchId, String paySecret, String orderNum, String certPath) {
try {
SortedMap<Object, Object> params = new TreeMap<Object, Object>();
params.put("mch_id", mchId);
//随机字符串,不能大于32位
params.put("nonce_str", WxCommonUtil.getUUID());
//商户订单号
params.put("partner_trade_no", orderNum);
//生成签名
String sign = WxCommonUtil.createSignMD5(params, paySecret);
log.info("微信请求支付接口签名:" + sign);
params.put("sign", sign);
log.info("微信请求支付接口参数:" + params);
String requestXML = WxCommonUtil.getRequestXml(params);
String result = WxCommonUtil.withdrawalPost(QUERY_BANK_URL, requestXML, mchId,
certPath);
log.error("微信请求支付接口返回:" + result);
//解析微信返回的信息,以Map形式存储便于取值
return WxCommonUtil.doXMLParse(result);
} catch (Exception e) {
log.error("企业付款到银行查询异常" + e.getMessage());
return null;
}
} } ```
4、用到的工具类
/**
* @Description:md5签名生成
* @Author:Nyl
* @Create: 2020/1/7 15:41
*/
public static String createSignMD5(SortedMap<Object, Object> parameters, String API_KEY) {
StringBuilder sb = new StringBuilder();
Set<Map.Entry<Object, Object>> es = parameters.entrySet();
Iterator<Map.Entry<Object, Object>> it = es.iterator();
while (it.hasNext()) {
Map.Entry<Object, Object> entry = it.next();
String k = (String) entry.getKey();
Object v = entry.getValue();
if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
/** 支付密钥必须参与加密,放在字符串最后面 */
sb.append("key=" + API_KEY);
String sign = Md5Encrypt.encodeByMD5(sb.toString()).toUpperCase();
return sign;
}
public static Map doXMLParse(String strxml) throws JDOMException, IOException {
strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
if (null == strxml || "".equals(strxml)) {
return null;
}
Map m = new HashMap();
InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
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 = WxCommonUtil.getChildrenText(children);
}
m.put(k, v);
}
//关闭流
in.close();
return m;
}
/**
* 退款请求并验证证书
*/
public static String withdrawalPost(String url, String data, String mch_id, String certPath) throws Exception {
//指定读取证书格式为PKCS12
KeyStore keyStore = KeyStore.getInstance("PKCS12");
//读取本机存放的PKCS12证书文件
FileInputStream instream = new FileInputStream(new File(certPath));
try {
//指定PKCS12的密码(商户ID)
keyStore.load(instream, mch_id.toCharArray());
} finally {
instream.close();
}
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mch_id.toCharArray()).build();
SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(
sslcontext, new String[]{"TLSv1"}, null,
new DefaultHostnameVerifier());
// SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
// sslcontext,new String[] { "TLSv1" },null,
// SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
//设置httpclient的SSLSocketFactory
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(factory).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();
}
}
public static Map doXMLParse(String strxml) throws JDOMException, IOException {
strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
if (null == strxml || "".equals(strxml)) {
return null;
}
Map m = new HashMap();
InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
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 = WxCommonUtil.getChildrenText(children);
}
m.put(k, v);
}
//关闭流
in.close();
return m;
}
//两个参数的积
public static double mul(double v1, double v2) {
BigDecimal b1 = new BigDecimal(String.valueOf(v1));
BigDecimal b2 = new BigDecimal(String.valueOf(v2));
return b1.multiply(b2).doubleValue();
}
//敏感数据RSA加密
public static String rsaEncryption(String parameter,String pubKeyUrl) {
PublicKey pub;
pub = RSAUtil.getPubKey(pubKeyUrl, "RSA");
try {
return Base64.encode(RSAUtil.encrypt(parameter.getBytes(), pub, 2048, 11, RSA_WAY));//并转为base64格式
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static PublicKey getPubKey(String publicKeyPath, String keyAlgorithm) {
PublicKey publicKey = null;
InputStream inputStream = null;
try {
URL urlPro = new URL(publicKeyPath);
inputStream = new DataInputStream(urlPro.openStream());
publicKey = getPublicKey(inputStream, keyAlgorithm);
} catch (Exception e) {
e.printStackTrace();//EAD PUBLIC KEY ERROR
System.out.println("加载公钥出错!");
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception e) {
System.out.println("加载公钥,关闭流时出错!");
}
}
}
return publicKey;
}
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 interface PublicKey extends Key {
// Declare serialVersionUID to be compatible with JDK1.1
/**
* The class fingerprint that is set to indicate serialization
* compatibility with a previous version of the class.
*/
static final long serialVersionUID = 7187392471159151072L;
}
微信公众号支付、支付查询、退款、退款查询、转账到零钱银行卡、转账查询接口整合(V2)
于 2020-12-17 16:35:52 首次发布