签名类接口化

This commit is contained in:
jinyu 2016-03-26 20:51:53 +08:00
parent 0897575fe1
commit 7ae17e97ee
39 changed files with 680 additions and 690 deletions

View File

@ -651,4 +651,6 @@
+ weixin4j-base:v2和v3支付改名 + weixin4j-base:v2和v3支付改名
+ weixin4j-base:支持服务商版支付 + weixin4j-base:支持服务商版支付
+ weixin4j-base:签名类接口化

View File

@ -2,25 +2,20 @@ package com.foxinmy.weixin4j.api;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference; import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.WeixinRequestExecutor;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse; import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.http.weixin.WeixinSSLRequestExecutor;
import com.foxinmy.weixin4j.model.WeixinPayAccount; import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.PayURLConsts;
import com.foxinmy.weixin4j.payment.mch.CorpPayment; import com.foxinmy.weixin4j.payment.mch.CorpPayment;
import com.foxinmy.weixin4j.payment.mch.CorpPaymentRecord; import com.foxinmy.weixin4j.payment.mch.CorpPaymentRecord;
import com.foxinmy.weixin4j.payment.mch.CorpPaymentResult; import com.foxinmy.weixin4j.payment.mch.CorpPaymentResult;
import com.foxinmy.weixin4j.payment.mch.Redpacket; import com.foxinmy.weixin4j.payment.mch.Redpacket;
import com.foxinmy.weixin4j.payment.mch.RedpacketRecord; import com.foxinmy.weixin4j.payment.mch.RedpacketRecord;
import com.foxinmy.weixin4j.payment.mch.RedpacketSendResult; import com.foxinmy.weixin4j.payment.mch.RedpacketSendResult;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.RandomUtil; import com.foxinmy.weixin4j.util.RandomUtil;
import com.foxinmy.weixin4j.xml.XmlStream; import com.foxinmy.weixin4j.xml.XmlStream;
@ -36,18 +31,16 @@ import com.foxinmy.weixin4j.xml.XmlStream;
* @see <a * @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_1">企业付款</a> * href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_1">企业付款</a>
*/ */
public class CashApi { public class CashApi extends MchApi {
private final WeixinPayAccount weixinAccount;
public CashApi(WeixinPayAccount weixinAccount) { public CashApi(WeixinPayAccount weixinAccount) {
this.weixinAccount = weixinAccount; super(weixinAccount);
} }
/** /**
* 发放红包 企业向微信用户个人发现金红包 * 发放红包 企业向微信用户个人发现金红包
* *
* @param ca * @param certificate
* 后缀为*.p12的证书文件 * 后缀为*.p12的证书文件
* @param redpacket * @param redpacket
* 红包信息 * 红包信息
@ -58,22 +51,19 @@ public class CashApi {
* href="http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_5">发放红包接口说明</a> * href="http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_5">发放红包接口说明</a>
* @throws WeixinException * @throws WeixinException
*/ */
public RedpacketSendResult sendRedpack(InputStream ca, Redpacket redpacket) public RedpacketSendResult sendRedpack(InputStream certificate,
throws WeixinException { Redpacket redpacket) throws WeixinException {
redpacket.setSign(DigestUtil.paysignMd5(redpacket, redpacket.setSign(weixinSignature.sign(redpacket));
weixinAccount.getPaySignKey()));
String param = XmlStream.map2xml((JSONObject) JSON.toJSON(redpacket)); String param = XmlStream.map2xml((JSONObject) JSON.toJSON(redpacket));
WeixinResponse response = null; WeixinResponse response = null;
try { try {
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor( response = createSSLRequestExecutor(certificate)
weixinAccount.getCertificateKey(), ca); .post(redpacket.getTotalNum() > 1 ? getRequestUri("groupredpack_send_uri")
response = weixinExecutor : getRequestUri("redpack_send_uri"), param);
.post(redpacket.getTotalNum() > 1 ? PayURLConsts.MCH_REDPACK_GROUPSEND_URL
: PayURLConsts.MCH_REDPACKSEND_URL, param);
} finally { } finally {
if (ca != null) { if (certificate != null) {
try { try {
ca.close(); certificate.close();
} catch (IOException e) { } catch (IOException e) {
; ;
} }
@ -86,7 +76,7 @@ public class CashApi {
/** /**
* 查询红包记录 * 查询红包记录
* *
* @param ca * @param certificate
* 后缀为*.p12的证书文件 * 后缀为*.p12的证书文件
* @param outTradeNo * @param outTradeNo
* 商户发放红包的商户订单号 * 商户发放红包的商户订单号
@ -96,28 +86,21 @@ public class CashApi {
* href="http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_6">查询红包接口说明</a> * href="http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_6">查询红包接口说明</a>
* @throws WeixinException * @throws WeixinException
*/ */
public RedpacketRecord queryRedpack(InputStream ca, String outTradeNo) public RedpacketRecord queryRedpack(InputStream certificate,
throws WeixinException { String outTradeNo) throws WeixinException {
Map<String, String> para = new HashMap<String, String>(); Map<String, String> para = createBaseRequestMap(null);
para.put("nonce_str", RandomUtil.generateString(16));
para.put("mch_id", weixinAccount.getMchId());
para.put("bill_type", "MCHT"); para.put("bill_type", "MCHT");
para.put("appid", weixinAccount.getId());
para.put("mch_billno", outTradeNo); para.put("mch_billno", outTradeNo);
String sign = DigestUtil para.put("sign", weixinSignature.sign(para));
.paysignMd5(para, weixinAccount.getPaySignKey());
para.put("sign", sign);
String param = XmlStream.map2xml(para); String param = XmlStream.map2xml(para);
WeixinResponse response = null; WeixinResponse response = null;
try { try {
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor( response = createSSLRequestExecutor(certificate).post(
weixinAccount.getCertificateKey(), ca); getRequestUri("redpack_query_uri"), param);
response = weixinExecutor.post(PayURLConsts.MCH_REDPACKQUERY_URL,
param);
} finally { } finally {
if (ca != null) { if (certificate != null) {
try { try {
ca.close(); certificate.close();
} catch (IOException e) { } catch (IOException e) {
; ;
} }
@ -130,7 +113,7 @@ public class CashApi {
/** /**
* 企业付款 实现企业向个人付款针对部分有开发能力的商户 提供通过API完成企业付款的功能 比如目前的保险行业向客户退保给付理赔 * 企业付款 实现企业向个人付款针对部分有开发能力的商户 提供通过API完成企业付款的功能 比如目前的保险行业向客户退保给付理赔
* *
* @param ca * @param certificate
* 后缀为*.p12的证书文件 * 后缀为*.p12的证书文件
* @param mpPayment * @param mpPayment
* 付款信息 * 付款信息
@ -141,27 +124,24 @@ public class CashApi {
* href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_1">企业付款</a> * href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_1">企业付款</a>
* @throws WeixinException * @throws WeixinException
*/ */
public CorpPaymentResult corpPayment(InputStream ca, CorpPayment payment) public CorpPaymentResult sendCorpPayment(InputStream certificate,
throws WeixinException { CorpPayment payment) throws WeixinException {
JSONObject obj = (JSONObject) JSON.toJSON(payment); JSONObject obj = (JSONObject) JSON.toJSON(payment);
obj.put("nonce_str", RandomUtil.generateString(16)); obj.put("nonce_str", RandomUtil.generateString(16));
obj.put("mchid", weixinAccount.getMchId()); obj.put("mchid", weixinAccount.getMchId());
obj.put("sub_mch_id", weixinAccount.getSubMchId()); obj.put("sub_mch_id", weixinAccount.getSubMchId());
obj.put("mch_appid", weixinAccount.getId()); obj.put("mch_appid", weixinAccount.getId());
obj.put("device_info", weixinAccount.getDeviceInfo()); obj.put("device_info", weixinAccount.getDeviceInfo());
String sign = DigestUtil.paysignMd5(obj, weixinAccount.getPaySignKey()); obj.put("sign", weixinSignature.sign(obj));
obj.put("sign", sign);
String param = XmlStream.map2xml(obj); String param = XmlStream.map2xml(obj);
WeixinResponse response = null; WeixinResponse response = null;
try { try {
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor( response = createSSLRequestExecutor(certificate).post(
weixinAccount.getCertificateKey(), ca); getRequestUri("corppayment_send_uri"), param);
response = weixinExecutor.post(PayURLConsts.MCH_ENPAYMENT_URL,
param);
} finally { } finally {
if (ca != null) { if (certificate != null) {
try { try {
ca.close(); certificate.close();
} catch (IOException e) { } catch (IOException e) {
; ;
} }
@ -178,7 +158,7 @@ public class CashApi {
/** /**
* 企业付款查询 用于商户的企业付款操作进行结果查询返回付款操作详细结果 * 企业付款查询 用于商户的企业付款操作进行结果查询返回付款操作详细结果
* *
* @param ca * @param certificate
* 后缀为*.p12的证书文件 * 后缀为*.p12的证书文件
* @param outTradeNo * @param outTradeNo
* 商户调用企业付款API时使用的商户订单号 * 商户调用企业付款API时使用的商户订单号
@ -188,26 +168,23 @@ public class CashApi {
* href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_3">企业付款查询</a> * href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_3">企业付款查询</a>
* @throws WeixinException * @throws WeixinException
*/ */
public CorpPaymentRecord queryCorpPayment(InputStream ca, String outTradeNo) public CorpPaymentRecord queryCorpPayment(InputStream certificate,
throws WeixinException { String outTradeNo) throws WeixinException {
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
obj.put("nonce_str", RandomUtil.generateString(16)); obj.put("nonce_str", RandomUtil.generateString(16));
obj.put("mch_id", weixinAccount.getMchId()); obj.put("mch_id", weixinAccount.getMchId());
obj.put("appid", weixinAccount.getId()); obj.put("appid", weixinAccount.getId());
obj.put("partner_trade_no", outTradeNo); obj.put("partner_trade_no", outTradeNo);
String sign = DigestUtil.paysignMd5(obj, weixinAccount.getPaySignKey()); obj.put("sign", weixinSignature.sign(obj));
obj.put("sign", sign);
String param = XmlStream.map2xml(obj); String param = XmlStream.map2xml(obj);
WeixinResponse response = null; WeixinResponse response = null;
try { try {
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor( response = createSSLRequestExecutor(certificate).post(
weixinAccount.getCertificateKey(), ca); getRequestUri("corppayment_query_uri"), param);
response = weixinExecutor.post(PayURLConsts.MCH_ENPAYQUERY_URL,
param);
} finally { } finally {
if (ca != null) { if (certificate != null) {
try { try {
ca.close(); certificate.close();
} catch (IOException e) { } catch (IOException e) {
; ;
} }

View File

@ -2,21 +2,15 @@ package com.foxinmy.weixin4j.api;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.alibaba.fastjson.TypeReference; import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.WeixinRequestExecutor;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse; import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.http.weixin.WeixinSSLRequestExecutor;
import com.foxinmy.weixin4j.model.WeixinPayAccount; import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.PayURLConsts;
import com.foxinmy.weixin4j.payment.coupon.CouponDetail; import com.foxinmy.weixin4j.payment.coupon.CouponDetail;
import com.foxinmy.weixin4j.payment.coupon.CouponResult; import com.foxinmy.weixin4j.payment.coupon.CouponResult;
import com.foxinmy.weixin4j.payment.coupon.CouponStock; import com.foxinmy.weixin4j.payment.coupon.CouponStock;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.RandomUtil;
import com.foxinmy.weixin4j.util.StringUtil; import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.xml.XmlStream; import com.foxinmy.weixin4j.xml.XmlStream;
@ -29,22 +23,17 @@ import com.foxinmy.weixin4j.xml.XmlStream;
* @since JDK 1.6 * @since JDK 1.6
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php">代金券文档</a> * @see <a href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php">代金券文档</a>
*/ */
public class CouponApi { public class CouponApi extends MchApi {
private final WeixinRequestExecutor weixinExecutor;
private final WeixinPayAccount weixinAccount;
public CouponApi(WeixinPayAccount weixinAccount) { public CouponApi(WeixinPayAccount weixinAccount) {
this.weixinAccount = weixinAccount; super(weixinAccount);
this.weixinExecutor = new WeixinRequestExecutor();
} }
/** /**
* 发放代金券(需要证书) * 发放代金券(需要证书)
* *
* @param ca * @param certificate
* 后缀为*.p12的证书文件 * 后缀为*.p12的证书文件
* @param couponStockId * @param couponStockId
* 代金券批次id * 代金券批次id
* @param partnerTradeNo * @param partnerTradeNo
@ -59,10 +48,10 @@ public class CouponApi {
* href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php?chapter=12_3">发放代金券接口</a> * href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php?chapter=12_3">发放代金券接口</a>
* @throws WeixinException * @throws WeixinException
*/ */
public CouponResult sendCoupon(InputStream ca, String couponStockId, public CouponResult sendCoupon(InputStream certificate,
String partnerTradeNo, String openId, String opUserId) String couponStockId, String partnerTradeNo, String openId,
throws WeixinException { String opUserId) throws WeixinException {
Map<String, String> map = baseMap(); Map<String, String> map = createBaseRequestMap(null);
map.put("coupon_stock_id", couponStockId); map.put("coupon_stock_id", couponStockId);
map.put("partner_trade_no", partnerTradeNo); map.put("partner_trade_no", partnerTradeNo);
map.put("openid", openId); map.put("openid", openId);
@ -75,19 +64,16 @@ public class CouponApi {
map.put("op_user_id", opUserId); map.put("op_user_id", opUserId);
map.put("version", "1.0"); map.put("version", "1.0");
map.put("type", "XML"); map.put("type", "XML");
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey()); map.put("sign", weixinSignature.sign(map));
map.put("sign", sign);
String param = XmlStream.map2xml(map); String param = XmlStream.map2xml(map);
WeixinResponse response = null; WeixinResponse response = null;
try { try {
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor( response = createSSLRequestExecutor(certificate).post(
weixinAccount.getCertificateKey(), ca); getRequestUri("coupon_send_uri"), param);
response = weixinExecutor.post(PayURLConsts.MCH_COUPONSEND_URL,
param);
} finally { } finally {
if (ca != null) { if (certificate != null) {
try { try {
ca.close(); certificate.close();
} catch (IOException e) { } catch (IOException e) {
; ;
} }
@ -110,13 +96,12 @@ public class CouponApi {
*/ */
public CouponStock queryCouponStock(String couponStockId) public CouponStock queryCouponStock(String couponStockId)
throws WeixinException { throws WeixinException {
Map<String, String> map = baseMap(); Map<String, String> map = createBaseRequestMap(null);
map.put("coupon_stock_id", couponStockId); map.put("coupon_stock_id", couponStockId);
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey()); map.put("sign", weixinSignature.sign(map));
map.put("sign", sign);
String param = XmlStream.map2xml(map); String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_COUPONSTOCKQUERY_URL, param); getRequestUri("couponstock_query_uri"), param);
return response.getAsObject(new TypeReference<CouponStock>() { return response.getAsObject(new TypeReference<CouponStock>() {
}); });
} }
@ -134,33 +119,13 @@ public class CouponApi {
*/ */
public CouponDetail queryCouponDetail(String couponId) public CouponDetail queryCouponDetail(String couponId)
throws WeixinException { throws WeixinException {
Map<String, String> map = baseMap(); Map<String, String> map = createBaseRequestMap(null);
map.put("coupon_id", couponId); map.put("coupon_id", couponId);
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey()); map.put("sign", weixinSignature.sign(map));
map.put("sign", sign);
String param = XmlStream.map2xml(map); String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_COUPONDETAILQUERY_URL, param); getRequestUri("coupondetail_query_uri"), param);
return response.getAsObject(new TypeReference<CouponDetail>() { return response.getAsObject(new TypeReference<CouponDetail>() {
}); });
} }
/**
* 接口请求基本数据
*
* @return
*/
private Map<String, String> baseMap() {
Map<String, String> map = new HashMap<String, String>();
map.put("appid", weixinAccount.getId());
map.put("mch_id", weixinAccount.getMchId());
map.put("nonce_str", RandomUtil.generateString(16));
if (StringUtil.isNotBlank(weixinAccount.getDeviceInfo())) {
map.put("device_info", weixinAccount.getDeviceInfo());
}
if (StringUtil.isNotBlank(weixinAccount.getSubMchId())) {
map.put("sub_mch_id", weixinAccount.getSubMchId());
}
return map;
}
} }

View File

@ -0,0 +1,90 @@
package com.foxinmy.weixin4j.api;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.WeixinRequestExecutor;
import com.foxinmy.weixin4j.http.weixin.WeixinSSLRequestExecutor;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.sign.WeixinPaymentSignature;
import com.foxinmy.weixin4j.sign.WeixinSignature;
import com.foxinmy.weixin4j.type.IdQuery;
import com.foxinmy.weixin4j.util.RandomUtil;
import com.foxinmy.weixin4j.util.StringUtil;
/**
* 商户支付
*
* @className MchApi
* @author jy
* @date 2016年3月26日
* @since JDK 1.6
* @see <a href="https://pay.weixin.qq.com/wiki/doc/api/index.html">商户支付平台</a>
*/
public class MchApi extends BaseApi {
private final static ResourceBundle WEIXIN_BUNDLE;
static {
WEIXIN_BUNDLE = ResourceBundle
.getBundle("com/foxinmy/weixin4j/payment/weixin");
}
protected final WeixinPayAccount weixinAccount;
protected final WeixinSignature weixinSignature;
public MchApi(WeixinPayAccount weixinAccount) {
this.weixinAccount = weixinAccount;
this.weixinSignature = new WeixinPaymentSignature(
weixinAccount.getPaySignKey());
}
@Override
protected ResourceBundle weixinBundle() {
return WEIXIN_BUNDLE;
}
/**
* 创建 SSL支付请求
*
* @param certificate
* *.p12证书文件
* @return
* @throws WeixinException
*/
protected WeixinRequestExecutor createSSLRequestExecutor(
InputStream certificate) throws WeixinException {
return new WeixinSSLRequestExecutor(weixinAccount.getCertificateKey(),
certificate);
}
/**
* 支付接口请求基本数据
*
* @param idQuery
* ID信息 可为空
* @return 基础map
*/
protected Map<String, String> createBaseRequestMap(IdQuery idQuery) {
Map<String, String> map = new HashMap<String, String>();
map.put("appid", weixinAccount.getId());
map.put("mch_id", weixinAccount.getMchId());
map.put("nonce_str", RandomUtil.generateString(16));
if (StringUtil.isNotBlank(weixinAccount.getDeviceInfo())) {
map.put("device_info", weixinAccount.getDeviceInfo());
}
if (StringUtil.isNotBlank(weixinAccount.getSubId())) {
map.put("sub_appid", weixinAccount.getSubId());
}
if (StringUtil.isNotBlank(weixinAccount.getSubMchId())) {
map.put("sub_mch_id", weixinAccount.getSubMchId());
}
if (idQuery != null) {
map.put(idQuery.getType().getName(), idQuery.getId());
}
return map;
}
}

View File

@ -19,14 +19,11 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference; import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.exception.WeixinPayException; import com.foxinmy.weixin4j.exception.WeixinPayException;
import com.foxinmy.weixin4j.http.weixin.WeixinRequestExecutor;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse; import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.http.weixin.WeixinSSLRequestExecutor;
import com.foxinmy.weixin4j.http.weixin.XmlResult; import com.foxinmy.weixin4j.http.weixin.XmlResult;
import com.foxinmy.weixin4j.model.Consts; import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.WeixinPayAccount; import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.MicroPayPackage; import com.foxinmy.weixin4j.payment.MicroPayPackage;
import com.foxinmy.weixin4j.payment.PayURLConsts;
import com.foxinmy.weixin4j.payment.mch.APPPayRequest; import com.foxinmy.weixin4j.payment.mch.APPPayRequest;
import com.foxinmy.weixin4j.payment.mch.ApiResult; import com.foxinmy.weixin4j.payment.mch.ApiResult;
import com.foxinmy.weixin4j.payment.mch.JSAPIPayRequest; import com.foxinmy.weixin4j.payment.mch.JSAPIPayRequest;
@ -63,14 +60,10 @@ import com.foxinmy.weixin4j.xml.XmlStream;
* @since JDK 1.6 * @since JDK 1.6
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/index.html">商户平台API</a> * @see <a href="http://pay.weixin.qq.com/wiki/doc/api/index.html">商户平台API</a>
*/ */
public class PayApi { public class PayApi extends MchApi {
private final WeixinRequestExecutor weixinExecutor;
private final WeixinPayAccount weixinAccount;
public PayApi(WeixinPayAccount weixinAccount) { public PayApi(WeixinPayAccount weixinAccount) {
this.weixinAccount = weixinAccount; super(weixinAccount);
this.weixinExecutor = new WeixinRequestExecutor();
} }
/** /**
@ -88,12 +81,11 @@ public class PayApi {
*/ */
public PrePay createPrePay(MchPayPackage payPackage) public PrePay createPrePay(MchPayPackage payPackage)
throws WeixinPayException { throws WeixinPayException {
payPackage.setSign(DigestUtil.paysignMd5(payPackage, payPackage.setSign(weixinSignature.sign(payPackage));
weixinAccount.getPaySignKey()));
String payJsRequestXml = XmlStream.toXML(payPackage); String payJsRequestXml = XmlStream.toXML(payPackage);
try { try {
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_UNIFIEDORDER_URL, payJsRequestXml); getRequestUri("order_create_uri"), payJsRequestXml);
PrePay prePay = response.getAsObject(new TypeReference<PrePay>() { PrePay prePay = response.getAsObject(new TypeReference<PrePay>() {
}); });
if (!prePay.getReturnCode().equalsIgnoreCase(Consts.SUCCESS)) { if (!prePay.getReturnCode().equalsIgnoreCase(Consts.SUCCESS)) {
@ -250,8 +242,7 @@ public class PayApi {
map.put("nonceStr", RandomUtil.generateString(16)); map.put("nonceStr", RandomUtil.generateString(16));
map.put("url", url); map.put("url", url);
map.put("accessToken", oauthToken); map.put("accessToken", oauthToken);
String sign = DigestUtil.SHA1(MapUtil.toJoinString(map, false, true, String sign = DigestUtil.SHA1(MapUtil.toJoinString(map, false, true));
null));
map.remove("url"); map.remove("url");
map.remove("accessToken"); map.remove("accessToken");
map.put("scope", "jsapi_address"); map.put("scope", "jsapi_address");
@ -279,8 +270,8 @@ public class PayApi {
map.put("time_stamp", timestamp); map.put("time_stamp", timestamp);
map.put("nonce_str", noncestr); map.put("nonce_str", noncestr);
map.put("product_id", productId); map.put("product_id", productId);
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey()); String sign = weixinSignature.sign(map);
return String.format(PayURLConsts.MCH_NATIVE_URL, sign, return String.format(getRequestUri("native_pay_uri"), sign,
weixinAccount.getId(), weixinAccount.getMchId(), productId, weixinAccount.getId(), weixinAccount.getMchId(), productId,
timestamp, noncestr); timestamp, noncestr);
} }
@ -438,15 +429,12 @@ public class PayApi {
*/ */
public Order createMicroPay(MicroPayPackage payPackage) public Order createMicroPay(MicroPayPackage payPackage)
throws WeixinException { throws WeixinException {
String sign = DigestUtil.paysignMd5(payPackage, payPackage.setSign(weixinSignature.sign(payPackage));
weixinAccount.getPaySignKey());
payPackage.setSign(sign);
String para = XmlStream.toXML(payPackage); String para = XmlStream.toXML(payPackage);
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_MICROPAY_URL, para); getRequestUri("micropay_uri"), para);
return response return response.getAsObject(new TypeReference<Order>() {
.getAsObject(new TypeReference<com.foxinmy.weixin4j.payment.mch.Order>() { });
});
} }
/** /**
@ -466,13 +454,12 @@ public class PayApi {
* @since V3 * @since V3
* @throws WeixinException * @throws WeixinException
*/ */
public Order orderQuery(IdQuery idQuery) throws WeixinException { public Order queryOrder(IdQuery idQuery) throws WeixinException {
Map<String, String> map = baseMap(idQuery); Map<String, String> map = createBaseRequestMap(idQuery);
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey()); map.put("sign", weixinSignature.sign(map));
map.put("sign", sign);
String param = XmlStream.map2xml(map); String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_ORDERQUERY_URL, param); getRequestUri("order_query_uri"), param);
return ListsuffixResultDeserializer.deserialize(response.getAsString(), return ListsuffixResultDeserializer.deserialize(response.getAsString(),
Order.class); Order.class);
} }
@ -489,7 +476,7 @@ public class PayApi {
* 要采用原来的退款单号总退款金额不能超过用户实际支付金额 * 要采用原来的退款单号总退款金额不能超过用户实际支付金额
* </p> * </p>
* *
* @param ca * @param certificate
* 后缀为*.p12的证书文件 * 后缀为*.p12的证书文件
* @param idQuery * @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级: * 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -511,12 +498,12 @@ public class PayApi {
* @since V3 * @since V3
* @throws WeixinException * @throws WeixinException
*/ */
public RefundResult refundApply(InputStream ca, IdQuery idQuery, public RefundResult applyRefund(InputStream certificate, IdQuery idQuery,
String outRefundNo, double totalFee, double refundFee, String outRefundNo, double totalFee, double refundFee,
CurrencyType refundFeeType, String opUserId) throws WeixinException { CurrencyType refundFeeType, String opUserId) throws WeixinException {
WeixinResponse response = null; WeixinResponse response = null;
try { try {
Map<String, String> map = baseMap(idQuery); Map<String, String> map = createBaseRequestMap(idQuery);
map.put("out_refund_no", outRefundNo); map.put("out_refund_no", outRefundNo);
map.put("total_fee", DateUtil.formaFee2Fen(totalFee)); map.put("total_fee", DateUtil.formaFee2Fen(totalFee));
map.put("refund_fee", DateUtil.formaFee2Fen(refundFee)); map.put("refund_fee", DateUtil.formaFee2Fen(refundFee));
@ -528,18 +515,14 @@ public class PayApi {
refundFeeType = CurrencyType.CNY; refundFeeType = CurrencyType.CNY;
} }
map.put("refund_fee_type", refundFeeType.name()); map.put("refund_fee_type", refundFeeType.name());
String sign = DigestUtil.paysignMd5(map, map.put("sign", weixinSignature.sign(map));
weixinAccount.getPaySignKey());
map.put("sign", sign);
String param = XmlStream.map2xml(map); String param = XmlStream.map2xml(map);
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor( response = createSSLRequestExecutor(certificate).post(
weixinAccount.getCertificateKey(), ca); getRequestUri("refund_apply_uri"), param);
response = weixinExecutor.post(PayURLConsts.MCH_REFUNDAPPLY_URL,
param);
} finally { } finally {
if (ca != null) { if (certificate != null) {
try { try {
ca.close(); certificate.close();
} catch (IOException e) { } catch (IOException e) {
; ;
} }
@ -552,7 +535,7 @@ public class PayApi {
/** /**
* 退款申请(全额退款) * 退款申请(全额退款)
* *
* @param ca * @param certificate
* 后缀为*.p12的证书文件 * 后缀为*.p12的证书文件
* @param idQuery * @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级: * 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -561,12 +544,12 @@ public class PayApi {
* 商户系统内部的退款单号, 户系统内部唯一,同一退款单号多次请求只退一笔 * 商户系统内部的退款单号, 户系统内部唯一,同一退款单号多次请求只退一笔
* @param totalFee * @param totalFee
* 订单总金额,单位为元 * 订单总金额,单位为元
* @see {@link #refundApply(InputStream, IdQuery, String, double, double,CurrencyType, String)} * @see {@link #applyRefund(InputStream, IdQuery, String, double, double,CurrencyType, String)}
*/ */
public RefundResult refundApply(InputStream ca, IdQuery idQuery, public RefundResult applyRefund(InputStream certificate, IdQuery idQuery,
String outRefundNo, double totalFee) throws WeixinException { String outRefundNo, double totalFee) throws WeixinException {
return refundApply(ca, idQuery, outRefundNo, totalFee, totalFee, null, return applyRefund(certificate, idQuery, outRefundNo, totalFee,
null); totalFee, null, null);
} }
/** /**
@ -575,7 +558,7 @@ public class PayApi {
* 如需实现相同功能请调用退款接口</font></br> <font * 如需实现相同功能请调用退款接口</font></br> <font
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上先调用查单接口,如果没有确切的返回,再调用撤销</font></br> * color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上先调用查单接口,如果没有确切的返回,再调用撤销</font></br>
* *
* @param ca * @param certificate
* 后缀为*.p12的证书文件 * 后缀为*.p12的证书文件
* @param idQuery * @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级: * 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -584,24 +567,20 @@ public class PayApi {
* @since V3 * @since V3
* @throws WeixinException * @throws WeixinException
*/ */
public ApiResult reverseOrder(InputStream ca, IdQuery idQuery) public ApiResult reverseOrder(InputStream certificate, IdQuery idQuery)
throws WeixinException { throws WeixinException {
try { try {
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor( Map<String, String> map = createBaseRequestMap(idQuery);
weixinAccount.getCertificateKey(), ca); map.put("sign", weixinSignature.sign(map));
Map<String, String> map = baseMap(idQuery);
String sign = DigestUtil.paysignMd5(map,
weixinAccount.getPaySignKey());
map.put("sign", sign);
String param = XmlStream.map2xml(map); String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post( WeixinResponse response = createSSLRequestExecutor(certificate)
PayURLConsts.MCH_ORDERREVERSE_URL, param); .post(getRequestUri("order_reverse_uri"), param);
return response.getAsObject(new TypeReference<ApiResult>() { return response.getAsObject(new TypeReference<ApiResult>() {
}); });
} finally { } finally {
if (ca != null) { if (certificate != null) {
try { try {
ca.close(); certificate.close();
} catch (IOException e) { } catch (IOException e) {
; ;
} }
@ -621,17 +600,16 @@ public class PayApi {
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_9">转换短链接API</a> * href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_9">转换短链接API</a>
*/ */
public String getShorturl(String url) throws WeixinException { public String getShorturl(String url) throws WeixinException {
Map<String, String> map = baseMap(null); Map<String, String> map = createBaseRequestMap(null);
try { try {
map.put("long_url", URLEncoder.encode(url, Consts.UTF_8.name())); map.put("long_url", URLEncoder.encode(url, Consts.UTF_8.name()));
} catch (UnsupportedEncodingException ignore) { } catch (UnsupportedEncodingException e) {
; ;
} }
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey()); map.put("sign", weixinSignature.sign(map));
map.put("sign", sign);
String param = XmlStream.map2xml(map); String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_SHORTURL_URL, param); getRequestUri("longurl_convert_uri"), param);
map = XmlStream.xml2map(response.getAsString()); map = XmlStream.xml2map(response.getAsString());
return map.get("short_url"); return map.get("short_url");
} }
@ -652,13 +630,12 @@ public class PayApi {
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3">关闭订单API</a> * href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3">关闭订单API</a>
*/ */
public ApiResult closeOrder(String outTradeNo) throws WeixinException { public ApiResult closeOrder(String outTradeNo) throws WeixinException {
Map<String, String> map = baseMap(new IdQuery(outTradeNo, Map<String, String> map = createBaseRequestMap(new IdQuery(outTradeNo,
IdType.TRADENO)); IdType.TRADENO));
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey()); map.put("sign", weixinSignature.sign(map));
map.put("sign", sign);
String param = XmlStream.map2xml(map); String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_CLOSEORDER_URL, param); getRequestUri("order_close_uri"), param);
return response.getAsObject(new TypeReference<ApiResult>() { return response.getAsObject(new TypeReference<ApiResult>() {
}); });
} }
@ -700,14 +677,13 @@ public class PayApi {
if (file.exists()) { if (file.exists()) {
return file; return file;
} }
Map<String, String> map = baseMap(null); Map<String, String> map = createBaseRequestMap(null);
map.put("bill_date", formatBillDate); map.put("bill_date", formatBillDate);
map.put("bill_type", billType.name()); map.put("bill_type", billType.name());
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey()); map.put("sign", weixinSignature.sign(map));
map.put("sign", sign);
String param = XmlStream.map2xml(map); String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_DOWNLOADBILL_URL, param); getRequestUri("downloadbill_uri"), param);
BufferedReader reader = null; BufferedReader reader = null;
BufferedWriter writer = null; BufferedWriter writer = null;
@ -757,13 +733,12 @@ public class PayApi {
* @since V3 * @since V3
* @throws WeixinException * @throws WeixinException
*/ */
public RefundRecord refundQuery(IdQuery idQuery) throws WeixinException { public RefundRecord queryRefund(IdQuery idQuery) throws WeixinException {
Map<String, String> map = baseMap(idQuery); Map<String, String> map = createBaseRequestMap(idQuery);
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey()); map.put("sign", weixinSignature.sign(map));
map.put("sign", sign);
String param = XmlStream.map2xml(map); String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_REFUNDQUERY_URL, param); getRequestUri("refund_query_uri"), param);
return ListsuffixResultDeserializer.deserialize(response.getAsString(), return ListsuffixResultDeserializer.deserialize(response.getAsString(),
RefundRecord.class); RefundRecord.class);
} }
@ -793,18 +768,17 @@ public class PayApi {
public XmlResult interfaceReport(String interfaceUrl, int executeTime, public XmlResult interfaceReport(String interfaceUrl, int executeTime,
String outTradeNo, String ip, Date time, XmlResult returnXml) String outTradeNo, String ip, Date time, XmlResult returnXml)
throws WeixinException { throws WeixinException {
Map<String, String> map = baseMap(null); Map<String, String> map = createBaseRequestMap(null);
map.put("interface_url", interfaceUrl); map.put("interface_url", interfaceUrl);
map.put("execute_time_", Integer.toString(executeTime)); map.put("execute_time_", Integer.toString(executeTime));
map.put("out_trade_no", outTradeNo); map.put("out_trade_no", outTradeNo);
map.put("user_ip", ip); map.put("user_ip", ip);
map.put("time", DateUtil.fortmat2yyyyMMddHHmmss(time)); map.put("time", DateUtil.fortmat2yyyyMMddHHmmss(time));
map.putAll((Map<String, String>) JSON.toJSON(returnXml)); map.putAll((Map<String, String>) JSON.toJSON(returnXml));
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey()); map.put("sign", weixinSignature.sign(map));
map.put("sign", sign);
String param = XmlStream.map2xml(map); String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_PAYREPORT_URL, param); getRequestUri("interface_report_uri"), param);
return response.getAsXmlResult(); return response.getAsXmlResult();
} }
@ -820,39 +794,13 @@ public class PayApi {
* @throws WeixinException * @throws WeixinException
*/ */
public OpenIdResult authCode2openId(String authCode) throws WeixinException { public OpenIdResult authCode2openId(String authCode) throws WeixinException {
Map<String, String> map = baseMap(null); Map<String, String> map = createBaseRequestMap(null);
map.put("auth_code", authCode); map.put("auth_code", authCode);
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey()); map.put("sign", weixinSignature.sign(map));
map.put("sign", sign);
String param = XmlStream.map2xml(map); String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_AUTHCODE_OPENID_URL, param); getRequestUri("authcode_openid_uri"), param);
return response.getAsObject(new TypeReference<OpenIdResult>() { return response.getAsObject(new TypeReference<OpenIdResult>() {
}); });
} }
/**
* 支付接口请求基本数据
*
* @return
*/
private Map<String, String> baseMap(IdQuery idQuery) {
Map<String, String> map = new HashMap<String, String>();
map.put("appid", weixinAccount.getId());
map.put("mch_id", weixinAccount.getMchId());
map.put("nonce_str", RandomUtil.generateString(16));
if (StringUtil.isNotBlank(weixinAccount.getDeviceInfo())) {
map.put("device_info", weixinAccount.getDeviceInfo());
}
if (StringUtil.isNotBlank(weixinAccount.getSubId())) {
map.put("sub_appid", weixinAccount.getSubId());
}
if (StringUtil.isNotBlank(weixinAccount.getSubMchId())) {
map.put("sub_mch_id", weixinAccount.getSubMchId());
}
if (idQuery != null) {
map.put(idQuery.getType().getName(), idQuery.getId());
}
return map;
}
} }

View File

@ -1,124 +0,0 @@
package com.foxinmy.weixin4j.payment;
/**
* 支付URL常量类
*
* @className PayURLConsts
* @author jy
* @date 2014年12月3日
* @since JDK 1.6
* @see
*/
public final class PayURLConsts {
private static final String MCH_BASE_URL = "https://api.mch.weixin.qq.com";
/**
* 商户平台下统一订单生成的url
*/
public static final String MCH_UNIFIEDORDER_URL = MCH_BASE_URL
+ "/pay/unifiedorder";
/**
* 订单查询(商户平台)
*/
public static final String MCH_ORDERQUERY_URL = MCH_BASE_URL
+ "/pay/orderquery";
/**
* 关闭订单(商户平台)
*/
public static final String MCH_CLOSEORDER_URL = MCH_BASE_URL
+ "/pay/closeorder";
/**
* 对账单下载(商户平台)
*/
public static final String MCH_DOWNLOADBILL_URL = MCH_BASE_URL
+ "/pay/downloadbill";
/**
* 退款查询(商户平台)
*/
public static final String MCH_REFUNDQUERY_URL = MCH_BASE_URL
+ "/pay/refundquery";
/**
* 退款申请(商户平台)
*/
public static final String MCH_REFUNDAPPLY_URL = MCH_BASE_URL
+ "/secapi/pay/refund";
/**
* 冲正撤销(商户平台)
*/
public static final String MCH_ORDERREVERSE_URL = MCH_BASE_URL
+ "/secapi/pay/reverse";
/**
* 被扫支付&刷卡支付(商户平台)
*/
public static final String MCH_MICROPAY_URL = MCH_BASE_URL
+ "/pay/micropay";
/**
* 接口上报(商户平台)
*/
public static final String MCH_PAYREPORT_URL = MCH_BASE_URL
+ "/payitil/report";
/**
* 发送现金红包-普通红包(商户平台)
*/
public static final String MCH_REDPACKSEND_URL = MCH_BASE_URL
+ "/mmpaymkttransfers/sendredpack";
/**
* 发送现金红包-裂变红包(商户平台)
*/
public static final String MCH_REDPACK_GROUPSEND_URL = MCH_BASE_URL
+ "/mmpaymkttransfers/sendgroupredpack";
/**
* 查询现金红包(商户平台)
*/
public static final String MCH_REDPACKQUERY_URL = MCH_BASE_URL
+ "/mmpaymkttransfers/gethbinfo";
/**
* 企业向个人付款(商户平台)
*/
public static final String MCH_ENPAYMENT_URL = MCH_BASE_URL
+ "/mmpaymkttransfers/promotion/transfers";
/**
* 企业付款查询(商户平台)
*/
public static final String MCH_ENPAYQUERY_URL = MCH_BASE_URL
+ "/mmpaymkttransfers/gettransferinfo";
/**
* 发放代金券(商户平台)
*/
public static final String MCH_COUPONSEND_URL = MCH_BASE_URL
+ "/mmpaymkttransfers/send_coupon";
/**
* 查询代金券批次信息(商户平台)
*/
public static final String MCH_COUPONSTOCKQUERY_URL = MCH_BASE_URL
+ "/mmpaymkttransfers/query_coupon_stock";
/**
* 查询代金券详细信息(商户平台)
*/
public static final String MCH_COUPONDETAILQUERY_URL = MCH_BASE_URL
+ "/promotion/query_coupon";
/**
* 长链接转换(商户平台)
*/
public static final String MCH_SHORTURL_URL = MCH_BASE_URL
+ "/tools/shorturl";
/**
* 商户平台下native支付的url(模式1)
*/
public static final String MCH_NATIVE_URL = "weixin://wxpay/bizpayurl?sign=%s&appid=%s&mch_id=%s&product_id=%s&time_stamp=%s&nonce_str=%s";
/**
* WAP支付
*
* @see <a
* href="https://pay.weixin.qq.com/wiki/doc/api/wap.php?chapter=15_1">WAP支付说明</a>
*/
public static final String MCH_WAP_URL = "weixin://wap/pay?%s";
/**
* 授权码查询OPENID接口
*/
public static final String MCH_AUTHCODE_OPENID_URL = MCH_BASE_URL
+ "/tools/authcodetoopenid";
}

View File

@ -30,6 +30,7 @@ import com.foxinmy.weixin4j.payment.mch.Redpacket;
import com.foxinmy.weixin4j.payment.mch.RedpacketRecord; import com.foxinmy.weixin4j.payment.mch.RedpacketRecord;
import com.foxinmy.weixin4j.payment.mch.RedpacketSendResult; import com.foxinmy.weixin4j.payment.mch.RedpacketSendResult;
import com.foxinmy.weixin4j.payment.mch.RefundRecord; import com.foxinmy.weixin4j.payment.mch.RefundRecord;
import com.foxinmy.weixin4j.payment.mch.RefundResult;
import com.foxinmy.weixin4j.type.BillType; import com.foxinmy.weixin4j.type.BillType;
import com.foxinmy.weixin4j.type.CurrencyType; import com.foxinmy.weixin4j.type.CurrencyType;
import com.foxinmy.weixin4j.type.IdQuery; import com.foxinmy.weixin4j.type.IdQuery;
@ -50,7 +51,7 @@ public class WeixinPayProxy {
/** /**
* 微信支付API:js支付扫码支付等接口 * 微信支付API:js支付扫码支付等接口
*/ */
private final PayApi pay3Api; private final PayApi payApi;
/** /**
* 代金券API * 代金券API
*/ */
@ -63,7 +64,7 @@ public class WeixinPayProxy {
* 配置相关 * 配置相关
*/ */
private final Weixin4jSettings settings; private final Weixin4jSettings settings;
/** /**
* 使用weixin4j.properties配置的支付账号信息 * 使用weixin4j.properties配置的支付账号信息
*/ */
@ -79,7 +80,7 @@ public class WeixinPayProxy {
*/ */
public WeixinPayProxy(Weixin4jSettings settings) { public WeixinPayProxy(Weixin4jSettings settings) {
this.settings = settings; this.settings = settings;
this.pay3Api = new PayApi(settings.getWeixinPayAccount()); this.payApi = new PayApi(settings.getWeixinPayAccount());
this.couponApi = new CouponApi(settings.getWeixinPayAccount()); this.couponApi = new CouponApi(settings.getWeixinPayAccount());
this.cashApi = new CashApi(settings.getWeixinPayAccount()); this.cashApi = new CashApi(settings.getWeixinPayAccount());
} }
@ -109,7 +110,7 @@ public class WeixinPayProxy {
*/ */
public PrePay createPrePay(MchPayPackage payPackage) public PrePay createPrePay(MchPayPackage payPackage)
throws WeixinPayException { throws WeixinPayException {
return pay3Api.createPrePay(payPackage); return payApi.createPrePay(payPackage);
} }
/** /**
@ -127,7 +128,7 @@ public class WeixinPayProxy {
*/ */
public MchPayRequest createPayRequest(MchPayPackage payPackage) public MchPayRequest createPayRequest(MchPayPackage payPackage)
throws WeixinPayException { throws WeixinPayException {
return pay3Api.createPayRequest(payPackage); return payApi.createPayRequest(payPackage);
} }
/** /**
@ -173,7 +174,7 @@ public class WeixinPayProxy {
double totalFee, String notifyUrl, String createIp, String attach, double totalFee, String notifyUrl, String createIp, String attach,
Date timeStart, Date timeExpire, String goodsTag, String limitPay) Date timeStart, Date timeExpire, String goodsTag, String limitPay)
throws WeixinPayException { throws WeixinPayException {
return pay3Api.createPayRequest(tradeType, openId, productId, body, return payApi.createPayRequest(tradeType, openId, productId, body,
detail, outTradeNo, totalFee, notifyUrl, createIp, attach, detail, outTradeNo, totalFee, notifyUrl, createIp, attach,
timeStart, timeExpire, goodsTag, limitPay); timeStart, timeExpire, goodsTag, limitPay);
} }
@ -201,7 +202,7 @@ public class WeixinPayProxy {
public MchPayRequest createJSPayRequest(String openId, String body, public MchPayRequest createJSPayRequest(String openId, String body,
String outTradeNo, double totalFee, String notifyUrl, String outTradeNo, double totalFee, String notifyUrl,
String createIp) throws WeixinPayException { String createIp) throws WeixinPayException {
return pay3Api.createJSPayRequest(openId, body, outTradeNo, totalFee, return payApi.createJSPayRequest(openId, body, outTradeNo, totalFee,
notifyUrl, createIp); notifyUrl, createIp);
} }
@ -226,7 +227,7 @@ public class WeixinPayProxy {
* @return 编辑地址请求JSON串 * @return 编辑地址请求JSON串
*/ */
public String createAddressRequestJSON(String url, String oauthToken) { public String createAddressRequestJSON(String url, String oauthToken) {
return pay3Api.createAddressRequestJSON(url, oauthToken); return payApi.createAddressRequestJSON(url, oauthToken);
} }
/** /**
@ -241,7 +242,7 @@ public class WeixinPayProxy {
* href="https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4">模式一</a> * href="https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4">模式一</a>
*/ */
public String createNativePayRequestURL(String productId) { public String createNativePayRequestURL(String productId) {
return pay3Api.createNativePayRequestURL(productId); return payApi.createNativePayRequestURL(productId);
} }
/** /**
@ -270,7 +271,7 @@ public class WeixinPayProxy {
public NativePayResponse createNativePayResponse(String productId, public NativePayResponse createNativePayResponse(String productId,
String body, String outTradeNo, double totalFee, String notifyUrl, String body, String outTradeNo, double totalFee, String notifyUrl,
String createIp) throws WeixinPayException { String createIp) throws WeixinPayException {
return pay3Api.createNativePayResponse(productId, body, outTradeNo, return payApi.createNativePayResponse(productId, body, outTradeNo,
totalFee, notifyUrl, createIp); totalFee, notifyUrl, createIp);
} }
@ -300,7 +301,7 @@ public class WeixinPayProxy {
public MchPayRequest createNativePayRequest(String productId, String body, public MchPayRequest createNativePayRequest(String productId, String body,
String outTradeNo, double totalFee, String notifyUrl, String outTradeNo, double totalFee, String notifyUrl,
String createIp) throws WeixinPayException { String createIp) throws WeixinPayException {
return pay3Api.createNativePayRequest(productId, body, outTradeNo, return payApi.createNativePayRequest(productId, body, outTradeNo,
totalFee, notifyUrl, createIp); totalFee, notifyUrl, createIp);
} }
@ -327,7 +328,7 @@ public class WeixinPayProxy {
public MchPayRequest createAppPayRequest(String body, String outTradeNo, public MchPayRequest createAppPayRequest(String body, String outTradeNo,
double totalFee, String notifyUrl, String createIp) double totalFee, String notifyUrl, String createIp)
throws WeixinPayException { throws WeixinPayException {
return pay3Api.createAppPayRequest(body, outTradeNo, totalFee, return payApi.createAppPayRequest(body, outTradeNo, totalFee,
notifyUrl, createIp); notifyUrl, createIp);
} }
@ -354,7 +355,7 @@ public class WeixinPayProxy {
public MchPayRequest createWAPPayRequest(String body, String outTradeNo, public MchPayRequest createWAPPayRequest(String body, String outTradeNo,
double totalFee, String notifyUrl, String createIp) double totalFee, String notifyUrl, String createIp)
throws WeixinPayException { throws WeixinPayException {
return pay3Api.createWAPPayRequest(body, outTradeNo, totalFee, return payApi.createWAPPayRequest(body, outTradeNo, totalFee,
notifyUrl, createIp); notifyUrl, createIp);
} }
@ -378,7 +379,7 @@ public class WeixinPayProxy {
*/ */
public Order createMicroPay(String authCode, String body, String orderNo, public Order createMicroPay(String authCode, String body, String orderNo,
double orderFee, String createIp) throws WeixinException { double orderFee, String createIp) throws WeixinException {
return pay3Api.createMicroPay(authCode, body, orderNo, orderFee, return payApi.createMicroPay(authCode, body, orderNo, orderFee,
createIp); createIp);
} }
@ -397,7 +398,7 @@ public class WeixinPayProxy {
*/ */
public Order createMicroPay(MicroPayPackage payPackage) public Order createMicroPay(MicroPayPackage payPackage)
throws WeixinException { throws WeixinException {
return pay3Api.createMicroPay(payPackage); return payApi.createMicroPay(payPackage);
} }
/** /**
@ -418,8 +419,8 @@ public class WeixinPayProxy {
* @return 订单详情 * @return 订单详情
* @throws WeixinException * @throws WeixinException
*/ */
public Order orderQuery(IdQuery idQuery) throws WeixinException { public Order queryOrder(IdQuery idQuery) throws WeixinException {
return pay3Api.orderQuery(idQuery); return payApi.queryOrder(idQuery);
} }
/** /**
@ -434,7 +435,7 @@ public class WeixinPayProxy {
* 要采用原来的退款单号总退款金额不能超过用户实际支付金额 * 要采用原来的退款单号总退款金额不能超过用户实际支付金额
* </p> * </p>
* *
* @param ca * @param certificate
* 后缀为*.p12的证书文件 * 后缀为*.p12的证书文件
* @param idQuery * @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级: * 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -458,11 +459,11 @@ public class WeixinPayProxy {
* @since V3 * @since V3
* @throws WeixinException * @throws WeixinException
*/ */
public com.foxinmy.weixin4j.payment.mch.RefundResult refundApply( public RefundResult applyRefund(
InputStream ca, IdQuery idQuery, String outRefundNo, InputStream certificate, IdQuery idQuery, String outRefundNo,
double totalFee, double refundFee, CurrencyType refundFeeType, double totalFee, double refundFee, CurrencyType refundFeeType,
String opUserId) throws WeixinException { String opUserId) throws WeixinException {
return pay3Api.refundApply(ca, idQuery, outRefundNo, totalFee, return payApi.applyRefund(certificate, idQuery, outRefundNo, totalFee,
refundFee, refundFeeType, opUserId); refundFee, refundFeeType, opUserId);
} }
@ -471,12 +472,12 @@ public class WeixinPayProxy {
* *
* @throws IOException * @throws IOException
* *
* @see {@link #refundApply(InputStream, IdQuery, String, double, double, String,CurrencyType)} * @see {@link #applyRefund(InputStream, IdQuery, String, double, double, String,CurrencyType)}
*/ */
public com.foxinmy.weixin4j.payment.mch.RefundResult refundApply( public RefundResult applyRefund(
IdQuery idQuery, String outRefundNo, double totalFee) IdQuery idQuery, String outRefundNo, double totalFee)
throws WeixinException, IOException { throws WeixinException, IOException {
return pay3Api.refundApply( return payApi.applyRefund(
new FileInputStream(settings.getCertificateFile0()), idQuery, new FileInputStream(settings.getCertificateFile0()), idQuery,
outRefundNo, totalFee); outRefundNo, totalFee);
} }
@ -499,8 +500,8 @@ public class WeixinPayProxy {
* @since V3 * @since V3
* @throws WeixinException * @throws WeixinException
*/ */
public RefundRecord refundQuery(IdQuery idQuery) throws WeixinException { public RefundRecord queryRefund(IdQuery idQuery) throws WeixinException {
return pay3Api.refundQuery(idQuery); return payApi.queryRefund(idQuery);
} }
/** /**
@ -524,7 +525,7 @@ public class WeixinPayProxy {
*/ */
public File downloadBill(Date billDate, BillType billType) public File downloadBill(Date billDate, BillType billType)
throws WeixinException { throws WeixinException {
return pay3Api.downloadBill(billDate, billType, settings.getTmpdir0()); return payApi.downloadBill(billDate, billType, settings.getTmpdir0());
} }
/** /**
@ -533,7 +534,7 @@ public class WeixinPayProxy {
* 如需实现相同功能请调用退款接口</font></br> <font * 如需实现相同功能请调用退款接口</font></br> <font
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上先调用查单接口,如果没有确切的返回,再调用撤销</font></br> * color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上先调用查单接口,如果没有确切的返回,再调用撤销</font></br>
* *
* @param ca * @param certificate
* 证书文件(V2版本后缀为*.pfx,V3版本后缀为*.p12) * 证书文件(V2版本后缀为*.pfx,V3版本后缀为*.p12)
* @param idQuery * @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级: * 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -543,9 +544,9 @@ public class WeixinPayProxy {
* @since V3 * @since V3
* @throws WeixinException * @throws WeixinException
*/ */
public ApiResult reverseOrder(InputStream ca, IdQuery idQuery) public ApiResult reverseOrder(InputStream certificate, IdQuery idQuery)
throws WeixinException { throws WeixinException {
return pay3Api.reverseOrder(ca, idQuery); return payApi.reverseOrder(certificate, idQuery);
} }
/** /**
@ -560,7 +561,7 @@ public class WeixinPayProxy {
*/ */
public ApiResult reverseOrder(IdQuery idQuery) throws WeixinException, public ApiResult reverseOrder(IdQuery idQuery) throws WeixinException,
IOException { IOException {
return pay3Api.reverseOrder( return payApi.reverseOrder(
new FileInputStream(settings.getCertificateFile0()), idQuery); new FileInputStream(settings.getCertificateFile0()), idQuery);
} }
@ -581,7 +582,7 @@ public class WeixinPayProxy {
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3">关闭订单API</a> * href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3">关闭订单API</a>
*/ */
public ApiResult closeOrder(String outTradeNo) throws WeixinException { public ApiResult closeOrder(String outTradeNo) throws WeixinException {
return pay3Api.closeOrder(outTradeNo); return payApi.closeOrder(outTradeNo);
} }
/** /**
@ -598,7 +599,7 @@ public class WeixinPayProxy {
* @throws WeixinException * @throws WeixinException
*/ */
public String getPayShorturl(String url) throws WeixinException { public String getPayShorturl(String url) throws WeixinException {
return pay3Api.getShorturl(url); return payApi.getShorturl(url);
} }
/** /**
@ -626,14 +627,14 @@ public class WeixinPayProxy {
public XmlResult interfaceReport(String interfaceUrl, int executeTime, public XmlResult interfaceReport(String interfaceUrl, int executeTime,
String outTradeNo, String ip, Date time, XmlResult returnXml) String outTradeNo, String ip, Date time, XmlResult returnXml)
throws WeixinException { throws WeixinException {
return pay3Api.interfaceReport(interfaceUrl, executeTime, outTradeNo, return payApi.interfaceReport(interfaceUrl, executeTime, outTradeNo,
ip, time, returnXml); ip, time, returnXml);
} }
/** /**
* 发放代金券(需要证书) * 发放代金券(需要证书)
* *
* @param ca * @param certificate
* 后缀为*.p12的证书文件 * 后缀为*.p12的证书文件
* @param couponStockId * @param couponStockId
* 代金券批次id * 代金券批次id
@ -650,11 +651,11 @@ public class WeixinPayProxy {
* href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php?chapter=12_3">发放代金券接口</a> * href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php?chapter=12_3">发放代金券接口</a>
* @throws WeixinException * @throws WeixinException
*/ */
public CouponResult sendCoupon(InputStream ca, String couponStockId, public CouponResult sendCoupon(InputStream certificate,
String partnerTradeNo, String openId, String opUserId) String couponStockId, String partnerTradeNo, String openId,
throws WeixinException { String opUserId) throws WeixinException {
return couponApi.sendCoupon(ca, couponStockId, partnerTradeNo, openId, return couponApi.sendCoupon(certificate, couponStockId, partnerTradeNo,
opUserId); openId, opUserId);
} }
/** /**
@ -706,7 +707,7 @@ public class WeixinPayProxy {
/** /**
* 发放红包 企业向微信用户个人发现金红包 * 发放红包 企业向微信用户个人发现金红包
* *
* @param ca * @param certificate
* 后缀为*.p12的证书文件 * 后缀为*.p12的证书文件
* @param redpacket * @param redpacket
* 红包信息 * 红包信息
@ -718,9 +719,9 @@ public class WeixinPayProxy {
* href="http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_5">红包接口说明</a> * href="http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_5">红包接口说明</a>
* @throws WeixinException * @throws WeixinException
*/ */
public RedpacketSendResult sendRedpack(InputStream ca, Redpacket redpacket) public RedpacketSendResult sendRedpack(InputStream certificate,
throws WeixinException { Redpacket redpacket) throws WeixinException {
return cashApi.sendRedpack(ca, redpacket); return cashApi.sendRedpack(certificate, redpacket);
} }
/** /**
@ -737,7 +738,7 @@ public class WeixinPayProxy {
/** /**
* 查询红包记录 * 查询红包记录
* *
* @param ca * @param certificate
* 后缀为*.p12的证书文件 * 后缀为*.p12的证书文件
* @param outTradeNo * @param outTradeNo
* 商户发放红包的商户订单号 * 商户发放红包的商户订单号
@ -748,9 +749,9 @@ public class WeixinPayProxy {
* href="http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_6">查询红包接口说明</a> * href="http://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_6">查询红包接口说明</a>
* @throws WeixinException * @throws WeixinException
*/ */
public RedpacketRecord queryRedpack(InputStream ca, String outTradeNo) public RedpacketRecord queryRedpack(InputStream certificate,
throws WeixinException { String outTradeNo) throws WeixinException {
return cashApi.queryRedpack(ca, outTradeNo); return cashApi.queryRedpack(certificate, outTradeNo);
} }
/** /**
@ -769,9 +770,9 @@ public class WeixinPayProxy {
/** /**
* 企业付款 实现企业向个人付款针对部分有开发能力的商户 提供通过API完成企业付款的功能 比如目前的保险行业向客户退保给付理赔 * 企业付款 实现企业向个人付款针对部分有开发能力的商户 提供通过API完成企业付款的功能 比如目前的保险行业向客户退保给付理赔
* *
* @param ca * @param certificate
* 后缀为*.p12的证书文件 * 后缀为*.p12的证书文件
* @param mpPayment * @param payment
* 付款信息 * 付款信息
* @return 付款结果 * @return 付款结果
* @see com.foxinmy.weixin4j.api.CashApi * @see com.foxinmy.weixin4j.api.CashApi
@ -781,26 +782,26 @@ public class WeixinPayProxy {
* href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_1">企业付款</a> * href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_1">企业付款</a>
* @throws WeixinException * @throws WeixinException
*/ */
public CorpPaymentResult corpPayment(InputStream ca, CorpPayment payment) public CorpPaymentResult sendCorpPayment(InputStream certificate,
throws WeixinException { CorpPayment payment) throws WeixinException {
return cashApi.corpPayment(ca, payment); return cashApi.sendCorpPayment(certificate, payment);
} }
/** /**
* 企业付款 * 企业付款
* *
* @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#corpPayment(InputStream, CorpPayment)} * @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#senCorpPayment(InputStream, CorpPayment)}
*/ */
public CorpPaymentResult corpPayment(CorpPayment payment) public CorpPaymentResult sendCorpPayment(CorpPayment payment)
throws WeixinException, IOException { throws WeixinException, IOException {
return cashApi.corpPayment( return cashApi.sendCorpPayment(
new FileInputStream(settings.getCertificateFile0()), payment); new FileInputStream(settings.getCertificateFile0()), payment);
} }
/** /**
* 企业付款查询 用于商户的企业付款操作进行结果查询返回付款操作详细结果 * 企业付款查询 用于商户的企业付款操作进行结果查询返回付款操作详细结果
* *
* @param ca * @param certificate
* 后缀为*.p12的证书文件 * 后缀为*.p12的证书文件
* @param outTradeNo * @param outTradeNo
* 商户调用企业付款API时使用的商户订单号 * 商户调用企业付款API时使用的商户订单号
@ -811,9 +812,9 @@ public class WeixinPayProxy {
* href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_3">企业付款查询</a> * href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_3">企业付款查询</a>
* @throws WeixinException * @throws WeixinException
*/ */
public CorpPaymentRecord queryCorpPayment(InputStream ca, String outTradeNo) public CorpPaymentRecord queryCorpPayment(InputStream certificate,
throws WeixinException { String outTradeNo) throws WeixinException {
return cashApi.queryCorpPayment(ca, outTradeNo); return cashApi.queryCorpPayment(certificate, outTradeNo);
} }
/** /**
@ -842,7 +843,7 @@ public class WeixinPayProxy {
* @throws WeixinException * @throws WeixinException
*/ */
public OpenIdResult authCode2openId(String authCode) throws WeixinException { public OpenIdResult authCode2openId(String authCode) throws WeixinException {
return pay3Api.authCode2openId(authCode); return payApi.authCode2openId(authCode);
} }
public final static String VERSION = "1.6.7"; public final static String VERSION = "1.6.7";

View File

@ -44,7 +44,7 @@ public class APPPayRequest extends AbstractPayRequest {
PayRequest payRequest = toRequestObject(); PayRequest payRequest = toRequestObject();
String sign = DigestUtil.MD5( String sign = DigestUtil.MD5(
String.format("%s&key=%s", String.format("%s&key=%s",
MapUtil.toJoinString(payRequest, false, true, null), MapUtil.toJoinString(payRequest, false, true),
getPayAccount().getPaySignKey())).toUpperCase(); getPayAccount().getPaySignKey())).toUpperCase();
StringBuilder content = new StringBuilder(); StringBuilder content = new StringBuilder();
content.append("<xml>"); content.append("<xml>");

View File

@ -1,15 +1,19 @@
package com.foxinmy.weixin4j.payment.mch; package com.foxinmy.weixin4j.payment.mch;
import com.foxinmy.weixin4j.model.WeixinPayAccount; import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.sign.WeixinPaymentSignature;
import com.foxinmy.weixin4j.sign.WeixinSignature;
public abstract class AbstractPayRequest implements MchPayRequest { public abstract class AbstractPayRequest implements MchPayRequest {
private final String prePayId; private final String prePayId;
private final WeixinPayAccount payAccount; private final WeixinPayAccount payAccount;
protected final WeixinSignature weixinSignature;
public AbstractPayRequest(String prePayId, WeixinPayAccount payAccount) { public AbstractPayRequest(String prePayId, WeixinPayAccount payAccount) {
this.prePayId = prePayId; this.prePayId = prePayId;
this.payAccount = payAccount; this.payAccount = payAccount;
this.weixinSignature = new WeixinPaymentSignature(payAccount.getPaySignKey());
} }
@Override @Override

View File

@ -5,7 +5,6 @@ import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.PayRequest; import com.foxinmy.weixin4j.payment.PayRequest;
import com.foxinmy.weixin4j.type.SignType; import com.foxinmy.weixin4j.type.SignType;
import com.foxinmy.weixin4j.type.TradeType; import com.foxinmy.weixin4j.type.TradeType;
import com.foxinmy.weixin4j.util.DigestUtil;
/** /**
* 公众号JS支付:get_brand_wcpay_request</br> * 公众号JS支付:get_brand_wcpay_request</br>
@ -29,7 +28,7 @@ public class JSAPIPayRequest extends AbstractPayRequest {
public JSAPIPayRequest(String prePayId, WeixinPayAccount payAccount) { public JSAPIPayRequest(String prePayId, WeixinPayAccount payAccount) {
super(prePayId, payAccount); super(prePayId, payAccount);
} }
@Override @Override
public TradeType getTradeType() { public TradeType getTradeType() {
return TradeType.JSAPI; return TradeType.JSAPI;
@ -40,8 +39,7 @@ public class JSAPIPayRequest extends AbstractPayRequest {
PayRequest payRequest = new PayRequest(getPayAccount().getId(), PayRequest payRequest = new PayRequest(getPayAccount().getId(),
"prepay_id=" + getPrePayId()); "prepay_id=" + getPrePayId());
payRequest.setSignType(SignType.MD5); payRequest.setSignType(SignType.MD5);
payRequest.setPaySign(DigestUtil.paysignMd5(payRequest, getPayAccount() payRequest.setPaySign(weixinSignature.sign(payRequest));
.getPaySignKey()));
return payRequest; return payRequest;
} }

View File

@ -9,7 +9,7 @@ import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.exception.WeixinPayException; import com.foxinmy.weixin4j.exception.WeixinPayException;
import com.foxinmy.weixin4j.model.Consts; import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.WeixinPayAccount; import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.util.DigestUtil; import com.foxinmy.weixin4j.sign.WeixinPaymentSignature;
import com.foxinmy.weixin4j.util.RandomUtil; import com.foxinmy.weixin4j.util.RandomUtil;
/** /**
@ -67,7 +67,8 @@ public class NativePayResponse extends ApiResult {
this.setAppId(weixinAccount.getId()); this.setAppId(weixinAccount.getId());
this.setNonceStr(RandomUtil.generateString(16)); this.setNonceStr(RandomUtil.generateString(16));
this.prepayId = prepayId; this.prepayId = prepayId;
this.setSign(DigestUtil.paysignMd5(this, weixinAccount.getPaySignKey())); this.setSign(new WeixinPaymentSignature(weixinAccount.getPaySignKey())
.sign(this));
} }
public String getPrepayId() { public String getPrepayId() {

View File

@ -3,7 +3,6 @@ package com.foxinmy.weixin4j.payment.mch;
import com.foxinmy.weixin4j.model.Consts; import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.WeixinPayAccount; import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.PayRequest; import com.foxinmy.weixin4j.payment.PayRequest;
import com.foxinmy.weixin4j.payment.PayURLConsts;
import com.foxinmy.weixin4j.type.TradeType; import com.foxinmy.weixin4j.type.TradeType;
import com.foxinmy.weixin4j.util.DigestUtil; import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.MapUtil; import com.foxinmy.weixin4j.util.MapUtil;
@ -46,12 +45,13 @@ public class WAPPayRequest extends AbstractPayRequest {
@Override @Override
public String toRequestString() { public String toRequestString() {
PayRequest payRequest = toRequestObject(); PayRequest payRequest = toRequestObject();
String original = MapUtil.toJoinString(payRequest, true, true, null); String original = MapUtil.toJoinString(payRequest, true, true);
String sign = DigestUtil.MD5( String sign = DigestUtil.MD5(
String.format("%s&key=%s", original, getPayAccount() String.format("%s&key=%s", original, getPayAccount()
.getPaySignKey())).toUpperCase(); .getPaySignKey())).toUpperCase();
return String.format(PayURLConsts.MCH_WAP_URL, URLEncodingUtil return String.format("weixin://wap/pay?%s",
.encoding(String.format("%s&sign=%s", original, sign), URLEncodingUtil.encoding(
String.format("%s&sign=%s", original, sign),
Consts.UTF_8, true)); Consts.UTF_8, true));
} }
} }

View File

@ -0,0 +1,51 @@
# \u5fae\u4fe1\u5546\u6237\u5e73\u53f0\u6587\u6863\u8bf4\u660e
# https://pay.weixin.qq.com/
# https://pay.weixin.qq.com/wiki/doc/api/index.php
# ----------------------------------------------------------------------------
mch_base_url=https://api.mch.weixin.qq.com
# \u53d1\u9001\u73b0\u91d1\u7ea2\u5305
redpack_send_uri={mch_base_url}/mmpaymkttransfers/sendredpack
# \u53d1\u9001\u73b0\u91d1\u88c2\u53d8\u7ea2\u5305
groupredpack_send_uri={mch_base_url}/mmpaymkttransfers/sendgroupredpack
# \u67e5\u8be2\u73b0\u91d1\u7ea2\u5305
redpack_query_uri={mch_base_url}/mmpaymkttransfers/gethbinfo
# \u7edf\u4e00\u8ba2\u5355\u751f\u6210
order_create_uri={mch_base_url}/pay/unifiedorder
# \u88ab\u626b\u652f\u4ed8
micropay_uri={mch_base_url}/pay/micropay
# \u8ba2\u5355\u67e5\u8be2
order_query_uri={mch_base_url}/pay/orderquery
# \u5173\u95ed\u8ba2\u5355
order_close_uri={mch_base_url}/pay/closeorder
# \u5bf9\u8d26\u5355\u4e0b\u8f7d
downloadbill_uri={mch_base_url}/pay/downloadbill
# \u9000\u6b3e\u67e5\u8be2
refund_query_uri={mch_base_url}/pay/refundquery
# \u9000\u6b3e\u7533\u8bf7
refund_apply_uri={mch_base_url}/secapi/pay/refund
# \u51b2\u6b63\u64a4\u9500
order_reverse_uri={mch_base_url}/secapi/pay/reverse
# \u957f\u94fe\u63a5\u8f6c\u6362
longurl_convert_uri={mch_base_url}/tools/shorturl
# \u53d1\u653e\u4ee3\u91d1\u5238
coupon_send_uri={mch_base_url}/mmpaymkttransfers/send_coupon
# \u67e5\u8be2\u4ee3\u91d1\u5238\u6279\u6b21\u4fe1\u606f
couponstock_query_uri={mch_base_url}/mmpaymkttransfers/query_coupon_stock
# \u67e5\u8be2\u4ee3\u91d1\u5238\u8be6\u7ec6\u4fe1\u606f
coupondetail_query_uri={mch_base_url}/promotion/query_coupon
# \u53d1\u9001\u73b0\u91d1\u7ea2\u5305
redpack_send_uri={mch_base_url}/mmpaymkttransfers/sendredpack
# \u67e5\u8be2\u73b0\u91d1\u7ea2\u5305
redpack_query_uri={mch_base_url}/mmpaymkttransfers/gethbinfo
# \u4f01\u4e1a\u5411\u4e2a\u4eba\u4ed8\u6b3e
corppayment_send_uri={mch_base_url}/mmpaymkttransfers/promotion/transfers
# \u4f01\u4e1a\u4ed8\u6b3e\u67e5\u8be2
corppayment_query_uri={mch_base_url}/mmpaymkttransfers/gettransferinfo
# \u63a5\u53e3\u4e0a\u62a5
interface_report_uri={mch_base_url}/payitil/report
# \u6388\u6743\u7801\u67e5\u8be2OPENID\u63a5\u53e3
authcode_openid_uri={mch_base_url}/tools/authcodetoopenid
# native\u652f\u4ed8url(\u6a21\u5f0f1)
native_pay_uri=weixin://wxpay/bizpayurl?sign=%s&appid=%s&mch_id=%s&product_id=%s&time_stamp=%s&nonce_str=%s

View File

@ -0,0 +1,43 @@
package com.foxinmy.weixin4j.sign;
import com.foxinmy.weixin4j.util.MapUtil;
/**
* 微信签名
*
* @className AbstractWeixinSignature
* @author jy
* @date 2016年3月26日
* @since JDK 1.6
* @see
*/
public abstract class AbstractWeixinSignature implements WeixinSignature {
/**
* 是否编码
*
* @return
*/
public boolean encoder() {
return false;
}
/**
* 是否转换小写
*
* @return
*/
public boolean lowerCase() {
return false;
}
/**
* 拼接字符串
*
* @param obj
* @return
*/
protected StringBuilder join(Object obj) {
return new StringBuilder(MapUtil.toJoinString(obj, encoder(),
lowerCase()));
}
}

View File

@ -0,0 +1,29 @@
package com.foxinmy.weixin4j.sign;
import com.foxinmy.weixin4j.util.DigestUtil;
/**
* 微信支付签名实现
*
* @className WeixinPaymentSignature
* @author jy
* @date 2016年3月26日
* @since JDK 1.6
* @see
*/
public class WeixinPaymentSignature extends AbstractWeixinSignature {
/**
* 支付密钥
*/
private final String paySignKey;
public WeixinPaymentSignature(String paySignKey) {
this.paySignKey = paySignKey;
}
@Override
public String sign(Object obj) {
StringBuilder sb = join(obj).append("&key=").append(paySignKey);
return DigestUtil.MD5(sb.toString()).toUpperCase();
}
}

View File

@ -0,0 +1,35 @@
package com.foxinmy.weixin4j.sign;
/**
* 微信签名
*
* @className WeixinSignature
* @author jy
* @date 2016年3月26日
* @since JDK 1.7
* @see
*/
public interface WeixinSignature {
/**
* 是否编码
*
* @return
*/
public boolean encoder();
/**
* 是否转换小写
*
* @return
*/
public boolean lowerCase();
/**
* 签名
*
* @param obj
* @return
*/
public String sign(Object obj);
}

View File

@ -2,6 +2,7 @@ package com.foxinmy.weixin4j.type;
/** /**
* 签名类型 * 签名类型
*
* @className SignType * @className SignType
* @author jy * @author jy
* @date 2014年11月5日 * @date 2014年11月5日
@ -9,5 +10,5 @@ package com.foxinmy.weixin4j.type;
* @see * @see
*/ */
public enum SignType { public enum SignType {
SHA1,MD5 SHA1, MD5, HMAC$SHA256
} }

View File

@ -1,16 +1,9 @@
package com.foxinmy.weixin4j.util; package com.foxinmy.weixin4j.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import com.foxinmy.weixin4j.model.Consts; import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.payment.mch.NativePayNotify;
import com.foxinmy.weixin4j.xml.XmlStream;
/** /**
* 签名工具类 * 签名工具类
@ -66,81 +59,4 @@ public final class DigestUtil {
byte[] data = StringUtil.getBytesUtf8(content); byte[] data = StringUtil.getBytesUtf8(content);
return HexUtil.encodeHexString(getDigest(Consts.MD5).digest(data)); return HexUtil.encodeHexString(getDigest(Consts.MD5).digest(data));
} }
/**
* md5签名(一般用于V3.x支付接口)
*
* @param obj
* 签名对象
* @param paySignKey
* 支付API的密钥
* @return
*/
public static String paysignMd5(Object obj, String paySignKey) {
StringBuilder sb = new StringBuilder();
// a--->string1
sb.append(MapUtil.toJoinString(obj, false, false, null));
// b--->
// string1 最后拼接上 key=paternerKey 得到 stringSignTemp 字符串,
// stringSignTemp 进行 md5 运算
// 再将得到的 字符串所有字符转换为大写 ,得到 sign signValue
sb.append("&key=").append(paySignKey);
return MD5(sb.toString()).toUpperCase();
}
/**
* sha签名(一般用于V2.x支付接口)
*
* @param obj
* 签名对象
* @param paySignKey
* 支付API的密钥<font color="red">请注意排序放进去的是put("appKey",
* paySignKey)</font>
* @return
*/
public static String paysignSha(Object obj, String paySignKey) {
Map<String, String> extra = new HashMap<String, String>();
if (StringUtil.isNotBlank(paySignKey)) {
extra.put("appKey", paySignKey);
}
return SHA1(MapUtil.toJoinString(obj, false, true, extra));
}
/**
* package拼接签名(一般用于V2.x支付接口)
*
* @param signObj
* 签名对象 PayPackageV2
* @param signKey
* 签名key
* @return
*/
public static String packageSign(Object signObj, String signKey) {
StringBuilder sb = new StringBuilder();
// a.对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序) ,
// 使用 URL 键值 对的格式( key1=value1&key2=value2...)拼接成字符串 string1
// 注意:值为空的参数不参与签名
sb.append(MapUtil.toJoinString(signObj, false, false, null));
// b--->
// string1 最后拼接上 key=signKey 得到 stringSignTemp 字符串,
// stringSignTemp 进行 md5 运算
// 再将得到的 字符串所有字符转换为大写 ,得到 sign signValue
sb.append("&key=").append(signKey);
// c---> & d---->
String sign = DigestUtil.MD5(sb.toString()).toUpperCase();
sb.delete(0, sb.length());
// c.对传入参数中所有键值对的 value 进行 urlencode 转码后重新拼接成字符串 string2
sb.append(MapUtil.toJoinString(signObj, true, false, null))
.append("&sign=").append(sign);
return sb.toString();
}
public static void main(String[] args) throws FileNotFoundException {
NativePayNotify notify = XmlStream.fromXML(new FileInputStream(
new File("/Users/jy/Downloads/weixin4j.xml")),
NativePayNotify.class);
notify.setSign(null);
System.err.println(paysignMd5(notify, "GATFzDwbQdbbci3QEQxX2rUBvwTrsMiZ"));
}
} }

View File

@ -35,7 +35,7 @@ public class MapUtil {
* @return * @return
*/ */
public static String toJoinString(Object object, boolean encoder, public static String toJoinString(Object object, boolean encoder,
boolean lowerCase, Map<String, String> extra) { boolean lowerCase) {
Map<String, String> map = new HashMap<String, String>(); Map<String, String> map = new HashMap<String, String>();
JSONObject obj = null; JSONObject obj = null;
if (object instanceof String) { if (object instanceof String) {
@ -46,14 +46,11 @@ public class MapUtil {
for (String key : obj.keySet()) { for (String key : obj.keySet()) {
map.put(key, obj.getString(key)); map.put(key, obj.getString(key));
} }
if (extra != null && !extra.isEmpty()) {
map.putAll(extra);
}
return toJoinString(map, encoder, lowerCase); return toJoinString(map, encoder, lowerCase);
} }
/** /**
* 接字符串 * 接字符串
* *
* @param map * @param map
* 对象 * 对象

View File

@ -43,17 +43,17 @@ public class CashTest extends PayTest {
} }
@Test @Test
public void mpPayment() throws WeixinException, IOException { public void sendCorpPayment() throws WeixinException, IOException {
CorpPayment payment = new CorpPayment("MP001", CorpPayment payment = new CorpPayment("MP001",
"ofW1gwok9vZIyle0YbA-eQe83Uk8", "ofW1gwok9vZIyle0YbA-eQe83Uk8",
MPPaymentCheckNameType.NO_CHECK, "企业付款测试", 1d, "127.0.0.1"); MPPaymentCheckNameType.NO_CHECK, "企业付款测试", 1d, "127.0.0.1");
CorpPaymentResult result = PAY.corpPayment(new FileInputStream(caFile), CorpPaymentResult result = PAY.sendCorpPayment(new FileInputStream(caFile),
payment); payment);
System.err.println(result); System.err.println(result);
} }
@Test @Test
public void mchPaymentQuery() throws WeixinException, IOException { public void queryCorpPayment() throws WeixinException, IOException {
System.err.println(PAY.queryCorpPayment(new FileInputStream(caFile), System.err.println(PAY.queryCorpPayment(new FileInputStream(caFile),
"MP001")); "MP001"));
} }

View File

@ -18,10 +18,13 @@ import com.foxinmy.weixin4j.payment.mch.ApiResult;
import com.foxinmy.weixin4j.payment.mch.MchPayPackage; import com.foxinmy.weixin4j.payment.mch.MchPayPackage;
import com.foxinmy.weixin4j.payment.mch.Order; import com.foxinmy.weixin4j.payment.mch.Order;
import com.foxinmy.weixin4j.payment.mch.PrePay; import com.foxinmy.weixin4j.payment.mch.PrePay;
import com.foxinmy.weixin4j.payment.mch.RefundRecord;
import com.foxinmy.weixin4j.payment.mch.RefundResult;
import com.foxinmy.weixin4j.sign.WeixinPaymentSignature;
import com.foxinmy.weixin4j.sign.WeixinSignature;
import com.foxinmy.weixin4j.type.IdQuery; import com.foxinmy.weixin4j.type.IdQuery;
import com.foxinmy.weixin4j.type.IdType; import com.foxinmy.weixin4j.type.IdType;
import com.foxinmy.weixin4j.type.TradeType; import com.foxinmy.weixin4j.type.TradeType;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.Weixin4jSettings; import com.foxinmy.weixin4j.util.Weixin4jSettings;
/** /**
@ -34,10 +37,13 @@ import com.foxinmy.weixin4j.util.Weixin4jSettings;
* @see * @see
*/ */
public class PayTest { public class PayTest {
protected final static WeixinPayProxy PAY;
protected final static WeixinPayAccount ACCOUNT; protected final static WeixinPayAccount ACCOUNT;
protected final static WeixinSignature SIGNATURE;
protected final static WeixinPayProxy PAY;
static { static {
ACCOUNT = new WeixinPayAccount("appid", "paySignKey", "mchid"); ACCOUNT = new WeixinPayAccount("appid", "paySignKey", "mchid");
SIGNATURE = new WeixinPaymentSignature(ACCOUNT.getPaySignKey());
PAY = new WeixinPayProxy(new Weixin4jSettings(ACCOUNT)); PAY = new WeixinPayProxy(new Weixin4jSettings(ACCOUNT));
} }
/** /**
@ -46,35 +52,34 @@ public class PayTest {
protected File caFile = new File("证书文件:*.p12"); protected File caFile = new File("证书文件:*.p12");
@Test @Test
public void orderQueryV3() throws WeixinException { public void queryOrder() throws WeixinException {
Order order = PAY.orderQuery(new IdQuery("BY2016010800025", Order order = PAY.queryOrder(new IdQuery("BY2016010800025",
IdType.TRADENO)); IdType.TRADENO));
System.err.println(order); System.err.println(order);
String sign = order.getSign(); String sign = order.getSign();
order.setSign(null); order.setSign(null);
String valiSign = DigestUtil.paysignMd5(order, ACCOUNT.getPaySignKey()); String valiSign = SIGNATURE.sign(order);
System.err System.err
.println(String.format("sign=%s,valiSign=%s", sign, valiSign)); .println(String.format("sign=%s,valiSign=%s", sign, valiSign));
Assert.assertEquals(valiSign, sign); Assert.assertEquals(valiSign, sign);
} }
@Test @Test
public void refundQueryV3() throws WeixinException { public void queryRefund() throws WeixinException {
com.foxinmy.weixin4j.payment.mch.RefundRecord record = PAY RefundRecord record = PAY.queryRefund(new IdQuery("TT_1427183696238",
.refundQuery(new IdQuery("TT_1427183696238", IdType.TRADENO)); IdType.TRADENO));
System.err.println(record); System.err.println(record);
// 这里的验证签名需要把details循环拼接 // 这里的验证签名需要把details循环拼接
String sign = record.getSign(); String sign = record.getSign();
record.setSign(null); record.setSign(null);
String valiSign = DigestUtil String valiSign = SIGNATURE.sign(record);
.paysignMd5(record, ACCOUNT.getPaySignKey());
System.err System.err
.println(String.format("sign=%s,valiSign=%s", sign, valiSign)); .println(String.format("sign=%s,valiSign=%s", sign, valiSign));
Assert.assertEquals(valiSign, sign); Assert.assertEquals(valiSign, sign);
} }
@Test @Test
public void downbillV3() throws WeixinException { public void downbill() throws WeixinException {
Calendar c = Calendar.getInstance(); Calendar c = Calendar.getInstance();
System.err.println(c.getTime()); System.err.println(c.getTime());
c.set(Calendar.YEAR, 2015); c.set(Calendar.YEAR, 2015);
@ -86,24 +91,22 @@ public class PayTest {
} }
@Test @Test
public void refundV3() throws WeixinException, IOException { public void refund() throws WeixinException, IOException {
IdQuery idQuery = new IdQuery("TT_1427183696238", IdType.TRADENO); IdQuery idQuery = new IdQuery("TT_1427183696238", IdType.TRADENO);
com.foxinmy.weixin4j.payment.mch.RefundResult result = PAY.refundApply( RefundResult result = PAY.applyRefund(new FileInputStream(caFile),
new FileInputStream(caFile), idQuery, idQuery, "TT_R" + System.currentTimeMillis(), 0.01d, 0.01d,
"TT_R" + System.currentTimeMillis(), 0.01d, 0.01d, null, null, "10020674");
"10020674");
System.err.println(result); System.err.println(result);
String sign = result.getSign(); String sign = result.getSign();
result.setSign(null); result.setSign(null);
String valiSign = DigestUtil String valiSign = SIGNATURE.sign(result);
.paysignMd5(result, ACCOUNT.getPaySignKey());
System.err System.err
.println(String.format("sign=%s,valiSign=%s", sign, valiSign)); .println(String.format("sign=%s,valiSign=%s", sign, valiSign));
Assert.assertEquals(valiSign, sign); Assert.assertEquals(valiSign, sign);
} }
@Test @Test
public void nativeV3() throws WeixinException { public void nativePay() throws WeixinException {
MchPayPackage payPackageV3 = new MchPayPackage(ACCOUNT, MchPayPackage payPackageV3 = new MchPayPackage(ACCOUNT,
"oyFLst1bqtuTcxK-ojF8hOGtLQao", "native测试", "T0001", 0.1d, "oyFLst1bqtuTcxK-ojF8hOGtLQao", "native测试", "T0001", 0.1d,
"notify_url", "127.0.0.1", TradeType.NATIVE); "notify_url", "127.0.0.1", TradeType.NATIVE);
@ -123,8 +126,7 @@ public class PayTest {
System.err.println(result); System.err.println(result);
String sign = result.getSign(); String sign = result.getSign();
result.setSign(null); result.setSign(null);
String valiSign = DigestUtil String valiSign = SIGNATURE.sign(result);
.paysignMd5(result, ACCOUNT.getPaySignKey());
System.err System.err
.println(String.format("sign=%s,valiSign=%s", sign, valiSign)); .println(String.format("sign=%s,valiSign=%s", sign, valiSign));
Assert.assertEquals(valiSign, sign); Assert.assertEquals(valiSign, sign);

View File

@ -34,12 +34,15 @@ import com.foxinmy.weixin4j.http.weixin.WeixinSSLRequestExecutor;
import com.foxinmy.weixin4j.model.Consts; import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.Token; import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.model.WeixinPayOldAccount; import com.foxinmy.weixin4j.model.WeixinPayOldAccount;
import com.foxinmy.weixin4j.mp.payment.v2.OrderV2; import com.foxinmy.weixin4j.mp.oldpayment.OrderV2;
import com.foxinmy.weixin4j.mp.payment.v2.PayPackageV2; import com.foxinmy.weixin4j.mp.oldpayment.PayPackageV2;
import com.foxinmy.weixin4j.mp.payment.v2.RefundRecordV2; import com.foxinmy.weixin4j.mp.oldpayment.RefundRecordV2;
import com.foxinmy.weixin4j.mp.payment.v2.RefundResultV2; import com.foxinmy.weixin4j.mp.oldpayment.RefundResultV2;
import com.foxinmy.weixin4j.mp.oldpayment.WeixinOldPaymentSignature;
import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator; import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.payment.PayRequest; import com.foxinmy.weixin4j.payment.PayRequest;
import com.foxinmy.weixin4j.sign.WeixinPaymentSignature;
import com.foxinmy.weixin4j.sign.WeixinSignature;
import com.foxinmy.weixin4j.token.FileTokenStorager; import com.foxinmy.weixin4j.token.FileTokenStorager;
import com.foxinmy.weixin4j.token.TokenHolder; import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenStorager; import com.foxinmy.weixin4j.token.TokenStorager;
@ -58,7 +61,7 @@ import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer;
/** /**
* V2老支付API * V2老支付API
* *
* @className Pay2Api * @className PayOldApi
* @author jy * @author jy
* @date 2014年10月28日 * @date 2014年10月28日
* @since JDK 1.6 * @since JDK 1.6
@ -66,8 +69,10 @@ import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer;
*/ */
public class PayOldApi extends MpApi { public class PayOldApi extends MpApi {
private final WeixinPayOldAccount payAccount; private final WeixinPayOldAccount weixinAccount;
private final TokenHolder tokenHolder; private final TokenHolder tokenHolder;
private final WeixinSignature weixinMD5Signature;
private final WeixinOldPaymentSignature weixinOldSignature;
/** /**
* 默认使用weixin4j.properties配置信息 * 默认使用weixin4j.properties配置信息
@ -90,14 +95,19 @@ public class PayOldApi extends MpApi {
WeixinPayOldAccount.class), tokenStorager); WeixinPayOldAccount.class), tokenStorager);
} }
public PayOldApi(WeixinPayOldAccount payAccount, TokenStorager tokenStorager) { public PayOldApi(WeixinPayOldAccount weixinAccount,
this.payAccount = payAccount; TokenStorager tokenStorager) {
this.weixinAccount = weixinAccount;
this.tokenHolder = new TokenHolder(new WeixinTokenCreator( this.tokenHolder = new TokenHolder(new WeixinTokenCreator(
payAccount.getId(), payAccount.getSecret()), tokenStorager); weixinAccount.getId(), weixinAccount.getSecret()),
tokenStorager);
this.weixinMD5Signature = new WeixinPaymentSignature(
weixinAccount.getPartnerKey());
this.weixinOldSignature = new WeixinOldPaymentSignature();
} }
public WeixinPayOldAccount getPayAccount() { public WeixinPayOldAccount getPayAccount() {
return this.payAccount; return this.weixinAccount;
} }
/** /**
@ -162,10 +172,10 @@ public class PayOldApi extends MpApi {
payPackage.setProductFee(productFee); payPackage.setProductFee(productFee);
payPackage.setGoodsTag(goodsTag); payPackage.setGoodsTag(goodsTag);
PayRequest payRequest = new PayRequest(getPayAccount().getId(), PayRequest payRequest = new PayRequest(getPayAccount().getId(),
DigestUtil.packageSign(payPackage, getPayAccount() weixinOldSignature.sign(payPackage, getPayAccount()
.getPartnerKey())); .getPartnerKey()));
payRequest.setPaySign(DigestUtil.paysignSha(payRequest, getPayAccount() payRequest.setPaySign(weixinOldSignature.sign(payRequest,
.getPaySignKey())); getPayAccount().getPaySignKey()));
payRequest.setSignType(SignType.SHA1); payRequest.setSignType(SignType.SHA1);
return JSON.toJSONString(payRequest); return JSON.toJSONString(payRequest);
} }
@ -186,9 +196,9 @@ public class PayOldApi extends MpApi {
map.put("noncestr", noncestr); map.put("noncestr", noncestr);
map.put("productid", productId); map.put("productid", productId);
map.put("appkey", getPayAccount().getPaySignKey()); map.put("appkey", getPayAccount().getPaySignKey());
String sign = DigestUtil.paysignSha(map, null); String sign = weixinOldSignature.sign(map);
String ordernative_v2_uri = getRequestUri("ordernative_v2_uri"); String nativepay_uri = getRequestUri("nativepay_old_uri");
return String.format(ordernative_v2_uri, sign, getPayAccount().getId(), return String.format(nativepay_uri, sign, getPayAccount().getId(),
productId, timestamp, noncestr); productId, timestamp, noncestr);
} }
@ -198,12 +208,12 @@ public class PayOldApi extends MpApi {
* @param idQuery * @param idQuery
* 订单号 * 订单号
* @return 订单信息 * @return 订单信息
* @see com.foxinmy.weixin4j.mp.payment.v2.OrderV2 * @see com.foxinmy.weixin4j.mp.oldpayment.OrderV2
* @since V2 * @since V2
* @throws WeixinException * @throws WeixinException
*/ */
public OrderV2 orderQuery(IdQuery idQuery) throws WeixinException { public OrderV2 queryOrder(IdQuery idQuery) throws WeixinException {
String orderquery_uri = getRequestUri("orderquery_v2_uri"); String orderquery_uri = getRequestUri("orderquery_old_uri");
Token token = tokenHolder.getToken(); Token token = tokenHolder.getToken();
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(idQuery.getType().getName()).append("=") sb.append(idQuery.getType().getName()).append("=")
@ -221,7 +231,7 @@ public class PayOldApi extends MpApi {
obj.put("appkey", getPayAccount().getPaySignKey()); obj.put("appkey", getPayAccount().getPaySignKey());
obj.put("package", sb.toString()); obj.put("package", sb.toString());
obj.put("timestamp", timestamp); obj.put("timestamp", timestamp);
String signature = DigestUtil.paysignSha(obj, null); String signature = weixinOldSignature.sign(obj);
obj.clear(); obj.clear();
obj.put("appid", getPayAccount().getId()); obj.put("appid", getPayAccount().getId());
@ -251,7 +261,7 @@ public class PayOldApi extends MpApi {
* 败后重新提交,要采用原来的 out_refund_no总退款金额不能超过用户实际支付金额</br> * 败后重新提交,要采用原来的 out_refund_no总退款金额不能超过用户实际支付金额</br>
* </p> * </p>
* *
* @param caFile * @param certificate
* 证书文件(V2版本后缀为*.pfx) * 证书文件(V2版本后缀为*.pfx)
* @param idQuery * @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级: * 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -268,18 +278,17 @@ public class PayOldApi extends MpApi {
* opUserPasswd * opUserPasswd
* *
* @return 退款申请结果 * @return 退款申请结果
* @see com.foxinmy.weixin4j.mp.payment.v2.RefundResultV2 * @see com.foxinmy.weixin4j.mp.oldpayment.RefundResultV2
* @since V2 * @since V2
* @throws WeixinException * @throws WeixinException
*/ */
protected RefundResultV2 refundApply(File caFile, IdQuery idQuery, protected RefundResultV2 applyRefund(InputStream certificate,
String outRefundNo, double totalFee, double refundFee, IdQuery idQuery, String outRefundNo, double totalFee,
String opUserId, Map<String, String> mopara) throws WeixinException { double refundFee, String opUserId, Map<String, String> mopara)
String refund_uri = getRequestUri("refundapply_v2_uri"); throws WeixinException {
String refund_uri = getRequestUri("refundapply_old_uri");
WeixinResponse response = null; WeixinResponse response = null;
InputStream ca = null;
try { try {
ca = new FileInputStream(caFile);
Map<String, String> map = new HashMap<String, String>(); Map<String, String> map = new HashMap<String, String>();
map.put("input_charset", Consts.UTF_8.name()); map.put("input_charset", Consts.UTF_8.name());
// 版本号 // 版本号
@ -298,24 +307,23 @@ public class PayOldApi extends MpApi {
if (mopara != null && !mopara.isEmpty()) { if (mopara != null && !mopara.isEmpty()) {
map.putAll(mopara); map.putAll(mopara);
} }
String sign = DigestUtil.paysignMd5(map, getPayAccount() String sign = weixinMD5Signature.sign(map);
.getPartnerKey());
map.put("sign", sign.toUpperCase()); map.put("sign", sign.toUpperCase());
SSLContext ctx = null; SSLContext ctx = null;
KeyStore ks = null; KeyStore ks = null;
String jksPwd = ""; String jksPwd = "";
File jksFile = new File(String.format("%s/tenpay_cacert.jks", File jksFile = new File(String.format("%s/tenpay_cacert.jks",
caFile.getParent())); Weixin4jConfigUtil.getClassPathValue("weixin4j.tmpdir",
System.getProperty("java.io.tmpdir"))));
// create jks ca // create jks ca
if (!jksFile.exists()) { if (!jksFile.exists()) {
CertificateFactory cf = CertificateFactory CertificateFactory cf = CertificateFactory
.getInstance(com.foxinmy.weixin4j.model.Consts.X509); .getInstance(Consts.X509);
java.security.cert.Certificate cert = cf java.security.cert.Certificate cert = cf
.generateCertificate(PayOldApi.class .generateCertificate(PayOldApi.class
.getResourceAsStream("cacert.pem")); .getResourceAsStream("cacert.pem"));
ks = KeyStore ks = KeyStore.getInstance(Consts.JKS);
.getInstance(com.foxinmy.weixin4j.model.Consts.JKS);
ks.load(null, null); ks.load(null, null);
ks.setCertificateEntry("tenpay", cert); ks.setCertificateEntry("tenpay", cert);
FileOutputStream os = new FileOutputStream(jksFile); FileOutputStream os = new FileOutputStream(jksFile);
@ -324,20 +332,20 @@ public class PayOldApi extends MpApi {
} }
// load jks ca // load jks ca
TrustManagerFactory tmf = TrustManagerFactory TrustManagerFactory tmf = TrustManagerFactory
.getInstance(com.foxinmy.weixin4j.model.Consts.SunX509); .getInstance(Consts.SunX509);
ks = KeyStore.getInstance(com.foxinmy.weixin4j.model.Consts.JKS); ks = KeyStore.getInstance(Consts.JKS);
FileInputStream is = new FileInputStream(jksFile); FileInputStream is = new FileInputStream(jksFile);
ks.load(is, jksPwd.toCharArray()); ks.load(is, jksPwd.toCharArray());
tmf.init(ks); tmf.init(ks);
is.close(); is.close();
// load pfx ca // load pfx ca
KeyManagerFactory kmf = KeyManagerFactory KeyManagerFactory kmf = KeyManagerFactory
.getInstance(com.foxinmy.weixin4j.model.Consts.SunX509); .getInstance(Consts.SunX509);
ks = KeyStore.getInstance(com.foxinmy.weixin4j.model.Consts.PKCS12); ks = KeyStore.getInstance(Consts.PKCS12);
ks.load(ca, getPayAccount().getPartnerId().toCharArray()); ks.load(certificate, getPayAccount().getPartnerId().toCharArray());
kmf.init(ks, getPayAccount().getPartnerId().toCharArray()); kmf.init(ks, getPayAccount().getPartnerId().toCharArray());
ctx = SSLContext.getInstance(com.foxinmy.weixin4j.model.Consts.TLS); ctx = SSLContext.getInstance(Consts.TLS);
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(),
new SecureRandom()); new SecureRandom());
@ -349,9 +357,9 @@ public class PayOldApi extends MpApi {
} catch (Exception e) { } catch (Exception e) {
throw new WeixinException(e); throw new WeixinException(e);
} finally { } finally {
if (ca != null) { if (certificate != null) {
try { try {
ca.close(); certificate.close();
} catch (IOException e) { } catch (IOException e) {
; ;
} }
@ -364,7 +372,7 @@ public class PayOldApi extends MpApi {
/** /**
* 退款申请 * 退款申请
* *
* @param caFile * @param certificate
* 证书文件(V2版本后缀为*.pfx) * 证书文件(V2版本后缀为*.pfx)
* @param idQuery * @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级: * 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -379,21 +387,21 @@ public class PayOldApi extends MpApi {
* 操作员帐号, 默认为商户号 * 操作员帐号, 默认为商户号
* @param opUserPasswd * @param opUserPasswd
* 操作员密码,默认为商户后台登录密码 * 操作员密码,默认为商户后台登录密码
* @see {@link #refundApply(File, IdQuery, String, double, double, String, Map)} * @see {@link #applyRefund(InputStream, IdQuery, String, double, double, String, Map)}
*/ */
public RefundResultV2 refundApply(File caFile, IdQuery idQuery, public RefundResultV2 applyRefund(InputStream certificate, IdQuery idQuery,
String outRefundNo, double totalFee, double refundFee, String outRefundNo, double totalFee, double refundFee,
String opUserId, String opUserPasswd) throws WeixinException { String opUserId, String opUserPasswd) throws WeixinException {
Map<String, String> mopara = new HashMap<String, String>(); Map<String, String> mopara = new HashMap<String, String>();
mopara.put("op_user_passwd", DigestUtil.MD5(opUserPasswd)); mopara.put("op_user_passwd", DigestUtil.MD5(opUserPasswd));
return refundApply(caFile, idQuery, outRefundNo, totalFee, refundFee, return applyRefund(certificate, idQuery, outRefundNo, totalFee,
opUserId, mopara); refundFee, opUserId, mopara);
} }
/** /**
* 退款申请 * 退款申请
* *
* @param caFile * @param certificate
* 证书文件(V2版本后缀为*.pfx) * 证书文件(V2版本后缀为*.pfx)
* @param idQuery * @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级: * 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -417,10 +425,10 @@ public class PayOldApi extends MpApi {
* @param refundType * @param refundType
* 为空或者填 1:商户号余额退款;2:现金帐号 退款;3:优先商户号退款,若商户号余额不足, 再做现金帐号退款使用 2 * 为空或者填 1:商户号余额退款;2:现金帐号 退款;3:优先商户号退款,若商户号余额不足, 再做现金帐号退款使用 2
* 3 ,需联系财 付通开通此功能 * 3 ,需联系财 付通开通此功能
* @see {@link #refundApply(File, IdQuery, String, double, double, String, Map)} * @see {@link #applyRefund(InputStream, IdQuery, String, double, double, String, Map)}
* @return 退款结果 * @return 退款结果
*/ */
public RefundResultV2 refundApply(File caFile, IdQuery idQuery, public RefundResultV2 applyRefund(InputStream certificate, IdQuery idQuery,
String outRefundNo, double totalFee, double refundFee, String outRefundNo, double totalFee, double refundFee,
String opUserId, String opUserPasswd, String recvUserId, String opUserId, String opUserPasswd, String recvUserId,
String reccvUserName, RefundType refundType) throws WeixinException { String reccvUserName, RefundType refundType) throws WeixinException {
@ -435,8 +443,8 @@ public class PayOldApi extends MpApi {
if (refundType != null) { if (refundType != null) {
mopara.put("refund_type", Integer.toString(refundType.getVal())); mopara.put("refund_type", Integer.toString(refundType.getVal()));
} }
return refundApply(caFile, idQuery, outRefundNo, totalFee, refundFee, return applyRefund(certificate, idQuery, outRefundNo, totalFee,
opUserId, mopara); refundFee, opUserId, mopara);
} }
/** /**
@ -474,7 +482,7 @@ public class PayOldApi extends MpApi {
if (file.exists()) { if (file.exists()) {
return file; return file;
} }
String downloadbill_uri = getRequestUri("downloadbill_v2_uri"); String downloadbill_uri = getRequestUri("downloadbill_old_uri");
Map<String, String> map = new LinkedHashMap<String, String>(); Map<String, String> map = new LinkedHashMap<String, String>();
map.put("spid", getPayAccount().getPartnerId()); map.put("spid", getPayAccount().getPartnerId());
@ -523,19 +531,18 @@ public class PayOldApi extends MpApi {
* 四个参数必填一个,优先级为: * 四个参数必填一个,优先级为:
* refund_id>out_refund_no>transaction_id>out_trade_no * refund_id>out_refund_no>transaction_id>out_trade_no
* @return 退款记录 * @return 退款记录
* @see com.foxinmy.weixin4j.mp.payment.v2.RefundRecordV2 * @see com.foxinmy.weixin4j.mp.oldpayment.RefundRecordV2
* @see com.foxinmy.weixin4j.mp.payment.v2.RefundDetailV2 * @see com.foxinmy.weixin4j.mp.oldpayment.RefundDetailV2
* @since V2 * @since V2
* @throws WeixinException * @throws WeixinException
*/ */
public RefundRecordV2 refundQuery(IdQuery idQuery) throws WeixinException { public RefundRecordV2 queryRefund(IdQuery idQuery) throws WeixinException {
String refundquery_uri = getRequestUri("refundquery_v2_uri"); String refundquery_uri = getRequestUri("refundquery_old_uri");
Map<String, String> map = new HashMap<String, String>(); Map<String, String> map = new HashMap<String, String>();
map.put("input_charset", Consts.UTF_8.name()); map.put("input_charset", Consts.UTF_8.name());
map.put("partner", getPayAccount().getPartnerId()); map.put("partner", getPayAccount().getPartnerId());
map.put(idQuery.getType().getName(), idQuery.getId()); map.put(idQuery.getType().getName(), idQuery.getId());
String sign = DigestUtil.paysignMd5(map, getPayAccount() String sign = weixinMD5Signature.sign(map);
.getPartnerKey());
map.put("sign", sign.toLowerCase()); map.put("sign", sign.toLowerCase());
WeixinResponse response = weixinExecutor.get(refundquery_uri, map); WeixinResponse response = weixinExecutor.get(refundquery_uri, map);
return ListsuffixResultDeserializer.deserialize(response.getAsString(), return ListsuffixResultDeserializer.deserialize(response.getAsString(),
@ -561,7 +568,7 @@ public class PayOldApi extends MpApi {
public JsonResult deliverNotify(String openId, String transid, public JsonResult deliverNotify(String openId, String transid,
String outTradeNo, boolean status, String statusMsg) String outTradeNo, boolean status, String statusMsg)
throws WeixinException { throws WeixinException {
String delivernotify_uri = getRequestUri("delivernotify_uri"); String delivernotify_uri = getRequestUri("delivernotify_old_uri");
Token token = tokenHolder.getToken(); Token token = tokenHolder.getToken();
Map<String, String> map = new HashMap<String, String>(); Map<String, String> map = new HashMap<String, String>();
@ -573,7 +580,7 @@ public class PayOldApi extends MpApi {
map.put("deliver_timestamp", DateUtil.timestamp2string()); map.put("deliver_timestamp", DateUtil.timestamp2string());
map.put("deliver_status", status ? "1" : "0"); map.put("deliver_status", status ? "1" : "0");
map.put("deliver_msg", statusMsg); map.put("deliver_msg", statusMsg);
map.put("app_signature", DigestUtil.paysignSha(map, null)); map.put("app_signature", weixinOldSignature.sign(map));
map.put("sign_method", SignType.SHA1.name().toLowerCase()); map.put("sign_method", SignType.SHA1.name().toLowerCase());
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
@ -594,11 +601,10 @@ public class PayOldApi extends MpApi {
*/ */
public JsonResult updateFeedback(String openId, String feedbackId) public JsonResult updateFeedback(String openId, String feedbackId)
throws WeixinException { throws WeixinException {
String payfeedback_update_uri = getRequestUri("payfeedback_update_uri"); String payfeedback_uri = getRequestUri("payfeedback_old_uri");
Token token = tokenHolder.getToken(); Token token = tokenHolder.getToken();
WeixinResponse response = weixinExecutor.get(String.format( WeixinResponse response = weixinExecutor.get(String.format(
payfeedback_update_uri, token.getAccessToken(), openId, payfeedback_uri, token.getAccessToken(), openId, feedbackId));
feedbackId));
return response.getAsJsonResult(); return response.getAsJsonResult();
} }
} }

View File

@ -6,12 +6,10 @@
api_base_url=https://api.weixin.qq.com api_base_url=https://api.weixin.qq.com
api_cgi_url={api_base_url}/cgi-bin api_cgi_url={api_base_url}/cgi-bin
mp_base_url=https://mp.weixin.qq.com/cgi-bin mp_base_url=https://mp.weixin.qq.com/cgi-bin
mch_base_url=https://api.mch.weixin.qq.com
tenpay_base_url=http://mch.tenpay.com tenpay_base_url=http://mch.tenpay.com
tenpay_ssl_base_url=https://mch.tenpay.com tenpay_ssl_base_url=https://mch.tenpay.com
tenpay_gw_base_url=https://gw.tenpay.com tenpay_gw_base_url=https://gw.tenpay.com
# \u7f51\u9875\u6388\u6743\u83b7\u53d6\u7528\u6237\u4fe1\u606f # \u7f51\u9875\u6388\u6743\u83b7\u53d6\u7528\u6237\u4fe1\u606f
sns_user_auth_uri=https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect sns_user_auth_uri=https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect
#open_user_auth_uri=https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect #open_user_auth_uri=https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect
@ -107,7 +105,6 @@ kfsession_list_uri={api_base_url}/customservice/kfsession/getsessionlist?access_
kfsession_wait_uri={api_base_url}/customservice/kfsession/getwaitcase?access_token=%s kfsession_wait_uri={api_base_url}/customservice/kfsession/getwaitcase?access_token=%s
# \u957f\u94fe\u63a5\u8f6c\u77ed\u94fe\u63a5 # \u957f\u94fe\u63a5\u8f6c\u77ed\u94fe\u63a5
shorturl_uri={api_cgi_url}/shorturl?access_token=%s shorturl_uri={api_cgi_url}/shorturl?access_token=%s
p_shorturl_uri={mch_base_url}/tools/shorturl
# \u8bbe\u7f6e\u5907\u6ce8\u540d # \u8bbe\u7f6e\u5907\u6ce8\u540d
updateremark_uri={api_cgi_url}/user/info/updateremark?access_token=%s updateremark_uri={api_cgi_url}/user/info/updateremark?access_token=%s
# \u8bbe\u7f6e\u6a21\u677f\u6d88\u606f\u6240\u5904\u884c\u4e1a # \u8bbe\u7f6e\u6a21\u677f\u6d88\u606f\u6240\u5904\u884c\u4e1a
@ -126,48 +123,26 @@ template_send_uri={api_cgi_url}/message/template/send?access_token=%s
semantic_uri={api_base_url}/semantic/semproxy/search?access_token=%s semantic_uri={api_base_url}/semantic/semproxy/search?access_token=%s
# \u5fae\u4fe1\u670d\u52a1\u5730\u5740 # \u5fae\u4fe1\u670d\u52a1\u5730\u5740
getcallbackip_uri={api_cgi_url}/getcallbackip?access_token=%s getcallbackip_uri={api_cgi_url}/getcallbackip?access_token=%s
# v2\u8ba2\u5355\u67e5\u8be2
orderquery_v2_uri={api_base_url}/pay/orderquery?access_token=%s
# v2native\u652f\u4ed8
ordernative_v2_uri=weixin://wxpay/bizpayurl?sign=%s&appid=%s&productid=%s&timestamp=%s&nocestr=%s\udbff\udce0\udbff\udce0\udbff\udce0\udbff\udce0\udbff\udc57\udbff\udc57\udbff\udc57\udbff\udc57\udbff\udc71\udbff\udc71\udbff\udc71\udbff\udc71\udbff\udc54\udbff\udc54\udbff\udc54\udbff\udc54\udbff\udc53\udbff\udc53\udbff\udc53\udbff\udc53\udbff\udce0\udbff\udce0\udbff\udce0\udbff\udce0\udbff\udc76\udbff\udc76\udbff\udc76\udbff\udc76\udbff\udcdc\udbff\udcdc\udbff\udcdc\udbff\udcdc\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcde\udbff\udcde\udbff\udcde\udbff\udcde\udbff\udc69\udbff\udc69\udbff\udc69\udbff\udc69\udbff\udcdf\udbff\udcdf\udbff\udcdf\udbff\udcdf\udbff\udc69\udbff\udc69\udbff\udc69\udbff\udc69\udbff\udc77\udbff\udc77\udbff\udc77\udbff\udc77\udbff\udc57\udbff\udc57\udbff\udc57\udbff\udc57\udbff\udc71\udbff\udc71\udbff\udc71\udbff\udc71\udbff\udc54\udbff\udc54\udbff\udc54\udbff\udc54\udbff\udc68\udbff\udc68\udbff\udc68\udbff\udc68\udbff\udcdc\udbff\udcdc\udbff\udcdc\udbff\udcdc\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd\udbff\udcdd
# \u53d1\u8d27\u901a\u77e5
delivernotify_uri={api_base_url}/pay/delivernotify?access_token=%s
# \u7ef4\u6743\u5904\u7406
payfeedback_update_uri={api_base_url}/payfeedback/update?access_token=%s&openid=%s&feedbackid=%s
# v2\u5bf9\u8d26\u5355\u4e0b\u8f7d
downloadbill_v2_uri={tenpay_base_url}/cgi-bin/mchdown_real_new.cgi
# v2\u9000\u6b3e\u67e5\u8be2
refundquery_v2_uri={tenpay_gw_base_url}/gateway/normalrefundquery.xml
# v2\u9000\u6b3e\u7533\u8bf7
refundapply_v2_uri={tenpay_ssl_base_url}/refundapi/gateway/refund.xml
# \u8ba2\u5355\u67e5\u8be2
orderquery_v3_uri={mch_base_url}/pay/orderquery
# \u5173\u95ed\u8ba2\u5355
closeorder_uri={mch_base_url}/pay/closeorder
# \u5bf9\u8d26\u5355\u4e0b\u8f7d
downloadbill_v3_uri={mch_base_url}/pay/downloadbill
# \u9000\u6b3e\u67e5\u8be2
refundquery_v3_uri={mch_base_url}/pay/refundquery
# \u9000\u6b3e\u7533\u8bf7
refund_v3_uri={mch_base_url}/secapi/pay/refund
# \u51b2\u6b63\u64a4\u9500
reverse_uri={mch_base_url}/secapi/pay/reverse
# \u88ab\u626b\u652f\u4ed8
micropay_uri={mch_base_url}/pay/micropay
# \u63a5\u53e3\u4e0a\u62a5
pay_report_uri={mch_base_url}/payitil/report
# \u7edf\u4e00\u8ba2\u5355\u751f\u6210
unifiedorder_uri={mch_base_url}/pay/unifiedorder
# native\u652f\u4ed8\u94fe\u63a5
nativepay_v2_uri=weixin://wxpay/bizpayurl?sign=%s&appid=%s&productid=%s&timestamp=%s&noncestr=%s
nativepay_v3_uri=weixin://wxpay/bizpayurl?sign=%s&appid=%s&mch_id=%s&product_id=%s&time_stamp=%s&nonce_str=%s
# \u6570\u636e\u7edf\u8ba1 # \u6570\u636e\u7edf\u8ba1
datacube_uri={api_base_url}/datacube/%s?access_token=%s datacube_uri={api_base_url}/datacube/%s?access_token=%s
##########################\u8001\u7248\u672c\u652f\u4ed8~start
# \u8ba2\u5355\u67e5\u8be2
orderquery_old_uri={api_base_url}/pay/orderquery?access_token=%s
# \u53d1\u8d27\u901a\u77e5
delivernotify_old_uri={api_base_url}/pay/delivernotify?access_token=%s
# \u7ef4\u6743\u5904\u7406
payfeedback_old_uri={api_base_url}/payfeedback/update?access_token=%s&openid=%s&feedbackid=%s
# \u5bf9\u8d26\u5355\u4e0b\u8f7d
downloadbill_old_uri={tenpay_base_url}/cgi-bin/mchdown_real_new.cgi
# \u9000\u6b3e\u67e5\u8be2
refundquery_old_uri={tenpay_gw_base_url}/gateway/normalrefundquery.xml
# \u9000\u6b3e\u7533\u8bf7
refundapply_old_uri={tenpay_ssl_base_url}/refundapi/gateway/refund.xml
# native\u652f\u4ed8
nativepay_old_uri=weixin://wxpay/bizpayurl?sign=%s&appid=%s&productid=%s&timestamp=%s&noncestr=%s
##########################\u8001\u7248\u672c\u652f\u4ed8~end
# \u4e0a\u4f20\u6c38\u4e45\u56fe\u6587\u7d20\u6750 # \u4e0a\u4f20\u6c38\u4e45\u56fe\u6587\u7d20\u6750
material_article_upload_uri={api_cgi_url}/material/add_news?access_token=%s material_article_upload_uri={api_cgi_url}/material/add_news?access_token=%s
# \u4e0a\u4f20\u6c38\u4e45\u5a92\u4f53\u7d20\u6750 # \u4e0a\u4f20\u6c38\u4e45\u5a92\u4f53\u7d20\u6750
@ -183,19 +158,4 @@ material_media_count_uri={api_cgi_url}/material/get_materialcount?access_token=%
# \u83b7\u53d6\u5a92\u4f53\u7d20\u6750\u5217\u8868 # \u83b7\u53d6\u5a92\u4f53\u7d20\u6750\u5217\u8868
material_media_list_uri={api_cgi_url}/material/batchget_material?access_token=%s material_media_list_uri={api_cgi_url}/material/batchget_material?access_token=%s
# \u81ea\u52a8\u56de\u590d\u89c4\u5219 # \u81ea\u52a8\u56de\u590d\u89c4\u5219
autoreply_setting_get_uri={api_cgi_url}/get_current_autoreply_info?access_token=%s autoreply_setting_get_uri={api_cgi_url}/get_current_autoreply_info?access_token=%s
# \u53d1\u653e\u4ee3\u91d1\u5238
coupon_send_uri={mch_base_url}/mmpaymkttransfers/send_coupon
# \u67e5\u8be2\u4ee3\u91d1\u5238\u6279\u6b21\u4fe1\u606f
couponstock_query_uri={mch_base_url}/mmpaymkttransfers/query_coupon_stock
# \u67e5\u8be2\u4ee3\u91d1\u5238\u8be6\u7ec6\u4fe1\u606f
coupondetail_query_uri={mch_base_url}/promotion/query_coupon
# \u53d1\u9001\u73b0\u91d1\u7ea2\u5305
redpack_send_uri={mch_base_url}/mmpaymkttransfers/sendredpack
# \u67e5\u8be2\u73b0\u91d1\u7ea2\u5305
redpack_query_uri={mch_base_url}/mmpaymkttransfers/gethbinfo
# \u4f01\u4e1a\u5411\u4e2a\u4eba\u4ed8\u6b3e
mp_payment_uri={mch_base_url}/mmpaymkttransfers/promotion/transfers
# \u4f01\u4e1a\u4ed8\u6b3e\u67e5\u8be2
mp_payquery_uri={mch_base_url}/mmpaymkttransfers/gettransferinfo

View File

@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.mp.payment.v2; package com.foxinmy.weixin4j.mp.oldpayment;
import java.io.Serializable; import java.io.Serializable;

View File

@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.mp.payment.v2; package com.foxinmy.weixin4j.mp.oldpayment;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;

View File

@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.mp.payment.v2; package com.foxinmy.weixin4j.mp.oldpayment;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -11,7 +11,6 @@ import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.model.WeixinPayOldAccount; import com.foxinmy.weixin4j.model.WeixinPayOldAccount;
import com.foxinmy.weixin4j.payment.PayRequest; import com.foxinmy.weixin4j.payment.PayRequest;
import com.foxinmy.weixin4j.util.DigestUtil;
/** /**
* V2 Native支付时的回调响应 * V2 Native支付时的回调响应
@ -64,10 +63,12 @@ public class NativePayResponseV2 extends PayRequest {
*/ */
public NativePayResponseV2(WeixinPayOldAccount weixinAccount, public NativePayResponseV2(WeixinPayOldAccount weixinAccount,
PayPackageV2 payPackage) { PayPackageV2 payPackage) {
super(weixinAccount.getId(), DigestUtil.packageSign(payPackage, super(weixinAccount.getId(), null);
weixinAccount.getPartnerKey()));
this.retCode = "0"; this.retCode = "0";
this.retMsg = "OK"; this.retMsg = "OK";
WeixinOldPaymentSignature weixinSignature = new WeixinOldPaymentSignature();
setPackageInfo(weixinSignature.sign(payPackage,
weixinAccount.getPartnerKey()));
Map<String, String> map = new HashMap<String, String>(); Map<String, String> map = new HashMap<String, String>();
map.put("appid", weixinAccount.getId()); map.put("appid", weixinAccount.getId());
map.put("appkey", weixinAccount.getPaySignKey()); map.put("appkey", weixinAccount.getPaySignKey());
@ -76,7 +77,7 @@ public class NativePayResponseV2 extends PayRequest {
map.put("package", getPackageInfo()); map.put("package", getPackageInfo());
map.put("retcode", getRetCode()); map.put("retcode", getRetCode());
map.put("reterrmsg", getRetMsg()); map.put("reterrmsg", getRetMsg());
this.setPaySign(DigestUtil.paysignSha(map, null)); this.setPaySign(weixinSignature.sign(map));
} }
public String getRetCode() { public String getRetCode() {

View File

@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.mp.payment.v2; package com.foxinmy.weixin4j.mp.oldpayment;
import java.util.Date; import java.util.Date;

View File

@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.mp.payment.v2; package com.foxinmy.weixin4j.mp.oldpayment;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;

View File

@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.mp.payment.v2; package com.foxinmy.weixin4j.mp.oldpayment;
import java.util.Date; import java.util.Date;

View File

@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.mp.payment.v2; package com.foxinmy.weixin4j.mp.oldpayment;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;

View File

@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.mp.payment.v2; package com.foxinmy.weixin4j.mp.oldpayment;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;

View File

@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.mp.payment.v2; package com.foxinmy.weixin4j.mp.oldpayment;
import java.util.List; import java.util.List;
@ -17,7 +17,7 @@ import com.foxinmy.weixin4j.xml.ListsuffixResult;
* @author jy * @author jy
* @date 2014年11月1日 * @date 2014年11月1日
* @since JDK 1.6 * @since JDK 1.6
* @see com.foxinmy.weixin4j.mp.payment.v2.RefundDetailV2 * @see com.foxinmy.weixin4j.mp.oldpayment.RefundDetailV2
*/ */
@XmlRootElement @XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)

View File

@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.mp.payment.v2; package com.foxinmy.weixin4j.mp.oldpayment;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;

View File

@ -0,0 +1,70 @@
package com.foxinmy.weixin4j.mp.oldpayment;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import com.foxinmy.weixin4j.sign.AbstractWeixinSignature;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.MapUtil;
/**
* 老版本支付签名
*
* @className WeixinOldPaymentSignature
* @author jy
* @date 2016年3月26日
* @since JDK 1.6
* @see
*/
public class WeixinOldPaymentSignature extends AbstractWeixinSignature {
@Override
public boolean lowerCase() {
return true;
}
@Override
public String sign(Object obj) {
return DigestUtil.SHA1(join(obj).toString());
}
public String sign(Object obj, String paySignKey) {
if (obj instanceof Map) {
JSONPath.set(obj, "appKey", paySignKey);
} else {
((JSONObject) JSON.toJSON(obj)).put("appKey", paySignKey);
}
return DigestUtil.SHA1(join(obj).toString());
}
/**
* package拼接签名
*
* @param packageInfo
* package对象
* @param partnerKey
* 签名key
* @return
*/
public String sign(PayPackageV2 packageInfo, String partnerKey) {
StringBuilder sb = new StringBuilder();
// a.对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序) ,
// 使用 URL 键值 对的格式( key1=value1&key2=value2...)拼接成字符串 string1
// 注意:值为空的参数不参与签名
sb.append(MapUtil.toJoinString(packageInfo, false, false));
// b--->
// string1 最后拼接上 key=signKey 得到 stringSignTemp 字符串,
// stringSignTemp 进行 md5 运算
// 再将得到的 字符串所有字符转换为大写 ,得到 sign signValue
sb.append("&key=").append(partnerKey);
// c---> & d---->
String sign = DigestUtil.MD5(sb.toString()).toUpperCase();
sb.delete(0, sb.length());
// c.对传入参数中所有键值对的 value 进行 urlencode 转码后重新拼接成字符串 string2
sb.append(MapUtil.toJoinString(packageInfo, true, false))
.append("&sign=").append(sign);
return sb.toString();
}
}

View File

@ -1,6 +1,8 @@
package com.foxinmy.weixin4j.mp.test; package com.foxinmy.weixin4j.mp.test;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Calendar; import java.util.Calendar;
import org.junit.Test; import org.junit.Test;
@ -36,20 +38,21 @@ public class PayTest {
@Test @Test
public void orderQueryV2() throws WeixinException { public void orderQueryV2() throws WeixinException {
System.err.println(PAY2.orderQuery(new IdQuery("D14110500021", System.err.println(PAY2.queryOrder(new IdQuery("D14110500021",
IdType.REFUNDNO))); IdType.REFUNDNO)));
} }
@Test @Test
public void refundV2() throws WeixinException { public void refundV2() throws WeixinException, IOException {
IdQuery idQuery = new IdQuery("D15020300005", IdType.TRADENO); IdQuery idQuery = new IdQuery("D15020300005", IdType.TRADENO);
System.err.println(PAY2.refundApply(caFile, idQuery, "1422925555037", System.err.println(PAY2.applyRefund(new FileInputStream(caFile),
16d, 16d, "1221928801", "111111", null, null, null)); idQuery, "1422925555037", 16d, 16d, "1221928801", "111111",
null, null, null));
} }
@Test @Test
public void refundQueryV2() throws WeixinException { public void refundQueryV2() throws WeixinException {
System.err.println(PAY2.refundQuery(new IdQuery("D14123000004", System.err.println(PAY2.queryRefund(new IdQuery("D14123000004",
IdType.TRADENO))); IdType.TRADENO)));
} }

View File

@ -6,7 +6,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.foxinmy.weixin4j.model.Token; import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.payment.v2.RefundRecordV2; import com.foxinmy.weixin4j.mp.oldpayment.RefundRecordV2;
import com.foxinmy.weixin4j.payment.mch.Order; import com.foxinmy.weixin4j.payment.mch.Order;
import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer; import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer;
import com.foxinmy.weixin4j.xml.XmlStream; import com.foxinmy.weixin4j.xml.XmlStream;

View File

@ -14,10 +14,10 @@ import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBElement;
@ -88,7 +88,7 @@ public class WeixinMessageDispatcher {
/** /**
* 消息转换 * 消息转换
*/ */
private ThreadLocal<Map<Class<? extends WeixinMessage>, Unmarshaller>> messageUnmarshaller; private Map<Class<? extends WeixinMessage>, Unmarshaller> messageUnmarshaller;
/** /**
* 是否总是响应请求,如未匹配到MessageHandler时回复空白消息 * 是否总是响应请求,如未匹配到MessageHandler时回复空白消息
*/ */
@ -100,12 +100,7 @@ public class WeixinMessageDispatcher {
public WeixinMessageDispatcher(WeixinMessageMatcher messageMatcher) { public WeixinMessageDispatcher(WeixinMessageMatcher messageMatcher) {
this.messageMatcher = messageMatcher; this.messageMatcher = messageMatcher;
this.messageUnmarshaller = new ThreadLocal<Map<Class<? extends WeixinMessage>, Unmarshaller>>() { this.messageUnmarshaller = new ConcurrentHashMap<Class<? extends WeixinMessage>, Unmarshaller>();
@Override
protected Map<Class<? extends WeixinMessage>, Unmarshaller> initialValue() {
return new HashMap<Class<? extends WeixinMessage>, Unmarshaller>();
}
};
} }
/** /**
@ -125,7 +120,8 @@ public class WeixinMessageDispatcher {
WeixinMessageKey messageKey = defineMessageKey(messageTransfer, request); WeixinMessageKey messageKey = defineMessageKey(messageTransfer, request);
Class<? extends WeixinMessage> targetClass = messageMatcher Class<? extends WeixinMessage> targetClass = messageMatcher
.match(messageKey); .match(messageKey);
WeixinMessage message = messageRead(request.getOriginalContent(), targetClass); WeixinMessage message = messageRead(request.getOriginalContent(),
targetClass);
logger.info("define '{}' matched '{}'", messageKey, targetClass); logger.info("define '{}' matched '{}'", messageKey, targetClass);
MessageHandlerExecutor handlerExecutor = getHandlerExecutor(context, MessageHandlerExecutor handlerExecutor = getHandlerExecutor(context,
request, messageKey, message, messageTransfer.getNodeNames()); request, messageKey, message, messageTransfer.getNodeNames());
@ -179,6 +175,7 @@ public class WeixinMessageDispatcher {
*/ */
protected void noHandlerFound(ChannelHandlerContext context, protected void noHandlerFound(ChannelHandlerContext context,
WeixinRequest request, Object message) { WeixinRequest request, Object message) {
logger.warn("no handler found {}", request);
if (alwaysResponse) { if (alwaysResponse) {
context.write(BlankResponse.global); context.write(BlankResponse.global);
} else { } else {
@ -209,13 +206,13 @@ public class WeixinMessageDispatcher {
*/ */
protected MessageHandlerExecutor getHandlerExecutor( protected MessageHandlerExecutor getHandlerExecutor(
ChannelHandlerContext context, WeixinRequest request, ChannelHandlerContext context, WeixinRequest request,
WeixinMessageKey messageKey, WeixinMessage message, Set<String> nodeNames) WeixinMessageKey messageKey, WeixinMessage message,
throws WeixinException { Set<String> nodeNames) throws WeixinException {
WeixinMessageHandler[] messageHandlers = getMessageHandlers(); WeixinMessageHandler[] messageHandlers = getMessageHandlers();
if (messageHandlers == null) { if (messageHandlers == null) {
return null; return null;
} }
logger.info("resolve handlers '{}'", this.messageHandlerList); logger.info("resolve message handlers '{}'", this.messageHandlerList);
List<WeixinMessageHandler> matchedMessageHandlers = new ArrayList<WeixinMessageHandler>(); List<WeixinMessageHandler> matchedMessageHandlers = new ArrayList<WeixinMessageHandler>();
for (WeixinMessageHandler handler : messageHandlers) { for (WeixinMessageHandler handler : messageHandlers) {
if (handler.canHandle(request, message, nodeNames)) { if (handler.canHandle(request, message, nodeNames)) {
@ -233,7 +230,7 @@ public class WeixinMessageDispatcher {
return m2.weight() - m1.weight(); return m2.weight() - m1.weight();
} }
}); });
logger.info("matched message handlers '{}'", matchedMessageHandlers); logger.info("matched message handler '{}'", matchedMessageHandlers);
return new MessageHandlerExecutor(context, return new MessageHandlerExecutor(context,
matchedMessageHandlers.get(0), getMessageInterceptors()); matchedMessageHandlers.get(0), getMessageInterceptors());
} }
@ -367,6 +364,8 @@ public class WeixinMessageDispatcher {
.size()]); .size()]);
} }
} }
logger.info("resolve message interceptors '{}'",
this.messageInterceptorList);
return this.messageInterceptors; return this.messageInterceptors;
} }
@ -406,12 +405,12 @@ public class WeixinMessageDispatcher {
*/ */
protected Unmarshaller getUnmarshaller(Class<? extends WeixinMessage> clazz) protected Unmarshaller getUnmarshaller(Class<? extends WeixinMessage> clazz)
throws WeixinException { throws WeixinException {
Unmarshaller unmarshaller = messageUnmarshaller.get().get(clazz); Unmarshaller unmarshaller = messageUnmarshaller.get(clazz);
if (unmarshaller == null) { if (unmarshaller == null) {
try { try {
JAXBContext jaxbContext = JAXBContext.newInstance(clazz); JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
unmarshaller = jaxbContext.createUnmarshaller(); unmarshaller = jaxbContext.createUnmarshaller();
messageUnmarshaller.get().put(clazz, unmarshaller); messageUnmarshaller.put(clazz, unmarshaller);
} catch (JAXBException e) { } catch (JAXBException e) {
throw new WeixinException(e); throw new WeixinException(e);
} }

View File

@ -87,6 +87,7 @@ public class WeixinMessageDecoder extends
messageContent = MessageUtil.aesDecrypt(aesToken.getWeixinId(), messageContent = MessageUtil.aesDecrypt(aesToken.getWeixinId(),
aesToken.getAesKey(), encryptContent); aesToken.getAesKey(), encryptContent);
} }
logger.info("read original message {}", messageContent);
WeixinRequest request = new WeixinRequest(req.headers(), method, WeixinRequest request = new WeixinRequest(req.headers(), method,
req.getUri(), encryptType, echoStr, timeStamp, nonce, req.getUri(), encryptType, echoStr, timeStamp, nonce,
signature, msgSignature, messageContent, encryptContent, signature, msgSignature, messageContent, encryptContent,

View File

@ -233,6 +233,9 @@ public final class WeixinServerBootstrap {
*/ */
public WeixinServerBootstrap addHandler( public WeixinServerBootstrap addHandler(
WeixinMessageHandler... messageHandler) { WeixinMessageHandler... messageHandler) {
if (messageHandler == null) {
throw new IllegalArgumentException("messageHandler not be null");
}
messageHandlerList.addAll(Arrays.asList(messageHandler)); messageHandlerList.addAll(Arrays.asList(messageHandler));
return this; return this;
} }
@ -246,6 +249,9 @@ public final class WeixinServerBootstrap {
*/ */
public WeixinServerBootstrap addInterceptor( public WeixinServerBootstrap addInterceptor(
WeixinMessageInterceptor... messageInterceptor) { WeixinMessageInterceptor... messageInterceptor) {
if (messageInterceptor == null) {
throw new IllegalArgumentException("messageInterceptor not be null");
}
messageInterceptorList.addAll(Arrays.asList(messageInterceptor)); messageInterceptorList.addAll(Arrays.asList(messageInterceptor));
return this; return this;
} }
@ -259,6 +265,10 @@ public final class WeixinServerBootstrap {
*/ */
public WeixinServerBootstrap handlerPackagesToScan( public WeixinServerBootstrap handlerPackagesToScan(
String... messageHandlerPackages) { String... messageHandlerPackages) {
if (messageHandlerPackages == null) {
throw new IllegalArgumentException(
"messageHandlerPackages not be null");
}
messageDispatcher.setMessageHandlerPackages(messageHandlerPackages); messageDispatcher.setMessageHandlerPackages(messageHandlerPackages);
return this; return this;
} }
@ -272,6 +282,10 @@ public final class WeixinServerBootstrap {
*/ */
public WeixinServerBootstrap interceptorPackagesToScan( public WeixinServerBootstrap interceptorPackagesToScan(
String... messageInterceptorPackages) { String... messageInterceptorPackages) {
if (messageInterceptorPackages == null) {
throw new IllegalArgumentException(
"messageInterceptorPackages not be null");
}
messageDispatcher messageDispatcher
.setMessageInterceptorPackages(messageInterceptorPackages); .setMessageInterceptorPackages(messageInterceptorPackages);
return this; return this;