From 64619c21926473547075f2253fcc5c743ec97bae Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Mon, 5 Dec 2016 17:47:25 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=EF=BC=8C=E6=98=8E=E7=A1=AE=E8=AF=81=E4=B9=A6=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E7=9A=84=E5=90=AB=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/me/chanjar/weixin/mp/api/WxMpPayService.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java index e1396afb..5f1f373b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java @@ -81,7 +81,7 @@ public interface WxMpPayService { * * * @param request 请求对象 - * @param keyFile 证书文件对象 + * @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3) * @return 退款操作结果 */ WxPayRefundResult refund(WxPayRefundRequest request, File keyFile) throws WxErrorException; @@ -128,7 +128,7 @@ public interface WxMpPayService { * * * @param request 请求对象 - * @param keyFile 证书文件对象 + * @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3) */ WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File keyFile) throws WxErrorException; @@ -141,7 +141,7 @@ public interface WxMpPayService { * 请求方式 POST * * @param mchBillNo 商户发放红包的商户订单号,比如10000098201411111234567890 - * @param keyFile 证书文件对象 + * @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3) */ WxPayRedpackQueryResult queryRedpack(String mchBillNo, File keyFile) throws WxErrorException; @@ -156,7 +156,7 @@ public interface WxMpPayService { * * * @param request 请求对象 - * @param keyFile 证书文件对象 + * @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3) */ WxEntPayResult entPay(WxEntPayRequest request, File keyFile) throws WxErrorException; @@ -169,7 +169,7 @@ public interface WxMpPayService { * * * @param partnerTradeNo 商户订单号 - * @param keyFile 证书文件对象 + * @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3) */ WxEntPayQueryResult queryEntPay(String partnerTradeNo, File keyFile) throws WxErrorException; From 41da9e15a648996af3d9e0272f83c69b5485f9a1 Mon Sep 17 00:00:00 2001 From: aimilin Date: Thu, 8 Dec 2016 20:44:03 +0800 Subject: [PATCH 2/9] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E6=94=AF=E4=BB=98=E5=9B=9E=E6=8E=89=E5=8A=9F=E8=83=BD=E5=AE=8C?= =?UTF-8?q?=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weixin/mp/api/WxMpConfigStorage.java | 19 + .../mp/api/WxMpInMemoryConfigStorage.java | 21 +- .../chanjar/weixin/mp/api/WxMpPayService.java | 80 +++- .../mp/api/impl/WxMpMenuServiceImpl.java | 1 - .../mp/api/impl/WxMpPayServiceImpl.java | 246 +++++++---- .../mp/bean/message/WxMpXmlOutMessage.java | 3 +- .../mp/bean/pay/WxPayJsSDKCallback.java | 267 ----------- .../mp/bean/pay/WxPayOrderNotifyCoupon.java | 59 +++ .../mp/bean/pay/WxPayOrderNotifyResponse.java | 61 +++ .../pay/WxPayOrderNotifyResultConverter.java | 130 ++++++ .../pay/request/WxEntPayQueryRequest.java | 1 - .../mp/bean/pay/request/WxPayBaseRequest.java | 12 + .../pay/request/WxPayUnifiedOrderRequest.java | 8 + .../mp/bean/pay/result/WxPayBaseResult.java | 8 + .../pay/result/WxPayOrderNotifyResult.java | 414 ++++++++++++++++++ .../weixin/mp/builder/kefu/BaseBuilder.java | 3 +- .../weixin/mp/builder/outxml/BaseBuilder.java | 6 +- ...lVoiceAndImageDownloadRequestExecutor.java | 2 - 18 files changed, 962 insertions(+), 379 deletions(-) delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayJsSDKCallback.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyCoupon.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResponse.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResultConverter.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java index 78b1a587..d93c3080 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java @@ -4,6 +4,7 @@ import me.chanjar.weixin.common.bean.WxAccessToken; import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; import javax.net.ssl.SSLContext; + import java.io.File; import java.util.concurrent.locks.Lock; @@ -81,6 +82,23 @@ public interface WxMpConfigStorage { String getPartnerId(); String getPartnerKey(); + + /** + * 微信支付异步回掉地址,通知url必须为直接可访问的url,不能携带参数。 + * @since 2.5.0 + * @return + */ + String getNotifyURL(); + + /** + * 交易类型 + *
+   * JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付
+   * 
+ * @since 2.5.0 + * @return + */ + String getTradeType(); String getToken(); @@ -112,4 +130,5 @@ public interface WxMpConfigStorage { * 是否自动刷新token */ boolean autoRefreshToken(); + } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java index e874e793..61b75fbb 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java @@ -20,6 +20,8 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { protected volatile String secret; protected volatile String partnerId; protected volatile String partnerKey; + protected volatile String notifyURL; + protected volatile String tradeType; protected volatile String token; protected volatile String accessToken; protected volatile String aesKey; @@ -267,8 +269,25 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { public void setPartnerKey(String partnerKey) { this.partnerKey = partnerKey; } + + + public String getNotifyURL() { + return notifyURL; + } - @Override + public void setNotifyURL(String notifyURL) { + this.notifyURL = notifyURL; + } + + public String getTradeType() { + return tradeType; + } + + public void setTradeType(String tradeType) { + this.tradeType = tradeType; + } + + @Override public File getTmpDirFile() { return this.tmpDirFile; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java index 5f1f373b..024ce4a8 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java @@ -1,7 +1,6 @@ package me.chanjar.weixin.mp.api; import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.mp.bean.pay.WxPayJsSDKCallback; import me.chanjar.weixin.mp.bean.pay.request.WxEntPayRequest; import me.chanjar.weixin.mp.bean.pay.request.WxPayRefundRequest; import me.chanjar.weixin.mp.bean.pay.request.WxPaySendRedpackRequest; @@ -107,15 +106,82 @@ public interface WxMpPayService { * 读取支付结果通知 * 详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7 */ - WxPayJsSDKCallback getJSSDKCallbackData(String xmlData) throws WxErrorException; + WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException; + + /** + * 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3) + * + * @param xmlbean Bean需要标记有XML注解,默认使用配置中的PartnerKey进行签名 + * @since 2.5.0 + * @return 签名字符串 + * @see #createSign(Map, String) + */ + String createSign(Object xmlbean); + + /** + * 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3) + * @param xmlbean Bean需要标记有XML注解 + * @param signKey 签名Key + * @return 签名字符串 + * @see #createSign(Map, String) + */ + String createSign(Object xmlbean, String signKey); + + /** + * 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3) + * @param prams 参数信息,默认使用配置中的PartnerKey进行签名 + * @param signKey 签名Key + * @return 签名字符串 + * @see #createSign(Map, String) + */ + String createSign(Map prams); + + + /** + * 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3) + * @param prams 参数信息 + * @param signKey 签名Key + * @return 签名字符串 + */ + String createSign(Map prams, String signKey); + + /** - *
-   * 计算Map键值对是否和签名相符,
-   * 按照字段名的 ASCII 码从小到大排序(字典序)后,使用 URL 键值对的 格式(即 key1=value1&key2=value2...)拼接成字符串
-   * 
+ * 校验签名是否正确,默认使用配置中的PartnerKey进行签名 + * @param xmlbean Bean需要标记有XML注解 + * @return true - 签名校验成功,false - 签名校验失败 + * @see #checkSign(Map, String) + */ + boolean checkSign(Object xmlbean); + + /** + * 校验签名是否正确 + * @param xmlbean Bean需要标记有XML注解 + * @param signKey 校验的签名Key + * @return true - 签名校验成功,false - 签名校验失败 + * @see #checkSign(Map, String) + */ + boolean checkSign(Object xmlbean, String signKey); + + /** + * 校验签名是否正确,默认使用配置中的PartnerKey进行签名 + * @param prams 需要校验的参数Map + * @return true - 签名校验成功,false - 签名校验失败 + * @see #checkSign(Map, String) + */ + boolean checkSign(Map prams); + + /** + * 校验签名是否正确 + * @param prams 需要校验的参数Map + * @param signKey 校验的签名Key + * @return true - 签名校验成功,false - 签名校验失败 + * @see #checkSign(Map, String) */ - boolean checkJSSDKCallbackDataSignature(Map kvm, String signature); + boolean checkSign(Map prams, String signKey); + + /** * 发送微信红包给个人用户 diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImpl.java index 1373c83d..579d5c72 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImpl.java @@ -5,7 +5,6 @@ import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.api.WxMpMenuService; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult; -import me.chanjar.weixin.mp.bean.menu.WxMpSelfMenuInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java index 78e76e0f..df4c5a5e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java @@ -1,15 +1,17 @@ package me.chanjar.weixin.mp.api.impl; -import com.thoughtworks.xstream.XStream; -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.common.util.xml.XStreamInitializer; -import me.chanjar.weixin.mp.api.WxMpPayService; -import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.bean.pay.WxPayJsSDKCallback; -import me.chanjar.weixin.mp.bean.pay.request.*; -import me.chanjar.weixin.mp.bean.pay.result.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyStore; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +import javax.net.ssl.SSLContext; + import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; @@ -27,12 +29,36 @@ import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.net.ssl.SSLContext; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.security.KeyStore; -import java.util.*; +import com.thoughtworks.xstream.XStream; + +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.common.util.xml.XStreamInitializer; +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.WxPayOrderNotifyResultConverter; +import me.chanjar.weixin.mp.bean.pay.request.WxEntPayQueryRequest; +import me.chanjar.weixin.mp.bean.pay.request.WxEntPayRequest; +import me.chanjar.weixin.mp.bean.pay.request.WxPayOrderCloseRequest; +import me.chanjar.weixin.mp.bean.pay.request.WxPayOrderQueryRequest; +import me.chanjar.weixin.mp.bean.pay.request.WxPayRedpackQueryRequest; +import me.chanjar.weixin.mp.bean.pay.request.WxPayRefundQueryRequest; +import me.chanjar.weixin.mp.bean.pay.request.WxPayRefundRequest; +import me.chanjar.weixin.mp.bean.pay.request.WxPaySendRedpackRequest; +import me.chanjar.weixin.mp.bean.pay.request.WxPayUnifiedOrderRequest; +import me.chanjar.weixin.mp.bean.pay.result.WxEntPayQueryResult; +import me.chanjar.weixin.mp.bean.pay.result.WxEntPayResult; +import me.chanjar.weixin.mp.bean.pay.result.WxPayBaseResult; +import me.chanjar.weixin.mp.bean.pay.result.WxPayOrderCloseResult; +import me.chanjar.weixin.mp.bean.pay.result.WxPayOrderNotifyResult; +import me.chanjar.weixin.mp.bean.pay.result.WxPayOrderQueryResult; +import me.chanjar.weixin.mp.bean.pay.result.WxPayRedpackQueryResult; +import me.chanjar.weixin.mp.bean.pay.result.WxPayRefundQueryResult; +import me.chanjar.weixin.mp.bean.pay.result.WxPayRefundResult; +import me.chanjar.weixin.mp.bean.pay.result.WxPaySendRedpackResult; +import me.chanjar.weixin.mp.bean.pay.result.WxPayUnifiedOrderResult; /** * Created by Binary Wang on 2016/7/28. @@ -47,9 +73,11 @@ public class WxMpPayServiceImpl implements WxMpPayService { "REFUND_SOURCE_UNSETTLED_FUNDS"}; protected final Logger log = LoggerFactory.getLogger(this.getClass()); private WxMpService wxMpService; + private WxMpConfigStorage config; public WxMpPayServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; + this.config = wxMpService.getWxMpConfigStorage(); } @Override @@ -61,13 +89,12 @@ public class WxMpPayServiceImpl implements WxMpPayService { xstream.processAnnotations(WxPayRefundRequest.class); xstream.processAnnotations(WxPayRefundResult.class); - request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); - String partnerId = this.wxMpService.getWxMpConfigStorage().getPartnerId(); + request.setAppid(this.config.getAppId()); + String partnerId = this.config.getPartnerId(); request.setMchId(partnerId); request.setNonceStr(System.currentTimeMillis() + ""); request.setOpUserId(partnerId); - String sign = this.createSign(BeanUtils.xmlBean2Map(request), this.wxMpService.getWxMpConfigStorage().getPartnerKey()); - request.setSign(sign); + request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/secapi/pay/refund"; String responseContent = this.executeRequestWithKeyFile(url, keyFile, xstream.toXML(request), partnerId); @@ -93,13 +120,10 @@ public class WxMpPayServiceImpl implements WxMpPayService { request.setOutRefundNo(StringUtils.trimToNull(outRefundNo)); request.setRefundId(StringUtils.trimToNull(refundId)); - request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); - request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); + request.setAppid(this.config.getAppId()); + request.setMchId(this.config.getPartnerId()); request.setNonceStr(System.currentTimeMillis() + ""); - - String sign = this.createSign(BeanUtils.xmlBean2Map(request), - this.wxMpService.getWxMpConfigStorage().getPartnerKey()); - request.setSign(sign); + request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/pay/refundquery"; @@ -109,8 +133,15 @@ public class WxMpPayServiceImpl implements WxMpPayService { this.checkResult(result); return result; } + private void checkResult(WxPayBaseResult result) throws WxErrorException { + //校验返回结果签名 + if(!checkSign(result.toMap())){ + throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("参数格式校验错误!").build()); + } + + //校验结果是否成功 if (!"SUCCESS".equalsIgnoreCase(result.getReturnCode()) || !"SUCCESS".equalsIgnoreCase(result.getResultCode())) { throw new WxErrorException(WxError.newBuilder().setErrorCode(-1) @@ -136,23 +167,23 @@ public class WxMpPayServiceImpl implements WxMpPayService { } @Override - public WxPayJsSDKCallback getJSSDKCallbackData(String xmlData) throws WxErrorException { + public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException { try { XStream xstream = XStreamInitializer.getInstance(); - xstream.alias("xml", WxPayJsSDKCallback.class); - return (WxPayJsSDKCallback) xstream.fromXML(xmlData); - } catch (Exception e) { - e.printStackTrace(); + xstream.autodetectAnnotations(true); + xstream.registerConverter(new WxPayOrderNotifyResultConverter(xstream.getMapper(),xstream.getReflectionProvider())); + WxPayOrderNotifyResult result = (WxPayOrderNotifyResult) xstream.fromXML(xmlData); + this.checkResult(result); + return result; + }catch (WxErrorException e) { + log.error(e.getMessage(),e); + throw e; + }catch (Exception e) { + log.error(e.getMessage(),e); throw new WxErrorException(WxError.newBuilder().setErrorMsg("发生异常" + e.getMessage()).build()); } } - @Override - public boolean checkJSSDKCallbackDataSignature(Map kvm, - String signature) { - return signature.equals(this.createSign(kvm, - this.wxMpService.getWxMpConfigStorage().getPartnerKey())); - } @Override public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File keyFile) @@ -161,14 +192,11 @@ public class WxMpPayServiceImpl implements WxMpPayService { xstream.processAnnotations(WxPaySendRedpackRequest.class); xstream.processAnnotations(WxPaySendRedpackResult.class); - request.setWxAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); - String mchId = this.wxMpService.getWxMpConfigStorage().getPartnerId(); + request.setWxAppid(this.config.getAppId()); + String mchId = this.config.getPartnerId(); request.setMchId(mchId); request.setNonceStr(System.currentTimeMillis() + ""); - - String sign = this.createSign(BeanUtils.xmlBean2Map(request), - this.wxMpService.getWxMpConfigStorage().getPartnerKey()); - request.setSign(sign); + request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/mmpaymkttransfers/sendredpack"; if (request.getAmtType() != null) { @@ -177,8 +205,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { } String responseContent = this.executeRequestWithKeyFile(url, keyFile, xstream.toXML(request), mchId); - WxPaySendRedpackResult result = (WxPaySendRedpackResult) xstream - .fromXML(responseContent); + WxPaySendRedpackResult result = (WxPaySendRedpackResult) xstream.fromXML(responseContent); this.checkResult(result); return result; } @@ -193,13 +220,12 @@ public class WxMpPayServiceImpl implements WxMpPayService { request.setMchBillNo(mchBillNo); request.setBillType("MCHT"); - request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); - String mchId = this.wxMpService.getWxMpConfigStorage().getPartnerId(); + request.setAppid(this.config.getAppId()); + String mchId = this.config.getPartnerId(); request.setMchId(mchId); request.setNonceStr(System.currentTimeMillis() + ""); - String sign = this.createSign(BeanUtils.xmlBean2Map(request), - this.wxMpService.getWxMpConfigStorage().getPartnerKey()); + String sign = this.createSign(request); request.setSign(sign); String url = PAY_BASE_URL + "/mmpaymkttransfers/gethbinfo"; @@ -208,30 +234,59 @@ public class WxMpPayServiceImpl implements WxMpPayService { this.checkResult(result); return result; } + + @Override + public String createSign(Object xmlBean) { + return createSign(BeanUtils.xmlBean2Map(xmlBean),this.config.getPartnerKey()); + } + + @Override + public String createSign(Object xmlBean, String signKey) { + return createSign(BeanUtils.xmlBean2Map(xmlBean), signKey); + } + + @Override + public String createSign(Map params) { + return createSign(params,this.config.getPartnerKey()); + } - /** - * 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3) - * - * @param packageParams 原始参数 - * @param signKey 加密Key(即 商户Key) - * @return 签名字符串 - */ - private String createSign(Map packageParams, String signKey) { - SortedMap sortedMap = new TreeMap<>(packageParams); + @Override + public String createSign(Map params, String signKey) { + SortedMap sortedMap = new TreeMap<>(params); StringBuilder toSign = new StringBuilder(); for (String key : sortedMap.keySet()) { - String value = packageParams.get(key); - if (null != value && !"".equals(value) && !"sign".equals(key) - && !"key".equals(key)) { + String value = params.get(key); + if (StringUtils.isNotEmpty(value) && !"sign".equals(key) && !"key".equals(key)) { toSign.append(key + "=" + value + "&"); } } toSign.append("key=" + signKey); - return DigestUtils.md5Hex(toSign.toString()).toUpperCase(); } + + @Override + public boolean checkSign(Object xmlBean) { + return checkSign(BeanUtils.xmlBean2Map(xmlBean) , this.config.getPartnerKey()); + } + + @Override + public boolean checkSign(Object xmlBean, String signKey) { + return checkSign(BeanUtils.xmlBean2Map(xmlBean) , signKey); + } + + @Override + public boolean checkSign(Map params) { + return checkSign(params , this.config.getPartnerKey()); + } + + @Override + public boolean checkSign(Map params, String signKey) { + String sign = this.createSign(params , signKey); + return sign.equals(params.get("sign")); + } + @Override public WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxErrorException { @@ -247,13 +302,10 @@ public class WxMpPayServiceImpl implements WxMpPayService { WxPayOrderQueryRequest request = new WxPayOrderQueryRequest(); request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); request.setTransactionId(StringUtils.trimToNull(transactionId)); - request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); - request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); + request.setAppid(this.config.getAppId()); + request.setMchId(this.config.getPartnerId()); request.setNonceStr(System.currentTimeMillis() + ""); - - String sign = this.createSign(BeanUtils.xmlBean2Map(request), - this.wxMpService.getWxMpConfigStorage().getPartnerKey()); - request.setSign(sign); + request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/pay/orderquery"; @@ -276,13 +328,10 @@ public class WxMpPayServiceImpl implements WxMpPayService { WxPayOrderCloseRequest request = new WxPayOrderCloseRequest(); request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); - request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); - request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); + request.setAppid(this.config.getAppId()); + request.setMchId(this.config.getPartnerId()); request.setNonceStr(System.currentTimeMillis() + ""); - - String sign = this.createSign(BeanUtils.xmlBean2Map(request), - this.wxMpService.getWxMpConfigStorage().getPartnerKey()); - request.setSign(sign); + request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/pay/closeorder"; @@ -302,13 +351,25 @@ public class WxMpPayServiceImpl implements WxMpPayService { xstream.processAnnotations(WxPayUnifiedOrderRequest.class); xstream.processAnnotations(WxPayUnifiedOrderResult.class); - request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); - request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); - request.setNonceStr(System.currentTimeMillis() + ""); - - String sign = this.createSign(BeanUtils.xmlBean2Map(request), - this.wxMpService.getWxMpConfigStorage().getPartnerKey()); - request.setSign(sign); + WxMpConfigStorage config = this.config; + + //如果没有设置,则使用配置中默认值 + if(StringUtils.isBlank(request.getAppid())){ + request.setAppid(config.getAppId()); + } + if(StringUtils.isBlank(request.getMchId())){ + request.setMchId(config.getPartnerId()); + } + if(StringUtils.isBlank(request.getNotifyURL())){ + request.setNotifyURL(config.getNotifyURL()); + } + if(StringUtils.isBlank(request.getTradeType())){ + request.setTradeType(config.getTradeType()); + } + if(StringUtils.isBlank(request.getNonceStr())){ + request.setNonceStr(System.currentTimeMillis() + ""); + } + request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/pay/unifiedorder"; @@ -345,7 +406,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { } Map payInfo = new HashMap<>(); - payInfo.put("appId", this.wxMpService.getWxMpConfigStorage().getAppId()); + payInfo.put("appId", this.config.getAppId()); // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); payInfo.put("nonceStr", System.currentTimeMillis() + ""); @@ -354,9 +415,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { if ("NATIVE".equals(request.getTradeType())) { payInfo.put("codeUrl", unifiedOrderResult.getCodeURL()); } - - String finalSign = this.createSign(payInfo, this.wxMpService.getWxMpConfigStorage().getPartnerKey()); - payInfo.put("paySign", finalSign); + payInfo.put("paySign", this.createSign(payInfo)); return payInfo; } @@ -368,12 +427,10 @@ public class WxMpPayServiceImpl implements WxMpPayService { xstream.processAnnotations(WxEntPayRequest.class); xstream.processAnnotations(WxEntPayResult.class); - request.setMchAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); - request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); + request.setMchAppid(this.config.getAppId()); + request.setMchId(this.config.getPartnerId()); request.setNonceStr(System.currentTimeMillis() + ""); - - String sign = this.createSign(BeanUtils.xmlBean2Map(request), this.wxMpService.getWxMpConfigStorage().getPartnerKey()); - request.setSign(sign); + request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/mmpaymkttransfers/promotion/transfers"; @@ -390,12 +447,10 @@ public class WxMpPayServiceImpl implements WxMpPayService { xstream.processAnnotations(WxEntPayQueryResult.class); WxEntPayQueryRequest request = new WxEntPayQueryRequest(); - request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); - request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); + request.setAppid(this.config.getAppId()); + request.setMchId(this.config.getPartnerId()); request.setNonceStr(System.currentTimeMillis() + ""); - - String sign = this.createSign(BeanUtils.xmlBean2Map(request), this.wxMpService.getWxMpConfigStorage().getPartnerKey()); - request.setSign(sign); + request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/mmpaymkttransfers/gettransferinfo"; @@ -456,5 +511,4 @@ public class WxMpPayServiceImpl implements WxMpPayService { throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg(e.getMessage()).build(), e); } } - } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMessage.java index 5b8b81e5..c0b53d46 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMessage.java @@ -62,7 +62,8 @@ public abstract class WxMpXmlOutMessage implements Serializable { this.msgType = msgType; } - public String toXml() { + @SuppressWarnings("unchecked") + public String toXml() { return XStreamTransformer.toXml((Class) this.getClass(), this); } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayJsSDKCallback.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayJsSDKCallback.java deleted file mode 100644 index 07a3fe16..00000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayJsSDKCallback.java +++ /dev/null @@ -1,267 +0,0 @@ -package me.chanjar.weixin.mp.bean.pay; - -import me.chanjar.weixin.common.util.ToStringUtils; - -import java.io.Serializable; - -/** - *
- * 订单支付状态回调
- * 支付结果通知(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7)
- * /pre>
- *
- * @author ukid
- */
-public class WxPayJsSDKCallback implements Serializable {
-  private static final long serialVersionUID = -4143804055690843641L;
-  private String return_code;
-  private String return_msg;
-
-  private String appid;
-  private String mch_id;
-  private String device_info;
-  private String nonce_str;
-  private String sign;
-  private String result_code;
-  private String err_code;
-  private String err_code_des;
-  private String openid;
-  private String is_subscribe;
-  private String trade_type;
-  private String bank_type;
-  private String total_fee;
-  private String fee_type;
-  private String cash_fee;
-  private String cash_fee_type;
-  private String coupon_fee;
-  private String coupon_count;
-  private String coupon_batch_id_$n;
-  private String coupon_id_$n;
-  private String coupon_fee_$n;
-  private String transaction_id;
-  private String out_trade_no;
-  private String attach;
-  private String time_end;
-
-  public String getReturn_code() {
-    return this.return_code;
-  }
-
-  public void setReturn_code(String return_code) {
-    this.return_code = return_code;
-  }
-
-  public String getReturn_msg() {
-    return this.return_msg;
-  }
-
-  public void setReturn_msg(String return_msg) {
-    this.return_msg = return_msg;
-  }
-
-  public String getAppid() {
-    return this.appid;
-  }
-
-  public void setAppid(String appid) {
-    this.appid = appid;
-  }
-
-  public String getMch_id() {
-    return this.mch_id;
-  }
-
-  public void setMch_id(String mch_id) {
-    this.mch_id = mch_id;
-  }
-
-  public String getDevice_info() {
-    return this.device_info;
-  }
-
-  public void setDevice_info(String device_info) {
-    this.device_info = device_info;
-  }
-
-  public String getNonce_str() {
-    return this.nonce_str;
-  }
-
-  public void setNonce_str(String nonce_str) {
-    this.nonce_str = nonce_str;
-  }
-
-  public String getSign() {
-    return this.sign;
-  }
-
-  public void setSign(String sign) {
-    this.sign = sign;
-  }
-
-  public String getResult_code() {
-    return this.result_code;
-  }
-
-  public void setResult_code(String result_code) {
-    this.result_code = result_code;
-  }
-
-  public String getErr_code() {
-    return this.err_code;
-  }
-
-  public void setErr_code(String err_code) {
-    this.err_code = err_code;
-  }
-
-  public String getErr_code_des() {
-    return this.err_code_des;
-  }
-
-  public void setErr_code_des(String err_code_des) {
-    this.err_code_des = err_code_des;
-  }
-
-  public String getOpenid() {
-    return this.openid;
-  }
-
-  public void setOpenid(String openid) {
-    this.openid = openid;
-  }
-
-  public String getIs_subscribe() {
-    return this.is_subscribe;
-  }
-
-  public void setIs_subscribe(String is_subscribe) {
-    this.is_subscribe = is_subscribe;
-  }
-
-  public String getTrade_type() {
-    return this.trade_type;
-  }
-
-  public void setTrade_type(String trade_type) {
-    this.trade_type = trade_type;
-  }
-
-  public String getBank_type() {
-    return this.bank_type;
-  }
-
-  public void setBank_type(String bank_type) {
-    this.bank_type = bank_type;
-  }
-
-  public String getTotal_fee() {
-    return this.total_fee;
-  }
-
-  public void setTotal_fee(String total_fee) {
-    this.total_fee = total_fee;
-  }
-
-  public String getFee_type() {
-    return this.fee_type;
-  }
-
-  public void setFee_type(String fee_type) {
-    this.fee_type = fee_type;
-  }
-
-  public String getCash_fee() {
-    return this.cash_fee;
-  }
-
-  public void setCash_fee(String cash_fee) {
-    this.cash_fee = cash_fee;
-  }
-
-  public String getCash_fee_type() {
-    return this.cash_fee_type;
-  }
-
-  public void setCash_fee_type(String cash_fee_type) {
-    this.cash_fee_type = cash_fee_type;
-  }
-
-  public String getCoupon_fee() {
-    return this.coupon_fee;
-  }
-
-  public void setCoupon_fee(String coupon_fee) {
-    this.coupon_fee = coupon_fee;
-  }
-
-  public String getCoupon_count() {
-    return this.coupon_count;
-  }
-
-  public void setCoupon_count(String coupon_count) {
-    this.coupon_count = coupon_count;
-  }
-
-  public String getCoupon_batch_id_$n() {
-    return this.coupon_batch_id_$n;
-  }
-
-  public void setCoupon_batch_id_$n(String coupon_batch_id_$n) {
-    this.coupon_batch_id_$n = coupon_batch_id_$n;
-  }
-
-  public String getCoupon_id_$n() {
-    return this.coupon_id_$n;
-  }
-
-  public void setCoupon_id_$n(String coupon_id_$n) {
-    this.coupon_id_$n = coupon_id_$n;
-  }
-
-  public String getCoupon_fee_$n() {
-    return this.coupon_fee_$n;
-  }
-
-  public void setCoupon_fee_$n(String coupon_fee_$n) {
-    this.coupon_fee_$n = coupon_fee_$n;
-  }
-
-  public String getTransaction_id() {
-    return this.transaction_id;
-  }
-
-  public void setTransaction_id(String transaction_id) {
-    this.transaction_id = transaction_id;
-  }
-
-  public String getOut_trade_no() {
-    return this.out_trade_no;
-  }
-
-  public void setOut_trade_no(String out_trade_no) {
-    this.out_trade_no = out_trade_no;
-  }
-
-  public String getAttach() {
-    return this.attach;
-  }
-
-  public void setAttach(String attach) {
-    this.attach = attach;
-  }
-
-  public String getTime_end() {
-    return this.time_end;
-  }
-
-  public void setTime_end(String time_end) {
-    this.time_end = time_end;
-  }
-
-  @Override
-  public String toString() {
-    return ToStringUtils.toSimpleString(this);
-  }
-
-}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyCoupon.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyCoupon.java
new file mode 100644
index 00000000..7cea57ba
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyCoupon.java
@@ -0,0 +1,59 @@
+package me.chanjar.weixin.mp.bean.pay;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+
+/**
+ * 支付异步通知代金券详细
+ */
+public class WxPayOrderNotifyCoupon implements Serializable {
+	/**
+	 * @fields serialVersionUID 
+	 */
+	private static final long serialVersionUID = -4165343733538156097L;
+	
+	@XStreamAlias("coupon_id")
+	private String couponId;
+	@XStreamAlias("coupon_type")
+	private String couponType;
+	@XStreamAlias("coupon_fee")
+	private Integer couponFee;
+	
+	public String getCouponId() {
+		return couponId;
+	}
+	public void setCouponId(String couponId) {
+		this.couponId = couponId;
+	}
+	public String getCouponType() {
+		return couponType;
+	}
+	public void setCouponType(String couponType) {
+		this.couponType = couponType;
+	}
+	public Integer getCouponFee() {
+		return couponFee;
+	}
+	public void setCouponFee(Integer couponFee) {
+		this.couponFee = couponFee;
+	}
+	
+	public Map toMap(int index){
+		Map map = new HashMap<>();
+		map.put("coupon_id_"+index, this.getCouponId());
+		map.put("coupon_type_"+index, this.getCouponType());
+		map.put("coupon_fee_"+index, this.getCouponFee()+"");
+		return map;
+	}
+	
+	@Override
+	public String toString() {
+		return ToStringBuilder.reflectionToString(this,ToStringStyle.MULTI_LINE_STYLE);
+	}
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResponse.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResponse.java
new file mode 100644
index 00000000..54f4fc56
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResponse.java
@@ -0,0 +1,61 @@
+package me.chanjar.weixin.mp.bean.pay;
+
+
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamOmitField;
+
+import me.chanjar.weixin.common.util.xml.XStreamInitializer;
+
+@XStreamAlias("xml")
+public class WxPayOrderNotifyResponse {
+	@XStreamOmitField
+	private transient static final String FAIL ="FAIL";
+	@XStreamOmitField
+	private transient static final String SUCCESS ="SUCCESS";
+	
+	@XStreamAlias("return_code")
+	private String returnCode;
+	@XStreamAlias("return_msg")
+	private String returnMsg;
+	
+	
+	public String getReturnCode() {
+		return returnCode;
+	}
+	public void setReturnCode(String returnCode) {
+		this.returnCode = returnCode;
+	}
+	public String getReturnMsg() {
+		return returnMsg;
+	}
+	public void setReturnMsg(String returnMsg) {
+		this.returnMsg = returnMsg;
+	}
+	
+
+	public WxPayOrderNotifyResponse() {
+		super();
+	}
+	public WxPayOrderNotifyResponse(String returnCode, String returnMsg) {
+		super();
+		this.returnCode = returnCode;
+		this.returnMsg = returnMsg;
+	}
+	
+	
+	public static String fail(String msg){
+		WxPayOrderNotifyResponse response =	new WxPayOrderNotifyResponse(FAIL,msg);
+		XStream xstream = XStreamInitializer.getInstance();
+		xstream.autodetectAnnotations(true);
+		return xstream.toXML(response);
+	}
+	
+	
+	public static String success(String msg){
+		WxPayOrderNotifyResponse response =	new WxPayOrderNotifyResponse(SUCCESS,msg);
+		XStream xstream = XStreamInitializer.getInstance();
+		xstream.autodetectAnnotations(true);
+		return xstream.toXML(response);
+	}
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResultConverter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResultConverter.java
new file mode 100644
index 00000000..1f90f0b9
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResultConverter.java
@@ -0,0 +1,130 @@
+package me.chanjar.weixin.mp.bean.pay;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Maps;
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter;
+import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+import me.chanjar.weixin.mp.bean.pay.result.WxPayOrderNotifyResult;
+
+public class WxPayOrderNotifyResultConverter extends AbstractReflectionConverter {
+
+	public WxPayOrderNotifyResultConverter(Mapper mapper, ReflectionProvider reflectionProvider) {
+		super(mapper, reflectionProvider);
+	}
+
+	@Override
+	@SuppressWarnings("rawtypes")
+	public boolean canConvert(Class type) {
+		return type.equals(WxPayOrderNotifyResult.class);
+	}
+
+	@Override
+	public void marshal(Object original, HierarchicalStreamWriter writer, MarshallingContext context) {
+		super.marshal(original, writer, context);
+		WxPayOrderNotifyResult obj = (WxPayOrderNotifyResult) original;
+		List list = obj.getCouponList();
+		if (list == null || list.size() == 0) {
+			return;
+		}
+		for (int i = 0; i < list.size(); i++) {
+			WxPayOrderNotifyCoupon coupon = list.get(i);
+			writer.startNode("coupon_id_" + i);
+			writer.setValue(coupon.getCouponId());
+			writer.endNode();
+			writer.startNode("coupon_type_" + i);
+			writer.setValue(coupon.getCouponType());
+			writer.endNode();
+			writer.startNode("coupon_fee_" + i);
+			writer.setValue(coupon.getCouponFee() + "");
+			writer.endNode();
+		}
+	}
+
+	@Override
+	protected void marshallField(MarshallingContext context, Object newObj, Field field) {
+		if (field.getName().equals("couponList")) {
+			return;
+		} else {
+			super.marshallField(context, newObj, field);
+		}
+	}
+
+	@Override
+	public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
+		WxPayOrderNotifyResult obj = new WxPayOrderNotifyResult();
+
+		List fields = new ArrayList<>(Arrays.asList(obj.getClass().getDeclaredFields()));
+		fields.addAll(Arrays.asList(obj.getClass().getSuperclass().getDeclaredFields()));
+		Map fieldMap = getFieldMap(fields);
+
+		List coupons = new ArrayList<>(10);
+		while (reader.hasMoreChildren()) {
+			reader.moveDown();
+			if (fieldMap.containsKey(reader.getNodeName())) {
+				Field field = fieldMap.get(reader.getNodeName());
+				setFieldValue(context, obj, field);
+			} else if (StringUtils.startsWith(reader.getNodeName(), "coupon_id_")) {
+				String id = (String) context.convertAnother(obj, String.class);
+				getIndex(coupons, reader.getNodeName()).setCouponId(id);
+			} else if (StringUtils.startsWith(reader.getNodeName(), "coupon_type_")) {
+				String type = (String) context.convertAnother(obj, String.class);
+				getIndex(coupons, reader.getNodeName()).setCouponType(type);
+			} else if (StringUtils.startsWith(reader.getNodeName(), "coupon_fee_")) {
+				Integer fee = (Integer) context.convertAnother(obj, Integer.class);
+				getIndex(coupons, reader.getNodeName()).setCouponFee(fee);
+			}
+			reader.moveUp();
+		}
+
+		obj.setCouponList(coupons);
+		return obj;
+	}
+
+	private void setFieldValue(UnmarshallingContext context, WxPayOrderNotifyResult obj, Field field) {
+		Object val = context.convertAnother(obj, field.getType());
+		try {
+			if (val != null) {
+				PropertyDescriptor pd = new PropertyDescriptor(field.getName(), obj.getClass());
+				pd.getWriteMethod().invoke(obj, val);
+			}
+		} catch (Exception e) {
+		}
+	}
+
+	private Map getFieldMap(List fields) {
+		Map fieldMap = Maps.uniqueIndex(fields, new Function() {
+			@Override
+			public String apply(Field field) {
+				if (field.isAnnotationPresent(XStreamAlias.class)) {
+					return field.getAnnotation(XStreamAlias.class).value();
+				}
+				return field.getName();
+			}
+		});
+		return fieldMap;
+	}
+
+	private WxPayOrderNotifyCoupon getIndex(List 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/bean/pay/request/WxEntPayQueryRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxEntPayQueryRequest.java
index 5982d3ee..df2de905 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxEntPayQueryRequest.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxEntPayQueryRequest.java
@@ -30,7 +30,6 @@ public class WxEntPayQueryRequest extends WxPayBaseRequest {
    * 微信支付分配的商户号
    * 
*/ - @SuppressWarnings("hiding") @XStreamAlias("mchid") private String mchId; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java index 341c3b2e..9ede16ec 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java @@ -71,6 +71,10 @@ public abstract class WxPayBaseRequest { return this.appid; } + /** + * 如果配置中已经设置,可以不设置值 + * @param appid + */ public void setAppid(String appid) { this.appid = appid; } @@ -79,6 +83,10 @@ public abstract class WxPayBaseRequest { return this.mchId; } + /** + * 如果配置中已经设置,可以不设置值 + * @param mchId + */ public void setMchId(String mchId) { this.mchId = mchId; } @@ -87,6 +95,10 @@ public abstract class WxPayBaseRequest { return this.nonceStr; } + /** + * 默认采用时间戳为随机字符串,可以不设置 + * @param nonceStr + */ public void setNonceStr(String nonceStr) { this.nonceStr = nonceStr; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayUnifiedOrderRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayUnifiedOrderRequest.java index 195e13b0..cf4c008f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayUnifiedOrderRequest.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayUnifiedOrderRequest.java @@ -360,6 +360,10 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest { return this.notifyURL; } + /** + * 如果配置中已经设置,可以不设置值 + * @param notifyURL + */ public void setNotifyURL(String notifyURL) { this.notifyURL = notifyURL; } @@ -368,6 +372,10 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest { return this.tradeType; } + /** + * 如果配置中已经设置,可以不设置值 + * @param tradeType 交易类型 + */ public void setTradeType(String tradeType) { this.tradeType = tradeType; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java index 64310138..d7455377 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java @@ -1,6 +1,10 @@ package me.chanjar.weixin.mp.bean.pay.result; +import java.util.Map; + import com.thoughtworks.xstream.annotations.XStreamAlias; + +import me.chanjar.weixin.common.util.BeanUtils; import me.chanjar.weixin.common.util.ToStringUtils; /** @@ -141,4 +145,8 @@ public abstract class WxPayBaseResult { public void setSign(String sign) { this.sign = sign; } + + public Map toMap(){ + return BeanUtils.xmlBean2Map(this); + } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java new file mode 100644 index 00000000..0a6815d8 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java @@ -0,0 +1,414 @@ +package me.chanjar.weixin.mp.bean.pay.result; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import com.thoughtworks.xstream.annotations.XStreamAlias; + +import me.chanjar.weixin.common.util.BeanUtils; +import me.chanjar.weixin.mp.bean.pay.WxPayOrderNotifyCoupon; + +/** + * 支付结果通用通知 ,文档见:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7 + * @author aimilin6688 + * @since 2.5.0 + */ +@XStreamAlias("xml") +public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializable { + + /** + * @fields serialVersionUID + */ + private static final long serialVersionUID = 5389718115223345496L; + + + /** + *
+	 * 设备号
+	 * device_info	
+	 * 否	
+	 * String(32)	
+	 * 013467007045764	
+	 * 微信支付分配的终端设备号,
+	 * 
+ * @fields deviceInfo + */ + @XStreamAlias("device_info") + private String deviceInfo; + + /** + *
+	 * 用户标识	
+	 * openid	
+	 * 是	
+	 * String(128)	
+	 * wxd930ea5d5a258f4f	
+	 * 用户在商户appid下的唯一标识
+	 * 
+ * @fields openid + */ + @XStreamAlias("openid") + private String openid; + + /** + *
+	 * 是否关注公众账号	
+	 * is_subscribe	
+	 * 否	
+	 * String(1)	
+	 * Y	
+	 * 用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
+	 * 
+ * @fields isSubscribe + */ + @XStreamAlias("is_subscribe") + private String isSubscribe; + + + /** + *
+	 * 交易类型	
+	 * trade_type	
+	 * 是	
+	 * String(16)	
+	 * JSAPI	JSAPI、NATIVE、APP
+	 * 
+ * @fields tradeType + */ + @XStreamAlias("trade_type") + private String tradeType; + + + /** + *
+	 * 付款银行	
+	 * bank_type	
+	 * 是	
+	 * String(16)	
+	 * CMC	
+	 * 银行类型,采用字符串类型的银行标识,银行类型见银行列表
+	 * 
+ * @fields bankType + */ + @XStreamAlias("bank_type") + private String bankType; + + + /** + *
+	 * 订单金额	
+	 * total_fee	
+	 * 是	
+	 * Int	
+	 * 100	
+	 * 订单总金额,单位为分
+	 * 
+ * @fields totalFee + */ + @XStreamAlias("total_fee") + private Integer totalFee; + /** + *
+	 * 应结订单金额	
+	 * settlement_total_fee	
+	 * 否	
+	 * Int	
+	 * 100	
+	 * 应结订单金额=订单金额-非充值代金券金额,应结订单金额<=订单金额。
+	 * 
+ * @fields settlementTotalFee + */ + @XStreamAlias("settlement_total_fee") + private Integer settlementTotalFee; + /** + *
+	 * 货币种类	
+	 * fee_type	
+	 * 否	
+	 * String(8)	
+	 * CNY	
+	 * 货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
+	 * 
+ * @fields feeType + */ + @XStreamAlias("fee_type") + private String feeType; + /** + *
+	 * 现金支付金额	
+	 * cash_fee	
+	 * 是	
+	 * Int	
+	 * 100	
+	 * 现金支付金额订单现金支付金额,详见支付金额
+	 * 
+ * @fields cashFee + */ + @XStreamAlias("cash_fee") + private Integer cashFee; + /** + *
+	 * 现金支付货币类型	
+	 * cash_fee_type	
+	 * 否	
+	 * String(16)	
+	 * CNY	
+	 * 货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
+	 * 
+ * @fields cashFeeType + */ + @XStreamAlias("cash_fee_type") + private String cashFeeType; + /** + *
+	 * 总代金券金额	
+	 * coupon_fee	
+	 * 否	
+	 * Int	
+	 * 10	
+	 * 代金券金额<=订单金额,订单金额-代金券金额=现金支付金额,详见支付金额
+	 * 
+ * @fields couponFee + */ + @XStreamAlias("coupon_fee") + private Integer couponFee; + + /** + *
+   * 代金券使用数量
+   * coupon_count
+   * 否
+   * Int
+   * 1
+   * 代金券使用数量
+   */
+	@XStreamAlias("coupon_count")
+	private Integer couponCount;
+	
+	private List couponList;
+	
+	
+	
+	/**
+	 * 
+	 * 微信支付订单号	
+	 * transaction_id	
+	 * 是	
+	 * String(32)	
+	 * 1217752501201407033233368018	
+	 * 微信支付订单号
+	 * 
+ * @fields transactionId + */ + @XStreamAlias("transaction_id") + private String transactionId; + + /** + *
+	 * 商户订单号	
+	 * out_trade_no	
+	 * 是	
+	 * String(32)	
+	 * 1212321211201407033568112322	
+	 * 商户系统的订单号,与请求一致。
+	 * 
+ * @fields outTradeNo + */ + @XStreamAlias("out_trade_no") + private String outTradeNo; + /** + *
+	 * 商家数据包	
+	 * attach	
+	 * 否	
+	 * String(128)	
+	 * 123456	
+	 * 商家数据包,原样返回
+	 * 
+ * @fields + */ + @XStreamAlias("attach") + private String attach; + /** + *
+	 * 支付完成时间	
+	 * time_end	
+	 * 是	
+	 * String(14)	
+	 * 20141030133525	
+	 * 支付完成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
+	 * 
+ * @fields timeEnd + */ + @XStreamAlias("time_end") + private String timeEnd; + + + public Integer getCouponCount() { + return couponCount; + } + + public void setCouponCount(Integer couponCount) { + this.couponCount = couponCount; + } + + public List getCouponList() { + return couponList; + } + + public void setCouponList(List couponList) { + this.couponList = couponList; + } + + public String getDeviceInfo() { + return deviceInfo; + } + + public void setDeviceInfo(String deviceInfo) { + this.deviceInfo = deviceInfo; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getIsSubscribe() { + return isSubscribe; + } + + public void setIsSubscribe(String isSubscribe) { + this.isSubscribe = isSubscribe; + } + + public String getTradeType() { + return tradeType; + } + + public void setTradeType(String tradeType) { + this.tradeType = tradeType; + } + + public String getBankType() { + return bankType; + } + + public void setBankType(String bankType) { + this.bankType = bankType; + } + + public Integer getTotalFee() { + return totalFee; + } + + public void setTotalFee(Integer totalFee) { + this.totalFee = totalFee; + } + + public Integer getSettlementTotalFee() { + return settlementTotalFee; + } + + public void setSettlementTotalFee(Integer settlementTotalFee) { + this.settlementTotalFee = settlementTotalFee; + } + + public String getFeeType() { + return feeType; + } + + public void setFeeType(String feeType) { + this.feeType = feeType; + } + + public Integer getCashFee() { + return cashFee; + } + + public void setCashFee(Integer cashFee) { + this.cashFee = cashFee; + } + + public String getCashFeeType() { + return cashFeeType; + } + + public void setCashFeeType(String cashFeeType) { + this.cashFeeType = cashFeeType; + } + + public Integer getCouponFee() { + return couponFee; + } + + public void setCouponFee(Integer couponFee) { + this.couponFee = couponFee; + } + + public String getTransactionId() { + return transactionId; + } + + public void setTransactionId(String transactionId) { + this.transactionId = transactionId; + } + + public String getOutTradeNo() { + return outTradeNo; + } + + public void setOutTradeNo(String outTradeNo) { + this.outTradeNo = outTradeNo; + } + + public String getAttach() { + return attach; + } + + public void setAttach(String attach) { + this.attach = attach; + } + + public String getTimeEnd() { + return timeEnd; + } + + public void setTimeEnd(String timeEnd) { + this.timeEnd = timeEnd; + } + + @Override + public Map toMap(){ + Map resultMap = BeanUtils.xmlBean2Map(this); + if(this.getCouponCount() > 0){ + for (int i = 0; i < this.getCouponCount(); i++) { + WxPayOrderNotifyCoupon coupon = couponList.get(i); + resultMap.putAll(coupon.toMap(i)); + } + } + return resultMap; + } + + + /** + * 将单位分转换成单位圆 + * @param fee + * @return + */ + public static String feeToYuan(Integer fee) { + return new BigDecimal(Double.valueOf(fee) / 100).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString(); + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this,ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/BaseBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/BaseBuilder.java index c5285d6f..3e40d178 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/BaseBuilder.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/BaseBuilder.java @@ -6,7 +6,8 @@ public class BaseBuilder { protected String msgType; protected String toUser; - public T toUser(String toUser) { + @SuppressWarnings("unchecked") + public T toUser(String toUser) { this.toUser = toUser; return (T) this; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/BaseBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/BaseBuilder.java index e594565c..60cf675d 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/BaseBuilder.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/BaseBuilder.java @@ -8,12 +8,14 @@ public abstract class BaseBuilder { protected String fromUserName; - public BuilderType toUser(String touser) { + @SuppressWarnings("unchecked") + public BuilderType toUser(String touser) { this.toUserName = touser; return (BuilderType) this; } - public BuilderType fromUser(String fromusername) { + @SuppressWarnings("unchecked") + public BuilderType fromUser(String fromusername) { this.fromUserName = fromusername; return (BuilderType) this; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVoiceAndImageDownloadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVoiceAndImageDownloadRequestExecutor.java index c40366ca..ceda65a6 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVoiceAndImageDownloadRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/MaterialVoiceAndImageDownloadRequestExecutor.java @@ -23,7 +23,6 @@ import me.chanjar.weixin.common.util.json.WxGsonBuilder; public class MaterialVoiceAndImageDownloadRequestExecutor implements RequestExecutor { - private File tmpDirFile; public MaterialVoiceAndImageDownloadRequestExecutor() { super(); @@ -31,7 +30,6 @@ public class MaterialVoiceAndImageDownloadRequestExecutor implements RequestExec public MaterialVoiceAndImageDownloadRequestExecutor(File tmpDirFile) { super(); - this.tmpDirFile = tmpDirFile; } @Override From 8bb70942c327062f8e6fc9eade7f32dac16e8a14 Mon Sep 17 00:00:00 2001 From: aimilin Date: Fri, 9 Dec 2016 12:20:00 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E6=94=AF=E4=BB=98?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chanjar/weixin/common/util/BeanUtils.java | 78 ++++--- .../mp/api/impl/WxMpPayServiceImpl.java | 107 ++++----- .../mp/bean/pay/WxPayOrderNotifyCoupon.java | 91 ++++---- .../mp/bean/pay/WxPayOrderNotifyResponse.java | 99 +++++---- .../pay/WxPayOrderNotifyResultConverter.java | 206 +++++++++--------- .../pay/result/WxPayOrderNotifyResult.java | 2 +- 6 files changed, 297 insertions(+), 286 deletions(-) diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java index 8935bc32..7c3db11f 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java @@ -1,18 +1,22 @@ package me.chanjar.weixin.common.util; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.thoughtworks.xstream.annotations.XStreamAlias; + import me.chanjar.weixin.common.annotation.Required; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - /** *
  * bean操作的一些工具类
@@ -21,6 +25,7 @@ import java.util.Map;
  * 
*/ public class BeanUtils { + private static Logger log = LoggerFactory.getLogger(BeanUtils.class); /** * 检查bean里标记为@Required的field是否为空,为空则抛异常 @@ -48,41 +53,42 @@ public class BeanUtils { } if (!nullFields.isEmpty()) { - throw new WxErrorException(WxError.newBuilder().setErrorMsg("必填字段 " + nullFields + " 必须提供值").build()); + String msg = "必填字段 " + nullFields + " 必须提供值"; + log.debug(msg); + throw new WxErrorException(WxError.newBuilder().setErrorMsg(msg).build()); } } - /** - * 将bean按照@XStreamAlias标识的字符串内容生成以之为key的map对象 - * @param bean 包含@XStreamAlias的xml bean对象 - * @return map对象 - */ - public static Map xmlBean2Map(Object bean) { - Map result = Maps.newHashMap(); - List fields = new ArrayList<>( Arrays.asList(bean.getClass().getDeclaredFields())); - fields.addAll(Arrays.asList(bean.getClass().getSuperclass().getDeclaredFields())); - for (Field field : fields) { - try { - boolean isAccessible = field.isAccessible(); - field.setAccessible(true); - if (field.get(bean) == null) { - field.setAccessible(isAccessible); - continue; - } + /** + * 将bean按照@XStreamAlias标识的字符串内容生成以之为key的map对象 + * + * @param bean 包含@XStreamAlias的xml bean对象 + * @return map对象 + */ + public static Map xmlBean2Map(Object bean) { + Map result = Maps.newHashMap(); + List fields = new ArrayList<>(Arrays.asList(bean.getClass().getDeclaredFields())); + fields.addAll(Arrays.asList(bean.getClass().getSuperclass().getDeclaredFields())); + for (Field field : fields) { + try { + boolean isAccessible = field.isAccessible(); + field.setAccessible(true); + if (field.get(bean) == null) { + field.setAccessible(isAccessible); + continue; + } - if (field.isAnnotationPresent(XStreamAlias.class)) { - result.put(field.getAnnotation(XStreamAlias.class).value(), - field.get(bean).toString()); - } + if (field.isAnnotationPresent(XStreamAlias.class)) { + result.put(field.getAnnotation(XStreamAlias.class).value(), field.get(bean).toString()); + } - field.setAccessible(isAccessible); - } catch (SecurityException | IllegalArgumentException - | IllegalAccessException e) { - e.printStackTrace(); - } + field.setAccessible(isAccessible); + } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } - } + } - return result; - } + return result; + } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java index df4c5a5e..84655a86 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java @@ -73,11 +73,17 @@ public class WxMpPayServiceImpl implements WxMpPayService { "REFUND_SOURCE_UNSETTLED_FUNDS"}; protected final Logger log = LoggerFactory.getLogger(this.getClass()); private WxMpService wxMpService; - private WxMpConfigStorage config; + private WxMpConfigStorage config = null; public WxMpPayServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; - this.config = wxMpService.getWxMpConfigStorage(); + } + + private WxMpConfigStorage getConfig(){ + if(config == null){ + this.config = wxMpService.getWxMpConfigStorage(); + } + return this.config; } @Override @@ -89,8 +95,8 @@ public class WxMpPayServiceImpl implements WxMpPayService { xstream.processAnnotations(WxPayRefundRequest.class); xstream.processAnnotations(WxPayRefundResult.class); - request.setAppid(this.config.getAppId()); - String partnerId = this.config.getPartnerId(); + request.setAppid(getConfig().getAppId()); + String partnerId = getConfig().getPartnerId(); request.setMchId(partnerId); request.setNonceStr(System.currentTimeMillis() + ""); request.setOpUserId(partnerId); @@ -120,8 +126,8 @@ public class WxMpPayServiceImpl implements WxMpPayService { request.setOutRefundNo(StringUtils.trimToNull(outRefundNo)); request.setRefundId(StringUtils.trimToNull(refundId)); - request.setAppid(this.config.getAppId()); - request.setMchId(this.config.getPartnerId()); + request.setAppid(getConfig().getAppId()); + request.setMchId(getConfig().getPartnerId()); request.setNonceStr(System.currentTimeMillis() + ""); request.setSign(this.createSign(request)); @@ -138,17 +144,20 @@ public class WxMpPayServiceImpl implements WxMpPayService { private void checkResult(WxPayBaseResult result) throws WxErrorException { //校验返回结果签名 if(!checkSign(result.toMap())){ + log.debug("校验结果签名失败,参数:{}",result.toMap()); throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("参数格式校验错误!").build()); } //校验结果是否成功 if (!"SUCCESS".equalsIgnoreCase(result.getReturnCode()) || !"SUCCESS".equalsIgnoreCase(result.getResultCode())) { - throw new WxErrorException(WxError.newBuilder().setErrorCode(-1) - .setErrorMsg("返回代码: " + result.getReturnCode() + ", 返回信息: " - + result.getReturnMsg() + ", 结果代码: " + result.getResultCode() + ", 错误代码: " - + result.getErrCode() + ", 错误详情: " + result.getErrCodeDes()) - .build()); + WxError error = WxError.newBuilder().setErrorCode(-1) + .setErrorMsg("返回代码: " + result.getReturnCode() + ", 返回信息: " + + result.getReturnMsg() + ", 结果代码: " + result.getResultCode() + ", 错误代码: " + + result.getErrCode() + ", 错误详情: " + result.getErrCodeDes()) + .build(); + log.debug("结果校验失败,参数:{},详细:{}",result.toMap(),error); + throw new WxErrorException(error); } } @@ -157,7 +166,7 @@ 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) + "其中之一"); + throw new IllegalArgumentException("refund_account目前必须为" + Arrays.toString(REFUND_ACCOUNT) + "其中之一,实际值:"+ request.getRefundAccount()); } } @@ -169,10 +178,12 @@ public class WxMpPayServiceImpl implements WxMpPayService { @Override public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException { try { + log.trace("微信支付回调参数详细:{}", xmlData); XStream xstream = XStreamInitializer.getInstance(); - xstream.autodetectAnnotations(true); + xstream.processAnnotations(WxPayOrderNotifyResult.class); xstream.registerConverter(new WxPayOrderNotifyResultConverter(xstream.getMapper(),xstream.getReflectionProvider())); WxPayOrderNotifyResult result = (WxPayOrderNotifyResult) xstream.fromXML(xmlData); + log.debug("微信支付回调结果对象:{}",result); this.checkResult(result); return result; }catch (WxErrorException e) { @@ -192,8 +203,8 @@ public class WxMpPayServiceImpl implements WxMpPayService { xstream.processAnnotations(WxPaySendRedpackRequest.class); xstream.processAnnotations(WxPaySendRedpackResult.class); - request.setWxAppid(this.config.getAppId()); - String mchId = this.config.getPartnerId(); + request.setWxAppid(getConfig().getAppId()); + String mchId = getConfig().getPartnerId(); request.setMchId(mchId); request.setNonceStr(System.currentTimeMillis() + ""); request.setSign(this.createSign(request)); @@ -220,8 +231,8 @@ public class WxMpPayServiceImpl implements WxMpPayService { request.setMchBillNo(mchBillNo); request.setBillType("MCHT"); - request.setAppid(this.config.getAppId()); - String mchId = this.config.getPartnerId(); + request.setAppid(getConfig().getAppId()); + String mchId = getConfig().getPartnerId(); request.setMchId(mchId); request.setNonceStr(System.currentTimeMillis() + ""); @@ -237,7 +248,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { @Override public String createSign(Object xmlBean) { - return createSign(BeanUtils.xmlBean2Map(xmlBean),this.config.getPartnerKey()); + return createSign(BeanUtils.xmlBean2Map(xmlBean),getConfig().getPartnerKey()); } @Override @@ -247,7 +258,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { @Override public String createSign(Map params) { - return createSign(params,this.config.getPartnerKey()); + return createSign(params,getConfig().getPartnerKey()); } @Override @@ -268,7 +279,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { @Override public boolean checkSign(Object xmlBean) { - return checkSign(BeanUtils.xmlBean2Map(xmlBean) , this.config.getPartnerKey()); + return checkSign(BeanUtils.xmlBean2Map(xmlBean) , getConfig().getPartnerKey()); } @Override @@ -278,7 +289,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { @Override public boolean checkSign(Map params) { - return checkSign(params , this.config.getPartnerKey()); + return checkSign(params , getConfig().getPartnerKey()); } @Override @@ -302,8 +313,8 @@ public class WxMpPayServiceImpl implements WxMpPayService { WxPayOrderQueryRequest request = new WxPayOrderQueryRequest(); request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); request.setTransactionId(StringUtils.trimToNull(transactionId)); - request.setAppid(this.config.getAppId()); - request.setMchId(this.config.getPartnerId()); + request.setAppid(getConfig().getAppId()); + request.setMchId(getConfig().getPartnerId()); request.setNonceStr(System.currentTimeMillis() + ""); request.setSign(this.createSign(request)); @@ -328,8 +339,8 @@ public class WxMpPayServiceImpl implements WxMpPayService { WxPayOrderCloseRequest request = new WxPayOrderCloseRequest(); request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); - request.setAppid(this.config.getAppId()); - request.setMchId(this.config.getPartnerId()); + request.setAppid(getConfig().getAppId()); + request.setMchId(getConfig().getPartnerId()); request.setNonceStr(System.currentTimeMillis() + ""); request.setSign(this.createSign(request)); @@ -345,37 +356,27 @@ public class WxMpPayServiceImpl implements WxMpPayService { @Override public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) throws WxErrorException { - checkParameters(request); XStream xstream = XStreamInitializer.getInstance(); xstream.processAnnotations(WxPayUnifiedOrderRequest.class); xstream.processAnnotations(WxPayUnifiedOrderResult.class); - WxMpConfigStorage config = this.config; + request.setAppid(getConfig().getAppId()); + request.setMchId(getConfig().getPartnerId()); + request.setNotifyURL(getConfig().getNotifyURL()); + request.setTradeType(getConfig().getTradeType()); + request.setNonceStr(System.currentTimeMillis() + ""); + + checkParameters(request);//校验参数 - //如果没有设置,则使用配置中默认值 - if(StringUtils.isBlank(request.getAppid())){ - request.setAppid(config.getAppId()); - } - if(StringUtils.isBlank(request.getMchId())){ - request.setMchId(config.getPartnerId()); - } - if(StringUtils.isBlank(request.getNotifyURL())){ - request.setNotifyURL(config.getNotifyURL()); - } - if(StringUtils.isBlank(request.getTradeType())){ - request.setTradeType(config.getTradeType()); - } - if(StringUtils.isBlank(request.getNonceStr())){ - request.setNonceStr(System.currentTimeMillis() + ""); - } request.setSign(this.createSign(request)); - String url = PAY_BASE_URL + "/pay/unifiedorder"; + String xmlParam = xstream.toXML(request); + log.debug("微信统一下单接口,URL:{},参数:{}",url, xmlParam); - String responseContent = this.executeRequest(url, xstream.toXML(request)); - WxPayUnifiedOrderResult result = (WxPayUnifiedOrderResult) xstream - .fromXML(responseContent); + String responseContent = this.executeRequest(url, xmlParam); + log.debug("微信统一下单接口,URL:{},结果:{}",url, responseContent); + WxPayUnifiedOrderResult result = (WxPayUnifiedOrderResult) xstream.fromXML(responseContent); this.checkResult(result); return result; } @@ -384,7 +385,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { BeanUtils.checkRequiredFields(request); if (!ArrayUtils.contains(TRADE_TYPES, request.getTradeType())) { - throw new IllegalArgumentException("trade_type目前必须为" + Arrays.toString(TRADE_TYPES) + "其中之一"); + throw new IllegalArgumentException("trade_type目前必须为" + Arrays.toString(TRADE_TYPES) + "其中之一,实际值:"+request.getTradeType()); } if ("JSAPI".equals(request.getTradeType()) && request.getOpenid() == null) { @@ -406,7 +407,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { } Map payInfo = new HashMap<>(); - payInfo.put("appId", this.config.getAppId()); + payInfo.put("appId", getConfig().getAppId()); // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); payInfo.put("nonceStr", System.currentTimeMillis() + ""); @@ -427,8 +428,8 @@ public class WxMpPayServiceImpl implements WxMpPayService { xstream.processAnnotations(WxEntPayRequest.class); xstream.processAnnotations(WxEntPayResult.class); - request.setMchAppid(this.config.getAppId()); - request.setMchId(this.config.getPartnerId()); + request.setMchAppid(getConfig().getAppId()); + request.setMchId(getConfig().getPartnerId()); request.setNonceStr(System.currentTimeMillis() + ""); request.setSign(this.createSign(request)); @@ -447,8 +448,8 @@ public class WxMpPayServiceImpl implements WxMpPayService { xstream.processAnnotations(WxEntPayQueryResult.class); WxEntPayQueryRequest request = new WxEntPayQueryRequest(); - request.setAppid(this.config.getAppId()); - request.setMchId(this.config.getPartnerId()); + request.setAppid(getConfig().getAppId()); + request.setMchId(getConfig().getPartnerId()); request.setNonceStr(System.currentTimeMillis() + ""); request.setSign(this.createSign(request)); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyCoupon.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyCoupon.java index 7cea57ba..60b3f688 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyCoupon.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyCoupon.java @@ -13,47 +13,52 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; * 支付异步通知代金券详细 */ public class WxPayOrderNotifyCoupon implements Serializable { - /** - * @fields serialVersionUID - */ - private static final long serialVersionUID = -4165343733538156097L; - - @XStreamAlias("coupon_id") - private String couponId; - @XStreamAlias("coupon_type") - private String couponType; - @XStreamAlias("coupon_fee") - private Integer couponFee; - - public String getCouponId() { - return couponId; - } - public void setCouponId(String couponId) { - this.couponId = couponId; - } - public String getCouponType() { - return couponType; - } - public void setCouponType(String couponType) { - this.couponType = couponType; - } - public Integer getCouponFee() { - return couponFee; - } - public void setCouponFee(Integer couponFee) { - this.couponFee = couponFee; - } - - public Map toMap(int index){ - Map map = new HashMap<>(); - map.put("coupon_id_"+index, this.getCouponId()); - map.put("coupon_type_"+index, this.getCouponType()); - map.put("coupon_fee_"+index, this.getCouponFee()+""); - return map; - } - - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this,ToStringStyle.MULTI_LINE_STYLE); - } + /** + * @fields serialVersionUID + */ + private static final long serialVersionUID = -4165343733538156097L; + + @XStreamAlias("coupon_id") + private String couponId; + @XStreamAlias("coupon_type") + private String couponType; + @XStreamAlias("coupon_fee") + private Integer couponFee; + + public String getCouponId() { + return couponId; + } + + public void setCouponId(String couponId) { + this.couponId = couponId; + } + + public String getCouponType() { + return couponType; + } + + public void setCouponType(String couponType) { + this.couponType = couponType; + } + + public Integer getCouponFee() { + return couponFee; + } + + public void setCouponFee(Integer couponFee) { + this.couponFee = couponFee; + } + + public Map toMap(int index) { + Map map = new HashMap<>(); + map.put("coupon_id_" + index, this.getCouponId()); + map.put("coupon_type_" + index, this.getCouponType()); + map.put("coupon_fee_" + index, this.getCouponFee() + ""); + return map; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResponse.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResponse.java index 54f4fc56..a1313ea0 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResponse.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResponse.java @@ -1,6 +1,5 @@ package me.chanjar.weixin.mp.bean.pay; - import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamOmitField; @@ -9,53 +8,53 @@ import me.chanjar.weixin.common.util.xml.XStreamInitializer; @XStreamAlias("xml") public class WxPayOrderNotifyResponse { - @XStreamOmitField - private transient static final String FAIL ="FAIL"; - @XStreamOmitField - private transient static final String SUCCESS ="SUCCESS"; - - @XStreamAlias("return_code") - private String returnCode; - @XStreamAlias("return_msg") - private String returnMsg; - - - public String getReturnCode() { - return returnCode; - } - public void setReturnCode(String returnCode) { - this.returnCode = returnCode; - } - public String getReturnMsg() { - return returnMsg; - } - public void setReturnMsg(String returnMsg) { - this.returnMsg = returnMsg; - } - - - public WxPayOrderNotifyResponse() { - super(); - } - public WxPayOrderNotifyResponse(String returnCode, String returnMsg) { - super(); - this.returnCode = returnCode; - this.returnMsg = returnMsg; - } - - - public static String fail(String msg){ - WxPayOrderNotifyResponse response = new WxPayOrderNotifyResponse(FAIL,msg); - XStream xstream = XStreamInitializer.getInstance(); - xstream.autodetectAnnotations(true); - return xstream.toXML(response); - } - - - public static String success(String msg){ - WxPayOrderNotifyResponse response = new WxPayOrderNotifyResponse(SUCCESS,msg); - XStream xstream = XStreamInitializer.getInstance(); - xstream.autodetectAnnotations(true); - return xstream.toXML(response); - } + @XStreamOmitField + private transient static final String FAIL = "FAIL"; + @XStreamOmitField + private transient static final String SUCCESS = "SUCCESS"; + + @XStreamAlias("return_code") + private String returnCode; + @XStreamAlias("return_msg") + private String returnMsg; + + public String getReturnCode() { + return returnCode; + } + + public void setReturnCode(String returnCode) { + this.returnCode = returnCode; + } + + public String getReturnMsg() { + return returnMsg; + } + + public void setReturnMsg(String returnMsg) { + this.returnMsg = returnMsg; + } + + public WxPayOrderNotifyResponse() { + super(); + } + + public WxPayOrderNotifyResponse(String returnCode, String returnMsg) { + super(); + this.returnCode = returnCode; + this.returnMsg = returnMsg; + } + + public static String fail(String msg) { + WxPayOrderNotifyResponse response = new WxPayOrderNotifyResponse(FAIL, msg); + XStream xstream = XStreamInitializer.getInstance(); + xstream.autodetectAnnotations(true); + return xstream.toXML(response); + } + + public static String success(String msg) { + WxPayOrderNotifyResponse response = new WxPayOrderNotifyResponse(SUCCESS, msg); + XStream xstream = XStreamInitializer.getInstance(); + xstream.autodetectAnnotations(true); + return xstream.toXML(response); + } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResultConverter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResultConverter.java index 1f90f0b9..bdd440b9 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResultConverter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/WxPayOrderNotifyResultConverter.java @@ -24,107 +24,107 @@ import me.chanjar.weixin.mp.bean.pay.result.WxPayOrderNotifyResult; public class WxPayOrderNotifyResultConverter extends AbstractReflectionConverter { - public WxPayOrderNotifyResultConverter(Mapper mapper, ReflectionProvider reflectionProvider) { - super(mapper, reflectionProvider); - } - - @Override - @SuppressWarnings("rawtypes") - public boolean canConvert(Class type) { - return type.equals(WxPayOrderNotifyResult.class); - } - - @Override - public void marshal(Object original, HierarchicalStreamWriter writer, MarshallingContext context) { - super.marshal(original, writer, context); - WxPayOrderNotifyResult obj = (WxPayOrderNotifyResult) original; - List list = obj.getCouponList(); - if (list == null || list.size() == 0) { - return; - } - for (int i = 0; i < list.size(); i++) { - WxPayOrderNotifyCoupon coupon = list.get(i); - writer.startNode("coupon_id_" + i); - writer.setValue(coupon.getCouponId()); - writer.endNode(); - writer.startNode("coupon_type_" + i); - writer.setValue(coupon.getCouponType()); - writer.endNode(); - writer.startNode("coupon_fee_" + i); - writer.setValue(coupon.getCouponFee() + ""); - writer.endNode(); - } - } - - @Override - protected void marshallField(MarshallingContext context, Object newObj, Field field) { - if (field.getName().equals("couponList")) { - return; - } else { - super.marshallField(context, newObj, field); - } - } - - @Override - public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { - WxPayOrderNotifyResult obj = new WxPayOrderNotifyResult(); - - List fields = new ArrayList<>(Arrays.asList(obj.getClass().getDeclaredFields())); - fields.addAll(Arrays.asList(obj.getClass().getSuperclass().getDeclaredFields())); - Map fieldMap = getFieldMap(fields); - - List coupons = new ArrayList<>(10); - while (reader.hasMoreChildren()) { - reader.moveDown(); - if (fieldMap.containsKey(reader.getNodeName())) { - Field field = fieldMap.get(reader.getNodeName()); - setFieldValue(context, obj, field); - } else if (StringUtils.startsWith(reader.getNodeName(), "coupon_id_")) { - String id = (String) context.convertAnother(obj, String.class); - getIndex(coupons, reader.getNodeName()).setCouponId(id); - } else if (StringUtils.startsWith(reader.getNodeName(), "coupon_type_")) { - String type = (String) context.convertAnother(obj, String.class); - getIndex(coupons, reader.getNodeName()).setCouponType(type); - } else if (StringUtils.startsWith(reader.getNodeName(), "coupon_fee_")) { - Integer fee = (Integer) context.convertAnother(obj, Integer.class); - getIndex(coupons, reader.getNodeName()).setCouponFee(fee); - } - reader.moveUp(); - } - - obj.setCouponList(coupons); - return obj; - } - - private void setFieldValue(UnmarshallingContext context, WxPayOrderNotifyResult obj, Field field) { - Object val = context.convertAnother(obj, field.getType()); - try { - if (val != null) { - PropertyDescriptor pd = new PropertyDescriptor(field.getName(), obj.getClass()); - pd.getWriteMethod().invoke(obj, val); - } - } catch (Exception e) { - } - } - - private Map getFieldMap(List fields) { - Map fieldMap = Maps.uniqueIndex(fields, new Function() { - @Override - public String apply(Field field) { - if (field.isAnnotationPresent(XStreamAlias.class)) { - return field.getAnnotation(XStreamAlias.class).value(); - } - return field.getName(); - } - }); - return fieldMap; - } - - private WxPayOrderNotifyCoupon getIndex(List 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); - } + public WxPayOrderNotifyResultConverter(Mapper mapper, ReflectionProvider reflectionProvider) { + super(mapper, reflectionProvider); + } + + @Override + @SuppressWarnings("rawtypes") + public boolean canConvert(Class type) { + return type.equals(WxPayOrderNotifyResult.class); + } + + @Override + public void marshal(Object original, HierarchicalStreamWriter writer, MarshallingContext context) { + super.marshal(original, writer, context); + WxPayOrderNotifyResult obj = (WxPayOrderNotifyResult) original; + List list = obj.getCouponList(); + if (list == null || list.size() == 0) { + return; + } + for (int i = 0; i < list.size(); i++) { + WxPayOrderNotifyCoupon coupon = list.get(i); + writer.startNode("coupon_id_" + i); + writer.setValue(coupon.getCouponId()); + writer.endNode(); + writer.startNode("coupon_type_" + i); + writer.setValue(coupon.getCouponType()); + writer.endNode(); + writer.startNode("coupon_fee_" + i); + writer.setValue(coupon.getCouponFee() + ""); + writer.endNode(); + } + } + + @Override + protected void marshallField(MarshallingContext context, Object newObj, Field field) { + if (field.getName().equals("couponList")) { + return; + } else { + super.marshallField(context, newObj, field); + } + } + + @Override + public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { + WxPayOrderNotifyResult obj = new WxPayOrderNotifyResult(); + + List fields = new ArrayList<>(Arrays.asList(obj.getClass().getDeclaredFields())); + fields.addAll(Arrays.asList(obj.getClass().getSuperclass().getDeclaredFields())); + Map fieldMap = getFieldMap(fields); + + List coupons = new ArrayList<>(10); + while (reader.hasMoreChildren()) { + reader.moveDown(); + if (fieldMap.containsKey(reader.getNodeName())) { + Field field = fieldMap.get(reader.getNodeName()); + setFieldValue(context, obj, field); + } else if (StringUtils.startsWith(reader.getNodeName(), "coupon_id_")) { + String id = (String) context.convertAnother(obj, String.class); + getIndex(coupons, reader.getNodeName()).setCouponId(id); + } else if (StringUtils.startsWith(reader.getNodeName(), "coupon_type_")) { + String type = (String) context.convertAnother(obj, String.class); + getIndex(coupons, reader.getNodeName()).setCouponType(type); + } else if (StringUtils.startsWith(reader.getNodeName(), "coupon_fee_")) { + Integer fee = (Integer) context.convertAnother(obj, Integer.class); + getIndex(coupons, reader.getNodeName()).setCouponFee(fee); + } + reader.moveUp(); + } + + obj.setCouponList(coupons); + return obj; + } + + private void setFieldValue(UnmarshallingContext context, WxPayOrderNotifyResult obj, Field field) { + Object val = context.convertAnother(obj, field.getType()); + try { + if (val != null) { + PropertyDescriptor pd = new PropertyDescriptor(field.getName(), obj.getClass()); + pd.getWriteMethod().invoke(obj, val); + } + } catch (Exception e) { + } + } + + private Map getFieldMap(List fields) { + Map fieldMap = Maps.uniqueIndex(fields, new Function() { + @Override + public String apply(Field field) { + if (field.isAnnotationPresent(XStreamAlias.class)) { + return field.getAnnotation(XStreamAlias.class).value(); + } + return field.getName(); + } + }); + return fieldMap; + } + + private WxPayOrderNotifyCoupon getIndex(List 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/bean/pay/result/WxPayOrderNotifyResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java index 0a6815d8..60a25c19 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java @@ -388,7 +388,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializ @Override public Map toMap(){ Map resultMap = BeanUtils.xmlBean2Map(this); - if(this.getCouponCount() > 0){ + if(this.getCouponCount() != null && this.getCouponCount() > 0){ for (int i = 0; i < this.getCouponCount(); i++) { WxPayOrderNotifyCoupon coupon = couponList.get(i); resultMap.putAll(coupon.toMap(i)); From 80034e50869836ca3df8fd1c0e84a38b3fa16e32 Mon Sep 17 00:00:00 2001 From: aimilin6688 Date: Fri, 9 Dec 2016 17:00:16 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E4=B8=AD=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=85=83=E8=BD=AC=E5=88=86=EF=BC=8C=E5=88=86=E8=BD=AC?= =?UTF-8?q?=E5=85=83=E6=96=B9=E6=B3=95=EF=BC=8C=E6=96=B9=E4=BE=BF=E5=8D=95?= =?UTF-8?q?=E4=BD=8D=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weixin/mp/bean/pay/request/WxPayBaseRequest.java | 12 ++++++++++++ .../weixin/mp/bean/pay/result/WxPayBaseResult.java | 10 ++++++++++ .../mp/bean/pay/result/WxPayOrderNotifyResult.java | 10 ---------- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java index 9ede16ec..d6926d0e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java @@ -1,5 +1,7 @@ package me.chanjar.weixin.mp.bean.pay.request; +import java.math.BigDecimal; + import com.thoughtworks.xstream.annotations.XStreamAlias; import me.chanjar.weixin.common.util.ToStringUtils; @@ -110,6 +112,16 @@ public abstract class WxPayBaseRequest { public void setSign(String sign) { this.sign = sign; } + + /** + * 将单位为元转换为单位为分 + * + * @param yuan + * @return + */ + public static Integer yuanToFee(String yuan) { + return new BigDecimal(yuan).setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue(); + } @Override public String toString() { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java index d7455377..b719e333 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java @@ -1,5 +1,6 @@ package me.chanjar.weixin.mp.bean.pay.result; +import java.math.BigDecimal; import java.util.Map; import com.thoughtworks.xstream.annotations.XStreamAlias; @@ -146,6 +147,15 @@ public abstract class WxPayBaseResult { this.sign = sign; } + /** + * 将单位分转换成单位圆 + * @param fee + * @return + */ + public static String feeToYuan(Integer fee) { + return new BigDecimal(Double.valueOf(fee) / 100).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString(); + } + public Map toMap(){ return BeanUtils.xmlBean2Map(this); } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java index 60a25c19..eae67a36 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java @@ -397,16 +397,6 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializ return resultMap; } - - /** - * 将单位分转换成单位圆 - * @param fee - * @return - */ - public static String feeToYuan(Integer fee) { - return new BigDecimal(Double.valueOf(fee) / 100).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString(); - } - @Override public String toString() { return ToStringBuilder.reflectionToString(this,ToStringStyle.MULTI_LINE_STYLE); From fd9898eec9f8111cbfc7b484d5f46a7151a34056 Mon Sep 17 00:00:00 2001 From: aimilin6688 Date: Fri, 9 Dec 2016 17:00:16 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E4=B8=AD=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=85=83=E8=BD=AC=E5=88=86=EF=BC=8C=E5=88=86=E8=BD=AC?= =?UTF-8?q?=E5=85=83=E6=96=B9=E6=B3=95=EF=BC=8C=E6=96=B9=E4=BE=BF=E5=8D=95?= =?UTF-8?q?=E4=BD=8D=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weixin/mp/bean/pay/request/WxPayBaseRequest.java | 12 ++++++++++++ .../weixin/mp/bean/pay/result/WxPayBaseResult.java | 10 ++++++++++ .../mp/bean/pay/result/WxPayOrderNotifyResult.java | 11 ----------- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java index 9ede16ec..d6926d0e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java @@ -1,5 +1,7 @@ package me.chanjar.weixin.mp.bean.pay.request; +import java.math.BigDecimal; + import com.thoughtworks.xstream.annotations.XStreamAlias; import me.chanjar.weixin.common.util.ToStringUtils; @@ -110,6 +112,16 @@ public abstract class WxPayBaseRequest { public void setSign(String sign) { this.sign = sign; } + + /** + * 将单位为元转换为单位为分 + * + * @param yuan + * @return + */ + public static Integer yuanToFee(String yuan) { + return new BigDecimal(yuan).setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue(); + } @Override public String toString() { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java index d7455377..b719e333 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java @@ -1,5 +1,6 @@ package me.chanjar.weixin.mp.bean.pay.result; +import java.math.BigDecimal; import java.util.Map; import com.thoughtworks.xstream.annotations.XStreamAlias; @@ -146,6 +147,15 @@ public abstract class WxPayBaseResult { this.sign = sign; } + /** + * 将单位分转换成单位圆 + * @param fee + * @return + */ + public static String feeToYuan(Integer fee) { + return new BigDecimal(Double.valueOf(fee) / 100).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString(); + } + public Map toMap(){ return BeanUtils.xmlBean2Map(this); } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java index 60a25c19..3c782477 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java @@ -1,7 +1,6 @@ package me.chanjar.weixin.mp.bean.pay.result; import java.io.Serializable; -import java.math.BigDecimal; import java.util.List; import java.util.Map; @@ -397,16 +396,6 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializ return resultMap; } - - /** - * 将单位分转换成单位圆 - * @param fee - * @return - */ - public static String feeToYuan(Integer fee) { - return new BigDecimal(Double.valueOf(fee) / 100).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString(); - } - @Override public String toString() { return ToStringBuilder.reflectionToString(this,ToStringStyle.MULTI_LINE_STYLE); From 5224f342ed68f38c6745edb7e639fe73ef4fb178 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Mon, 12 Dec 2016 13:52:34 +0800 Subject: [PATCH 6/9] reformat code for PayService --- .../chanjar/weixin/mp/api/WxMpPayService.java | 58 +++---- .../mp/api/impl/WxMpPayServiceImpl.java | 157 ++++++++---------- 2 files changed, 96 insertions(+), 119 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java index 024ce4a8..afe888f8 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java @@ -30,9 +30,8 @@ public interface WxMpPayService { * 接口地址:https://api.mch.weixin.qq.com/pay/orderquery *
* - * @param transactionId 微信支付分配的商户号 + * @param transactionId 微信订单号 * @param outTradeNo 商户系统内部的订单号,当没提供transaction_id时需要传这个。 - * @throws WxErrorException */ WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxErrorException; @@ -49,7 +48,6 @@ public interface WxMpPayService { * * * @param outTradeNo 商户系统内部的订单号,当没提供transaction_id时需要传这个。 - * @throws WxErrorException */ WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorException; @@ -59,7 +57,6 @@ public interface WxMpPayService { * 接口地址:https://api.mch.weixin.qq.com/pay/unifiedorder * * @param request 请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置) - * @throws WxErrorException */ WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) throws WxErrorException; @@ -68,7 +65,6 @@ public interface WxMpPayService { * 详见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN * * @param request 请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置) - * @throws WxErrorException */ Map getPayInfo(WxPayUnifiedOrderRequest request) throws WxErrorException; @@ -93,7 +89,8 @@ public interface WxMpPayService { * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5 * 接口链接:https://api.mch.weixin.qq.com/pay/refundquery * - * 以下四个参数四选一 + * 以下四个参数四选一 + * * @param transactionId 微信订单号 * @param outTradeNo 商户订单号 * @param outRefundNo 商户退款单号 @@ -107,81 +104,85 @@ public interface WxMpPayService { * 详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7 */ WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException; - + /** * 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3) * * @param xmlbean Bean需要标记有XML注解,默认使用配置中的PartnerKey进行签名 - * @since 2.5.0 * @return 签名字符串 * @see #createSign(Map, String) + * @since 2.5.0 */ String createSign(Object xmlbean); - + /** * 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3) - * @param xmlbean Bean需要标记有XML注解 + * + * @param xmlbean Bean需要标记有XML注解 * @param signKey 签名Key * @return 签名字符串 * @see #createSign(Map, String) */ String createSign(Object xmlbean, String signKey); - + /** * 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3) - * @param prams 参数信息,默认使用配置中的PartnerKey进行签名 - * @param signKey 签名Key + * + * @param prams 参数信息,默认使用配置中的PartnerKey进行签名 * @return 签名字符串 * @see #createSign(Map, String) */ String createSign(Map prams); - - + + /** * 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3) - * @param prams 参数信息 + * + * @param prams 参数信息 * @param signKey 签名Key * @return 签名字符串 */ String createSign(Map prams, String signKey); - - + /** * 校验签名是否正确,默认使用配置中的PartnerKey进行签名 + * * @param xmlbean Bean需要标记有XML注解 * @return true - 签名校验成功,false - 签名校验失败 * @see #checkSign(Map, String) */ boolean checkSign(Object xmlbean); - + /** * 校验签名是否正确 + * * @param xmlbean Bean需要标记有XML注解 - * @param signKey 校验的签名Key + * @param signKey 校验的签名Key * @return true - 签名校验成功,false - 签名校验失败 * @see #checkSign(Map, String) */ boolean checkSign(Object xmlbean, String signKey); - + /** * 校验签名是否正确,默认使用配置中的PartnerKey进行签名 + * * @param prams 需要校验的参数Map * @return true - 签名校验成功,false - 签名校验失败 * @see #checkSign(Map, String) */ boolean checkSign(Map prams); - + /** * 校验签名是否正确 - * @param prams 需要校验的参数Map - * @param signKey 校验的签名Key + * + * @param params 需要校验的参数Map + * @param signKey 校验的签名Key * @return true - 签名校验成功,false - 签名校验失败 * @see #checkSign(Map, String) */ - boolean checkSign(Map prams, String signKey); - - + boolean checkSign(Map params, String signKey); + /** * 发送微信红包给个人用户 @@ -206,8 +207,9 @@ public interface WxMpPayService { * 是否需要证书 是(证书及使用说明详见商户证书) * 请求方式 POST * + * * @param mchBillNo 商户发放红包的商户订单号,比如10000098201411111234567890 - * @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3) + * @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3) */ WxPayRedpackQueryResult queryRedpack(String mchBillNo, File keyFile) throws WxErrorException; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java index 84655a86..f195f922 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java @@ -1,17 +1,16 @@ package me.chanjar.weixin.mp.api.impl; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.security.KeyStore; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; - -import javax.net.ssl.SSLContext; - +import com.thoughtworks.xstream.XStream; +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.common.util.xml.XStreamInitializer; +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.WxPayOrderNotifyResultConverter; +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.StringUtils; @@ -29,36 +28,12 @@ import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.thoughtworks.xstream.XStream; - -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.common.util.xml.XStreamInitializer; -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.WxPayOrderNotifyResultConverter; -import me.chanjar.weixin.mp.bean.pay.request.WxEntPayQueryRequest; -import me.chanjar.weixin.mp.bean.pay.request.WxEntPayRequest; -import me.chanjar.weixin.mp.bean.pay.request.WxPayOrderCloseRequest; -import me.chanjar.weixin.mp.bean.pay.request.WxPayOrderQueryRequest; -import me.chanjar.weixin.mp.bean.pay.request.WxPayRedpackQueryRequest; -import me.chanjar.weixin.mp.bean.pay.request.WxPayRefundQueryRequest; -import me.chanjar.weixin.mp.bean.pay.request.WxPayRefundRequest; -import me.chanjar.weixin.mp.bean.pay.request.WxPaySendRedpackRequest; -import me.chanjar.weixin.mp.bean.pay.request.WxPayUnifiedOrderRequest; -import me.chanjar.weixin.mp.bean.pay.result.WxEntPayQueryResult; -import me.chanjar.weixin.mp.bean.pay.result.WxEntPayResult; -import me.chanjar.weixin.mp.bean.pay.result.WxPayBaseResult; -import me.chanjar.weixin.mp.bean.pay.result.WxPayOrderCloseResult; -import me.chanjar.weixin.mp.bean.pay.result.WxPayOrderNotifyResult; -import me.chanjar.weixin.mp.bean.pay.result.WxPayOrderQueryResult; -import me.chanjar.weixin.mp.bean.pay.result.WxPayRedpackQueryResult; -import me.chanjar.weixin.mp.bean.pay.result.WxPayRefundQueryResult; -import me.chanjar.weixin.mp.bean.pay.result.WxPayRefundResult; -import me.chanjar.weixin.mp.bean.pay.result.WxPaySendRedpackResult; -import me.chanjar.weixin.mp.bean.pay.result.WxPayUnifiedOrderResult; +import javax.net.ssl.SSLContext; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyStore; +import java.util.*; /** * Created by Binary Wang on 2016/7/28. @@ -71,16 +46,16 @@ public class WxMpPayServiceImpl implements WxMpPayService { 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"}; - protected final Logger log = LoggerFactory.getLogger(this.getClass()); + private final Logger log = LoggerFactory.getLogger(this.getClass()); private WxMpService wxMpService; private WxMpConfigStorage config = null; public WxMpPayServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; } - - private WxMpConfigStorage getConfig(){ - if(config == null){ + + private WxMpConfigStorage getConfig() { + if (config == null) { this.config = wxMpService.getWxMpConfigStorage(); } return this.config; @@ -139,24 +114,24 @@ public class WxMpPayServiceImpl implements WxMpPayService { this.checkResult(result); return result; } - + private void checkResult(WxPayBaseResult result) throws WxErrorException { - //校验返回结果签名 - if(!checkSign(result.toMap())){ - log.debug("校验结果签名失败,参数:{}",result.toMap()); - throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("参数格式校验错误!").build()); - } - - //校验结果是否成功 + //校验返回结果签名 + if (!checkSign(result.toMap())) { + log.debug("校验结果签名失败,参数:{}", result.toMap()); + throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("参数格式校验错误!").build()); + } + + //校验结果是否成功 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()) - .build(); - log.debug("结果校验失败,参数:{},详细:{}",result.toMap(),error); + .setErrorMsg("返回代码: " + result.getReturnCode() + ", 返回信息: " + + result.getReturnMsg() + ", 结果代码: " + result.getResultCode() + ", 错误代码: " + + result.getErrCode() + ", 错误详情: " + result.getErrCodeDes()) + .build(); + log.debug("结果校验失败,参数:{},详细:{}", result.toMap(), error); throw new WxErrorException(error); } } @@ -166,7 +141,7 @@ 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()); } } @@ -181,16 +156,16 @@ public class WxMpPayServiceImpl implements WxMpPayService { log.trace("微信支付回调参数详细:{}", xmlData); XStream xstream = XStreamInitializer.getInstance(); xstream.processAnnotations(WxPayOrderNotifyResult.class); - xstream.registerConverter(new WxPayOrderNotifyResultConverter(xstream.getMapper(),xstream.getReflectionProvider())); - WxPayOrderNotifyResult result = (WxPayOrderNotifyResult) xstream.fromXML(xmlData); - log.debug("微信支付回调结果对象:{}",result); - this.checkResult(result); - return result; - }catch (WxErrorException e) { - log.error(e.getMessage(),e); - throw e; - }catch (Exception e) { - log.error(e.getMessage(),e); + xstream.registerConverter(new WxPayOrderNotifyResultConverter(xstream.getMapper(), xstream.getReflectionProvider())); + WxPayOrderNotifyResult result = (WxPayOrderNotifyResult) xstream.fromXML(xmlData); + log.debug("微信支付回调结果对象:{}", result); + this.checkResult(result); + return result; + } catch (WxErrorException e) { + log.error(e.getMessage(), e); + throw e; + } catch (Exception e) { + log.error(e.getMessage(), e); throw new WxErrorException(WxError.newBuilder().setErrorMsg("发生异常" + e.getMessage()).build()); } } @@ -245,20 +220,20 @@ public class WxMpPayServiceImpl implements WxMpPayService { this.checkResult(result); return result; } - + @Override public String createSign(Object xmlBean) { - return createSign(BeanUtils.xmlBean2Map(xmlBean),getConfig().getPartnerKey()); + return createSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey()); } - + @Override public String createSign(Object xmlBean, String signKey) { - return createSign(BeanUtils.xmlBean2Map(xmlBean), signKey); + return createSign(BeanUtils.xmlBean2Map(xmlBean), signKey); } - + @Override public String createSign(Map params) { - return createSign(params,getConfig().getPartnerKey()); + return createSign(params, getConfig().getPartnerKey()); } @Override @@ -276,28 +251,28 @@ public class WxMpPayServiceImpl implements WxMpPayService { toSign.append("key=" + signKey); return DigestUtils.md5Hex(toSign.toString()).toUpperCase(); } - + @Override public boolean checkSign(Object xmlBean) { - return checkSign(BeanUtils.xmlBean2Map(xmlBean) , getConfig().getPartnerKey()); + return checkSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey()); } - + @Override public boolean checkSign(Object xmlBean, String signKey) { - return checkSign(BeanUtils.xmlBean2Map(xmlBean) , signKey); + return checkSign(BeanUtils.xmlBean2Map(xmlBean), signKey); } - + @Override public boolean checkSign(Map params) { - return checkSign(params , getConfig().getPartnerKey()); + return checkSign(params, getConfig().getPartnerKey()); } - + @Override public boolean checkSign(Map params, String signKey) { - String sign = this.createSign(params , signKey); + String sign = this.createSign(params, signKey); return sign.equals(params.get("sign")); } - + @Override public WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxErrorException { @@ -366,16 +341,16 @@ public class WxMpPayServiceImpl implements WxMpPayService { request.setNotifyURL(getConfig().getNotifyURL()); request.setTradeType(getConfig().getTradeType()); request.setNonceStr(System.currentTimeMillis() + ""); - + checkParameters(request);//校验参数 - + request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/pay/unifiedorder"; - String xmlParam = xstream.toXML(request); - log.debug("微信统一下单接口,URL:{},参数:{}",url, xmlParam); + String xmlParam = xstream.toXML(request); + log.debug("微信统一下单接口,URL:{},参数:{}", url, xmlParam); String responseContent = this.executeRequest(url, xmlParam); - log.debug("微信统一下单接口,URL:{},结果:{}",url, responseContent); + log.debug("微信统一下单接口,URL:{},结果:{}", url, responseContent); WxPayUnifiedOrderResult result = (WxPayUnifiedOrderResult) xstream.fromXML(responseContent); this.checkResult(result); return result; @@ -385,7 +360,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { BeanUtils.checkRequiredFields(request); if (!ArrayUtils.contains(TRADE_TYPES, request.getTradeType())) { - throw new IllegalArgumentException("trade_type目前必须为" + Arrays.toString(TRADE_TYPES) + "其中之一,实际值:"+request.getTradeType()); + throw new IllegalArgumentException("trade_type目前必须为" + Arrays.toString(TRADE_TYPES) + "其中之一,实际值:" + request.getTradeType()); } if ("JSAPI".equals(request.getTradeType()) && request.getOpenid() == null) { From 28e7e454b90a7a10af701f340bc4926b8d83dcb6 Mon Sep 17 00:00:00 2001 From: aimilin6688 Date: Wed, 14 Dec 2016 11:41:37 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=94=AF=E4=BB=98?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E4=BF=A1=E6=81=AF=E4=B8=8D=E8=83=BD=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E8=AE=BE=E7=BD=AEBUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java index 84655a86..875d4e4e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java @@ -73,17 +73,13 @@ public class WxMpPayServiceImpl implements WxMpPayService { "REFUND_SOURCE_UNSETTLED_FUNDS"}; protected final Logger log = LoggerFactory.getLogger(this.getClass()); private WxMpService wxMpService; - private WxMpConfigStorage config = null; public WxMpPayServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; } private WxMpConfigStorage getConfig(){ - if(config == null){ - this.config = wxMpService.getWxMpConfigStorage(); - } - return this.config; + return wxMpService.getWxMpConfigStorage(); } @Override From d18e11cc4e25e335087e61977a64969d0bc17203 Mon Sep 17 00:00:00 2001 From: aimilin6688 Date: Wed, 14 Dec 2016 12:07:01 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E5=9B=9E=E5=A4=8D=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java index 875d4e4e..84655a86 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java @@ -73,13 +73,17 @@ public class WxMpPayServiceImpl implements WxMpPayService { "REFUND_SOURCE_UNSETTLED_FUNDS"}; protected final Logger log = LoggerFactory.getLogger(this.getClass()); private WxMpService wxMpService; + private WxMpConfigStorage config = null; public WxMpPayServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; } private WxMpConfigStorage getConfig(){ - return wxMpService.getWxMpConfigStorage(); + if(config == null){ + this.config = wxMpService.getWxMpConfigStorage(); + } + return this.config; } @Override From 95d87231fa2d02e405724be08336a907b338470a Mon Sep 17 00:00:00 2001 From: aimilin6688 Date: Wed, 14 Dec 2016 12:10:47 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dconfig=E4=B8=8D=E8=83=BD?= =?UTF-8?q?=E6=8C=87=E5=AE=9ABug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java index f195f922..4675946c 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java @@ -48,17 +48,13 @@ public class WxMpPayServiceImpl implements WxMpPayService { "REFUND_SOURCE_UNSETTLED_FUNDS"}; private final Logger log = LoggerFactory.getLogger(this.getClass()); private WxMpService wxMpService; - private WxMpConfigStorage config = null; public WxMpPayServiceImpl(WxMpService wxMpService) { this.wxMpService = wxMpService; } private WxMpConfigStorage getConfig() { - if (config == null) { - this.config = wxMpService.getWxMpConfigStorage(); - } - return this.config; + return wxMpService.getWxMpConfigStorage(); } @Override