签名类接口化

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

View File

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

View File

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

View File

@ -2,21 +2,15 @@ package com.foxinmy.weixin4j.api;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.TypeReference;
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.WeixinSSLRequestExecutor;
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.CouponResult;
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.xml.XmlStream;
@ -29,21 +23,16 @@ import com.foxinmy.weixin4j.xml.XmlStream;
* @since JDK 1.6
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php">代金券文档</a>
*/
public class CouponApi {
private final WeixinRequestExecutor weixinExecutor;
private final WeixinPayAccount weixinAccount;
public class CouponApi extends MchApi {
public CouponApi(WeixinPayAccount weixinAccount) {
this.weixinAccount = weixinAccount;
this.weixinExecutor = new WeixinRequestExecutor();
super(weixinAccount);
}
/**
* 发放代金券(需要证书)
*
* @param ca
* @param certificate
* 后缀为*.p12的证书文件
* @param couponStockId
* 代金券批次id
@ -59,10 +48,10 @@ public class CouponApi {
* href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php?chapter=12_3">发放代金券接口</a>
* @throws WeixinException
*/
public CouponResult sendCoupon(InputStream ca, String couponStockId,
String partnerTradeNo, String openId, String opUserId)
throws WeixinException {
Map<String, String> map = baseMap();
public CouponResult sendCoupon(InputStream certificate,
String couponStockId, String partnerTradeNo, String openId,
String opUserId) throws WeixinException {
Map<String, String> map = createBaseRequestMap(null);
map.put("coupon_stock_id", couponStockId);
map.put("partner_trade_no", partnerTradeNo);
map.put("openid", openId);
@ -75,19 +64,16 @@ public class CouponApi {
map.put("op_user_id", opUserId);
map.put("version", "1.0");
map.put("type", "XML");
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
map.put("sign", weixinSignature.sign(map));
String param = XmlStream.map2xml(map);
WeixinResponse response = null;
try {
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor(
weixinAccount.getCertificateKey(), ca);
response = weixinExecutor.post(PayURLConsts.MCH_COUPONSEND_URL,
param);
response = createSSLRequestExecutor(certificate).post(
getRequestUri("coupon_send_uri"), param);
} finally {
if (ca != null) {
if (certificate != null) {
try {
ca.close();
certificate.close();
} catch (IOException e) {
;
}
@ -110,13 +96,12 @@ public class CouponApi {
*/
public CouponStock queryCouponStock(String couponStockId)
throws WeixinException {
Map<String, String> map = baseMap();
Map<String, String> map = createBaseRequestMap(null);
map.put("coupon_stock_id", couponStockId);
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
map.put("sign", weixinSignature.sign(map));
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_COUPONSTOCKQUERY_URL, param);
getRequestUri("couponstock_query_uri"), param);
return response.getAsObject(new TypeReference<CouponStock>() {
});
}
@ -134,33 +119,13 @@ public class CouponApi {
*/
public CouponDetail queryCouponDetail(String couponId)
throws WeixinException {
Map<String, String> map = baseMap();
Map<String, String> map = createBaseRequestMap(null);
map.put("coupon_id", couponId);
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
map.put("sign", weixinSignature.sign(map));
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_COUPONDETAILQUERY_URL, param);
getRequestUri("coupondetail_query_uri"), param);
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.foxinmy.weixin4j.exception.WeixinException;
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.WeixinSSLRequestExecutor;
import com.foxinmy.weixin4j.http.weixin.XmlResult;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
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.ApiResult;
import com.foxinmy.weixin4j.payment.mch.JSAPIPayRequest;
@ -63,14 +60,10 @@ import com.foxinmy.weixin4j.xml.XmlStream;
* @since JDK 1.6
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/index.html">商户平台API</a>
*/
public class PayApi {
private final WeixinRequestExecutor weixinExecutor;
private final WeixinPayAccount weixinAccount;
public class PayApi extends MchApi {
public PayApi(WeixinPayAccount weixinAccount) {
this.weixinAccount = weixinAccount;
this.weixinExecutor = new WeixinRequestExecutor();
super(weixinAccount);
}
/**
@ -88,12 +81,11 @@ public class PayApi {
*/
public PrePay createPrePay(MchPayPackage payPackage)
throws WeixinPayException {
payPackage.setSign(DigestUtil.paysignMd5(payPackage,
weixinAccount.getPaySignKey()));
payPackage.setSign(weixinSignature.sign(payPackage));
String payJsRequestXml = XmlStream.toXML(payPackage);
try {
WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_UNIFIEDORDER_URL, payJsRequestXml);
getRequestUri("order_create_uri"), payJsRequestXml);
PrePay prePay = response.getAsObject(new TypeReference<PrePay>() {
});
if (!prePay.getReturnCode().equalsIgnoreCase(Consts.SUCCESS)) {
@ -250,8 +242,7 @@ public class PayApi {
map.put("nonceStr", RandomUtil.generateString(16));
map.put("url", url);
map.put("accessToken", oauthToken);
String sign = DigestUtil.SHA1(MapUtil.toJoinString(map, false, true,
null));
String sign = DigestUtil.SHA1(MapUtil.toJoinString(map, false, true));
map.remove("url");
map.remove("accessToken");
map.put("scope", "jsapi_address");
@ -279,8 +270,8 @@ public class PayApi {
map.put("time_stamp", timestamp);
map.put("nonce_str", noncestr);
map.put("product_id", productId);
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
return String.format(PayURLConsts.MCH_NATIVE_URL, sign,
String sign = weixinSignature.sign(map);
return String.format(getRequestUri("native_pay_uri"), sign,
weixinAccount.getId(), weixinAccount.getMchId(), productId,
timestamp, noncestr);
}
@ -438,14 +429,11 @@ public class PayApi {
*/
public Order createMicroPay(MicroPayPackage payPackage)
throws WeixinException {
String sign = DigestUtil.paysignMd5(payPackage,
weixinAccount.getPaySignKey());
payPackage.setSign(sign);
payPackage.setSign(weixinSignature.sign(payPackage));
String para = XmlStream.toXML(payPackage);
WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_MICROPAY_URL, para);
return response
.getAsObject(new TypeReference<com.foxinmy.weixin4j.payment.mch.Order>() {
getRequestUri("micropay_uri"), para);
return response.getAsObject(new TypeReference<Order>() {
});
}
@ -466,13 +454,12 @@ public class PayApi {
* @since V3
* @throws WeixinException
*/
public Order orderQuery(IdQuery idQuery) throws WeixinException {
Map<String, String> map = baseMap(idQuery);
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
public Order queryOrder(IdQuery idQuery) throws WeixinException {
Map<String, String> map = createBaseRequestMap(idQuery);
map.put("sign", weixinSignature.sign(map));
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_ORDERQUERY_URL, param);
getRequestUri("order_query_uri"), param);
return ListsuffixResultDeserializer.deserialize(response.getAsString(),
Order.class);
}
@ -489,7 +476,7 @@ public class PayApi {
* 要采用原来的退款单号总退款金额不能超过用户实际支付金额
* </p>
*
* @param ca
* @param certificate
* 后缀为*.p12的证书文件
* @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -511,12 +498,12 @@ public class PayApi {
* @since V3
* @throws WeixinException
*/
public RefundResult refundApply(InputStream ca, IdQuery idQuery,
public RefundResult applyRefund(InputStream certificate, IdQuery idQuery,
String outRefundNo, double totalFee, double refundFee,
CurrencyType refundFeeType, String opUserId) throws WeixinException {
WeixinResponse response = null;
try {
Map<String, String> map = baseMap(idQuery);
Map<String, String> map = createBaseRequestMap(idQuery);
map.put("out_refund_no", outRefundNo);
map.put("total_fee", DateUtil.formaFee2Fen(totalFee));
map.put("refund_fee", DateUtil.formaFee2Fen(refundFee));
@ -528,18 +515,14 @@ public class PayApi {
refundFeeType = CurrencyType.CNY;
}
map.put("refund_fee_type", refundFeeType.name());
String sign = DigestUtil.paysignMd5(map,
weixinAccount.getPaySignKey());
map.put("sign", sign);
map.put("sign", weixinSignature.sign(map));
String param = XmlStream.map2xml(map);
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor(
weixinAccount.getCertificateKey(), ca);
response = weixinExecutor.post(PayURLConsts.MCH_REFUNDAPPLY_URL,
param);
response = createSSLRequestExecutor(certificate).post(
getRequestUri("refund_apply_uri"), param);
} finally {
if (ca != null) {
if (certificate != null) {
try {
ca.close();
certificate.close();
} catch (IOException e) {
;
}
@ -552,7 +535,7 @@ public class PayApi {
/**
* 退款申请(全额退款)
*
* @param ca
* @param certificate
* 后缀为*.p12的证书文件
* @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -561,12 +544,12 @@ public class PayApi {
* 商户系统内部的退款单号, 户系统内部唯一,同一退款单号多次请求只退一笔
* @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 {
return refundApply(ca, idQuery, outRefundNo, totalFee, totalFee, null,
null);
return applyRefund(certificate, idQuery, outRefundNo, totalFee,
totalFee, null, null);
}
/**
@ -575,7 +558,7 @@ public class PayApi {
* 如需实现相同功能请调用退款接口</font></br> <font
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上先调用查单接口,如果没有确切的返回,再调用撤销</font></br>
*
* @param ca
* @param certificate
* 后缀为*.p12的证书文件
* @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -584,24 +567,20 @@ public class PayApi {
* @since V3
* @throws WeixinException
*/
public ApiResult reverseOrder(InputStream ca, IdQuery idQuery)
public ApiResult reverseOrder(InputStream certificate, IdQuery idQuery)
throws WeixinException {
try {
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor(
weixinAccount.getCertificateKey(), ca);
Map<String, String> map = baseMap(idQuery);
String sign = DigestUtil.paysignMd5(map,
weixinAccount.getPaySignKey());
map.put("sign", sign);
Map<String, String> map = createBaseRequestMap(idQuery);
map.put("sign", weixinSignature.sign(map));
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_ORDERREVERSE_URL, param);
WeixinResponse response = createSSLRequestExecutor(certificate)
.post(getRequestUri("order_reverse_uri"), param);
return response.getAsObject(new TypeReference<ApiResult>() {
});
} finally {
if (ca != null) {
if (certificate != null) {
try {
ca.close();
certificate.close();
} 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>
*/
public String getShorturl(String url) throws WeixinException {
Map<String, String> map = baseMap(null);
Map<String, String> map = createBaseRequestMap(null);
try {
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", sign);
map.put("sign", weixinSignature.sign(map));
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_SHORTURL_URL, param);
getRequestUri("longurl_convert_uri"), param);
map = XmlStream.xml2map(response.getAsString());
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>
*/
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));
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
map.put("sign", weixinSignature.sign(map));
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_CLOSEORDER_URL, param);
getRequestUri("order_close_uri"), param);
return response.getAsObject(new TypeReference<ApiResult>() {
});
}
@ -700,14 +677,13 @@ public class PayApi {
if (file.exists()) {
return file;
}
Map<String, String> map = baseMap(null);
Map<String, String> map = createBaseRequestMap(null);
map.put("bill_date", formatBillDate);
map.put("bill_type", billType.name());
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
map.put("sign", weixinSignature.sign(map));
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_DOWNLOADBILL_URL, param);
getRequestUri("downloadbill_uri"), param);
BufferedReader reader = null;
BufferedWriter writer = null;
@ -757,13 +733,12 @@ public class PayApi {
* @since V3
* @throws WeixinException
*/
public RefundRecord refundQuery(IdQuery idQuery) throws WeixinException {
Map<String, String> map = baseMap(idQuery);
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
public RefundRecord queryRefund(IdQuery idQuery) throws WeixinException {
Map<String, String> map = createBaseRequestMap(idQuery);
map.put("sign", weixinSignature.sign(map));
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_REFUNDQUERY_URL, param);
getRequestUri("refund_query_uri"), param);
return ListsuffixResultDeserializer.deserialize(response.getAsString(),
RefundRecord.class);
}
@ -793,18 +768,17 @@ public class PayApi {
public XmlResult interfaceReport(String interfaceUrl, int executeTime,
String outTradeNo, String ip, Date time, XmlResult returnXml)
throws WeixinException {
Map<String, String> map = baseMap(null);
Map<String, String> map = createBaseRequestMap(null);
map.put("interface_url", interfaceUrl);
map.put("execute_time_", Integer.toString(executeTime));
map.put("out_trade_no", outTradeNo);
map.put("user_ip", ip);
map.put("time", DateUtil.fortmat2yyyyMMddHHmmss(time));
map.putAll((Map<String, String>) JSON.toJSON(returnXml));
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
map.put("sign", weixinSignature.sign(map));
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_PAYREPORT_URL, param);
getRequestUri("interface_report_uri"), param);
return response.getAsXmlResult();
}
@ -820,39 +794,13 @@ public class PayApi {
* @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);
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
map.put("sign", sign);
map.put("sign", weixinSignature.sign(map));
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_AUTHCODE_OPENID_URL, param);
getRequestUri("authcode_openid_uri"), param);
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.RedpacketSendResult;
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.CurrencyType;
import com.foxinmy.weixin4j.type.IdQuery;
@ -50,7 +51,7 @@ public class WeixinPayProxy {
/**
* 微信支付API:js支付扫码支付等接口
*/
private final PayApi pay3Api;
private final PayApi payApi;
/**
* 代金券API
*/
@ -79,7 +80,7 @@ public class WeixinPayProxy {
*/
public WeixinPayProxy(Weixin4jSettings settings) {
this.settings = settings;
this.pay3Api = new PayApi(settings.getWeixinPayAccount());
this.payApi = new PayApi(settings.getWeixinPayAccount());
this.couponApi = new CouponApi(settings.getWeixinPayAccount());
this.cashApi = new CashApi(settings.getWeixinPayAccount());
}
@ -109,7 +110,7 @@ public class WeixinPayProxy {
*/
public PrePay createPrePay(MchPayPackage payPackage)
throws WeixinPayException {
return pay3Api.createPrePay(payPackage);
return payApi.createPrePay(payPackage);
}
/**
@ -127,7 +128,7 @@ public class WeixinPayProxy {
*/
public MchPayRequest createPayRequest(MchPayPackage payPackage)
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,
Date timeStart, Date timeExpire, String goodsTag, String limitPay)
throws WeixinPayException {
return pay3Api.createPayRequest(tradeType, openId, productId, body,
return payApi.createPayRequest(tradeType, openId, productId, body,
detail, outTradeNo, totalFee, notifyUrl, createIp, attach,
timeStart, timeExpire, goodsTag, limitPay);
}
@ -201,7 +202,7 @@ public class WeixinPayProxy {
public MchPayRequest createJSPayRequest(String openId, String body,
String outTradeNo, double totalFee, String notifyUrl,
String createIp) throws WeixinPayException {
return pay3Api.createJSPayRequest(openId, body, outTradeNo, totalFee,
return payApi.createJSPayRequest(openId, body, outTradeNo, totalFee,
notifyUrl, createIp);
}
@ -226,7 +227,7 @@ public class WeixinPayProxy {
* @return 编辑地址请求JSON串
*/
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>
*/
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,
String body, String outTradeNo, double totalFee, String notifyUrl,
String createIp) throws WeixinPayException {
return pay3Api.createNativePayResponse(productId, body, outTradeNo,
return payApi.createNativePayResponse(productId, body, outTradeNo,
totalFee, notifyUrl, createIp);
}
@ -300,7 +301,7 @@ public class WeixinPayProxy {
public MchPayRequest createNativePayRequest(String productId, String body,
String outTradeNo, double totalFee, String notifyUrl,
String createIp) throws WeixinPayException {
return pay3Api.createNativePayRequest(productId, body, outTradeNo,
return payApi.createNativePayRequest(productId, body, outTradeNo,
totalFee, notifyUrl, createIp);
}
@ -327,7 +328,7 @@ public class WeixinPayProxy {
public MchPayRequest createAppPayRequest(String body, String outTradeNo,
double totalFee, String notifyUrl, String createIp)
throws WeixinPayException {
return pay3Api.createAppPayRequest(body, outTradeNo, totalFee,
return payApi.createAppPayRequest(body, outTradeNo, totalFee,
notifyUrl, createIp);
}
@ -354,7 +355,7 @@ public class WeixinPayProxy {
public MchPayRequest createWAPPayRequest(String body, String outTradeNo,
double totalFee, String notifyUrl, String createIp)
throws WeixinPayException {
return pay3Api.createWAPPayRequest(body, outTradeNo, totalFee,
return payApi.createWAPPayRequest(body, outTradeNo, totalFee,
notifyUrl, createIp);
}
@ -378,7 +379,7 @@ public class WeixinPayProxy {
*/
public Order createMicroPay(String authCode, String body, String orderNo,
double orderFee, String createIp) throws WeixinException {
return pay3Api.createMicroPay(authCode, body, orderNo, orderFee,
return payApi.createMicroPay(authCode, body, orderNo, orderFee,
createIp);
}
@ -397,7 +398,7 @@ public class WeixinPayProxy {
*/
public Order createMicroPay(MicroPayPackage payPackage)
throws WeixinException {
return pay3Api.createMicroPay(payPackage);
return payApi.createMicroPay(payPackage);
}
/**
@ -418,8 +419,8 @@ public class WeixinPayProxy {
* @return 订单详情
* @throws WeixinException
*/
public Order orderQuery(IdQuery idQuery) throws WeixinException {
return pay3Api.orderQuery(idQuery);
public Order queryOrder(IdQuery idQuery) throws WeixinException {
return payApi.queryOrder(idQuery);
}
/**
@ -434,7 +435,7 @@ public class WeixinPayProxy {
* 要采用原来的退款单号总退款金额不能超过用户实际支付金额
* </p>
*
* @param ca
* @param certificate
* 后缀为*.p12的证书文件
* @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -458,11 +459,11 @@ public class WeixinPayProxy {
* @since V3
* @throws WeixinException
*/
public com.foxinmy.weixin4j.payment.mch.RefundResult refundApply(
InputStream ca, IdQuery idQuery, String outRefundNo,
public RefundResult applyRefund(
InputStream certificate, IdQuery idQuery, String outRefundNo,
double totalFee, double refundFee, CurrencyType refundFeeType,
String opUserId) throws WeixinException {
return pay3Api.refundApply(ca, idQuery, outRefundNo, totalFee,
return payApi.applyRefund(certificate, idQuery, outRefundNo, totalFee,
refundFee, refundFeeType, opUserId);
}
@ -471,12 +472,12 @@ public class WeixinPayProxy {
*
* @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)
throws WeixinException, IOException {
return pay3Api.refundApply(
return payApi.applyRefund(
new FileInputStream(settings.getCertificateFile0()), idQuery,
outRefundNo, totalFee);
}
@ -499,8 +500,8 @@ public class WeixinPayProxy {
* @since V3
* @throws WeixinException
*/
public RefundRecord refundQuery(IdQuery idQuery) throws WeixinException {
return pay3Api.refundQuery(idQuery);
public RefundRecord queryRefund(IdQuery idQuery) throws WeixinException {
return payApi.queryRefund(idQuery);
}
/**
@ -524,7 +525,7 @@ public class WeixinPayProxy {
*/
public File downloadBill(Date billDate, BillType billType)
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
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上先调用查单接口,如果没有确切的返回,再调用撤销</font></br>
*
* @param ca
* @param certificate
* 证书文件(V2版本后缀为*.pfx,V3版本后缀为*.p12)
* @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -543,9 +544,9 @@ public class WeixinPayProxy {
* @since V3
* @throws WeixinException
*/
public ApiResult reverseOrder(InputStream ca, IdQuery idQuery)
public ApiResult reverseOrder(InputStream certificate, IdQuery idQuery)
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,
IOException {
return pay3Api.reverseOrder(
return payApi.reverseOrder(
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>
*/
public ApiResult closeOrder(String outTradeNo) throws WeixinException {
return pay3Api.closeOrder(outTradeNo);
return payApi.closeOrder(outTradeNo);
}
/**
@ -598,7 +599,7 @@ public class WeixinPayProxy {
* @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,
String outTradeNo, String ip, Date time, XmlResult returnXml)
throws WeixinException {
return pay3Api.interfaceReport(interfaceUrl, executeTime, outTradeNo,
return payApi.interfaceReport(interfaceUrl, executeTime, outTradeNo,
ip, time, returnXml);
}
/**
* 发放代金券(需要证书)
*
* @param ca
* @param certificate
* 后缀为*.p12的证书文件
* @param couponStockId
* 代金券批次id
@ -650,11 +651,11 @@ public class WeixinPayProxy {
* href="http://pay.weixin.qq.com/wiki/doc/api/sp_coupon.php?chapter=12_3">发放代金券接口</a>
* @throws WeixinException
*/
public CouponResult sendCoupon(InputStream ca, String couponStockId,
String partnerTradeNo, String openId, String opUserId)
throws WeixinException {
return couponApi.sendCoupon(ca, couponStockId, partnerTradeNo, openId,
opUserId);
public CouponResult sendCoupon(InputStream certificate,
String couponStockId, String partnerTradeNo, String openId,
String opUserId) throws WeixinException {
return couponApi.sendCoupon(certificate, couponStockId, partnerTradeNo,
openId, opUserId);
}
/**
@ -706,7 +707,7 @@ public class WeixinPayProxy {
/**
* 发放红包 企业向微信用户个人发现金红包
*
* @param ca
* @param certificate
* 后缀为*.p12的证书文件
* @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>
* @throws WeixinException
*/
public RedpacketSendResult sendRedpack(InputStream ca, Redpacket redpacket)
throws WeixinException {
return cashApi.sendRedpack(ca, redpacket);
public RedpacketSendResult sendRedpack(InputStream certificate,
Redpacket redpacket) throws WeixinException {
return cashApi.sendRedpack(certificate, redpacket);
}
/**
@ -737,7 +738,7 @@ public class WeixinPayProxy {
/**
* 查询红包记录
*
* @param ca
* @param certificate
* 后缀为*.p12的证书文件
* @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>
* @throws WeixinException
*/
public RedpacketRecord queryRedpack(InputStream ca, String outTradeNo)
throws WeixinException {
return cashApi.queryRedpack(ca, outTradeNo);
public RedpacketRecord queryRedpack(InputStream certificate,
String outTradeNo) throws WeixinException {
return cashApi.queryRedpack(certificate, outTradeNo);
}
/**
@ -769,9 +770,9 @@ public class WeixinPayProxy {
/**
* 企业付款 实现企业向个人付款针对部分有开发能力的商户 提供通过API完成企业付款的功能 比如目前的保险行业向客户退保给付理赔
*
* @param ca
* @param certificate
* 后缀为*.p12的证书文件
* @param mpPayment
* @param payment
* 付款信息
* @return 付款结果
* @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>
* @throws WeixinException
*/
public CorpPaymentResult corpPayment(InputStream ca, CorpPayment payment)
throws WeixinException {
return cashApi.corpPayment(ca, payment);
public CorpPaymentResult sendCorpPayment(InputStream certificate,
CorpPayment payment) throws WeixinException {
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 {
return cashApi.corpPayment(
return cashApi.sendCorpPayment(
new FileInputStream(settings.getCertificateFile0()), payment);
}
/**
* 企业付款查询 用于商户的企业付款操作进行结果查询返回付款操作详细结果
*
* @param ca
* @param certificate
* 后缀为*.p12的证书文件
* @param outTradeNo
* 商户调用企业付款API时使用的商户订单号
@ -811,9 +812,9 @@ public class WeixinPayProxy {
* href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_3">企业付款查询</a>
* @throws WeixinException
*/
public CorpPaymentRecord queryCorpPayment(InputStream ca, String outTradeNo)
throws WeixinException {
return cashApi.queryCorpPayment(ca, outTradeNo);
public CorpPaymentRecord queryCorpPayment(InputStream certificate,
String outTradeNo) throws WeixinException {
return cashApi.queryCorpPayment(certificate, outTradeNo);
}
/**
@ -842,7 +843,7 @@ public class WeixinPayProxy {
* @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";

View File

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

View File

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

View File

@ -5,7 +5,6 @@ import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.PayRequest;
import com.foxinmy.weixin4j.type.SignType;
import com.foxinmy.weixin4j.type.TradeType;
import com.foxinmy.weixin4j.util.DigestUtil;
/**
* 公众号JS支付:get_brand_wcpay_request</br>
@ -40,8 +39,7 @@ public class JSAPIPayRequest extends AbstractPayRequest {
PayRequest payRequest = new PayRequest(getPayAccount().getId(),
"prepay_id=" + getPrePayId());
payRequest.setSignType(SignType.MD5);
payRequest.setPaySign(DigestUtil.paysignMd5(payRequest, getPayAccount()
.getPaySignKey()));
payRequest.setPaySign(weixinSignature.sign(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.model.Consts;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.sign.WeixinPaymentSignature;
import com.foxinmy.weixin4j.util.RandomUtil;
/**
@ -67,7 +67,8 @@ public class NativePayResponse extends ApiResult {
this.setAppId(weixinAccount.getId());
this.setNonceStr(RandomUtil.generateString(16));
this.prepayId = prepayId;
this.setSign(DigestUtil.paysignMd5(this, weixinAccount.getPaySignKey()));
this.setSign(new WeixinPaymentSignature(weixinAccount.getPaySignKey())
.sign(this));
}
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.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.PayRequest;
import com.foxinmy.weixin4j.payment.PayURLConsts;
import com.foxinmy.weixin4j.type.TradeType;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.MapUtil;
@ -46,12 +45,13 @@ public class WAPPayRequest extends AbstractPayRequest {
@Override
public String toRequestString() {
PayRequest payRequest = toRequestObject();
String original = MapUtil.toJoinString(payRequest, true, true, null);
String original = MapUtil.toJoinString(payRequest, true, true);
String sign = DigestUtil.MD5(
String.format("%s&key=%s", original, getPayAccount()
.getPaySignKey())).toUpperCase();
return String.format(PayURLConsts.MCH_WAP_URL, URLEncodingUtil
.encoding(String.format("%s&sign=%s", original, sign),
return String.format("weixin://wap/pay?%s",
URLEncodingUtil.encoding(
String.format("%s&sign=%s", original, sign),
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
* @author jy
* @date 2014年11月5日
@ -9,5 +10,5 @@ package com.foxinmy.weixin4j.type;
* @see
*/
public enum SignType {
SHA1,MD5
SHA1, MD5, HMAC$SHA256
}

View File

@ -1,16 +1,9 @@
package com.foxinmy.weixin4j.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
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);
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
*/
public static String toJoinString(Object object, boolean encoder,
boolean lowerCase, Map<String, String> extra) {
boolean lowerCase) {
Map<String, String> map = new HashMap<String, String>();
JSONObject obj = null;
if (object instanceof String) {
@ -46,14 +46,11 @@ public class MapUtil {
for (String key : obj.keySet()) {
map.put(key, obj.getString(key));
}
if (extra != null && !extra.isEmpty()) {
map.putAll(extra);
}
return toJoinString(map, encoder, lowerCase);
}
/**
* 接字符串
* 接字符串
*
* @param map
* 对象

View File

@ -43,17 +43,17 @@ public class CashTest extends PayTest {
}
@Test
public void mpPayment() throws WeixinException, IOException {
public void sendCorpPayment() throws WeixinException, IOException {
CorpPayment payment = new CorpPayment("MP001",
"ofW1gwok9vZIyle0YbA-eQe83Uk8",
MPPaymentCheckNameType.NO_CHECK, "企业付款测试", 1d, "127.0.0.1");
CorpPaymentResult result = PAY.corpPayment(new FileInputStream(caFile),
CorpPaymentResult result = PAY.sendCorpPayment(new FileInputStream(caFile),
payment);
System.err.println(result);
}
@Test
public void mchPaymentQuery() throws WeixinException, IOException {
public void queryCorpPayment() throws WeixinException, IOException {
System.err.println(PAY.queryCorpPayment(new FileInputStream(caFile),
"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.Order;
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.IdType;
import com.foxinmy.weixin4j.type.TradeType;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.Weixin4jSettings;
/**
@ -34,10 +37,13 @@ import com.foxinmy.weixin4j.util.Weixin4jSettings;
* @see
*/
public class PayTest {
protected final static WeixinPayProxy PAY;
protected final static WeixinPayAccount ACCOUNT;
protected final static WeixinSignature SIGNATURE;
protected final static WeixinPayProxy PAY;
static {
ACCOUNT = new WeixinPayAccount("appid", "paySignKey", "mchid");
SIGNATURE = new WeixinPaymentSignature(ACCOUNT.getPaySignKey());
PAY = new WeixinPayProxy(new Weixin4jSettings(ACCOUNT));
}
/**
@ -46,35 +52,34 @@ public class PayTest {
protected File caFile = new File("证书文件:*.p12");
@Test
public void orderQueryV3() throws WeixinException {
Order order = PAY.orderQuery(new IdQuery("BY2016010800025",
public void queryOrder() throws WeixinException {
Order order = PAY.queryOrder(new IdQuery("BY2016010800025",
IdType.TRADENO));
System.err.println(order);
String sign = order.getSign();
order.setSign(null);
String valiSign = DigestUtil.paysignMd5(order, ACCOUNT.getPaySignKey());
String valiSign = SIGNATURE.sign(order);
System.err
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
Assert.assertEquals(valiSign, sign);
}
@Test
public void refundQueryV3() throws WeixinException {
com.foxinmy.weixin4j.payment.mch.RefundRecord record = PAY
.refundQuery(new IdQuery("TT_1427183696238", IdType.TRADENO));
public void queryRefund() throws WeixinException {
RefundRecord record = PAY.queryRefund(new IdQuery("TT_1427183696238",
IdType.TRADENO));
System.err.println(record);
// 这里的验证签名需要把details循环拼接
String sign = record.getSign();
record.setSign(null);
String valiSign = DigestUtil
.paysignMd5(record, ACCOUNT.getPaySignKey());
String valiSign = SIGNATURE.sign(record);
System.err
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
Assert.assertEquals(valiSign, sign);
}
@Test
public void downbillV3() throws WeixinException {
public void downbill() throws WeixinException {
Calendar c = Calendar.getInstance();
System.err.println(c.getTime());
c.set(Calendar.YEAR, 2015);
@ -86,24 +91,22 @@ public class PayTest {
}
@Test
public void refundV3() throws WeixinException, IOException {
public void refund() throws WeixinException, IOException {
IdQuery idQuery = new IdQuery("TT_1427183696238", IdType.TRADENO);
com.foxinmy.weixin4j.payment.mch.RefundResult result = PAY.refundApply(
new FileInputStream(caFile), idQuery,
"TT_R" + System.currentTimeMillis(), 0.01d, 0.01d, null,
"10020674");
RefundResult result = PAY.applyRefund(new FileInputStream(caFile),
idQuery, "TT_R" + System.currentTimeMillis(), 0.01d, 0.01d,
null, "10020674");
System.err.println(result);
String sign = result.getSign();
result.setSign(null);
String valiSign = DigestUtil
.paysignMd5(result, ACCOUNT.getPaySignKey());
String valiSign = SIGNATURE.sign(result);
System.err
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
Assert.assertEquals(valiSign, sign);
}
@Test
public void nativeV3() throws WeixinException {
public void nativePay() throws WeixinException {
MchPayPackage payPackageV3 = new MchPayPackage(ACCOUNT,
"oyFLst1bqtuTcxK-ojF8hOGtLQao", "native测试", "T0001", 0.1d,
"notify_url", "127.0.0.1", TradeType.NATIVE);
@ -123,8 +126,7 @@ public class PayTest {
System.err.println(result);
String sign = result.getSign();
result.setSign(null);
String valiSign = DigestUtil
.paysignMd5(result, ACCOUNT.getPaySignKey());
String valiSign = SIGNATURE.sign(result);
System.err
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
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.Token;
import com.foxinmy.weixin4j.model.WeixinPayOldAccount;
import com.foxinmy.weixin4j.mp.payment.v2.OrderV2;
import com.foxinmy.weixin4j.mp.payment.v2.PayPackageV2;
import com.foxinmy.weixin4j.mp.payment.v2.RefundRecordV2;
import com.foxinmy.weixin4j.mp.payment.v2.RefundResultV2;
import com.foxinmy.weixin4j.mp.oldpayment.OrderV2;
import com.foxinmy.weixin4j.mp.oldpayment.PayPackageV2;
import com.foxinmy.weixin4j.mp.oldpayment.RefundRecordV2;
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.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.TokenHolder;
import com.foxinmy.weixin4j.token.TokenStorager;
@ -58,7 +61,7 @@ import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer;
/**
* V2老支付API
*
* @className Pay2Api
* @className PayOldApi
* @author jy
* @date 2014年10月28日
* @since JDK 1.6
@ -66,8 +69,10 @@ import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer;
*/
public class PayOldApi extends MpApi {
private final WeixinPayOldAccount payAccount;
private final WeixinPayOldAccount weixinAccount;
private final TokenHolder tokenHolder;
private final WeixinSignature weixinMD5Signature;
private final WeixinOldPaymentSignature weixinOldSignature;
/**
* 默认使用weixin4j.properties配置信息
@ -90,14 +95,19 @@ public class PayOldApi extends MpApi {
WeixinPayOldAccount.class), tokenStorager);
}
public PayOldApi(WeixinPayOldAccount payAccount, TokenStorager tokenStorager) {
this.payAccount = payAccount;
public PayOldApi(WeixinPayOldAccount weixinAccount,
TokenStorager tokenStorager) {
this.weixinAccount = weixinAccount;
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() {
return this.payAccount;
return this.weixinAccount;
}
/**
@ -162,10 +172,10 @@ public class PayOldApi extends MpApi {
payPackage.setProductFee(productFee);
payPackage.setGoodsTag(goodsTag);
PayRequest payRequest = new PayRequest(getPayAccount().getId(),
DigestUtil.packageSign(payPackage, getPayAccount()
weixinOldSignature.sign(payPackage, getPayAccount()
.getPartnerKey()));
payRequest.setPaySign(DigestUtil.paysignSha(payRequest, getPayAccount()
.getPaySignKey()));
payRequest.setPaySign(weixinOldSignature.sign(payRequest,
getPayAccount().getPaySignKey()));
payRequest.setSignType(SignType.SHA1);
return JSON.toJSONString(payRequest);
}
@ -186,9 +196,9 @@ public class PayOldApi extends MpApi {
map.put("noncestr", noncestr);
map.put("productid", productId);
map.put("appkey", getPayAccount().getPaySignKey());
String sign = DigestUtil.paysignSha(map, null);
String ordernative_v2_uri = getRequestUri("ordernative_v2_uri");
return String.format(ordernative_v2_uri, sign, getPayAccount().getId(),
String sign = weixinOldSignature.sign(map);
String nativepay_uri = getRequestUri("nativepay_old_uri");
return String.format(nativepay_uri, sign, getPayAccount().getId(),
productId, timestamp, noncestr);
}
@ -198,12 +208,12 @@ public class PayOldApi extends MpApi {
* @param idQuery
* 订单号
* @return 订单信息
* @see com.foxinmy.weixin4j.mp.payment.v2.OrderV2
* @see com.foxinmy.weixin4j.mp.oldpayment.OrderV2
* @since V2
* @throws WeixinException
*/
public OrderV2 orderQuery(IdQuery idQuery) throws WeixinException {
String orderquery_uri = getRequestUri("orderquery_v2_uri");
public OrderV2 queryOrder(IdQuery idQuery) throws WeixinException {
String orderquery_uri = getRequestUri("orderquery_old_uri");
Token token = tokenHolder.getToken();
StringBuilder sb = new StringBuilder();
sb.append(idQuery.getType().getName()).append("=")
@ -221,7 +231,7 @@ public class PayOldApi extends MpApi {
obj.put("appkey", getPayAccount().getPaySignKey());
obj.put("package", sb.toString());
obj.put("timestamp", timestamp);
String signature = DigestUtil.paysignSha(obj, null);
String signature = weixinOldSignature.sign(obj);
obj.clear();
obj.put("appid", getPayAccount().getId());
@ -251,7 +261,7 @@ public class PayOldApi extends MpApi {
* 败后重新提交,要采用原来的 out_refund_no总退款金额不能超过用户实际支付金额</br>
* </p>
*
* @param caFile
* @param certificate
* 证书文件(V2版本后缀为*.pfx)
* @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -268,18 +278,17 @@ public class PayOldApi extends MpApi {
* opUserPasswd
*
* @return 退款申请结果
* @see com.foxinmy.weixin4j.mp.payment.v2.RefundResultV2
* @see com.foxinmy.weixin4j.mp.oldpayment.RefundResultV2
* @since V2
* @throws WeixinException
*/
protected RefundResultV2 refundApply(File caFile, IdQuery idQuery,
String outRefundNo, double totalFee, double refundFee,
String opUserId, Map<String, String> mopara) throws WeixinException {
String refund_uri = getRequestUri("refundapply_v2_uri");
protected RefundResultV2 applyRefund(InputStream certificate,
IdQuery idQuery, String outRefundNo, double totalFee,
double refundFee, String opUserId, Map<String, String> mopara)
throws WeixinException {
String refund_uri = getRequestUri("refundapply_old_uri");
WeixinResponse response = null;
InputStream ca = null;
try {
ca = new FileInputStream(caFile);
Map<String, String> map = new HashMap<String, String>();
map.put("input_charset", Consts.UTF_8.name());
// 版本号
@ -298,24 +307,23 @@ public class PayOldApi extends MpApi {
if (mopara != null && !mopara.isEmpty()) {
map.putAll(mopara);
}
String sign = DigestUtil.paysignMd5(map, getPayAccount()
.getPartnerKey());
String sign = weixinMD5Signature.sign(map);
map.put("sign", sign.toUpperCase());
SSLContext ctx = null;
KeyStore ks = null;
String jksPwd = "";
File jksFile = new File(String.format("%s/tenpay_cacert.jks",
caFile.getParent()));
Weixin4jConfigUtil.getClassPathValue("weixin4j.tmpdir",
System.getProperty("java.io.tmpdir"))));
// create jks ca
if (!jksFile.exists()) {
CertificateFactory cf = CertificateFactory
.getInstance(com.foxinmy.weixin4j.model.Consts.X509);
.getInstance(Consts.X509);
java.security.cert.Certificate cert = cf
.generateCertificate(PayOldApi.class
.getResourceAsStream("cacert.pem"));
ks = KeyStore
.getInstance(com.foxinmy.weixin4j.model.Consts.JKS);
ks = KeyStore.getInstance(Consts.JKS);
ks.load(null, null);
ks.setCertificateEntry("tenpay", cert);
FileOutputStream os = new FileOutputStream(jksFile);
@ -324,20 +332,20 @@ public class PayOldApi extends MpApi {
}
// load jks ca
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(com.foxinmy.weixin4j.model.Consts.SunX509);
ks = KeyStore.getInstance(com.foxinmy.weixin4j.model.Consts.JKS);
.getInstance(Consts.SunX509);
ks = KeyStore.getInstance(Consts.JKS);
FileInputStream is = new FileInputStream(jksFile);
ks.load(is, jksPwd.toCharArray());
tmf.init(ks);
is.close();
// load pfx ca
KeyManagerFactory kmf = KeyManagerFactory
.getInstance(com.foxinmy.weixin4j.model.Consts.SunX509);
ks = KeyStore.getInstance(com.foxinmy.weixin4j.model.Consts.PKCS12);
ks.load(ca, getPayAccount().getPartnerId().toCharArray());
.getInstance(Consts.SunX509);
ks = KeyStore.getInstance(Consts.PKCS12);
ks.load(certificate, 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(),
new SecureRandom());
@ -349,9 +357,9 @@ public class PayOldApi extends MpApi {
} catch (Exception e) {
throw new WeixinException(e);
} finally {
if (ca != null) {
if (certificate != null) {
try {
ca.close();
certificate.close();
} catch (IOException e) {
;
}
@ -364,7 +372,7 @@ public class PayOldApi extends MpApi {
/**
* 退款申请
*
* @param caFile
* @param certificate
* 证书文件(V2版本后缀为*.pfx)
* @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -379,21 +387,21 @@ public class PayOldApi extends MpApi {
* 操作员帐号, 默认为商户号
* @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 opUserId, String opUserPasswd) throws WeixinException {
Map<String, String> mopara = new HashMap<String, String>();
mopara.put("op_user_passwd", DigestUtil.MD5(opUserPasswd));
return refundApply(caFile, idQuery, outRefundNo, totalFee, refundFee,
opUserId, mopara);
return applyRefund(certificate, idQuery, outRefundNo, totalFee,
refundFee, opUserId, mopara);
}
/**
* 退款申请
*
* @param caFile
* @param certificate
* 证书文件(V2版本后缀为*.pfx)
* @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
@ -417,10 +425,10 @@ public class PayOldApi extends MpApi {
* @param refundType
* 为空或者填 1:商户号余额退款;2:现金帐号 退款;3:优先商户号退款,若商户号余额不足, 再做现金帐号退款使用 2
* 3 ,需联系财 付通开通此功能
* @see {@link #refundApply(File, IdQuery, String, double, double, String, Map)}
* @see {@link #applyRefund(InputStream, IdQuery, String, double, double, String, Map)}
* @return 退款结果
*/
public RefundResultV2 refundApply(File caFile, IdQuery idQuery,
public RefundResultV2 applyRefund(InputStream certificate, IdQuery idQuery,
String outRefundNo, double totalFee, double refundFee,
String opUserId, String opUserPasswd, String recvUserId,
String reccvUserName, RefundType refundType) throws WeixinException {
@ -435,8 +443,8 @@ public class PayOldApi extends MpApi {
if (refundType != null) {
mopara.put("refund_type", Integer.toString(refundType.getVal()));
}
return refundApply(caFile, idQuery, outRefundNo, totalFee, refundFee,
opUserId, mopara);
return applyRefund(certificate, idQuery, outRefundNo, totalFee,
refundFee, opUserId, mopara);
}
/**
@ -474,7 +482,7 @@ public class PayOldApi extends MpApi {
if (file.exists()) {
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.put("spid", getPayAccount().getPartnerId());
@ -523,19 +531,18 @@ public class PayOldApi extends MpApi {
* 四个参数必填一个,优先级为:
* refund_id>out_refund_no>transaction_id>out_trade_no
* @return 退款记录
* @see com.foxinmy.weixin4j.mp.payment.v2.RefundRecordV2
* @see com.foxinmy.weixin4j.mp.payment.v2.RefundDetailV2
* @see com.foxinmy.weixin4j.mp.oldpayment.RefundRecordV2
* @see com.foxinmy.weixin4j.mp.oldpayment.RefundDetailV2
* @since V2
* @throws WeixinException
*/
public RefundRecordV2 refundQuery(IdQuery idQuery) throws WeixinException {
String refundquery_uri = getRequestUri("refundquery_v2_uri");
public RefundRecordV2 queryRefund(IdQuery idQuery) throws WeixinException {
String refundquery_uri = getRequestUri("refundquery_old_uri");
Map<String, String> map = new HashMap<String, String>();
map.put("input_charset", Consts.UTF_8.name());
map.put("partner", getPayAccount().getPartnerId());
map.put(idQuery.getType().getName(), idQuery.getId());
String sign = DigestUtil.paysignMd5(map, getPayAccount()
.getPartnerKey());
String sign = weixinMD5Signature.sign(map);
map.put("sign", sign.toLowerCase());
WeixinResponse response = weixinExecutor.get(refundquery_uri, map);
return ListsuffixResultDeserializer.deserialize(response.getAsString(),
@ -561,7 +568,7 @@ public class PayOldApi extends MpApi {
public JsonResult deliverNotify(String openId, String transid,
String outTradeNo, boolean status, String statusMsg)
throws WeixinException {
String delivernotify_uri = getRequestUri("delivernotify_uri");
String delivernotify_uri = getRequestUri("delivernotify_old_uri");
Token token = tokenHolder.getToken();
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_status", status ? "1" : "0");
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());
WeixinResponse response = weixinExecutor.post(
@ -594,11 +601,10 @@ public class PayOldApi extends MpApi {
*/
public JsonResult updateFeedback(String openId, String feedbackId)
throws WeixinException {
String payfeedback_update_uri = getRequestUri("payfeedback_update_uri");
String payfeedback_uri = getRequestUri("payfeedback_old_uri");
Token token = tokenHolder.getToken();
WeixinResponse response = weixinExecutor.get(String.format(
payfeedback_update_uri, token.getAccessToken(), openId,
feedbackId));
payfeedback_uri, token.getAccessToken(), openId, feedbackId));
return response.getAsJsonResult();
}
}

View File

@ -6,12 +6,10 @@
api_base_url=https://api.weixin.qq.com
api_cgi_url={api_base_url}/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_ssl_base_url=https://mch.tenpay.com
tenpay_gw_base_url=https://gw.tenpay.com
# \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
#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
# \u957f\u94fe\u63a5\u8f6c\u77ed\u94fe\u63a5
shorturl_uri={api_cgi_url}/shorturl?access_token=%s
p_shorturl_uri={mch_base_url}/tools/shorturl
# \u8bbe\u7f6e\u5907\u6ce8\u540d
updateremark_uri={api_cgi_url}/user/info/updateremark?access_token=%s
# \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
# \u5fae\u4fe1\u670d\u52a1\u5730\u5740
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
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
material_article_upload_uri={api_cgi_url}/material/add_news?access_token=%s
# \u4e0a\u4f20\u6c38\u4e45\u5a92\u4f53\u7d20\u6750
@ -184,18 +159,3 @@ material_media_count_uri={api_cgi_url}/material/get_materialcount?access_token=%
material_media_list_uri={api_cgi_url}/material/batchget_material?access_token=%s
# \u81ea\u52a8\u56de\u590d\u89c4\u5219
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;

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

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.XmlAccessorType;

View File

@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.mp.payment.v2;
package com.foxinmy.weixin4j.mp.oldpayment;
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.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.XmlAccessorType;

View File

@ -1,4 +1,4 @@
package com.foxinmy.weixin4j.mp.payment.v2;
package com.foxinmy.weixin4j.mp.oldpayment;
import java.util.List;
@ -17,7 +17,7 @@ import com.foxinmy.weixin4j.xml.ListsuffixResult;
* @author jy
* @date 2014年11月1日
* @since JDK 1.6
* @see com.foxinmy.weixin4j.mp.payment.v2.RefundDetailV2
* @see com.foxinmy.weixin4j.mp.oldpayment.RefundDetailV2
*/
@XmlRootElement
@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.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;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Calendar;
import org.junit.Test;
@ -36,20 +38,21 @@ public class PayTest {
@Test
public void orderQueryV2() throws WeixinException {
System.err.println(PAY2.orderQuery(new IdQuery("D14110500021",
System.err.println(PAY2.queryOrder(new IdQuery("D14110500021",
IdType.REFUNDNO)));
}
@Test
public void refundV2() throws WeixinException {
public void refundV2() throws WeixinException, IOException {
IdQuery idQuery = new IdQuery("D15020300005", IdType.TRADENO);
System.err.println(PAY2.refundApply(caFile, idQuery, "1422925555037",
16d, 16d, "1221928801", "111111", null, null, null));
System.err.println(PAY2.applyRefund(new FileInputStream(caFile),
idQuery, "1422925555037", 16d, 16d, "1221928801", "111111",
null, null, null));
}
@Test
public void refundQueryV2() throws WeixinException {
System.err.println(PAY2.refundQuery(new IdQuery("D14123000004",
System.err.println(PAY2.queryRefund(new IdQuery("D14123000004",
IdType.TRADENO)));
}

View File

@ -6,7 +6,7 @@ import java.util.HashMap;
import java.util.Map;
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.xml.ListsuffixResultDeserializer;
import com.foxinmy.weixin4j.xml.XmlStream;

View File

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

View File

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

View File

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