coupons, String nodeName) {
+ Integer index = Integer.valueOf(StringUtils.substring(nodeName, nodeName.lastIndexOf("_") + 1));
+ if (index >= coupons.size() || coupons.get(index) == null) {
+ coupons.add(index, new WxPayOrderNotifyCoupon());
+ }
+ return coupons.get(index);
+ }
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java
similarity index 93%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java
rename to weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java
index 543b59bd..34ba8cdc 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java
@@ -1,23 +1,26 @@
-package me.chanjar.weixin.mp.api;
+package com.github.binarywang.wxpay.service;
+import com.github.binarywang.wxpay.bean.request.*;
+import com.github.binarywang.wxpay.bean.result.*;
+import com.github.binarywang.wxpay.config.WxPayConfig;
import me.chanjar.weixin.common.exception.WxErrorException;
-import me.chanjar.weixin.mp.bean.pay.request.*;
-import me.chanjar.weixin.mp.bean.pay.result.*;
import java.io.File;
import java.util.Map;
/**
+ *
* 微信支付相关接口
* Created by Binary Wang on 2016/7/28.
+ *
*
* @author binarywang (https://github.com/binarywang)
*/
-public interface WxMpPayService {
+public interface WxPayService {
/**
*
- * 查询订单(详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2)
+ * 查询订单(详见https://com.github.binarywang.wechat.pay.bean.pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2)
* 该接口提供所有微信支付订单的查询,商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑。
* 需要调用查询接口的情况:
* ◆ 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;
@@ -49,7 +52,7 @@ public interface WxMpPayService {
WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorException;
/**
- * 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
+ * 统一下单(详见http://com.github.binarywang.wechat.pay.bean.pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
* 接口地址:https://api.mch.weixin.qq.com/pay/unifiedorder
*
@@ -65,6 +68,16 @@ public interface WxMpPayService {
*/
Map getPayInfo(WxPayUnifiedOrderRequest request) throws WxErrorException;
+ /**
+ * 获取配置
+ */
+ WxPayConfig getConfig();
+
+ /**
+ * 设置配置对象
+ */
+ void setConfig(WxPayConfig config);
+
/**
*
* 微信支付-申请退款
@@ -81,7 +94,8 @@ public interface WxMpPayService {
*
* 微信支付-查询退款
* 应用场景:
- * 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
+ * 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,
+ * 银行卡支付的退款3个工作日后重新查询退款状态。
* 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
* 接口链接:https://api.mch.weixin.qq.com/pay/refundquery
*
@@ -93,11 +107,12 @@ public interface WxMpPayService {
* @param refundId 微信退款单号
* @return 退款信息
*/
- WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId) throws WxErrorException;
+ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId)
+ throws WxErrorException;
/**
* 读取支付结果通知
- * 详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
+ * 详见http://com.github.binarywang.wechat.pay.bean.pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
*/
WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java
similarity index 74%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java
rename to weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java
index d8a98544..dea7a7e8 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java
@@ -1,20 +1,21 @@
-package me.chanjar.weixin.mp.api.impl;
+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.service.WxPayService;
import com.google.common.collect.Maps;
+import jodd.http.HttpRequest;
+import jodd.http.HttpResponse;
import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.BeanUtils;
-import me.chanjar.weixin.mp.api.WxMpConfigStorage;
-import me.chanjar.weixin.mp.api.WxMpPayService;
-import me.chanjar.weixin.mp.api.WxMpService;
-import me.chanjar.weixin.mp.bean.pay.request.*;
-import me.chanjar.weixin.mp.bean.pay.result.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
-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;
@@ -28,7 +29,7 @@ import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLContext;
import java.io.File;
-import java.io.IOException;
+import java.io.UnsupportedEncodingException;
import java.util.*;
/**
@@ -36,28 +37,31 @@ import java.util.*;
*
* @author binarywang (https://github.com/binarywang)
*/
-public class WxMpPayServiceImpl implements WxMpPayService {
+public class WxPayServiceImpl implements WxPayService {
private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com";
private static final String[] TRADE_TYPES = new String[]{"JSAPI", "NATIVE", "APP"};
private static final String[] REFUND_ACCOUNT = new String[]{"REFUND_SOURCE_RECHARGE_FUNDS", "REFUND_SOURCE_UNSETTLED_FUNDS"};
- private static final String[] BILL_TYPE = new String[]{"ALL","REFUND","SUCCESS"};;
+ private static final String[] BILL_TYPE = new String[]{"ALL", "REFUND", "SUCCESS"};
+
private final Logger log = LoggerFactory.getLogger(this.getClass());
- private WxMpService wxMpService;
- public WxMpPayServiceImpl(WxMpService wxMpService) {
- this.wxMpService = wxMpService;
+ private WxPayConfig config;
+
+ @Override
+ public WxPayConfig getConfig() {
+ return this.config;
}
- private WxMpConfigStorage getConfig() {
- return wxMpService.getWxMpConfigStorage();
+ @Override
+ public void setConfig(WxPayConfig config) {
+ this.config = config;
}
- private String getPayBaseUrl(){
- if(this.getConfig().useSandboxForWxPay()){
+ private String getPayBaseUrl() {
+ if (this.getConfig().useSandboxForWxPay()) {
return PAY_BASE_URL + "/sandboxnew";
}
-
return PAY_BASE_URL;
}
@@ -65,22 +69,27 @@ public class WxMpPayServiceImpl implements WxMpPayService {
public WxPayRefundResult refund(WxPayRefundRequest request) throws WxErrorException {
this.initRequest(request);
if (StringUtils.isBlank(request.getOpUserId())) {
- request.setOpUserId(this.getConfig().getPartnerId());
+ request.setOpUserId(this.getConfig().getMchId());
}
+
this.checkParameters(request);
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/secapi/pay/refund";
- String responseContent = this.executeWithKey(url, request.toXML());
+ String responseContent = this.postWithKey(url, request.toXML());
WxPayRefundResult result = WxPayRefundResult.fromXML(responseContent, WxPayRefundResult.class);
this.checkResult(result);
return result;
}
@Override
- public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId) throws WxErrorException {
- if ((StringUtils.isBlank(transactionId) && StringUtils.isBlank(outTradeNo) && StringUtils.isBlank(outRefundNo) && StringUtils.isBlank(refundId)) ||
- (StringUtils.isNotBlank(transactionId) && StringUtils.isNotBlank(outTradeNo) && StringUtils.isNotBlank(outRefundNo) && StringUtils.isNotBlank(refundId))) {
+ public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo,
+ String outRefundNo, String refundId)
+ throws WxErrorException {
+ if ((StringUtils.isBlank(transactionId) && StringUtils.isBlank(outTradeNo)
+ && StringUtils.isBlank(outRefundNo) && StringUtils.isBlank(refundId)) ||
+ (StringUtils.isNotBlank(transactionId) && StringUtils.isNotBlank(outTradeNo)
+ && StringUtils.isNotBlank(outRefundNo) && StringUtils.isNotBlank(refundId))) {
throw new IllegalArgumentException("transaction_id , out_trade_no,out_refund_no, refund_id 必须四选一");
}
@@ -93,18 +102,17 @@ public class WxMpPayServiceImpl implements WxMpPayService {
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/pay/refundquery";
- String responseContent = this.executeRequest(url, request.toXML());
+ String responseContent = this.post(url, request.toXML());
WxPayRefundQueryResult result = WxPayRefundQueryResult.fromXML(responseContent, WxPayRefundQueryResult.class);
result.composeRefundRecords();
this.checkResult(result);
return result;
}
-
private void checkResult(WxPayBaseResult result) throws WxErrorException {
//校验返回结果签名
Map map = result.toMap();
- if (result.getSign() != null &&!this.checkSign(map)) {
+ if (result.getSign() != null && !this.checkSign(map)) {
log.debug("校验结果签名失败,参数:{}", map);
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("参数格式校验错误!").build());
}
@@ -112,12 +120,28 @@ public class WxMpPayServiceImpl implements WxMpPayService {
//校验结果是否成功
if (!"SUCCESS".equalsIgnoreCase(result.getReturnCode())
|| !"SUCCESS".equalsIgnoreCase(result.getResultCode())) {
- WxError error = WxError.newBuilder().setErrorCode(-1)
- .setErrorMsg("返回代码: " + result.getReturnCode() + ", 返回信息: "
- + result.getReturnMsg() + ", 结果代码: " + result.getResultCode() + ", 错误代码: "
- + result.getErrCode() + ", 错误详情: " + result.getErrCodeDes())
+ StringBuilder errorMsg = new StringBuilder();
+ if (result.getReturnCode() != null) {
+ errorMsg.append("返回代码:" + result.getReturnCode());
+ }
+ if (result.getReturnMsg() != null) {
+ errorMsg.append(",返回信息:" + result.getReturnMsg());
+ }
+ if (result.getResultCode() != null) {
+ errorMsg.append(",结果代码:" + result.getResultCode());
+ }
+ if (result.getErrCode() != null) {
+ errorMsg.append(",错误代码:" + result.getErrCode());
+ }
+ if (result.getErrCodeDes() != null) {
+ errorMsg.append(",错误详情:" + result.getErrCodeDes());
+ }
+
+ WxError error = WxError.newBuilder()
+ .setErrorCode(-1)
+ .setErrorMsg(errorMsg.toString())
.build();
- log.error("结果业务代码异常,参数:{},详细:{}", map, error);
+ log.error("\n结果业务代码异常,返回結果:{},\n{}", map, error);
throw new WxErrorException(error);
}
}
@@ -129,8 +153,9 @@ public class WxMpPayServiceImpl implements WxMpPayService {
throw new IllegalArgumentException("tar_type值如果存在,只能为GZIP");
}
- if ( !ArrayUtils.contains(BILL_TYPE, request.getBillType())) {
- throw new IllegalArgumentException("bill_tpye目前必须为" + Arrays.toString(BILL_TYPE) + "其中之一,实际值:" + request.getBillType());
+ if (!ArrayUtils.contains(BILL_TYPE, request.getBillType())) {
+ throw new IllegalArgumentException("bill_tpye目前必须为" + Arrays.toString(BILL_TYPE)
+ + "其中之一,实际值:" + request.getBillType());
}
}
@@ -140,7 +165,8 @@ public class WxMpPayServiceImpl implements WxMpPayService {
if (StringUtils.isNotBlank(request.getRefundAccount())) {
if (!ArrayUtils.contains(REFUND_ACCOUNT, request.getRefundAccount())) {
- throw new IllegalArgumentException("refund_account目前必须为" + Arrays.toString(REFUND_ACCOUNT) + "其中之一,实际值:" + request.getRefundAccount());
+ throw new IllegalArgumentException("refund_account目前必须为" + Arrays.toString(REFUND_ACCOUNT)
+ + "其中之一,实际值:" + request.getRefundAccount());
}
}
@@ -152,7 +178,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override
public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException {
try {
- log.trace("微信支付回调参数详细:{}", xmlData);
+ log.debug("微信支付回调参数详细:{}", xmlData);
WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlData);
log.debug("微信支付回调结果对象:{}", result);
this.checkResult(result);
@@ -177,7 +203,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
//裂变红包
url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendgroupredpack";
}
- String responseContent = this.executeWithKey(url, request.toXML());
+ String responseContent = this.postWithKey(url, request.toXML());
WxPaySendRedpackResult result = WxPaySendRedpackResult.fromXML(responseContent, WxPaySendRedpackResult.class);
//毋须校验,因为没有返回签名信息
// this.checkResult(result);
@@ -193,7 +219,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gethbinfo";
- String responseContent = this.executeWithKey(url, request.toXML());
+ String responseContent = this.postWithKey(url, request.toXML());
WxPayRedpackQueryResult result = WxPayRedpackQueryResult.fromXML(responseContent, WxPayRedpackQueryResult.class);
this.checkResult(result);
return result;
@@ -213,7 +239,11 @@ public class WxMpPayServiceImpl implements WxMpPayService {
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/pay/orderquery";
- String responseContent = this.executeRequest(url, request.toXML());
+ String responseContent = this.post(url, request.toXML());
+ if (StringUtils.isBlank(responseContent)) {
+ throw new WxErrorException(WxError.newBuilder().setErrorMsg("无响应结果").build());
+ }
+
WxPayOrderQueryResult result = WxPayOrderQueryResult.fromXML(responseContent, WxPayOrderQueryResult.class);
result.composeCoupons();
this.checkResult(result);
@@ -223,17 +253,17 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override
public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorException {
if (StringUtils.isBlank(outTradeNo)) {
- throw new IllegalArgumentException("out_trade_no 不能为空");
+ throw new IllegalArgumentException("out_trade_no不能为空");
}
WxPayOrderCloseRequest request = new WxPayOrderCloseRequest();
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
- initRequest(request);
+ this.initRequest(request);
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/pay/closeorder";
- String responseContent = this.executeRequest(url, request.toXML());
- WxPayOrderCloseResult result = WxPayOrderCloseResult.fromXML(responseContent, WxPayOrderCloseResult.class);
+ String responseContent = this.post(url, request.toXML());
+ WxPayOrderCloseResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderCloseResult.class);
this.checkResult(result);
return result;
@@ -242,23 +272,20 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override
public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request)
throws WxErrorException {
-
this.initRequest(request);
if (StringUtils.isBlank(request.getNotifyURL())) {
- request.setNotifyURL(getConfig().getNotifyURL());
+ request.setNotifyURL(getConfig().getNotifyUrl());
}
+
if (StringUtils.isBlank(request.getTradeType())) {
request.setTradeType(getConfig().getTradeType());
}
- checkParameters(request);//校验参数
+
+ this.checkParameters(request);//校验参数
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/pay/unifiedorder";
- String xmlParam = request.toXML();
- log.debug("微信统一下单接口,URL:{},参数:{}", url, xmlParam);
-
- String responseContent = this.executeRequest(url, xmlParam);
- log.debug("微信统一下单接口,URL:{},结果:{}", url, responseContent);
+ String responseContent = this.post(url, request.toXML());
WxPayUnifiedOrderResult result = WxPayUnifiedOrderResult.fromXML(responseContent, WxPayUnifiedOrderResult.class);
this.checkResult(result);
return result;
@@ -266,19 +293,19 @@ public class WxMpPayServiceImpl implements WxMpPayService {
private void initRequest(WxPayBaseRequest request) {
if (StringUtils.isBlank(request.getAppid())) {
- request.setAppid(getConfig().getAppId());
+ request.setAppid(this.getConfig().getAppId());
}
if (StringUtils.isBlank(request.getMchId())) {
- request.setMchId(getConfig().getPartnerId());
+ request.setMchId(this.getConfig().getMchId());
}
if (StringUtils.isBlank(request.getSubAppId())) {
- request.setAppid(getConfig().getSubAppId());
+ request.setSubAppId(this.getConfig().getSubAppId());
}
if (StringUtils.isBlank(request.getSubMchId())) {
- request.setMchId(getConfig().getSubMchId());
+ request.setSubMchId(this.getConfig().getSubMchId());
}
if (StringUtils.isBlank(request.getNonceStr())) {
@@ -307,13 +334,14 @@ public class WxMpPayServiceImpl implements WxMpPayService {
WxPayUnifiedOrderResult unifiedOrderResult = this.unifiedOrder(request);
String prepayId = unifiedOrderResult.getPrepayId();
if (StringUtils.isBlank(prepayId)) {
- throw new RuntimeException(String.format("Failed to get prepay id due to error code '%s'(%s).",
+ throw new RuntimeException(String.format("无法获取prepay id,错误代码: '%s',信息:%s。",
unifiedOrderResult.getErrCode(), unifiedOrderResult.getErrCodeDes()));
}
Map payInfo = new HashMap<>();
payInfo.put("appId", getConfig().getAppId());
- // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
+ // 支付签名时间戳,注意微信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);
@@ -333,7 +361,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/promotion/transfers";
- String responseContent = this.executeWithKey(url, request.toXML());
+ String responseContent = this.postWithKey(url, request.toXML());
WxEntPayResult result = WxEntPayResult.fromXML(responseContent, WxEntPayResult.class);
this.checkResult(result);
return result;
@@ -346,7 +374,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gettransferinfo";
- String responseContent = this.executeWithKey(url, request.toXML());
+ String responseContent = this.postWithKey(url, request.toXML());
WxEntPayQueryResult result = WxEntPayQueryResult.fromXML(responseContent, WxEntPayQueryResult.class);
this.checkResult(result);
return result;
@@ -358,7 +386,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
StringBuilder codeUrl = new StringBuilder("weixin://wxpay/bizpayurl?");
Map params = Maps.newHashMap();
params.put("appid", this.getConfig().getAppId());
- params.put("mch_id", this.getConfig().getPartnerId());
+ params.put("mch_id", this.getConfig().getMchId());
params.put("product_id", productId);
params.put("time_stamp", String.valueOf(System.currentTimeMillis()));
params.put("nonce_str", String.valueOf(System.currentTimeMillis()));
@@ -393,7 +421,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/payitil/report";
- String responseContent = this.wxMpService.post(url, request.toXML());
+ String responseContent = this.post(url, request.toXML());
WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class);
this.checkResult(result);
}
@@ -411,7 +439,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
String url = this.getPayBaseUrl() + "/pay/downloadbill";
//TODO 返回的内容可能是文件流,也有可能是xml,需要区分对待
- String responseContent = this.wxMpService.post(url, request.toXML());
+ String responseContent = this.post(url, request.toXML());
WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class);
this.checkResult(result);
@@ -419,42 +447,41 @@ public class WxMpPayServiceImpl implements WxMpPayService {
return null;
}
- private String executeRequest(String url, String requestStr) throws WxErrorException {
- HttpPost httpPost = new HttpPost(url);
- if (this.wxMpService.getHttpProxy() != null) {
- httpPost.setConfig(RequestConfig.custom().setProxy(this.wxMpService.getHttpProxy()).build());
+ private String post(String url, String xmlParam) {
+ String requestString = null;
+ try {
+ requestString = new String(xmlParam.getBytes(CharEncoding.UTF_8), CharEncoding.ISO_8859_1);
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
}
- try (CloseableHttpClient httpclient = HttpClients.custom().build()) {
- httpPost.setEntity(new StringEntity(new String(requestStr.getBytes("UTF-8"), "ISO-8859-1")));
-
- try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
- String result = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
- this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", url, requestStr, result);
- return result;
- }
- } catch (IOException e) {
- this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", url, requestStr, e.getMessage());
- throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg(e.getMessage()).build(), e);
- } finally {
- httpPost.releaseConnection();
+ HttpRequest request = HttpRequest.post(url).body(requestString);
+ HttpResponse response = request.send();
+ String responseString = null;
+ try {
+ responseString = new String(response.bodyText().getBytes(CharEncoding.ISO_8859_1), CharEncoding.UTF_8);
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
}
+
+ this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", url, xmlParam, responseString);
+ return responseString;
}
- private String executeWithKey(String url, String requestStr) throws WxErrorException {
+ /**
+ * 由于暂时未找到使用jodd-http实现证书配置的办法,故而暂时使用httpclient
+ */
+ private String postWithKey(String url, String requestStr) throws WxErrorException {
try {
- SSLContext sslContext = getConfig().getSslContext();
+ SSLContext sslContext = this.getConfig().getSslContext();
if (null == sslContext) {
- throw new IllegalArgumentException("请先初始化配置类(即WxMpConfigStorage的实现类)中的SSLContext!");
+ sslContext = this.getConfig().initSSLContext();
}
- SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1"}, null,
- new DefaultHostnameVerifier());
+ SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,
+ new String[]{"TLSv1"}, null, new DefaultHostnameVerifier());
HttpPost httpPost = new HttpPost(url);
- if (this.wxMpService.getHttpProxy() != null) {
- httpPost.setConfig(RequestConfig.custom().setProxy(this.wxMpService.getHttpProxy()).build());
- }
try (CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build()) {
httpPost.setEntity(new StringEntity(new String(requestStr.getBytes("UTF-8"), "ISO-8859-1")));
@@ -474,7 +501,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override
public String createSign(Object xmlBean) {
- return this.createSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey());
+ return this.createSign(BeanUtils.xmlBean2Map(xmlBean), this.getConfig().getMchKey());
}
@Override
@@ -484,14 +511,14 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override
public String createSign(Map params) {
- return this.createSign(params, this.getConfig().getPartnerKey());
+ return this.createSign(params, this.getConfig().getMchKey());
}
@Override
public String createSign(Map params, String signKey) {
- if(this.getConfig().useSandboxForWxPay()){
+ if (this.getConfig().useSandboxForWxPay()) {
//使用仿真测试环境
- //TODO 目前测试发现,以下两行代码都会出问题,所以暂不建议使用这个仿真测试环境
+ //TODO 目前测试发现,以下两行代码都会出问题,所以暂不建议使用仿真测试环境
signKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456";
//return "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456";
}
@@ -512,7 +539,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override
public boolean checkSign(Object xmlBean) {
- return this.checkSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey());
+ return this.checkSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getMchKey());
}
@Override
@@ -522,7 +549,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override
public boolean checkSign(Map params) {
- return this.checkSign(params, getConfig().getPartnerKey());
+ return this.checkSign(params, getConfig().getMchKey());
}
@Override
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResultTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResultTest.java
similarity index 94%
rename from weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResultTest.java
rename to weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResultTest.java
index aaab37a2..c99f4115 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResultTest.java
+++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResultTest.java
@@ -1,5 +1,6 @@
-package me.chanjar.weixin.mp.bean.pay.result;
+package com.github.binarywang.wxpay.bean.result;
+import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import org.testng.*;
import org.testng.annotations.*;
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderQueryResultTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayOrderQueryResultTest.java
similarity index 98%
rename from weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderQueryResultTest.java
rename to weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayOrderQueryResultTest.java
index e0fd9808..d847a155 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderQueryResultTest.java
+++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayOrderQueryResultTest.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean.pay.result;
+package com.github.binarywang.wxpay.bean.result;
import org.testng.*;
import org.testng.annotations.*;
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRefundQueryResultTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayRefundQueryResultTest.java
similarity index 97%
rename from weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRefundQueryResultTest.java
rename to weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayRefundQueryResultTest.java
index 6b8a9ae9..6ca4192a 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRefundQueryResultTest.java
+++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayRefundQueryResultTest.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean.pay.result;
+package com.github.binarywang.wxpay.bean.result;
import org.testng.*;
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPaySendRedpackResultTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPaySendRedpackResultTest.java
similarity index 98%
rename from weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPaySendRedpackResultTest.java
rename to weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPaySendRedpackResultTest.java
index f2aa0a94..1985c924 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPaySendRedpackResultTest.java
+++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPaySendRedpackResultTest.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean.pay.result;
+package com.github.binarywang.wxpay.bean.result;
import com.thoughtworks.xstream.XStream;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/WxMpPayServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/WxMpPayServiceImplTest.java
new file mode 100644
index 00000000..820101c5
--- /dev/null
+++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/WxMpPayServiceImplTest.java
@@ -0,0 +1,196 @@
+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.service.WxPayService;
+import com.github.binarywang.wxpay.testbase.ApiTestModule;
+import com.github.binarywang.wxpay.testbase.TestPayConfig;
+import com.google.inject.Inject;
+import me.chanjar.weixin.common.exception.WxErrorException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.*;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import static org.testng.Assert.*;
+
+/**
+ * 测试支付相关接口
+ * Created by Binary Wang on 2016/7/28.
+ *
+ * @author binarywang (https://github.com/binarywang)
+ */
+@Test
+@Guice(modules = ApiTestModule.class)
+public class WxMpPayServiceImplTest {
+ private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ @Inject
+ protected WxPayService wxService;
+
+ @Test
+ public void testGetPayInfo() throws Exception {
+
+ }
+
+ @Test
+ public void testDownloadBill() throws Exception {
+ File file = this.wxService.downloadBill("20170101", "ALL", "GZIP", "1111111");
+ assertNotNull(file);
+ //必填字段为空时,抛出异常
+ this.wxService.downloadBill("", "", "", null);
+ }
+
+ @Test
+ public void testReport() throws Exception {
+ WxPayReportRequest request = new WxPayReportRequest();
+ request.setInterfaceUrl("hahahah");
+ request.setSignType("HMAC-SHA256");//貌似接口未校验此字段
+ request.setExecuteTime(1000);
+ request.setReturnCode("aaa");
+ request.setResultCode("aaa");
+ request.setUserIp("8.8.8");
+ this.wxService.report(request);
+ }
+
+ /**
+ * Test method for {@link WxPayService#refund(WxPayRefundRequest)} .
+ */
+ @Test//(dependsOnMethods = {"setSSLKey"})
+ public void testRefund() throws Exception {
+ WxPayRefundResult result = this.wxService.refund(
+ WxPayRefundRequest.newBuilder()
+ .outRefundNo("aaa")
+ .outTradeNo("1111")
+ .totalFee(1222)
+ .refundFee(111)
+ .build());
+ this.logger.info(result.toString());
+ }
+
+ /**
+ * Test method for {@link WxPayService#refundQuery(java.lang.String, java.lang.String, java.lang.String, java.lang.String)} .
+ */
+ @Test
+ public void testRefundQuery() throws Exception {
+ WxPayRefundQueryResult result;
+
+ result = this.wxService.refundQuery("1", "", "", "");
+ this.logger.info(result.toString());
+
+ result = this.wxService.refundQuery("", "2", "", "");
+ this.logger.info(result.toString());
+
+ result = this.wxService.refundQuery("", "", "3", "");
+ this.logger.info(result.toString());
+
+ result = this.wxService.refundQuery("", "", "", "4");
+ this.logger.info(result.toString());
+
+ //测试四个参数都填的情况,应该报异常的
+ result = this.wxService.refundQuery("1", "2", "3", "4");
+ this.logger.info(result.toString());
+ }
+
+ /**
+ * Test method for {@link WxPayService#sendRedpack(WxPaySendRedpackRequest)} .
+ */
+ @Test//(dependsOnMethods = {"setSSLKey"})
+ public void testSendRedpack() throws Exception {
+ WxPaySendRedpackRequest request = new WxPaySendRedpackRequest();
+ request.setActName("abc");
+ request.setClientIp("aaa");
+ request.setMchBillNo("aaaa");
+ request.setReOpenid(((TestPayConfig) this.wxService.getConfig()).getOpenid());
+ WxPaySendRedpackResult redpackResult = this.wxService.sendRedpack(request);
+ this.logger.info(redpackResult.toString());
+ }
+
+ /**
+ * Test method for {@link WxPayService#queryRedpack(java.lang.String)}.
+ */
+ @Test//(dependsOnMethods = {"setSSLKey"})
+ public void testQueryRedpack() throws Exception {
+ WxPayRedpackQueryResult redpackResult = this.wxService.queryRedpack("aaaa");
+ this.logger.info(redpackResult.toString());
+ }
+
+ /**
+ * Test method for {@link WxPayService#unifiedOrder(WxPayUnifiedOrderRequest)}.
+ */
+ @Test
+ public void testUnifiedOrder() throws WxErrorException {
+ WxPayUnifiedOrderResult result = this.wxService
+ .unifiedOrder(WxPayUnifiedOrderRequest.builder()
+ .body("我去")
+ .totalFee(1)
+ .spbillCreateIp("111111")
+ .notifyURL("111111")
+ .tradeType("JSAPI")
+ .openid("122")
+ .outTradeNo("111111")
+ .build());
+ this.logger.info(result.toString());
+ }
+
+ /**
+ * Test method for {@link WxPayService#queryOrder(java.lang.String, java.lang.String)} .
+ */
+ @Test
+ public void testQueryOrder() throws WxErrorException {
+ this.logger.info(this.wxService.queryOrder("11212121", null).toString());
+ this.logger.info(this.wxService.queryOrder(null, "11111").toString());
+ }
+
+ /**
+ * Test method for {@link WxPayService#closeOrder(java.lang.String)} .
+ */
+ @Test
+ public void testCloseOrder() throws WxErrorException {
+ this.logger.info(this.wxService.closeOrder("11212121").toString());
+ }
+
+ /**
+ * Test method for {@link WxPayService#entPay(WxEntPayRequest)}.
+ */
+ @Test//(dependsOnMethods = {"setSSLKey"})
+ public void testEntPay() throws WxErrorException {
+ WxEntPayRequest request = new WxEntPayRequest();
+ this.logger.info(this.wxService.entPay(request).toString());
+ }
+
+ /**
+ * Test method for {@link WxPayService#queryEntPay(java.lang.String)}.
+ */
+ @Test//(dependsOnMethods = {"setSSLKey"})
+ public void testQueryEntPay() throws WxErrorException {
+ this.logger.info(this.wxService.queryEntPay("11212121").toString());
+ }
+
+ @Test
+ public void testCreateScanPayQrcodeMode1() throws Exception {
+ String productId = "abc";
+ byte[] bytes = this.wxService.createScanPayQrcodeMode1(productId, null, null);
+ Path qrcodeFilePath = Files.createTempFile("qrcode_", ".jpg");
+ Files.write(qrcodeFilePath, bytes);
+ String qrcodeContent = QrcodeUtils.decodeQrcode(qrcodeFilePath.toFile());
+ this.logger.info(qrcodeContent);
+
+ assertTrue(qrcodeContent.startsWith("weixin://wxpay/bizpayurl?"));
+ assertTrue(qrcodeContent.contains("product_id=" + productId));
+ }
+
+ @Test
+ public void testCreateScanPayQrcodeMode2() throws Exception {
+ String qrcodeContent = "abc";
+ byte[] bytes = this.wxService.createScanPayQrcodeMode2(qrcodeContent, null, null);
+ Path qrcodeFilePath = Files.createTempFile("qrcode_", ".jpg");
+ Files.write(qrcodeFilePath, bytes);
+ assertEquals(QrcodeUtils.decodeQrcode(qrcodeFilePath.toFile()), qrcodeContent);
+ }
+
+}
diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/testbase/ApiTestModule.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/testbase/ApiTestModule.java
new file mode 100644
index 00000000..0ca02bb6
--- /dev/null
+++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/testbase/ApiTestModule.java
@@ -0,0 +1,38 @@
+package com.github.binarywang.wxpay.testbase;
+
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
+import com.google.inject.Binder;
+import com.google.inject.Module;
+import com.thoughtworks.xstream.XStream;
+import me.chanjar.weixin.common.util.xml.XStreamInitializer;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ApiTestModule implements Module {
+
+ @Override
+ public void configure(Binder binder) {
+ try (InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml")) {
+ TestPayConfig config = this.fromXml(TestPayConfig.class, is1);
+ WxPayService wxService = new WxPayServiceImpl();
+ wxService.setConfig(config);
+
+ binder.bind(WxPayService.class).toInstance(wxService);
+ binder.bind(WxPayConfig.class).toInstance(config);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private T fromXml(Class clazz, InputStream is) {
+ XStream xstream = XStreamInitializer.getInstance();
+ xstream.alias("xml", clazz);
+ xstream.processAnnotations(clazz);
+ return (T) xstream.fromXML(is);
+ }
+
+}
diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/testbase/XmlWxPayConfig.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/testbase/XmlWxPayConfig.java
new file mode 100644
index 00000000..227c365d
--- /dev/null
+++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/testbase/XmlWxPayConfig.java
@@ -0,0 +1,31 @@
+package com.github.binarywang.wxpay.testbase;
+
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.http.ssl.SSLContexts;
+
+import javax.net.ssl.SSLContext;
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+
+@XStreamAlias("xml")
+public class TestPayConfig extends WxPayConfig {
+ private String openid;
+
+ public String getOpenid() {
+ return openid;
+ }
+
+ public void setOpenid(String openid) {
+ this.openid = openid;
+ }
+
+ @Override
+ public boolean useSandboxForWxPay() {
+ //沙箱环境不成熟,有问题无法使用,暂时屏蔽掉
+ // return true;
+ return false;
+ }
+}
diff --git a/weixin-java-pay/src/test/resources/logback-test.xml b/weixin-java-pay/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..75de28c0
--- /dev/null
+++ b/weixin-java-pay/src/test/resources/logback-test.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
diff --git a/weixin-java-pay/src/test/resources/test-config.sample.xml b/weixin-java-pay/src/test/resources/test-config.sample.xml
new file mode 100644
index 00000000..1e64cbe4
--- /dev/null
+++ b/weixin-java-pay/src/test/resources/test-config.sample.xml
@@ -0,0 +1,13 @@
+
+ 公众号appid
+ 微信商户平台ID
+ 商户平台设置的API密钥
+
+ 商户平台的证书文件地址
+ 某个openId
+