签名类接口化

This commit is contained in:
jinyu
2016-03-26 20:54:35 +08:00
parent 0897575fe1
commit 40cf672715
39 changed files with 680 additions and 690 deletions
@@ -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) {
;
}
@@ -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,22 +23,17 @@ 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
* 后缀为*.p12的证书文件
* @param certificate
* 后缀为*.p12的证书文件
* @param couponStockId
* 代金券批次id
* @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>
* @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;
}
}
@@ -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;
}
}
@@ -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,15 +429,12 @@ 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;
}
}
@@ -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";
}
@@ -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
*/
@@ -63,7 +64,7 @@ public class WeixinPayProxy {
* 配置相关
*/
private final Weixin4jSettings settings;
/**
* 使用weixin4j.properties配置的支付账号信息
*/
@@ -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";
@@ -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>");
@@ -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
@@ -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>
@@ -29,7 +28,7 @@ public class JSAPIPayRequest extends AbstractPayRequest {
public JSAPIPayRequest(String prePayId, WeixinPayAccount payAccount) {
super(prePayId, payAccount);
}
@Override
public TradeType getTradeType() {
return TradeType.JSAPI;
@@ -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;
}
@@ -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() {
@@ -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));
}
}
@@ -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
@@ -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()));
}
}
@@ -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();
}
}
@@ -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);
}
@@ -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
}
@@ -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"));
}
}
@@ -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
* 对象
@@ -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"));
}
@@ -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);