diff --git a/weixin-java-pay/pom.xml b/weixin-java-pay/pom.xml index 7e9780f8..7bb79b22 100644 --- a/weixin-java-pay/pom.xml +++ b/weixin-java-pay/pom.xml @@ -23,10 +23,11 @@ com.github.binarywang qrcode-utils + org.jodd jodd-http - compile + provided diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResult.java index 3f07a581..802e22b3 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResult.java @@ -1,7 +1,7 @@ package com.github.binarywang.wxpay.bean.result; import com.github.binarywang.wxpay.exception.WxPayException; -import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; +import com.github.binarywang.wxpay.service.impl.WxPayServiceAbstractImpl; import com.github.binarywang.wxpay.util.SignUtils; import com.google.common.base.Joiner; import com.google.common.collect.Maps; @@ -307,7 +307,7 @@ public abstract class WxPayBaseResult { /** * 校验返回结果签名 */ - public void checkResult(WxPayServiceImpl wxPayService) throws WxPayException { + public void checkResult(WxPayServiceAbstractImpl wxPayService) throws WxPayException { //校验返回结果签名 Map map = toMap(); if (getSign() != null && !SignUtils.checkSign(map, wxPayService.getConfig().getMchKey())) { diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImpl.java new file mode 100644 index 00000000..aa929176 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImpl.java @@ -0,0 +1,466 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.utils.qrcode.QrcodeUtils; +import com.github.binarywang.wxpay.bean.request.*; +import com.github.binarywang.wxpay.bean.result.*; +import com.github.binarywang.wxpay.config.WxPayConfig; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.util.SignUtils; +import com.google.common.collect.Maps; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + *
+ *  微信支付接口请求抽象实现类
+ * Created by Binary Wang on 2017-7-8.
+ * 
+ * @author Binary Wang + */ +public abstract class WxPayServiceAbstractImpl implements WxPayService { + private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com"; + protected final Logger log = LoggerFactory.getLogger(this.getClass()); + + protected WxPayConfig config; + + @Override + public WxPayConfig getConfig() { + return this.config; + } + + @Override + public void setConfig(WxPayConfig config) { + this.config = config; + } + + private String getPayBaseUrl() { + if (this.getConfig().useSandbox()) { + return PAY_BASE_URL + "/sandboxnew"; + } + + return PAY_BASE_URL; + } + + /** + * 发送post请求 + * + * @param url 请求地址 + * @param requestStr 请求信息 + * @param useKey 是否使用证书 + * @return 返回请求结果字符串 + */ + protected abstract String post(String url, String requestStr, boolean useKey) throws WxPayException; + + @Override + public WxPayRefundResult refund(WxPayRefundRequest request) throws WxPayException { + request.checkAndSign(this.getConfig()); + + String url = this.getPayBaseUrl() + "/secapi/pay/refund"; + String responseContent = this.post(url, request.toXML(), true); + WxPayRefundResult result = WxPayBaseResult.fromXML(responseContent, WxPayRefundResult.class); + result.checkResult(this); + return result; + } + + @Override + public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId) + throws WxPayException { + WxPayRefundQueryRequest request = new WxPayRefundQueryRequest(); + request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); + request.setTransactionId(StringUtils.trimToNull(transactionId)); + request.setOutRefundNo(StringUtils.trimToNull(outRefundNo)); + request.setRefundId(StringUtils.trimToNull(refundId)); + + request.checkAndSign(this.getConfig()); + + String url = this.getPayBaseUrl() + "/pay/refundquery"; + String responseContent = this.post(url, request.toXML(), false); + WxPayRefundQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayRefundQueryResult.class); + result.composeRefundRecords(); + result.checkResult(this); + return result; + } + + @Override + public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxPayException { + try { + log.debug("微信支付回调参数详细:{}", xmlData); + WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlData); + log.debug("微信支付回调结果对象:{}", result); + result.checkResult(this); + return result; + } catch (WxPayException e) { + log.error(e.getMessage(), e); + throw e; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new WxPayException("发生异常," + e.getMessage(), e); + } + } + + @Override + public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request) throws WxPayException { + request.checkAndSign(this.getConfig()); + + String url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendredpack"; + if (request.getAmtType() != null) { + //裂变红包 + url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendgroupredpack"; + } + + String responseContent = this.post(url, request.toXML(), true); + WxPaySendRedpackResult result = WxPayBaseResult.fromXML(responseContent, WxPaySendRedpackResult.class); + //毋须校验,因为没有返回签名信息 + // this.checkResult(result); + return result; + } + + @Override + public WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxPayException { + WxPayRedpackQueryRequest request = new WxPayRedpackQueryRequest(); + request.setMchBillNo(mchBillNo); + request.setBillType("MCHT"); + request.checkAndSign(this.getConfig()); + + String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gethbinfo"; + String responseContent = this.post(url, request.toXML(), true); + WxPayRedpackQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayRedpackQueryResult.class); + result.checkResult(this); + return result; + } + + @Override + public WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxPayException { + WxPayOrderQueryRequest request = new WxPayOrderQueryRequest(); + request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); + request.setTransactionId(StringUtils.trimToNull(transactionId)); + request.checkAndSign(this.getConfig()); + + String url = this.getPayBaseUrl() + "/pay/orderquery"; + String responseContent = this.post(url, request.toXML(), false); + if (StringUtils.isBlank(responseContent)) { + throw new WxPayException("无响应结果"); + } + + WxPayOrderQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderQueryResult.class); + result.composeCoupons(); + result.checkResult(this); + return result; + } + + @Override + public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxPayException { + if (StringUtils.isBlank(outTradeNo)) { + throw new IllegalArgumentException("out_trade_no不能为空"); + } + + WxPayOrderCloseRequest request = new WxPayOrderCloseRequest(); + request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); + request.checkAndSign(this.getConfig()); + + String url = this.getPayBaseUrl() + "/pay/closeorder"; + String responseContent = this.post(url, request.toXML(), false); + WxPayOrderCloseResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderCloseResult.class); + result.checkResult(this); + + return result; + } + + @Override + public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) throws WxPayException { + request.checkAndSign(this.getConfig()); + + String url = this.getPayBaseUrl() + "/pay/unifiedorder"; + String responseContent = this.post(url, request.toXML(), false); + WxPayUnifiedOrderResult result = WxPayBaseResult.fromXML(responseContent, WxPayUnifiedOrderResult.class); + result.checkResult(this); + return result; + } + + @Override + public Map getPayInfo(WxPayUnifiedOrderRequest request) throws WxPayException { + WxPayUnifiedOrderResult unifiedOrderResult = this.unifiedOrder(request); + String prepayId = unifiedOrderResult.getPrepayId(); + if (StringUtils.isBlank(prepayId)) { + throw new RuntimeException(String.format("无法获取prepay id,错误代码: '%s',信息:%s。", + unifiedOrderResult.getErrCode(), unifiedOrderResult.getErrCodeDes())); + } + + Map payInfo = new HashMap<>(); + if ("NATIVE".equals(request.getTradeType())) { + payInfo.put("codeUrl", unifiedOrderResult.getCodeURL()); + } else if ("APP".equals(request.getTradeType())) { + // APP支付绑定的是微信开放平台上的账号,APPID为开放平台上绑定APP后发放的参数 + String appId = getConfig().getAppId(); + Map configMap = new HashMap<>(); + // 此map用于参与调起sdk支付的二次签名,格式全小写,timestamp只能是10位,格式固定,切勿修改 + String partnerid = getConfig().getMchId(); + configMap.put("prepayid", prepayId); + configMap.put("partnerid", partnerid); + configMap.put("package", "Sign=WXPay"); + configMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000)); + configMap.put("noncestr", String.valueOf(System.currentTimeMillis())); + configMap.put("appid", appId); + // 此map用于客户端与微信服务器交互 + payInfo.put("sign", SignUtils.createSign(configMap, this.getConfig().getMchKey())); + payInfo.put("prepayId", prepayId); + payInfo.put("partnerId", partnerid); + payInfo.put("appId", appId); + payInfo.put("packageValue", "Sign=WXPay"); + payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); + payInfo.put("nonceStr", String.valueOf(System.currentTimeMillis())); + } else if ("JSAPI".equals(request.getTradeType())) { + payInfo.put("appId", unifiedOrderResult.getAppid()); + // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 + payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); + payInfo.put("nonceStr", String.valueOf(System.currentTimeMillis())); + payInfo.put("package", "prepay_id=" + prepayId); + payInfo.put("signType", "MD5"); + payInfo.put("paySign", SignUtils.createSign(payInfo, this.getConfig().getMchKey())); + } + return payInfo; + } + + @Override + public WxEntPayResult entPay(WxEntPayRequest request) throws WxPayException { + request.checkAndSign(this.getConfig()); + String url = this.getPayBaseUrl() + "/mmpaymkttransfers/promotion/transfers"; + + String responseContent = this.post(url, request.toXML(), true); + WxEntPayResult result = WxPayBaseResult.fromXML(responseContent, WxEntPayResult.class); + result.checkResult(this); + return result; + } + + @Override + public WxEntPayQueryResult queryEntPay(String partnerTradeNo) throws WxPayException { + WxEntPayQueryRequest request = new WxEntPayQueryRequest(); + request.setPartnerTradeNo(partnerTradeNo); + request.checkAndSign(this.getConfig()); + + String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gettransferinfo"; + String responseContent = this.post(url, request.toXML(), true); + WxEntPayQueryResult result = WxPayBaseResult.fromXML(responseContent, WxEntPayQueryResult.class); + result.checkResult(this); + return result; + } + + @Override + public byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength) { + String content = this.createScanPayQrcodeMode1(productId); + return this.createQrcode(content, logoFile, sideLength); + } + + @Override + public String createScanPayQrcodeMode1(String productId) { + //weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX + StringBuilder codeUrl = new StringBuilder("weixin://wxpay/bizpayurl?"); + Map params = Maps.newHashMap(); + params.put("appid", this.getConfig().getAppId()); + params.put("mch_id", this.getConfig().getMchId()); + params.put("product_id", productId); + params.put("time_stamp", String.valueOf(System.currentTimeMillis() / 1000));//这里需要秒,10位数字 + params.put("nonce_str", String.valueOf(System.currentTimeMillis())); + + String sign = SignUtils.createSign(params, this.getConfig().getMchKey()); + params.put("sign", sign); + + + for (String key : params.keySet()) { + codeUrl.append(key + "=" + params.get(key) + "&"); + } + + String content = codeUrl.toString().substring(0, codeUrl.length() - 1); + log.debug("扫码支付模式一生成二维码的URL:{}", content); + return content; + } + + @Override + public byte[] createScanPayQrcodeMode2(String codeUrl, File logoFile, Integer sideLength) { + return this.createQrcode(codeUrl, logoFile, sideLength); + } + + private byte[] createQrcode(String content, File logoFile, Integer sideLength) { + if (sideLength == null || sideLength < 1) { + return QrcodeUtils.createQrcode(content, logoFile); + } + + return QrcodeUtils.createQrcode(content, sideLength, logoFile); + } + + public void report(WxPayReportRequest request) throws WxPayException { + request.checkAndSign(this.getConfig()); + + String url = this.getPayBaseUrl() + "/payitil/report"; + String responseContent = this.post(url, request.toXML(), false); + WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class); + result.checkResult(this); + } + + @Override + public WxPayBillResult downloadBill(String billDate, String billType, String tarType, String deviceInfo) throws WxPayException { + WxPayDownloadBillRequest request = new WxPayDownloadBillRequest(); + request.setBillType(billType); + request.setBillDate(billDate); + request.setTarType(tarType); + request.setDeviceInfo(deviceInfo); + + request.checkAndSign(this.getConfig()); + + String url = this.getPayBaseUrl() + "/pay/downloadbill"; + String responseContent = this.post(url, request.toXML(), false); + if (responseContent.startsWith("<")) { + WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class); + result.checkResult(this); + return null; + } else { + WxPayBillResult wxPayBillResult = billInformationDeal(responseContent); + return wxPayBillResult; + } + } + + private WxPayBillResult billInformationDeal(String responseContent) { + WxPayBillResult wxPayBillResult = new WxPayBillResult(); + + String listStr = ""; + String objStr = ""; + if (responseContent.contains("总交易单数")) { + listStr = responseContent.substring(0, responseContent.indexOf("总交易单数")); + objStr = responseContent.substring(responseContent.indexOf("总交易单数")); + } + + /* + * 交易时间:2017-04-06 01:00:02 公众账号ID: 商户号: 子商户号:0 设备号:WEB 微信订单号: 商户订单号:2017040519091071873216 用户标识: 交易类型:NATIVE + * 交易状态:REFUND 付款银行:CFT 货币种类:CNY 总金额:0.00 企业红包金额:0.00 微信退款单号: 商户退款单号:20170406010000933 退款金额:0.01 企业红包退款金额:0.00 + * 退款类型:ORIGINAL 退款状态:SUCCESS 商品名称: 商户数据包: 手续费:0.00000 费率 :0.60% + */ + + // 参考以上格式进行取值 + + List wxPayBillBaseResultLst = new LinkedList<>(); + String newStr = listStr.replaceAll(",", " "); // 去空格 + String[] tempStr = newStr.split("`"); // 数据分组 + String[] t = tempStr[0].split(" ");// 分组标题 + int j = tempStr.length / t.length; // 计算循环次数 + int k = 1; // 纪录数组下标 + for (int i = 0; i < j; i++) { + WxPayBillBaseResult wxPayBillBaseResult = new WxPayBillBaseResult(); + + wxPayBillBaseResult.setTradeTime(tempStr[k]); + wxPayBillBaseResult.setAppId(tempStr[k + 1]); + wxPayBillBaseResult.setMchId(tempStr[k + 2]); + wxPayBillBaseResult.setSubMchId(tempStr[k + 3]); + wxPayBillBaseResult.setDeviceInfo(tempStr[k + 4]); + wxPayBillBaseResult.setTransationId(tempStr[k + 5]); + wxPayBillBaseResult.setOutTradeNo(tempStr[k + 6]); + wxPayBillBaseResult.setOpenId(tempStr[k + 7]); + wxPayBillBaseResult.setTradeType(tempStr[k + 8]); + wxPayBillBaseResult.setTradeState(tempStr[k + 9]); + wxPayBillBaseResult.setBankType(tempStr[k + 10]); + wxPayBillBaseResult.setFeeType(tempStr[k + 11]); + wxPayBillBaseResult.setTotalFee(tempStr[k + 12]); + wxPayBillBaseResult.setCouponFee(tempStr[k + 13]); + wxPayBillBaseResult.setRefundId(tempStr[k + 14]); + wxPayBillBaseResult.setOutRefundNo(tempStr[k + 15]); + wxPayBillBaseResult.setSettlementRefundFee(tempStr[k + 16]); + wxPayBillBaseResult.setCouponRefundFee(tempStr[k + 17]); + wxPayBillBaseResult.setRefundChannel(tempStr[k + 18]); + wxPayBillBaseResult.setRefundState(tempStr[k + 19]); + wxPayBillBaseResult.setBody(tempStr[k + 20]); + wxPayBillBaseResult.setAttach(tempStr[k + 21]); + wxPayBillBaseResult.setPoundage(tempStr[k + 22]); + wxPayBillBaseResult.setPoundageRate(tempStr[k + 23]); + wxPayBillBaseResultLst.add(wxPayBillBaseResult); + k += t.length; + } + /* + * 总交易单数,总交易额,总退款金额,总代金券或立减优惠退款金额,手续费总金额 `2,`0.02,`0.0,`0.0,`0 + */ + + // 参考以上格式进行取值 + + String totalStr = objStr.replaceAll(",", " "); + String[] totalTempStr = totalStr.split("`"); + wxPayBillResult.setTotalRecord(totalTempStr[1]); + wxPayBillResult.setTotalFee(totalTempStr[2]); + wxPayBillResult.setTotalRefundFee(totalTempStr[3]); + wxPayBillResult.setTotalCouponFee(totalTempStr[4]); + wxPayBillResult.setTotalPoundageFee(totalTempStr[5]); + + return wxPayBillResult; + } + + @Override + public WxPayMicropayResult micropay(WxPayMicropayRequest request) throws WxPayException { + request.checkAndSign(this.getConfig()); + + String url = this.getPayBaseUrl() + "/pay/micropay"; + String responseContent = this.post(url, request.toXML(), false); + WxPayMicropayResult result = WxPayBaseResult.fromXML(responseContent, WxPayMicropayResult.class); + result.checkResult(this); + return result; + } + + @Override + public WxPayOrderReverseResult reverseOrder(WxPayOrderReverseRequest request) throws WxPayException { + request.checkAndSign(this.getConfig()); + + String url = this.getPayBaseUrl() + "/secapi/pay/reverse"; + String responseContent = this.post(url, request.toXML(), true); + WxPayOrderReverseResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderReverseResult.class); + result.checkResult(this); + return result; + } + + @Override + public String shorturl(WxPayShorturlRequest request) throws WxPayException { + request.checkAndSign(this.getConfig()); + + String url = this.getPayBaseUrl() + "/tools/shorturl"; + String responseContent = this.post(url, request.toXML(), false); + WxPayShorturlResult result = WxPayBaseResult.fromXML(responseContent, WxPayShorturlResult.class); + result.checkResult(this); + return result.getShortUrl(); + } + + @Override + public String shorturl(String longUrl) throws WxPayException { + return this.shorturl(new WxPayShorturlRequest(longUrl)); + } + + @Override + public String authcode2Openid(WxPayAuthcode2OpenidRequest request) throws WxPayException { + request.checkAndSign(this.getConfig()); + + String url = this.getPayBaseUrl() + "/tools/authcodetoopenid"; + String responseContent = this.post(url, request.toXML(), false); + WxPayAuthcode2OpenidResult result = WxPayBaseResult.fromXML(responseContent, WxPayAuthcode2OpenidResult.class); + result.checkResult(this); + return result.getOpenid(); + } + + @Override + public String authcode2Openid(String authCode) throws WxPayException { + return this.authcode2Openid(new WxPayAuthcode2OpenidRequest(authCode)); + } + + @Override + public String getSandboxSignKey() throws WxPayException { + WxPayDefaultRequest request = new WxPayDefaultRequest(); + request.checkAndSign(this.getConfig()); + + String url = "https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey"; + String responseContent = this.post(url, request.toXML(), false); + WxPaySandboxSignKeyResult result = WxPayBaseResult.fromXML(responseContent, WxPaySandboxSignKeyResult.class); + result.checkResult(this); + return result.getSandboxSignKey(); + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java new file mode 100644 index 00000000..c5da982c --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java @@ -0,0 +1,66 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.exception.WxPayException; +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.DefaultHostnameVerifier; +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.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +import javax.net.ssl.SSLContext; +import java.nio.charset.StandardCharsets; + +/** + *
+ * 微信支付请求实现类,apache httpclient实现
+ * Created by Binary Wang on 2016/7/28.
+ * 
+ * + * @author binarywang (https://github.com/binarywang) + */ +public class WxPayServiceApacheHttpImpl extends WxPayServiceAbstractImpl { + + @Override + protected String post(String url, String requestStr, boolean useKey) throws WxPayException { + try { + HttpClientBuilder httpClientBuilder = HttpClients.custom(); + if (useKey) { + SSLContext sslContext = this.getConfig().getSslContext(); + if (null == sslContext) { + sslContext = this.getConfig().initSSLContext(); + } + + SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, + new String[]{"TLSv1"}, null, new DefaultHostnameVerifier()); + httpClientBuilder.setSSLSocketFactory(sslsf); + } + + HttpPost httpPost = new HttpPost(url); + httpPost.setConfig(RequestConfig.custom() + .setConnectionRequestTimeout(this.getConfig().getHttpConnectionTimeout()) + .setConnectTimeout(this.getConfig().getHttpConnectionTimeout()) + .setSocketTimeout(this.getConfig().getHttpTimeout()) + .build()); + + try (CloseableHttpClient httpclient = httpClientBuilder.build()) { + httpPost.setEntity(new StringEntity(new String(requestStr.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1))); + try (CloseableHttpResponse response = httpclient.execute(httpPost)) { + String result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, result); + return result; + } + } finally { + httpPost.releaseConnection(); + } + } catch (Exception e) { + this.log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage()); + throw new WxPayException(e.getMessage(), e); + } + } + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java index f799a2c9..8e795966 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java @@ -1,515 +1,12 @@ package com.github.binarywang.wxpay.service.impl; -import com.github.binarywang.utils.qrcode.QrcodeUtils; -import com.github.binarywang.wxpay.bean.request.*; -import com.github.binarywang.wxpay.bean.result.*; -import com.github.binarywang.wxpay.config.WxPayConfig; -import com.github.binarywang.wxpay.exception.WxPayException; -import com.github.binarywang.wxpay.service.WxPayService; -import com.github.binarywang.wxpay.util.SignUtils; -import com.google.common.collect.Maps; -import jodd.http.HttpRequest; -import jodd.http.HttpResponse; -import jodd.http.net.SSLSocketHttpConnectionProvider; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.SSLContext; -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - /** - * Created by Binary Wang on 2016/7/28. + *
+ * 微信支付接口请求实现类,默认使用Apache HttpClient实现
+ * Created by Binary Wang on 2017-7-8.
+ * 
* - * @author binarywang (https://github.com/binarywang) + * @author Binary Wang */ -public class WxPayServiceImpl implements WxPayService { - private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com"; - private final Logger log = LoggerFactory.getLogger(this.getClass()); - - private WxPayConfig config; - - @Override - public WxPayConfig getConfig() { - return this.config; - } - - @Override - public void setConfig(WxPayConfig config) { - this.config = config; - } - - private String getPayBaseUrl() { - if (this.getConfig().useSandbox()) { - return PAY_BASE_URL + "/sandboxnew"; - } - - return PAY_BASE_URL; - } - - @Override - public WxPayRefundResult refund(WxPayRefundRequest request) throws WxPayException { - request.checkAndSign(this.getConfig()); - - String url = this.getPayBaseUrl() + "/secapi/pay/refund"; - String responseContent = this.post(url, request.toXML(), true); - WxPayRefundResult result = WxPayBaseResult.fromXML(responseContent, WxPayRefundResult.class); - result.checkResult(this); - return result; - } - - @Override - public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId) - throws WxPayException { - WxPayRefundQueryRequest request = new WxPayRefundQueryRequest(); - request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); - request.setTransactionId(StringUtils.trimToNull(transactionId)); - request.setOutRefundNo(StringUtils.trimToNull(outRefundNo)); - request.setRefundId(StringUtils.trimToNull(refundId)); - - request.checkAndSign(this.getConfig()); - - String url = this.getPayBaseUrl() + "/pay/refundquery"; - String responseContent = this.post(url, request.toXML(), false); - WxPayRefundQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayRefundQueryResult.class); - result.composeRefundRecords(); - result.checkResult(this); - return result; - } - - @Override - public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxPayException { - try { - log.debug("微信支付回调参数详细:{}", xmlData); - WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlData); - log.debug("微信支付回调结果对象:{}", result); - result.checkResult(this); - return result; - } catch (WxPayException e) { - log.error(e.getMessage(), e); - throw e; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new WxPayException("发生异常," + e.getMessage(), e); - } - } - - @Override - public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request) throws WxPayException { - request.checkAndSign(this.getConfig()); - - String url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendredpack"; - if (request.getAmtType() != null) { - //裂变红包 - url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendgroupredpack"; - } - - String responseContent = this.post(url, request.toXML(), true); - WxPaySendRedpackResult result = WxPayBaseResult.fromXML(responseContent, WxPaySendRedpackResult.class); - //毋须校验,因为没有返回签名信息 - // this.checkResult(result); - return result; - } - - @Override - public WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxPayException { - WxPayRedpackQueryRequest request = new WxPayRedpackQueryRequest(); - request.setMchBillNo(mchBillNo); - request.setBillType("MCHT"); - request.checkAndSign(this.getConfig()); - - String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gethbinfo"; - String responseContent = this.post(url, request.toXML(), true); - WxPayRedpackQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayRedpackQueryResult.class); - result.checkResult(this); - return result; - } - - @Override - public WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxPayException { - WxPayOrderQueryRequest request = new WxPayOrderQueryRequest(); - request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); - request.setTransactionId(StringUtils.trimToNull(transactionId)); - request.checkAndSign(this.getConfig()); - - String url = this.getPayBaseUrl() + "/pay/orderquery"; - String responseContent = this.post(url, request.toXML(), false); - if (StringUtils.isBlank(responseContent)) { - throw new WxPayException("无响应结果"); - } - - WxPayOrderQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderQueryResult.class); - result.composeCoupons(); - result.checkResult(this); - return result; - } - - @Override - public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxPayException { - if (StringUtils.isBlank(outTradeNo)) { - throw new IllegalArgumentException("out_trade_no不能为空"); - } - - WxPayOrderCloseRequest request = new WxPayOrderCloseRequest(); - request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); - request.checkAndSign(this.getConfig()); - - String url = this.getPayBaseUrl() + "/pay/closeorder"; - String responseContent = this.post(url, request.toXML(), false); - WxPayOrderCloseResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderCloseResult.class); - result.checkResult(this); - - return result; - } - - @Override - public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) throws WxPayException { - request.checkAndSign(this.getConfig()); - - String url = this.getPayBaseUrl() + "/pay/unifiedorder"; - String responseContent = this.post(url, request.toXML(), false); - WxPayUnifiedOrderResult result = WxPayBaseResult.fromXML(responseContent, WxPayUnifiedOrderResult.class); - result.checkResult(this); - return result; - } - - @Override - public Map getPayInfo(WxPayUnifiedOrderRequest request) throws WxPayException { - WxPayUnifiedOrderResult unifiedOrderResult = this.unifiedOrder(request); - String prepayId = unifiedOrderResult.getPrepayId(); - if (StringUtils.isBlank(prepayId)) { - throw new RuntimeException(String.format("无法获取prepay id,错误代码: '%s',信息:%s。", - unifiedOrderResult.getErrCode(), unifiedOrderResult.getErrCodeDes())); - } - - Map payInfo = new HashMap<>(); - if ("NATIVE".equals(request.getTradeType())) { - payInfo.put("codeUrl", unifiedOrderResult.getCodeURL()); - } else if ("APP".equals(request.getTradeType())) { - // APP支付绑定的是微信开放平台上的账号,APPID为开放平台上绑定APP后发放的参数 - String appId = getConfig().getAppId(); - Map configMap = new HashMap<>(); - // 此map用于参与调起sdk支付的二次签名,格式全小写,timestamp只能是10位,格式固定,切勿修改 - String partnerid = getConfig().getMchId(); - configMap.put("prepayid", prepayId); - configMap.put("partnerid", partnerid); - configMap.put("package", "Sign=WXPay"); - configMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000)); - configMap.put("noncestr", String.valueOf(System.currentTimeMillis())); - configMap.put("appid", appId); - // 此map用于客户端与微信服务器交互 - payInfo.put("sign", SignUtils.createSign(configMap, this.getConfig().getMchKey())); - payInfo.put("prepayId", prepayId); - payInfo.put("partnerId", partnerid); - payInfo.put("appId", appId); - payInfo.put("packageValue", "Sign=WXPay"); - payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); - payInfo.put("nonceStr", String.valueOf(System.currentTimeMillis())); - } else if ("JSAPI".equals(request.getTradeType())) { - payInfo.put("appId", unifiedOrderResult.getAppid()); - // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 - payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); - payInfo.put("nonceStr", String.valueOf(System.currentTimeMillis())); - payInfo.put("package", "prepay_id=" + prepayId); - payInfo.put("signType", "MD5"); - payInfo.put("paySign", SignUtils.createSign(payInfo, this.getConfig().getMchKey())); - } - return payInfo; - } - - @Override - public WxEntPayResult entPay(WxEntPayRequest request) throws WxPayException { - request.checkAndSign(this.getConfig()); - String url = this.getPayBaseUrl() + "/mmpaymkttransfers/promotion/transfers"; - - String responseContent = this.post(url, request.toXML(), true); - WxEntPayResult result = WxPayBaseResult.fromXML(responseContent, WxEntPayResult.class); - result.checkResult(this); - return result; - } - - @Override - public WxEntPayQueryResult queryEntPay(String partnerTradeNo) throws WxPayException { - WxEntPayQueryRequest request = new WxEntPayQueryRequest(); - request.setPartnerTradeNo(partnerTradeNo); - request.checkAndSign(this.getConfig()); - - String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gettransferinfo"; - String responseContent = this.post(url, request.toXML(), true); - WxEntPayQueryResult result = WxPayBaseResult.fromXML(responseContent, WxEntPayQueryResult.class); - result.checkResult(this); - return result; - } - - @Override - public byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength) { - String content = this.createScanPayQrcodeMode1(productId); - return this.createQrcode(content, logoFile, sideLength); - } - - @Override - public String createScanPayQrcodeMode1(String productId) { - //weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX - StringBuilder codeUrl = new StringBuilder("weixin://wxpay/bizpayurl?"); - Map params = Maps.newHashMap(); - params.put("appid", this.getConfig().getAppId()); - params.put("mch_id", this.getConfig().getMchId()); - params.put("product_id", productId); - params.put("time_stamp", String.valueOf(System.currentTimeMillis() / 1000));//这里需要秒,10位数字 - params.put("nonce_str", String.valueOf(System.currentTimeMillis())); - - String sign = SignUtils.createSign(params, this.getConfig().getMchKey()); - params.put("sign", sign); - - - for (String key : params.keySet()) { - codeUrl.append(key + "=" + params.get(key) + "&"); - } - - String content = codeUrl.toString().substring(0, codeUrl.length() - 1); - log.debug("扫码支付模式一生成二维码的URL:{}", content); - return content; - } - - @Override - public byte[] createScanPayQrcodeMode2(String codeUrl, File logoFile, Integer sideLength) { - return this.createQrcode(codeUrl, logoFile, sideLength); - } - - private byte[] createQrcode(String content, File logoFile, Integer sideLength) { - if (sideLength == null || sideLength < 1) { - return QrcodeUtils.createQrcode(content, logoFile); - } - - return QrcodeUtils.createQrcode(content, sideLength, logoFile); - } - - public void report(WxPayReportRequest request) throws WxPayException { - request.checkAndSign(this.getConfig()); - - String url = this.getPayBaseUrl() + "/payitil/report"; - String responseContent = this.post(url, request.toXML(), false); - WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class); - result.checkResult(this); - } - - @Override - public WxPayBillResult downloadBill(String billDate, String billType, String tarType, String deviceInfo) throws WxPayException { - WxPayDownloadBillRequest request = new WxPayDownloadBillRequest(); - request.setBillType(billType); - request.setBillDate(billDate); - request.setTarType(tarType); - request.setDeviceInfo(deviceInfo); - - request.checkAndSign(this.getConfig()); - - String url = this.getPayBaseUrl() + "/pay/downloadbill"; - String responseContent = this.post(url, request.toXML(), false); - if (responseContent.startsWith("<")) { - WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class); - result.checkResult(this); - return null; - } else { - WxPayBillResult wxPayBillResult = billInformationDeal(responseContent); - return wxPayBillResult; - } - } - - private WxPayBillResult billInformationDeal(String responseContent) { - WxPayBillResult wxPayBillResult = new WxPayBillResult(); - - String listStr = ""; - String objStr = ""; - if (responseContent.contains("总交易单数")) { - listStr = responseContent.substring(0, responseContent.indexOf("总交易单数")); - objStr = responseContent.substring(responseContent.indexOf("总交易单数")); - } - - /* - * 交易时间:2017-04-06 01:00:02 公众账号ID: 商户号: 子商户号:0 设备号:WEB 微信订单号: 商户订单号:2017040519091071873216 用户标识: 交易类型:NATIVE - * 交易状态:REFUND 付款银行:CFT 货币种类:CNY 总金额:0.00 企业红包金额:0.00 微信退款单号: 商户退款单号:20170406010000933 退款金额:0.01 企业红包退款金额:0.00 - * 退款类型:ORIGINAL 退款状态:SUCCESS 商品名称: 商户数据包: 手续费:0.00000 费率 :0.60% - */ - - // 参考以上格式进行取值 - - List wxPayBillBaseResultLst = new LinkedList<>(); - String newStr = listStr.replaceAll(",", " "); // 去空格 - String[] tempStr = newStr.split("`"); // 数据分组 - String[] t = tempStr[0].split(" ");// 分组标题 - int j = tempStr.length / t.length; // 计算循环次数 - int k = 1; // 纪录数组下标 - for (int i = 0; i < j; i++) { - WxPayBillBaseResult wxPayBillBaseResult = new WxPayBillBaseResult(); - - wxPayBillBaseResult.setTradeTime(tempStr[k]); - wxPayBillBaseResult.setAppId(tempStr[k + 1]); - wxPayBillBaseResult.setMchId(tempStr[k + 2]); - wxPayBillBaseResult.setSubMchId(tempStr[k + 3]); - wxPayBillBaseResult.setDeviceInfo(tempStr[k + 4]); - wxPayBillBaseResult.setTransationId(tempStr[k + 5]); - wxPayBillBaseResult.setOutTradeNo(tempStr[k + 6]); - wxPayBillBaseResult.setOpenId(tempStr[k + 7]); - wxPayBillBaseResult.setTradeType(tempStr[k + 8]); - wxPayBillBaseResult.setTradeState(tempStr[k + 9]); - wxPayBillBaseResult.setBankType(tempStr[k + 10]); - wxPayBillBaseResult.setFeeType(tempStr[k + 11]); - wxPayBillBaseResult.setTotalFee(tempStr[k + 12]); - wxPayBillBaseResult.setCouponFee(tempStr[k + 13]); - wxPayBillBaseResult.setRefundId(tempStr[k + 14]); - wxPayBillBaseResult.setOutRefundNo(tempStr[k + 15]); - wxPayBillBaseResult.setSettlementRefundFee(tempStr[k + 16]); - wxPayBillBaseResult.setCouponRefundFee(tempStr[k + 17]); - wxPayBillBaseResult.setRefundChannel(tempStr[k + 18]); - wxPayBillBaseResult.setRefundState(tempStr[k + 19]); - wxPayBillBaseResult.setBody(tempStr[k + 20]); - wxPayBillBaseResult.setAttach(tempStr[k + 21]); - wxPayBillBaseResult.setPoundage(tempStr[k + 22]); - wxPayBillBaseResult.setPoundageRate(tempStr[k + 23]); - wxPayBillBaseResultLst.add(wxPayBillBaseResult); - k += t.length; - } - /* - * 总交易单数,总交易额,总退款金额,总代金券或立减优惠退款金额,手续费总金额 `2,`0.02,`0.0,`0.0,`0 - */ - - // 参考以上格式进行取值 - - String totalStr = objStr.replaceAll(",", " "); - String[] totalTempStr = totalStr.split("`"); - wxPayBillResult.setTotalRecord(totalTempStr[1]); - wxPayBillResult.setTotalFee(totalTempStr[2]); - wxPayBillResult.setTotalRefundFee(totalTempStr[3]); - wxPayBillResult.setTotalCouponFee(totalTempStr[4]); - wxPayBillResult.setTotalPoundageFee(totalTempStr[5]); - - return wxPayBillResult; - } - - @Override - public WxPayMicropayResult micropay(WxPayMicropayRequest request) throws WxPayException { - request.checkAndSign(this.getConfig()); - - String url = this.getPayBaseUrl() + "/pay/micropay"; - String responseContent = this.post(url, request.toXML(), false); - WxPayMicropayResult result = WxPayBaseResult.fromXML(responseContent, WxPayMicropayResult.class); - result.checkResult(this); - return result; - } - - @Override - public WxPayOrderReverseResult reverseOrder(WxPayOrderReverseRequest request) throws WxPayException { - request.checkAndSign(this.getConfig()); - - String url = this.getPayBaseUrl() + "/secapi/pay/reverse"; - String responseContent = this.post(url, request.toXML(), true); - WxPayOrderReverseResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderReverseResult.class); - result.checkResult(this); - return result; - } - - @Override - public String shorturl(WxPayShorturlRequest request) throws WxPayException { - request.checkAndSign(this.getConfig()); - - String url = this.getPayBaseUrl() + "/tools/shorturl"; - String responseContent = this.post(url, request.toXML(), false); - WxPayShorturlResult result = WxPayBaseResult.fromXML(responseContent, WxPayShorturlResult.class); - result.checkResult(this); - return result.getShortUrl(); - } - - @Override - public String shorturl(String longUrl) throws WxPayException { - return this.shorturl(new WxPayShorturlRequest(longUrl)); - } - - @Override - public String authcode2Openid(WxPayAuthcode2OpenidRequest request) throws WxPayException { - request.checkAndSign(this.getConfig()); - - String url = this.getPayBaseUrl() + "/tools/authcodetoopenid"; - String responseContent = this.post(url, request.toXML(), false); - WxPayAuthcode2OpenidResult result = WxPayBaseResult.fromXML(responseContent, WxPayAuthcode2OpenidResult.class); - result.checkResult(this); - return result.getOpenid(); - } - - @Override - public String authcode2Openid(String authCode) throws WxPayException { - return this.authcode2Openid(new WxPayAuthcode2OpenidRequest(authCode)); - } - - @Override - public String getSandboxSignKey() throws WxPayException { - WxPayDefaultRequest request = new WxPayDefaultRequest(); - request.checkAndSign(this.getConfig()); - - String url = "https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey"; - String responseContent = this.post(url, request.toXML(), false); - WxPaySandboxSignKeyResult result = WxPayBaseResult.fromXML(responseContent, WxPaySandboxSignKeyResult.class); - result.checkResult(this); - return result.getSandboxSignKey(); - } - - /** - * 发送post请求 - * - * @param url 请求地址 - * @param requestStr 请求信息 - * @param useKey 是否使用证书 - * @return 返回请求结果字符串 - */ - private String post(String url, String requestStr, boolean useKey) throws WxPayException { - try { - HttpRequest request = HttpRequest - .post(url) - .timeout(this.config.getHttpTimeout()) - .connectionTimeout(this.config.getHttpConnectionTimeout()) - .bodyText(requestStr); - - if (useKey) { - SSLContext sslContext = this.getConfig().getSslContext(); - if (null == sslContext) { - sslContext = this.getConfig().initSSLContext(); - } - request.withConnectionProvider(new SSLSocketHttpConnectionProvider(sslContext)); - } - - String responseString = this.getResponseString(request.send()); - - this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, responseString); - return responseString; - } catch (Exception e) { - this.log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage()); - throw new WxPayException(e.getMessage(), e); - } - } - - private String getResponseString(HttpResponse response) throws WxPayException { - try { - this.log.debug("【微信服务器响应头信息】:\n{}", response.toString(false)); - } catch (NullPointerException e) { - throw new WxPayException("response.toString() 居然抛出空指针异常了", e); - } - - String responseString = response.bodyText(); - - if (StringUtils.isBlank(responseString)) { - throw new WxPayException("响应信息为空"); - } - - if (StringUtils.isBlank(response.charset())) { - responseString = new String(responseString.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); - } - - return responseString; - } - - +public class WxPayServiceImpl extends WxPayServiceApacheHttpImpl { } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceJoddHttpImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceJoddHttpImpl.java new file mode 100644 index 00000000..29008e26 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceJoddHttpImpl.java @@ -0,0 +1,68 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.exception.WxPayException; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.net.SSLSocketHttpConnectionProvider; +import org.apache.commons.lang3.StringUtils; + +import javax.net.ssl.SSLContext; +import java.nio.charset.StandardCharsets; + +/** + * 微信支付请求实现类,jodd-http实现 + * Created by Binary Wang on 2016/7/28. + * + * @author binarywang (https://github.com/binarywang) + */ +public class WxPayServiceJoddHttpImpl extends WxPayServiceAbstractImpl { + + @Override + protected String post(String url, String requestStr, boolean useKey) throws WxPayException { + try { + HttpRequest request = HttpRequest + .post(url) + .timeout(this.config.getHttpTimeout()) + .connectionTimeout(this.config.getHttpConnectionTimeout()) + .bodyText(requestStr); + + if (useKey) { + SSLContext sslContext = this.getConfig().getSslContext(); + if (null == sslContext) { + sslContext = this.getConfig().initSSLContext(); + } + request.withConnectionProvider(new SSLSocketHttpConnectionProvider(sslContext)); + } + + String responseString = this.getResponseString(request.send()); + + this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, responseString); + return responseString; + } catch (Exception e) { + this.log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage()); + throw new WxPayException(e.getMessage(), e); + } + } + + private String getResponseString(HttpResponse response) throws WxPayException { + try { + this.log.debug("【微信服务器响应头信息】:\n{}", response.toString(false)); + } catch (NullPointerException e) { + throw new WxPayException("response.toString() 居然抛出空指针异常了", e); + } + + String responseString = response.bodyText(); + + if (StringUtils.isBlank(responseString)) { + throw new WxPayException("响应信息为空"); + } + + if (StringUtils.isBlank(response.charset())) { + responseString = new String(responseString.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); + } + + return responseString; + } + + +}