diff --git a/pom.xml b/pom.xml index 7b2fd0af..8d90565a 100644 --- a/pom.xml +++ b/pom.xml @@ -47,6 +47,7 @@ weixin4j-server weixin4j-example weixin4j-serverX + weixin4j-pay UTF-8 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 16c74ec5..b3e84b5c 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 @@ -45,7 +45,9 @@ import com.foxinmy.weixin4j.xml.XmlStream; * @see * 企业付款 + * @deprecated 商户平台API迁移到子模块weixin4j-pay */ +@Deprecated public class CashApi extends MchApi { public CashApi(WeixinPayAccount weixinAccount) { @@ -92,7 +94,7 @@ public class CashApi extends MchApi { /** * 批量发放红包 企业向微信用户个人发现金红包 * - * @param redpacket + * @param redpackets * 多个红包信息 * @return 发放结果 * @see #sendRedpacks(Redpacket...) diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/CouponApi.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/CouponApi.java index 0aa07e6c..4129614d 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/CouponApi.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/CouponApi.java @@ -21,7 +21,9 @@ import com.foxinmy.weixin4j.xml.XmlStream; * @since JDK 1.6 * @see 代金券 + * @deprecated 商户平台API迁移到子模块weixin4j-pay */ +@Deprecated public class CouponApi extends MchApi { public CouponApi(WeixinPayAccount weixinAccount) { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/CustomsApi.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/CustomsApi.java index b273c0fb..7aed672d 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/CustomsApi.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/CustomsApi.java @@ -22,7 +22,9 @@ import com.foxinmy.weixin4j.xml.XmlStream; * @date 2016年3月67日 * @since JDK 1.6 * @see + * @deprecated 商户平台API迁移到子模块weixin4j-pay */ +@Deprecated public class CustomsApi extends MchApi { public CustomsApi(WeixinPayAccount weixinAccount) { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/MchApi.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/MchApi.java index 8f89afe8..b0323a0e 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/MchApi.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/MchApi.java @@ -27,7 +27,9 @@ import com.foxinmy.weixin4j.util.Weixin4jConfigUtil; * @date 2016年3月26日 * @since JDK 1.6 * @see 商户支付平台 + * @deprecated 商户平台API迁移到子模块weixin4j-pay */ +@Deprecated public class MchApi extends BaseApi { private final static ResourceBundle WEIXIN_BUNDLE; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/PayApi.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/PayApi.java index e852eff6..b7f6e8ca 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/PayApi.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/PayApi.java @@ -60,7 +60,9 @@ import com.foxinmy.weixin4j.xml.XmlStream; * @author jinyu(foxinmy@gmail.com) * @date 2014年10月28日 * @since JDK 1.6 + * @deprecated 商户平台API迁移到子模块weixin4j-pay */ +@Deprecated public class PayApi extends MchApi { public PayApi(WeixinPayAccount weixinAccount) { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinRequestExecutor.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinRequestExecutor.java index c058041d..1002d472 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinRequestExecutor.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinRequestExecutor.java @@ -39,6 +39,7 @@ import com.foxinmy.weixin4j.logging.InternalLogLevel; import com.foxinmy.weixin4j.logging.InternalLogger; import com.foxinmy.weixin4j.logging.InternalLoggerFactory; import com.foxinmy.weixin4j.util.Consts; +import com.foxinmy.weixin4j.util.StringUtil; import org.bouncycastle.jce.provider.BouncyCastleProvider; import static java.util.regex.Pattern.CASE_INSENSITIVE; @@ -218,10 +219,13 @@ public class WeixinRequestExecutor { try { XmlResult xmlResult = XmlMessageConverter.GLOBAL.convert( XmlResult.class, response); - if (!SUCCESS_CODE.contains(String.format(",%s,", xmlResult - .getResultCode().toLowerCase()))) { - throw new WeixinException(xmlResult.getErrCode(), - xmlResult.getErrCodeDes()); + // 微信最新的刷脸支付API中已没有返回resultCode,需做非空判断,否则抛异常 + if(StringUtil.isNotBlank(xmlResult.getResultCode())) { + if (!SUCCESS_CODE.contains(String.format(",%s,", xmlResult + .getResultCode().toLowerCase()))) { + throw new WeixinException(xmlResult.getErrCode(), + xmlResult.getErrCodeDes()); + } } } catch (IOException e) { ; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/logging/JdkLoggerFactory.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/logging/JdkLoggerFactory.java index 81397cd6..5994d9d4 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/logging/JdkLoggerFactory.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/logging/JdkLoggerFactory.java @@ -16,6 +16,10 @@ package com.foxinmy.weixin4j.logging; +import com.foxinmy.weixin4j.util.Weixin4jConfigUtil; + +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; import java.util.logging.Logger; /** @@ -27,6 +31,15 @@ public class JdkLoggerFactory extends InternalLoggerFactory { @Override public InternalLogger newInstance(String name) { - return new JdkLogger(Logger.getLogger(name)); + Logger logger = Logger.getLogger(name); + Level level = Weixin4jConfigUtil.getJdkLoggerLevel(); + logger.setLevel(level); + if(logger.getHandlers().length==0) { + ConsoleHandler consoleHandler = new ConsoleHandler(); + consoleHandler.setLevel(level); + logger.addHandler(consoleHandler); + } + + return new JdkLogger(logger); } } 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 46a713a4..f23fbcb2 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 @@ -12,7 +12,9 @@ import com.foxinmy.weixin4j.util.StringUtil; * @date 2015年6月26日 * @since JDK 1.6 * @see + * @deprecated 支付相关的类现已迁移到weixin4j-pay子模块 */ +@Deprecated public class WeixinPayAccount extends WeixinAccount { private static final long serialVersionUID = -2791256176906048632L; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/JsPayNotify.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/JsPayNotify.java index 25f61cdd..2cd87d05 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/JsPayNotify.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/JsPayNotify.java @@ -15,7 +15,9 @@ import com.alibaba.fastjson.annotation.JSONField; * @date 2014年8月19日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class JsPayNotify extends PayBaseInfo { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayBaseInfo.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayBaseInfo.java index 07f4796e..b45b330c 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayBaseInfo.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayBaseInfo.java @@ -19,7 +19,9 @@ import com.foxinmy.weixin4j.type.SignType; * @date 2014年11月5日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class PayBaseInfo implements Serializable { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayPackage.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayPackage.java index 00746673..8140b6ba 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayPackage.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayPackage.java @@ -18,7 +18,9 @@ import com.foxinmy.weixin4j.util.DateUtil; * @author jinyu(foxinmy@gmail.com) * @date 2014年12月18日 * @since JDK 1.6 + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class PayPackage extends MerchantResult { 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 c6e2d728..7568277b 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 @@ -10,6 +10,7 @@ import com.alibaba.fastjson.annotation.JSONField; import com.foxinmy.weixin4j.util.DateUtil; import com.foxinmy.weixin4j.util.RandomUtil; +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class PayRequest extends PayBaseInfo { 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 77f021a0..b418a20e 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 @@ -56,7 +56,9 @@ import com.foxinmy.weixin4j.util.Weixin4jConfigUtil; * @date 2015年1月3日 * @since JDK 1.6 * @see 商户平台支付API + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public class WeixinPayProxy { /** diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/CouponDetail.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/CouponDetail.java index 18173d6e..deed288b 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/CouponDetail.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/CouponDetail.java @@ -22,7 +22,9 @@ import com.foxinmy.weixin4j.util.DateUtil; * @date 2015年3月27日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class CouponDetail extends MerchantResult { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/CouponResult.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/CouponResult.java index 2c4b0ba2..b9317583 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/CouponResult.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/CouponResult.java @@ -16,7 +16,9 @@ import com.foxinmy.weixin4j.payment.mch.MerchantResult; * @date 2015年3月25日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class CouponResult extends MerchantResult { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/CouponStock.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/CouponStock.java index e4e6ecef..6fc55765 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/CouponStock.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/CouponStock.java @@ -21,7 +21,9 @@ import com.foxinmy.weixin4j.util.DateUtil; * @date 2015年3月27日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class CouponStock extends MerchantResult { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/OrderCouponInfo.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/OrderCouponInfo.java index 85948d6d..6999e0ef 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/OrderCouponInfo.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/OrderCouponInfo.java @@ -18,7 +18,9 @@ import com.foxinmy.weixin4j.type.mch.CouponType; * @date 2015年3月24日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class OrderCouponInfo implements Serializable { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/RefundCouponInfo.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/RefundCouponInfo.java index 4392345a..e660d6fa 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/RefundCouponInfo.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/coupon/RefundCouponInfo.java @@ -17,7 +17,9 @@ import com.alibaba.fastjson.annotation.JSONField; * @date 2015年3月24日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class RefundCouponInfo implements Serializable { 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 e8ce7267..d9c8b981 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 @@ -21,7 +21,9 @@ import com.foxinmy.weixin4j.util.MapUtil; * @see com.foxinmy.weixin4j.payment.PayRequest * @see APP支付 + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public class APPPayRequest extends AbstractPayRequest { public APPPayRequest(String prePayId, WeixinPayAccount payAccount) { super(prePayId, payAccount); diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/AbstractPayRequest.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/AbstractPayRequest.java index 7e344dd8..c75d225d 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/AbstractPayRequest.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/AbstractPayRequest.java @@ -4,6 +4,7 @@ import com.foxinmy.weixin4j.model.WeixinPayAccount; import com.foxinmy.weixin4j.sign.WeixinPaymentSignature; import com.foxinmy.weixin4j.sign.WeixinSignature; +@Deprecated public abstract class AbstractPayRequest implements MchPayRequest { private final String prePayId; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CorpPayment.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CorpPayment.java index 16eccfef..2ad2123c 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CorpPayment.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CorpPayment.java @@ -17,7 +17,9 @@ import com.foxinmy.weixin4j.util.DateUtil; * @date 2015年4月1日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class CorpPayment extends MerchantResult { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CorpPaymentRecord.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CorpPaymentRecord.java index 85e50da6..fd421cde 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CorpPaymentRecord.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CorpPaymentRecord.java @@ -19,7 +19,9 @@ import com.foxinmy.weixin4j.util.DateUtil; * @date 2015年6月23日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class CorpPaymentRecord extends MerchantResult { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CorpPaymentResult.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CorpPaymentResult.java index f0656a4f..62011fd1 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CorpPaymentResult.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CorpPaymentResult.java @@ -18,7 +18,9 @@ import com.foxinmy.weixin4j.util.DateUtil; * @date 2015年4月1日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class CorpPaymentResult extends MerchantResult { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CustomsOrder.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CustomsOrder.java index b76ad761..39f0ca03 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CustomsOrder.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CustomsOrder.java @@ -15,7 +15,9 @@ import com.foxinmy.weixin4j.type.CustomsCity; * @date 2016年3月27日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public class CustomsOrder extends MerchantResult { private static final long serialVersionUID = 799510373861612386L; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CustomsOrderRecord.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CustomsOrderRecord.java index 305e67ce..6c701831 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CustomsOrderRecord.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CustomsOrderRecord.java @@ -15,7 +15,9 @@ import com.foxinmy.weixin4j.xml.ListsuffixResult; * @date 2016年3月27日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public class CustomsOrderRecord extends MerchantResult { private static final long serialVersionUID = -1675090110657154049L; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CustomsOrderResult.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CustomsOrderResult.java index 43363715..f06d42a3 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CustomsOrderResult.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/CustomsOrderResult.java @@ -16,7 +16,9 @@ import com.foxinmy.weixin4j.util.DateUtil; * @date 2016年3月27日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public class CustomsOrderResult extends MerchantResult { private static final long serialVersionUID = 799510373861612386L; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/JSAPIPayRequest.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/JSAPIPayRequest.java index 258167ce..f9656824 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/JSAPIPayRequest.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/JSAPIPayRequest.java @@ -22,7 +22,9 @@ import com.foxinmy.weixin4j.type.TradeType; * @see com.foxinmy.weixin4j.payment.PayRequest * @see 网页端调起支付API + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public class JSAPIPayRequest extends AbstractPayRequest { public JSAPIPayRequest(String prePayId, WeixinPayAccount payAccount) { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MICROPayRequest.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MICROPayRequest.java index 72ad9661..96959272 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MICROPayRequest.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MICROPayRequest.java @@ -18,7 +18,9 @@ import com.foxinmy.weixin4j.type.TradeType; * @see com.foxinmy.weixin4j.payment.PayRequest * @see 刷卡支付 + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public class MICROPayRequest extends Order implements MchPayRequest { private static final long serialVersionUID = 6147576305404111278L; 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 f454c14e..2de072ee 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 @@ -20,7 +20,9 @@ import com.foxinmy.weixin4j.type.TradeType; * @date 2014年10月21日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class MchPayPackage extends PayPackage { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MchPayRequest.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MchPayRequest.java index 1feda2b4..63bdcbee 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MchPayRequest.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MchPayRequest.java @@ -16,7 +16,9 @@ import com.foxinmy.weixin4j.type.TradeType; * @see MICROPayRequest 刷卡支付 * @see APPPayRequest APP支付 * @see WAPPayRequest WAP支付 + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public interface MchPayRequest { /** * 预支付交易ID diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MerchantResult.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MerchantResult.java index 6561dd2f..3b985779 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MerchantResult.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MerchantResult.java @@ -17,7 +17,9 @@ import com.foxinmy.weixin4j.type.SignType; * @date 2014年10月21日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class MerchantResult extends XmlResult { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MerchantTradeResult.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MerchantTradeResult.java index c52274d3..ef18ae64 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MerchantTradeResult.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MerchantTradeResult.java @@ -13,7 +13,9 @@ import com.foxinmy.weixin4j.type.CurrencyType; * @date 2016年7月21日 * @since JDK 1.7 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public class MerchantTradeResult extends MerchantResult { private static final long serialVersionUID = 4205906286092873877L; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/NATIVEPayRequest.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/NATIVEPayRequest.java index 3eb7809c..0b156419 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/NATIVEPayRequest.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/NATIVEPayRequest.java @@ -15,7 +15,9 @@ import com.foxinmy.weixin4j.type.TradeType; * @see com.foxinmy.weixin4j.payment.PayRequest * @see NATIVE扫码支付(模式二) + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public class NATIVEPayRequest extends AbstractPayRequest { private final String codeUrl; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/NativePayNotify.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/NativePayNotify.java index 323e6f11..63e1dd0d 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/NativePayNotify.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/NativePayNotify.java @@ -15,7 +15,9 @@ import com.alibaba.fastjson.annotation.JSONField; * @date 2014年10月30日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class NativePayNotify extends OpenIdResult { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/NativePayResponse.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/NativePayResponse.java index 0cd0267b..82591c51 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/NativePayResponse.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/NativePayResponse.java @@ -19,7 +19,9 @@ import com.foxinmy.weixin4j.util.RandomUtil; * @date 2014年10月28日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class NativePayResponse extends MerchantResult { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/OpenIdResult.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/OpenIdResult.java index 2d494554..2a1ae821 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/OpenIdResult.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/OpenIdResult.java @@ -15,7 +15,9 @@ import com.alibaba.fastjson.annotation.JSONField; * @date 2015年7月23日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class OpenIdResult extends MerchantResult { 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 f6662181..82c70c1c 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 @@ -25,7 +25,9 @@ import com.foxinmy.weixin4j.xml.ListsuffixResult; * @date 2014年11月2日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Order extends MerchantTradeResult { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/PrePay.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/PrePay.java index 7c7306c1..d0c44637 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/PrePay.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/PrePay.java @@ -16,7 +16,9 @@ import com.foxinmy.weixin4j.type.TradeType; * @date 2014年10月21日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class PrePay extends MerchantResult { 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 0000003f..06ce10dd 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 @@ -20,7 +20,9 @@ import com.foxinmy.weixin4j.util.DateUtil; * href="https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_1">普通红包 * @see 裂变红包 + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Redpacket extends MerchantResult { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RedpacketRecord.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RedpacketRecord.java index 760d57fe..6082e0e7 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RedpacketRecord.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RedpacketRecord.java @@ -25,7 +25,9 @@ import com.foxinmy.weixin4j.util.DateUtil; * @date 2015年6月4日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class RedpacketRecord extends XmlResult { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RedpacketRisk.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RedpacketRisk.java index 809d4738..c2cda3a6 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RedpacketRisk.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RedpacketRisk.java @@ -17,7 +17,9 @@ import com.foxinmy.weixin4j.util.MapUtil; * @date 2017年1月4日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public class RedpacketRisk { private Map risk; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RedpacketSendResult.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RedpacketSendResult.java index bc64471a..1dd05939 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RedpacketSendResult.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RedpacketSendResult.java @@ -18,7 +18,9 @@ import com.foxinmy.weixin4j.util.DateUtil; * @date 2015年4月1日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class RedpacketSendResult extends MerchantResult { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RefundDetail.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RefundDetail.java index 2ac72095..aaec86a4 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RefundDetail.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RefundDetail.java @@ -24,7 +24,9 @@ import com.foxinmy.weixin4j.xml.ListsuffixResult; * @author jinyu(foxinmy@gmail.com) * @date 2016年7月21日 * @since JDK 1.6 + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class RefundDetail implements Serializable { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RefundRecord.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RefundRecord.java index 945b4e64..3ed978f0 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RefundRecord.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RefundRecord.java @@ -17,7 +17,9 @@ import com.foxinmy.weixin4j.xml.ListsuffixResult; * @author jinyu(foxinmy@gmail.com) * @date 2014年11月1日 * @since JDK 1.6 + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class RefundRecord extends MerchantTradeResult { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RefundResult.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RefundResult.java index 2b46cafa..9768a341 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RefundResult.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/RefundResult.java @@ -19,7 +19,9 @@ import com.foxinmy.weixin4j.xml.ListsuffixResult; * @date 2014年11月6日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class RefundResult extends MerchantTradeResult { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/SceneInfoApp.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/SceneInfoApp.java index 62912079..29a7992a 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/SceneInfoApp.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/SceneInfoApp.java @@ -4,6 +4,7 @@ import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class SceneInfoApp { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/SceneInfoStore.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/SceneInfoStore.java index 23674a6b..a4bd7698 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/SceneInfoStore.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/SceneInfoStore.java @@ -7,6 +7,7 @@ import javax.xml.bind.annotation.XmlRootElement; import com.alibaba.fastjson.annotation.JSONField; +@Deprecated @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class SceneInfoStore { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/SettlementRecord.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/SettlementRecord.java index ffb2d678..46811a65 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/SettlementRecord.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/SettlementRecord.java @@ -17,6 +17,7 @@ import com.foxinmy.weixin4j.util.DateUtil; * @since JDK 1.6 * @see */ +@Deprecated public class SettlementRecord extends MerchantResult { private static final long serialVersionUID = 7952659545609519979L; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/WAPPayRequest.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/WAPPayRequest.java index 17ce2bad..2895d30e 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/WAPPayRequest.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/WAPPayRequest.java @@ -16,6 +16,7 @@ import com.foxinmy.weixin4j.type.TradeType; * @see WAP支付 */ +@Deprecated public class WAPPayRequest extends AbstractPayRequest { /** * 微信支付URL diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/sign/AbstractWeixinSignature.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/sign/AbstractWeixinSignature.java index 946066cc..de91afe1 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/sign/AbstractWeixinSignature.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/sign/AbstractWeixinSignature.java @@ -10,7 +10,9 @@ import com.foxinmy.weixin4j.util.MapUtil; * @date 2016年3月26日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public abstract class AbstractWeixinSignature implements WeixinSignature { /** * 是否编码 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/sign/WeixinPaymentSignature.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/sign/WeixinPaymentSignature.java index 9d32ef29..1905ad58 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/sign/WeixinPaymentSignature.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/sign/WeixinPaymentSignature.java @@ -12,7 +12,9 @@ import com.foxinmy.weixin4j.util.DigestUtil; * @since JDK 1.6 * @see 支付签名说明 + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public class WeixinPaymentSignature extends AbstractWeixinSignature { /** * 支付密钥 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/sign/WeixinSignature.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/sign/WeixinSignature.java index 2b7574da..da133527 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/sign/WeixinSignature.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/sign/WeixinSignature.java @@ -10,7 +10,9 @@ import com.foxinmy.weixin4j.type.SignType; * @date 2016年3月26日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public interface WeixinSignature { /** * 是否编码 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/BankType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/BankType.java index f0db2a69..70cd9f72 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/BankType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/BankType.java @@ -9,7 +9,9 @@ package com.foxinmy.weixin4j.type; * @date 2015年8月19日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum BankType { /** * 工商银行(借记卡) diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CredentialType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CredentialType.java index 4340c827..1d46317d 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CredentialType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CredentialType.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type; * @date 2016年3月27日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum CredentialType { IDCARD("身份证"); CredentialType(String name) { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CurrencyType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CurrencyType.java index 26baf846..a846033b 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CurrencyType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CurrencyType.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type; * @date 2014年11月2日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum CurrencyType { CNY("人民币"), HKD("港元"), TWD("台币"), EUR("欧元"), USD("美元"), GBP("英镑"), JPY("日元"), CAD( "加拿大元"), AUD("澳大利亚元"), NZD("新西兰元"), KRW("韩元"), THB("泰铢"); diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CustomsCity.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CustomsCity.java index 874446d4..9ed49d60 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CustomsCity.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CustomsCity.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type; * @date 2016年3月27日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum CustomsCity { NO("无需上报海关"), GUANGZHOU("广州"), HANGZHOU("杭州"), NINGBO("宁波"), ZHENGZHOU_BS( "郑州(保税物流中心)"), CHONGQING("重庆"), XIAN("西安"), SHANGHAI("上海"), ZHENGZHOU_ZH( diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CustomsSatus.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CustomsSatus.java index 50437bda..a807c23d 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CustomsSatus.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/CustomsSatus.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type; * @date 2016年3月27日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum CustomsSatus { UNDECLARED("未申报"), SUBMITTED("申报已提交"), PROCESSING("申报中"), SUCCESS("申报成功"), FAIL( "申报失败"), EXCEPT("海关接口异常"); diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/IdQuery.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/IdQuery.java index 4757dce7..e1470413 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/IdQuery.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/IdQuery.java @@ -10,7 +10,9 @@ import java.io.Serializable; * @date 2014年11月1日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public class IdQuery implements Serializable { private static final long serialVersionUID = -5273675987521807370L; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/IdType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/IdType.java index 70c1f105..3a475d57 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/IdType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/IdType.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type; * @date 2014年11月1日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum IdType { /** * 微信退款单号 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/SignType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/SignType.java index 60cb1526..fff58546 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/SignType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/SignType.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type; * @date 2014年11月5日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum SignType { SHA1, MD5, HMAC$SHA256 } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/TarType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/TarType.java index 1e48af17..efffde26 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/TarType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/TarType.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type; * @date 2016年12月21日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum TarType { GZIP } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/TradeState.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/TradeState.java index 2d974e0f..2ec5b42c 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/TradeState.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/TradeState.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type; * @date 2014年11月2日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum TradeState { /** * 支付成功 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/TradeType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/TradeType.java index c660a2ec..b77fa3fb 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/TradeType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/TradeType.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type; * @date 2014年10月21日 * @since JDK 1.6 * @see + * @deprecated 迁移到weixin4j-pay子模块 */ +@Deprecated public enum TradeType { /** * JS支付 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/BillType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/BillType.java index d0951468..baace932 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/BillType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/BillType.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type.mch; * @date 2014年10月31日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum BillType { /** * 全部 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CorpPaymentCheckNameType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CorpPaymentCheckNameType.java index 593e5872..40631c48 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CorpPaymentCheckNameType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CorpPaymentCheckNameType.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type.mch; * @date 2015年4月1日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum CorpPaymentCheckNameType { /** * 不校验真实姓名 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponStatus.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponStatus.java index 18060971..38956878 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponStatus.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponStatus.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type.mch; * @date 2015年3月27日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum CouponStatus { /** * 已激活 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponStockStatus.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponStockStatus.java index 946966d8..765502c4 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponStockStatus.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponStockStatus.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type.mch; * @date 2015年3月27日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum CouponStockStatus { /** * 未激活 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponStockType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponStockType.java index 94d088b3..adf7be50 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponStockType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponStockType.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type.mch; * @date 2015年3月27日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum CouponStockType { /** * 批量型 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponType.java index 76d979f6..116c980c 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/CouponType.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type.mch; * @date 2015年3月27日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum CouponType { /** * 使用无门槛 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketSceneType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketSceneType.java index 0da68f68..a477bd7e 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketSceneType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketSceneType.java @@ -7,7 +7,9 @@ package com.foxinmy.weixin4j.type.mch; * @author jinyu(foxinmy@gmail.com) * @date 2017年1月4日 * @since JDK 1.6 + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum RedpacketSceneType { /** * 商品促销 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketSendType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketSendType.java index b446458d..265b15ca 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketSendType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketSendType.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type.mch; * @date 2015年6月4日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum RedpacketSendType { /** * 通过API接口发放 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketStatus.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketStatus.java index afa49e52..4fc6d723 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketStatus.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketStatus.java @@ -7,7 +7,9 @@ package com.foxinmy.weixin4j.type.mch; * @date 2015年6月4日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum RedpacketStatus { /** * 发放中 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketType.java index 70056054..be34cc78 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RedpacketType.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type.mch; * @date 2015年6月4日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum RedpacketType { /** * 裂变红包 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundAccountType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundAccountType.java index af10c2e1..d4088929 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundAccountType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundAccountType.java @@ -5,7 +5,9 @@ package com.foxinmy.weixin4j.type.mch; * @className RefundAccountType * @author jinyu(foxinmy@gmail.com) * @date 2016年12月12日 + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum RefundAccountType { /** * ---未结算资金退款(默认使用未结算资金退款) diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundChannel.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundChannel.java index 144e49ab..ae729875 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundChannel.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundChannel.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type.mch; * @date 2014年11月6日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum RefundChannel { /** * 原路退款 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundStatus.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundStatus.java index dc294571..7c645ed3 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundStatus.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundStatus.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type.mch; * @date 2014年11月2日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum RefundStatus { /** * 退款成功 diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundType.java index 1724db2c..1e62943d 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/mch/RefundType.java @@ -8,7 +8,9 @@ package com.foxinmy.weixin4j.type.mch; * @date 2014年12月31日 * @since JDK 1.6 * @see + * @deprecated 迁移到子模块weixin4j-pay */ +@Deprecated public enum RefundType { /** * 1:商户号余额退款; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/DigestUtil.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/DigestUtil.java index 0d30578b..defa1b13 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/DigestUtil.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/DigestUtil.java @@ -1,5 +1,8 @@ package com.foxinmy.weixin4j.util; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -57,4 +60,26 @@ public final class DigestUtil { byte[] data = StringUtil.getBytesUtf8(content); return HexUtil.encodeHexString(getDigest(Consts.MD5).digest(data)); } + + /** + * HMAC-SHA256签名 + * + * @param content + * 待签名字符串 + * @param key + * 支付密钥 + * @return + * @throws InvalidKeyException + */ + public static String HMACSHA256(String content, String key) throws InvalidKeyException{ + try { + Mac mac = Mac.getInstance("HmacSHA256"); + SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256"); + mac.init(secret_key); + byte[] bytes = mac.doFinal(content.getBytes()); + return HexUtil.encodeHexString(bytes); + } catch (NoSuchAlgorithmException e) { + } + return null; + } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/MapUtil.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/MapUtil.java index b25d6f02..acd13f81 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/MapUtil.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/MapUtil.java @@ -29,8 +29,6 @@ public class MapUtil { * 是否编码 * @param lowerCase * 是否转换小写 - * @param extra - * 附加对象 * @return */ public static String toJoinString(Object object, boolean encoder, diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Weixin4jConfigUtil.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Weixin4jConfigUtil.java index ea3d502e..302ee867 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Weixin4jConfigUtil.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/Weixin4jConfigUtil.java @@ -2,6 +2,7 @@ package com.foxinmy.weixin4j.util; import java.util.MissingResourceException; import java.util.ResourceBundle; +import java.util.logging.Level; import com.alibaba.fastjson.JSON; import com.foxinmy.weixin4j.model.WeixinAccount; @@ -112,4 +113,13 @@ public class Weixin4jConfigUtil { } return account; } + + public static Level getJdkLoggerLevel(){ + try { + Level level = Level.parse(getValue("jdkLogger.level", "OFF")); + return level; + }catch (IllegalArgumentException ex){ + return Level.OFF; + } + } } diff --git a/weixin4j-base/src/main/resources/com/foxinmy/weixin4j/payment/weixin.properties b/weixin4j-base/src/main/resources/com/foxinmy/weixin4j/payment/weixin.properties index 68ed23ca..635bb53b 100644 --- a/weixin4j-base/src/main/resources/com/foxinmy/weixin4j/payment/weixin.properties +++ b/weixin4j-base/src/main/resources/com/foxinmy/weixin4j/payment/weixin.properties @@ -1,59 +1,64 @@ -# \u5fae\u4fe1\u5546\u6237\u5e73\u53f0\u6587\u6863\u8bf4\u660e +# \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 +payapp_base_url=https://payapp.weixin.qq.com -# \u53d1\u9001\u73b0\u91d1\u7ea2\u5305 +# \u53D1\u9001\u73B0\u91D1\u7EA2\u5305 redpack_send_uri={mch_base_url}/mmpaymkttransfers/sendredpack -# \u53d1\u9001\u73b0\u91d1\u88c2\u53d8\u7ea2\u5305 +# \u53D1\u9001\u73B0\u91D1\u88C2\u53D8\u7EA2\u5305 groupredpack_send_uri={mch_base_url}/mmpaymkttransfers/sendgroupredpack -# \u67e5\u8be2\u73b0\u91d1\u7ea2\u5305 +# \u67E5\u8BE2\u73B0\u91D1\u7EA2\u5305 redpack_query_uri={mch_base_url}/mmpaymkttransfers/gethbinfo -# \u7edf\u4e00\u8ba2\u5355\u751f\u6210 +# \u7EDF\u4E00\u8BA2\u5355\u751F\u6210 order_create_uri={mch_base_url}/pay/unifiedorder -# \u88ab\u626b\u652f\u4ed8 +# \u88AB\u626B\u652F\u4ED8 micropay_uri={mch_base_url}/pay/micropay -# \u8ba2\u5355\u67e5\u8be2 +# \u8BA2\u5355\u67E5\u8BE2 order_query_uri={mch_base_url}/pay/orderquery -# \u5173\u95ed\u8ba2\u5355 +# \u5173\u95ED\u8BA2\u5355 order_close_uri={mch_base_url}/pay/closeorder -# \u5bf9\u8d26\u5355\u4e0b\u8f7d +# \u5BF9\u8D26\u5355\u4E0B\u8F7D downloadbill_uri={mch_base_url}/pay/downloadbill -# \u9000\u6b3e\u67e5\u8be2 +# \u9000\u6B3E\u67E5\u8BE2 refund_query_uri={mch_base_url}/pay/refundquery -# \u9000\u6b3e\u7533\u8bf7 +# \u9000\u6B3E\u7533\u8BF7 refund_apply_uri={mch_base_url}/secapi/pay/refund -# \u51b2\u6b63\u64a4\u9500 +# \u51B2\u6B63\u64A4\u9500 order_reverse_uri={mch_base_url}/secapi/pay/reverse -# \u957f\u94fe\u63a5\u8f6c\u6362 +# \u957F\u94FE\u63A5\u8F6C\u6362 longurl_convert_uri={mch_base_url}/tools/shorturl -# \u53d1\u653e\u4ee3\u91d1\u5238 +# \u53D1\u653E\u4EE3\u91D1\u5238 coupon_send_uri={mch_base_url}/mmpaymkttransfers/send_coupon -# \u67e5\u8be2\u4ee3\u91d1\u5238\u6279\u6b21\u4fe1\u606f +# \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 +# \u67E5\u8BE2\u4EE3\u91D1\u5238\u8BE6\u7EC6\u4FE1\u606F coupondetail_query_uri={mch_base_url}/mmpaymkttransfers/querycouponsinfo -# \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 +# \u4F01\u4E1A\u5411\u4E2A\u4EBA\u4ED8\u6B3E corppayment_send_uri={mch_base_url}/mmpaymkttransfers/promotion/transfers -# \u4f01\u4e1a\u4ed8\u6b3e\u67e5\u8be2 +# \u4F01\u4E1A\u4ED8\u6B3E\u67E5\u8BE2 corppayment_query_uri={mch_base_url}/mmpaymkttransfers/gettransferinfo -# \u63a5\u53e3\u4e0a\u62a5 +# \u63A5\u53E3\u4E0A\u62A5 interface_report_uri={mch_base_url}/payitil/report -# \u6388\u6743\u7801\u67e5\u8be2OPENID\u63a5\u53e3 +# \u6388\u6743\u7801\u67E5\u8BE2OPENID\u63A5\u53E3 authcode_openid_uri={mch_base_url}/tools/authcodetoopenid -# native\u652f\u4ed8url(\u6a21\u5f0f1) +# 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 -# \u67e5\u8be2\u7ed3\u7b97\u8d44\u91d1 +# \u67E5\u8BE2\u7ED3\u7B97\u8D44\u91D1 settlement_query_uri={mch_base_url}/pay/settlementquery -# \u67e5\u8be2\u6c47\u7387 +# \u67E5\u8BE2\u6C47\u7387 exchagerate_query_uri={mch_base_url}/pay/queryexchagerate -# \u8ba2\u5355\u9644\u52a0\u4fe1\u606f\u63d0\u4ea4 +# \u8BA2\u5355\u9644\u52A0\u4FE1\u606F\u63D0\u4EA4 customsorder_declare_uri={mch_base_url}/mch/customs/customdeclareorder -# \u8ba2\u5355\u9644\u52a0\u4fe1\u606f\u67e5\u8be2 -customsorder_query_uri={mch_base_url}/mch/customs/customdeclarequery \ No newline at end of file +# \u8BA2\u5355\u9644\u52A0\u4FE1\u606F\u67E5\u8BE2 +customsorder_query_uri={mch_base_url}/mch/customs/customdeclarequery +# \u5237\u8138\u652F\u4ED8\u4EA4\u4E92\u6D41\u7A0B--\u83B7\u53D6\u8C03\u7528\u51ED\u8BC1 +get_wxpayface_authinfo_uri={payapp_base_url}/face/get_wxpayface_authinfo +# \u65E7\u7248\u5237\u8138\u652F\u4ED8\u63A5\u53E3 +facepay_url={mch_base_url}/pay/facepay +# \u652F\u4ED8\u62BC\u91D1\uFF08\u4EBA\u8138\uFF09 +deposit_facepay_uri={mch_base_url}/deposit/facepay +# \u652F\u4ED8\u62BC\u91D1\uFF08\u4ED8\u6B3E\u7801\uFF09 +deposit_micropay_uri={mch_base_url}/deposit/micropay \ No newline at end of file diff --git a/weixin4j-pay/pom.xml b/weixin4j-pay/pom.xml new file mode 100644 index 00000000..aa887ef8 --- /dev/null +++ b/weixin4j-pay/pom.xml @@ -0,0 +1,47 @@ + + + + weixin4j + com.foxinmy + 1.9.0-SNAPSHOT + + 4.0.0 + weixin4j-pay + weixin4j-pay + 1.0.0-SNAPSHOT + https://github.com/foxinmy/weixin4j/tree/master/weixin4j-pay + 微信支付商户平台API + + + kit-lee + Kit lee + ryuji.cn@gmail.com + https://github.com/kit-lee + + kit_21cn@21cn.com + https://github.com/kit-lee/weixin4j + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.foxinmy + weixin4j-base + 1.9.0-SNAPSHOT + + + junit + junit + + + \ No newline at end of file diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/README.md b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/README.md new file mode 100644 index 00000000..1792dfa0 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/README.md @@ -0,0 +1,47 @@ +支付模块【JSAPI】【NATIVE】【MICROPAY】 + +微信公众平台[V2版本支付](https://mp.weixin.qq.com/paymch/readtemplate?t=mp/business/course2_tmpl&lang=zh_CN)文档 + +微信公众平台[V3版本支付](https://mp.weixin.qq.com/paymch/readtemplate?t=mp/business/course3_tmpl&lang=zh_CN)文档 + +**在`2014年10月9号`之前申请并审核通过的支付接口应该属于`V2版本`支付,而之后申请的接口则为`V3版本(商户平台)`支付** + + +[WeixinPayProxy](WeixinPayProxy.java) +------------------------- + +* createPayJsRequestJson: 创建V3版本(商户平台)的JSAPI支付串 + +* createNativePayRequestURL: 创建V3版本(商户平台)的扫码支付链接 + +* createPrePay: 调用V3版本(商户平台)的统一订单接口生成预订单数据 + +* createMicroPay: 创建刷卡支付(商户平台)请求 + +* orderQuery: 订单查询接口 + +* refundOrder: 退款申请接口 + +* reverseOrder: 冲正订单接口 + +* closeOrder: 关闭订单接口 + +* downloadBill: 下载对账单接口 + +* refundQuery: 退款查询接口 + + +[Pay2Api](https://github.com/foxinmy/weixin4j/blob/master/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/Pay2Api.java) +------------------------- + +* createPayJsRequestJson: 创建V2版本的JSAPI支付串 + +* createNativePayRequestURL: 创建V2版本的扫码支付链接 + +* orderQuery: 订单查询接口 + +* refundOrder: 退款申请接口 + +* downloadBill: 下载对账单接口 + +* refundQuery: 退款查询接口 diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/WeixinPayProxy.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/WeixinPayProxy.java new file mode 100644 index 00000000..563d62d4 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/WeixinPayProxy.java @@ -0,0 +1,890 @@ +package com.foxinmy.weixin4j.pay; + +import com.alibaba.fastjson.JSON; +import com.foxinmy.weixin4j.pay.api.*; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.weixin.XmlResult; +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.model.paging.Pageable; +import com.foxinmy.weixin4j.pay.payment.coupon.*; +import com.foxinmy.weixin4j.pay.payment.face.PayfaceAuthinfo; +import com.foxinmy.weixin4j.pay.payment.face.PayfaceAuthinfoRequest; +import com.foxinmy.weixin4j.pay.payment.mch.*; +import com.foxinmy.weixin4j.pay.sign.WeixinSignature; +import com.foxinmy.weixin4j.pay.type.*; +import com.foxinmy.weixin4j.pay.type.mch.BillType; +import com.foxinmy.weixin4j.pay.type.mch.RefundAccountType; +import com.foxinmy.weixin4j.util.Consts; +import com.foxinmy.weixin4j.util.Weixin4jConfigUtil; + +import java.io.OutputStream; +import java.util.Date; +import java.util.List; +import java.util.concurrent.Future; + +/** + * 微信支付接口实现 + * + * @className WeixinPayProxy + * @author jinyu(foxinmy@gmail.com) + * @date 2015年1月3日 + * @since JDK 1.6 + * @see 商户平台支付API + */ +public class WeixinPayProxy { + + /** + * 微信支付API:js支付、扫码支付等接口 + */ + private final PayApi payApi; + /** + * 代金券API + */ + private final CouponApi couponApi; + /** + * 现金API + */ + private final CashApi cashApi; + /** + * 海关API + */ + private final CustomsApi customsApi; + /** + * 商户信息 + */ + private final WeixinPayAccount weixinPayAccount; + + /** + * 微信支付接口实现(使用weixin4j.properties配置的account商户信息) + */ + public WeixinPayProxy() { + this(JSON.parseObject(Weixin4jConfigUtil.getValue("account"), + WeixinPayAccount.class)); + } + + /** + * 微信支付接口实现 + * + * @param weixinPayAccount + * 微信商户信息 + */ + public WeixinPayProxy(WeixinPayAccount weixinPayAccount) { + if (weixinPayAccount == null) { + throw new IllegalArgumentException( + "weixinPayAccount must not be empty"); + } + this.weixinPayAccount = weixinPayAccount; + this.payApi = new PayApi(weixinPayAccount); + this.couponApi = new CouponApi(weixinPayAccount); + this.cashApi = new CashApi(weixinPayAccount); + this.customsApi = new CustomsApi(weixinPayAccount); + } + + /** + * 获取微信商户账号信息 + * + * @return + */ + public WeixinPayAccount getWeixinPayAccount() { + return weixinPayAccount; + } + + /** + * 获取微信签名类 + * + * @return + */ + public WeixinSignature getWeixinSignature() { + return payApi.getWeixinSignature(); + } + + /** + * 统一下单接口
+ * 除被扫支付场景以外,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再按扫码、JSAPI + * 、APP等不同场景生成交易串调起支付。 + * + * @param payPackage + * 包含订单信息的对象 + * @see PayApi + * @see MchPayPackage + * @see PrePay + * @see 统一下单接口 + * + * @return 预支付对象 + */ + public PrePay createPrePay(MchPayPackage payPackage) throws WeixinException { + return payApi.createPrePay(payPackage); + } + + /** + * 创建支付请求对象 + * + * @param payPackage + * 支付详情 + * @return 支付请求对象 + * @see PayApi + * @see JSAPIPayRequest JS支付 + * @see NATIVEPayRequest 扫码支付 + * @see MICROPayRequest 刷卡支付 + * @see APPPayRequest APP支付 + * @see WAPPayRequest WAP支付 + * @see MchPayRequest#toRequestString() + * @throws WeixinException + */ + public MchPayRequest createPayRequest(MchPayPackage payPackage) + throws WeixinException { + return payApi.createPayRequest(payPackage); + } + + /** + * 创建JSAPI支付请求对象 + * + * @param openId + * 用户ID + * @param body + * 订单描述 + * @param outTradeNo + * 订单号 + * @param totalFee + * 订单总额(元) + * @param notifyUrl + * 支付通知地址 + * @param createIp + * ip地址 + * @param attach + * 附加数据 非必填 + * @see PayApi + * @see JSAPIPayRequest + * @see MchPayRequest#toRequestString() + * @return JSAPI支付对象 + * @throws WeixinException + */ + public MchPayRequest createJSPayRequest(String openId, String body, + String outTradeNo, double totalFee, String notifyUrl, + String createIp, String attach) throws WeixinException { + return payApi.createJSPayRequest(openId, body, outTradeNo, totalFee, + notifyUrl, createIp, attach); + } + + /** + * 创建Native支付(扫码支付)链接【模式一】 + * + * @param productId + * 与订单ID等价 + * @return 支付链接 + * @see PayApi + * @see 扫码支付 + * + * @see 模式一 + * + */ + public String createNativePayRequest(String productId) { + return payApi.createNativePayRequest(productId); + } + + /** + * 创建Native支付(扫码支付)回调对象【模式一】 + * + * @param productId + * 商品ID + * @param body + * 商品描述 + * @param outTradeNo + * 商户内部唯一订单号 + * @param totalFee + * 商品总额 单位元 + * @param notifyUrl + * 支付回调URL + * @param createIp + * 订单生成的机器 IP + * @param attach + * 附加数据 非必填 + * @return Native回调对象 + * @see PayApi + * @see NativePayResponse + * @see 扫码支付 + * + * @see 模式一 + * + * @throws WeixinException + */ + public NativePayResponse createNativePayResponse(String productId, + String body, String outTradeNo, double totalFee, String notifyUrl, + String createIp, String attach) throws WeixinException { + return payApi.createNativePayResponse(productId, body, outTradeNo, + totalFee, notifyUrl, createIp, attach); + } + + /** + * 创建Native支付(扫码支付)链接【模式二】 + * + * @param productId + * 商品ID + * @param body + * 商品描述 + * @param outTradeNo + * 商户内部唯一订单号 + * @param totalFee + * 商品总额 单位元 + * @param notifyUrl + * 支付回调URL + * @param createIp + * 订单生成的机器 IP + * @param attach + * 附加数据 非必填 + * @return Native支付对象 + * @see PayApi + * @see NATIVEPayRequest + * @see MchPayRequest#toRequestString() + * @see 扫码支付 + * + * @see 模式二 + * + * @throws WeixinException + */ + public MchPayRequest createNativePayRequest(String productId, String body, + String outTradeNo, double totalFee, String notifyUrl, + String createIp, String attach) throws WeixinException { + return payApi.createNativePayRequest(productId, body, outTradeNo, + totalFee, notifyUrl, createIp, attach); + } + + /** + * 创建APP支付请求对象 + * + * @param body + * 商品描述 + * @param outTradeNo + * 商户内部唯一订单号 + * @param totalFee + * 商品总额 单位元 + * @param notifyUrl + * 支付回调URL + * @param createIp + * 订单生成的机器 IP + * @param attach + * 附加数据 非必填 + * @param store + * 门店信息 非必填 + * @return APP支付对象 + * @see PayApi + * @see SceneInfoStore + * @see APPPayRequest + * @see MchPayRequest#toRequestString() + * @see + * APP支付 + * @throws WeixinException + */ + public MchPayRequest createAppPayRequest(String body, String outTradeNo, + double totalFee, String notifyUrl, String createIp, String attach, + SceneInfoStore store) throws WeixinException { + return payApi.createAppPayRequest(body, outTradeNo, totalFee, + notifyUrl, createIp, attach, store); + } + + /** + * 创建WAP支付请求对象 + * + * @param body + * 商品描述 + * @param outTradeNo + * 商户内部唯一订单号 + * @param totalFee + * 商品总额 单位元 + * @param notifyUrl + * 支付回调URL + * @param createIp + * 订单生成的机器 IP + * @param attach + * 附加数据 非必填 + * @param app + * 应用信息 + * @return WAP支付对象 + * @see PayApi + * @see SceneInfoApp + * @see WAPPayRequest + * @see MchPayRequest#toRequestString() + * @see WAP支付 + * + * @throws WeixinException + */ + public MchPayRequest createWapPayRequest(String body, String outTradeNo, + double totalFee, String notifyUrl, String createIp, String attach, + SceneInfoApp app) throws WeixinException { + return payApi.createWapPayRequest(body, outTradeNo, totalFee, + notifyUrl, createIp, attach, app); + } + + /** + * 提交被扫支付 + * + * @param authCode + * 扫码支付授权码 ,设备读取用户微信中的条码或者二维码信息 + * @param body + * 商品描述 + * @param outTradeNo + * 商户内部唯一订单号 + * @param totalFee + * 商品总额 单位元 + * @param createIp + * 订单生成的机器 IP + * @param attach + * 附加数据 非必填 + * @param store + * 门店信息 非必填 + * @return 支付的订单信息 + * @see PayApi + * @see Order + * @see SceneInfoStore + * @see MICROPayRequest + * @see MchPayRequest#toRequestString() + * @see + * 提交被扫支付API + * @throws WeixinException + */ + public MchPayRequest createMicroPayRequest(String authCode, String body, + String outTradeNo, double totalFee, String createIp, String attach, + SceneInfoStore store) throws WeixinException { + return payApi.createMicroPayRequest(authCode, body, outTradeNo, + totalFee, createIp, attach, store); + } + + /** + * 旧版刷脸支付接口 + * + * @param faceCode + * 人脸凭证 + * @param body + * 商品或支付单简要描述,格式要求:门店品牌名-城市分店名-实际商品名称 + * @param outTradeNo + * 商户系统内部的订单号,32个字符内、可包含字母;更换授权码必须要换新的商户订单号 + * @param totalFee + * 订单总金额,单位元 + * @param createIp + * 调用微信支付API的机器IP + * @param openId + * 用户在商户appid 下的唯一标识 + * @param attach + * 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据 + * @return + * @throws WeixinException + * @see + * 刷脸支付后端接口 + * @see + */ + public MchPayRequest createFacePayRequest(String faceCode, String body, + String outTradeNo, double totalFee, String createIp, String openId, + String attach) throws WeixinException { + return payApi.createFacePayRequest(faceCode, body, outTradeNo, + totalFee, createIp, openId, attach); + } + + /** + * 押金支付请求 + * + * @param code + * 授权码/人脸凭证 + * @param body + * 商品或支付单简要描述,格式要求:门店品牌名-城市分店名-实际商品名称 + * @param outTradeNo + * 商户系统内部的订单号,32个字符内、可包含字母;更换授权码必须要换新的商户订单号 + * @param totalFee + * 订单总金额,单位元 + * @param createIp + * 调用微信支付API的机器IP + * @param openId + * 用户在商户appid 下的唯一标识,人脸支付押金时提供 + * @param attach + * 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据,非必填 + * @param store + * 门店信息,仅在付款码支付押金时提供,非必填 + * @param isFacePay + * 是否人脸押金支付,否则是付款码押金支付 + * @return + * @throws WeixinException + */ + public MchPayRequest createDepositPayRequest(String code, String body, + String outTradeNo, double totalFee, String createIp, String openId, + String attach, SceneInfoStore store, boolean isFacePay) throws WeixinException{ + + return payApi.createDepositPayRequest(code, body, outTradeNo, totalFee, createIp, openId, attach, store, isFacePay); + } + + /** + * 订单查询 + *

+ * 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;
调用支付接口后,返回系统错误或未知交易状态情况;
+ * 调用被扫支付API,返回USERPAYING的状态;
调用关单或撤销接口API之前,需确认支付状态; + *

+ * + * @param idQuery + * 商户系统内部的订单号, transaction_id、out_trade_no 二 选一,如果同时存在优先级: + * transaction_id> out_trade_no + * @since V3 + * @see Order + * @see PayApi + * @see
+ * 订单查询API + * @return 订单详情 + * @throws WeixinException + */ + public Order queryOrder(IdQuery idQuery) throws WeixinException { + return payApi.queryOrder(idQuery); + } + + /** + * 申请退款 + * + * @see PayApi#applyRefund(IdQuery, String, double, double, CurrencyType, String, String, RefundAccountType) + */ + public RefundResult applyRefund(IdQuery idQuery, String outRefundNo, + double totalFee, double refundFee, CurrencyType refundFeeType, + String opUserId, String refundDesc, + RefundAccountType refundAccountType) throws WeixinException { + return payApi.applyRefund(idQuery, outRefundNo, totalFee, refundFee, + refundFeeType, opUserId, refundDesc, refundAccountType); + } + + /** + * 申请退款 + * + * @see PayApi#applyRefund(IdQuery, String, double) + */ + public RefundResult applyRefund(IdQuery idQuery, String outRefundNo, + double totalFee) throws WeixinException { + return payApi.applyRefund(idQuery, outRefundNo, totalFee); + } + + /** + * 退款查询 + *

+ * 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。 + *

+ * + * @param idQuery + * 单号 refund_id、out_refund_no、 out_trade_no 、 transaction_id + * 四个参数必填一个,优先级为: + * refund_id>out_refund_no>transaction_id>out_trade_no + * @return 退款记录 + * @see PayApi + * @see RefundRecord + * @see + * 退款查询API + * @since V3 + * @throws WeixinException + */ + public RefundRecord queryRefund(IdQuery idQuery) throws WeixinException { + return payApi.queryRefund(idQuery); + } + + /** + * 下载对账单
+ * 1.微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账 单中,跟原支付单订单号一致,bill_type 为 + * REVOKED;
+ * 2.微信在次日 9 点启动生成前一天的对账单,建议商户 9 点半后再获取;
+ * 3.对账单中涉及金额的字段单位为“元”。
+ * + * @param billDate + * 下载对账单的日期 + * @param billType + * 下载对账单的类型 ALL,返回当日所有订单信息, 默认值 SUCCESS,返回当日成功支付的订单 + * REFUND,返回当日退款订单 + * @para outputStream 输出流 + * @param tarType + * 非必传参数,固定值:GZIP,返回格式为.gzip的压缩包账单。不传则默认为数据流形式。 + * @since V2 & V3 + * @see PayApi + * @see + * 下载对账单API + * @throws WeixinException + */ + public void downloadBill(Date billDate, BillType billType, + OutputStream outputStream, TarType tarType) throws WeixinException { + payApi.downloadBill(billDate, billType, outputStream, tarType); + } + + /** + * 冲正订单(需要证书)
当支付返回失败,或收银系统超时需要取消交易,可以调用该接口
接口逻辑:支 + * 付失败的关单,支付成功的撤销支付
7天以内的单可撤销,其他正常支付的单 + * 如需实现相同功能请调用退款接口
调用扣款接口后请勿立即调用撤销,需要等待5秒以上。先调用查单接口,如果没有确切的返回,再调用撤销
+ * + * @param idQuery + * 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级: + * transaction_id> out_trade_no + * @return 撤销结果 + * @see PayApi + * @since V3 + * @throws WeixinException + */ + public MerchantResult reverseOrder(IdQuery idQuery) throws WeixinException { + return payApi.reverseOrder(idQuery); + } + + /** + * 关闭订单 + *

+ * 商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;系统下单后,用户支付超时,系统退出不再受理,避免用户继续 + * ,请调用关单接口,如果关单失败,返回已完 成支付请按正常支付处理。如果出现银行掉单,调用关单成功后,微信后台会主动发起退款。 + *

+ * + * @param outTradeNo + * 商户系统内部的订单号 + * @return 执行结果 + * @see PayApi + * @since V3 + * @throws WeixinException + * @see + * 关闭订单API + */ + public MerchantResult closeOrder(String outTradeNo) throws WeixinException { + return payApi.closeOrder(outTradeNo); + } + + /** + * native支付URL转短链接:用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),减小二维码数据量 + * ,提升扫描速度和精确度。 + * + * @param url + * 具有native标识的支付URL + * @return 转换后的短链接 + * @see PayApi + * @see + * 转换短链接API + * @since V3 + * @throws WeixinException + */ + public String getPayShorturl(String url) throws WeixinException { + return payApi.getShorturl(url); + } + + /** + * 接口上报 + * + * @param interfaceUrl + * 上报对应的接口的完整 URL, 类似: https://api.mch.weixin.q + * q.com/pay/unifiedorder + * @param executeTime + * 接口耗时情况,单位为毫秒 + * @param outTradeNo + * 商户系统内部的订单号,商 户可以在上报时提供相关商户订单号方便微信支付更好 的提高服务质量。 + * @param ip + * 发起接口调用时的机器 IP + * @param time + * 商户调用该接口时商户自己 系统的时间 + * @param returnXml + * 调用接口返回的基本数据 + * @return 处理结果 + * @see PayApi + * @see + * 接口测试上报API + * @throws WeixinException + */ + public XmlResult reportInterface(String interfaceUrl, int executeTime, + String outTradeNo, String ip, Date time, XmlResult returnXml) + throws WeixinException { + return payApi.reportInterface(interfaceUrl, executeTime, outTradeNo, + ip, time, returnXml); + } + + /** + * 发放代金券(需要证书) + * + * @param couponStockId + * 代金券批次id + * @param partnerTradeNo + * 商户发放凭据号(格式:商户id+日期+流水号),商户侧需保持唯一性 + * @param openId + * 用户的openid + * @param opUserId + * 操作员帐号, 默认为商户号 可在商户平台配置操作员对应的api权限 可为空 + * @return 发放结果 + * @see CouponApi + * @see CouponResult + * @see + * 发放代金券接口 + * @throws WeixinException + */ + public CouponResult sendCoupon(String couponStockId, String partnerTradeNo, + String openId, String opUserId) throws WeixinException { + return couponApi.sendCoupon(couponStockId, partnerTradeNo, openId, + opUserId); + } + + /** + * 查询代金券批次 + * + * @param couponStockId + * 代金券批次ID + * @return 代金券批次信息 + * @see CouponApi + * @see CouponStock + * @see + * 查询代金券批次信息接口 + * @throws WeixinException + */ + public CouponStock queryCouponStock(String couponStockId) + throws WeixinException { + return couponApi.queryCouponStock(couponStockId); + } + + /** + * 查询代金券详细 + * + * @param openId + * 用户ID + * @param couponId + * 代金券ID + * @param stockId + * 代金劵对应的批次号 + * @return 代金券详细信息 + * @see CouponApi + * @see CouponDetail + * @see + * 查询代金券详细信息接口 + * @throws WeixinException + */ + public CouponDetail queryCouponDetail(String openId, String couponId, + String stockId) throws WeixinException { + return couponApi.queryCouponDetail(openId, couponId, stockId); + } + + /** + * 发放红包 企业向微信用户个人发现金红包 + * + * @param redpacket + * 红包信息 + * @return 发放结果 + * @see CashApi + * @see Redpacket + * @see RedpacketSendResult + * @see + * 发放现金红包接口 + * @see + * 发放裂变红包接口 + * @throws WeixinException + */ + public RedpacketSendResult sendRedpack(Redpacket redpacket) + throws WeixinException { + return cashApi.sendRedpack(redpacket); + } + + /** + * 批量发放红包 企业向微信用户个人发现金红包 + * + * @param redpackets + * 多个红包信息 + * @return 发放结果 + * @see CashApi + * @see #sendRedpacks(Redpacket...) + * @throws WeixinException + */ + public List> sendRedpacks( + Redpacket... redpackets) { + return cashApi.sendRedpacks(redpackets); + } + + /** + * 查询红包记录 + * + * @param outTradeNo + * 商户发放红包的商户订单号 + * @return 红包记录 + * @see CashApi + * @see RedpacketRecord + * @see + * 查询现金红包接口 + * @see + * 查询裂变红包接口 + * @throws WeixinException + */ + public RedpacketRecord queryRedpack(String outTradeNo) + throws WeixinException { + return cashApi.queryRedpack(outTradeNo); + } + + /** + * 企业付款 + * + * @see CashApi#sendCorpPayment(CorpPayment) + */ + public CorpPaymentResult sendCorpPayment(CorpPayment payment) + throws WeixinException { + return cashApi.sendCorpPayment(payment); + } + + /** + * 企业付款查询 用于商户的企业付款操作进行结果查询,返回付款操作详细结果 + * + * @param outTradeNo + * 商户调用企业付款API时使用的商户订单号 + * @return 付款记录 + * @see CashApi + * @see CorpPaymentRecord + * @see + * 企业付款查询接口 + * @throws WeixinException + */ + public CorpPaymentRecord queryCorpPayment(String outTradeNo) + throws WeixinException { + return cashApi.queryCorpPayment(outTradeNo); + } + + /** + * 授权码查询OPENID + * + * @param authCode + * 扫码支付授权码,设备读取用户微信中的条码或者二维码信息 + * @return 查询结果 + * @see CashApi + * @see OpenIdResult + * @see + * 授权码查询OPENID + * @throws WeixinException + */ + public OpenIdResult authCode2openId(String authCode) throws WeixinException { + return payApi.authCode2openId(authCode); + } + + /** + * 查询结算资金 + * + * @param status + * 是否结算 + * @param pageable + * 分页数据 + * @param start + * 开始日期 查询未结算记录时,该字段可不传 + * @param end + * 结束日期 查询未结算记录时,该字段可不传 + * @return 结算金额记录 + * @throws WeixinException + * @see CashApi + * @see SettlementRecord + * @see + * 查询结算资金接口 + */ + public SettlementRecord querySettlement(boolean status, Pageable pageable, + Date start, Date end) throws WeixinException { + return cashApi.querySettlement(status, pageable, start, end); + } + + /** + * 查询汇率 + * + * @param currencyType + * 外币币种 + * @param date + * 日期 不填则默认当天 + * @return 汇率对象 + * @throws WeixinException + * @see CashApi + * @see + * 查询汇率接口 + */ + public double queryExchageRate(CurrencyType currencyType, Date date) + throws WeixinException { + return cashApi.queryExchageRate(currencyType, date); + } + + /** + * 订单附加信息提交 + * + * @param customsOrder + * 附加订单信息 + * @return 报关结果 + * @see CustomsApi + * @see CustomsOrder + * @see CustomsOrderResult + * @see + * 附加订单信息提交接口 + * @throws WeixinException + */ + public CustomsOrderResult declareCustomsOrder(CustomsOrder customsOrder) + throws WeixinException { + return customsApi.declareCustomsOrder(customsOrder); + } + + /** + * 订单附加信息查询 + * + * @param idQuery + * out_trade_no,transaction_id,sub_order_no,sub_order_id四选一 + * @param customsCity + * 海关 + * @return 报关记录 + * @see CustomsOrderRecord + * @see CustomsApi + * @see + * 附加订单信息查询接口 + * @throws WeixinException + */ + public CustomsOrderRecord queryCustomsOrder(IdQuery idQuery, + CustomsCity customsCity) throws WeixinException { + return customsApi.queryCustomsOrder(idQuery, customsCity); + } + + /** + * 微信刷脸支付,获取调用凭证 + * + * @param storeId + * 门店编号, 由商户定义, 各门店唯一。 + * @param storeName + * 门店名称,由商户定义。(可用于展示) + * @param deviceId + * 终端设备编号,由商户定义。 + * @param attach + * 附加字段。字段格式使用Json, 非必填 + * @param rawdata + * 初始化数据。由微信人脸SDK的接口返回。 + * @return SDK调用凭证 + * @throws WeixinException + * @see + * 获取数据-getwxpayfacerawdata + * @see + * 获取调用凭证-get-wxpayface-authinfo + * @see PayfaceAuthinfo + */ + public PayfaceAuthinfo getWxPayfaceAuthinfo(String storeId, String storeName, String deviceId, + String attach, String rawdata) throws WeixinException { + PayfaceAuthinfoRequest request = new PayfaceAuthinfoRequest(this.weixinPayAccount, storeId, storeName, deviceId, + attach, rawdata); + return payApi.getWxPayfaceAuthinfo(request); + } + + public final static String VERSION = Consts.VERSION; +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/api/CashApi.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/api/CashApi.java new file mode 100644 index 00000000..c02b7b0e --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/api/CashApi.java @@ -0,0 +1,269 @@ +package com.foxinmy.weixin4j.pay.api; + +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.WeixinResponse; +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.model.paging.Pageable; +import com.foxinmy.weixin4j.pay.payment.mch.*; +import com.foxinmy.weixin4j.pay.type.CurrencyType; +import com.foxinmy.weixin4j.util.DateUtil; +import com.foxinmy.weixin4j.util.RandomUtil; +import com.foxinmy.weixin4j.util.StringUtil; +import com.foxinmy.weixin4j.xml.XmlStream; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.concurrent.*; + +/** + * 现金API + * + * @className CashApi + * @author jinyu(foxinmy@gmail.com) + * @date 2015年3月28日 + * @since JDK 1.6 + * @see + * 现金红包 + * @see + * 企业付款 + */ +public class CashApi extends MchApi { + + public CashApi(WeixinPayAccount weixinAccount) { + super(weixinAccount); + } + + /** + * 发放红包 企业向微信用户个人发现金红包 + * + * @param redpacket + * 红包信息 + * @return 发放结果 + * @see Redpacket + * @see RedpacketSendResult + * @see + * 发放现金红包接口 + * @see + * 发放裂变红包接口 + * @throws WeixinException + */ + public RedpacketSendResult sendRedpack(Redpacket redpacket) + throws WeixinException { + String appId = redpacket.getAppId(); + super.declareMerchant(redpacket); + final JSONObject obj = (JSONObject) JSON.toJSON(redpacket); + if (StringUtil.isNotBlank(appId)) { + obj.put("appid", appId); + } + obj.put("wxappid", obj.remove("appid")); + final String redpack_uri = redpacket.getTotalNum() > 1 ? getRequestUri("groupredpack_send_uri") + : getRequestUri("redpack_send_uri"); + obj.put("sign", weixinSignature.sign(obj)); + String param = XmlStream.map2xml(obj); + WeixinResponse response = getWeixinSSLExecutor().post(redpack_uri, + param); + String text = response.getAsString() + .replaceFirst("", "") + .replaceFirst("", ""); + return XmlStream.fromXML(text, RedpacketSendResult.class); + } + + /** + * 批量发放红包 企业向微信用户个人发现金红包 + * + * 多个红包信息 + * @return 发放结果 + * @see #sendRedpacks(Redpacket...) + * @throws WeixinException + */ + public List> sendRedpacks( + Redpacket... redpackets) { + ExecutorService sendExecutor = Executors.newFixedThreadPool(Math.max(1, + redpackets.length / 10)); // 十分之一? + CompletionService completion = new ExecutorCompletionService( + sendExecutor); + List> callSendList = new ArrayList>( + redpackets.length); + for (final Redpacket redpacket : redpackets) { + Future futureSend = completion + .submit(new Callable() { + @Override + public RedpacketSendResult call() throws Exception { + return sendRedpack(redpacket); + } + }); + callSendList.add(futureSend); + } + // 关闭启动线程,不再接受新的任务 + sendExecutor.shutdown(); + return callSendList; + } + + /** + * 查询红包记录 + * + * @param outTradeNo + * 商户发放红包的商户订单号 + * @return 红包记录 + * @see RedpacketRecord + * @see + * 查询现金红包接口 + * @see + * 查询裂变红包接口 + * @throws WeixinException + */ + public RedpacketRecord queryRedpack(String outTradeNo) + throws WeixinException { + Map para = createBaseRequestMap(null); + para.put("bill_type", "MCHT"); + para.put("mch_billno", outTradeNo); + para.put("sign", weixinSignature.sign(para)); + String param = XmlStream.map2xml(para); + WeixinResponse response = getWeixinSSLExecutor().post( + getRequestUri("redpack_query_uri"), param); + return response.getAsObject(new TypeReference() { + }); + } + + /** + * 企业付款为企业提供付款至用户零钱的能力 + * + * @param payment 付款信息 + * @return 付款结果 + * @see CorpPayment + * @see CorpPaymentResult + * @see 企业付款 + * @see 场景介绍(使用条件、付款资金、付款规则等) + * @throws WeixinException + */ + public CorpPaymentResult sendCorpPayment(CorpPayment payment) + throws WeixinException { + super.declareMerchant(payment); + JSONObject obj = (JSONObject) JSON.toJSON(payment); + obj.put("mchid", obj.remove("mch_id")); + obj.put("mch_appid", obj.remove("appid")); + obj.put("sign", weixinSignature.sign(obj)); + String param = XmlStream.map2xml(obj); + WeixinResponse response = getWeixinSSLExecutor().post( + getRequestUri("corppayment_send_uri"), param); + String text = response.getAsString() + .replaceFirst("", "") + .replaceFirst("", "") + .replaceFirst("", "") + .replaceFirst("", ""); + return XmlStream.fromXML(text, CorpPaymentResult.class); + } + + /** + * 企业付款查询 用于商户的企业付款操作进行结果查询,返回付款操作详细结果 + * + * @param outTradeNo + * 商户调用企业付款API时使用的商户订单号 + * @return 付款记录 + * @see CorpPaymentRecord + * @see + * 企业付款查询接口 + * @throws WeixinException + */ + public CorpPaymentRecord queryCorpPayment(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); + obj.put("sign", weixinSignature.sign(obj)); + String param = XmlStream.map2xml(obj); + WeixinResponse response = getWeixinSSLExecutor().post( + getRequestUri("corppayment_query_uri"), param); + return response.getAsObject(new TypeReference() { + }); + } + + /** + * 查询结算资金 + * + * @param status + * 是否结算 + * @param pageable + * 分页数据 + * @param start + * 开始日期 查询未结算记录时,该字段可不传 + * @param end + * 结束日期 查询未结算记录时,该字段可不传 + * @return 结算金额记录 + * @throws WeixinException + * @see SettlementRecord + * @see + * 查询结算资金接口 + */ + public SettlementRecord querySettlement(boolean status, Pageable pageable, + Date start, Date end) 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("usetag", status ? 1 : 2); + obj.put("offset", pageable.getOffset()); + obj.put("limit", pageable.getPageSize()); + if (start != null) { + obj.put("date_start", DateUtil.fortmat2yyyyMMdd(start)); + } + if (end != null) { + obj.put("date_end", DateUtil.fortmat2yyyyMMdd(end)); + } + obj.put("sign", weixinSignature.sign(obj)); + String param = XmlStream.map2xml(obj); + WeixinResponse response = weixinExecutor.post( + getRequestUri("settlement_query_uri"), param); + return response.getAsObject(new TypeReference() { + }); + } + + /** + * 查询汇率 + * + * @param currencyType + * 外币币种 + * @param date + * 日期 不填则默认当天 + * @return 汇率 例如美元兑换人民币的比例为6.5 + * @throws WeixinException + * @see + * 查询汇率接口 + */ + public double queryExchageRate(CurrencyType currencyType, Date date) + throws WeixinException { + if (date == null) { + date = new Date(); + } + JSONObject obj = new JSONObject(); + obj.put("mch_id", weixinAccount.getMchId()); + obj.put("appid", weixinAccount.getId()); + obj.put("sub_mch_id", weixinAccount.getSubMchId()); + obj.put("fee_type", currencyType.name()); + obj.put("date", DateUtil.fortmat2yyyyMMdd(date)); + obj.put("sign", weixinSignature.sign(obj)); + String param = XmlStream.map2xml(obj); + WeixinResponse response = weixinExecutor.post( + getRequestUri("exchagerate_query_uri"), param); + BigDecimal rate = new BigDecimal(XmlStream.xml2map( + response.getAsString()).get("rate")); + return rate.divide(new BigDecimal(100000000d)).doubleValue(); + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/api/CouponApi.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/api/CouponApi.java new file mode 100644 index 00000000..67c80c13 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/api/CouponApi.java @@ -0,0 +1,122 @@ +package com.foxinmy.weixin4j.pay.api; + +import com.alibaba.fastjson.TypeReference; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.weixin.WeixinResponse; +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.payment.coupon.CouponDetail; +import com.foxinmy.weixin4j.pay.payment.coupon.CouponResult; +import com.foxinmy.weixin4j.pay.payment.coupon.CouponStock; +import com.foxinmy.weixin4j.util.StringUtil; +import com.foxinmy.weixin4j.xml.XmlStream; + +import java.util.Map; + +/** + * 代金券API + * + * @className CouponApi + * @author jinyu(foxinmy@gmail.com) + * @date 2015年3月25日 + * @since JDK 1.6 + * @see 代金券 + */ +public class CouponApi extends MchApi { + + public CouponApi(WeixinPayAccount weixinAccount) { + super(weixinAccount); + } + + /** + * 发放代金券(需要证书) + * + * @param couponStockId + * 代金券批次id + * @param partnerTradeNo + * 商户发放凭据号(格式:商户id+日期+流水号),商户侧需保持唯一性 + * @param openId + * 用户的openid + * @param opUserId + * 操作员帐号, 默认为商户号 可在商户平台配置操作员对应的api权限 可为空 + * @return 发放结果 + * @see CouponResult + * @see 发放代金券接口 + * @throws WeixinException + */ + public CouponResult sendCoupon(String couponStockId, String partnerTradeNo, + String openId, String opUserId) throws WeixinException { + Map map = createBaseRequestMap(null); + map.put("coupon_stock_id", couponStockId); + map.put("partner_trade_no", partnerTradeNo); + map.put("openid", openId); + // openid记录数(目前支持num=1) + map.put("openid_count", "1"); + // 操作员帐号, 默认为商户号 可在商户平台配置操作员对应的api权限 + if (StringUtil.isBlank(opUserId)) { + opUserId = weixinAccount.getMchId(); + } + map.put("op_user_id", opUserId); + map.put("version", "1.0"); + map.put("type", "XML"); + map.put("sign", weixinSignature.sign(map)); + String param = XmlStream.map2xml(map); + WeixinResponse response = getWeixinSSLExecutor().post( + getRequestUri("coupon_send_uri"), param); + return response.getAsObject(new TypeReference() { + }); + } + + /** + * 查询代金券批次 + * + * @param couponStockId + * 代金券批次ID + * @return 代金券批次信息 + * @see CouponStock + * @see 查询代金券批次信息接口 + * @throws WeixinException + */ + public CouponStock queryCouponStock(String couponStockId) + throws WeixinException { + Map map = createBaseRequestMap(null); + map.put("coupon_stock_id", couponStockId); + map.put("sign", weixinSignature.sign(map)); + String param = XmlStream.map2xml(map); + WeixinResponse response = weixinExecutor.post( + getRequestUri("couponstock_query_uri"), param); + return response.getAsObject(new TypeReference() { + }); + } + + /** + * 查询代金券详细 + * + * @param openId + * 用户ID + * @param couponId + * 代金券ID + * @param stockId + * 代金劵对应的批次号 + * @return 代金券详细信息 + * @see CouponDetail + * @see 查询代金券详细信息接口 + * @throws WeixinException + */ + public CouponDetail queryCouponDetail(String openId, String couponId, + String stockId) throws WeixinException { + Map map = createBaseRequestMap(null); + map.put("openid", openId); + map.put("coupon_id", couponId); + map.put("stock_id", stockId); + map.put("sign", weixinSignature.sign(map)); + String param = XmlStream.map2xml(map); + WeixinResponse response = weixinExecutor.post( + getRequestUri("coupondetail_query_uri"), param); + return response.getAsObject(new TypeReference() { + }); + } +} \ No newline at end of file diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/api/CustomsApi.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/api/CustomsApi.java new file mode 100644 index 00000000..258396dc --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/api/CustomsApi.java @@ -0,0 +1,84 @@ +package com.foxinmy.weixin4j.pay.api; + +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.WeixinResponse; +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.payment.mch.CustomsOrder; +import com.foxinmy.weixin4j.pay.payment.mch.CustomsOrderRecord; +import com.foxinmy.weixin4j.pay.payment.mch.CustomsOrderResult; +import com.foxinmy.weixin4j.pay.type.CustomsCity; +import com.foxinmy.weixin4j.pay.type.IdQuery; +import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer; +import com.foxinmy.weixin4j.xml.XmlStream; + +/** + * 报关接口 + * + * @className CustomsApi + * @author jinyu(foxinmy@gmail.com) + * @date 2016年3月67日 + * @since JDK 1.6 + * @see + */ +public class CustomsApi extends MchApi { + + public CustomsApi(WeixinPayAccount weixinAccount) { + super(weixinAccount); + } + + /** + * 订单附加信息提交 + * + * @param customsOrder + * 附加订单信息 + * @return 报关结果 + * @see CustomsOrder + * @see CustomsOrderResult + * @see 附加订单信息提交接口 + * @throws WeixinException + */ + public CustomsOrderResult declareCustomsOrder(CustomsOrder customsOrder) + throws WeixinException { + JSONObject para = (JSONObject) JSON.toJSON(customsOrder); + para.put("appid", weixinAccount.getId()); + para.put("mch_id", weixinAccount.getMchId()); + para.put("sign", weixinSignature.sign(para)); + String param = XmlStream.map2xml(para); + WeixinResponse response = weixinExecutor.post( + getRequestUri("customsorder_declare_uri"), param); + return response.getAsObject(new TypeReference() { + }); + } + + /** + * 订单附加信息查询 + * + * @param idQuery + * out_trade_no,transaction_id,sub_order_no,sub_order_id四选一 + * @param customsCity + * 海关 + * @return 报关记录 + * @see CustomsOrderRecord + * @see 附加订单信息查询接口 + * @throws WeixinException + */ + public CustomsOrderRecord queryCustomsOrder(IdQuery idQuery, + CustomsCity customsCity) throws WeixinException { + JSONObject para = new JSONObject(); + para.put("appid", weixinAccount.getId()); + para.put("mch_id", weixinAccount.getMchId()); + para.put(idQuery.getType().getName(), idQuery.getId()); + para.put("customs", customsCity.name()); + para.put("sign", weixinSignature.sign(para)); + String param = XmlStream.map2xml(para); + WeixinResponse response = weixinExecutor.post( + getRequestUri("customsorder_query_uri"), param); + return ListsuffixResultDeserializer.deserialize(response.getAsString(), + CustomsOrderRecord.class); + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/api/MchApi.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/api/MchApi.java new file mode 100644 index 00000000..104efa19 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/api/MchApi.java @@ -0,0 +1,138 @@ +package com.foxinmy.weixin4j.pay.api; + +import com.foxinmy.weixin4j.api.BaseApi; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.weixin.WeixinRequestExecutor; +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.payment.mch.MerchantResult; +import com.foxinmy.weixin4j.pay.sign.WeixinPaymentSignature; +import com.foxinmy.weixin4j.pay.type.IdQuery; +import com.foxinmy.weixin4j.pay.sign.WeixinSignature; +import com.foxinmy.weixin4j.util.RandomUtil; +import com.foxinmy.weixin4j.util.StringUtil; +import com.foxinmy.weixin4j.util.Weixin4jConfigUtil; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.ResourceBundle; + +/** + * 商户支付 + * + * @className MchApi + * @author jinyu(foxinmy@gmail.com) + * @date 2016年3月26日 + * @since JDK 1.6 + * @see 商户支付平台 + */ +public class MchApi extends BaseApi { + private final static ResourceBundle WEIXIN_BUNDLE; + + private final static String PEM_CERT_PREFIX = "-----BEGIN CERTIFICATE-----"; + + static { + WEIXIN_BUNDLE = ResourceBundle.getBundle("com/foxinmy/weixin4j/payment/weixin"); + } + + protected final WeixinPayAccount weixinAccount; + protected final WeixinSignature weixinSignature; + private volatile WeixinRequestExecutor weixinSSLExecutor; + + public MchApi(WeixinPayAccount weixinAccount) { + this.weixinAccount = weixinAccount; + this.weixinSignature = new WeixinPaymentSignature(weixinAccount.getPaySignKey()); + } + + @Override + protected ResourceBundle weixinBundle() { + return WEIXIN_BUNDLE; + } + + /** + * 支付接口请求基本数据 + * + * @param idQuery + * ID信息 可为空 + * @return 基础map + */ + protected Map createBaseRequestMap(IdQuery idQuery) { + Map map = new HashMap(); + 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; + } + + /** + * 微信签名类 + * + * @return + */ + public WeixinSignature getWeixinSignature() { + return this.weixinSignature; + } + + /** + * 微信SSL + * + * @return + */ + protected WeixinRequestExecutor getWeixinSSLExecutor() throws WeixinException { + if (weixinSSLExecutor == null) { + if(weixinAccount.getCertificateFile().startsWith(PEM_CERT_PREFIX)){ + // 证书是PEM格式,直接使用PEM内容生成请求执行类 + this.weixinSSLExecutor = weixinExecutor.createSSLRequestExecutor(weixinAccount.getMchId(), + weixinAccount.getCertificateFile(), weixinAccount.getCertificateKey()); + }else { + // 证书是p12格式,读取证书文件并生成请求执行类 + try { + InputStream is = null; + File certificate = new File( + Weixin4jConfigUtil.replaceClassPathValue(weixinAccount.getCertificateFile())); + if (!certificate.exists() || !certificate.isFile()) { + is = Weixin4jConfigUtil.CLASSLOADER.getResourceAsStream(certificate.getName()); + } else { + is = new FileInputStream(certificate); + } + if (is == null) { + throw new WeixinException("Invalid certificate file : " + certificate.toString()); + } + this.weixinSSLExecutor = weixinExecutor.createSSLRequestExecutor(weixinAccount.getCertificateKey(), is); + } catch (IOException e) { + throw new WeixinException("IO Error on createSSLRequestExecutor", e); + } + } + } + return this.weixinSSLExecutor; + } + + /** + * 设置商户信息 + * + * @param merchant + */ + protected void declareMerchant(T merchant) { + merchant.setAppId(weixinAccount.getId()); + merchant.setMchId(weixinAccount.getMchId()); + merchant.setDeviceInfo(weixinAccount.getDeviceInfo()); + merchant.setSubAppId(weixinAccount.getSubId()); + merchant.setSubMchId(weixinAccount.getSubMchId()); + merchant.setNonceStr(RandomUtil.generateString(16)); + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/api/PayApi.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/api/PayApi.java new file mode 100644 index 00000000..4ad38149 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/api/PayApi.java @@ -0,0 +1,815 @@ +package com.foxinmy.weixin4j.pay.api; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.TypeReference; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.weixin.WeixinResponse; +import com.foxinmy.weixin4j.http.weixin.XmlResult; +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.payment.face.PayfaceAuthinfo; +import com.foxinmy.weixin4j.pay.payment.face.PayfaceAuthinfoRequest; +import com.foxinmy.weixin4j.pay.payment.mch.*; +import com.foxinmy.weixin4j.pay.type.mch.BillType; +import com.foxinmy.weixin4j.pay.type.mch.DepositType; +import com.foxinmy.weixin4j.pay.type.mch.RefundAccountType; +import com.foxinmy.weixin4j.pay.type.*; +import com.foxinmy.weixin4j.util.*; +import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer; +import com.foxinmy.weixin4j.xml.XmlStream; + +import java.io.*; +import java.net.URLEncoder; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * 支付API + * + * @className PayApi + * @author jinyu(foxinmy@gmail.com) + * @date 2014年10月28日 + * @since JDK 1.6 + */ +public class PayApi extends MchApi { + + public PayApi(WeixinPayAccount weixinAccount) { + super(weixinAccount); + } + + /** + * 统一下单接口
+ * 除被扫支付场景以外,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再按扫码、JSAPI + * 、APP等不同场景生成交易串调起支付。 + * + * @param payPackage + * 包含订单信息的对象 + * @see MchPayPackage + * @see PrePay + * @see 统一下单接口 + * + * @return 预支付对象 + */ + public PrePay createPrePay(MchPayPackage payPackage) throws WeixinException { + super.declareMerchant(payPackage); + payPackage.setSign(weixinSignature.sign(payPackage)); + String payJsRequestXml = XmlStream.toXML(payPackage); + WeixinResponse response = weixinExecutor.post( + getRequestUri("order_create_uri"), payJsRequestXml); + return response.getAsObject(new TypeReference() { + }); + } + + /** + * 创建支付请求对象 + * + * @param payPackage + * 支付详情 + * @return 支付请求对象 + * @see JSAPIPayRequest JS支付 + * @see NATIVEPayRequest 扫码支付 + * @see MICROPayRequest 刷卡支付 + * @see APPPayRequest APP支付 + * @see WAPPayRequest WAP支付 + * @throws WeixinException + */ + public MchPayRequest createPayRequest(MchPayPackage payPackage) + throws WeixinException { + if (StringUtil.isBlank(payPackage.getTradeType())) { + throw new WeixinException("tradeType not be empty"); + } + String tradeType = payPackage.getTradeType().toUpperCase(); + if (TradeType.MICROPAY.name().equals(tradeType) || TradeType.FACEPAY.name().equals(tradeType)) { + MchPayPackage _payPackage = new MchPayPackage(payPackage.getBody(), + payPackage.getDetail(), payPackage.getOutTradeNo(), + DateUtil.formatFee2Yuan(payPackage.getTotalFee()), null, + null, payPackage.getCreateIp(), null, payPackage.getOpenId(), + payPackage.getAuthCode(), null, payPackage.getAttach(), + null, null, payPackage.getGoodsTag(), + payPackage.getLimitPay(), payPackage.getSubAppId(), payPackage.getFaceCode(), + payPackage.getDeposit()); + // 默认为MD5签名 + SignType signType= SignType.MD5; + super.declareMerchant(_payPackage); + // 默认为刷卡支付(付款码支付)的API地址 + String url = getRequestUri("micropay_uri"); + if(payPackage.getDeposit()==DepositType.Y){ + // 押金支付只支持HMAC-SHA256签名 + signType = SignType.HMAC$SHA256; + _payPackage.setSignType("HMAC-SHA256"); + // 如果是押金支付,改为押金支付的API地址 + url = TradeType.MICROPAY.name().equals(tradeType) ? getRequestUri("deposit_micropay_uri") : + getRequestUri("deposit_facepay_uri"); + }else if(TradeType.FACEPAY.name().equals(tradeType)){ + url = getRequestUri("facepay_url"); + } + _payPackage.setSign(weixinSignature.sign(_payPackage, signType)); + String para = XmlStream.toXML(_payPackage); + + WeixinResponse response = weixinExecutor.post(url, para); + MICROPayRequest microPayRequest = response.getAsObject(new TypeReference() {}); + microPayRequest.setPaymentAccount(weixinAccount); + return microPayRequest; + } + PrePay prePay = createPrePay(payPackage); + if (TradeType.APP.name().equals(tradeType)) { + return new APPPayRequest(prePay.getPrepayId(), weixinAccount); + } else if (TradeType.JSAPI.name().equals(tradeType)) { + return new JSAPIPayRequest(prePay.getPrepayId(), weixinAccount); + } else if (TradeType.NATIVE.name().equals(tradeType)) { + return new NATIVEPayRequest(prePay.getPrepayId(), + prePay.getPayUrl(), weixinAccount); + } else if (TradeType.MWEB.name().equals(tradeType)) { + return new WAPPayRequest(prePay.getPrepayId(), prePay.getPayUrl(), + weixinAccount); + } else { + throw new WeixinException("unknown tradeType:" + tradeType); + } + } + + /** + * 创建JSAPI支付请求对象 + * + * @param openId + * 用户ID + * @param body + * 订单描述 + * @param outTradeNo + * 订单号 + * @param totalFee + * 订单总额(元) + * @param notifyUrl + * 支付通知地址 + * @param createIp + * ip地址 + * @param attach + * 附加数据 非必填 + * @see JSAPIPayRequest + * @return JSAPI支付对象 + * @throws WeixinException + */ + public MchPayRequest createJSPayRequest(String openId, String body, + String outTradeNo, double totalFee, String notifyUrl, + String createIp, String attach) throws WeixinException { + MchPayPackage payPackage = new MchPayPackage(body, outTradeNo, + totalFee, notifyUrl, createIp, TradeType.JSAPI, openId, null, + null, attach); + return createPayRequest(payPackage); + } + + /** + * 创建Native支付(扫码支付)链接【模式一】 + * + * @param productId + * 与订单ID等价 + * @return 支付链接 + * @see 扫码支付 + * + * @see 模式一 + * + */ + public String createNativePayRequest(String productId) { + Map map = new HashMap(); + String timestamp = DateUtil.timestamp2string(); + String noncestr = RandomUtil.generateString(16); + map.put("appid", weixinAccount.getId()); + map.put("mch_id", weixinAccount.getMchId()); + map.put("time_stamp", timestamp); + map.put("nonce_str", noncestr); + map.put("product_id", productId); + String sign = weixinSignature.sign(map); + return String.format(getRequestUri("native_pay_uri"), sign, + weixinAccount.getId(), weixinAccount.getMchId(), productId, + timestamp, noncestr); + } + + /** + * 创建Native支付(扫码支付)回调对象【模式一】 + * + * @param productId + * 商品ID + * @param body + * 商品描述 + * @param outTradeNo + * 商户内部唯一订单号 + * @param totalFee + * 商品总额 单位元 + * @param notifyUrl + * 支付回调URL + * @param createIp + * 订单生成的机器 IP + * @param attach + * 附加数据 非必填 + * @return Native回调对象 + * @see NativePayResponse + * @see 扫码支付 + * + * @see 模式一 + * + * @throws WeixinException + */ + public NativePayResponse createNativePayResponse(String productId, + String body, String outTradeNo, double totalFee, String notifyUrl, + String createIp, String attach) throws WeixinException { + MchPayPackage payPackage = new MchPayPackage(body, outTradeNo, + totalFee, notifyUrl, createIp, TradeType.NATIVE, null, null, + productId, attach); + PrePay prePay = createPrePay(payPackage); + return new NativePayResponse(weixinAccount, prePay.getPrepayId()); + } + + /** + * 创建Native支付(扫码支付)链接【模式二】 + * + * @param productId + * 商品ID + * @param body + * 商品描述 + * @param outTradeNo + * 商户内部唯一订单号 + * @param totalFee + * 商品总额 单位元 + * @param notifyUrl + * 支付回调URL + * @param createIp + * 订单生成的机器 IP + * @param attach + * 附加数据 非必填 + * @return Native支付对象 + * @see NATIVEPayRequest + * @see 扫码支付 + * + * @see 模式二 + * + * @throws WeixinException + */ + public MchPayRequest createNativePayRequest(String productId, String body, + String outTradeNo, double totalFee, String notifyUrl, + String createIp, String attach) throws WeixinException { + MchPayPackage payPackage = new MchPayPackage(body, outTradeNo, + totalFee, notifyUrl, createIp, TradeType.NATIVE, null, null, + productId, attach); + return createPayRequest(payPackage); + } + + /** + * 创建APP支付请求对象 + * + * @param body + * 商品描述 + * @param outTradeNo + * 商户内部唯一订单号 + * @param totalFee + * 商品总额 单位元 + * @param notifyUrl + * 支付回调URL + * @param createIp + * 订单生成的机器 IP + * @param attach + * 附加数据 非必填 + * @param store + * 门店信息 非必填 + * @return APP支付对象 + * @see SceneInfoStore + * @see APPPayRequest + * @see + * APP支付 + * @throws WeixinException + */ + public MchPayRequest createAppPayRequest(String body, String outTradeNo, + double totalFee, String notifyUrl, String createIp, String attach, + SceneInfoStore store) throws WeixinException { + MchPayPackage payPackage = new MchPayPackage(body, outTradeNo, + totalFee, notifyUrl, createIp, TradeType.APP, null, null, null, + attach); + if (store != null) { + payPackage.setSceneInfo(String.format( + "{\"store_id\": \"%s\", \"store_name\":\"%s\"}", + store.getId(), store.getName())); + } + return createPayRequest(payPackage); + } + + /** + * 创建WAP支付请求对象:正常流程用户支付完成后会返回至发起支付的页面,如需返回至指定页面, + * 则可以在MWEB_URL后拼接上redirect_url参数,来指定回调页面 + * + * @param body + * 商品描述 + * @param outTradeNo + * 商户内部唯一订单号 + * @param totalFee + * 商品总额 单位元 + * @param notifyUrl + * 支付回调URL + * @param createIp + * 订单生成的机器 IP + * @param attach + * 附加数据 非必填 + * @param app + * 应用信息 + * @return WAP支付对象 + * @see SceneInfoApp + * @see WAPPayRequest + * @see WAP支付 + * + * @throws WeixinException + */ + public MchPayRequest createWapPayRequest(String body, String outTradeNo, + double totalFee, String notifyUrl, String createIp, String attach, + SceneInfoApp app) throws WeixinException { + MchPayPackage payPackage = new MchPayPackage(body, outTradeNo, + totalFee, notifyUrl, createIp, TradeType.MWEB, null, null, + null, attach); + if (app != null) { + payPackage.setSceneInfo(String.format("{\"h5_info\":\"%s\"}", + app.getSceneInfo())); + } + return createPayRequest(payPackage); + } + + /** + * 提交被扫支付 + * + * @param authCode + * 扫码支付授权码 ,设备读取用户微信中的条码或者二维码信息 + * @param body + * 商品描述 + * @param outTradeNo + * 商户内部唯一订单号 + * @param totalFee + * 商品总额 单位元 + * @param createIp + * 订单生成的机器 IP + * @param attach + * 附加数据 非必填 + * @param store + * 门店信息 非必填 + * @return 支付的订单信息 + * @see MICROPayRequest + * @see Order + * @see SceneInfoStore + * @see + * 提交被扫支付API + * @throws WeixinException + */ + public MchPayRequest createMicroPayRequest(String authCode, String body, + String outTradeNo, double totalFee, String createIp, String attach, + SceneInfoStore store) throws WeixinException { + MchPayPackage payPackage = new MchPayPackage(body, outTradeNo, + totalFee, null, createIp, TradeType.MICROPAY, null, authCode, + null, attach); + if (store != null) { + payPackage.setSceneInfo(String.format("{\"store_info\":\"%s\"}", + JSON.toJSONString(store))); + } + return createPayRequest(payPackage); + } + + /** + * 订单查询 + *

+ * 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;
调用支付接口后,返回系统错误或未知交易状态情况;
+ * 调用被扫支付API,返回USERPAYING的状态;
调用关单或撤销接口API之前,需确认支付状态; + *

+ * + * @param idQuery + * 商户系统内部的订单号, transaction_id、out_trade_no 二 选一,如果同时存在优先级: + * transaction_id> out_trade_no + * @return 订单信息 + * @see Order + * @see + * 订单查询API + * @since V3 + * @throws WeixinException + */ + public Order queryOrder(IdQuery idQuery) throws WeixinException { + Map map = createBaseRequestMap(idQuery); + map.put("sign", weixinSignature.sign(map)); + String param = XmlStream.map2xml(map); + WeixinResponse response = weixinExecutor.post( + getRequestUri("order_query_uri"), param); + return ListsuffixResultDeserializer.deserialize(response.getAsString(), + Order.class); + } + + /** + * 申请退款(请求需要双向证书) + * + *

+ * 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后, + * 按照退款规则将支付款按原路退到买家帐号上。 + *

+ * + *
    + *
  1. 交易时间超过一年的订单无法提交退款;
  2. + *
  3. + * 微信支付退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。 + * 申请退款总金额不能超过订单金额。 + * 一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号。 + *
  4. + *
  5. + * 请求频率限制:150qps,即每秒钟正常的申请退款请求次数不超过150次。 + * 错误或无效请求频率限制:6qps,即每秒钟异常或错误的退款申请请求不超过6次。 + *
  6. + *
  7. 每个支付订单的部分退款次数不能超过50次。
  8. + *
+ * + * @param idQuery + * 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级: + * transaction_id> out_trade_no + * @param outRefundNo + * 商户系统内部的退款单号,商 户系统内部唯一,同一退款单号多次请求只退一笔 + * @param totalFee + * 订单总金额,单位为元 + * @param refundFee + * 退款总金额,单位为元,可以做部分退款 + * @param refundFeeType + * 货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY + * @param opUserId + * 操作员帐号, 默认为商户号 + * @param refundDesc + * 退款原因,若商户传入,会在下发给用户的退款消息中体现退款原因 + * @param refundAccountType + * 退款资金来源,默认使用未结算资金退款:REFUND_SOURCE_UNSETTLED_FUNDS + * @return 退款申请结果 + * @see RefundResult + * @see + * 申请退款API + * @since V3 + * @throws WeixinException + */ + public RefundResult applyRefund(IdQuery idQuery, String outRefundNo, + double totalFee, double refundFee, CurrencyType refundFeeType, + String opUserId, String refundDesc, + RefundAccountType refundAccountType) throws WeixinException { + Map map = createBaseRequestMap(idQuery); + map.put("out_refund_no", outRefundNo); + map.put("total_fee", + Integer.toString(DateUtil.formatYuan2Fen(totalFee))); + map.put("refund_fee", + Integer.toString(DateUtil.formatYuan2Fen(refundFee))); + if (StringUtil.isBlank(opUserId)) { + opUserId = weixinAccount.getMchId(); + } + map.put("op_user_id", opUserId); + if (refundFeeType == null) { + refundFeeType = CurrencyType.CNY; + } + if (refundAccountType == null) { + refundAccountType = RefundAccountType.REFUND_SOURCE_UNSETTLED_FUNDS; + } + if (StringUtil.isNotBlank(refundDesc)) { + map.put("refund_desc", refundDesc); + } + map.put("refund_fee_type", refundFeeType.name()); + map.put("refund_account", refundAccountType.name()); + map.put("sign", weixinSignature.sign(map)); + String param = XmlStream.map2xml(map); + WeixinResponse response = getWeixinSSLExecutor().post( + getRequestUri("refund_apply_uri"), param); + return response.getAsObject(new TypeReference() { + }); + } + + /** + * 退款申请(全额退款) + * + * @param idQuery + * 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级: + * transaction_id> out_trade_no + * @param outRefundNo + * 商户系统内部的退款单号,商 户系统内部唯一,同一退款单号多次请求只退一笔 + * @param totalFee + * 订单总金额,单位为元 + * @see #applyRefund(IdQuery, String, double, double, CurrencyType, String, String, RefundAccountType) + */ + public RefundResult applyRefund(IdQuery idQuery, String outRefundNo, + double totalFee) throws WeixinException { + return applyRefund(idQuery, outRefundNo, totalFee, totalFee, null, + null, null, null); + } + + /** + * 冲正订单(需要证书)
当支付返回失败,或收银系统超时需要取消交易,可以调用该接口
接口逻辑:支 + * 付失败的关单,支付成功的撤销支付
7天以内的单可撤销,其他正常支付的单 + * 如需实现相同功能请调用退款接口
调用扣款接口后请勿立即调用撤销,需要等待5秒以上。先调用查单接口,如果没有确切的返回,再调用撤销
+ * + * @param idQuery + * 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级: + * transaction_id> out_trade_no + * @return 撤销结果 + * @since V3 + * @throws WeixinException + */ + public MerchantResult reverseOrder(IdQuery idQuery) throws WeixinException { + Map map = createBaseRequestMap(idQuery); + map.put("sign", weixinSignature.sign(map)); + String param = XmlStream.map2xml(map); + WeixinResponse response = getWeixinSSLExecutor().post( + getRequestUri("order_reverse_uri"), param); + return response.getAsObject(new TypeReference() { + }); + } + + /** + * native支付URL转短链接:用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),减小二维码数据量 + * ,提升扫描速度和精确度。 + * + * @param url + * 具有native标识的支付URL + * @return 转换后的短链接 + * @throws WeixinException + * @see + * 转换短链接API + */ + public String getShorturl(String url) throws WeixinException { + Map map = createBaseRequestMap(null); + try { + map.put("long_url", URLEncoder.encode(url, Consts.UTF_8.name())); + } catch (UnsupportedEncodingException e) { + ; + } + map.put("sign", weixinSignature.sign(map)); + String param = XmlStream.map2xml(map); + WeixinResponse response = weixinExecutor.post( + getRequestUri("longurl_convert_uri"), param); + map = XmlStream.xml2map(response.getAsString()); + return map.get("short_url"); + } + + /** + * 关闭订单 + *

+ * 商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;系统下单后,用户支付超时,系统退出不再受理,避免用户继续 + * ,请调用关单接口,如果关单失败,返回已完 成支付请按正常支付处理。如果出现银行掉单,调用关单成功后,微信后台会主动发起退款。 + *

+ * + * @param outTradeNo + * 商户系统内部的订单号 + * @return 处理结果 + * @since V3 + * @throws WeixinException + * @see + * 关闭订单API + */ + public MerchantResult closeOrder(String outTradeNo) throws WeixinException { + Map map = createBaseRequestMap(new IdQuery(outTradeNo, + IdType.TRADENO)); + map.put("sign", weixinSignature.sign(map)); + String param = XmlStream.map2xml(map); + WeixinResponse response = weixinExecutor.post( + getRequestUri("order_close_uri"), param); + return response.getAsObject(new TypeReference() { + }); + } + + /** + * 下载对账单
+ * 1.微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账 单中,跟原支付单订单号一致,bill_type 为 + * REVOKED;
+ * 2.微信在次日 9 点启动生成前一天的对账单,建议商户 9 点半后再获取;
+ * 3.对账单中涉及金额的字段单位为“元”。
+ * + * @param billDate + * 下载对账单的日期 + * @param billType + * 下载对账单的类型 ALL,返回当日所有订单信息, 默认值 SUCCESS,返回当日成功支付的订单 + * REFUND,返回当日退款订单 + * @param outputStream + * 输出流 + * @param tarType + * 非必传参数,固定值:GZIP,返回格式为.gzip的压缩包账单。不传则默认为数据流形式。 + * @since V3 + * @see + * 下载对账单API + * @throws WeixinException + */ + public void downloadBill(Date billDate, BillType billType, + OutputStream outputStream, TarType tarType) throws WeixinException { + if (billDate == null) { + Calendar now = Calendar.getInstance(); + now.add(Calendar.DAY_OF_MONTH, -1); + billDate = now.getTime(); + } + if (billType == null) { + billType = BillType.ALL; + } + String formatBillDate = DateUtil.fortmat2yyyyMMdd(billDate); + Map map = createBaseRequestMap(null); + map.put("bill_date", formatBillDate); + map.put("bill_type", billType.name()); + if (tarType != null) { + map.put("tar_type", tarType.name()); + } + map.put("sign", weixinSignature.sign(map)); + String param = XmlStream.map2xml(map); + WeixinResponse response = weixinExecutor.post( + getRequestUri("downloadbill_uri"), param); + + if (TarType.GZIP == tarType) { + try { + IOUtil.copy(response.getBody(), outputStream); + } catch (IOException e) { + ; + } + } else { + BufferedReader reader = null; + BufferedWriter writer = null; + try { + writer = new BufferedWriter(new OutputStreamWriter( + outputStream, Consts.UTF_8)); + reader = new BufferedReader(new InputStreamReader( + response.getBody(), Consts.UTF_8)); + String line = null; + while ((line = reader.readLine()) != null) { + writer.write(line); + writer.newLine(); + } + } catch (IOException e) { + throw new WeixinException(e); + } finally { + try { + if (reader != null) { + reader.close(); + } + if (writer != null) { + writer.close(); + } + } catch (IOException ignore) { + ; + } + } + } + } + + /** + * 退款查询 + * + *

+ * 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。 + *

+ * + * @param idQuery + * 单号 refund_id、out_refund_no、 out_trade_no 、 transaction_id + * 四个参数必填一个,优先级为: + * refund_id>out_refund_no>transaction_id>out_trade_no + * @return 退款记录 + * @see RefundRecord + * @see com.foxinmy.weixin4j.payment.mch.RefundDetail + * @see + * 退款查询API + * @since V3 + * @throws WeixinException + */ + public RefundRecord queryRefund(IdQuery idQuery) throws WeixinException { + Map map = createBaseRequestMap(idQuery); + map.put("sign", weixinSignature.sign(map)); + String param = XmlStream.map2xml(map); + WeixinResponse response = weixinExecutor.post( + getRequestUri("refund_query_uri"), param); + return ListsuffixResultDeserializer.deserialize(response.getAsString(), + RefundRecord.class); + } + + /** + * 接口上报 + * + * @param interfaceUrl + * 上报对应的接口的完整 URL, 类似: https://api.mch.weixin.q + * q.com/pay/unifiedorder + * @param executeTime + * 接口耗时情况,单位为毫秒 + * @param outTradeNo + * 商户系统内部的订单号,商 户可以在上报时提供相关商户订单号方便微信支付更好 的提高服务质量。 + * @param ip + * 发起接口调用时的机器 IP + * @param time + * 商户调用该接口时商户自己 系统的时间 + * @param returnXml + * 调用接口返回的基本数据 + * @return 处理结果 + * @throws WeixinException + * @see + * 交易保障 + */ + @SuppressWarnings("unchecked") + public XmlResult reportInterface(String interfaceUrl, int executeTime, + String outTradeNo, String ip, Date time, XmlResult returnXml) + throws WeixinException { + Map 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) JSON.toJSON(returnXml)); + map.put("sign", weixinSignature.sign(map)); + String param = XmlStream.map2xml(map); + WeixinResponse response = weixinExecutor.post( + getRequestUri("interface_report_uri"), param); + return response.getAsXml(); + } + + /** + * 授权码查询OPENID接口 + * + * @param authCode + * 扫码支付授权码,设备读取用户微信中的条码或者二维码信息 + * @return 查询结果 + * @see OpenIdResult + * @see + * 授权码查询OPENID + * @throws WeixinException + */ + public OpenIdResult authCode2openId(String authCode) throws WeixinException { + Map map = createBaseRequestMap(null); + map.put("auth_code", authCode); + map.put("sign", weixinSignature.sign(map)); + String param = XmlStream.map2xml(map); + WeixinResponse response = weixinExecutor.post( + getRequestUri("authcode_openid_uri"), param); + return response.getAsObject(new TypeReference() { + }); + } + + /** + * 微信刷脸支付,获取调用凭证 + * + * @param request + * @return + * @see + * 获取调用凭证-get-wxpayface-authinfo + */ + public PayfaceAuthinfo getWxPayfaceAuthinfo(PayfaceAuthinfoRequest request) throws WeixinException { + WeixinResponse response = weixinExecutor.post( + getRequestUri("get_wxpayface_authinfo_uri"), request.toRequestString()); + return response.getAsObject(new TypeReference() {}); + } + + /** + * 微信旧版刷脸支付 + * + * @param faceCode + * @param body + * @param outTradeNo + * @param totalFee + * @param createIp + * @param openId + * @param attach + * @return + * @throws WeixinException + */ + public MchPayRequest createFacePayRequest(String faceCode, String body, + String outTradeNo, double totalFee, String createIp, String openId, + String attach) throws WeixinException { + MchPayPackage payPackage = new MchPayPackage(body, outTradeNo, + totalFee, null, createIp, TradeType.FACEPAY, openId, null, + null, attach); + payPackage.setFaceCode(faceCode); + return createPayRequest(payPackage); + } + + public MchPayRequest createDepositPayRequest(String code, String body, String outTradeNo, double totalFee, + String createIp, String openId, String attach, SceneInfoStore store, + boolean isFacePay) throws WeixinException { + MchPayPackage payPackage; + if(isFacePay) { + payPackage = new MchPayPackage(body, outTradeNo, totalFee, null, createIp, TradeType.FACEPAY, + openId, null, null, attach); + payPackage.setFaceCode(code); + payPackage.setDeposit(DepositType.Y); + return createPayRequest(payPackage); + }else{ + payPackage = new MchPayPackage(body, outTradeNo, totalFee, null, createIp, TradeType.MICROPAY, + openId, code, null, attach); + payPackage.setDeposit(DepositType.Y); + if (store != null) { + payPackage.setSceneInfo(String.format("{\"store_info\":\"%s\"}", + JSON.toJSONString(store))); + } + return createPayRequest(payPackage); + } + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/model/WeixinPayAccount.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/model/WeixinPayAccount.java new file mode 100644 index 00000000..d6dc9fc2 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/model/WeixinPayAccount.java @@ -0,0 +1,190 @@ +package com.foxinmy.weixin4j.pay.model; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.model.WeixinAccount; +import com.foxinmy.weixin4j.util.StringUtil; + +/** + * 微信支付账户 + * + * @className WeixinPayAccount + * @author jinyu(foxinmy@gmail.com) + * @date 2015年6月26日 + * @since JDK 1.6 + * @see + */ +public class WeixinPayAccount extends WeixinAccount { + + private static final long serialVersionUID = -2791256176906048632L; + /** + * 公众号支付请求中用于加密的密钥 + */ + private final String paySignKey; + /** + * 微信支付分配的商户号 + */ + private final String mchId; + /** + * 加载支付证书文件的密码(默认为商户号) + */ + private String certificateKey; + /** + * 商户证书文件(默认加载classpath:ca.p12) + */ + private String certificateFile; + /** + * 微信支付分配的设备号 + */ + private String deviceInfo; + /** + * 财付通商户身份的标识 + */ + private String partnerId; + + /** + * 微信分配的子商户公众账号ID + */ + private String subId; + /** + * 微信支付分配的子商户号 + */ + private String subMchId; + + /** + * 支付商户信息 + * + * @param id + * 公众号唯一的身份ID(必填) + * @param paySignKey + * 支付密钥字符串(必填) + * @param mchId + * 微信支付分配的商户号(必填) + */ + public WeixinPayAccount(String id, String paySignKey, String mchId) { + this(id, paySignKey, mchId, mchId, "classpath:ca.p12"); + } + + /** + * 支付商户信息 + * + * @param id + * 公众号唯一的身份ID(必填) + * @param paySignKey + * 支付密钥字符串(必填) + * @param mchId + * 微信支付分配的商户号(必填) + * @param certificateKey + * 加载支付证书文件的密码(默认为商户号) + * @param certificateFile + * 商户证书文件(默认加载classpath:ca.p12) + */ + public WeixinPayAccount(String id, String paySignKey, String mchId, String certificateKey, String certificateFile) { + this(id, null, paySignKey, mchId, certificateKey, certificateFile, null, null, null, null); + } + + /** + * 支付商户信息 + * + * @param id + * 公众号唯一的身份ID(必填) + * @param secret + * 公众号调用接口的凭证(最好填写) + * @param paySignKey + * 支付密钥字符串(必填) + * @param mchId + * 微信支付分配的商户号(必填) + * @param certificateKey + * 加载支付证书文件的密码(默认为商户号) + * @param certificateFile + * 商户证书文件(默认加载classpath:ca.p12) + * @param deviceInfo + * 微信支付分配的设备号(非必填) + * @param partnerId + * 财付通的商户号(非必填) + * @param subId + * 微信分配的子商户公众账号ID(非必填) + * @param subMchId + * 微信支付分配的子商户号(非必填) + */ + @JSONCreator + 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 = "certificateFile") String certificateFile, + @JSONField(name = "deviceInfo") String deviceInfo, @JSONField(name = "partnerId") String partnerId, + @JSONField(name = "subId") String subId, @JSONField(name = "subMchId") String subMchId) { + super(id, secret); + this.paySignKey = paySignKey; + this.mchId = mchId; + this.certificateKey = certificateKey; + this.certificateFile = certificateFile; + this.deviceInfo = deviceInfo; + this.partnerId = partnerId; + this.subId = subId; + this.subMchId = subMchId; + } + + public String getPaySignKey() { + return paySignKey; + } + + public String getMchId() { + return mchId; + } + + public String getDeviceInfo() { + return deviceInfo; + } + + public String getCertificateKey() { + return StringUtil.isBlank(certificateKey) ? mchId : certificateKey; + } + + public String getPartnerId() { + return partnerId; + } + + public String getSubId() { + return subId; + } + + public String getSubMchId() { + return subMchId; + } + + public void setCertificateKey(String certificateKey) { + this.certificateKey = certificateKey; + } + + public String getCertificateFile() { + return certificateFile; + } + + public void setCertificateFile(String certificateFile) { + this.certificateFile = certificateFile; + } + + public void setDeviceInfo(String deviceInfo) { + this.deviceInfo = deviceInfo; + } + + public void setPartnerId(String partnerId) { + this.partnerId = partnerId; + } + + public void setSubId(String subId) { + this.subId = subId; + } + + public void setSubMchId(String subMchId) { + this.subMchId = subMchId; + } + + @Override + public String toString() { + return "WeixinPayAccount [" + super.toString() + ", paySignKey=" + paySignKey + ", mchId=" + mchId + + ", certificateKey=" + certificateKey + ",certificateFile =" + certificateFile + ", deviceInfo=" + + deviceInfo + ", partnerId=" + partnerId + ", subId=" + subId + ", subMchId=" + subMchId + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/JsPayNotify.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/JsPayNotify.java new file mode 100644 index 00000000..14af1807 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/JsPayNotify.java @@ -0,0 +1,60 @@ +package com.foxinmy.weixin4j.pay.payment; + +import com.alibaba.fastjson.annotation.JSONField; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * JSAPI支付回调时的POST信息 + * + * @className JsPayNotify + * @author jinyu(foxinmy@gmail.com) + * @date 2014年8月19日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class JsPayNotify extends PayBaseInfo { + + private static final long serialVersionUID = -4659030958445259803L; + + /** + * 用户的openid + */ + @JSONField(name = "OpenId") + @XmlElement(name = "OpenId") + private String openId; + /** + * 是否关注公众号 + */ + @JSONField(name = "IsSubscribe") + @XmlElement(name = "IsSubscribe") + private int isSubscribe; + + public JsPayNotify() { + + } + + public String getOpenId() { + return openId; + } + + public int getIsSubscribe() { + return isSubscribe; + } + + @JSONField(serialize = false) + public boolean getFormatIsSubscribe() { + return isSubscribe == 1; + } + + @Override + public String toString() { + return "openId=" + openId + ", isSubscribe=" + getFormatIsSubscribe() + + ", " + super.toString(); + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/PayBaseInfo.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/PayBaseInfo.java new file mode 100644 index 00000000..a38eaab2 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/PayBaseInfo.java @@ -0,0 +1,116 @@ +package com.foxinmy.weixin4j.pay.payment; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.pay.type.SignType; + +import javax.xml.bind.annotation.*; +import java.io.Serializable; + +/** + * 基本信息 + * + * @className PayBaseInfo + * @author jinyu(foxinmy@gmail.com) + * @date 2014年11月5日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class PayBaseInfo implements Serializable { + + private static final long serialVersionUID = 1843024880782466990L; + + /** + * 公众号ID + */ + @JSONField(name = "appId") + @XmlElement(name = "AppId") + private String appId; + /** + * 时间戳 + */ + @JSONField(name = "timeStamp") + @XmlElement(name = "TimeStamp") + private String timeStamp; + /** + * 随机字符串 + */ + @JSONField(name = "nonceStr") + @XmlElement(name = "NonceStr") + private String nonceStr; + /** + * 签名结果 + */ + @JSONField(name = "paySign") + @XmlElement(name = "AppSignature") + private String paySign; + /** + * 签名方式 + */ + @JSONField(name = "signType") + @XmlElement(name = "SignMethod") + private String signType; + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(String timeStamp) { + this.timeStamp = timeStamp; + } + + public String getNonceStr() { + return nonceStr; + } + + public void setNonceStr(String nonceStr) { + this.nonceStr = nonceStr; + } + + public String getPaySign() { + return paySign; + } + + public void setPaySign(String paySign) { + this.paySign = paySign; + } + + public String getSignType() { + return signType; + } + + @XmlTransient + @JSONField(serialize = false) + public SignType getFormatSignType() { + return signType != null ? SignType.valueOf(signType.toUpperCase()) + : null; + } + + public void setSignType(SignType signType) { + this.signType = signType != null ? signType.name() : null; + } + + public PayBaseInfo() { + } + + public PayBaseInfo(String appId, String timestamp, String noncestr) { + this.appId = appId; + this.timeStamp = timestamp; + this.nonceStr = noncestr; + } + + @Override + public String toString() { + return "appId=" + appId + ", timeStamp=" + timeStamp + ", nonceStr=" + + nonceStr + ", paySign=" + paySign + ", signType=" + signType; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/PayPackage.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/PayPackage.java new file mode 100644 index 00000000..e652828f --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/PayPackage.java @@ -0,0 +1,284 @@ +package com.foxinmy.weixin4j.pay.payment; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.pay.payment.mch.MerchantResult; +import com.foxinmy.weixin4j.util.DateUtil; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Date; + +/** + * 订单信息 + * + * @className PayPackage + * @author jinyu(foxinmy@gmail.com) + * @date 2014年12月18日 + * @since JDK 1.6 + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class PayPackage extends MerchantResult { + + private static final long serialVersionUID = 3450161267802545790L; + + /** + * 商品描述 必须 + */ + private String body; + /** + * 商品详情 非必须 + */ + private String detail; + /** + * 商户系统内部的订单号 ,32 个字符内 、可包含字母 ,确保 在商户系统唯一 必须 + */ + @XmlElement(name = "out_trade_no") + @JSONField(name = "out_trade_no") + private String outTradeNo; + /** + * 订单总金额,单位为分,不能带小数点 必须 + */ + @XmlElement(name = "total_fee") + @JSONField(name = "total_fee") + private int totalFee; + /** + * 通知地址接收微信支付成功通知 必须 + */ + @XmlElement(name = "notify_url") + @JSONField(name = "notify_url") + private String notifyUrl; + /** + * 订单生成的机器 IP 必须 + */ + @XmlElement(name = "spbill_create_ip") + @JSONField(name = "spbill_create_ip") + private String createIp; + /** + * 附加数据,原样返回 非必须 + */ + private String attach; + /** + * 订单生成时间,格式为 yyyyMMddHHmmss,如 2009 年 12月25日9点10分10秒表示为 20091225091010。时区 为 + * GMT+8 beijing。该时间取 自商户服务器 非必须 + */ + @XmlElement(name = "time_start") + @JSONField(name = "time_start") + private String timeStart; + /** + * 订单失效时间,格为 yyyyMMddHHmmss,如 2009 年 12月27日9点10分10秒表示为 20091227091010。时区 为 + * GMT+8 beijing。该时间取 自商户服务商品标记 非必须 + */ + @XmlElement(name = "time_expire") + @JSONField(name = "time_expire") + private String timeExpire; + /** + * 商品标记,该字段不能随便填,不使用请填空 非必须 + */ + @XmlElement(name = "goods_tag") + @JSONField(name = "goods_tag") + private String goodsTag; + + protected PayPackage() { + // jaxb required + } + + /** + * 订单对象 + * + * @param body + * 订单描述 必填 + * @param detail + * 订单详情 非必填 + * @param outTradeNo + * 商户内部ID 必填 + * @param totalFee + * 订单总额 必填 单位为元 + * @param notifyUrl + * 回调地址 必填 + * @param createIp + * 生成订单数据的机器IP 必填 + * @param attach + * 附加数据 非必填 + * @param timeStart + * 订单生成时间 非必填 + * @param timeExpire + * 订单失效时间 非必填 + * @param goodsTag + * 订单标记 非必填 + */ + public PayPackage(String body, String detail, String outTradeNo, + double totalFee, String notifyUrl, String createIp, String attach, + Date timeStart, Date timeExpire, String goodsTag) { + this.body = body; + this.detail = detail; + this.outTradeNo = outTradeNo; + this.totalFee = DateUtil.formatYuan2Fen(totalFee); + this.notifyUrl = notifyUrl; + this.createIp = createIp; + this.attach = attach; + this.timeStart = timeStart != null ? DateUtil + .fortmat2yyyyMMddHHmmss(timeStart) : null; + this.timeExpire = timeExpire != null ? DateUtil + .fortmat2yyyyMMddHHmmss(timeExpire) : null; + this.goodsTag = goodsTag; + } + + /** + * 订单对象 + * + * @param body + * 订单描述 必填 + * @param detail + * 订单详情 非必填 + * @param outTradeNo + * 商户内部ID 必填 + * @param totalFee + * 订单总额 必填 单位为分 + * @param notifyUrl + * 回调地址 必填 + * @param createIp + * 生成订单数据的机器IP 必填 + * @param attach + * 附加数据 非必填 + * @param timeStart + * 订单生成时间 非必填 + * @param timeExpire + * 订单失效时间 非必填 + * @param goodsTag + * 订单标记 非必填 + */ + public PayPackage(String body, String detail, String outTradeNo, + long totalFee, String notifyUrl, String createIp, String attach, + Date timeStart, Date timeExpire, String goodsTag) { + this.body = body; + this.detail = detail; + this.outTradeNo = outTradeNo; + this.totalFee = Long.valueOf(totalFee).intValue(); + this.notifyUrl = notifyUrl; + this.createIp = createIp; + this.attach = attach; + this.timeStart = timeStart != null ? DateUtil + .fortmat2yyyyMMddHHmmss(timeStart) : null; + this.timeExpire = timeExpire != null ? DateUtil + .fortmat2yyyyMMddHHmmss(timeExpire) : null; + this.goodsTag = goodsTag; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getDetail() { + return detail; + } + + public void setDetail(String detail) { + this.detail = detail; + } + + public String getOutTradeNo() { + return outTradeNo; + } + + public void setOutTradeNo(String outTradeNo) { + this.outTradeNo = outTradeNo; + } + + public int getTotalFee() { + return totalFee; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatTotalFee() { + return totalFee / 100d; + } + + /** + * 单位为元,自动格式化为分 + * + * @param totalFee + * 订单总额 单位为元 + */ + public void setTotalFee(double totalFee) { + this.totalFee = DateUtil.formatYuan2Fen(totalFee); + } + + public String getNotifyUrl() { + return notifyUrl; + } + + public void setNotifyUrl(String notifyUrl) { + this.notifyUrl = notifyUrl; + } + + public String getCreateIp() { + return createIp; + } + + public void setCreateIp(String createIp) { + this.createIp = createIp; + } + + public String getAttach() { + return attach; + } + + public void setAttach(String attach) { + this.attach = attach; + } + + public String getTimeStart() { + return timeStart; + } + + public void setTimeStart(String timeStart) { + this.timeStart = timeStart; + } + + public void setTimeExpire(String timeExpire) { + this.timeExpire = timeExpire; + } + + public void setTimeStart(Date timeStart) { + this.timeStart = timeStart != null ? DateUtil + .fortmat2yyyyMMddHHmmss(timeStart) : null; + } + + public String getTimeExpire() { + return timeExpire; + } + + public void setTimeExpire(Date timeExpire) { + this.timeExpire = timeExpire != null ? DateUtil + .fortmat2yyyyMMddHHmmss(timeExpire) : null; + } + + public String getGoodsTag() { + return goodsTag; + } + + public void setGoodsTag(String goodsTag) { + this.goodsTag = goodsTag; + } + + @Override + public String toString() { + return "body=" + body + ", detail=" + detail + ", outTradeNo=" + + outTradeNo + ", totalFee=" + totalFee + ", notifyUrl=" + + notifyUrl + ", createIp=" + createIp + ", attach=" + attach + + ", timeStart=" + timeStart + ", timeExpire=" + timeExpire + + ", goodsTag=" + goodsTag; + } +} \ No newline at end of file diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/PayRequest.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/PayRequest.java new file mode 100644 index 00000000..365bf49c --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/PayRequest.java @@ -0,0 +1,75 @@ +package com.foxinmy.weixin4j.pay.payment; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.util.DateUtil; +import com.foxinmy.weixin4j.util.RandomUtil; + +import javax.xml.bind.annotation.*; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class PayRequest extends PayBaseInfo { + + private static final long serialVersionUID = -453746488398523883L; + + /** + * 订单详情扩展 订单信息组成该字符串 + */ + @XmlElement(name = "Package") + @JSONField(name = "package") + private String packageInfo; + + /** + * 冗余字段 + */ + @XmlTransient + @JSONField(serialize = false) + private String prepayId; + /** + * 冗余字段 + */ + @XmlTransient + @JSONField(serialize = false) + private String partnerId; + + + protected PayRequest() { + // jaxb required + } + + public PayRequest(String appId, String packageInfo) { + super(appId, DateUtil.timestamp2string(), RandomUtil.generateString(16)); + this.packageInfo = packageInfo; + } + + public String getPackageInfo() { + return packageInfo; + } + + public void setPackageInfo(String packageInfo) { + this.packageInfo = packageInfo; + } + + public String getPrepayId() { + return prepayId; + } + + public void setPrepayId(String prepayId) { + this.prepayId = prepayId; + } + + public String getPartnerId() { + return partnerId; + } + + public void setPartnerId(String partnerId) { + this.partnerId = partnerId; + } + + + @Override + public String toString() { + return "package" + packageInfo + ", prepayId=" + prepayId + + super.toString(); + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/coupon/CouponDetail.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/coupon/CouponDetail.java new file mode 100644 index 00000000..949e02bb --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/coupon/CouponDetail.java @@ -0,0 +1,377 @@ +package com.foxinmy.weixin4j.pay.payment.coupon; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.pay.payment.mch.MerchantResult; +import com.foxinmy.weixin4j.pay.type.mch.CouponStatus; +import com.foxinmy.weixin4j.pay.type.mch.CouponStockType; +import com.foxinmy.weixin4j.pay.type.mch.CouponType; +import com.foxinmy.weixin4j.util.DateUtil; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Date; + +/** + * 代金券详细 + * + * @className CouponDetail + * @author jinyu(foxinmy@gmail.com) + * @date 2015年3月27日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class CouponDetail extends MerchantResult { + + private static final long serialVersionUID = -311265355895457070L; + + /** + * 代金券批次Id + */ + @XmlElement(name = "coupon_stock_id") + @JSONField(name = "coupon_stock_id") + private String couponStockId; + + /** + * 批次类型;1-批量型,2-触发型 + */ + @XmlElement(name = "coupon_stock_type") + @JSONField(name = "coupon_stock_type") + private int couponStockType; + + /** + * 代金券id + */ + @XmlElement(name = "coupon_id") + @JSONField(name = "coupon_id") + private String couponId; + /** + * 代金券面值,单位是分 + */ + @XmlElement(name = "coupon_value") + @JSONField(name = "coupon_value") + private int couponValue; + + /** + * 代金券使用最低限额,单位是分 + */ + @XmlElement(name = "coupon_mininum") + @JSONField(name = "coupon_mininum") + private int couponMininum; + /** + * 代金券名称 + */ + @XmlElement(name = "coupon_name") + @JSONField(name = "coupon_name") + private String couponName; + /** + * 代金券状态:2-已激活,4-已锁定,8-已实扣 + */ + @XmlElement(name = "coupon_state") + @JSONField(name = "coupon_state") + private int couponStatus; + /** + * 代金券类型:1-代金券无门槛,2-代金券有门槛互斥,3-代金券有门槛叠加, + */ + @XmlElement(name = "coupon_type") + @JSONField(name = "coupon_type") + private int couponType; + /** + * 代金券描述 + */ + @XmlElement(name = "coupon_desc") + @JSONField(name = "coupon_desc") + private String couponDesc; + + /** + * 代金券实际使用金额 + */ + @XmlElement(name = "coupon_use_value") + @JSONField(name = "coupon_use_value") + private int couponUseValue; + + /** + * 代金券剩余金额:部分使用情况下,可能会存在券剩余金额 + */ + @XmlElement(name = "coupon_remain_value") + @JSONField(name = "coupon_remain_value") + private int couponRemainValue; + + /** + * 生效开始时间:格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。 + */ + @XmlElement(name = "begin_time") + @JSONField(name = "begin_time") + private String beginTime; + + /** + * 生效结束时间:格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。 + */ + @XmlElement(name = "end_time") + @JSONField(name = "end_time") + private String endTime; + + /** + * 发放时间:格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。 + */ + @XmlElement(name = "send_time") + @JSONField(name = "send_time") + private String sendTime; + + /** + * 使用时间:格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。 + */ + @XmlElement(name = "use_time") + @JSONField(name = "use_time") + private String useTime; + + /** + * 使用单号:代金券使用后,关联的大单收单单号 + */ + @XmlElement(name = "trade_no") + @JSONField(name = "trade_no") + private String tradeNo; + + /** + * 消耗方商户id:代金券使用后,消耗方商户id + */ + @XmlElement(name = "consumer_mch_id") + @JSONField(name = "consumer_mch_id") + private String consumerMchId; + + /** + * 消耗方商户名称:代金券使用后,消耗方商户名称 + */ + @XmlElement(name = "consumer_mch_name") + @JSONField(name = "consumer_mch_name") + private String consumerMchName; + + /** + * 消耗方商户appid:代金券使用后,消耗方商户appid + */ + @XmlElement(name = "consumer_mch_appid") + @JSONField(name = "consumer_mch_appid") + private String consumerMchAppid; + + /** + * 发放来源:代金券发放来源 + */ + @XmlElement(name = "send_source") + @JSONField(name = "send_source") + private String sendSource; + + /** + * 是否允许部分使用:该代金券是否允许部分使用标识:1-表示支持部分使用 + */ + @XmlElement(name = "is_partial_use") + @JSONField(name = "is_partial_use") + private int isPartialUse; + + public CouponDetail() { + + } + + public String getCouponStockId() { + return couponStockId; + } + + public int getCouponStockType() { + return couponStockType; + } + + @JSONField(serialize = false) + public CouponStockType getFormatCouponStockType() { + for (CouponStockType couponStockType : CouponStockType.values()) { + if (couponStockType.getVal() == this.couponStockType) { + return couponStockType; + } + } + return null; + } + + public String getCouponId() { + return couponId; + } + + public int getCouponValue() { + return couponValue; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatCouponValue() { + return couponValue / 100d; + } + + public int getCouponMininum() { + return couponMininum; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatCouponMininum() { + return couponMininum / 100d; + } + + public String getCouponName() { + return couponName; + } + + public int getCouponStatus() { + return couponStatus; + } + + @JSONField(serialize = false) + public CouponStatus getFormatCouponStatus() { + for (CouponStatus couponStatus : CouponStatus.values()) { + if (couponStatus.getVal() == this.couponStatus) { + return couponStatus; + } + } + return null; + } + + public int getCouponType() { + return couponType; + } + + @JSONField(deserialize = false, serialize = false) + public CouponType getFormatCouponType() { + for (CouponType couponType : CouponType.values()) { + if (couponType.getVal() == this.couponType) { + return couponType; + } + } + return null; + } + + public String getCouponDesc() { + return couponDesc; + } + + public int getCouponUseValue() { + return couponUseValue; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatCouponUseValue() { + return couponUseValue / 100d; + } + + public int getCouponRemainValue() { + return couponRemainValue; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatCouponRemainValue() { + return couponRemainValue / 100d; + } + + public String getBeginTime() { + return beginTime; + } + + @JSONField(serialize = false) + public Date getFormatBeginTime() { + return beginTime != null ? DateUtil.parse2yyyyMMddHHmmss(beginTime) + : null; + } + + public String getEndTime() { + return endTime; + } + + @JSONField(serialize = false) + public Date getFormatEndTime() { + return endTime != null ? DateUtil.parse2yyyyMMddHHmmss(endTime) : null; + } + + public String getSendTime() { + return sendTime; + } + + @JSONField(serialize = false) + public Date getFormatSendTime() { + return sendTime != null ? DateUtil.parse2yyyyMMddHHmmss(sendTime) + : null; + } + + public String getUseTime() { + return useTime; + } + + @JSONField(serialize = false) + public Date getFormatUseTime() { + return useTime != null ? DateUtil.parse2yyyyMMddHHmmss(useTime) : null; + } + + public String getTradeNo() { + return tradeNo; + } + + public String getConsumerMchId() { + return consumerMchId; + } + + public String getConsumerMchName() { + return consumerMchName; + } + + public String getConsumerMchAppid() { + return consumerMchAppid; + } + + public String getSendSource() { + return sendSource; + } + + public int getIsPartialUse() { + return isPartialUse; + } + + @JSONField(serialize = false) + public boolean getFormatIsPartialUse() { + return isPartialUse == 1; + } + + @Override + public String toString() { + return "CouponDetail [couponStockId=" + couponStockId + + ", couponStockType=" + getFormatCouponStockType() + + ", couponId=" + couponId + ", couponValue=" + + getFormatCouponValue() + ", couponMininum=" + + getFormatCouponMininum() + ", couponName=" + couponName + + ", couponStatus=" + getCouponStatus() + ", couponType=" + + getFormatCouponType() + ", couponDesc=" + couponDesc + + ", couponUseValue=" + getFormatCouponUseValue() + + ", couponRemainValue=" + getFormatCouponRemainValue() + + ", beginTime=" + getFormatBeginTime() + ", endTime=" + + getFormatEndTime() + ", sendTime=" + getFormatSendTime() + + ", useTime=" + getFormatUseTime() + ", tradeNo=" + tradeNo + + ", consumerMchId=" + consumerMchId + ", consumerMchName=" + + consumerMchName + ", consumerMchAppid=" + consumerMchAppid + + ", sendSource=" + sendSource + ", isPartialUse=" + + getFormatIsPartialUse() + ", " + super.toString() + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/coupon/CouponResult.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/coupon/CouponResult.java new file mode 100644 index 00000000..afe82022 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/coupon/CouponResult.java @@ -0,0 +1,119 @@ +package com.foxinmy.weixin4j.pay.payment.coupon; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.pay.payment.mch.MerchantResult; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * 代金券发放结果 + * + * @className CouponResult + * @author jinyu(foxinmy@gmail.com) + * @date 2015年3月25日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class CouponResult extends MerchantResult { + + private static final long serialVersionUID = -1996967923720149124L; + + /** + * 代金券批次id + */ + @XmlElement(name = "coupon_stock_id") + @JSONField(name = "coupon_stock_id") + private String couponStockId; + /** + * 返回记录数 + */ + @XmlElement(name = "resp_count") + @JSONField(name = "resp_count") + private int responseCount; + /** + * 成功记录数 + */ + @XmlElement(name = "success_count") + @JSONField(name = "success_count") + private int successCount; + /** + * 失败记录数 + */ + @XmlElement(name = "failed_count") + @JSONField(name = "failed_count") + private int failedCount; + /** + * 用户在商户appid下的唯一标识 + */ + @XmlElement(name = "openid") + @JSONField(name = "openid") + private String openId; + /** + * 返回码 SUCCESS或者FAILED + */ + @XmlElement(name = "ret_code") + @JSONField(name = "ret_code") + private String retCode; + /** + * 代金券id + */ + @XmlElement(name = "coupon_id") + @JSONField(name = "coupon_id") + private String couponId; + /** + * 失败描述信息,例如:“用户已达领用上限” + */ + @XmlElement(name = "ret_msg") + @JSONField(name = "ret_msg") + private String retMsg; + + public CouponResult() { + + } + + public String getCouponStockId() { + return couponStockId; + } + + public int getResponseCount() { + return responseCount; + } + + public int getSuccessCount() { + return successCount; + } + + public int getFailedCount() { + return failedCount; + } + + public String getOpenId() { + return openId; + } + + public String getRetCode() { + return retCode; + } + + public String getCouponId() { + return couponId; + } + + public String getRetMsg() { + return retMsg; + } + + @Override + public String toString() { + return "CouponResult [couponStockId=" + couponStockId + + ", responseCount=" + responseCount + ", successCount=" + + successCount + ", failedCount=" + failedCount + ", openId=" + + openId + ", retCode=" + retCode + ", couponId=" + couponId + + ", retMsg=" + retMsg + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/coupon/CouponStock.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/coupon/CouponStock.java new file mode 100644 index 00000000..d1d2be64 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/coupon/CouponStock.java @@ -0,0 +1,307 @@ +package com.foxinmy.weixin4j.pay.payment.coupon; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.pay.payment.mch.MerchantResult; +import com.foxinmy.weixin4j.pay.type.mch.CouponStockStatus; +import com.foxinmy.weixin4j.pay.type.mch.CouponType; +import com.foxinmy.weixin4j.util.DateUtil; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Date; + +/** + * 代金券信息 + * + * @className CouponStock + * @author jinyu(foxinmy@gmail.com) + * @date 2015年3月27日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class CouponStock extends MerchantResult { + + private static final long serialVersionUID = -8627202879200080499L; + + /** + * 代金券批次ID + */ + @XmlElement(name = "coupon_stock_id") + @JSONField(name = "coupon_stock_id") + private String couponStockId; + /** + * 代金券名称 + */ + @XmlElement(name = "coupon_name") + @JSONField(name = "coupon_name") + private String couponName; + /** + * 代金券面额 + */ + @XmlElement(name = "coupon_value") + @JSONField(name = "coupon_value") + private int couponValue; + /** + * 代金券使用最低限额 + */ + @XmlElement(name = "coupon_mininumn") + @JSONField(name = "coupon_mininumn") + private Integer couponMininumn; + /** + * 代金券类型:1-代金券无门槛,2-代金券有门槛互斥,3-代金券有门槛叠加 + */ + @XmlElement(name = "coupon_type") + @JSONField(name = "coupon_type") + private int couponType; + /** + * 批次状态: 1-未激活;2-审批中;4-已激活;8-已作废;16-中止发放; + */ + @XmlElement(name = "coupon_stock_status") + @JSONField(name = "coupon_stock_status") + private int couponStockStatus; + /** + * 代金券数量 + */ + @XmlElement(name = "coupon_total") + @JSONField(name = "coupon_total") + private int couponTotal; + /** + * 代金券每个人最多能领取的数量, 如果为0,则表示没有限制 + */ + @XmlElement(name = "max_quota") + @JSONField(name = "max_quota") + private Integer maxQuota; + /** + * 代金券锁定数量 + */ + @XmlElement(name = "locked_num") + @JSONField(name = "locked_num") + private Integer lockedNum; + /** + * 代金券已使用数量 + */ + @XmlElement(name = "used_num") + @JSONField(name = "used_num") + private Integer usedNum; + /** + * 代金券已经发送的数量 + */ + @XmlElement(name = "is_send_num") + @JSONField(name = "is_send_num") + private Integer sendNum; + /** + * 生效开始时间 格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。 + */ + @XmlElement(name = "begin_time") + @JSONField(name = "begin_time") + private String beginTime; + /** + * 生效结束时间 格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。 + */ + @XmlElement(name = "end_time") + @JSONField(name = "end_time") + private String endTime; + /** + * 创建时间 格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。 + */ + @XmlElement(name = "create_time") + @JSONField(name = "create_time") + private String createTime; + /** + * 代金券预算额度 + */ + @XmlElement(name = "coupon_budget") + @JSONField(name = "coupon_budget") + private Integer couponBudget; + + public CouponStock() { + + } + + public String getCouponStockId() { + return couponStockId; + } + + public String getCouponName() { + return couponName; + } + + public int getCouponValue() { + return couponValue; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatCouponValue() { + return couponValue / 100d; + } + + public Integer getCouponMininumn() { + return couponMininumn; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatCouponMininumn() { + return couponMininumn != null ? couponMininumn.intValue() / 100d : 0d; + } + + public int getCouponType() { + return couponType; + } + + @JSONField(serialize = false) + public CouponType getFormatCouponType() { + for (CouponType couponType : CouponType.values()) { + if (couponType.getVal() == this.couponType) { + return couponType; + } + } + return null; + } + + public int getCouponStockStatus() { + return couponStockStatus; + } + + @JSONField(serialize = false) + public CouponStockStatus getFormatCouponStockStatus() { + for (CouponStockStatus couponStockStatus : CouponStockStatus.values()) { + if (couponStockStatus.getVal() == this.couponStockStatus) { + return couponStockStatus; + } + } + return null; + } + + public int getCouponTotal() { + return couponTotal; + } + + public Integer getMaxQuota() { + return maxQuota; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatMaxQuota() { + return maxQuota != null ? maxQuota.intValue() / 100d : 0d; + } + + public Integer getLockedNum() { + return lockedNum; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatLockedNum() { + return lockedNum != null ? lockedNum.intValue() / 100d : 0d; + } + + public Integer getUsedNum() { + return usedNum; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatUsedNum() { + return usedNum != null ? usedNum.intValue() / 100d : 0d; + } + + public Integer getSendNum() { + return sendNum; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatSendNum() { + return sendNum != null ? sendNum.intValue() / 100d : 0d; + } + + public String getBeginTime() { + return beginTime; + } + + @JSONField(serialize = false) + public Date getFormatBeginTime() { + return beginTime != null ? DateUtil.parse2yyyyMMddHHmmss(beginTime) + : null; + } + + public String getEndTime() { + return endTime; + } + + @JSONField(serialize = false) + public Date getFormatEndTime() { + return endTime != null ? DateUtil.parse2yyyyMMddHHmmss(endTime) : null; + } + + public String getCreateTime() { + return createTime; + } + + @JSONField(serialize = false) + public Date getFormatCreateTime() { + return createTime != null ? DateUtil.parse2yyyyMMddHHmmss(createTime) + : null; + } + + public Integer getCouponBudget() { + return couponBudget; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatCouponBudget() { + return couponBudget != null ? couponBudget.intValue() / 100d : 0d; + } + + @Override + public String toString() { + return "CouponDetail [couponStockId=" + couponStockId + ", couponName=" + + couponName + ", couponValue=" + getFormatCouponValue() + + ", couponMininumn=" + getFormatCouponMininumn() + + ", couponType=" + getFormatCouponType() + + ", couponStockStatus=" + getFormatCouponStockStatus() + + ", couponTotal=" + couponTotal + ", maxQuota=" + + getFormatMaxQuota() + ", lockedNum=" + getFormatLockedNum() + + ", usedNum=" + getFormatUsedNum() + ", sendNum=" + + getFormatSendNum() + ", beginTime=" + beginTime + + ", endTime=" + endTime + ", createTime=" + createTime + + ", couponBudget=" + getFormatCouponBudget() + ", " + + super.toString() + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/coupon/OrderCouponInfo.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/coupon/OrderCouponInfo.java new file mode 100644 index 00000000..eb53a222 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/coupon/OrderCouponInfo.java @@ -0,0 +1,95 @@ +package com.foxinmy.weixin4j.pay.payment.coupon; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.pay.type.mch.CouponType; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; + +/** + * 订单代金券信息 + * + * @className OrderCouponInfo + * @author jinyu(foxinmy@gmail.com) + * @date 2015年3月24日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class OrderCouponInfo implements Serializable { + + private static final long serialVersionUID = -8744999305258786901L; + + /** + * 代金券或立减优惠批次ID + */ + @XmlElement(name = "coupon_batch_id") + @JSONField(name = "coupon_batch_id") + private String couponBatchId; + /** + * 代金券类型 + * + * @see CouponType + */ + @XmlElement(name = "coupon_type") + @JSONField(name = "coupon_type") + private String couponType; + /** + * 代金券或立减优惠ID + */ + @XmlElement(name = "coupon_id") + @JSONField(name = "coupon_id") + private String couponId; + /** + * 单个代金券或立减优惠支付金额 + */ + @XmlElement(name = "coupon_fee") + @JSONField(name = "coupon_fee") + private Integer couponFee; + + protected OrderCouponInfo() { + // jaxb requried + } + + public String getCouponBatchId() { + return couponBatchId; + } + + public String getCouponType() { + return couponType; + } + + @JSONField(serialize = false) + public CouponType getFormatCouponType() { + return couponType != null ? CouponType + .valueOf(couponType.toUpperCase()) : null; + } + + public String getCouponId() { + return couponId; + } + + public Integer getCouponFee() { + return couponFee; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatCouponFee() { + return couponFee != null ? couponFee.doubleValue() / 100d : 0d; + } + + @Override + public String toString() { + return "couponBatchId=" + couponBatchId + ", couponType=" + couponType + + ", couponId=" + couponId + ", couponFee=" + couponFee; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/coupon/RefundCouponInfo.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/coupon/RefundCouponInfo.java new file mode 100644 index 00000000..796bea15 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/coupon/RefundCouponInfo.java @@ -0,0 +1,76 @@ +package com.foxinmy.weixin4j.pay.payment.coupon; + +import com.alibaba.fastjson.annotation.JSONField; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; + +/** + * 退款代金券信息 + * + * @className RefundCouponInfo + * @author jinyu(foxinmy@gmail.com) + * @date 2015年3月24日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RefundCouponInfo implements Serializable { + + private static final long serialVersionUID = -8744999305258786901L; + + /** + * 代金券或立减优惠批次ID + */ + @XmlElement(name = "coupon_refund_batch_id") + @JSONField(name = "coupon_refund_batch_id") + private String couponBatchId; + /** + * 退款代金券ID + */ + @XmlElement(name = "coupon_refund_id") + @JSONField(name = "coupon_refund_id") + private String couponId; + /** + * 单个代金券或立减优惠支付金额 + */ + @XmlElement(name = "coupon_refund_fee") + @JSONField(name = "coupon_refund_fee") + private Integer couponFee; + + protected RefundCouponInfo() { + // jaxb requried + } + + public String getCouponBatchId() { + return couponBatchId; + } + + public String getCouponId() { + return couponId; + } + + public Integer getCouponFee() { + return couponFee; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatCouponFee() { + return couponFee != null ? couponFee.doubleValue() / 100d : 0d; + } + + @Override + public String toString() { + return "couponBatchId=" + couponBatchId + ", couponId=" + couponId + + ", couponFee=" + couponFee; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/face/PayfaceAuthinfo.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/face/PayfaceAuthinfo.java new file mode 100644 index 00000000..2fdd46bf --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/face/PayfaceAuthinfo.java @@ -0,0 +1,44 @@ +package com.foxinmy.weixin4j.pay.payment.face; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.pay.payment.mch.MerchantResult; + +import javax.xml.bind.annotation.XmlElement; + +/** + * 微信刷脸支付交互流程--获取调用凭证(get_wxpayface_authinfo)接口响应结果 + * + * @className PayfaceAuthinfo + * @author kit(kit_21cn@21cn.com) + * @date 2019年9月17日 + * @since JDK 1.6 + * @see + */ +public class PayfaceAuthinfo extends MerchantResult { + /** + * authinfo的有效时间, 单位秒。 例如: 3600 + * 在有效时间内, 对于同一台终端设备,相同的参数的前提下(如:相同的公众号、商户号、 门店编号等),可以用同一个authinfo, + * 多次调用SDK的getWxpayfaceCode接口。 + * + * @see + * 人脸支付凭证(getWxpayfaceCode) + */ + @JSONField(name = "expires_in") + @XmlElement(name = "expires_in") + private int expiresIn; + /** + * SDK调用凭证。用于调用SDK的人脸识别接口。 + * + * @see + * 人脸支付凭证(getWxpayfaceCode) + */ + private String authinfo; + + @Override + public String toString() { + return "PayfaceAuthinfo{" + + "expiresIn=" + expiresIn + + ", authinfo='" + authinfo + '\'' + + '}'; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/face/PayfaceAuthinfoRequest.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/face/PayfaceAuthinfoRequest.java new file mode 100644 index 00000000..6a3c27e1 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/face/PayfaceAuthinfoRequest.java @@ -0,0 +1,96 @@ +package com.foxinmy.weixin4j.pay.payment.face; + +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.sign.WeixinPaymentSignature; +import com.foxinmy.weixin4j.pay.type.SignType; +import com.foxinmy.weixin4j.util.*; +import com.foxinmy.weixin4j.xml.XmlStream; + +import java.util.HashMap; +import java.util.Map; + +/** + * 微信刷脸支付, 获取调用凭证(get_wxpayface_authinfo)API接口请求参数封装 + * + * @className PayfaceAuthinfoRequest + * @author kit(kit_21cn@21cn.com) + * @date 2019年9月18日 + * @since JDK 1.6 + * @see + * 获取调用凭证-get-wxpayface-authinfo + */ +public class PayfaceAuthinfoRequest { + private WeixinPayAccount payAccount; + /** + * 门店编号, 由商户定义, 各门店唯一。 + */ + private String storeId; + /** + * 门店名称,由商户定义。(可用于展示) + */ + private String storeName; + /** + * 终端设备编号,由商户定义。 + */ + private String deviceId; + /** + * 附加字段。字段格式使用Json + */ + private String attach; + + private String nonceStr = RandomUtil.generateString(16); + + private String now = DateUtil.timestamp2string(); + /** + * 初始化数据。由微信人脸SDK的接口返回。 + * + * @see + * * 获取数据-getwxpayfacerawdata + */ + private String rawdata; + + private WeixinPaymentSignature paymentSignature; + + public PayfaceAuthinfoRequest(WeixinPayAccount account, String storeId, String storeName, String deviceId, + String attach, String rawdata){ + this.payAccount = account; + this.deviceId = deviceId; + this.rawdata = rawdata; + this.storeId = storeId; + this.storeName = storeName; + this.attach = attach; + this.paymentSignature = new WeixinPaymentSignature(account.getPaySignKey()); + } + + public String toRequestString(){ + Map paramsMap = getRequestParam(); + return XmlStream.map2xml(paramsMap); + } + + private Map getRequestParam(){ + Map map = new HashMap(); + map.put("appid", payAccount.getId()); + map.put("mch_id", payAccount.getMchId()); + if(StringUtil.isNotBlank(payAccount.getSubId())) { + map.put("sub_appid", payAccount.getSubId()); + } + if(StringUtil.isNotBlank(payAccount.getSubMchId())){ + map.put("sub_mch_id", payAccount.getSubMchId()); + } + map.put("now", now); + map.put("version", "1"); + map.put("sign_type", SignType.MD5.name()); + map.put("nonce_str", nonceStr); + map.put("store_id", storeId); + map.put("store_name", storeName); + map.put("device_id", deviceId); + map.put("rawdata", rawdata); + if(StringUtil.isNotBlank(attach)) { + map.put("attach", attach); + } + String sign = paymentSignature.sign(map); + map.put("sign", sign); + + return map; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/APPPayRequest.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/APPPayRequest.java new file mode 100644 index 00000000..c531ec78 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/APPPayRequest.java @@ -0,0 +1,74 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.payment.PayRequest; +import com.foxinmy.weixin4j.pay.type.SignType; +import com.foxinmy.weixin4j.pay.type.TradeType; +import com.foxinmy.weixin4j.util.DigestUtil; +import com.foxinmy.weixin4j.util.MapUtil; + +import java.util.HashMap; +import java.util.Map; + +/** + * APP支付 + * + * @className APPPayRequest + * @author jinyu(foxinmy@gmail.com) + * @date 2015年12月25日 + * @since JDK 1.6 + * @see PrePay + * @see PayRequest + * @see APP支付 + */ +public class APPPayRequest extends AbstractPayRequest { + public APPPayRequest(String prePayId, WeixinPayAccount payAccount) { + super(prePayId, payAccount); + } + + @Override + public TradeType getPaymentType() { + return TradeType.APP; + } + + /** + * 只做查看之用,请不要尝试作为支付请求 + */ + @Override + public PayRequest toRequestObject() { + PayRequest payRequest = new PayRequest(getPaymentAccount().getId(), "Sign=WXPay"); + payRequest.setPartnerId(getPaymentAccount().getMchId()); + payRequest.setPrepayId(getPrePayId()); + Map map = new HashMap(); + map.put("appid", payRequest.getAppId()); + // 因为partnerid和prepayid在PayRequest类中是不进行序列化的 + map.put("partnerid", payRequest.getPartnerId()); + map.put("prepayid", payRequest.getPrepayId()); + map.put("package", payRequest.getPackageInfo()); + map.put("timestamp", payRequest.getTimeStamp()); + map.put("noncestr", payRequest.getNonceStr()); + String sign = DigestUtil.MD5( + String.format("%s&key=%s", MapUtil.toJoinString(map, false, true), getPaymentAccount().getPaySignKey())) + .toUpperCase(); + payRequest.setPaySign(sign); + payRequest.setSignType(SignType.MD5); + return payRequest; + } + + @Override + public String toRequestString() { + PayRequest payRequest = toRequestObject(); + StringBuilder content = new StringBuilder(); + content.append(""); + content.append(String.format("", payRequest.getAppId())); + content.append(String.format("", payRequest.getPartnerId())); + content.append(String.format("", payRequest.getPrepayId())); + content.append(String.format("", payRequest.getPackageInfo())); + content.append(String.format("", payRequest.getNonceStr())); + content.append(String.format("", payRequest.getTimeStamp())); + content.append(String.format("", payRequest.getPaySign())); + content.append(""); + return content.toString(); + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/AbstractPayRequest.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/AbstractPayRequest.java new file mode 100644 index 00000000..77af4ee7 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/AbstractPayRequest.java @@ -0,0 +1,28 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.sign.WeixinPaymentSignature; +import com.foxinmy.weixin4j.pay.sign.WeixinSignature; + +public abstract class AbstractPayRequest implements MchPayRequest { + + private final String prePayId; + private final WeixinPayAccount paymentAccount; + protected final WeixinSignature weixinSignature; + + public AbstractPayRequest(String prePayId, WeixinPayAccount paymentAccount) { + this.prePayId = prePayId; + this.paymentAccount = paymentAccount; + this.weixinSignature = new WeixinPaymentSignature(paymentAccount.getPaySignKey()); + } + + @Override + public String getPrePayId() { + return this.prePayId; + } + + @Override + public WeixinPayAccount getPaymentAccount() { + return this.paymentAccount; + } +} \ No newline at end of file diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CorpPayment.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CorpPayment.java new file mode 100644 index 00000000..b5f5816f --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CorpPayment.java @@ -0,0 +1,147 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.type.mch.CorpPaymentCheckNameType; +import com.foxinmy.weixin4j.util.DateUtil; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * 企业付款 + * + * @className CorpPayment + * @author jinyu(foxinmy@gmail.com) + * @date 2015年4月1日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class CorpPayment extends MerchantResult { + + private static final long serialVersionUID = 3734639674346425312L; + /** + * 商户订单号 + */ + @XmlElement(name = "partner_trade_no") + @JSONField(name = "partner_trade_no") + private String outTradeNo; + /** + * 接收红包的用户的openid + */ + @JSONField(name = "openid") + @XmlElement(name = "openid") + private String openId; + /** + * 校验用户姓名选项 + * + * @see CorpPaymentCheckNameType.type.MPPaymentCheckNameType + */ + @XmlElement(name = "check_name") + @JSONField(name = "check_name") + private CorpPaymentCheckNameType checkNameType; + /** + * 收款用户真实姓名。 如果check_name设置为FORCE_CHECK或OPTION_CHECK,则必填用户真实姓名 可选 + */ + @XmlElement(name = "re_user_name") + @JSONField(name = "re_user_name") + private String userName; + /** + * 企业付款描述信息 + */ + private String desc; + /** + * 付款金额 单位分 + */ + private int amount; + /** + * 调用接口的机器Ip地址 + */ + @XmlElement(name = "spbill_create_ip") + @JSONField(name = "spbill_create_ip") + private String clientIp; + + protected CorpPayment() { + // jaxb required + } + + /** + * 企业付款 + * + * @param outTradeNo + * 商户的订单号 + * @param openId + * 用户的openid + * @param checkNameType + * 校验用户姓名选项 + * @param desc + * 描述 + * @param amount + * 金额 单位元 + * @param clientIp + * 调用接口IP + */ + public CorpPayment(String outTradeNo, String openId, + CorpPaymentCheckNameType checkNameType, String desc, double amount, + String clientIp) { + this.outTradeNo = outTradeNo; + this.openId = openId; + this.checkNameType = checkNameType; + this.desc = desc; + this.amount = DateUtil.formatYuan2Fen(amount); + this.clientIp = clientIp; + } + + public String getOutTradeNo() { + return outTradeNo; + } + + public String getOpenId() { + return openId; + } + + public CorpPaymentCheckNameType getCheckNameType() { + return checkNameType; + } + + public String getUserName() { + return userName; + } + + public String getDesc() { + return desc; + } + + public int getAmount() { + return amount; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatAmount() { + return amount / 100d; + } + + public String getClientIp() { + return clientIp; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + @Override + public String toString() { + return "CorpPayment [outTradeNo=" + outTradeNo + ", openId=" + openId + + ", checkNameType=" + checkNameType + ", userName=" + userName + + ", desc=" + desc + ", amount=" + amount + ", clientIp=" + + clientIp + ", " + super.toString() + "]"; + } +} \ No newline at end of file diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CorpPaymentRecord.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CorpPaymentRecord.java new file mode 100644 index 00000000..5d93cc0a --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CorpPaymentRecord.java @@ -0,0 +1,202 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.type.mch.CorpPaymentCheckNameType; +import com.foxinmy.weixin4j.util.DateUtil; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Date; + +/** + * 企业付款记录 + * + * @className CorpPaymentRecord + * @author jinyu(foxinmy@gmail.com) + * @date 2015年6月23日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class CorpPaymentRecord extends MerchantResult { + + private static final long serialVersionUID = -1926873539419750498L; + + /** + * 微信订单订单号 + */ + @JSONField(name = "detail_id") + @XmlElement(name = "detail_id") + private String transactionId; + /** + * 商户订单号 + */ + @JSONField(name = "partner_trade_no") + @XmlElement(name = "partner_trade_no") + private String outTradeNo; + /** + * 交易状态 SUCCESS:转账成功 FAILED:转账失败 + */ + @JSONField(name = "status") + @XmlElement(name = "status") + private String transactionStatus; + /** + * 如果失败则应该有原因 + */ + @JSONField(name = "reason") + @XmlElement(name = "reason") + private String failureReason; + /** + * 收款用户openid + */ + @JSONField(name = "openid") + @XmlElement(name = "openid") + private String openId; + /** + * 收款用户姓名 + */ + @JSONField(name = "transfer_name") + @XmlElement(name = "transfer_name") + private String transferName; + /** + * 付款金额(单位为分) + */ + @JSONField(name = "payment_amount") + @XmlElement(name = "payment_amount") + private int paymentAmount; + /** + * 转账时间 + */ + @JSONField(name = "transfer_time") + @XmlElement(name = "transfer_time") + private String transferTime; + /** + * 校验用户姓名选项 + * + * @see CorpPaymentCheckNameType.type.MPPaymentCheckNameType + */ + @XmlElement(name = "check_name") + @JSONField(name = "check_name") + private String checkNameType; + /** + * 企业付款描述信息 + */ + @XmlElement(name = "desc") + private String desc; + /** + * 实名验证结果 PASS:通过 FAILED:不通过 + */ + @JSONField(name = "check_name_result") + @XmlElement(name = "check_name_result") + private String checkNameResult; + + protected CorpPaymentRecord() { + // jaxb required + } + + public String getTransactionId() { + return transactionId; + } + + public String getOutTradeNo() { + return outTradeNo; + } + + public String getTransactionStatus() { + return transactionStatus; + } + + /** + * 格式化交易状态 + * + * @return + */ + @JSONField(serialize = false) + public boolean getFormatTransactionStatus() { + return "success".equalsIgnoreCase(transactionStatus); + } + + public String getFailureReason() { + return failureReason; + } + + public String getOpenId() { + return openId; + } + + public String getTransferName() { + return transferName; + } + + public int getPaymentAmount() { + return paymentAmount; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatPaymentAmount() { + return paymentAmount / 100d; + } + + public String getTransferTime() { + return transferTime; + } + + /** + * 格式化转账时间 + * + * @return + */ + @JSONField(serialize = false) + public Date getFormatTransferTime() { + return transferTime != null ? DateUtil + .parse2yyyyMMddHHmmss(transferTime) : null; + } + + public String getCheckNameType() { + return checkNameType; + } + + @JSONField(serialize = false) + public CorpPaymentCheckNameType getFormatCheckNameType() { + return checkNameType != null ? CorpPaymentCheckNameType + .valueOf(checkNameType) : null; + } + + public String getDesc() { + return desc; + } + + public String getCheckNameResult() { + return checkNameResult; + } + + /** + * 格式化交易状态 + * + * @return + */ + @JSONField(serialize = false) + public boolean getFormatCheckNameResult() { + return "pass".equalsIgnoreCase(checkNameResult); + } + + @Override + public String toString() { + return "CorpPaymentRecord [transactionId=" + transactionId + + ", outTradeNo=" + outTradeNo + ", transactionStatus=" + + getFormatTransactionStatus() + ", failureReason=" + + failureReason + ", openId=" + openId + ", transferName=" + + transferName + ", paymentAmount=" + getFormatPaymentAmount() + + ", transferTime=" + transferTime + ", checkNameType=" + + checkNameType + ", desc=" + desc + ", checkNameResult=" + + getFormatCheckNameResult() + ", " + super.toString() + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CorpPaymentResult.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CorpPaymentResult.java new file mode 100644 index 00000000..dc4b67b7 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CorpPaymentResult.java @@ -0,0 +1,74 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.util.DateUtil; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Date; + +/** + * 企业付款结果 + * + * @className CorpPaymentResult + * @author jinyu(foxinmy@gmail.com) + * @date 2015年4月1日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class CorpPaymentResult extends MerchantResult { + + private static final long serialVersionUID = 1110472826089211646L; + + /** + * 微信订单订单号 + */ + @JSONField(name = "payment_no") + @XmlElement(name = "payment_no") + private String transactionId; + /** + * 商户订单号 + */ + @JSONField(name = "partner_trade_no") + @XmlElement(name = "partner_trade_no") + private String outTradeNo; + /** + * 支付时间 + */ + @JSONField(name = "payment_time") + @XmlElement(name = "payment_time") + private String paymentTime; + + protected CorpPaymentResult() { + // jaxb required + } + + public String getTransactionId() { + return transactionId; + } + + public String getOutTradeNo() { + return outTradeNo; + } + + public String getPaymentTime() { + return paymentTime; + } + + @JSONField(serialize = false) + public Date getFormatPaymentTime() { + return paymentTime != null ? DateUtil.parseDate(paymentTime, + "yyyy-MM-dd HH:mm:ss") : null; + } + + @Override + public String toString() { + return "CorpPaymentResult [transactionId=" + transactionId + + ", outTradeNo=" + outTradeNo + ", paymentTime=" + paymentTime + + ", " + super.toString() + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CustomsOrder.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CustomsOrder.java new file mode 100644 index 00000000..e21da276 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CustomsOrder.java @@ -0,0 +1,217 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.type.CredentialType; +import com.foxinmy.weixin4j.type.CurrencyType; +import com.foxinmy.weixin4j.type.CustomsCity; + +import javax.xml.bind.annotation.XmlElement; + +/** + * 报关对象 + * + * @className CustomsOrder + * @author jinyu(foxinmy@gmail.com) + * @date 2016年3月27日 + * @since JDK 1.6 + * @see + */ +public class CustomsOrder extends MerchantResult { + + private static final long serialVersionUID = 799510373861612386L; + /** + * 微信支付订单号 + */ + @XmlElement(name = "transaction_id") + @JSONField(name = "transaction_id") + private String transactionId; + /** + * 商户订单号 + */ + @XmlElement(name = "out_trade_no") + @JSONField(name = "out_trade_no") + private String outTradeNo; + /** + * 商户子订单号,如有拆单则必传 + */ + @XmlElement(name = "sub_order_no") + @JSONField(name = "sub_order_no") + private String subOrderNo; + /** + * 货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY + * + * @see com.foxinmy.weixin4j.mp.type.CurrencyType + */ + @XmlElement(name = "fee_type") + @JSONField(name = "fee_type") + private CurrencyType feeType; + /** + * 子订单金额,以分为单位,不能超过原订单金额,order_fee=transport_fee+product_fee(应付金额=物流费+商品价格), + * 如有拆单则必传。 + */ + @XmlElement(name = "order_fee") + @JSONField(name = "order_fee") + private String orderFee; + /** + * 物流费用,以分为单位,如有拆单则必传。 + */ + @XmlElement(name = "transport_fee") + @JSONField(name = "transport_fee") + private String transportFee; + /** + * 商品费用,以分为单位,如有拆单则必传。 + */ + @XmlElement(name = "product_fee") + @JSONField(name = "product_fee") + private String productFee; + /** + * 关税,以分为单位 + */ + @XmlElement(name = "duty") + @JSONField(name = "duty") + private String dutyFee; + /** + * 海关 + */ + @XmlElement(name = "customs") + @JSONField(name = "customs") + private CustomsCity customsCity; + /** + * 商户在海关登记的备案号,customsCity非NO,此参数必填 + */ + @XmlElement(name = "mch_customs_no") + @JSONField(name = "mch_customs_no") + private String customsNo; + /** + * 证件类型:暂只支持身份证,该参数是指用户信息,商户若有用户信息,可上送,系统将以商户上传的数据为准,进行海关通关报备 + */ + @XmlElement(name = "cert_type") + @JSONField(name = "cert_type") + private CredentialType credentialType; + /** + * 证件号码:身份证号,该参数是指用户信息,商户若有用户信息,可上送,系统将以商户上传的数据为准,进行海关通关报备; + */ + @XmlElement(name = "cert_id") + @JSONField(name = "cert_id") + private String credentialId; + /** + * 用户姓名,该参数是指用户信息,商户若有用户信息,可上送,系统将以商户上传的数据为准,进行海关通关报备; + */ + @XmlElement(name = "name") + @JSONField(name = "name") + private String uname; + + public CustomsOrder(String transactionId, String outTradeNo) { + this.transactionId = transactionId; + this.outTradeNo = outTradeNo; + this.customsCity = CustomsCity.NO; + } + + public String getSubOrderNo() { + return subOrderNo; + } + + public void setSubOrderNo(String subOrderNo) { + this.subOrderNo = subOrderNo; + } + + public CurrencyType getFeeType() { + return feeType; + } + + public void setFeeType(CurrencyType feeType) { + this.feeType = feeType; + } + + public String getOrderFee() { + return orderFee; + } + + public void setOrderFee(String orderFee) { + this.orderFee = orderFee; + } + + public String getTransportFee() { + return transportFee; + } + + public void setTransportFee(String transportFee) { + this.transportFee = transportFee; + } + + public String getProductFee() { + return productFee; + } + + public void setProductFee(String productFee) { + this.productFee = productFee; + } + + public String getDutyFee() { + return dutyFee; + } + + public void setDutyFee(String dutyFee) { + this.dutyFee = dutyFee; + } + + public CustomsCity getCustomsCity() { + return customsCity; + } + + public void setCustomsCity(CustomsCity customsCity) { + this.customsCity = customsCity; + } + + public String getCustomsNo() { + return customsNo; + } + + public void setCustomsNo(String customsNo) { + this.customsNo = customsNo; + } + + public CredentialType getCredentialType() { + return credentialType; + } + + public void setCredentialType(CredentialType credentialType) { + this.credentialType = credentialType; + } + + public String getCredentialId() { + return credentialId; + } + + public void setCredentialId(String credentialId) { + this.credentialId = credentialId; + } + + public String getUname() { + return uname; + } + + public void setUname(String uname) { + this.uname = uname; + } + + public String getTransactionId() { + return transactionId; + } + + public String getOutTradeNo() { + return outTradeNo; + } + + @Override + public String toString() { + return "CustomsOrder [transactionId=" + transactionId + ", outTradeNo=" + + outTradeNo + ", subOrderNo=" + subOrderNo + ", feeType=" + + feeType + ", orderFee=" + orderFee + ", transportFee=" + + transportFee + ", productFee=" + productFee + ", dutyFee=" + + dutyFee + ", customsCity=" + customsCity + ", customsNo=" + + customsNo + ", credentialType=" + credentialType + + ", credentialId=" + credentialId + ", uname=" + uname + ", " + + super.toString() + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CustomsOrderRecord.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CustomsOrderRecord.java new file mode 100644 index 00000000..7daf88a9 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CustomsOrderRecord.java @@ -0,0 +1,72 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.xml.ListsuffixResult; + +import javax.xml.bind.annotation.XmlElement; +import java.util.List; + +/** + * 报关记录 + * + * @className CustomsOrderRecord + * @author jinyu(foxinmy@gmail.com) + * @date 2016年3月27日 + * @since JDK 1.6 + * @see + */ +public class CustomsOrderRecord extends MerchantResult { + + private static final long serialVersionUID = -1675090110657154049L; + /** + * 微信支付订单号 + */ + @XmlElement(name = "transaction_id") + @JSONField(name = "transaction_id") + private String transactionId; + /** + * 笔数 + */ + @XmlElement(name = "count") + @JSONField(name = "count") + private int orderCount; + + /** + * 报关详情 + * + * @see CustomsOrderResult + */ + @ListsuffixResult + private List customsOrderList; + + public String getTransactionId() { + return transactionId; + } + + public void setTransactionId(String transactionId) { + this.transactionId = transactionId; + } + + public int getOrderCount() { + return orderCount; + } + + public void setOrderCount(int orderCount) { + this.orderCount = orderCount; + } + + public List getCustomsOrderList() { + return customsOrderList; + } + + public void setCustomsOrderList(List customsOrderList) { + this.customsOrderList = customsOrderList; + } + + @Override + public String toString() { + return "CustomsOrderRecord [transactionId=" + transactionId + + ", orderCount=" + orderCount + ", customsOrderList=" + + customsOrderList + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CustomsOrderResult.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CustomsOrderResult.java new file mode 100644 index 00000000..ba58c2cf --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/CustomsOrderResult.java @@ -0,0 +1,123 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.type.CustomsSatus; +import com.foxinmy.weixin4j.util.DateUtil; + +import javax.xml.bind.annotation.XmlElement; +import java.util.Date; + +/** + * 报关结果 + * + * @className CustomsOrderResult + * @author jinyu(foxinmy@gmail.com) + * @date 2016年3月27日 + * @since JDK 1.6 + * @see + */ +public class CustomsOrderResult extends MerchantResult { + + private static final long serialVersionUID = 799510373861612386L; + /** + * 状态码 + */ + private String state; + /** + * 微信支付订单号 + */ + @XmlElement(name = "transaction_id") + @JSONField(name = "transaction_id") + private String transactionId; + /** + * 商户订单号 + */ + @XmlElement(name = "out_trade_no") + @JSONField(name = "out_trade_no") + private String outTradeNo; + /** + * 商户子订单号 + */ + @XmlElement(name = "sub_order_no") + @JSONField(name = "sub_order_no") + private String subOrderNo; + /** + * 微信子订单号 + * + */ + @XmlElement(name = "sub_order_id") + @JSONField(name = "sub_order_id") + private String subOrderId; + /** + * 最后更新时间 + */ + @XmlElement(name = "modify_time") + @JSONField(name = "modify_time") + private String modifyTime; + + public String getState() { + return state; + } + + @JSONField(serialize = false) + public CustomsSatus getFormatState() { + return CustomsSatus.valueOf(state.toUpperCase()); + } + + public void setState(String state) { + this.state = state; + } + + public String getTransactionId() { + return transactionId; + } + + public void setTransactionId(String transactionId) { + this.transactionId = transactionId; + } + + public String getOutTradeNo() { + return outTradeNo; + } + + public void setOutTradeNo(String outTradeNo) { + this.outTradeNo = outTradeNo; + } + + public String getSubOrderNo() { + return subOrderNo; + } + + public void setSubOrderNo(String subOrderNo) { + this.subOrderNo = subOrderNo; + } + + public String getSubOrderId() { + return subOrderId; + } + + public void setSubOrderId(String subOrderId) { + this.subOrderId = subOrderId; + } + + public String getModifyTime() { + return modifyTime; + } + + @JSONField(serialize = false) + public Date getFormatModifyTime() { + return DateUtil.parse2yyyyMMddHHmmss(modifyTime); + } + + public void setModifyTime(String modifyTime) { + this.modifyTime = modifyTime; + } + + @Override + public String toString() { + return "CustomsOrderResult [state=" + state + ", transactionId=" + + transactionId + ", outTradeNo=" + outTradeNo + + ", subOrderNo=" + subOrderNo + ", subOrderId=" + subOrderId + + ", modifyTime=" + modifyTime + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/JSAPIPayRequest.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/JSAPIPayRequest.java new file mode 100644 index 00000000..804ba769 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/JSAPIPayRequest.java @@ -0,0 +1,50 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.JSON; +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.payment.PayRequest; +import com.foxinmy.weixin4j.pay.type.SignType; +import com.foxinmy.weixin4j.pay.type.TradeType; + +/** + * 公众号JS支付:get_brand_wcpay_request
+ *

+ * get_brand_wcpay_request:ok 支付成功
+ * get_brand_wcpay_request:cancel 支付过程中用户取消
+ * get_brand_wcpay_request:fail 支付失败 + *

+ * + * @className JSAPIPayRequest + * @author jinyu(foxinmy@gmail.com) + * @date 2015年12月25日 + * @since JDK 1.6 + * @see PrePay + * @see PayRequest + * @see 网页端调起支付API + */ +public class JSAPIPayRequest extends AbstractPayRequest { + + public JSAPIPayRequest(String prePayId, WeixinPayAccount payAccount) { + super(prePayId, payAccount); + } + + @Override + public TradeType getPaymentType() { + return TradeType.JSAPI; + } + + @Override + public PayRequest toRequestObject() { + PayRequest payRequest = new PayRequest(getPaymentAccount().getId(), + "prepay_id=" + getPrePayId()); + payRequest.setSignType(SignType.MD5); + payRequest.setPaySign(weixinSignature.sign(payRequest)); + return payRequest; + } + + @Override + public String toRequestString() { + return JSON.toJSONString(toRequestObject()); + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/MICROPayRequest.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/MICROPayRequest.java new file mode 100644 index 00000000..8bf5d703 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/MICROPayRequest.java @@ -0,0 +1,75 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.payment.PayRequest; +import com.foxinmy.weixin4j.pay.type.TradeType; + +import javax.xml.bind.annotation.XmlTransient; + +/** + * MICROPAY刷卡支付 + * + * @className MICROPayRequest + * @author jinyu(foxinmy@gmail.com) + * @date 2015年12月25日 + * @since JDK 1.6 + * @see PrePay + * @see PayRequest + * @see 刷卡支付 + */ +public class MICROPayRequest extends Order implements MchPayRequest { + + private static final long serialVersionUID = 6147576305404111278L; + + @XmlTransient + @JSONField(serialize = false) + private WeixinPayAccount paymentAccount; + + protected MICROPayRequest() { + // jaxb required + } + + @Override + @JSONField(serialize = false) + public TradeType getPaymentType() { + return TradeType.MICROPAY; + } + + /** + * 返回null,请不要尝试作为支付请求 + */ + @Override + @JSONField(serialize = false) + public String toRequestString() { + return null; + } + + /** + * 返回null,请不要尝试作为支付请求 + */ + @JSONField(serialize = false) + @Override + public PayRequest toRequestObject() { + return null; + } + + /** + * 返回null,请不要尝试作为支付请求 + */ + @JSONField(serialize = false) + @Override + public String getPrePayId() { + return null; + } + + public void setPaymentAccount(WeixinPayAccount paymentAccount) { + this.paymentAccount = paymentAccount; + } + + @Override + public WeixinPayAccount getPaymentAccount() { + return this.paymentAccount; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/MchPayPackage.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/MchPayPackage.java new file mode 100644 index 00000000..1934e8fc --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/MchPayPackage.java @@ -0,0 +1,267 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.pay.payment.PayPackage; +import com.foxinmy.weixin4j.pay.type.CurrencyType; +import com.foxinmy.weixin4j.pay.type.TradeType; +import com.foxinmy.weixin4j.pay.type.mch.DepositType; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Date; + +/** + * 支付订单详情 + * + * @className MchPayPackage + * @author jinyu(foxinmy@gmail.com) + * @date 2014年10月21日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class MchPayPackage extends PayPackage { + + private static final long serialVersionUID = 8944928173669656177L; + + /** + * 交易类型JSAPI、NATIVE、APP 必须 + */ + @XmlElement(name = "trade_type") + @JSONField(name = "trade_type") + private String tradeType; + /** + * 符合ISO 4217标准的三位字母代码,默认人民币:CNY 非必须 + */ + @XmlElement(name = "fee_type") + @JSONField(name = "fee_type") + private String feeType; + /** + * 用户在商户 appid 下的唯一 标识, trade_type 为 JSAPI 时,此参数必传 + */ + @XmlElement(name = "openid") + @JSONField(name = "openid") + private String openId; + + /** + * 只在 trade_type 为 NATIVE 且【模式一】 时需要填写 非必须 + */ + @XmlElement(name = "product_id") + @JSONField(name = "product_id") + private String productId; + + /** + * 扫码支付授权码 ,设备读取用户微信中的条码或者二维码信息 + */ + @XmlElement(name = "auth_code") + @JSONField(name = "auth_code") + private String authCode; + /** + * 指定支付方式:no_credit--指定不能使用信用卡支付 + */ + @XmlElement(name = "limit_pay") + @JSONField(name = "limit_pay") + private String limitPay; + /** + * 服务商下的用户子标识 非必须 + */ + @XmlElement(name = "sub_openid") + @JSONField(name = "sub_openid") + private String subOpenId; + /** + * 场景信息 + */ + @XmlElement(name = "scene_info") + @JSONField(name = "scene_info") + private String sceneInfo; + /** + * 人脸凭证,用于旧版人脸支付。 + */ + @XmlElement(name = "face_code") + @JSONField(name = "face_code") + private String faceCode; + /** + * 是否押金人脸支付,Y-是,N-普通人脸支付 + */ + @XmlElement(name = "deposit") + @JSONField(name = "deposit") + private DepositType deposit; + + protected MchPayPackage() { + // jaxb required + } + + /** + * 微信支付 + * + * @param body + * 支付详情 必填 + * @param outTradeNo + * 商户侧订单号 必填 + * @param totalFee + * 支付金额(单位元) 必填 + * @param notifyUrl + * 支付回调URL 必填 + * @param createIp + * 发起支付的IP地址 必填 + * @param tradeType + * 支付类型 必填 + * @param openId + * 用户唯一标识 公众号JSAPI支付必填 + * @param authCode + * 支付授权码 刷卡MICROPAY支付必填 + * @param productId + * 商品ID 扫码NATIVE支付必填 + * @param attach + * 支付时附加信息 非必填 + */ + public MchPayPackage(String body, String outTradeNo, double totalFee, + String notifyUrl, String createIp, TradeType tradeType, + String openId, String authCode, String productId, String attach) { + this(body, null, outTradeNo, totalFee, CurrencyType.CNY, notifyUrl, + createIp, tradeType, openId, authCode, productId, attach, null, + null, null, null, null, null, null); + } + + /** + * 完整参数 + * + * @param body + * 商品描述 必填项 + * @param detial + * 商品名称明细列表 非必填项 + * @param outTradeNo + * 商户内部唯一订单号 必填项 + * @param totalFee + * 商品总额 单位元 必填项 + * @param notifyUrl + * 支付回调URL 必填项 + * @param createIp + * 订单生成的机器IP 必填项 + * @param tradeType + * 交易类型 必填项 + * @param feeType + * 货币类型 非必填项 + * @param openId + * 用户ID tradeType=JSAPI时必填 + * @param authCode + * 刷卡支付授权码 tradeType=MICROPAY时必填 + * @param productId + * 产品ID tradeType=NATIVE时必填 + * @param attach + * 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据 非必填项 + * @param timeStart + * 订单生成时间,格式为yyyyMMddHHmmss 非必填项 + * @param timeExpire + * 订单失效时间,格式为yyyyMMddHHmmss;注意:最短失效时间间隔必须大于5分钟 非必填项 + * @param goodsTag + * 商品标记,代金券或立减优惠功能的参数 非必填项 + * @param limitPay + * 指定支付方式:no_credit--指定不能使用信用卡支付 非必填项 + * @param subOpenId + * 用户在子商户appid下的唯一标识 非必填 + * openid和sub_openid可以选传其中之一,如果选择传sub_openid ,则必须传sub_appid + * @param faceCode + * 人脸凭证,用于旧版刷脸支付。 + * @param depositType + * 是否押金支付 + */ + public MchPayPackage(String body, String detial, String outTradeNo, + double totalFee, CurrencyType feeType, String notifyUrl, + String createIp, TradeType tradeType, String openId, + String authCode, String productId, String attach, Date timeStart, + Date timeExpire, String goodsTag, String limitPay, String subOpenId, String faceCode, + DepositType depositType) { + super(body, detial, outTradeNo, totalFee, notifyUrl, createIp, attach, + timeStart, timeExpire, goodsTag); + this.tradeType = tradeType != null ? tradeType.name() : null; + this.feeType = feeType == null ? CurrencyType.CNY.name() : feeType + .name(); + this.openId = openId; + this.authCode = authCode; + this.productId = productId; + this.limitPay = limitPay; + this.subOpenId = subOpenId; + this.faceCode = faceCode; + this.deposit = depositType; + } + + public String getTradeType() { + return tradeType; + } + + public String getFeeType() { + return feeType; + } + + public String getOpenId() { + return openId; + } + + public String getAuthCode() { + return authCode; + } + + public String getProductId() { + return productId; + } + + public String getLimitPay() { + return limitPay; + } + + public void setLimitPay(String limitPay) { + this.limitPay = limitPay; + } + + public String getSubOpenId() { + return subOpenId; + } + + public void setSubOpenId(String subOpenId) { + this.subOpenId = subOpenId; + } + + public String getSceneInfo() { + return sceneInfo; + } + + public void setSceneInfo(String sceneInfo) { + this.sceneInfo = sceneInfo; + } + + public String getFaceCode() { + return faceCode; + } + + public void setFaceCode(String faceCode) { + this.faceCode = faceCode; + } + + public DepositType getDeposit() { + return deposit; + } + + public void setDeposit(DepositType deposit) { + this.deposit = deposit; + } + + @Override + public String toString() { + return "MchPayPackage{" + + "tradeType='" + tradeType + '\'' + + ", feeType='" + feeType + '\'' + + ", openId='" + openId + '\'' + + ", productId='" + productId + '\'' + + ", authCode='" + authCode + '\'' + + ", limitPay='" + limitPay + '\'' + + ", subOpenId='" + subOpenId + '\'' + + ", sceneInfo='" + sceneInfo + '\'' + + ", faceCode='" + faceCode + '\'' + + ", deposit=" + deposit + + '}'; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/MchPayRequest.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/MchPayRequest.java new file mode 100644 index 00000000..9bfce2a8 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/MchPayRequest.java @@ -0,0 +1,55 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.payment.PayRequest; +import com.foxinmy.weixin4j.pay.type.TradeType; + +/** + * 支付请求接口 + * + * @className MchPayRequest + * @author jinyu(foxinmy@gmail.com) + * @date 2015年12月25日 + * @since JDK 1.6 + * @see JSAPIPayRequest JS支付 + * @see NATIVEPayRequest 扫码支付 + * @see MICROPayRequest 刷卡支付 + * @see APPPayRequest APP支付 + * @see WAPPayRequest WAP支付 + */ +public interface MchPayRequest { + /** + * 预支付交易ID + * + * @return + */ + public String getPrePayId(); + + /** + * 支付账号 + * + * @return + */ + public WeixinPayAccount getPaymentAccount(); + + /** + * 支付类型 + * + * @return + */ + public TradeType getPaymentType(); + + /** + * 支付请求字符串 + * + * @return + */ + public String toRequestString(); + + /** + * 支付请求对象 + * + * @return + */ + public PayRequest toRequestObject(); +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/MerchantResult.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/MerchantResult.java new file mode 100644 index 00000000..ddebf2e2 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/MerchantResult.java @@ -0,0 +1,170 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.http.weixin.XmlResult; +import com.foxinmy.weixin4j.pay.type.SignType; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * 调用商户平台接口返回的公用字段 + * + * @className MerchantResult + * @author jinyu(foxinmy@gmail.com) + * @date 2014年10月21日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class MerchantResult extends XmlResult { + + private static final long serialVersionUID = -8430005768959715444L; + + /** + * 微信分配的公众账号 ID商户号 非空 + */ + @XmlElement(name = "appid") + @JSONField(name = "appid") + private String appId; + /** + * 微信支付分配的商户号 非空 + */ + @XmlElement(name = "mch_id") + @JSONField(name = "mch_id") + private String mchId; + /** + * 微信分配的子商户公众账号ID 非必须 + */ + @XmlElement(name = "sub_appid") + @JSONField(name = "sub_appid") + private String subAppId; + /** + * 微信支付分配的子商户号 非必须 + */ + @XmlElement(name = "sub_mch_id") + @JSONField(name = "sub_mch_id") + private String subMchId; + /** + * 随机字符串 非空 + */ + @XmlElement(name = "nonce_str") + @JSONField(name = "nonce_str") + private String nonceStr; + /** + * 签名 调用者无需关心 + */ + private String sign; + /** + * 签名类型 默认MD5 + */ + @XmlElement(name = "sign_type") + @JSONField(name = "sign_type") + private String signType; + /** + * 微信支付分配的终端设备号 可能为空 + */ + @XmlElement(name = "device_info") + @JSONField(name = "device_info") + private String deviceInfo; + /** + * 是否需要继续调用接口 Y- 需要,N-不需要 + */ + private String recall; + + protected MerchantResult() { + // jaxb required + } + + public MerchantResult(String returnCode, String returnMsg) { + super(returnCode, returnMsg); + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getMchId() { + return mchId; + } + + public void setMchId(String mchId) { + this.mchId = mchId; + } + + public String getSubAppId() { + return subAppId; + } + + public void setSubAppId(String subAppId) { + this.subAppId = subAppId; + } + + public String getSubMchId() { + return subMchId; + } + + public void setSubMchId(String subMchId) { + this.subMchId = subMchId; + } + + public String getNonceStr() { + return nonceStr; + } + + public void setNonceStr(String nonceStr) { + this.nonceStr = nonceStr; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getSignType() { + return signType; + } + + public void setSignType(String signType) { + this.signType = signType; + } + + public String getDeviceInfo() { + return deviceInfo; + } + + public void setDeviceInfo(String deviceInfo) { + this.deviceInfo = deviceInfo; + } + + public String getRecall() { + return recall; + } + + public void setRecall(String recall) { + this.recall = recall; + } + + @JSONField(serialize = false) + public boolean getFormatRecall() { + return recall != null && recall.equalsIgnoreCase("y"); + } + + @Override + public String toString() { + return "appId=" + appId + ", mchId=" + mchId + ", subAppId=" + subAppId + + ", subMchId=" + subMchId + ", nonceStr=" + nonceStr + + ", sign=" + sign + ", deviceInfo=" + deviceInfo + ", recall=" + + getFormatRecall() + ", " + super.toString(); + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/MerchantTradeResult.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/MerchantTradeResult.java new file mode 100644 index 00000000..d257f11b --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/MerchantTradeResult.java @@ -0,0 +1,126 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.type.CurrencyType; + +import javax.xml.bind.annotation.XmlElement; + +/** + * 商户平台交易结果 + * + * @className MerchantTradeResult + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月21日 + * @since JDK 1.7 + * @see + */ +public class MerchantTradeResult extends MerchantResult { + + private static final long serialVersionUID = 4205906286092873877L; + /** + * 微信支付订单号 + */ + @XmlElement(name = "transaction_id") + @JSONField(name = "transaction_id") + private String transactionId; + /** + * 商户订单号 + */ + @XmlElement(name = "out_trade_no") + @JSONField(name = "out_trade_no") + private String outTradeNo; + /** + * 订单总金额,单位为分 + */ + @XmlElement(name = "total_fee") + @JSONField(name = "total_fee") + private Integer totalFee; + /** + * 应结订单金额,单位为分:应结订单金额=订单金额-非充值代金券金额,应结订单金额<=订单金额。 + */ + @XmlElement(name = "settlement_total_fee") + @JSONField(name = "settlement_total_fee") + private Integer settlementTotalFee; + /** + * 货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY + * + * @see com.foxinmy.weixin4j.pay.type.CurrencyType + */ + @XmlElement(name = "fee_type") + @JSONField(name = "fee_type") + private String feeType; + /** + * 现金支付金额 + */ + @XmlElement(name = "cash_fee") + @JSONField(name = "cash_fee") + private Integer cashFee; + + public Integer getCashFee() { + return cashFee; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatCashFee() { + return cashFee != null ? cashFee / 100d : 0d; + } + + public Integer getTotalFee() { + return totalFee; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatTotalFee() { + return totalFee != null ? totalFee / 100d : 0d; + } + + @JSONField(serialize = false) + public CurrencyType getFormatFeeType() { + return feeType != null ? CurrencyType.valueOf(feeType.toUpperCase()) + : null; + } + + public String getFeeType() { + return feeType; + } + + public String getTransactionId() { + return transactionId; + } + + public String getOutTradeNo() { + return outTradeNo; + } + + public Integer getSettlementTotalFee() { + return settlementTotalFee; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatSettlementTotalFee() { + return settlementTotalFee != null ? settlementTotalFee / 100d : 0d; + } + + @Override + public String toString() { + return "transactionId=" + transactionId + ", outTradeNo=" + outTradeNo + + ", totalFee=" + totalFee + ", cashFee=" + cashFee + + ", feeType=" + feeType + ", settlementTotalFee=" + + settlementTotalFee + ", " + super.toString(); + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/NATIVEPayRequest.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/NATIVEPayRequest.java new file mode 100644 index 00000000..787dfacb --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/NATIVEPayRequest.java @@ -0,0 +1,46 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.payment.PayRequest; +import com.foxinmy.weixin4j.pay.type.TradeType; + +/** + * NATIVE扫码支付(模式二) + * + * @className NATIVEPayRequest + * @author jinyu(foxinmy@gmail.com) + * @date 2015年12月25日 + * @since JDK 1.6 + * @see PrePay + * @see PayRequest + * @see NATIVE扫码支付(模式二) + */ +public class NATIVEPayRequest extends AbstractPayRequest { + + private final String codeUrl; + + public NATIVEPayRequest(String prePayId, String codeUrl, + WeixinPayAccount payAccount) { + super(prePayId, payAccount); + this.codeUrl = codeUrl; + } + + @Override + public TradeType getPaymentType() { + return TradeType.NATIVE; + } + + /** + * 只做查看之用,请不要尝试作为支付请求 + */ + @Override + public PayRequest toRequestObject() { + return new PayRequest(getPaymentAccount().getId(), "code_url=" + codeUrl); + } + + @Override + public String toRequestString() { + return this.codeUrl; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/NativePayNotify.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/NativePayNotify.java new file mode 100644 index 00000000..57c9b697 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/NativePayNotify.java @@ -0,0 +1,54 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Native支付回调时POST的信息 + * + * @className PayNativeNotify + * @author jinyu(foxinmy@gmail.com) + * @date 2014年10月30日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class NativePayNotify extends OpenIdResult { + + private static final long serialVersionUID = 4515471400239795492L; + /** + * 用户是否关注公众账号,Y- 关注,N-未关注,仅在公众 账号类型支付有效 + */ + @XmlElement(name = "is_subscribe") + @JSONField(name = "is_subscribe") + private String isSubscribe; + /** + * 产品ID 可视为订单ID + */ + @XmlElement(name = "product_id") + @JSONField(name = "product_id") + private String productId; + + protected NativePayNotify() { + // jaxb required + } + + public String getProductId() { + return productId; + } + + public String getIsSubscribe() { + return isSubscribe; + } + + @Override + public String toString() { + return "NativePayNotify [productId=" + productId + ", isSubscribe=" + + isSubscribe + ", " + super.toString() + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/NativePayResponse.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/NativePayResponse.java new file mode 100644 index 00000000..04b2f253 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/NativePayResponse.java @@ -0,0 +1,79 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.sign.WeixinPaymentSignature; +import com.foxinmy.weixin4j.util.Consts; +import com.foxinmy.weixin4j.util.RandomUtil; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Native支付时的回调响应 + * + * @className NativePayResponse + * @author jinyu(foxinmy@gmail.com) + * @date 2014年10月28日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class NativePayResponse extends MerchantResult { + + private static final long serialVersionUID = 6119895998783333012L; + + @XmlElement(name = "prepay_id") + @JSONField(name = "prepay_id") + private String prepayId; + + protected NativePayResponse() { + // jaxb required + } + + /** + * 作为return_code 为 FAIL 的时候返回 + * + * @param returnMsg + * 失败消息 + * @param resultMsg + * 结果消息 + */ + public NativePayResponse(String returnMsg, String resultMsg) { + super(Consts.FAIL, returnMsg); + super.setErrCodeDes(resultMsg); + super.setResultCode(Consts.FAIL); + } + + /** + * 作为return_code 为 SUCCESS 的时候返回 + * + * @param weixinAccount + * 商户信息 + * @param prepayId + * 调用统一下单接口生成的预支付ID + */ + public NativePayResponse(WeixinPayAccount weixinAccount, String prepayId) { + super(Consts.SUCCESS, "OK"); + this.setResultCode(Consts.SUCCESS); + this.setMchId(weixinAccount.getMchId()); + this.setAppId(weixinAccount.getId()); + this.setNonceStr(RandomUtil.generateString(16)); + this.prepayId = prepayId; + this.setSign(new WeixinPaymentSignature(weixinAccount.getPaySignKey()) + .sign(this)); + } + + public String getPrepayId() { + return prepayId; + } + + @Override + public String toString() { + return "NativePayResponse [prepayId=" + prepayId + ", " + + super.toString() + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/OpenIdResult.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/OpenIdResult.java new file mode 100644 index 00000000..3c4cfd95 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/OpenIdResult.java @@ -0,0 +1,52 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * authcode2openid + * + * @className OpenIdResult + * @author jinyu(foxinmy@gmail.com) + * @date 2015年7月23日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class OpenIdResult extends MerchantResult { + + private static final long serialVersionUID = 902743989722741814L; + + /** + * 用户在商户appid下的唯一标识 + */ + @XmlElement(name = "openid") + @JSONField(name = "openid") + private String openId; + + /** + * 用户在商户appid下的唯一标识 + */ + @XmlElement(name = "sub_openid") + @JSONField(name = "sub_openid") + private String subOpenId; + + public String getOpenId() { + return openId; + } + + public String getSubOpenId() { + return subOpenId; + } + + @Override + public String toString() { + return "OpenIdResult [openId=" + openId + ", subOpenId=" + subOpenId + + ", " + super.toString() + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/Order.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/Order.java new file mode 100644 index 00000000..9265c63c --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/Order.java @@ -0,0 +1,247 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.pay.payment.coupon.OrderCouponInfo; +import com.foxinmy.weixin4j.type.BankType; +import com.foxinmy.weixin4j.type.CurrencyType; +import com.foxinmy.weixin4j.type.TradeState; +import com.foxinmy.weixin4j.type.TradeType; +import com.foxinmy.weixin4j.util.DateUtil; +import com.foxinmy.weixin4j.xml.ListsuffixResult; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Date; +import java.util.List; + +/** + * 订单信息 + * + * @className Order + * @author jinyu(foxinmy@gmail.com) + * @date 2014年11月2日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class Order extends MerchantTradeResult { + + private static final long serialVersionUID = 5636828325595317079L; + /** + * 交易状态 + * + * @see TradeState + */ + @XmlElement(name = "trade_state") + @JSONField(name = "trade_state") + private String tradeState; + /** + * 用户的openid + */ + @XmlElement(name = "openid") + @JSONField(name = "openid") + private String openId; + /** + * 用户是否关注公众账号,Y- 关注,N-未关注,仅在公众 账号类型支付有效 + */ + @XmlElement(name = "is_subscribe") + @JSONField(name = "is_subscribe") + private String isSubscribe; + /** + * 交易类型 + * + * @see TradeType + */ + @XmlElement(name = "trade_type") + @JSONField(name = "trade_type") + private String tradeType; + /** + * 银行类型 + */ + @XmlElement(name = "bank_type") + @JSONField(name = "bank_type") + private String bankType; + + /** + * 现金支付货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY + * + * @see com.foxinmy.weixin4j.pay.type.CurrencyType + */ + @XmlElement(name = "cash_fee_type") + @JSONField(name = "cash_fee_type") + private String cashFeeType; + /** + * 代金券金额:“代金券”金额<=订单金额,订单金额-“代金券”金额=现金支付金额 + */ + @XmlElement(name = "coupon_fee") + @JSONField(name = "coupon_fee") + private Integer couponFee; + /** + * 代金券或立减优惠使用数量 + */ + @XmlElement(name = "coupon_count") + @JSONField(name = "coupon_count") + private Integer couponCount; + /** + * 代金券信息 验证签名有点麻烦 + */ + @ListsuffixResult + private List couponList; + /** + * 商家数据包 + */ + private String attach; + /** + * 支付完成时间,格式为 yyyyMMddhhmmss + */ + @XmlElement(name = "time_end") + @JSONField(name = "time_end") + private String timeEnd; + /** + * 交易状态描述 + */ + @XmlElement(name = "trade_state_desc") + @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 + } + + @JSONField(serialize = false) + public TradeState getFormatTradeState() { + return tradeState != null ? TradeState + .valueOf(tradeState.toUpperCase()) : null; + } + + public String getOpenId() { + return openId; + } + + public String getIsSubscribe() { + return isSubscribe; + } + + @JSONField(serialize = false) + public boolean getFormatIsSubscribe() { + return isSubscribe != null && isSubscribe.equalsIgnoreCase("y"); + } + + @JSONField(serialize = false) + public TradeType getFormatTradeType() { + return tradeType != null ? TradeType.valueOf(tradeType.toUpperCase()) + : null; + } + + public String getBankType() { + return bankType; + } + + @JSONField(serialize = false) + public BankType getFormatBankType() { + return bankType != null ? BankType.valueOf(bankType.toUpperCase()) + : null; + } + + public Integer getCouponFee() { + return couponFee; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatCouponFee() { + return couponFee != null ? couponFee / 100d : 0d; + } + + public Integer getCouponCount() { + return couponCount; + } + + public String getTradeState() { + return tradeState; + } + + public String getTradeType() { + return tradeType; + } + + public String getAttach() { + return attach; + } + + public String getTimeEnd() { + return timeEnd; + } + + @JSONField(serialize = false) + public Date getFormatTimeEnd() { + return timeEnd != null ? DateUtil.parse2yyyyMMddHHmmss(timeEnd) : null; + } + + public String getTradeStateDesc() { + return tradeStateDesc; + } + + public List getCouponList() { + return couponList; + } + + public void setCouponList(List couponList) { + 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"); + } + + public String getCashFeeType() { + return cashFeeType; + } + + @JSONField(serialize = false) + public CurrencyType getFormatCashFeeType() { + return cashFeeType != null ? CurrencyType.valueOf(cashFeeType + .toUpperCase()) : null; + } + + @Override + public String toString() { + return "Order [tradeState=" + tradeState + ", openId=" + openId + + ", isSubscribe=" + isSubscribe + ", tradeType=" + tradeType + + ", bankType=" + bankType + ", cashFeeType=" + cashFeeType + + ", couponFee=" + couponFee + ", couponCount=" + couponCount + + ", couponList=" + couponList + ", attach=" + attach + + ", timeEnd=" + timeEnd + ", tradeStateDesc=" + tradeStateDesc + + ", subOpenId=" + subOpenId + ", subIsSubscribe=" + + subIsSubscribe + ", " + super.toString() + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/PrePay.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/PrePay.java new file mode 100644 index 00000000..a8059fbe --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/PrePay.java @@ -0,0 +1,79 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.foxinmy.weixin4j.type.TradeType; + +import javax.xml.bind.annotation.*; + +/** + * V3预订单信息 + * + * @className PrePay + * @author jinyu(foxinmy@gmail.com) + * @date 2014年10月21日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class PrePay extends MerchantResult { + + private static final long serialVersionUID = -8430005768959715444L; + + /** + * 调用接口提交的交易类型,取值如下:JSAPI,NATIVE,APP, + * + * @see com.foxinmy.weixin4j.mp.type.TradeType + */ + @XmlElement(name = "trade_type") + private TradeType tradeType; + /** + * 微信生成的预支付回话标识,用于后续接口调用中使用,该值有效期为2小时 + */ + @XmlElement(name = "prepay_id") + private String prepayId; + /** + * 对于trade_type 为 NATIVE 或者 MWEB 是有 返回
NATVIE支付:可直接生成二维码展示出来进行扫码支付可能为空
+ * MWEB支付:可直接作为跳转支付的URL + */ + @XmlElements({ @XmlElement(name = "code_url"), + @XmlElement(name = "mweb_url") }) + private String payUrl; + + protected PrePay() { + // jaxb required + } + + public PrePay(String returnCode, String returnMsg) { + super(returnCode, returnMsg); + } + + public TradeType getTradeType() { + return tradeType; + } + + public void setTradeType(TradeType tradeType) { + this.tradeType = tradeType; + } + + public String getPrepayId() { + return prepayId; + } + + public void setPrepayId(String prepayId) { + this.prepayId = prepayId; + } + + public String getPayUrl() { + return payUrl; + } + + public void setPayUrl(String payUrl) { + this.payUrl = payUrl; + } + + @Override + public String toString() { + return "PrePay [tradeType=" + tradeType + ", prepayId=" + prepayId + + ", payUrl=" + payUrl + ", " + super.toString() + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/Redpacket.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/Redpacket.java new file mode 100644 index 00000000..6888862e --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/Redpacket.java @@ -0,0 +1,269 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.type.mch.RedpacketSceneType; +import com.foxinmy.weixin4j.util.DateUtil; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * 红包 + * + * @className Redpacket + * @author jinyu(foxinmy@gmail.com) + * @date 2015年3月28日 + * @since JDK 1.6 + * @see 普通红包 + * @see 裂变红包 + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class Redpacket extends MerchantResult { + + private static final long serialVersionUID = -7021352305575714281L; + + /** + * 商户订单号(每个订单号必须唯一) 组成: mch_id+yyyymmdd+10位一天内不能重复的数字。 + */ + @XmlElement(name = "mch_billno") + @JSONField(name = "mch_billno") + private String outTradeNo; + /** + * 接受收红包的用户的openid 必填 + */ + @XmlElement(name = "re_openid") + @JSONField(name = "re_openid") + private String openId; + /** + * 红包发送者名称 必填 + */ + @XmlElement(name = "send_name") + @JSONField(name = "send_name") + private String sendName; + /** + * 付款金额,单位分 + */ + @XmlElement(name = "total_amount") + @JSONField(name = "total_amount") + private int totalAmount; + /** + * 红包发放总人数 + */ + @XmlElement(name = "total_num") + @JSONField(name = "total_num") + private int totalNum; + /** + * 红包金额设置方式(裂变红包) ALL_RAND—全部随机,商户指定总金额和红包发放总人数,由微信支付随机计算出各红包金额 + */ + @XmlElement(name = "amt_type") + @JSONField(name = "amt_type") + private String amtType; + /** + * 红包祝福语 + */ + private String wishing; + /** + * ip地址 + */ + @XmlElement(name = "client_ip") + @JSONField(name = "client_ip") + private String clientIp; + /** + * 活动名称 + */ + @XmlElement(name = "act_name") + @JSONField(name = "act_name") + private String actName; + /** + * 备注 + */ + private String remark; + + /** + * 服务商模式下触达用户时的appid(可填服务商自己的appid或子商户的appid),服务商模式下必填, + * 服务商模式下填入的子商户appid必须在微信支付商户平台中先录入,否则会校验不过。 非必须 + */ + @XmlElement(name = "msgappid") + @JSONField(name = "msgappid") + private String msgAppId; + /** + * 扣钱方mchid,常规模式下无效,服务商模式下选填,服务商模式下不填默认扣子商户的钱.非必须 + */ + @XmlElement(name = "consume_mch_id") + @JSONField(name = "consume_mch_id") + private String consumeMchId; + /** + * 发放红包使用场景,红包金额大于200时必传 + */ + @XmlElement(name = "scene_id") + @JSONField(name = "scene_id") + private RedpacketSceneType sceneType; + /** + * 活动信息 + */ + @XmlElement(name = "risk_info") + @JSONField(name = "risk_info") + private String risk; + + protected Redpacket() { + // jaxb required + } + + /** + * 红包 + * + * @param outTradeNo + * 商户侧一天内不可重复的订单号 接口根据商户订单号支持重入 如出现超时可再调用 必填 + * @param openId + * 接受收红包的用户的openid 必填 + * @param sendName + * 红包发送者名称 必填 + * @param totalAmount + * 付款金额 单位为元,自动格式化为分 必填 + * @param totalNum + * 红包发放总人数 大于1视为裂变红包 必填 + * @param wishing + * 红包祝福语 必填 + * @param clientIp + * Ip地址 必填 + * @param actName + * 活动名称 必填 + * @param remark + * 备注 必填 + */ + public Redpacket(String outTradeNo, String openId, String sendName, + double totalAmount, int totalNum, String wishing, String clientIp, + String actName, String remark) { + this.outTradeNo = outTradeNo; + this.openId = openId; + this.sendName = sendName; + this.totalAmount = DateUtil.formatYuan2Fen(totalAmount); + this.totalNum = totalNum; + this.wishing = wishing; + this.clientIp = clientIp; + this.actName = actName; + this.remark = remark; + this.amtType = totalNum > 1 ? "ALL_RAND" : null; + } + + /** + * 批量发送时可能需要 + * + * @param outTradeNo + * 订单号 + * @param openId + * 用户ID + * @return 红包实体 + */ + public Redpacket copy(String outTradeNo, String openId) { + Redpacket readpacket = new Redpacket(outTradeNo, openId, sendName, + totalAmount, totalNum, wishing, clientIp, actName, remark); + readpacket.setMsgAppId(msgAppId); + readpacket.setConsumeMchId(consumeMchId); + readpacket.setSceneType(sceneType); + readpacket.setRisk(risk); + return readpacket; + } + + public String getOutTradeNo() { + return outTradeNo; + } + + public String getOpenId() { + return openId; + } + + public String getSendName() { + return sendName; + } + + public int getTotalAmount() { + return totalAmount; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatTotalAmount() { + return totalAmount / 100d; + } + + public int getTotalNum() { + return totalNum; + } + + public String getWishing() { + return wishing; + } + + public String getAmtType() { + return amtType; + } + + public String getClientIp() { + return clientIp; + } + + public String getActName() { + return actName; + } + + public String getRemark() { + return remark; + } + + public String getMsgAppId() { + return msgAppId; + } + + public void setMsgAppId(String msgAppId) { + this.msgAppId = msgAppId; + } + + public String getConsumeMchId() { + return consumeMchId; + } + + public void setConsumeMchId(String consumeMchId) { + this.consumeMchId = consumeMchId; + } + + public RedpacketSceneType getSceneType() { + return sceneType; + } + + public void setSceneType(RedpacketSceneType sceneType) { + this.sceneType = sceneType; + } + + public String getRisk() { + return risk; + } + + public void setRisk(String risk) { + this.risk = risk; + } + + public void setRisk(RedpacketRisk risk) { + this.risk = risk.toContent(); + } + + @Override + public String toString() { + return "Redpacket [outTradeNo=" + outTradeNo + ", openId=" + openId + + ", sendName=" + sendName + ", totalAmount=" + totalAmount + + ", totalNum=" + totalNum + ", amtType=" + amtType + + ", wishing=" + wishing + ", clientIp=" + clientIp + + ", actName=" + actName + ", remark=" + remark + ", msgAppId=" + + msgAppId + ", consumeMchId=" + consumeMchId + ", sceneType=" + + sceneType + ", risk=" + risk + ", " + super.toString() + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RedpacketRecord.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RedpacketRecord.java new file mode 100644 index 00000000..2cee591b --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RedpacketRecord.java @@ -0,0 +1,315 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.http.weixin.XmlResult; +import com.foxinmy.weixin4j.type.mch.RedpacketSendType; +import com.foxinmy.weixin4j.type.mch.RedpacketStatus; +import com.foxinmy.weixin4j.type.mch.RedpacketType; +import com.foxinmy.weixin4j.util.DateUtil; + +import javax.xml.bind.annotation.*; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * 红包记录 + * + * @className RedpacketRecord + * @author jinyu(foxinmy@gmail.com) + * @date 2015年6月4日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RedpacketRecord extends XmlResult { + + private static final long serialVersionUID = 929959747323918458L; + + /** + * 商户订单号(每个订单号必须唯一) 组成: mch_id+yyyymmdd+10位一天内不能重复的数字。 + */ + @XmlElement(name = "mch_billno") + @JSONField(name = "mch_billno") + private String outTradeNo; + /** + * 微信支付分配的商户号 + */ + @XmlElement(name = "mch_id") + @JSONField(name = "mch_id") + private String mchId; + /** + * 红包单号 + */ + @XmlElement(name = "detail_id") + @JSONField(name = "detail_id") + private String repacketId; + /** + * 红包状态 + */ + @XmlElement(name = "status") + private String status; + /** + * 发放类型 + */ + @XmlElement(name = "send_type") + @JSONField(name = "send_type") + private String sendType; + /** + * 红包类型 + */ + @XmlElement(name = "hb_type") + @JSONField(name = "hb_type") + private String hbType; + /** + * 红包个数 + */ + @XmlElement(name = "total_num") + @JSONField(name = "total_num") + private int totalNum; + /** + * 红包总金额(单位分) + */ + @XmlElement(name = "total_amount") + @JSONField(name = "total_amount") + private int totalAmount; + /** + * 发送失败原因 + */ + @XmlElement(name = "reason") + private String reason; + /** + * 发放时间 + */ + @XmlElement(name = "send_time") + @JSONField(name = "send_time") + private String sendTime; + /** + * 红包退款时间 + */ + @XmlElement(name = "refund_time") + @JSONField(name = "refund_time") + private String refundTime; + /** + * 红包退款金额 + */ + @XmlElement(name = "refund_amount") + @JSONField(name = "refund_amount") + private Integer refundAmount; + /** + * 祝福语 + */ + @XmlElement(name = "wishing") + private String wishing; + /** + * 活动描述 + */ + @XmlElement(name = "remark") + private String remark; + /** + * 活动名称 + */ + @XmlElement(name = "act_name") + @JSONField(name = "act_name") + private String actName; + /** + * 裂变红包领取列表 + */ + @XmlElement(name = "hbinfo") + @XmlElementWrapper(name = "hblist") + @JSONField(name = "hblist") + private List receivers; + + public String getOutTradeNo() { + return outTradeNo; + } + + public String getMchId() { + return mchId; + } + + public String getRepacketId() { + return repacketId; + } + + @JSONField(serialize = false) + public RedpacketStatus getFormatStatus() { + return status != null ? RedpacketStatus.valueOf(status.toUpperCase()) + : null; + } + + @JSONField(serialize = false) + public RedpacketSendType getFormatSendType() { + return sendType != null ? RedpacketSendType.valueOf(sendType) : null; + } + + @JSONField(serialize = false) + public RedpacketType getFomatHbType() { + return hbType != null ? RedpacketType.valueOf(hbType) : null; + } + + public String getStatus() { + return status; + } + + public String getSendType() { + return sendType; + } + + public String getHbType() { + return hbType; + } + + public int getTotalNum() { + return totalNum; + } + + public int getTotalAmount() { + return totalAmount; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatTotalAmount() { + return totalAmount / 100d; + } + + public String getReason() { + return reason; + } + + public String getSendTime() { + return sendTime; + } + + @JSONField(serialize = false) + public Date getFormatSendTime() { + return sendTime != null ? DateUtil.parse2yyyyMMddHHmmss(sendTime) + : null; + } + + public String getRefundTime() { + return refundTime; + } + + @JSONField(serialize = false) + public Date getFormatRefundTime() { + return refundTime != null ? DateUtil.parse2yyyyMMddHHmmss(refundTime) + : null; + } + + public Integer getRefundAmount() { + return refundAmount; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatRefundAmount() { + return refundAmount != null ? refundAmount.intValue() / 100d : 0d; + } + + public String getWishing() { + return wishing; + } + + public String getRemark() { + return remark; + } + + public String getActName() { + return actName; + } + + public List getReceivers() { + return receivers; + } + + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RedpacketReceiver implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 领取红包的Openid + */ + @XmlElement(name = "openid") + private String openId; + /** + * 领取状态 + */ + @XmlElement(name = "status") + private RedpacketStatus status; + /** + * 领取金额 + */ + private int amount; + /** + * 领取时间 + */ + @XmlElement(name = "rcv_time") + @JSONField(name = "rcv_time") + private String receiveTime; + + public String getOpenId() { + return openId; + } + + public RedpacketStatus getStatus() { + return status; + } + + public int getAmount() { + return amount; + } + + public String getReceiveTime() { + return receiveTime; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatAmount() { + return amount / 100d; + } + + @JSONField(serialize = false) + public Date getFormatReceiveTime() { + return receiveTime != null ? DateUtil + .parse2yyyyMMddHHmmss(receiveTime) : null; + } + + @Override + public String toString() { + return "RedpacketReceiver [openId=" + openId + ", status=" + status + + ", amount=" + getFormatAmount() + ", receiveTime=" + + receiveTime + "]"; + } + } + + @Override + public String toString() { + return "RedpacketRecord [outTradeNo=" + outTradeNo + ", mchId=" + mchId + + ", repacketId=" + repacketId + ", status=" + status + + ", sendType=" + sendType + ", hbType=" + hbType + + ", totalNum=" + totalNum + ", totalAmount=" + + getFormatTotalAmount() + ", reason=" + reason + ", sendTime=" + + sendTime + ", refundTime=" + refundTime + ", refundAmount=" + + getFormatRefundAmount() + ", wishing=" + wishing + + ", remark=" + remark + ", actName=" + actName + + ", receivers=" + receivers + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RedpacketRisk.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RedpacketRisk.java new file mode 100644 index 00000000..05127d0b --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RedpacketRisk.java @@ -0,0 +1,85 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.foxinmy.weixin4j.util.Consts; +import com.foxinmy.weixin4j.util.DateUtil; +import com.foxinmy.weixin4j.util.MapUtil; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Map; + +/** + * 发送红包的活动信息 + * + * @className RedpacketRisk + * @author jinyu(foxinmy@gmail.com) + * @date 2017年1月4日 + * @since JDK 1.6 + * @see + */ +public class RedpacketRisk { + private Map risk; + + public RedpacketRisk() { + this.risk = new HashMap(); + } + + /** + * 用户操作的时间戳 + * + * @return + */ + public RedpacketRisk postTimestamp() { + risk.put("posttime", DateUtil.timestamp2string()); + return this; + } + + /** + * 业务系统账号的手机号,国家代码-手机号。不需要+号 + * + * @param mobile + * @return + */ + public RedpacketRisk mobile(String mobile) { + risk.put("mobile", mobile); + return this; + } + + /** + * 用户操作的客户端版本 + * + * @param clientVersion + * @return + */ + public RedpacketRisk clientVersion(String clientVersion) { + risk.put("clientversion", clientVersion); + return this; + } + + /** + * mac 地址或者设备唯一标识 + * + * @param deviceid + * @return + */ + public RedpacketRisk deviceid(String deviceid) { + risk.put("deviceid", deviceid); + return this; + } + + public Map getRisk() { + return risk; + } + + public String toContent() { + if (risk.isEmpty()) + return null; + try { + return URLEncoder.encode(MapUtil.toJoinString(risk, false, false), + Consts.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + return null; + } + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RedpacketSendResult.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RedpacketSendResult.java new file mode 100644 index 00000000..741c9e29 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RedpacketSendResult.java @@ -0,0 +1,102 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.util.DateUtil; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Date; + +/** + * 发送红包结果 + * + * @className RedpacketSendResult + * @author jinyu(foxinmy@gmail.com) + * @date 2015年4月1日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RedpacketSendResult extends MerchantResult { + + private static final long serialVersionUID = 5611847899634131711L; + /** + * 商户订单号(每个订单号必须唯一) 组成: mch_id+yyyymmdd+10位一天内不能重复的数字。 + */ + @XmlElement(name = "mch_billno") + @JSONField(name = "mch_billno") + private String outTradeNo; + /** + * 接收红包的用户的openid + */ + @XmlElement(name = "re_openid") + @JSONField(name = "re_openid") + private String openId; + /** + * 付款金额 单位为分 + */ + @XmlElement(name = "total_amount") + @JSONField(name = "total_amount") + private int totalAmount; + /** + * 发放成功时间 + */ + @XmlElement(name = "send_time") + @JSONField(name = "send_time") + private String sendTime; + /** + * 微信单号 + */ + @XmlElement(name = "send_listid") + @JSONField(name = "send_listid") + private String sendListid; + + protected RedpacketSendResult() { + // jaxb required + } + + public String getOutTradeNo() { + return outTradeNo; + } + + public String getOpenId() { + return openId; + } + + public int getTotalAmount() { + return totalAmount; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatTotalAmount() { + return totalAmount / 100d; + } + + public String getSendTime() { + return sendTime; + } + + @JSONField(serialize = false) + public Date getFormatSendTime() { + return DateUtil.parse2yyyyMMddHHmmss(sendTime); + } + + public String getSendListid() { + return sendListid; + } + + @Override + public String toString() { + return "RedpacketSendResult [outTradeNo=" + outTradeNo + ", openId=" + + openId + ", totalAmount=" + totalAmount + ", " + + super.toString() + "]"; + } +} \ No newline at end of file diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RefundDetail.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RefundDetail.java new file mode 100644 index 00000000..8d81f4ee --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RefundDetail.java @@ -0,0 +1,218 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.pay.payment.coupon.RefundCouponInfo; +import com.foxinmy.weixin4j.type.mch.CouponType; +import com.foxinmy.weixin4j.type.mch.RefundChannel; +import com.foxinmy.weixin4j.type.mch.RefundStatus; +import com.foxinmy.weixin4j.util.DateUtil; +import com.foxinmy.weixin4j.xml.ListsuffixResult; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * 退款详细 + * + * @className RefundDetail + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月21日 + * @since JDK 1.6 + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RefundDetail implements Serializable { + private static final long serialVersionUID = 1402738803019986864L; + + protected RefundDetail() { + // jaxb required + } + + /** + * 商户退款单号 + */ + @XmlElement(name = "out_refund_no") + @JSONField(name = "out_refund_no") + private String outRefundNo; + /** + * 微信退款单号 + */ + @XmlElement(name = "refund_id") + @JSONField(name = "refund_id") + private String refundId; + /** + * 退款渠道:ORIGINAL—原路退款,默认 BALANCE—退回到余额 + */ + @XmlElement(name = "refund_channel") + @JSONField(name = "refund_channel") + private String refundChannel; + /** + * 退款总金额,单位为分,可以做部分退款 + */ + @XmlElement(name = "refund_fee") + @JSONField(name = "refund_fee") + private int refundFee; + /** + * 退款状态 + */ + @XmlElement(name = "refund_status") + @JSONField(name = "refund_status") + private String refundStatus; + /** + * 退款金额:退款金额=申请退款金额-非充值代金券退款金额,退款金额<=申请退款金额 + */ + @XmlElement(name = "settlement_refund_fee") + @JSONField(name = "settlement_refund_fee") + private Integer settlementRefundFee; + /** + * 代金券退款金额:代金券退款金额<=退款金额,退款金额-代金券或立减优惠退款金额为现金, + */ + @XmlElement(name = "coupon_refund_fee") + @JSONField(name = "coupon_refund_fee") + private Integer couponRefundFee; + /** + * 代金券或立减优惠使用数量 + */ + @XmlElement(name = "coupon_refund_count") + @JSONField(name = "coupon_refund_count") + private Integer couponRefundCount; + /** + * 代金券类型 + * + * @see CouponType + */ + @XmlElement(name = "coupon_type") + @JSONField(name = "coupon_type") + private String couponType; + /** + * 退款入账账户:取当前退款单的退款入账方 1)退回银行卡: {银行名称}{卡类型}{卡尾号} 2)退回支付用户零钱: 支付用户零钱 + */ + @XmlElement(name = "refund_recv_accout") + @JSONField(name = "refund_recv_accout") + private String refundRecvAccout; + /** + * 退款成功时间,当退款状态为退款成功时有返回 + */ + @XmlElement(name = "refund_success_time") + @JSONField(name = "refund_success_time") + private String refundSuccessTime; + /** + * 退款代金券信息 + * + * @see RefundCouponInfo + */ + @ListsuffixResult + private List couponList; + + public String getOutRefundNo() { + return outRefundNo; + } + + public String getRefundId() { + return refundId; + } + + public String getRefundChannel() { + return refundChannel; + } + + @JSONField(serialize = false) + public RefundChannel getFormatRefundChannel() { + return refundChannel != null ? RefundChannel.valueOf(refundChannel + .toUpperCase()) : null; + } + + public int getRefundFee() { + return refundFee; + } + + public String getRefundStatus() { + return refundStatus; + } + + @JSONField(serialize = false) + public RefundStatus getFormatRefundStatus() { + return refundStatus != null ? RefundStatus.valueOf(refundStatus + .toUpperCase()) : null; + } + + public List getCouponList() { + return couponList; + } + + public void setCouponList(List couponList) { + this.couponList = couponList; + } + + public Integer getSettlementRefundFee() { + return settlementRefundFee; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatSettlementRefundFee() { + return settlementRefundFee != null ? settlementRefundFee / 100d : 0d; + } + + public Integer getCouponRefundFee() { + return couponRefundFee; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatCouponRefundFee() { + return couponRefundFee != null ? couponRefundFee / 100d : 0d; + } + + public Integer getCouponRefundCount() { + return couponRefundCount; + } + + public String getCouponType() { + return couponType; + } + + @JSONField(serialize = false) + public CouponType getFormatCouponType() { + return couponType != null ? CouponType + .valueOf(couponType.toUpperCase()) : null; + } + + public String getRefundRecvAccout() { + return refundRecvAccout; + } + + public String getRefundSuccessTime() { + return refundSuccessTime; + } + + @JSONField(serialize = false) + public Date getFormatRefundSuccessTime() { + return refundSuccessTime != null ? DateUtil.parse2yyyyMMddHHmmss(refundSuccessTime) : null; + } + + @Override + public String toString() { + return "RefundDetail [outRefundNo=" + outRefundNo + ", refundId=" + + refundId + ", refundChannel=" + refundChannel + + ", refundFee=" + refundFee + ", refundStatus=" + refundStatus + + ", settlementRefundFee=" + settlementRefundFee + + ", couponRefundFee=" + couponRefundFee + + ", couponRefundCount=" + couponRefundCount + ", couponType=" + + couponType + ", refundRecvAccout=" + refundRecvAccout + + ", couponList=" + couponList + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RefundRecord.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RefundRecord.java new file mode 100644 index 00000000..9de5fd05 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RefundRecord.java @@ -0,0 +1,81 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.xml.ListsuffixResult; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.List; + +/** + * 退款记录 + * + * @className RefundRecord + * @author jinyu(foxinmy@gmail.com) + * @date 2014年11月1日 + * @since JDK 1.6 + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RefundRecord extends MerchantTradeResult { + + private static final long serialVersionUID = -2971132874939642721L; + /** + * 退款笔数 + */ + @XmlElement(name = "refund_count") + @JSONField(name = "refund_count") + private int refundCount; + /** + * 退款总金额,单位为分,可以做部分退款 + */ + @XmlElement(name = "refund_fee") + @JSONField(name = "refund_fee") + private int refundFee; + /** + * 退款详情 + * + * @see RefundDetail + */ + @ListsuffixResult({ ".*(_\\d)$" }) + private List refundList; + + protected RefundRecord() { + // jaxb required + } + + public int getRefundCount() { + return refundCount; + } + + public int getRefundFee() { + return refundFee; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatRefundFee() { + return refundFee / 100d; + } + + public List getRefundList() { + return refundList; + } + + public void setRefundList(List refundList) { + this.refundList = refundList; + } + + @Override + public String toString() { + return "RefundRecord [refundCount=" + refundCount + ", refundFee=" + + refundFee + ", refundList=" + refundList + ", " + + super.toString() + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RefundResult.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RefundResult.java new file mode 100644 index 00000000..717c4bc5 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/RefundResult.java @@ -0,0 +1,128 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.type.mch.RefundChannel; +import com.foxinmy.weixin4j.xml.ListsuffixResult; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.List; + +/** + * 退款申请结果 + * + * @className RefundResult + * @author jinyu(foxinmy@gmail.com) + * @date 2014年11月6日 + * @since JDK 1.6 + * @see + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RefundResult extends MerchantTradeResult { + + private static final long serialVersionUID = -3687863914168618620L; + + /** + * 商户退款单号 + */ + @XmlElement(name = "out_refund_no") + @JSONField(name = "out_refund_no") + private String outRefundNo; + /** + * 微信退款单号 + */ + @XmlElement(name = "refund_id") + @JSONField(name = "refund_id") + private String refundId; + /** + * 退款渠道:ORIGINAL—原路退款,默认 BALANCE—退回到余额 + */ + @XmlElement(name = "refund_channel") + @JSONField(name = "refund_channel") + private String refundChannel; + /** + * 退款总金额,单位为分,可以做部分退款 + */ + @XmlElement(name = "refund_fee") + @JSONField(name = "refund_fee") + private int refundFee; + /** + * 现金退款金额 + */ + @XmlElement(name = "cash_refund_fee") + @JSONField(name = "cash_refund_fee") + private Integer cashRefundFee; + /** + * 退款详情 + * + * @see RefundDetail + */ + @ListsuffixResult({ ".*(_\\d)$" }) + private List refundList; + + protected RefundResult() { + // jaxb required + } + + public String getOutRefundNo() { + return outRefundNo; + } + + public String getRefundId() { + return refundId; + } + + public String getRefundChannel() { + return refundChannel; + } + + @JSONField(serialize = false) + public RefundChannel getFormatRefundChannel() { + return refundChannel != null ? RefundChannel.valueOf(refundChannel + .toUpperCase()) : null; + } + + public int getRefundFee() { + return refundFee; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatRefundFee() { + return refundFee / 100d; + } + + public Integer getCashRefundFee() { + return cashRefundFee; + } + + /** + * 调用接口获取单位为分,get方法转换为元方便使用 + * + * @return 元单位 + */ + @JSONField(serialize = false) + public double getFormatCashRefundFee() { + return cashRefundFee != null ? cashRefundFee.intValue() / 100d : 0d; + } + + public List getRefundList() { + return refundList; + } + + @Override + public String toString() { + return "RefundResult [" + super.toString() + ", outRefundNo=" + + outRefundNo + ", refundId=" + refundId + ", refundChannel=" + + refundChannel + ", refundFee=" + refundFee + + ", cashRefundFee=" + cashRefundFee + ", refundList=" + + refundList + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/SceneInfoApp.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/SceneInfoApp.java new file mode 100644 index 00000000..48a5b763 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/SceneInfoApp.java @@ -0,0 +1,99 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class SceneInfoApp { + /** + * 终端类型 + */ + private String type; + /** + * 应用名称 + */ + private String name; + /** + * 应用路径 + */ + private String path; + private String sceneInfo; + + private SceneInfoApp(String type, String name, String path) { + this.type = type; + this.name = name; + this.path = path; + } + + public String getType() { + return type; + } + + public String getName() { + return name; + } + + public String getPath() { + return path; + } + + public String getSceneInfo() { + return sceneInfo; + } + + public void setSceneInfo(String sceneInfo) { + this.sceneInfo = sceneInfo; + } + + /** + * IOS应用 + * + * @param appName 应用名 + * @param bundleId 模块ID + * @return + */ + public static SceneInfoApp createIOSAPP(String appName, String bundleId) { + SceneInfoApp app = new SceneInfoApp("IOS", appName, bundleId); + String sceneInfo = String + .format("{\"type\": \"%s\",\"app_name\": \"%s\",\"bundle_id\": \"%s\"}", + app.getType(), app.getName(), app.getPath()); + app.setSceneInfo(sceneInfo); + return app; + } + + /** + * Android应用 + * + * @param appName 应用名 + * @param packageName 包名 + * @return + */ + public static SceneInfoApp createAndroidAPP(String appName, String packageName) { + SceneInfoApp app = new SceneInfoApp("Android", appName, packageName); + String sceneInfo = String + .format("{\"type\": \"%s\",\"app_name\": \"%s\",\"package_name\": \"%s\"}", + app.getType(), app.getName(), app.getPath()); + app.setSceneInfo(sceneInfo); + return app; + } + + /** + * Wap应用 + * + * @param name + * 网站名 + * @param url + * 网站URL地址 + * @return + */ + public static SceneInfoApp createWapAPP(String name, String url) { + SceneInfoApp app = new SceneInfoApp("Wap", name, url); + String sceneInfo = String.format( + "{\"type\": \"%s\",\"wap_name\": \"%s\",\"wap_url\": \"%s\"}", + app.getType(), app.getName(), app.getPath()); + app.setSceneInfo(sceneInfo); + return app; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/SceneInfoStore.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/SceneInfoStore.java new file mode 100644 index 00000000..550e9edd --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/SceneInfoStore.java @@ -0,0 +1,75 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class SceneInfoStore { + /** + * SZTX001 门店唯一标识 + */ + private String id; + /** + * 腾讯大厦腾大餐厅 门店名称 + */ + private String name; + /** + * 门店所在地行政区划码,详细见《最新县及县以上行政区划代码》 + */ + @XmlElement(name = "area_code") + @JSONField(name = "area_code") + private String areaCode; + /** + * 科技园中一路腾讯大厦 门店详细地址 + */ + private String address; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAreaCode() { + return areaCode; + } + + public void setAreaCode(String areaCode) { + this.areaCode = areaCode; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public SceneInfoStore(String id, String name) { + super(); + this.id = id; + this.name = name; + } + + @Override + public String toString() { + return "SceneInfoStore [id=" + id + ", name=" + name + ", areaCode=" + + areaCode + ", address=" + address + "]"; + } +} \ No newline at end of file diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/SettlementRecord.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/SettlementRecord.java new file mode 100644 index 00000000..501abd03 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/SettlementRecord.java @@ -0,0 +1,272 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.type.CurrencyType; +import com.foxinmy.weixin4j.util.DateUtil; + +import javax.xml.bind.annotation.XmlElement; +import java.util.Date; + +/** + * 结算资金 + * + * @className Settlement + * @author jinyu(foxinmy@gmail.com) + * @date 2016年3月26日 + * @since JDK 1.6 + * @see + */ +public class SettlementRecord extends MerchantResult { + + private static final long serialVersionUID = 7952659545609519979L; + + /** + * 付款批次号 + */ + @XmlElement(name = "fbatchno") + @JSONField(name = "fbatchno") + private String batchNo; + /** + * 结算日期 + */ + @XmlElement(name = "date_settlement") + @JSONField(name = "date_settlement") + private String settleDate; + /** + * 交易开始日期 + */ + @XmlElement(name = "date_start") + @JSONField(name = "date_start") + private String startDate; + /** + * 交易结束日期 + */ + @XmlElement(name = "date_end") + @JSONField(name = "date_end") + private String endDate; + /** + * 划账金额:外币标价,外币最小单位 + */ + @XmlElement(name = "transaction_id") + @JSONField(name = "transaction_id") + private int settleFee; + /** + * 未划账金额:外币标价,外币最小单位 + */ + @XmlElement(name = "unsettlement_fee") + @JSONField(name = "unsettlement_fee") + private int unSettleFee; + /** + * 结算币种 + */ + @XmlElement(name = "settlementfee_type") + @JSONField(name = "settlementfee_type") + private String settleFeeType; + /** + * 支付金额:外币标价,外币最小单位 + */ + @XmlElement(name = "pay_fee") + @JSONField(name = "pay_fee") + private int payFee; + /** + * 退款金额:外币标价,外币最小单位 + */ + @XmlElement(name = "refund_fee") + @JSONField(name = "refund_fee") + private int refundFee; + /** + * 支付净额:外币标价,外币最小单位 + */ + @XmlElement(name = "pay_net_fee") + @JSONField(name = "pay_net_fee") + private int payNetFee; + /** + * 手续费金额:外币标价,外币最小单位 + */ + @XmlElement(name = "poundage_fee") + @JSONField(name = "poundage_fee") + private int poundageFee; + + protected SettlementRecord() { + // jaxb required + } + + public String getBatchNo() { + return batchNo; + } + + public void setBatchNo(String batchNo) { + this.batchNo = batchNo; + } + + public String getSettleDate() { + return settleDate; + } + + @JSONField(serialize = false) + public Date getFormatSettleDate() { + return DateUtil.parse2yyyyMMddHHmmss(settleDate); + } + + public void setSettleDate(String settleDate) { + this.settleDate = settleDate; + } + + public String getStartDate() { + return startDate; + } + + @JSONField(serialize = false) + public Date getFormatStartDate() { + return DateUtil.parse2yyyyMMddHHmmss(startDate); + } + + public void setStartDate(String startDate) { + this.startDate = startDate; + } + + public String getEndDate() { + return endDate; + } + + @JSONField(serialize = false) + public Date getFormatEndDate() { + return DateUtil.parse2yyyyMMddHHmmss(settleDate); + } + + public void setEndDate(String endDate) { + this.endDate = endDate; + } + + public int getSettleFee() { + return settleFee; + } + + /** + * 最小单位除100得到的值 + * + * @return /100 + */ + @JSONField(serialize = false) + public double getFormatSettleFee() { + return settleFee / 100d; + } + + public void setSettleFee(int settleFee) { + this.settleFee = settleFee; + } + + public int getUnSettleFee() { + return unSettleFee; + } + + /** + * 最小单位除100得到的值 + * + * @return /100 + */ + @JSONField(serialize = false) + public double getFormatUnSettleFee() { + return unSettleFee / 100d; + } + + public void setUnSettleFee(int unSettleFee) { + this.unSettleFee = unSettleFee; + } + + public String getSettleFeeType() { + return settleFeeType; + } + + @JSONField(serialize = false) + public CurrencyType getFormatSettleFeeType() { + return CurrencyType.valueOf(settleFeeType.toUpperCase()); + } + + public void setSettleFeeType(String settleFeeType) { + this.settleFeeType = settleFeeType; + } + + public int getPayFee() { + return payFee; + } + + /** + * 最小单位除100得到的值 + * + * @return /100 + */ + @JSONField(serialize = false) + public double getFormatPayFee() { + return payFee / 100d; + } + + public void setPayFee(int payFee) { + this.payFee = payFee; + } + + public int getRefundFee() { + return refundFee; + } + + /** + * 最小单位除100得到的值 + * + * @return /100 + */ + @JSONField(serialize = false) + public double getFormatRefundFee() { + return refundFee / 100d; + } + + public void setRefundFee(int refundFee) { + this.refundFee = refundFee; + } + + public int getPayNetFee() { + return payNetFee; + } + + public void setPayNetFee(int payNetFee) { + this.payNetFee = payNetFee; + } + + /** + * 最小单位除100得到的值 + * + * @return /100 + */ + @JSONField(serialize = false) + public double getFormatPayNetFee() { + return payNetFee / 100d; + } + + public int getPoundageFee() { + return poundageFee; + } + + /** + * 最小单位除100得到的值 + * + * @return /100 + */ + @JSONField(serialize = false) + public double getFormatPoundageFee() { + return poundageFee / 100d; + } + + public void setPoundageFee(int poundageFee) { + this.poundageFee = poundageFee; + } + + @Override + public String toString() { + return "SettlementRecord [batchNo=" + batchNo + ", settleDate=" + + settleDate + ", startDate=" + startDate + ", endDate=" + + endDate + ", settleFee=" + settleFee + ", unSettleFee=" + + unSettleFee + ", settleFeeType=" + settleFeeType + + ", payFee=" + payFee + ", refundFee=" + refundFee + + ", payNetFee=" + payNetFee + ", poundageFee=" + poundageFee + + ", " + super.toString() + "]"; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/WAPPayRequest.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/WAPPayRequest.java new file mode 100644 index 00000000..f08eff1f --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/payment/mch/WAPPayRequest.java @@ -0,0 +1,61 @@ +package com.foxinmy.weixin4j.pay.payment.mch; + +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.payment.PayRequest; +import com.foxinmy.weixin4j.pay.type.TradeType; + +/** + * WAP支付 + * + * @className WAPPayRequest + * @author jinyu(foxinmy@gmail.com) + * @date 2015年12月25日 + * @since JDK 1.6 + * @see PrePay + * @see PayRequest + * @see WAP支付 + */ +public class WAPPayRequest extends AbstractPayRequest { + /** + * 微信支付URL + */ + private final String payUrl; + + public WAPPayRequest(String prePayId, String payUrl, + WeixinPayAccount payAccount) { + super(prePayId, payAccount); + this.payUrl = payUrl; + + } + + @Override + public TradeType getPaymentType() { + return TradeType.MWEB; + } + + /** + * 只做查看之用,请不要尝试作为支付请求 + */ + @Override + public PayRequest toRequestObject() { + PayRequest payRequest = new PayRequest(getPaymentAccount().getId(), + getPaymentType().name()); + payRequest.setPrepayId(getPrePayId()); + return payRequest; + } + + @Override + public String toRequestString() { + // PayRequest payRequest = toRequestObject(); + // String original = MapUtil.toJoinString(payRequest, true, true); + // String sign = DigestUtil.MD5( + // String.format("%s&key=%s", original, getPaymentAccount() + // .getPaySignKey())).toUpperCase(); + // return String.format("weixin://wap/pay?%s", + // URLEncodingUtil.encoding( + // String.format("%s&sign=%s", original, sign), + // Consts.UTF_8, true)); + return this.payUrl; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/sign/AbstractWeixinSignature.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/sign/AbstractWeixinSignature.java new file mode 100644 index 00000000..6a077b99 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/sign/AbstractWeixinSignature.java @@ -0,0 +1,45 @@ +package com.foxinmy.weixin4j.pay.sign; + +import com.foxinmy.weixin4j.util.MapUtil; + +/** + * 微信签名 + * + * @className AbstractWeixinSignature + * @author jinyu(foxinmy@gmail.com) + * @date 2016年3月26日 + * @since JDK 1.6 + * @see + */ +public abstract class AbstractWeixinSignature implements WeixinSignature { + /** + * 是否编码 + * + * @return 默认false不进行编码 + */ + @Override + public boolean encoder() { + return false; + } + + /** + * 是否转换小写 + * + * @return 默认false不转换小写 + */ + @Override + public boolean lowerCase() { + return false; + } + + /** + * 拼接字符串 + * + * @param obj + * @return + */ + protected StringBuilder join(Object obj) { + return new StringBuilder(MapUtil.toJoinString(obj, encoder(), + lowerCase())); + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/sign/WeixinPaymentSignature.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/sign/WeixinPaymentSignature.java new file mode 100644 index 00000000..45b8aa10 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/sign/WeixinPaymentSignature.java @@ -0,0 +1,52 @@ +package com.foxinmy.weixin4j.pay.sign; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.pay.type.SignType; +import com.foxinmy.weixin4j.util.DigestUtil; + +import java.security.InvalidKeyException; + +/** + * 微信支付签名实现 + * + * @className WeixinPaymentSignature + * @author jinyu(foxinmy@gmail.com) + * @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(); + } + + @Override + public String sign(Object obj, SignType signType) { + if(signType==null){ + return sign(obj); + } + switch (signType){ + case HMAC$SHA256: + StringBuilder sb = join(obj).append("&key=").append(paySignKey); + try { + return DigestUtil.HMACSHA256(sb.toString(), paySignKey).toUpperCase(); + }catch (InvalidKeyException e){ + throw new RuntimeException("商户支付密钥有误", e); + } + default: + return sign(obj); + } + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/sign/WeixinSignature.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/sign/WeixinSignature.java new file mode 100644 index 00000000..8c02344f --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/sign/WeixinSignature.java @@ -0,0 +1,45 @@ +package com.foxinmy.weixin4j.pay.sign; + +import com.foxinmy.weixin4j.pay.type.SignType; + +/** + * 微信签名 + * + * @className WeixinSignature + * @author jinyu(foxinmy@gmail.com) + * @date 2016年3月26日 + * @since JDK 1.6 + * @see + */ +public interface WeixinSignature { + /** + * 是否编码 + * + * @return + */ + boolean encoder(); + + /** + * 是否转换小写 + * + * @return + */ + boolean lowerCase(); + + /** + * 签名(默认的MD5签名) + * + * @param obj + * @return + */ + String sign(Object obj); + + /** + * 签名(指定签名算法) + * + * @param obj + * @param signType + * @return + */ + String sign(Object obj, SignType signType); +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/BankType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/BankType.java new file mode 100644 index 00000000..397f9a4e --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/BankType.java @@ -0,0 +1,260 @@ +package com.foxinmy.weixin4j.pay.type; + + +/** + * 银行类型 + * + * @className BankType + * @author jinyu(foxinmy@gmail.com) + * @date 2015年8月19日 + * @since JDK 1.6 + * @see + */ +public enum BankType { + /** + * 工商银行(借记卡) + */ + ICBC_DEBIT("工商银行(借记卡)"), + /** + * 工商银行(信用卡) + */ + ICBC_CREDIT("工商银行(信用卡)"), + /** + * 农业银行(借记卡) + */ + ABC_DEBIT("农业银行(借记卡)"), + /** + * 农业银行 (信用卡) + */ + ABC_CREDIT("农业银行 (信用卡)"), + /** + * 邮政储蓄(借记卡) + */ + PSBC_DEBIT("邮政储蓄(借记卡)"), + /** + * 邮政储蓄 (信用卡) + */ + PSBC_CREDIT("邮政储蓄 (信用卡)"), + /** + * 建设银行(借记卡) + */ + CCB_DEBIT("建设银行(借记卡)"), + /** + * 建设银行 (信用卡) + */ + CCB_CREDIT("建设银行 (信用卡)"), + /** + * 招商银行(借记卡) + */ + CMB_DEBIT("招商银行(借记卡)"), + /** + * 招商银行(信用卡) + */ + CMB_CREDIT("招商银行(信用卡)"), + /** + * 交通银行(借记卡) + */ + COMM_DEBIT("交通银行(借记卡)"), + /** + * 中国银行(信用卡) + */ + BOC_CREDIT("中国银行(信用卡)"), + /** + * 浦发银行(借记卡) + */ + SPDB_DEBIT("浦发银行(借记卡)"), + /** + * 浦发银行 (信用卡) + */ + SPDB_CREDIT("浦发银行 (信用卡)"), + /** + * 广发银行(借记卡) + */ + GDB_DEBIT("广发银行(借记卡)"), + /** + * 广发银行(信用卡) + */ + GDB_CREDIT("广发银行(信用卡)"), + /** + * 民生银行(借记卡) + */ + CMBC_DEBIT("民生银行(借记卡)"), + /** + * 民生银行(信用卡) + */ + CMBC_CREDIT("民生银行(信用卡)"), + /** + * 平安银行(借记卡) + */ + PAB_DEBIT("平安银行(借记卡)"), + /** + * 平安银行(信用卡) + */ + PAB_CREDIT("平安银行(信用卡)"), + /** + * 光大银行(借记卡) + */ + CEB_DEBIT("光大银行(借记卡)"), + /** + * 光大银行(信用卡) + */ + CEB_CREDIT("光大银行(信用卡)"), + /** + * 兴业银行 (借记卡) + */ + CIB_DEBIT("兴业银行 (借记卡)"), + /** + * 兴业银行(信用卡) + */ + CIB_CREDIT("兴业银行(信用卡)"), + /** + * 中信银行(借记卡) + */ + CITIC_DEBIT("中信银行(借记卡)"), + /** + * 中信银行(信用卡) + */ + CITIC_CREDIT("中信银行(信用卡)"), + /** + * 深发银行(信用卡) + */ + SDB_CREDIT("深发银行(信用卡)"), + /** + * 上海银行(借记卡) + */ + BOSH_DEBIT("上海银行(借记卡)"), + /** + * 上海银行 (信用卡) + */ + BOSH_CREDIT("上海银行 (信用卡)"), + /** + * 华润银行(借记卡) + */ + CRB_DEBIT("华润银行(借记卡)"), + /** + * 杭州银行(借记卡) + */ + HZB_DEBIT("杭州银行(借记卡)"), + /** + * 杭州银行(信用卡) + */ + HZB_CREDIT("杭州银行(信用卡)"), + /** + * 包商银行(借记卡) + */ + BSB_DEBIT("包商银行(借记卡)"), + /** + * 包商银行 (信用卡) + */ + BSB_CREDIT("包商银行 (信用卡)"), + /** + * 重庆银行(借记卡) + */ + CQB_DEBIT("重庆银行(借记卡)"), + /** + * 顺德农商行 (借记卡) + */ + SDEB_DEBIT("顺德农商行 (借记卡)"), + /** + * 深圳农商银行(借记卡) + */ + SZRCB_DEBIT("深圳农商银行(借记卡)"), + /** + * 哈尔滨银行(借记卡) + */ + HRBB_DEBIT("哈尔滨银行(借记卡)"), + /** + * 成都银行(借记卡) + */ + BOCD_DEBIT("成都银行(借记卡)"), + /** + * 南粤银行 (借记卡) + */ + GDNYB_DEBIT("南粤银行 (借记卡)"), + /** + * 南粤银行 (信用卡) + */ + GDNYB_CREDIT("南粤银行 (信用卡)"), + /** + * 广州银行(信用卡) + */ + GZCB_CREDIT("广州银行(信用卡)"), + /** + * 江苏银行(借记卡) + */ + JSB_DEBIT("江苏银行(借记卡)"), + /** + * 江苏银行(信用卡) + */ + JSB_CREDIT("江苏银行(信用卡)"), + /** + * 宁波银行(借记卡) + */ + NBCB_DEBIT("宁波银行(借记卡)"), + /** + * 宁波银行(信用卡) + */ + NBCB_CREDIT("宁波银行(信用卡)"), + /** + * 南京银行(借记卡) + */ + NJCB_DEBIT("南京银行(借记卡)"), + /** + * 青岛银行(借记卡) + */ + QDCCB_DEBIT("青岛银行(借记卡)"), + /** + * 浙江泰隆银行(借记卡) + */ + ZJTLCB_DEBIT("浙江泰隆银行(借记卡)"), + /** + * 西安银行(借记卡) + */ + XAB_DEBIT("西安银行(借记卡)"), + /** + * 常熟农商银行 (借记卡) + */ + CSRCB_DEBIT("常熟农商银行 (借记卡)"), + /** + * 齐鲁银行(借记卡) + */ + QLB_DEBIT("齐鲁银行(借记卡)"), + /** + * 龙江银行(借记卡) + */ + LJB_DEBIT("龙江银行(借记卡)"), + /** + * 华夏银行(借记卡) + */ + HXB_DEBIT("华夏银行(借记卡)"), + /** + * 测试银行借记卡快捷支付 (借记卡) + */ + CS_DEBIT("测试银行借记卡快捷支付 (借记卡)"), + /** + * AE (信用卡) + */ + AE_CREDIT("AE (信用卡)"), + /** + * JCB (信用卡) + */ + JCB_CREDIT("JCB (信用卡)"), + /** + * MASTERCARD (信用卡) + */ + MASTERCARD_CREDIT("MASTERCARD (信用卡)"), + /** + * VISA (信用卡) + */ + VISA_CREDIT("VISA (信用卡)"); + + private String desc; + + BankType(String desc) { + this.desc = desc; + } + + public String getDesc() { + return desc; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/CredentialType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/CredentialType.java new file mode 100644 index 00000000..4cd93298 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/CredentialType.java @@ -0,0 +1,23 @@ +package com.foxinmy.weixin4j.pay.type; + +/** + * 证件类型 + * + * @className CredentialType + * @author jinyu(foxinmy@gmail.com) + * @date 2016年3月27日 + * @since JDK 1.6 + * @see + */ +public enum CredentialType { + IDCARD("身份证"); + CredentialType(String name) { + this.name = name; + } + + private String name; + + public String getName() { + return this.name; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/CurrencyType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/CurrencyType.java new file mode 100644 index 00000000..21c288bc --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/CurrencyType.java @@ -0,0 +1,25 @@ +package com.foxinmy.weixin4j.pay.type; + +/** + * 币种 + * + * @className CurrencyType + * @author jinyu(foxinmy@gmail.com) + * @date 2014年11月2日 + * @since JDK 1.6 + * @see + */ +public enum CurrencyType { + CNY("人民币"), HKD("港元"), TWD("台币"), EUR("欧元"), USD("美元"), GBP("英镑"), JPY("日元"), CAD( + "加拿大元"), AUD("澳大利亚元"), NZD("新西兰元"), KRW("韩元"), THB("泰铢"); + + private String desc; + + CurrencyType(String desc) { + this.desc = desc; + } + + public String getDesc() { + return desc; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/CustomsCity.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/CustomsCity.java new file mode 100644 index 00000000..2922c1a4 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/CustomsCity.java @@ -0,0 +1,26 @@ +package com.foxinmy.weixin4j.pay.type; + +/** + * 海关 + * + * @className CustomsCity + * @author jinyu(foxinmy@gmail.com) + * @date 2016年3月27日 + * @since JDK 1.6 + * @see + */ +public enum CustomsCity { + NO("无需上报海关"), GUANGZHOU("广州"), HANGZHOU("杭州"), NINGBO("宁波"), ZHENGZHOU_BS( + "郑州(保税物流中心)"), CHONGQING("重庆"), XIAN("西安"), SHANGHAI("上海"), ZHENGZHOU_ZH( + "郑州(综保区)"); + + private String name; + + CustomsCity(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/CustomsSatus.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/CustomsSatus.java new file mode 100644 index 00000000..55442274 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/CustomsSatus.java @@ -0,0 +1,24 @@ +package com.foxinmy.weixin4j.pay.type; + +/** + * 报关状态 + * + * @className CustomsSatus + * @author jinyu(foxinmy@gmail.com) + * @date 2016年3月27日 + * @since JDK 1.6 + * @see + */ +public enum CustomsSatus { + UNDECLARED("未申报"), SUBMITTED("申报已提交"), PROCESSING("申报中"), SUCCESS("申报成功"), FAIL( + "申报失败"), EXCEPT("海关接口异常"); + private String sate; + + CustomsSatus(String sate) { + this.sate = sate; + } + + public String getSate() { + return this.sate; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/IdQuery.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/IdQuery.java new file mode 100644 index 00000000..175a87ba --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/IdQuery.java @@ -0,0 +1,45 @@ +package com.foxinmy.weixin4j.pay.type; + +import java.io.Serializable; + +/** + * ID查询 + * + * @className IdQuery + * @author jinyu(foxinmy@gmail.com) + * @date 2014年11月1日 + * @since JDK 1.6 + * @see + */ +public class IdQuery implements Serializable { + + private static final long serialVersionUID = -5273675987521807370L; + /** + * id值 + */ + private String id; + /** + * id类型 + * + * @see IdType + */ + private IdType type; + + public IdQuery(String id, IdType idType) { + this.id = id; + this.type = idType; + } + + public String getId() { + return id; + } + + public IdType getType() { + return type; + } + + @Override + public String toString() { + return String.format("%s=%s", type.getName(), id); + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/IdType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/IdType.java new file mode 100644 index 00000000..8af90392 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/IdType.java @@ -0,0 +1,46 @@ +package com.foxinmy.weixin4j.pay.type; + +/** + * ID类型 + * + * @className IdType + * @author jinyu(foxinmy@gmail.com) + * @date 2014年11月1日 + * @since JDK 1.6 + * @see + */ +public enum IdType { + /** + * 微信退款单号 + */ + REFUNDID("refund_id"), + /** + * 微信订单号 + */ + TRANSACTIONID("transaction_id"), + /** + * 商户订单号 + */ + TRADENO("out_trade_no"), + /** + * 商户退款号 + */ + REFUNDNO("out_refund_no"), + /** + * 商户子订单号 + */ + SUBORDERNO("sub_order_no"), + /** + * 微信子订单号 + */ + SUBORDERID("sub_order_id"); + private String name; + + IdType(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/SignType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/SignType.java new file mode 100644 index 00000000..d961b1c1 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/SignType.java @@ -0,0 +1,14 @@ +package com.foxinmy.weixin4j.pay.type; + +/** + * 签名类型 + * + * @className SignType + * @author jinyu(foxinmy@gmail.com) + * @date 2014年11月5日 + * @since JDK 1.6 + * @see + */ +public enum SignType { + MD5, HMAC$SHA256 +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/TarType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/TarType.java new file mode 100644 index 00000000..bc4e32bb --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/TarType.java @@ -0,0 +1,14 @@ +package com.foxinmy.weixin4j.pay.type; + +/** + * 压缩类型 + * + * @className TarType + * @author jinyu(foxinmy@gmail.com) + * @date 2016年12月21日 + * @since JDK 1.6 + * @see + */ +public enum TarType { + GZIP +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/TradeState.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/TradeState.java new file mode 100644 index 00000000..14a30e3c --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/TradeState.java @@ -0,0 +1,46 @@ +package com.foxinmy.weixin4j.pay.type; + +/** + * 交易状态 + * + * @className TradeState + * @author jinyu(foxinmy@gmail.com) + * @date 2014年11月2日 + * @since JDK 1.6 + * @see + * @deprecated 迁移到子模块weixin4j-pay + */ +public enum TradeState { + /** + * 支付成功 + */ + SUCCESS, + /** + * 转入退款 + */ + REFUND, + /** + * 未支付 + */ + NOTPAY, + /** + * 已关闭 + */ + CLOSED, + /** + * 已撤销 + */ + REVOKED, + /** + * 用户支付中 + */ + USERPAYING, + /** + * 未支付(输入密码或 确认支付超时) + */ + NOPAY, + /** + * 支付失败(其他 原因,如银行返回失败) + */ + PAYERROR; +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/TradeType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/TradeType.java new file mode 100644 index 00000000..c9bfc2e2 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/TradeType.java @@ -0,0 +1,37 @@ +package com.foxinmy.weixin4j.pay.type; + +/** + * 微信支付类型 + * + * @className TradeType + * @author jinyu(foxinmy@gmail.com) + * @date 2014年10月21日 + * @since JDK 1.6 + * @see + */ +public enum TradeType { + /** + * JS支付 + */ + JSAPI, + /** + * 刷卡支付 + */ + MICROPAY, + /** + * 扫码支付 + */ + NATIVE, + /** + * APP支付 + */ + APP, + /** + * WAP支付 + */ + MWEB, + /** + * 刷脸支付 + */ + FACEPAY; +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/BillType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/BillType.java new file mode 100644 index 00000000..85f1ab14 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/BillType.java @@ -0,0 +1,34 @@ +package com.foxinmy.weixin4j.pay.type.mch; + +/** + * 对账单类型 + * + * @className BillType + * @author jinyu(foxinmy@gmail.com) + * @date 2014年10月31日 + * @since JDK 1.6 + * @see + */ +public enum BillType { + /** + * 全部 + */ + ALL(0), + /** + * 成功订单 + */ + SUCCESS(1), + /** + * 退款订单 + */ + REFUND(2); + private int val; + + BillType(int val) { + this.val = val; + } + + public int getVal() { + return val; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/CorpPaymentCheckNameType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/CorpPaymentCheckNameType.java new file mode 100644 index 00000000..c109432f --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/CorpPaymentCheckNameType.java @@ -0,0 +1,25 @@ +package com.foxinmy.weixin4j.pay.type.mch; + +/** + * 企业付款检查收款人姓名的策略 + * + * @className CorpPaymentCheckNameType + * @author jinyu(foxinmy@gmail.com) + * @date 2015年4月1日 + * @since JDK 1.6 + * @see + */ +public enum CorpPaymentCheckNameType { + /** + * 不校验真实姓名 + */ + NO_CHECK, + /** + * 强校验真实姓名(未实名认证的用户会校验失败,无法转账) + */ + FORCE_CHECK, + /** + * 针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功) + */ + OPTION_CHECK; +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/CouponStatus.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/CouponStatus.java new file mode 100644 index 00000000..696e073c --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/CouponStatus.java @@ -0,0 +1,34 @@ +package com.foxinmy.weixin4j.pay.type.mch; + +/** + * 代金券状态 + * + * @className CouponStatus + * @author jinyu(foxinmy@gmail.com) + * @date 2015年3月27日 + * @since JDK 1.6 + * @see + */ +public enum CouponStatus { + /** + * 已激活 + */ + ACTIVATED(2), + /** + * 已锁定 + */ + LOCKED(4), + /** + * 已实扣 + */ + USED(8); + private int val; + + CouponStatus(int val) { + this.val = val; + } + + public int getVal() { + return val; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/CouponStockStatus.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/CouponStockStatus.java new file mode 100644 index 00000000..36b6bd4b --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/CouponStockStatus.java @@ -0,0 +1,42 @@ +package com.foxinmy.weixin4j.pay.type.mch; + +/** + * 代金券批次状态 + * + * @className CouponStockStatus + * @author jinyu(foxinmy@gmail.com) + * @date 2015年3月27日 + * @since JDK 1.6 + * @see + */ +public enum CouponStockStatus { + /** + * 未激活 + */ + INACTIVE(1), + /** + * 审批中 + */ + APPROVAL_PROCESS(2), + /** + * 已激活 + */ + ACTIVATED(4), + /** + * 已作废 + */ + SUPERSEDED(8), + /** + * 中止发放 + */ + SUSPEND(16); + private int val; + + CouponStockStatus(int val) { + this.val = val; + } + + public int getVal() { + return val; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/CouponStockType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/CouponStockType.java new file mode 100644 index 00000000..896b8d7f --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/CouponStockType.java @@ -0,0 +1,30 @@ +package com.foxinmy.weixin4j.pay.type.mch; + +/** + * 代金券批次类型 + * + * @className CouponStockType + * @author jinyu(foxinmy@gmail.com) + * @date 2015年3月27日 + * @since JDK 1.6 + * @see + */ +public enum CouponStockType { + /** + * 批量型 + */ + BATCH(1), + /** + * 触发型 + */ + TRIGGER(2); + private int val; + + CouponStockType(int val) { + this.val = val; + } + + public int getVal() { + return val; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/CouponType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/CouponType.java new file mode 100644 index 00000000..6dd536fb --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/CouponType.java @@ -0,0 +1,43 @@ +package com.foxinmy.weixin4j.pay.type.mch; + +/** + * 代金券类型 + * + * @className CouponType + * @author jinyu(foxinmy@gmail.com) + * @date 2015年3月27日 + * @since JDK 1.6 + * @see + */ +public enum CouponType { + /** + * 使用无门槛 + */ + NO_THRESHOLD(1), + /** + * 使用有门槛 + */ + HAS_THRESHOLD(2), + /** + * 门槛叠加 + */ + THRESHOLD_PLUS(3), + + /** + * 充值代金券 + */ + CASH(-1), + /** + * 非充值代金券 + */ + NO_CASH(-2); + private int val; + + CouponType(int val) { + this.val = val; + } + + public int getVal() { + return val; + } +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/DepositType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/DepositType.java new file mode 100644 index 00000000..08524415 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/DepositType.java @@ -0,0 +1,20 @@ +package com.foxinmy.weixin4j.pay.type.mch; + +/** + * 是否押金支付 + * + * @className DepositType + * @author kit(kit_21cn@21cn.com) + * @date 2019年9月21日 + * @since JDK 1.6 + */ +public enum DepositType { + /** + * 是 + */ + Y, + /** + * 否 + */ + N; +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RedpacketSceneType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RedpacketSceneType.java new file mode 100644 index 00000000..341542b2 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RedpacketSceneType.java @@ -0,0 +1,44 @@ +package com.foxinmy.weixin4j.pay.type.mch; + +/** + * 发放红包使用场景 + * + * @className RedpacketSceneType + * @author jinyu(foxinmy@gmail.com) + * @date 2017年1月4日 + * @since JDK 1.6 + */ +public enum RedpacketSceneType { + /** + * 商品促销 + */ + PRODUCT_1, + /** + * 抽奖 + */ + PRODUCT_2, + /** + * 虚拟物品兑奖 + */ + PRODUCT_3, + /** + * 企业内部福利 + */ + PRODUCT_4, + /** + * 渠道分润 + */ + PRODUCT_5, + /** + * 保险回馈 + */ + PRODUCT_6, + /** + * 彩票派奖 + */ + PRODUCT_7, + /** + * 税务刮奖 + */ + PRODUCT_8 +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RedpacketSendType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RedpacketSendType.java new file mode 100644 index 00000000..55ba69b3 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RedpacketSendType.java @@ -0,0 +1,25 @@ +package com.foxinmy.weixin4j.pay.type.mch; + +/** + * 红包发放类型 + * + * @className RedpacketSendType + * @author jinyu(foxinmy@gmail.com) + * @date 2015年6月4日 + * @since JDK 1.6 + * @see + */ +public enum RedpacketSendType { + /** + * 通过API接口发放 + */ + API, + /** + * 通过上传文件方式发放 + */ + UPLOAD, + /** + * 通过活动方式发放 + */ + ACTIVITY; +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RedpacketStatus.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RedpacketStatus.java new file mode 100644 index 00000000..5b440ae7 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RedpacketStatus.java @@ -0,0 +1,32 @@ +package com.foxinmy.weixin4j.pay.type.mch; + +/** + * 红包状态 + * @className RedpacketStatus + * @author jinyu(foxinmy@gmail.com) + * @date 2015年6月4日 + * @since JDK 1.6 + * @see + */ +public enum RedpacketStatus { + /** + * 发放中 + */ + SENDING, + /** + * 已发放待领取 + */ + SENT, + /** + * 发放失败 + */ + FAILED, + /** + * 已领取 + */ + RECEIVED, + /** + * 已退款 + */ + REFUND; +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RedpacketType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RedpacketType.java new file mode 100644 index 00000000..d59ed2c9 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RedpacketType.java @@ -0,0 +1,21 @@ +package com.foxinmy.weixin4j.pay.type.mch; + +/** + * 红包类型 + * + * @className RedpacketType + * @author jinyu(foxinmy@gmail.com) + * @date 2015年6月4日 + * @since JDK 1.6 + * @see + */ +public enum RedpacketType { + /** + * 裂变红包 + */ + GROUP, + /** + * 普通红包 + */ + NORMAL; +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RefundAccountType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RefundAccountType.java new file mode 100644 index 00000000..4e64b914 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RefundAccountType.java @@ -0,0 +1,18 @@ +package com.foxinmy.weixin4j.pay.type.mch; + +/** + * 退款资金来源 + * @className RefundAccountType + * @author jinyu(foxinmy@gmail.com) + * @date 2016年12月12日 + */ +public enum RefundAccountType { + /** + * ---未结算资金退款(默认使用未结算资金退款) + */ + REFUND_SOURCE_UNSETTLED_FUNDS, + /** + * ---可用余额退款 + */ + REFUND_SOURCE_RECHARGE_FUNDS +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RefundChannel.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RefundChannel.java new file mode 100644 index 00000000..40b01e07 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RefundChannel.java @@ -0,0 +1,37 @@ +package com.foxinmy.weixin4j.pay.type.mch; + +/** + * 退款渠道 + * + * @className RefundChannel + * @author jinyu(foxinmy@gmail.com) + * @date 2014年11月6日 + * @since JDK 1.6 + * @see + */ +public enum RefundChannel { + /** + * 原路退款 + */ + ORIGINAL, + /** + * 退回到余额 + */ + BALANCE, + /** + * 财付通 + */ + TENPAY, + /** + * 银行 + */ + BANK, + /** + * 原账户异常退到其他余额账户 + */ + OTHER_BALANCE, + /** + * 原银行卡异常退到其他银行卡 + */ + OTHER_BANKCARD +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RefundStatus.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RefundStatus.java new file mode 100644 index 00000000..b4fe3e2a --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RefundStatus.java @@ -0,0 +1,34 @@ +package com.foxinmy.weixin4j.pay.type.mch; + +/** + * 退款状态 + * + * @className RefundStatus + * @author jinyu(foxinmy@gmail.com) + * @date 2014年11月2日 + * @since JDK 1.6 + * @see + */ +public enum RefundStatus { + /** + * 退款成功 + */ + SUCCESS, + /** + * 退款失败 + */ + FAIL, + /** + * 退款处理中 + */ + PROCESSING, + /** + * 未确定,需要商户 原退款单号重新发起 + */ + NOTSURE, + /** + * 转入代发,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,资金回流到商户的现金帐号,需要商户人工干预,通过线下或者财付通转 + * 账的方式进行退款。 + */ + CHANGE; +} diff --git a/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RefundType.java b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RefundType.java new file mode 100644 index 00000000..fd96a037 --- /dev/null +++ b/weixin4j-pay/src/main/java/com/foxinmy/weixin4j/pay/type/mch/RefundType.java @@ -0,0 +1,35 @@ +package com.foxinmy.weixin4j.pay.type.mch; + +/** + * 退款类型 + * + * @className RefundType + * @author jinyu(foxinmy@gmail.com) + * @date 2014年12月31日 + * @since JDK 1.6 + * @see + */ +public enum RefundType { + /** + * 1:商户号余额退款; + */ + BALANCE(1), + /** + * 2:现金帐号 退款; + */ + CASH(2), + /** + * 3:优先商户号退款,若商户号余额不足, 再做现金帐号退款。 使用 2 或 3 时,需联系财 付通开通此功能 + */ + BOTH(3); + + private int val; + + RefundType(int val) { + this.val = val; + } + + public int getVal() { + return val; + } +} diff --git a/weixin4j-pay/src/main/resources/com/foxinmy/weixin4j/payment/weixin.properties b/weixin4j-pay/src/main/resources/com/foxinmy/weixin4j/payment/weixin.properties new file mode 100644 index 00000000..635bb53b --- /dev/null +++ b/weixin4j-pay/src/main/resources/com/foxinmy/weixin4j/payment/weixin.properties @@ -0,0 +1,64 @@ +# \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 +payapp_base_url=https://payapp.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}/mmpaymkttransfers/querycouponsinfo +# \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 +# \u67E5\u8BE2\u7ED3\u7B97\u8D44\u91D1 +settlement_query_uri={mch_base_url}/pay/settlementquery +# \u67E5\u8BE2\u6C47\u7387 +exchagerate_query_uri={mch_base_url}/pay/queryexchagerate +# \u8BA2\u5355\u9644\u52A0\u4FE1\u606F\u63D0\u4EA4 +customsorder_declare_uri={mch_base_url}/mch/customs/customdeclareorder +# \u8BA2\u5355\u9644\u52A0\u4FE1\u606F\u67E5\u8BE2 +customsorder_query_uri={mch_base_url}/mch/customs/customdeclarequery +# \u5237\u8138\u652F\u4ED8\u4EA4\u4E92\u6D41\u7A0B--\u83B7\u53D6\u8C03\u7528\u51ED\u8BC1 +get_wxpayface_authinfo_uri={payapp_base_url}/face/get_wxpayface_authinfo +# \u65E7\u7248\u5237\u8138\u652F\u4ED8\u63A5\u53E3 +facepay_url={mch_base_url}/pay/facepay +# \u652F\u4ED8\u62BC\u91D1\uFF08\u4EBA\u8138\uFF09 +deposit_facepay_uri={mch_base_url}/deposit/facepay +# \u652F\u4ED8\u62BC\u91D1\uFF08\u4ED8\u6B3E\u7801\uFF09 +deposit_micropay_uri={mch_base_url}/deposit/micropay \ No newline at end of file diff --git a/weixin4j-pay/src/main/resources/weixin4j.properties b/weixin4j-pay/src/main/resources/weixin4j.properties new file mode 100644 index 00000000..1f14b8bc --- /dev/null +++ b/weixin4j-pay/src/main/resources/weixin4j.properties @@ -0,0 +1,2 @@ +# \u914D\u7F6E\u5F53\u4F7F\u7528jdkLogger\u65F6\uFF0C\u65E5\u5FD7\u7684\u7EA7\u522B +# weixin4j.jdkLogger.level=INFO diff --git a/weixin4j-pay/src/test/java/com/foxinmy/weixin4j/pay/test/TestDepositPay.java b/weixin4j-pay/src/test/java/com/foxinmy/weixin4j/pay/test/TestDepositPay.java new file mode 100644 index 00000000..13ef92bb --- /dev/null +++ b/weixin4j-pay/src/test/java/com/foxinmy/weixin4j/pay/test/TestDepositPay.java @@ -0,0 +1,26 @@ +package com.foxinmy.weixin4j.pay.test; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.pay.WeixinPayProxy; +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.payment.mch.MchPayRequest; +import org.junit.Test; + +public class TestDepositPay { + @Test + public void test() throws WeixinException { + String appid = ""; + String mchid = ""; + String paySignKey = ""; + String code = ""; + boolean isFacePay = false; //true - 人脸押金支付,false - 付款码押金支付 + + WeixinPayAccount payAccount = new WeixinPayAccount(appid, paySignKey, mchid); + payAccount.setSubMchId(mchid); + WeixinPayProxy proxy = new WeixinPayProxy(payAccount); + + MchPayRequest payRequest = proxy.createDepositPayRequest(code, "测试押金支付", "TESTORDER20190921001", 0.01, + "127.0.0.1", null, null, null, isFacePay); + System.out.println(payRequest.toRequestString()); + } +} diff --git a/weixin4j-pay/src/test/java/com/foxinmy/weixin4j/pay/test/TestFacePay.java b/weixin4j-pay/src/test/java/com/foxinmy/weixin4j/pay/test/TestFacePay.java new file mode 100644 index 00000000..8b3145c1 --- /dev/null +++ b/weixin4j-pay/src/test/java/com/foxinmy/weixin4j/pay/test/TestFacePay.java @@ -0,0 +1,31 @@ +package com.foxinmy.weixin4j.pay.test; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.pay.WeixinPayProxy; +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.payment.mch.MchPayRequest; +import com.foxinmy.weixin4j.pay.type.mch.DepositType; +import org.junit.Test; + +public class TestFacePay { + @Test + public void test() throws WeixinException { + String appid = ""; + String mchid = ""; + String paySignKey = ""; + WeixinPayAccount payAccount = new WeixinPayAccount(appid, paySignKey, mchid); + WeixinPayProxy proxy = new WeixinPayProxy(payAccount); + + String orderNo = "TESTORDER2019092001"; + String openId = "oguJRswolIOGg7Vd1VaqGJuDBFAE"; + String faceCode = "0f879a6c-5fff-421c-a233-5fac0f4aad12"; + + MchPayRequest rsp = proxy.createFacePayRequest(faceCode, "测试的人脸支付", + orderNo, 1, + "127.0.0.1", openId, null); + + JSONObject obj = (JSONObject) JSON.toJSON(rsp); + } +} \ No newline at end of file diff --git a/weixin4j-pay/src/test/java/com/foxinmy/weixin4j/pay/test/TestGetPayFaceAuthInfo.java b/weixin4j-pay/src/test/java/com/foxinmy/weixin4j/pay/test/TestGetPayFaceAuthInfo.java new file mode 100644 index 00000000..57ac56a7 --- /dev/null +++ b/weixin4j-pay/src/test/java/com/foxinmy/weixin4j/pay/test/TestGetPayFaceAuthInfo.java @@ -0,0 +1,24 @@ +package com.foxinmy.weixin4j.pay.test; + +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.pay.WeixinPayProxy; +import com.foxinmy.weixin4j.pay.model.WeixinPayAccount; +import com.foxinmy.weixin4j.pay.payment.face.PayfaceAuthinfo; +import org.junit.Assert; +import org.junit.Test; + +public class TestGetPayFaceAuthInfo { + @Test + public void test() throws WeixinException { + String appid = ""; + String mchid = ""; + String paySignKey = ""; + String rawData = "7rfwfRXEDBBbs5MjHW67ritEHtQ7AchIcd0E1zfBxmxyIEXA3aiPTdtrZ1I1fXn6Mpyln11al546YOfNK/HXe81b589a9EyAHuoziZmoe+qJFf2ulkwBWOFffnSN05Qy/ykboG4PciO5yvIMlKEEdmqEjj4ck9oBmAKCqXCM2bRDqNEQOuckZGqGsJsM4xyKEZmlL4cLk+/l9xtvOseJccBeDJfkg5fAdwG1z7lX1DThdyb8uRuE3UCvVghQ21KslyIrF9G6rhh3bP83sD//QklJsdf/dapidxkCACfZkGyNl7wFDnjj5bUgwj9pYW3gQBUff606pI9Eh7VoLwFb768DGfSGHVTwQOPeq+Ldu0bAFyuTNFZUBETYnOCZx0ue7ehDmfmFSxyqVfLRhmlMTPHC/AHRVp6wwg1EnQUTRpUltHdn4O3w5B0PRDVlXogdri0WaTDyrYo18GaZvUdCWld09NZboEPknWEgfQfwaF4vow6R4negvKCVna5kNbjDlDRWNaN+AKtHIznnPKWipc6UunBKeMw/kNTced2f73dUEDALGLPE41nnxA7y1uePWMXVJyNGnWxk461/nz6g/NfyJAgIOILrO1wThEhBd6tFAJGQwu366fnN/5eU9XfBzApHE+OIrtYyRLYJHVaAsAeXOy+PvVqMUFkEWJ3iSLJUZhLJYUbnqVEZaIeAvMY0NJ5+E26WvXXhIGr91gPq35aEjuPu4LKbGTw1jgM="; + + WeixinPayAccount payAccount = new WeixinPayAccount(appid, paySignKey, mchid); + WeixinPayProxy proxy = new WeixinPayProxy(payAccount); + PayfaceAuthinfo info = proxy.getWxPayfaceAuthinfo("TEST01", "甘坑客家小镇", "TESTDEVICE01", rawData); + System.out.print(info); + Assert.assertEquals("SUCCESS", info.getReturnCode()); + } +} diff --git a/weixin4j-pay/src/test/java/com/foxinmy/weixin4j/pay/test/TestHmacSHA256Sign.java b/weixin4j-pay/src/test/java/com/foxinmy/weixin4j/pay/test/TestHmacSHA256Sign.java new file mode 100644 index 00000000..b8a9a775 --- /dev/null +++ b/weixin4j-pay/src/test/java/com/foxinmy/weixin4j/pay/test/TestHmacSHA256Sign.java @@ -0,0 +1,24 @@ +package com.foxinmy.weixin4j.pay.test; + +import com.alibaba.fastjson.JSONObject; +import com.foxinmy.weixin4j.pay.sign.WeixinPaymentSignature; +import com.foxinmy.weixin4j.pay.type.SignType; +import org.junit.Assert; +import org.junit.Test; + +/** + * HmacSHA256签名算法测试 + * @author kit (kit_21cn@21cn.com) + */ +public class TestHmacSHA256Sign { + @Test + public void test(){ + WeixinPaymentSignature signature = new WeixinPaymentSignature("muses"); + JSONObject json = new JSONObject(); + json.put("appid", "1"); + json.put("mch_id", "2"); + String sign = signature.sign(json, SignType.HMAC$SHA256); + + Assert.assertEquals("637CF27B23F731398B2BE0118F484191B3728749C25D1EEF7479B6E93033602C", sign); + } +}