@@ -1,18 +1,22 @@ | |||||
package me.chanjar.weixin.common.util; | 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.Lists; | ||||
import com.google.common.collect.Maps; | import com.google.common.collect.Maps; | ||||
import com.thoughtworks.xstream.annotations.XStreamAlias; | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
import me.chanjar.weixin.common.annotation.Required; | import me.chanjar.weixin.common.annotation.Required; | ||||
import me.chanjar.weixin.common.bean.result.WxError; | import me.chanjar.weixin.common.bean.result.WxError; | ||||
import me.chanjar.weixin.common.exception.WxErrorException; | 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> | * <pre> | ||||
* bean操作的一些工具类 | * bean操作的一些工具类 | ||||
@@ -21,6 +25,7 @@ import java.util.Map; | |||||
* </pre> | * </pre> | ||||
*/ | */ | ||||
public class BeanUtils { | public class BeanUtils { | ||||
private static Logger log = LoggerFactory.getLogger(BeanUtils.class); | |||||
/** | /** | ||||
* 检查bean里标记为@Required的field是否为空,为空则抛异常 | * 检查bean里标记为@Required的field是否为空,为空则抛异常 | ||||
@@ -48,41 +53,42 @@ public class BeanUtils { | |||||
} | } | ||||
if (!nullFields.isEmpty()) { | 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; | |||||
} | |||||
} | } |
@@ -4,6 +4,7 @@ import me.chanjar.weixin.common.bean.WxAccessToken; | |||||
import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; | import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; | ||||
import javax.net.ssl.SSLContext; | import javax.net.ssl.SSLContext; | ||||
import java.io.File; | import java.io.File; | ||||
import java.util.concurrent.locks.Lock; | import java.util.concurrent.locks.Lock; | ||||
@@ -81,6 +82,23 @@ public interface WxMpConfigStorage { | |||||
String getPartnerId(); | String getPartnerId(); | ||||
String getPartnerKey(); | String getPartnerKey(); | ||||
/** | |||||
* 微信支付异步回掉地址,通知url必须为直接可访问的url,不能携带参数。 | |||||
* @since 2.5.0 | |||||
* @return | |||||
*/ | |||||
String getNotifyURL(); | |||||
/** | |||||
* 交易类型 | |||||
* <pre> | |||||
* JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付 | |||||
* </pre> | |||||
* @since 2.5.0 | |||||
* @return | |||||
*/ | |||||
String getTradeType(); | |||||
String getToken(); | String getToken(); | ||||
@@ -112,4 +130,5 @@ public interface WxMpConfigStorage { | |||||
* 是否自动刷新token | * 是否自动刷新token | ||||
*/ | */ | ||||
boolean autoRefreshToken(); | boolean autoRefreshToken(); | ||||
} | } |
@@ -20,6 +20,8 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { | |||||
protected volatile String secret; | protected volatile String secret; | ||||
protected volatile String partnerId; | protected volatile String partnerId; | ||||
protected volatile String partnerKey; | protected volatile String partnerKey; | ||||
protected volatile String notifyURL; | |||||
protected volatile String tradeType; | |||||
protected volatile String token; | protected volatile String token; | ||||
protected volatile String accessToken; | protected volatile String accessToken; | ||||
protected volatile String aesKey; | protected volatile String aesKey; | ||||
@@ -267,8 +269,25 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { | |||||
public void setPartnerKey(String partnerKey) { | public void setPartnerKey(String partnerKey) { | ||||
this.partnerKey = 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() { | public File getTmpDirFile() { | ||||
return this.tmpDirFile; | return this.tmpDirFile; | ||||
} | } | ||||
@@ -1,7 +1,6 @@ | |||||
package me.chanjar.weixin.mp.api; | package me.chanjar.weixin.mp.api; | ||||
import me.chanjar.weixin.common.exception.WxErrorException; | 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.WxEntPayRequest; | ||||
import me.chanjar.weixin.mp.bean.pay.request.WxPayRefundRequest; | 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.WxPaySendRedpackRequest; | ||||
@@ -31,9 +30,8 @@ public interface WxMpPayService { | |||||
* 接口地址:https://api.mch.weixin.qq.com/pay/orderquery | * 接口地址:https://api.mch.weixin.qq.com/pay/orderquery | ||||
* </pre> | * </pre> | ||||
* | * | ||||
* @param transactionId 微信支付分配的商户号 | |||||
* @param transactionId 微信订单号 | |||||
* @param outTradeNo 商户系统内部的订单号,当没提供transaction_id时需要传这个。 | * @param outTradeNo 商户系统内部的订单号,当没提供transaction_id时需要传这个。 | ||||
* @throws WxErrorException | |||||
*/ | */ | ||||
WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxErrorException; | WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxErrorException; | ||||
@@ -50,7 +48,6 @@ public interface WxMpPayService { | |||||
* </pre> | * </pre> | ||||
* | * | ||||
* @param outTradeNo 商户系统内部的订单号,当没提供transaction_id时需要传这个。 | * @param outTradeNo 商户系统内部的订单号,当没提供transaction_id时需要传这个。 | ||||
* @throws WxErrorException | |||||
*/ | */ | ||||
WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorException; | WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorException; | ||||
@@ -60,7 +57,6 @@ public interface WxMpPayService { | |||||
* 接口地址:https://api.mch.weixin.qq.com/pay/unifiedorder | * 接口地址:https://api.mch.weixin.qq.com/pay/unifiedorder | ||||
* | * | ||||
* @param request 请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置) | * @param request 请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置) | ||||
* @throws WxErrorException | |||||
*/ | */ | ||||
WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) throws WxErrorException; | WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) throws WxErrorException; | ||||
@@ -69,7 +65,6 @@ public interface WxMpPayService { | |||||
* 详见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN | * 详见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN | ||||
* | * | ||||
* @param request 请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置) | * @param request 请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置) | ||||
* @throws WxErrorException | |||||
*/ | */ | ||||
Map<String, String> getPayInfo(WxPayUnifiedOrderRequest request) throws WxErrorException; | Map<String, String> getPayInfo(WxPayUnifiedOrderRequest request) throws WxErrorException; | ||||
@@ -81,7 +76,7 @@ public interface WxMpPayService { | |||||
* </pre> | * </pre> | ||||
* | * | ||||
* @param request 请求对象 | * @param request 请求对象 | ||||
* @param keyFile 证书文件对象 | |||||
* @param keyFile 证书文件对象(即apiclient_cert.p12 商户证书文件,详细参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3) | |||||
* @return 退款操作结果 | * @return 退款操作结果 | ||||
*/ | */ | ||||
WxPayRefundResult refund(WxPayRefundRequest request, File keyFile) throws WxErrorException; | WxPayRefundResult refund(WxPayRefundRequest request, File keyFile) throws WxErrorException; | ||||
@@ -94,7 +89,8 @@ public interface WxMpPayService { | |||||
* 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5 | * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5 | ||||
* 接口链接:https://api.mch.weixin.qq.com/pay/refundquery | * 接口链接:https://api.mch.weixin.qq.com/pay/refundquery | ||||
* </pre> | * </pre> | ||||
* 以下四个参数四选一 | |||||
* 以下四个参数四选一 | |||||
* | |||||
* @param transactionId 微信订单号 | * @param transactionId 微信订单号 | ||||
* @param outTradeNo 商户订单号 | * @param outTradeNo 商户订单号 | ||||
* @param outRefundNo 商户退款单号 | * @param outRefundNo 商户退款单号 | ||||
@@ -107,15 +103,86 @@ public interface WxMpPayService { | |||||
* 读取支付结果通知 | * 读取支付结果通知 | ||||
* 详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7 | * 详见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; | |||||
/** | /** | ||||
* <pre> | |||||
* 计算Map键值对是否和签名相符, | |||||
* 按照字段名的 ASCII 码从小到大排序(字典序)后,使用 URL 键值对的 格式(即 key1=value1&key2=value2...)拼接成字符串 | |||||
* </pre> | |||||
* 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3) | |||||
* | |||||
* @param xmlbean Bean需要标记有XML注解,默认使用配置中的PartnerKey进行签名 | |||||
* @return 签名字符串 | |||||
* @see #createSign(Map, String) | |||||
* @since 2.5.0 | |||||
*/ | */ | ||||
boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature); | |||||
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进行签名 | |||||
* @return 签名字符串 | |||||
* @see #createSign(Map, String) | |||||
*/ | |||||
String createSign(Map<String, String> 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<String, String> 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 | |||||
* @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<String, String> prams); | |||||
/** | |||||
* 校验签名是否正确 | |||||
* | |||||
* @param params 需要校验的参数Map | |||||
* @param signKey 校验的签名Key | |||||
* @return true - 签名校验成功,false - 签名校验失败 | |||||
* @see #checkSign(Map, String) | |||||
*/ | |||||
boolean checkSign(Map<String, String> params, String signKey); | |||||
/** | /** | ||||
* 发送微信红包给个人用户 | * 发送微信红包给个人用户 | ||||
@@ -128,7 +195,7 @@ public interface WxMpPayService { | |||||
* </pre> | * </pre> | ||||
* | * | ||||
* @param request 请求对象 | * @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; | WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File keyFile) throws WxErrorException; | ||||
@@ -140,8 +207,9 @@ public interface WxMpPayService { | |||||
* 是否需要证书 是(证书及使用说明详见商户证书) | * 是否需要证书 是(证书及使用说明详见商户证书) | ||||
* 请求方式 POST | * 请求方式 POST | ||||
* </pre> | * </pre> | ||||
* | |||||
* @param mchBillNo 商户发放红包的商户订单号,比如10000098201411111234567890 | * @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; | WxPayRedpackQueryResult queryRedpack(String mchBillNo, File keyFile) throws WxErrorException; | ||||
@@ -156,7 +224,7 @@ public interface WxMpPayService { | |||||
* </pre> | * </pre> | ||||
* | * | ||||
* @param request 请求对象 | * @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; | WxEntPayResult entPay(WxEntPayRequest request, File keyFile) throws WxErrorException; | ||||
@@ -169,7 +237,7 @@ public interface WxMpPayService { | |||||
* </pre> | * </pre> | ||||
* | * | ||||
* @param partnerTradeNo 商户订单号 | * @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; | WxEntPayQueryResult queryEntPay(String partnerTradeNo, File keyFile) throws WxErrorException; | ||||
@@ -5,7 +5,6 @@ import me.chanjar.weixin.common.exception.WxErrorException; | |||||
import me.chanjar.weixin.mp.api.WxMpMenuService; | import me.chanjar.weixin.mp.api.WxMpMenuService; | ||||
import me.chanjar.weixin.mp.api.WxMpService; | import me.chanjar.weixin.mp.api.WxMpService; | ||||
import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult; | import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult; | ||||
import me.chanjar.weixin.mp.bean.menu.WxMpSelfMenuInfo; | |||||
import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
@@ -5,9 +5,10 @@ import me.chanjar.weixin.common.bean.result.WxError; | |||||
import me.chanjar.weixin.common.exception.WxErrorException; | import me.chanjar.weixin.common.exception.WxErrorException; | ||||
import me.chanjar.weixin.common.util.BeanUtils; | import me.chanjar.weixin.common.util.BeanUtils; | ||||
import me.chanjar.weixin.common.util.xml.XStreamInitializer; | 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.WxMpPayService; | ||||
import me.chanjar.weixin.mp.api.WxMpService; | import me.chanjar.weixin.mp.api.WxMpService; | ||||
import me.chanjar.weixin.mp.bean.pay.WxPayJsSDKCallback; | |||||
import me.chanjar.weixin.mp.bean.pay.WxPayOrderNotifyResultConverter; | |||||
import me.chanjar.weixin.mp.bean.pay.request.*; | import me.chanjar.weixin.mp.bean.pay.request.*; | ||||
import me.chanjar.weixin.mp.bean.pay.result.*; | import me.chanjar.weixin.mp.bean.pay.result.*; | ||||
import org.apache.commons.codec.digest.DigestUtils; | import org.apache.commons.codec.digest.DigestUtils; | ||||
@@ -45,13 +46,17 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
private static final String[] TRADE_TYPES = new String[]{"JSAPI", "NATIVE", "APP"}; | private static final String[] TRADE_TYPES = new String[]{"JSAPI", "NATIVE", "APP"}; | ||||
private static final String[] REFUND_ACCOUNT = new String[]{"REFUND_SOURCE_RECHARGE_FUNDS", | private static final String[] REFUND_ACCOUNT = new String[]{"REFUND_SOURCE_RECHARGE_FUNDS", | ||||
"REFUND_SOURCE_UNSETTLED_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 WxMpService wxMpService; | ||||
public WxMpPayServiceImpl(WxMpService wxMpService) { | public WxMpPayServiceImpl(WxMpService wxMpService) { | ||||
this.wxMpService = wxMpService; | this.wxMpService = wxMpService; | ||||
} | } | ||||
private WxMpConfigStorage getConfig() { | |||||
return wxMpService.getWxMpConfigStorage(); | |||||
} | |||||
@Override | @Override | ||||
public WxPayRefundResult refund(WxPayRefundRequest request, File keyFile) | public WxPayRefundResult refund(WxPayRefundRequest request, File keyFile) | ||||
throws WxErrorException { | throws WxErrorException { | ||||
@@ -61,13 +66,12 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
xstream.processAnnotations(WxPayRefundRequest.class); | xstream.processAnnotations(WxPayRefundRequest.class); | ||||
xstream.processAnnotations(WxPayRefundResult.class); | xstream.processAnnotations(WxPayRefundResult.class); | ||||
request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); | |||||
String partnerId = this.wxMpService.getWxMpConfigStorage().getPartnerId(); | |||||
request.setAppid(getConfig().getAppId()); | |||||
String partnerId = getConfig().getPartnerId(); | |||||
request.setMchId(partnerId); | request.setMchId(partnerId); | ||||
request.setNonceStr(System.currentTimeMillis() + ""); | request.setNonceStr(System.currentTimeMillis() + ""); | ||||
request.setOpUserId(partnerId); | 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 url = PAY_BASE_URL + "/secapi/pay/refund"; | ||||
String responseContent = this.executeRequestWithKeyFile(url, keyFile, xstream.toXML(request), partnerId); | String responseContent = this.executeRequestWithKeyFile(url, keyFile, xstream.toXML(request), partnerId); | ||||
@@ -93,13 +97,10 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
request.setOutRefundNo(StringUtils.trimToNull(outRefundNo)); | request.setOutRefundNo(StringUtils.trimToNull(outRefundNo)); | ||||
request.setRefundId(StringUtils.trimToNull(refundId)); | request.setRefundId(StringUtils.trimToNull(refundId)); | ||||
request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); | |||||
request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); | |||||
request.setAppid(getConfig().getAppId()); | |||||
request.setMchId(getConfig().getPartnerId()); | |||||
request.setNonceStr(System.currentTimeMillis() + ""); | 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"; | String url = PAY_BASE_URL + "/pay/refundquery"; | ||||
@@ -110,14 +111,24 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
return result; | return result; | ||||
} | } | ||||
private void checkResult(WxPayBaseResult result) throws WxErrorException { | 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()) | if (!"SUCCESS".equalsIgnoreCase(result.getReturnCode()) | ||||
|| !"SUCCESS".equalsIgnoreCase(result.getResultCode())) { | || !"SUCCESS".equalsIgnoreCase(result.getResultCode())) { | ||||
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1) | |||||
WxError error = WxError.newBuilder().setErrorCode(-1) | |||||
.setErrorMsg("返回代码: " + result.getReturnCode() + ", 返回信息: " | .setErrorMsg("返回代码: " + result.getReturnCode() + ", 返回信息: " | ||||
+ result.getReturnMsg() + ", 结果代码: " + result.getResultCode() + ", 错误代码: " | + result.getReturnMsg() + ", 结果代码: " + result.getResultCode() + ", 错误代码: " | ||||
+ result.getErrCode() + ", 错误详情: " + result.getErrCodeDes()) | + result.getErrCode() + ", 错误详情: " + result.getErrCodeDes()) | ||||
.build()); | |||||
.build(); | |||||
log.debug("结果校验失败,参数:{},详细:{}", result.toMap(), error); | |||||
throw new WxErrorException(error); | |||||
} | } | ||||
} | } | ||||
@@ -126,7 +137,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
if (StringUtils.isNotBlank(request.getRefundAccount())) { | if (StringUtils.isNotBlank(request.getRefundAccount())) { | ||||
if (!ArrayUtils.contains(REFUND_ACCOUNT, 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()); | |||||
} | } | ||||
} | } | ||||
@@ -136,23 +147,25 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
} | } | ||||
@Override | @Override | ||||
public WxPayJsSDKCallback getJSSDKCallbackData(String xmlData) throws WxErrorException { | |||||
public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException { | |||||
try { | try { | ||||
log.trace("微信支付回调参数详细:{}", xmlData); | |||||
XStream xstream = XStreamInitializer.getInstance(); | XStream xstream = XStreamInitializer.getInstance(); | ||||
xstream.alias("xml", WxPayJsSDKCallback.class); | |||||
return (WxPayJsSDKCallback) xstream.fromXML(xmlData); | |||||
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) { | } catch (Exception e) { | ||||
e.printStackTrace(); | |||||
log.error(e.getMessage(), e); | |||||
throw new WxErrorException(WxError.newBuilder().setErrorMsg("发生异常" + e.getMessage()).build()); | throw new WxErrorException(WxError.newBuilder().setErrorMsg("发生异常" + e.getMessage()).build()); | ||||
} | } | ||||
} | } | ||||
@Override | |||||
public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, | |||||
String signature) { | |||||
return signature.equals(this.createSign(kvm, | |||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey())); | |||||
} | |||||
@Override | @Override | ||||
public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File keyFile) | public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File keyFile) | ||||
@@ -161,14 +174,11 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
xstream.processAnnotations(WxPaySendRedpackRequest.class); | xstream.processAnnotations(WxPaySendRedpackRequest.class); | ||||
xstream.processAnnotations(WxPaySendRedpackResult.class); | xstream.processAnnotations(WxPaySendRedpackResult.class); | ||||
request.setWxAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); | |||||
String mchId = this.wxMpService.getWxMpConfigStorage().getPartnerId(); | |||||
request.setWxAppid(getConfig().getAppId()); | |||||
String mchId = getConfig().getPartnerId(); | |||||
request.setMchId(mchId); | request.setMchId(mchId); | ||||
request.setNonceStr(System.currentTimeMillis() + ""); | 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"; | String url = PAY_BASE_URL + "/mmpaymkttransfers/sendredpack"; | ||||
if (request.getAmtType() != null) { | if (request.getAmtType() != null) { | ||||
@@ -177,8 +187,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
} | } | ||||
String responseContent = this.executeRequestWithKeyFile(url, keyFile, xstream.toXML(request), mchId); | 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); | this.checkResult(result); | ||||
return result; | return result; | ||||
} | } | ||||
@@ -193,13 +202,12 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
request.setMchBillNo(mchBillNo); | request.setMchBillNo(mchBillNo); | ||||
request.setBillType("MCHT"); | request.setBillType("MCHT"); | ||||
request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); | |||||
String mchId = this.wxMpService.getWxMpConfigStorage().getPartnerId(); | |||||
request.setAppid(getConfig().getAppId()); | |||||
String mchId = getConfig().getPartnerId(); | |||||
request.setMchId(mchId); | request.setMchId(mchId); | ||||
request.setNonceStr(System.currentTimeMillis() + ""); | request.setNonceStr(System.currentTimeMillis() + ""); | ||||
String sign = this.createSign(BeanUtils.xmlBean2Map(request), | |||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey()); | |||||
String sign = this.createSign(request); | |||||
request.setSign(sign); | request.setSign(sign); | ||||
String url = PAY_BASE_URL + "/mmpaymkttransfers/gethbinfo"; | String url = PAY_BASE_URL + "/mmpaymkttransfers/gethbinfo"; | ||||
@@ -209,30 +217,59 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
return result; | return result; | ||||
} | } | ||||
/** | |||||
* 微信公众号支付签名算法(详见: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<String, String> packageParams, String signKey) { | |||||
SortedMap<String, String> sortedMap = new TreeMap<>(packageParams); | |||||
@Override | |||||
public String createSign(Object xmlBean) { | |||||
return createSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey()); | |||||
} | |||||
@Override | |||||
public String createSign(Object xmlBean, String signKey) { | |||||
return createSign(BeanUtils.xmlBean2Map(xmlBean), signKey); | |||||
} | |||||
@Override | |||||
public String createSign(Map<String, String> params) { | |||||
return createSign(params, getConfig().getPartnerKey()); | |||||
} | |||||
@Override | |||||
public String createSign(Map<String, String> params, String signKey) { | |||||
SortedMap<String, String> sortedMap = new TreeMap<>(params); | |||||
StringBuilder toSign = new StringBuilder(); | StringBuilder toSign = new StringBuilder(); | ||||
for (String key : sortedMap.keySet()) { | 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 + "=" + value + "&"); | ||||
} | } | ||||
} | } | ||||
toSign.append("key=" + signKey); | toSign.append("key=" + signKey); | ||||
return DigestUtils.md5Hex(toSign.toString()).toUpperCase(); | return DigestUtils.md5Hex(toSign.toString()).toUpperCase(); | ||||
} | } | ||||
@Override | |||||
public boolean checkSign(Object xmlBean) { | |||||
return checkSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey()); | |||||
} | |||||
@Override | |||||
public boolean checkSign(Object xmlBean, String signKey) { | |||||
return checkSign(BeanUtils.xmlBean2Map(xmlBean), signKey); | |||||
} | |||||
@Override | |||||
public boolean checkSign(Map<String, String> params) { | |||||
return checkSign(params, getConfig().getPartnerKey()); | |||||
} | |||||
@Override | |||||
public boolean checkSign(Map<String, String> params, String signKey) { | |||||
String sign = this.createSign(params, signKey); | |||||
return sign.equals(params.get("sign")); | |||||
} | |||||
@Override | @Override | ||||
public WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxErrorException { | public WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxErrorException { | ||||
if ((StringUtils.isBlank(transactionId) && StringUtils.isBlank(outTradeNo)) || | if ((StringUtils.isBlank(transactionId) && StringUtils.isBlank(outTradeNo)) || | ||||
@@ -247,13 +284,10 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
WxPayOrderQueryRequest request = new WxPayOrderQueryRequest(); | WxPayOrderQueryRequest request = new WxPayOrderQueryRequest(); | ||||
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); | request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); | ||||
request.setTransactionId(StringUtils.trimToNull(transactionId)); | request.setTransactionId(StringUtils.trimToNull(transactionId)); | ||||
request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); | |||||
request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); | |||||
request.setAppid(getConfig().getAppId()); | |||||
request.setMchId(getConfig().getPartnerId()); | |||||
request.setNonceStr(System.currentTimeMillis() + ""); | 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"; | String url = PAY_BASE_URL + "/pay/orderquery"; | ||||
@@ -276,13 +310,10 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
WxPayOrderCloseRequest request = new WxPayOrderCloseRequest(); | WxPayOrderCloseRequest request = new WxPayOrderCloseRequest(); | ||||
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); | request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); | ||||
request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); | |||||
request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); | |||||
request.setAppid(getConfig().getAppId()); | |||||
request.setMchId(getConfig().getPartnerId()); | |||||
request.setNonceStr(System.currentTimeMillis() + ""); | 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"; | String url = PAY_BASE_URL + "/pay/closeorder"; | ||||
@@ -296,25 +327,27 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
@Override | @Override | ||||
public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) | public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) | ||||
throws WxErrorException { | throws WxErrorException { | ||||
checkParameters(request); | |||||
XStream xstream = XStreamInitializer.getInstance(); | XStream xstream = XStreamInitializer.getInstance(); | ||||
xstream.processAnnotations(WxPayUnifiedOrderRequest.class); | xstream.processAnnotations(WxPayUnifiedOrderRequest.class); | ||||
xstream.processAnnotations(WxPayUnifiedOrderResult.class); | xstream.processAnnotations(WxPayUnifiedOrderResult.class); | ||||
request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); | |||||
request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); | |||||
request.setAppid(getConfig().getAppId()); | |||||
request.setMchId(getConfig().getPartnerId()); | |||||
request.setNotifyURL(getConfig().getNotifyURL()); | |||||
request.setTradeType(getConfig().getTradeType()); | |||||
request.setNonceStr(System.currentTimeMillis() + ""); | request.setNonceStr(System.currentTimeMillis() + ""); | ||||
String sign = this.createSign(BeanUtils.xmlBean2Map(request), | |||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey()); | |||||
request.setSign(sign); | |||||
checkParameters(request);//校验参数 | |||||
request.setSign(this.createSign(request)); | |||||
String url = PAY_BASE_URL + "/pay/unifiedorder"; | 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); | this.checkResult(result); | ||||
return result; | return result; | ||||
} | } | ||||
@@ -323,7 +356,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
BeanUtils.checkRequiredFields(request); | BeanUtils.checkRequiredFields(request); | ||||
if (!ArrayUtils.contains(TRADE_TYPES, request.getTradeType())) { | 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) { | if ("JSAPI".equals(request.getTradeType()) && request.getOpenid() == null) { | ||||
@@ -345,7 +378,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
} | } | ||||
Map<String, String> payInfo = new HashMap<>(); | Map<String, String> payInfo = new HashMap<>(); | ||||
payInfo.put("appId", this.wxMpService.getWxMpConfigStorage().getAppId()); | |||||
payInfo.put("appId", getConfig().getAppId()); | |||||
// 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 | // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 | ||||
payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); | payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); | ||||
payInfo.put("nonceStr", System.currentTimeMillis() + ""); | payInfo.put("nonceStr", System.currentTimeMillis() + ""); | ||||
@@ -354,9 +387,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
if ("NATIVE".equals(request.getTradeType())) { | if ("NATIVE".equals(request.getTradeType())) { | ||||
payInfo.put("codeUrl", unifiedOrderResult.getCodeURL()); | 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; | return payInfo; | ||||
} | } | ||||
@@ -368,12 +399,10 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
xstream.processAnnotations(WxEntPayRequest.class); | xstream.processAnnotations(WxEntPayRequest.class); | ||||
xstream.processAnnotations(WxEntPayResult.class); | xstream.processAnnotations(WxEntPayResult.class); | ||||
request.setMchAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); | |||||
request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); | |||||
request.setMchAppid(getConfig().getAppId()); | |||||
request.setMchId(getConfig().getPartnerId()); | |||||
request.setNonceStr(System.currentTimeMillis() + ""); | 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"; | String url = PAY_BASE_URL + "/mmpaymkttransfers/promotion/transfers"; | ||||
@@ -390,12 +419,10 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
xstream.processAnnotations(WxEntPayQueryResult.class); | xstream.processAnnotations(WxEntPayQueryResult.class); | ||||
WxEntPayQueryRequest request = new WxEntPayQueryRequest(); | WxEntPayQueryRequest request = new WxEntPayQueryRequest(); | ||||
request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId()); | |||||
request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId()); | |||||
request.setAppid(getConfig().getAppId()); | |||||
request.setMchId(getConfig().getPartnerId()); | |||||
request.setNonceStr(System.currentTimeMillis() + ""); | 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"; | String url = PAY_BASE_URL + "/mmpaymkttransfers/gettransferinfo"; | ||||
@@ -456,5 +483,4 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg(e.getMessage()).build(), e); | throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg(e.getMessage()).build(), e); | ||||
} | } | ||||
} | } | ||||
} | } |
@@ -62,7 +62,8 @@ public abstract class WxMpXmlOutMessage implements Serializable { | |||||
this.msgType = msgType; | this.msgType = msgType; | ||||
} | } | ||||
public String toXml() { | |||||
@SuppressWarnings("unchecked") | |||||
public String toXml() { | |||||
return XStreamTransformer.toXml((Class<WxMpXmlOutMessage>) this.getClass(), this); | return XStreamTransformer.toXml((Class<WxMpXmlOutMessage>) this.getClass(), this); | ||||
} | } | ||||
@@ -1,267 +0,0 @@ | |||||
package me.chanjar.weixin.mp.bean.pay; | |||||
import me.chanjar.weixin.common.util.ToStringUtils; | |||||
import java.io.Serializable; | |||||
/** | |||||
* <pre> | |||||
* 订单支付状态回调 | |||||
* 支付结果通知(详见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); | |||||
} | |||||
} |
@@ -0,0 +1,64 @@ | |||||
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<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); | |||||
} | |||||
} |
@@ -0,0 +1,60 @@ | |||||
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); | |||||
} | |||||
} |
@@ -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<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); | |||||
} | |||||
} |
@@ -30,7 +30,6 @@ public class WxEntPayQueryRequest extends WxPayBaseRequest { | |||||
* 微信支付分配的商户号 | * 微信支付分配的商户号 | ||||
* </pre> | * </pre> | ||||
*/ | */ | ||||
@SuppressWarnings("hiding") | |||||
@XStreamAlias("mchid") | @XStreamAlias("mchid") | ||||
private String mchId; | private String mchId; | ||||
@@ -1,5 +1,7 @@ | |||||
package me.chanjar.weixin.mp.bean.pay.request; | package me.chanjar.weixin.mp.bean.pay.request; | ||||
import java.math.BigDecimal; | |||||
import com.thoughtworks.xstream.annotations.XStreamAlias; | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
import me.chanjar.weixin.common.util.ToStringUtils; | import me.chanjar.weixin.common.util.ToStringUtils; | ||||
@@ -71,6 +73,10 @@ public abstract class WxPayBaseRequest { | |||||
return this.appid; | return this.appid; | ||||
} | } | ||||
/** | |||||
* 如果配置中已经设置,可以不设置值 | |||||
* @param appid | |||||
*/ | |||||
public void setAppid(String appid) { | public void setAppid(String appid) { | ||||
this.appid = appid; | this.appid = appid; | ||||
} | } | ||||
@@ -79,6 +85,10 @@ public abstract class WxPayBaseRequest { | |||||
return this.mchId; | return this.mchId; | ||||
} | } | ||||
/** | |||||
* 如果配置中已经设置,可以不设置值 | |||||
* @param mchId | |||||
*/ | |||||
public void setMchId(String mchId) { | public void setMchId(String mchId) { | ||||
this.mchId = mchId; | this.mchId = mchId; | ||||
} | } | ||||
@@ -87,6 +97,10 @@ public abstract class WxPayBaseRequest { | |||||
return this.nonceStr; | return this.nonceStr; | ||||
} | } | ||||
/** | |||||
* 默认采用时间戳为随机字符串,可以不设置 | |||||
* @param nonceStr | |||||
*/ | |||||
public void setNonceStr(String nonceStr) { | public void setNonceStr(String nonceStr) { | ||||
this.nonceStr = nonceStr; | this.nonceStr = nonceStr; | ||||
} | } | ||||
@@ -98,6 +112,16 @@ public abstract class WxPayBaseRequest { | |||||
public void setSign(String sign) { | public void setSign(String sign) { | ||||
this.sign = 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 | @Override | ||||
public String toString() { | public String toString() { | ||||
@@ -360,6 +360,10 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest { | |||||
return this.notifyURL; | return this.notifyURL; | ||||
} | } | ||||
/** | |||||
* 如果配置中已经设置,可以不设置值 | |||||
* @param notifyURL | |||||
*/ | |||||
public void setNotifyURL(String notifyURL) { | public void setNotifyURL(String notifyURL) { | ||||
this.notifyURL = notifyURL; | this.notifyURL = notifyURL; | ||||
} | } | ||||
@@ -368,6 +372,10 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest { | |||||
return this.tradeType; | return this.tradeType; | ||||
} | } | ||||
/** | |||||
* 如果配置中已经设置,可以不设置值 | |||||
* @param tradeType 交易类型 | |||||
*/ | |||||
public void setTradeType(String tradeType) { | public void setTradeType(String tradeType) { | ||||
this.tradeType = tradeType; | this.tradeType = tradeType; | ||||
} | } | ||||
@@ -1,6 +1,11 @@ | |||||
package me.chanjar.weixin.mp.bean.pay.result; | package me.chanjar.weixin.mp.bean.pay.result; | ||||
import java.math.BigDecimal; | |||||
import java.util.Map; | |||||
import com.thoughtworks.xstream.annotations.XStreamAlias; | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
import me.chanjar.weixin.common.util.BeanUtils; | |||||
import me.chanjar.weixin.common.util.ToStringUtils; | import me.chanjar.weixin.common.util.ToStringUtils; | ||||
/** | /** | ||||
@@ -141,4 +146,17 @@ public abstract class WxPayBaseResult { | |||||
public void setSign(String sign) { | public void setSign(String sign) { | ||||
this.sign = sign; | 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<String,String> toMap(){ | |||||
return BeanUtils.xmlBean2Map(this); | |||||
} | |||||
} | } |
@@ -0,0 +1,403 @@ | |||||
package me.chanjar.weixin.mp.bean.pay.result; | |||||
import java.io.Serializable; | |||||
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; | |||||
/** | |||||
* <pre> | |||||
* 设备号 | |||||
* device_info | |||||
* 否 | |||||
* String(32) | |||||
* 013467007045764 | |||||
* 微信支付分配的终端设备号, | |||||
* </pre> | |||||
* @fields deviceInfo | |||||
*/ | |||||
@XStreamAlias("device_info") | |||||
private String deviceInfo; | |||||
/** | |||||
* <pre> | |||||
* 用户标识 | |||||
* openid | |||||
* 是 | |||||
* String(128) | |||||
* wxd930ea5d5a258f4f | |||||
* 用户在商户appid下的唯一标识 | |||||
* </pre> | |||||
* @fields openid | |||||
*/ | |||||
@XStreamAlias("openid") | |||||
private String openid; | |||||
/** | |||||
* <pre> | |||||
* 是否关注公众账号 | |||||
* is_subscribe | |||||
* 否 | |||||
* String(1) | |||||
* Y | |||||
* 用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效 | |||||
* </pre> | |||||
* @fields isSubscribe | |||||
*/ | |||||
@XStreamAlias("is_subscribe") | |||||
private String isSubscribe; | |||||
/** | |||||
* <pre> | |||||
* 交易类型 | |||||
* trade_type | |||||
* 是 | |||||
* String(16) | |||||
* JSAPI JSAPI、NATIVE、APP | |||||
* </pre> | |||||
* @fields tradeType | |||||
*/ | |||||
@XStreamAlias("trade_type") | |||||
private String tradeType; | |||||
/** | |||||
* <pre> | |||||
* 付款银行 | |||||
* bank_type | |||||
* 是 | |||||
* String(16) | |||||
* CMC | |||||
* 银行类型,采用字符串类型的银行标识,银行类型见银行列表 | |||||
* </pre> | |||||
* @fields bankType | |||||
*/ | |||||
@XStreamAlias("bank_type") | |||||
private String bankType; | |||||
/** | |||||
* <pre> | |||||
* 订单金额 | |||||
* total_fee | |||||
* 是 | |||||
* Int | |||||
* 100 | |||||
* 订单总金额,单位为分 | |||||
* </pre> | |||||
* @fields totalFee | |||||
*/ | |||||
@XStreamAlias("total_fee") | |||||
private Integer totalFee; | |||||
/** | |||||
* <pre> | |||||
* 应结订单金额 | |||||
* settlement_total_fee | |||||
* 否 | |||||
* Int | |||||
* 100 | |||||
* 应结订单金额=订单金额-非充值代金券金额,应结订单金额<=订单金额。 | |||||
* </pre> | |||||
* @fields settlementTotalFee | |||||
*/ | |||||
@XStreamAlias("settlement_total_fee") | |||||
private Integer settlementTotalFee; | |||||
/** | |||||
* <pre> | |||||
* 货币种类 | |||||
* fee_type | |||||
* 否 | |||||
* String(8) | |||||
* CNY | |||||
* 货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型 | |||||
* </pre> | |||||
* @fields feeType | |||||
*/ | |||||
@XStreamAlias("fee_type") | |||||
private String feeType; | |||||
/** | |||||
* <pre> | |||||
* 现金支付金额 | |||||
* cash_fee | |||||
* 是 | |||||
* Int | |||||
* 100 | |||||
* 现金支付金额订单现金支付金额,详见支付金额 | |||||
* </pre> | |||||
* @fields cashFee | |||||
*/ | |||||
@XStreamAlias("cash_fee") | |||||
private Integer cashFee; | |||||
/** | |||||
* <pre> | |||||
* 现金支付货币类型 | |||||
* cash_fee_type | |||||
* 否 | |||||
* String(16) | |||||
* CNY | |||||
* 货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型 | |||||
* </pre> | |||||
* @fields cashFeeType | |||||
*/ | |||||
@XStreamAlias("cash_fee_type") | |||||
private String cashFeeType; | |||||
/** | |||||
* <pre> | |||||
* 总代金券金额 | |||||
* coupon_fee | |||||
* 否 | |||||
* Int | |||||
* 10 | |||||
* 代金券金额<=订单金额,订单金额-代金券金额=现金支付金额,详见支付金额 | |||||
* </pre> | |||||
* @fields couponFee | |||||
*/ | |||||
@XStreamAlias("coupon_fee") | |||||
private Integer couponFee; | |||||
/** | |||||
* <pre> | |||||
* 代金券使用数量 | |||||
* coupon_count | |||||
* 否 | |||||
* Int | |||||
* 1 | |||||
* 代金券使用数量 | |||||
*/ | |||||
@XStreamAlias("coupon_count") | |||||
private Integer couponCount; | |||||
private List<WxPayOrderNotifyCoupon> couponList; | |||||
/** | |||||
* <pre> | |||||
* 微信支付订单号 | |||||
* transaction_id | |||||
* 是 | |||||
* String(32) | |||||
* 1217752501201407033233368018 | |||||
* 微信支付订单号 | |||||
* </pre> | |||||
* @fields transactionId | |||||
*/ | |||||
@XStreamAlias("transaction_id") | |||||
private String transactionId; | |||||
/** | |||||
* <pre> | |||||
* 商户订单号 | |||||
* out_trade_no | |||||
* 是 | |||||
* String(32) | |||||
* 1212321211201407033568112322 | |||||
* 商户系统的订单号,与请求一致。 | |||||
* </pre> | |||||
* @fields outTradeNo | |||||
*/ | |||||
@XStreamAlias("out_trade_no") | |||||
private String outTradeNo; | |||||
/** | |||||
* <pre> | |||||
* 商家数据包 | |||||
* attach | |||||
* 否 | |||||
* String(128) | |||||
* 123456 | |||||
* 商家数据包,原样返回 | |||||
* </pre> | |||||
* @fields | |||||
*/ | |||||
@XStreamAlias("attach") | |||||
private String attach; | |||||
/** | |||||
* <pre> | |||||
* 支付完成时间 | |||||
* time_end | |||||
* 是 | |||||
* String(14) | |||||
* 20141030133525 | |||||
* 支付完成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则 | |||||
* </pre> | |||||
* @fields timeEnd | |||||
*/ | |||||
@XStreamAlias("time_end") | |||||
private String timeEnd; | |||||
public Integer getCouponCount() { | |||||
return couponCount; | |||||
} | |||||
public void setCouponCount(Integer couponCount) { | |||||
this.couponCount = couponCount; | |||||
} | |||||
public List<WxPayOrderNotifyCoupon> getCouponList() { | |||||
return couponList; | |||||
} | |||||
public void setCouponList(List<WxPayOrderNotifyCoupon> 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<String,String> toMap(){ | |||||
Map<String,String> resultMap = BeanUtils.xmlBean2Map(this); | |||||
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)); | |||||
} | |||||
} | |||||
return resultMap; | |||||
} | |||||
@Override | |||||
public String toString() { | |||||
return ToStringBuilder.reflectionToString(this,ToStringStyle.MULTI_LINE_STYLE); | |||||
} | |||||
} |
@@ -6,7 +6,8 @@ public class BaseBuilder<T> { | |||||
protected String msgType; | protected String msgType; | ||||
protected String toUser; | protected String toUser; | ||||
public T toUser(String toUser) { | |||||
@SuppressWarnings("unchecked") | |||||
public T toUser(String toUser) { | |||||
this.toUser = toUser; | this.toUser = toUser; | ||||
return (T) this; | return (T) this; | ||||
} | } | ||||
@@ -8,12 +8,14 @@ public abstract class BaseBuilder<BuilderType, ValueType> { | |||||
protected String fromUserName; | protected String fromUserName; | ||||
public BuilderType toUser(String touser) { | |||||
@SuppressWarnings("unchecked") | |||||
public BuilderType toUser(String touser) { | |||||
this.toUserName = touser; | this.toUserName = touser; | ||||
return (BuilderType) this; | return (BuilderType) this; | ||||
} | } | ||||
public BuilderType fromUser(String fromusername) { | |||||
@SuppressWarnings("unchecked") | |||||
public BuilderType fromUser(String fromusername) { | |||||
this.fromUserName = fromusername; | this.fromUserName = fromusername; | ||||
return (BuilderType) this; | return (BuilderType) this; | ||||
} | } | ||||
@@ -23,7 +23,6 @@ import me.chanjar.weixin.common.util.json.WxGsonBuilder; | |||||
public class MaterialVoiceAndImageDownloadRequestExecutor implements RequestExecutor<InputStream, String> { | public class MaterialVoiceAndImageDownloadRequestExecutor implements RequestExecutor<InputStream, String> { | ||||
private File tmpDirFile; | |||||
public MaterialVoiceAndImageDownloadRequestExecutor() { | public MaterialVoiceAndImageDownloadRequestExecutor() { | ||||
super(); | super(); | ||||
@@ -31,7 +30,6 @@ public class MaterialVoiceAndImageDownloadRequestExecutor implements RequestExec | |||||
public MaterialVoiceAndImageDownloadRequestExecutor(File tmpDirFile) { | public MaterialVoiceAndImageDownloadRequestExecutor(File tmpDirFile) { | ||||
super(); | super(); | ||||
this.tmpDirFile = tmpDirFile; | |||||
} | } | ||||
@Override | @Override | ||||