فهرست منبع

微信支付逻辑修改

aimilin 8 سال پیش
والد
کامیت
8bb70942c3

+ 42 - 36
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;
-
 /**
  * <pre>
  * bean操作的一些工具类
@@ -21,6 +25,7 @@ import java.util.Map;
  * </pre>
  */
 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<String, String> xmlBean2Map(Object bean) {
-    Map<String, String> result = Maps.newHashMap();
-    List<Field> 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<String, String> xmlBean2Map(Object bean) {
+		Map<String, String> result = Maps.newHashMap();
+		List<Field> 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;
+	}
 }

+ 54 - 53
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<String, String> 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<String, String> 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<String, String> 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));
 

+ 48 - 43
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<String,String> toMap(int index){
-		Map<String,String> 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<String, String> toMap(int index) {
+    Map<String, String> 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);
+  }
 }

+ 49 - 50
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);
+  }
 }

+ 103 - 103
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<WxPayOrderNotifyCoupon> 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<Field> fields = new ArrayList<>(Arrays.asList(obj.getClass().getDeclaredFields()));
-		fields.addAll(Arrays.asList(obj.getClass().getSuperclass().getDeclaredFields()));
-		Map<String, Field> fieldMap = getFieldMap(fields);
-
-		List<WxPayOrderNotifyCoupon> 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<String, Field> getFieldMap(List<Field> fields) {
-		Map<String, Field> fieldMap = Maps.uniqueIndex(fields, new Function<Field, String>() {
-			@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<WxPayOrderNotifyCoupon> 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<WxPayOrderNotifyCoupon> 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<Field> fields = new ArrayList<>(Arrays.asList(obj.getClass().getDeclaredFields()));
+    fields.addAll(Arrays.asList(obj.getClass().getSuperclass().getDeclaredFields()));
+    Map<String, Field> fieldMap = getFieldMap(fields);
+
+    List<WxPayOrderNotifyCoupon> 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<String, Field> getFieldMap(List<Field> fields) {
+    Map<String, Field> fieldMap = Maps.uniqueIndex(fields, new Function<Field, String>() {
+      @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<WxPayOrderNotifyCoupon> 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);
+  }
 }

+ 1 - 1
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<String,String> toMap(){
 		Map<String,String> 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));