diff --git a/CHANGE.md b/CHANGE.md index 50726c3f..45dcbfb7 100644 --- a/CHANGE.md +++ b/CHANGE.md @@ -645,4 +645,10 @@ * 2016-03-22 - + weixin4j-base:企业付款相关类更名 \ No newline at end of file + + weixin4j-base:企业付款相关类更名 + +* 2016-03-25 + + + weixin4j-base:v2和v3支付改名 + + + weixin4j-base:支持服务商版支付 \ No newline at end of file diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/CashApi.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/CashApi.java index 4656b831..08f471e4 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/CashApi.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/CashApi.java @@ -60,14 +60,9 @@ public class CashApi { */ public RedpacketSendResult sendRedpack(InputStream ca, Redpacket redpacket) throws WeixinException { - JSONObject obj = (JSONObject) JSON.toJSON(redpacket); - obj.put("nonce_str", RandomUtil.generateString(16)); - obj.put("mch_id", weixinAccount.getMchId()); - obj.put("sub_mch_id", weixinAccount.getSubMchId()); - obj.put("wxappid", weixinAccount.getId()); - String sign = DigestUtil.paysignMd5(obj, weixinAccount.getPaySignKey()); - obj.put("sign", sign); - String param = XmlStream.map2xml(obj); + redpacket.setSign(DigestUtil.paysignMd5(redpacket, + weixinAccount.getPaySignKey())); + String param = XmlStream.map2xml((JSONObject) JSON.toJSON(redpacket)); WeixinResponse response = null; try { WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor( @@ -184,7 +179,7 @@ public class CashApi { * 企业付款查询 用于商户的企业付款操作进行结果查询,返回付款操作详细结果 * * @param ca - * 后缀为*.p12的证书文件 + * 后缀为*.p12的证书文件 * @param outTradeNo * 商户调用企业付款API时使用的商户订单号 * @return 付款记录 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/Pay3Api.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/PayApi.java similarity index 98% rename from weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/Pay3Api.java rename to weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/PayApi.java index 1d9255eb..cba65184 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/Pay3Api.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/PayApi.java @@ -63,12 +63,12 @@ import com.foxinmy.weixin4j.xml.XmlStream; * @since JDK 1.6 * @see 商户平台API */ -public class Pay3Api { +public class PayApi { private final WeixinRequestExecutor weixinExecutor; private final WeixinPayAccount weixinAccount; - public Pay3Api(WeixinPayAccount weixinAccount) { + public PayApi(WeixinPayAccount weixinAccount) { this.weixinAccount = weixinAccount; this.weixinExecutor = new WeixinRequestExecutor(); } @@ -88,10 +88,8 @@ public class Pay3Api { */ public PrePay createPrePay(MchPayPackage payPackage) throws WeixinPayException { - if (StringUtil.isBlank(payPackage.getSign())) { - payPackage.setSign(DigestUtil.paysignMd5(payPackage, - weixinAccount.getPaySignKey())); - } + payPackage.setSign(DigestUtil.paysignMd5(payPackage, + weixinAccount.getPaySignKey())); String payJsRequestXml = XmlStream.toXML(payPackage); try { WeixinResponse response = weixinExecutor.post( @@ -126,8 +124,6 @@ public class Pay3Api { */ public MchPayRequest createPayRequest(MchPayPackage payPackage) throws WeixinPayException { - payPackage.setSign(DigestUtil.paysignMd5(payPackage, - weixinAccount.getPaySignKey())); PrePay prePay = createPrePay(payPackage); String tradeType = payPackage.getTradeType(); if (TradeType.APP.name().equalsIgnoreCase(tradeType)) { @@ -140,7 +136,7 @@ public class Pay3Api { } else if (TradeType.WAP.name().equalsIgnoreCase(tradeType)) { return new WAPPayRequest(prePay.getPrepayId(), weixinAccount); } else if (TradeType.MICROPAY.name().equalsIgnoreCase(tradeType)) { - throw new WeixinPayException("maybe use createMicroPay method?"); + throw new WeixinPayException("maybe invoke createMicroPay method?"); } else { throw new WeixinPayException("unknown tradeType:" + tradeType); } @@ -180,7 +176,7 @@ public class Pay3Api { * @see com.foxinmy.weixin4j.payment.mch.JSAPIPayRequest JS支付 * @see com.foxinmy.weixin4j.payment.mch.NATIVEPayRequest 扫码支付 * @see com.foxinmy.weixin4j.payment.mch.APPPayRequest APP支付 - * @see com.foxinmy.weixin4j.payment.mch.WAPPayRequest WAP支付t + * @see com.foxinmy.weixin4j.payment.mch.WAPPayRequest WAP支付 * @throws WeixinPayException */ public MchPayRequest createPayRequest(TradeType tradeType, String openId, @@ -836,7 +832,7 @@ public class Pay3Api { } /** - * V3接口请求基本数据 + * 支付接口请求基本数据 * * @return */ @@ -848,6 +844,12 @@ public class Pay3Api { 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()); } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/README.md b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/README.md index 35188e3e..5da8af2f 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/README.md +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/README.md @@ -2,4 +2,4 @@ * CouponApi `优惠券API` -* Pay3Api `微信支付API` \ No newline at end of file +* PayApi `微信支付API` \ No newline at end of file diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/WeixinPayAccount.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/WeixinPayAccount.java index 03ce99e0..cf13a8fd 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/WeixinPayAccount.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/WeixinPayAccount.java @@ -17,127 +17,142 @@ public class WeixinPayAccount extends WeixinAccount { private static final long serialVersionUID = -2791256176906048632L; /** - * 公众号支付请求中用于加密的密钥 Key,可验证商户唯一身份,PaySignKey 对应于支付场景中的 appKey 值 + * 公众号支付请求中用于加密的密钥 */ private String paySignKey; /** - * 财付通商户身份的标识 - */ - private String partnerId; - /** - * 财付通商户权限密钥Key - */ - private String partnerKey; - /** - * 微信支付分配的商户号(商户平台版) + * 微信支付分配的商户号 */ private String mchId; /** - * 加载支付证书文件的密码(商户平台版) + * 加载支付证书文件的密码(默认为商户号) */ private String certificateKey; /** - * 微信支付分配的子商户号,受理模式下必填(商户平台版) - */ - private String subMchId; - /** - * 微信支付分配的设备号(商户平台版) + * 微信支付分配的设备号 */ private String deviceInfo; /** - * 商户平台版本(V3)字段 + * 财付通商户身份的标识 + */ + private String partnerId; + + /** + * 微信分配的子商户公众账号ID + */ + private String subId; + /** + * 微信支付分配的子商户号 + */ + private String subMchId; + + /** + * 支付商户信息 * - * @param appId + * @param id * 公众号唯一的身份ID(必填) - * @param appSecret - * 调用接口的凭证(最好填写) * @param paySignKey * 支付密钥字符串(必填) * @param mchId * 微信支付分配的商户号(必填) */ - public WeixinPayAccount(String appId, String appSecret, String paySignKey, - String mchId) { - this(appId, appSecret, paySignKey, mchId, null, null, null, null, null); + public WeixinPayAccount(String id, String paySignKey, String mchId) { + this(id, null, paySignKey, mchId, null, null, null, null, null); } /** * 支付商户信息 * - * @param appId + * @param id * 公众号唯一的身份ID(必填) - * @param appSecret - * 调用接口的凭证(最好填写) + * @param secret + * 公众号调用接口的凭证(最好填写) * @param paySignKey * 支付密钥字符串(必填) * @param mchId - * 微信支付分配的商户号(V3商户平台版必填) + * 微信支付分配的商户号(必填) * @param certificateKey - * 加载支付证书文件的密码(商户平台版) - * @param subMchId - * 微信支付分配的子商户号,受理模式下必填(V3商户平台版 非必须) + * 加载支付证书文件的密码(默认为商户号) * @param deviceInfo - * 微信支付分配的设备号(V3商户平台版 非必须) + * 微信支付分配的设备号(非必填) * @param partnerId - * 财付通的商户号(V2版本必填) - * @param partnerKey - * 财付通商户权限密钥Key(V2版本必填) + * 财付通的商户号(非必填) + * @param subId + * 微信分配的子商户公众账号ID(非必填) + * @param subMchId + * 微信支付分配的子商户号(非必填) */ @JSONCreator - public WeixinPayAccount(@JSONField(name = "id") String appId, - @JSONField(name = "secret") String appSecret, + public WeixinPayAccount(@JSONField(name = "id") String id, + @JSONField(name = "secret") String secret, @JSONField(name = "paySignKey") String paySignKey, @JSONField(name = "mchId") String mchId, @JSONField(name = "certificateKey") String certificateKey, - @JSONField(name = "subMchId") String subMchId, @JSONField(name = "deviceInfo") String deviceInfo, @JSONField(name = "partnerId") String partnerId, - @JSONField(name = "partnerKey") String partnerKey) { - super(appId, appSecret); + @JSONField(name = "subId") String subId, + @JSONField(name = "subMchId") String subMchId) { + super(id, secret); this.paySignKey = paySignKey; this.mchId = mchId; this.certificateKey = certificateKey; - this.subMchId = subMchId; this.deviceInfo = deviceInfo; this.partnerId = partnerId; - this.partnerKey = partnerKey; + this.subId = subId; + this.subMchId = subMchId; } public String getPaySignKey() { return paySignKey; } - public String getPartnerId() { - return partnerId; - } - - public String getPartnerKey() { - return partnerKey; - } - public String getMchId() { return mchId; } - public String getSubMchId() { - return subMchId; - } - public String getDeviceInfo() { return deviceInfo; } + public void setDeviceInfo(String deviceInfo) { + this.deviceInfo = deviceInfo; + } + public String getCertificateKey() { return StringUtil.isBlank(certificateKey) ? mchId : certificateKey; } + public String getPartnerId() { + return partnerId; + } + + public void setPartnerId(String partnerId) { + this.partnerId = partnerId; + } + + public String getSubId() { + return subId; + } + + public void setSubId(String subId) { + this.subId = subId; + } + + public String getSubMchId() { + return subMchId; + } + + public void setSubMchId(String subMchId) { + this.subMchId = subMchId; + } + @Override public String toString() { return "WeixinPayAccount [" + super.toString() + ", paySignKey=" - + paySignKey + ", partnerId=" + partnerId + ", partnerKey=" - + partnerKey + ", mchId=" + mchId + ", certificateKey=" - + getCertificateKey() + ", subMchId=" + subMchId - + ", deviceInfo=" + deviceInfo + "]"; + + paySignKey + ", mchId=" + mchId + ", certificateKey=" + + certificateKey + ", deviceInfo=" + deviceInfo + + ", partnerId=" + partnerId + ", subId=" + subId + + ", subMchId=" + subMchId + "]"; } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/WeixinPayOldAccount.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/WeixinPayOldAccount.java new file mode 100644 index 00000000..e9c83a07 --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/WeixinPayOldAccount.java @@ -0,0 +1,75 @@ +package com.foxinmy.weixin4j.model; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.fastjson.annotation.JSONField; + +/** + * 微信支付账户(2014年10月申请支付的老版本) + * + * @className WeixinPayOldAccount + * @author jy + * @date 2015年6月26日 + * @since JDK 1.6 + * @see + */ +public class WeixinPayOldAccount extends WeixinAccount { + + private static final long serialVersionUID = -2791256176906048632L; + /** + * 公众号支付请求中用于加密的密钥 Key,可验证商户唯一身份,PaySignKey 对应于支付场景中的 appKey 值 + */ + private String paySignKey; + /** + * 财付通商户身份的标识 + */ + private String partnerId; + /** + * 财付通商户权限密钥Key + */ + private String partnerKey; + + /** + * 支付商户信息 + * + * @param appId + * 公众号唯一的身份ID(必填) + * @param appSecret + * 调用接口的凭证(必填) + * @param paySignKey + * 支付密钥字符串(必填) + * @param partnerId + * 财付通的商户号(必填) + * @param partnerKey + * 财付通商户权限密钥Key(必填) + */ + @JSONCreator + public WeixinPayOldAccount(@JSONField(name = "id") String appId, + @JSONField(name = "secret") String appSecret, + @JSONField(name = "paySignKey") String paySignKey, + @JSONField(name = "partnerId") String partnerId, + @JSONField(name = "partnerKey") String partnerKey) { + super(appId, appSecret); + this.paySignKey = paySignKey; + this.partnerId = partnerId; + this.partnerKey = partnerKey; + } + + public String getPaySignKey() { + return paySignKey; + } + + public String getPartnerId() { + return partnerId; + } + + public String getPartnerKey() { + return partnerKey; + } + + @Override + public String toString() { + return "WeixinPayOldAccount [" + super.toString() + ", paySignKey=" + + paySignKey + ", partnerId=" + partnerId + ", partnerKey=" + + partnerKey + "]"; + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/MicroPayPackage.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/MicroPayPackage.java index 16ae45ec..82186f28 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/MicroPayPackage.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/MicroPayPackage.java @@ -43,6 +43,18 @@ public class MicroPayPackage extends PayPackage { @XmlElement(name = "device_info") @JSONField(name = "device_info") private String deviceInfo; + /** + * 微信分配的子商户公众账号ID 非必须 + */ + @XmlElement(name = "sub_id") + @JSONField(name = "sub_id") + private String subId; + /** + * 微信支付分配的子商户号 非必须 + */ + @XmlElement(name = "sub_mch_id") + @JSONField(name = "sub_mch_id") + private String subMchId; /** * 随机字符串,不长于 32 位 必须 */ @@ -70,22 +82,72 @@ public class MicroPayPackage extends PayPackage { // jaxb required } + /** + * + * @param weixinAccount + * 商户信息 + * @param authCode + * 授权码 + * @param body + * 支付详情 + * @param totalFee + * 支付金额(单位元) 必填 + * @param createIp + * 发起支付的IP地址 + */ public MicroPayPackage(WeixinPayAccount weixinAccount, String authCode, String body, String outTradeNo, double totalFee, String createIp) { this(weixinAccount.getId(), weixinAccount.getMchId(), weixinAccount - .getDeviceInfo(), authCode, body, outTradeNo, totalFee, - createIp, null, null, null, null, null); + .getDeviceInfo(), weixinAccount.getSubId(), weixinAccount + .getSubMchId(), authCode, body, outTradeNo, totalFee, createIp, + null, null, null, null, null); } + /** + * 完整参数 + * + * @param appId + * 公众号唯一标识 必填 + * @param mchId + * 微信支付商户号 必填 + * @param deviceInfo + * 微信支付设备号 非必填 + * @param subId + * 子商户唯一标识 非必填 + * @param subMchId + * 子商户商户号 非必填 + * @param authCode + * 授权码 必填 + * @param body + * 支付详情 必填 + * @param outTradeNo + * 商户侧订单号 必填 + * @param totalFee + * 支付金额(单位元) 必填 + * @param createIp + * 发起支付的IP地址 必填 + * @param attach + * 支付时附加信息 非必填 + * @param timeStart + * 订单生成时间 非必填 + * @param timeExpire + * 订单失效时间 非必填 + * @param goodsTag + * 商品标记 非必填 + * @param limitPay + * 指定支付方式 非必填 + */ public MicroPayPackage(String appId, String mchId, String deviceInfo, - String authCode, String body, String outTradeNo, double totalFee, - String createIp, String attach, Date timeStart, Date timeExpire, - String goodsTag, String limitPay) { + String subId, String subMchId, String authCode, String body, + String outTradeNo, double totalFee, String createIp, String attach, + Date timeStart, Date timeExpire, String goodsTag, String limitPay) { super(body, outTradeNo, totalFee, null, createIp, null, timeStart, timeExpire, goodsTag); this.appId = appId; this.mchId = mchId; this.deviceInfo = deviceInfo; + this.subId = subId; + this.subMchId = subMchId; this.nonceStr = RandomUtil.generateString(16); this.authCode = authCode; this.limitPay = limitPay; @@ -134,8 +196,9 @@ public class MicroPayPackage extends PayPackage { @Override public String toString() { return "MicroPayPackage [appId=" + appId + ", mchId=" + mchId - + ", deviceInfo=" + deviceInfo + ", nonceStr=" + nonceStr - + ", sign=" + sign + ", authCode=" + authCode + ", " - + super.toString() + "]"; + + ", deviceInfo=" + deviceInfo + ", subId=" + subId + + ", subMchId=" + subMchId + ", nonceStr=" + nonceStr + + ", sign=" + sign + ", authCode=" + authCode + ", limitPay=" + + limitPay + ", " + super.toString() + "]"; } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayRequest.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayRequest.java index cdd48b7a..785120b9 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayRequest.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayRequest.java @@ -61,16 +61,9 @@ public class PayRequest extends PayBaseInfo { this.prepayId = prepayId; } - public String getPartnerId() { - return partnerId; - } - - public void setPartnerId(String partnerId) { - this.partnerId = partnerId; - } - @Override public String toString() { - return "package" + packageInfo + ", " + super.toString(); + return "package" + packageInfo + ", prepayId=" + prepayId + + super.toString(); } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/WeixinPayProxy.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/WeixinPayProxy.java index e15e2765..f5c95b83 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/WeixinPayProxy.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/WeixinPayProxy.java @@ -8,7 +8,7 @@ import java.util.Date; import com.foxinmy.weixin4j.api.CashApi; import com.foxinmy.weixin4j.api.CouponApi; -import com.foxinmy.weixin4j.api.Pay3Api; +import com.foxinmy.weixin4j.api.PayApi; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinPayException; import com.foxinmy.weixin4j.http.weixin.XmlResult; @@ -50,7 +50,7 @@ public class WeixinPayProxy { /** * 微信支付API:js支付、扫码支付等接口 */ - private final Pay3Api pay3Api; + private final PayApi pay3Api; /** * 代金券API */ @@ -79,7 +79,7 @@ public class WeixinPayProxy { */ public WeixinPayProxy(Weixin4jSettings settings) { this.settings = settings; - this.pay3Api = new Pay3Api(settings.getWeixinPayAccount()); + this.pay3Api = new PayApi(settings.getWeixinPayAccount()); this.couponApi = new CouponApi(settings.getWeixinPayAccount()); this.cashApi = new CashApi(settings.getWeixinPayAccount()); } @@ -100,7 +100,7 @@ public class WeixinPayProxy { * * @param payPackage * 包含订单信息的对象 - * @see com.foxinmy.weixin4j.api.Pay3Api + * @see com.foxinmy.weixin4j.api.PayApi * @see com.foxinmy.weixin4j.payment.mch.MchPayPackage * @see com.foxinmy.weixin4j.payment.mch.PrePay * @see 收货地址共享 * @return 编辑地址请求JSON串 @@ -235,7 +235,7 @@ public class WeixinPayProxy { * @param productId * 与订单ID等价 * @return 支付链接 - * @see com.foxinmy.weixin4j.api.Pay3Api + * @see com.foxinmy.weixin4j.api.PayApi * @see 扫码支付 * @see 模式一 @@ -260,7 +260,7 @@ public class WeixinPayProxy { * @param createIp * 订单生成的机器 IP * @return Native回调对象 - * @see com.foxinmy.weixin4j.api.Pay3Api + * @see com.foxinmy.weixin4j.api.PayApi * @see com.foxinmy.weixin4j.payment.mch.NativePayResponse * @see 扫码支付 * @see 扫码支付 * @see APP支付 @@ -345,7 +345,7 @@ public class WeixinPayProxy { * @param createIp * 订单生成的机器 IP * @return WAP支付对象 - * @see com.foxinmy.weixin4j.api.Pay3Api + * @see com.foxinmy.weixin4j.api.PayApi * @see com.foxinmy.weixin4j.payment.mch.WAPPayRequest * @see WAP支付 @@ -372,7 +372,7 @@ public class WeixinPayProxy { * @param createIp * 订单生成的机器 IP * @return 支付的订单信息 - * @see com.foxinmy.weixin4j.api.Pay3Api + * @see com.foxinmy.weixin4j.api.PayApi * @see {@link #createMicroPay(MicroPayPackage)} * @throws WeixinException */ @@ -389,7 +389,7 @@ public class WeixinPayProxy { * 订单信息 * @return 支付的订单信息 * @throws WeixinException - * @see com.foxinmy.weixin4j.api.Pay3Api + * @see com.foxinmy.weixin4j.api.PayApi * @see com.foxinmy.weixin4j.payment.MicroPayPackage * @see com.foxinmy.weixin4j.payment.mch.Order * @see out_trade_no * @since V3 * @see com.foxinmy.weixin4j.payment.mch.Order - * @see com.foxinmy.weixin4j.api.Pay3Api + * @see com.foxinmy.weixin4j.api.PayApi * @see 订单查询API * @return 订单详情 @@ -452,7 +452,7 @@ public class WeixinPayProxy { * * @return 退款申请结果 * @see com.foxinmy.weixin4j.payment.mch.RefundResult - * @see com.foxinmy.weixin4j.api.Pay3Api + * @see com.foxinmy.weixin4j.api.PayApi * @see 申请退款API * @since V3 @@ -492,7 +492,7 @@ public class WeixinPayProxy { * 四个参数必填一个,优先级为: * refund_id>out_refund_no>transaction_id>out_trade_no * @return 退款记录 - * @see com.foxinmy.weixin4j.api.Pay3Api + * @see com.foxinmy.weixin4j.api.PayApi * @see com.foxinmy.weixin4j.payment.mch.RefundRecord * @see 退款查询API @@ -517,7 +517,7 @@ public class WeixinPayProxy { * REFUND,返回当日退款订单 * @return excel表格 * @since V2 & V3 - * @see com.foxinmy.weixin4j.api.Pay3Api + * @see com.foxinmy.weixin4j.api.PayApi * @see 下载对账单API * @throws WeixinException @@ -539,7 +539,7 @@ public class WeixinPayProxy { * 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级: * transaction_id> out_trade_no * @return 撤销结果 - * @see com.foxinmy.weixin4j.api.Pay3Api + * @see com.foxinmy.weixin4j.api.PayApi * @since V3 * @throws WeixinException */ @@ -574,7 +574,7 @@ public class WeixinPayProxy { * @param outTradeNo * 商户系统内部的订单号 * @return 执行结果 - * @see com.foxinmy.weixin4j.api.Pay3Api + * @see com.foxinmy.weixin4j.api.PayApi * @since V3 * @throws WeixinException * @see 转换短链接API * @since V3 @@ -618,7 +618,7 @@ public class WeixinPayProxy { * @param returnXml * 调用接口返回的基本数据 * @return 处理结果 - * @see com.foxinmy.weixin4j.api.Pay3Api + * @see com.foxinmy.weixin4j.api.PayApi * @see 接口测试上报API * @throws WeixinException diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/APPPayRequest.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/APPPayRequest.java index 69a8d174..881b3a24 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/APPPayRequest.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/APPPayRequest.java @@ -19,7 +19,6 @@ import com.foxinmy.weixin4j.util.MapUtil; * href="https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=8_1">APP支付 */ public class APPPayRequest extends AbstractPayRequest { - public APPPayRequest(String prePayId, WeixinPayAccount payAccount) { super(prePayId, payAccount); } @@ -37,7 +36,6 @@ public class APPPayRequest extends AbstractPayRequest { PayRequest payRequest = new PayRequest(getPayAccount().getId(), "Sign=WXPay"); payRequest.setPrepayId(getPrePayId()); - payRequest.setPartnerId(getPayAccount().getPartnerId()); return payRequest; } @@ -53,7 +51,7 @@ public class APPPayRequest extends AbstractPayRequest { content.append(String.format("", payRequest.getAppId())); content.append(String.format("", - payRequest.getPartnerId())); + getPayAccount().getPartnerId())); content.append(String.format("", payRequest.getPrepayId())); content.append(String.format("", diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/ApiResult.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/ApiResult.java index a1d4e364..e8efa7c7 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/ApiResult.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/ApiResult.java @@ -36,7 +36,13 @@ public class ApiResult extends XmlResult { @JSONField(name = "mch_id") private String mchId; /** - * 代理模式下分配的商户号 可能为空 + * 微信分配的子商户公众账号ID 非必须 + */ + @XmlElement(name = "sub_id") + @JSONField(name = "sub_id") + private String subId; + /** + * 微信支付分配的子商户号 非必须 */ @XmlElement(name = "sub_mch_id") @JSONField(name = "sub_mch_id") @@ -86,6 +92,14 @@ public class ApiResult extends XmlResult { this.mchId = mchId; } + public String getSubId() { + return subId; + } + + public void setSubId(String subId) { + this.subId = subId; + } + public String getSubMchId() { return subMchId; } @@ -133,9 +147,9 @@ public class ApiResult extends XmlResult { @Override public String toString() { - return "appId=" + appId + ", mchId=" + mchId + ", subMchId=" + subMchId - + ", nonceStr=" + nonceStr + ", sign=" + sign + ", deviceInfo=" - + deviceInfo + ", recall=" + getFormatRecall() + ", " - + super.toString(); + return "appId=" + appId + ", mchId=" + mchId + ", subId=" + subId + + ", subMchId=" + subMchId + ", nonceStr=" + nonceStr + + ", sign=" + sign + ", deviceInfo=" + deviceInfo + ", recall=" + + getFormatRecall() + ", " + super.toString(); } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MchPayPackage.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MchPayPackage.java index 96272cfe..cf7bbb6d 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MchPayPackage.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MchPayPackage.java @@ -14,7 +14,7 @@ import com.foxinmy.weixin4j.type.TradeType; import com.foxinmy.weixin4j.util.RandomUtil; /** - * JS支付订单详情 + * 支付订单详情 * * @className MchPayPackage * @author jy @@ -46,6 +46,24 @@ public class MchPayPackage extends PayPackage { @XmlElement(name = "device_info") @JSONField(name = "device_info") private String deviceInfo; + /** + * 微信分配的子商户公众账号ID 非必须 + */ + @XmlElement(name = "sub_id") + @JSONField(name = "sub_id") + private String subId; + /** + * 微信支付分配的子商户号 非必须 + */ + @XmlElement(name = "sub_mch_id") + @JSONField(name = "sub_mch_id") + private String subMchId; + /** + * 用户子标识 非必须 + */ + @XmlElement(name = "sub_openid") + @JSONField(name = "sub_openid") + private String subOpenId; /** * 随机字符串,不长于 32 位 必须 */ @@ -85,6 +103,25 @@ public class MchPayPackage extends PayPackage { // jaxb required } + /** + * + * @param weixinAccount + * 商户信息 必填 + * @param openId + * 用户唯一标识 JSAPI支付必填 + * @param body + * 支付详情 必填 + * @param outTradeNo + * 商户侧订单号 必填 + * @param totalFee + * 支付金额(单位元) 必填 + * @param notifyUrl + * 支付回调URL + * @param createIp + * 发起支付的IP地址 + * @param tradeType + * 支付类型 + */ public MchPayPackage(WeixinPayAccount weixinAccount, String openId, String body, String outTradeNo, double totalFee, String notifyUrl, String createIp, TradeType tradeType) { @@ -92,17 +129,83 @@ public class MchPayPackage extends PayPackage { createIp, tradeType, null); } + /** + * + * @param weixinAccount + * 商户信息 必填 + * @param openId + * 用户唯一标识 JSAPI支付必填 + * @param body + * 支付详情 必填 + * @param outTradeNo + * 商户侧订单号 必填 + * @param totalFee + * 支付金额(单位元) 必填 + * @param notifyUrl + * 支付回调URL + * @param createIp + * 发起支付的IP地址 + * @param tradeType + * 支付类型 + * @param attach + * 支付时附加信息 + */ public MchPayPackage(WeixinPayAccount weixinAccount, String openId, String body, String outTradeNo, double totalFee, String notifyUrl, String createIp, TradeType tradeType, String attach) { this(weixinAccount.getId(), weixinAccount.getMchId(), weixinAccount - .getDeviceInfo(), body, outTradeNo, totalFee, notifyUrl, + .getDeviceInfo(), weixinAccount.getSubId(), weixinAccount + .getSubMchId(), null, body, outTradeNo, totalFee, notifyUrl, createIp, tradeType, openId, attach, null, null, null, null, null); } + /** + * 完整参数 + * + * @param appId + * 公众号唯一标识 必填 + * @param mchId + * 微信支付商户号 必填 + * @param deviceInfo + * 微信支付设备号 非必填 + * @param subId + * 子商户唯一标识 非必填 + * @param subMchId + * 子商户商户号 非必填 + * @param subOpenId + * 用户在子商户appid下的唯一标识 非必填 + * openid和sub_openid可以选传其中之一,如果选择传sub_openid ,则必须传sub_appid + * @param body + * 支付详情 必填 + * @param outTradeNo + * 商户侧订单号 必填 + * @param totalFee + * 支付金额(单位元) 必填 + * @param notifyUrl + * 支付回调URL 必填 + * @param createIp + * 发起支付的IP地址 必填 + * @param tradeType + * 支付类型 必填 + * @param openId + * 用户唯一标识 JSAPI支付必填 + * @param attach + * 支付时附加信息 非必填 + * @param timeStart + * 订单生成时间 非必填 + * @param timeExpire + * 订单失效时间 非必填 + * @param goodsTag + * 商品标记 非必填 + * @param productId + * 商品ID native支付必填 + * @param limitPay + * 指定支付方式 非必填 + */ public MchPayPackage(String appId, String mchId, String deviceInfo, - String body, String outTradeNo, double totalFee, String notifyUrl, + String subId, String subMchId, String subOpenId, String body, + String outTradeNo, double totalFee, String notifyUrl, String createIp, TradeType tradeType, String openId, String attach, Date timeStart, Date timeExpire, String goodsTag, String productId, String limitPay) { @@ -111,6 +214,9 @@ public class MchPayPackage extends PayPackage { this.appId = appId; this.mchId = mchId; this.deviceInfo = deviceInfo; + this.subId = subId; + this.subMchId = subMchId; + this.subOpenId = subOpenId; this.nonceStr = RandomUtil.generateString(16); this.tradeType = tradeType.name(); this.openId = openId; @@ -169,9 +275,10 @@ public class MchPayPackage extends PayPackage { @Override public String toString() { return "MchPayPackage [appId=" + appId + ", mchId=" + mchId - + ", deviceInfo=" + deviceInfo + ", nonceStr=" + nonceStr - + ", sign=" + sign + ", tradeType=" + tradeType + ", openId=" - + openId + ", productId=" + productId + ", " + super.toString() - + "]"; + + ", deviceInfo=" + deviceInfo + ", subId=" + subId + + ", subMchId=" + subMchId + ", subOpenId=" + subOpenId + + ", nonceStr=" + nonceStr + ", sign=" + sign + ", tradeType=" + + tradeType + ", openId=" + openId + ", productId=" + productId + + ", limitPay=" + limitPay + ", " + super.toString() + "]"; } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/Order.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/Order.java index e12c4353..5136ae6e 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/Order.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/Order.java @@ -18,7 +18,7 @@ import com.foxinmy.weixin4j.util.DateUtil; import com.foxinmy.weixin4j.xml.ListsuffixResult; /** - * V3订单信息 + * 订单信息 * * @className Order * @author jy @@ -131,6 +131,19 @@ public class Order extends ApiResult { @JSONField(name = "trade_state_desc") private String tradeStateDesc; + /** + * 用户在子商户下的openid + */ + @XmlElement(name = "sub_openid") + @JSONField(name = "sub_openid") + private String subOpenId; + /** + * 是否关注子公众账号,Y- 关注,N-未关注,仅在公众 账号类型支付有效 + */ + @XmlElement(name = "sub_is_subscribe") + @JSONField(name = "sub_is_subscribe") + private String subIsSubscribe; + protected Order() { // jaxb required } @@ -267,6 +280,19 @@ public class Order extends ApiResult { this.couponList = couponList; } + public String getSubOpenId() { + return subOpenId; + } + + public String getSubIsSubscribe() { + return subIsSubscribe; + } + + @JSONField(serialize = false) + public boolean getFormatSubIsSubscribe() { + return subIsSubscribe != null && subIsSubscribe.equalsIgnoreCase("y"); + } + @Override public String toString() { return "Order [tradeState=" + tradeState + ", openId=" + openId @@ -278,7 +304,8 @@ public class Order extends ApiResult { + getFormatCouponFee() + ", couponCount=" + couponCount + ", couponList=" + couponList + ", cashFee=" + getFormatCashFee() + ", timeEnd=" + getFormatTimeEnd() - + ", tradeStateDesc=" + tradeStateDesc + ", " + + ", tradeStateDesc=" + tradeStateDesc + ", subOpenId=" + + subOpenId + ", subIsSubscribe=" + subIsSubscribe + super.toString() + "]"; } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/Redpacket.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/Redpacket.java index 3cea660d..079dce00 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/Redpacket.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/Redpacket.java @@ -8,7 +8,9 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.model.WeixinPayAccount; import com.foxinmy.weixin4j.util.DateUtil; +import com.foxinmy.weixin4j.util.RandomUtil; /** * 红包 @@ -27,12 +29,53 @@ import com.foxinmy.weixin4j.util.DateUtil; public class Redpacket implements Serializable { private static final long serialVersionUID = -7021352305575714281L; + /** + * 微信分配的公众账号 ID商户号 非空 + */ + @XmlElement(name = "wxappid") + @JSONField(name = "wxappid") + private String appId; + /** + * 微信支付分配的商户号 非空 + */ + @XmlElement(name = "mch_id") + @JSONField(name = "mch_id") + private String mchId; + /** + * 微信支付分配的子商户号 非必须 + */ + @XmlElement(name = "sub_mch_id") + @JSONField(name = "sub_mch_id") + private String subMchId; + /** + * 服务商模式下触达用户时的appid(可填服务商自己的appid或子商户的appid),服务商模式下必填, + * 服务商模式下填入的子商户appid必须在微信支付商户平台中先录入,否则会校验不过。 非必须 + */ + @XmlElement(name = "msgappid") + @JSONField(name = "msgappid") + private String subMsgId; + /** + * 扣钱方mchid,常规模式下无效,服务商模式下选填,服务商模式下不填默认扣子商户的钱.非必须 + */ + @XmlElement(name = "consume_mch_id") + @JSONField(name = "consume_mch_id") + private String consumeMchId; /** * 商户订单号(每个订单号必须唯一) 组成: mch_id+yyyymmdd+10位一天内不能重复的数字。 */ @XmlElement(name = "mch_billno") @JSONField(name = "mch_billno") private String outTradeNo; + /** + * 随机字符串,不长于 32 位 必须 + */ + @XmlElement(name = "nonce_str") + @JSONField(name = "nonce_str") + private String nonceStr; + /** + * 签名 调用者无需关心 + */ + private String sign; /** * 红包发送者名称 必填 */ @@ -92,23 +135,83 @@ public class Redpacket implements Serializable { * 红包 * * @param outTradeNo - * 商户侧一天内不可重复的订单号 接口根据商户订单号支持重入 如出现超时可再调用 + * 商户侧一天内不可重复的订单号 接口根据商户订单号支持重入 如出现超时可再调用 必填 * @param sendName - * 红包发送者名称 + * 红包发送者名称 必填 * @param openid - * 接受收红包的用户的openid + * 接受收红包的用户的openid 必填 * @param totalAmount - * 付款金额 单位为元,自动格式化为分 + * 付款金额 单位为元,自动格式化为分 必填 * @param totalNum - * 红包发放总人数 大于1视为裂变红包 + * 红包发放总人数 大于1视为裂变红包 必填 + * @param wishing + * 红包祝福语 必填 + * @param clientIp + * Ip地址 必填 + * @param actName + * 活动名称 必填 + * @param remark + * 备注 必填 */ - public Redpacket(String outTradeNo, String sendName, String openid, - double totalAmount, int totalNum) { + public Redpacket(WeixinPayAccount payAccount, String outTradeNo, + String sendName, String openid, double totalAmount, int totalNum, + String wishing, String clientIp, String actName, String remark) { + this(payAccount.getId(), payAccount.getMchId(), payAccount + .getSubMchId(), null, null, outTradeNo, sendName, openid, + totalAmount, totalNum, wishing, clientIp, actName, remark); + } + + /** + * 红包 完整参数 + * + * @param appId + * 公众号唯一标识 必填 + * @param mchId + * 微信支付商户号 必填 + * @param subMchId + * 子商户商户号 非必填 + * @param subMsgId + * 触达用户appid 非必填 + * @param consumeMchId + * 扣钱方mchid 非必填 + * @param outTradeNo + * 商户侧一天内不可重复的订单号 接口根据商户订单号支持重入 如出现超时可再调用 必填 + * @param sendName + * 红包发送者名称 必填 + * @param openid + * 接受收红包的用户的openid 必填 + * @param totalAmount + * 付款金额 单位为元,自动格式化为分 必填 + * @param totalNum + * 红包发放总人数 大于1视为裂变红包 必填 + * @param wishing + * 红包祝福语 必填 + * @param clientIp + * Ip地址 必填 + * @param actName + * 活动名称 必填 + * @param remark + * 备注 必填 + */ + public Redpacket(String appId, String mchId, String subMchId, + String subMsgId, String consumeMchId, String outTradeNo, + String sendName, String openid, double totalAmount, int totalNum, + String wishing, String clientIp, String actName, String remark) { + this.appId = appId; + this.mchId = mchId; + this.subMchId = subMchId; + this.subMsgId = subMsgId; + this.consumeMchId = consumeMchId; this.outTradeNo = outTradeNo; this.sendName = sendName; this.openid = openid; - this.totalAmount = DateUtil.formaFee2Fen(totalAmount); this.totalNum = totalNum; + this.wishing = wishing; + this.clientIp = clientIp; + this.actName = actName; + this.remark = remark; + this.nonceStr = RandomUtil.generateString(16); + this.totalAmount = DateUtil.formaFee2Fen(totalAmount); this.amtType = totalNum > 1 ? "ALL_RAND" : null; } @@ -136,10 +239,6 @@ public class Redpacket implements Serializable { return wishing; } - public void setWishing(String wishing) { - this.wishing = wishing; - } - public String getAmtType() { return amtType; } @@ -148,32 +247,31 @@ public class Redpacket implements Serializable { return clientIp; } - public void setClientIp(String clientIp) { - this.clientIp = clientIp; - } - public String getActName() { return actName; } - public void setActName(String actName) { - this.actName = actName; - } - public String getRemark() { return remark; } - public void setRemark(String remark) { - this.remark = remark; + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; } @Override public String toString() { - return "Redpacket [ sendName=" + sendName + ", openid=" + openid - + ", amtType=" + amtType + ", totalAmount=" + totalAmount - + ", totalNum=" + totalNum + ", wishing=" + wishing + return "Redpacket [appId=" + appId + ", mchId=" + mchId + ", subMchId=" + + subMchId + ", subMsgId=" + subMsgId + ", consumeMchId=" + + consumeMchId + ", outTradeNo=" + outTradeNo + ", nonceStr=" + + nonceStr + ", sendName=" + sendName + ", openid=" + openid + + ", totalAmount=" + totalAmount + ", totalNum=" + totalNum + + ", amtType=" + amtType + ", wishing=" + wishing + ", clientIp=" + clientIp + ", actName=" + actName - + ", remark=" + remark + "]"; + + ", remark=" + remark + ", sign=" + sign + "]"; } } diff --git a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/CashTest.java b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/CashTest.java index c1d0f9d9..01f25a1e 100644 --- a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/CashTest.java +++ b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/CashTest.java @@ -26,21 +26,18 @@ public class CashTest extends PayTest { @Test public void sendRedpacket() throws WeixinException, IOException { - Redpacket redpacket = new Redpacket("HB001", "无忧钱庄", - "oyFLst1bqtuTcxK-ojF8hOGtLQao", 1d, 1); - redpacket.setActName("红包测试"); - redpacket.setClientIp("127.0.0.1"); - redpacket.setRemark("快来领取红包吧!"); - redpacket.setWishing("来就送钱"); - RedpacketSendResult result = PAY3.sendRedpack(new FileInputStream( - caFile), redpacket); + Redpacket redpacket = new Redpacket(ACCOUNT, "HB001", "无忧钱庄", + "oyFLst1bqtuTcxK-ojF8hOGtLQao", 1d, 1, "红包测试", "127.0.0.1", + "快来领取红包吧!", "来就送钱"); + RedpacketSendResult result = PAY.sendRedpack( + new FileInputStream(caFile), redpacket); System.err.println(result); } @Test public void queryRedpacket() throws WeixinException, IOException { String outTradeNo = "HB001"; - RedpacketRecord record = PAY3.queryRedpack(new FileInputStream(caFile), + RedpacketRecord record = PAY.queryRedpack(new FileInputStream(caFile), outTradeNo); System.err.println(record); } @@ -50,14 +47,14 @@ public class CashTest extends PayTest { CorpPayment payment = new CorpPayment("MP001", "ofW1gwok9vZIyle0YbA-eQe83Uk8", MPPaymentCheckNameType.NO_CHECK, "企业付款测试", 1d, "127.0.0.1"); - CorpPaymentResult result = PAY3.corpPayment( - new FileInputStream(caFile), payment); + CorpPaymentResult result = PAY.corpPayment(new FileInputStream(caFile), + payment); System.err.println(result); } @Test public void mchPaymentQuery() throws WeixinException, IOException { - System.err.println(PAY3.queryCorpPayment(new FileInputStream(caFile), + System.err.println(PAY.queryCorpPayment(new FileInputStream(caFile), "MP001")); } } diff --git a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/CouponTest.java b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/CouponTest.java index 99801928..3ae8cb53 100644 --- a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/CouponTest.java +++ b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/CouponTest.java @@ -27,22 +27,22 @@ public class CouponTest extends PayTest { @Test public void sendCoupon() throws WeixinException, IOException { - String partnerTradeNo = String.format("%s%s%s", ACCOUNT3.getMchId(), + String partnerTradeNo = String.format("%s%s%s", ACCOUNT.getMchId(), DateUtil.fortmat2yyyyMMdd(new Date()), "1"); - CouponResult result = PAY3.sendCoupon(new FileInputStream(caFile), + CouponResult result = PAY.sendCoupon(new FileInputStream(caFile), "123", partnerTradeNo, "oyFLst1bqtuTcxK-ojF8hOGtLQao", null); Assert.assertTrue(result.getRetCode().equalsIgnoreCase(Consts.SUCCESS)); } @Test public void queryCouponStock() throws WeixinException { - CouponStock couponStock = PAY3.queryCouponStock("couponStockId"); + CouponStock couponStock = PAY.queryCouponStock("couponStockId"); System.err.println(couponStock); } @Test public void queryCouponDetail() throws WeixinException { - CouponDetail couponDetail = PAY3.queryCouponDetail("couponId"); + CouponDetail couponDetail = PAY.queryCouponDetail("couponId"); System.err.println(couponDetail); } } diff --git a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/PayTest.java b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/PayTest.java index ac1d9ce6..1c6a76f5 100644 --- a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/PayTest.java +++ b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/PayTest.java @@ -34,12 +34,11 @@ import com.foxinmy.weixin4j.util.Weixin4jSettings; * @see */ public class PayTest { - protected final static WeixinPayProxy PAY3; - protected final static WeixinPayAccount ACCOUNT3; + protected final static WeixinPayProxy PAY; + protected final static WeixinPayAccount ACCOUNT; static { - ACCOUNT3 = new WeixinPayAccount("appid", "appsecret", "paySignKey", - "mchid"); - PAY3 = new WeixinPayProxy(new Weixin4jSettings(ACCOUNT3)); + ACCOUNT = new WeixinPayAccount("appid", "paySignKey", "mchid"); + PAY = new WeixinPayProxy(new Weixin4jSettings(ACCOUNT)); } /** * 商户证书文件 @@ -48,13 +47,12 @@ public class PayTest { @Test public void orderQueryV3() throws WeixinException { - Order order = PAY3.orderQuery(new IdQuery("BY2016010800025", + Order order = PAY.orderQuery(new IdQuery("BY2016010800025", IdType.TRADENO)); System.err.println(order); String sign = order.getSign(); order.setSign(null); - String valiSign = DigestUtil - .paysignMd5(order, ACCOUNT3.getPaySignKey()); + String valiSign = DigestUtil.paysignMd5(order, ACCOUNT.getPaySignKey()); System.err .println(String.format("sign=%s,valiSign=%s", sign, valiSign)); Assert.assertEquals(valiSign, sign); @@ -62,14 +60,14 @@ public class PayTest { @Test public void refundQueryV3() throws WeixinException { - com.foxinmy.weixin4j.payment.mch.RefundRecord record = PAY3 + com.foxinmy.weixin4j.payment.mch.RefundRecord record = PAY .refundQuery(new IdQuery("TT_1427183696238", IdType.TRADENO)); System.err.println(record); // 这里的验证签名需要把details循环拼接 String sign = record.getSign(); record.setSign(null); - String valiSign = DigestUtil.paysignMd5(record, - ACCOUNT3.getPaySignKey()); + String valiSign = DigestUtil + .paysignMd5(record, ACCOUNT.getPaySignKey()); System.err .println(String.format("sign=%s,valiSign=%s", sign, valiSign)); Assert.assertEquals(valiSign, sign); @@ -83,22 +81,22 @@ public class PayTest { c.set(Calendar.MONTH, 2); c.set(Calendar.DAY_OF_MONTH, 24); System.err.println(c.getTime()); - File file = PAY3.downloadBill(c.getTime(), null); + File file = PAY.downloadBill(c.getTime(), null); System.err.println(file); } @Test public void refundV3() throws WeixinException, IOException { IdQuery idQuery = new IdQuery("TT_1427183696238", IdType.TRADENO); - com.foxinmy.weixin4j.payment.mch.RefundResult result = PAY3 - .refundApply(new FileInputStream(caFile), idQuery, "TT_R" - + System.currentTimeMillis(), 0.01d, 0.01d, null, - "10020674"); + com.foxinmy.weixin4j.payment.mch.RefundResult result = PAY.refundApply( + 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, - ACCOUNT3.getPaySignKey()); + String valiSign = DigestUtil + .paysignMd5(result, ACCOUNT.getPaySignKey()); System.err .println(String.format("sign=%s,valiSign=%s", sign, valiSign)); Assert.assertEquals(valiSign, sign); @@ -106,13 +104,13 @@ public class PayTest { @Test public void nativeV3() throws WeixinException { - MchPayPackage payPackageV3 = new MchPayPackage(ACCOUNT3, + MchPayPackage payPackageV3 = new MchPayPackage(ACCOUNT, "oyFLst1bqtuTcxK-ojF8hOGtLQao", "native测试", "T0001", 0.1d, "notify_url", "127.0.0.1", TradeType.NATIVE); payPackageV3.setProductId("0001"); PrePay prePay = null; try { - prePay = PAY3.createPrePay(payPackageV3); + prePay = PAY.createPrePay(payPackageV3); } catch (WeixinPayException e) { e.printStackTrace(); } @@ -121,12 +119,12 @@ public class PayTest { @Test public void closeOrder() throws WeixinException { - ApiResult result = PAY3.closeOrder("D111"); + ApiResult result = PAY.closeOrder("D111"); System.err.println(result); String sign = result.getSign(); result.setSign(null); - String valiSign = DigestUtil.paysignMd5(result, - ACCOUNT3.getPaySignKey()); + String valiSign = DigestUtil + .paysignMd5(result, ACCOUNT.getPaySignKey()); System.err .println(String.format("sign=%s,valiSign=%s", sign, valiSign)); Assert.assertEquals(valiSign, sign); @@ -135,7 +133,7 @@ public class PayTest { @Test public void shortUrl() throws WeixinException { String url = "weixin://wxpay/bizpayurl?xxxxxx"; - String shortUrl = PAY3.getPayShorturl(url); + String shortUrl = PAY.getPayShorturl(url); System.err.println(shortUrl); } @@ -148,7 +146,7 @@ public class PayTest { Date time = new Date(); XmlResult returnXml = new XmlResult("SUCCESS", ""); returnXml.setResultCode("SUCCESS"); - returnXml = PAY3.interfaceReport(interfaceUrl, executeTime, outTradeNo, + returnXml = PAY.interfaceReport(interfaceUrl, executeTime, outTradeNo, ip, time, returnXml); System.err.println(returnXml); } diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/Pay2Api.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/PayOldApi.java similarity index 93% rename from weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/Pay2Api.java rename to weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/PayOldApi.java index 9b464f5a..dcb3e0ce 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/Pay2Api.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/PayOldApi.java @@ -33,14 +33,16 @@ import com.foxinmy.weixin4j.http.weixin.WeixinResponse; import com.foxinmy.weixin4j.http.weixin.WeixinSSLRequestExecutor; import com.foxinmy.weixin4j.model.Consts; import com.foxinmy.weixin4j.model.Token; -import com.foxinmy.weixin4j.model.WeixinPayAccount; +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.token.WeixinTokenCreator; import com.foxinmy.weixin4j.payment.PayRequest; +import com.foxinmy.weixin4j.token.FileTokenStorager; import com.foxinmy.weixin4j.token.TokenHolder; +import com.foxinmy.weixin4j.token.TokenStorager; import com.foxinmy.weixin4j.type.BillType; import com.foxinmy.weixin4j.type.IdQuery; import com.foxinmy.weixin4j.type.RefundType; @@ -50,11 +52,11 @@ import com.foxinmy.weixin4j.util.DigestUtil; import com.foxinmy.weixin4j.util.MapUtil; import com.foxinmy.weixin4j.util.RandomUtil; import com.foxinmy.weixin4j.util.StringUtil; -import com.foxinmy.weixin4j.util.Weixin4jSettings; +import com.foxinmy.weixin4j.util.Weixin4jConfigUtil; import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer; /** - * V2支付API + * V2老支付API * * @className Pay2Api * @author jy @@ -62,24 +64,40 @@ import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer; * @since JDK 1.6 * @see */ -public class Pay2Api extends MpApi { +public class PayOldApi extends MpApi { - private final Weixin4jSettings settings; + private final WeixinPayOldAccount payAccount; private final TokenHolder tokenHolder; - public Pay2Api() { - this(new Weixin4jSettings()); + /** + * 默认使用weixin4j.properties配置信息 + */ + public PayOldApi() { + this(JSON.parseObject(Weixin4jConfigUtil.getValue("account"), + WeixinPayOldAccount.class), new FileTokenStorager( + Weixin4jConfigUtil.getClassPathValue("weixin4j.tmpdir", + System.getProperty("java.io.tmpdir")))); } - public Pay2Api(Weixin4jSettings settings) { - this.tokenHolder = new TokenHolder(new WeixinTokenCreator(settings - .getWeixinAccount().getId(), settings.getWeixinAccount() - .getSecret()), settings.getTokenStorager0()); - this.settings = settings; + public PayOldApi(WeixinPayOldAccount payAccount) { + this(payAccount, new FileTokenStorager( + Weixin4jConfigUtil.getClassPathValue("weixin4j.tmpdir", + System.getProperty("java.io.tmpdir")))); } - public WeixinPayAccount getPayAccount() { - return this.settings.getWeixinPayAccount(); + public PayOldApi(TokenStorager tokenStorager) { + this(JSON.parseObject(Weixin4jConfigUtil.getValue("account"), + WeixinPayOldAccount.class), tokenStorager); + } + + public PayOldApi(WeixinPayOldAccount payAccount, TokenStorager tokenStorager) { + this.payAccount = payAccount; + this.tokenHolder = new TokenHolder(new WeixinTokenCreator( + payAccount.getId(), payAccount.getSecret()), tokenStorager); + } + + public WeixinPayOldAccount getPayAccount() { + return this.payAccount; } /** @@ -294,7 +312,7 @@ public class Pay2Api extends MpApi { CertificateFactory cf = CertificateFactory .getInstance(com.foxinmy.weixin4j.model.Consts.X509); java.security.cert.Certificate cert = cf - .generateCertificate(Pay2Api.class + .generateCertificate(PayOldApi.class .getResourceAsStream("cacert.pem")); ks = KeyStore .getInstance(com.foxinmy.weixin4j.model.Consts.JKS); @@ -433,11 +451,13 @@ public class Pay2Api extends MpApi { * @param billType * 下载对账单的类型 ALL,返回当日所有订单信息, 默认值 SUCCESS,返回当日成功支付的订单 * REFUND,返回当日退款订单 + * @param billPath + * 对账单保存路径 * @return excel表格 * @since V2 * @throws WeixinException */ - public File downloadBill(Date billDate, BillType billType) + public File downloadBill(Date billDate, BillType billType, String billPath) throws WeixinException { if (billDate == null) { Calendar now = Calendar.getInstance(); @@ -450,8 +470,7 @@ public class Pay2Api extends MpApi { String formatBillDate = DateUtil.fortmat2yyyyMMdd(billDate); String fileName = String.format("%s_%s_%s.txt", formatBillDate, billType.name().toLowerCase(), getPayAccount().getId()); - File file = new File(String.format("%s/weixin4j_bill_%s", - settings.getTmpdir0(), fileName)); + File file = new File(String.format("%s/%s", billPath, fileName)); if (file.exists()) { return file; } diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v2/NativePayResponseV2.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v2/NativePayResponseV2.java index fa03f197..10b29eaf 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v2/NativePayResponseV2.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/payment/v2/NativePayResponseV2.java @@ -9,7 +9,7 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import com.alibaba.fastjson.annotation.JSONField; -import com.foxinmy.weixin4j.model.WeixinPayAccount; +import com.foxinmy.weixin4j.model.WeixinPayOldAccount; import com.foxinmy.weixin4j.payment.PayRequest; import com.foxinmy.weixin4j.util.DigestUtil; @@ -62,7 +62,7 @@ public class NativePayResponseV2 extends PayRequest { * @param payPackage * 订单信息 */ - public NativePayResponseV2(WeixinPayAccount weixinAccount, + public NativePayResponseV2(WeixinPayOldAccount weixinAccount, PayPackageV2 payPackage) { super(weixinAccount.getId(), DigestUtil.packageSign(payPackage, weixinAccount.getPartnerKey())); diff --git a/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/PayTest.java b/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/PayTest.java index d198739d..6de07213 100644 --- a/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/PayTest.java +++ b/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/PayTest.java @@ -6,11 +6,10 @@ import java.util.Calendar; import org.junit.Test; import com.foxinmy.weixin4j.exception.WeixinException; -import com.foxinmy.weixin4j.model.WeixinPayAccount; -import com.foxinmy.weixin4j.mp.api.Pay2Api; +import com.foxinmy.weixin4j.model.WeixinPayOldAccount; +import com.foxinmy.weixin4j.mp.api.PayOldApi; import com.foxinmy.weixin4j.type.IdQuery; import com.foxinmy.weixin4j.type.IdType; -import com.foxinmy.weixin4j.util.Weixin4jSettings; /** * 支付测试(V2版本 2014年9月之前申请微信支付的公众号) @@ -22,13 +21,13 @@ import com.foxinmy.weixin4j.util.Weixin4jSettings; * @see */ public class PayTest { - protected final static Pay2Api PAY2; - protected final static WeixinPayAccount ACCOUNT2; + protected final static PayOldApi PAY2; + protected final static WeixinPayOldAccount ACCOUNT2; static { - ACCOUNT2 = new WeixinPayAccount("请填入v2版本的appid", "请填入v2版本的appSecret", - "请填入v2版本的paysignkey", null, null, null, null, - "请填入v2版本的partnerId", "请填入v2版本的partnerKey"); - PAY2 = new Pay2Api(new Weixin4jSettings(ACCOUNT2)); + ACCOUNT2 = new WeixinPayOldAccount("请填入v2版本的appid", + "请填入v2版本的appSecret", "请填入v2版本的paysignkey", "请填入v2版本的partnerId", + "请填入v2版本的partnerKey"); + PAY2 = new PayOldApi(ACCOUNT2); } /** * 商户证书文件 @@ -60,7 +59,7 @@ public class PayTest { c.set(Calendar.YEAR, 2014); c.set(Calendar.MONTH, 11); c.set(Calendar.DAY_OF_MONTH, 22); - File file = PAY2.downloadBill(c.getTime(), null); + File file = PAY2.downloadBill(c.getTime(), null, "/tmp/bill"); System.err.println(file); } }