Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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操作的一些工具类
Expand All @@ -21,6 +25,7 @@
* </pre>
*/
public class BeanUtils {
private static Logger log = LoggerFactory.getLogger(BeanUtils.class);

/**
* 检查bean里标记为@Required的field是否为空,为空则抛异常
Expand Down Expand Up @@ -48,41 +53,42 @@ public static void checkRequiredFields(Object bean) throws WxErrorException {
}

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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -89,8 +95,8 @@ public WxPayRefundResult refund(WxPayRefundRequest request, File keyFile)
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);
Expand Down Expand Up @@ -120,8 +126,8 @@ public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeN
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));

Expand All @@ -138,17 +144,20 @@ public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeN
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);
}
}

Expand All @@ -157,7 +166,7 @@ private void checkParameters(WxPayRefundRequest request) throws WxErrorException

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());
}
}

Expand All @@ -169,10 +178,12 @@ private void checkParameters(WxPayRefundRequest request) throws WxErrorException
@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) {
Expand All @@ -192,8 +203,8 @@ public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request, File
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));
Expand All @@ -220,8 +231,8 @@ public WxPayRedpackQueryResult queryRedpack(String mchBillNo, File keyFile) thro
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() + "");

Expand All @@ -237,7 +248,7 @@ public WxPayRedpackQueryResult queryRedpack(String mchBillNo, File keyFile) thro

@Override
public String createSign(Object xmlBean) {
return createSign(BeanUtils.xmlBean2Map(xmlBean),this.config.getPartnerKey());
return createSign(BeanUtils.xmlBean2Map(xmlBean),getConfig().getPartnerKey());
}

@Override
Expand All @@ -247,7 +258,7 @@ public String createSign(Object xmlBean, String signKey) {

@Override
public String createSign(Map<String, String> params) {
return createSign(params,this.config.getPartnerKey());
return createSign(params,getConfig().getPartnerKey());
}

@Override
Expand All @@ -268,7 +279,7 @@ public String createSign(Map<String, String> params, String signKey) {

@Override
public boolean checkSign(Object xmlBean) {
return checkSign(BeanUtils.xmlBean2Map(xmlBean) , this.config.getPartnerKey());
return checkSign(BeanUtils.xmlBean2Map(xmlBean) , getConfig().getPartnerKey());
}

@Override
Expand All @@ -278,7 +289,7 @@ public boolean checkSign(Object xmlBean, String signKey) {

@Override
public boolean checkSign(Map<String, String> params) {
return checkSign(params , this.config.getPartnerKey());
return checkSign(params , getConfig().getPartnerKey());
}

@Override
Expand All @@ -302,8 +313,8 @@ public WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo)
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));

Expand All @@ -328,8 +339,8 @@ public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorExcepti

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));

Expand All @@ -345,37 +356,27 @@ public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorExcepti
@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;
}
Expand All @@ -384,7 +385,7 @@ private void checkParameters(WxPayUnifiedOrderRequest request) throws WxErrorExc
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) {
Expand All @@ -406,7 +407,7 @@ public Map<String, String> getPayInfo(WxPayUnifiedOrderRequest request) throws W
}

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() + "");
Expand All @@ -427,8 +428,8 @@ public WxEntPayResult entPay(WxEntPayRequest request, File keyFile) throws WxErr
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));

Expand All @@ -447,8 +448,8 @@ public WxEntPayQueryResult queryEntPay(String partnerTradeNo, File keyFile) thro
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));

Expand Down
Loading