diff --git a/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/api/WxCombinePayService.java b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/api/WxCombinePayService.java new file mode 100644 index 0000000..4c99699 --- /dev/null +++ b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/api/WxCombinePayService.java @@ -0,0 +1,159 @@ +package com.egzosn.pay.wx.v3.api; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.egzosn.pay.common.bean.CloseOrder; +import com.egzosn.pay.common.bean.Order; +import com.egzosn.pay.common.bean.OrderParaStructure; +import com.egzosn.pay.common.bean.PayMessage; +import com.egzosn.pay.common.bean.PayOrder; +import com.egzosn.pay.common.bean.result.PayException; +import com.egzosn.pay.common.exception.PayErrorException; +import com.egzosn.pay.common.http.HttpConfigStorage; +import com.egzosn.pay.common.util.DateUtils; +import com.egzosn.pay.common.util.MapGen; +import com.egzosn.pay.common.util.str.StringUtils; +import com.egzosn.pay.wx.v3.bean.WxTransactionType; +import com.egzosn.pay.wx.v3.bean.combine.CombinePayMessage; +import com.egzosn.pay.wx.v3.utils.WxConst; + +/** + * 微信合单支付服务 + * + * @author egan + *
+ * email egzosn@gmail.com + * date 2016-5-18 14:09:01 + *+ */ +public class WxCombinePayService extends WxPayService { + + /** + * 创建支付服务 + * + * @param payConfigStorage 微信对应的支付配置 + */ + public WxCombinePayService(WxPayConfigStorage payConfigStorage) { + super(payConfigStorage); + } + + /** + * 创建支付服务 + * + * @param payConfigStorage 微信对应的支付配置 + * @param configStorage 微信对应的网络配置,包含代理配置、ssl证书配置 + */ + public WxCombinePayService(WxPayConfigStorage payConfigStorage, HttpConfigStorage configStorage) { + super(payConfigStorage, configStorage); + } + + + /** + * 获取公共参数 + * + * @return 公共参数 + */ + public Map
+ * email egan@egzosn.com + * date 2021/10/5 + *+ */ +public class CombineAmount extends Amount { + + /** + * 子单金额,单位为分,必填 + * 境外场景下,标价金额要超过商户结算币种的最小单位金额,例如结算币种为美元,则标价金额必须大于1美分 + */ + @JSONField(name = "total_amount") + private Integer totalAmount; + + + public Integer getTotalAmount() { + return totalAmount; + } + + public void setTotalAmount(Integer totalAmount) { + this.totalAmount = totalAmount; + } + + +} \ No newline at end of file diff --git a/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/combine/CombineCloseOrder.java b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/combine/CombineCloseOrder.java new file mode 100644 index 0000000..cef6267 --- /dev/null +++ b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/combine/CombineCloseOrder.java @@ -0,0 +1,30 @@ +package com.egzosn.pay.wx.v3.bean.combine; + +import java.util.List; + +import com.egzosn.pay.common.bean.CloseOrder; +import com.egzosn.pay.wx.v3.utils.WxConst; + +/** + * 微信合单关闭订单 + * @author Egan + * @email egan@egzosn.com + * @date 2021/10/6 + */ +public class CombineCloseOrder extends CloseOrder { + + /** + * 子单信息,必填,最多50单 + */ + private List
+ * email egan@egzosn.com + * date 2021/10/4 + *+ */ +public class CombinePayMessage extends PayMessage { + + + /** + * 合单商户appid,即合单发起方的appid + */ + @JSONField(name = WxConst.COMBINE_APPID) + private String combineAppid; + + /** + * 合单商户号. + */ + @JSONField(name = WxConst.COMBINE_MCH_ID) + private String combineMchid; + + /** + * 合单商户订单号. + */ + @JSONField(name = WxConst.COMBINE_OUT_TRADE_NO) + private String combineOutTradeNo; + + + /** + * 支付者信息 + */ + @JSONField(name = "combine_payer_info") + private Payer combinePayerInfo; + + /** + * 场景信息,合单支付回调只返回device_id + */ + @JSONField(name = WxConst.SCENE_INFO) + private SceneInfo sceneInfo; + + /** + * 合单支付回调子订单. + */ + @JSONField(name = WxConst.SUB_ORDERS) + private List
+ * email egan@egzosn.com + * date 2021/10/5 + *+ */ +public class CombinePayOrder extends PayOrder { + + /** + * 子单信息,必填,最多50单 + */ + private List
+ * email egan@egzosn.com + * date 2021/10/5 + *+ */ +public class CombineSubOrder { + + /** + * 子单发起方商户号,必填,必须与发起方appid有绑定关系。 + */ + private String mchid; + + /** + * 商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。 + * 示例值:20150806125346 + */ + @JSONField(name = "out_trade_no") + private String outTradeNo; + + public String getMchid() { + return mchid; + } + + public void setMchid(String mchid) { + this.mchid = mchid; + } + + public String getOutTradeNo() { + return outTradeNo; + } + + public void setOutTradeNo(String outTradeNo) { + this.outTradeNo = outTradeNo; + } +} diff --git a/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/order/SettleInfo.java b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/order/SettleInfo.java new file mode 100644 index 0000000..4ce0a7c --- /dev/null +++ b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/order/SettleInfo.java @@ -0,0 +1,45 @@ +package com.egzosn.pay.wx.v3.bean.order; + +import com.alibaba.fastjson.annotation.JSONField; + +/** + * 结算信息 + * @author Egan + *
+ * email egan@egzosn.com + * date 2021/10/5 + *+ */ +public class SettleInfo { + /** + * 是否指定分账,枚举值 + * true:是 + * false:否 + * 示例值:true + */ + @JSONField(name = "profit_sharing") + private Boolean profitSharing; + /** + * 补差金额 + * SettleInfo.profit_sharing为true时,该金额才生效。 + * 注意:单笔订单最高补差金额为5000元 + */ + @JSONField(name = "subsidy_amount") + private Integer subsidyAmount; + + public Boolean getProfitSharing() { + return profitSharing; + } + + public void setProfitSharing(Boolean profitSharing) { + this.profitSharing = profitSharing; + } + + public Integer getSubsidyAmount() { + return subsidyAmount; + } + + public void setSubsidyAmount(Integer subsidyAmount) { + this.subsidyAmount = subsidyAmount; + } +} diff --git a/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/order/SubOrder.java b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/order/SubOrder.java new file mode 100644 index 0000000..0b0010d --- /dev/null +++ b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/order/SubOrder.java @@ -0,0 +1,187 @@ +package com.egzosn.pay.wx.v3.bean.order; + +import java.util.Date; +import java.util.List; + +import com.alibaba.fastjson.annotation.JSONField; +import com.egzosn.pay.wx.v3.bean.WxTransactionType; +import com.egzosn.pay.wx.v3.bean.combine.CombineAmount; +import com.egzosn.pay.wx.v3.bean.combine.CombineSubOrder; +import com.egzosn.pay.wx.v3.bean.response.order.PromotionDetail; +import com.egzosn.pay.wx.v3.bean.response.order.TradeState; + +/** + * 子单信息,最多50单. + * + * @author Egan + *
+ * email egan@egzosn.com + * date 2021/10/5 + *+ */ +public class SubOrder extends CombineSubOrder { + /** + * 合单支付订单金额信息,必填。 + */ + private CombineAmount amount; + + + /** + * 商品描述,必填,需传入应用市场上的APP名字-实际商品名称,例如:天天爱消除-游戏充值。 + */ + private String description; + + + /** + * 二级商户商户号,由微信支付生成并下发。 + *
+ * 服务商子商户的商户号,被合单方。 + *
+ * 直连商户不用传二级商户号。
+ */
+ @JSONField(name = "sub_mchid")
+ private String subMchid;
+
+ /**
+ * 结算信息,选填
+ */
+ @JSONField(name = "settle_info")
+ private SettleInfo settleInfo;
+
+
+ /**
+ * 银行类型,采用字符串类型的银行标识。
+ * 银行标识请参考 《银行类型对照表》
+ * 示例值:CMC
+ */
+ @JSONField(name = "bank_type")
+ private String bankType;
+
+ /**
+ * 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用
+ */
+ private String attach;
+
+ /**
+ * 支付完成时间|| 退款完成时间,遵循rfc3339标准格式,
+ * 格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,
+ * TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。
+ * 例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
+ * 示例值:2018-06-08T10:34:56+08:00
+ */
+ @JSONField(name = "success_time", format = "yyyy-MM-dd'T'HH:mm:ssXXX")
+ private Date successTime;
+
+ /**
+ * 交易状态
+ */
+ @JSONField(name = "trade_state")
+ private TradeState tradeState;
+
+ /**
+ * 交易类型
+ */
+ @JSONField(name = "trade_type")
+ private WxTransactionType tradeType;
+
+ /**
+ * 微信支付侧订单号
+ */
+ @JSONField(name = "transaction_id")
+ private String transactionId;
+
+ /**
+ * 优惠功能,子单有核销优惠券时有返回
+ */
+ @JSONField(name = "promotion_detail")
+ private List
* email egan@egzosn.com
@@ -99,8 +99,36 @@ public class WxPayMessage extends PayMessage {
*/
@JSONField(name = "trade_state")
private TradeState tradeState;
-
-
+ /**
+ * 商户退款单号
+ */
+ @JSONField(name = "out_refund_no")
+ private String outRefundNo;
+ /**
+ * 微信退款单号
+ */
+ @JSONField(name = "refund_id")
+ private String refundId;
+ /**
+ * 退款状态,枚举值:
+ * SUCCESS:退款成功
+ * CLOSE:退款关闭
+ * ABNORMAL:退款异常,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往【商户平台—>交易中心】,手动处理此笔退款
+ * 示例值:SUCCESS
+ */
+ @JSONField(name = "refund_status")
+ private TradeState refundStatus;
+ /**
+ * 退款入账账户
+ * 取当前退款单的退款入账方。
+ * 1、退回银行卡:{银行名称}{卡类型}{卡尾号}
+ * 2、退回支付用户零钱: 支付用户零钱
+ * 3、退还商户: 商户基本账户、商户结算银行账户
+ * 4、退回支付用户零钱通:支付用户零钱通
+ * 示例值:招商银行信用卡0403
+ */
+ @JSONField(name = "user_received_account")
+ private String userReceivedAccount;
/**
* 交易状态描述
* 示例值:支付成功
@@ -121,7 +149,7 @@ public class WxPayMessage extends PayMessage {
private String attach;
/**
- * 支付完成时间,遵循rfc3339标准格式,
+ * 支付完成时间|| 退款完成时间,遵循rfc3339标准格式,
* 格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,
* TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。
* 例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
@@ -301,6 +329,37 @@ public class WxPayMessage extends PayMessage {
return BigDecimal.valueOf(getAmount().getTotal());
}
+ public String getOutRefundNo() {
+ return outRefundNo;
+ }
+
+ public void setOutRefundNo(String outRefundNo) {
+ this.outRefundNo = outRefundNo;
+ }
+
+ public String getRefundId() {
+ return refundId;
+ }
+
+ public void setRefundId(String refundId) {
+ this.refundId = refundId;
+ }
+
+ public TradeState getRefundStatus() {
+ return refundStatus;
+ }
+
+ public void setRefundStatus(TradeState refundStatus) {
+ this.refundStatus = refundStatus;
+ }
+
+ public String getUserReceivedAccount() {
+ return userReceivedAccount;
+ }
+
+ public void setUserReceivedAccount(String userReceivedAccount) {
+ this.userReceivedAccount = userReceivedAccount;
+ }
public static final WxPayMessage create(Map
* email egan@egzosn.com
* date 2021/10/4
*
*/
-public class Amount extends com.egzosn.pay.wx.v3.bean.order.Amount{
+public class Amount extends com.egzosn.pay.wx.v3.bean.order.Amount {
/**
* 用户支付金额,单位为分。
*/
+ @JSONField(name = "payer_total")
private BigDecimal payerTotal;
/**
* 用户支付币种
*/
+ @JSONField(name = "payer_currency")
private String payerCurrency;
+ /**
+ * 退款金额,单位为分
+ */
+ private Integer refund;
+
+ /**
+ * 退款给用户的金额,单位为分,不包含所有优惠券金额
+ */
+ @JSONField(name = "payer_refund")
+ private Integer payerRefund;
+
public BigDecimal getPayerTotal() {
return payerTotal;
}
@@ -36,4 +52,20 @@ public class Amount extends com.egzosn.pay.wx.v3.bean.order.Amount{
public void setPayerCurrency(String payerCurrency) {
this.payerCurrency = payerCurrency;
}
+
+ public Integer getRefund() {
+ return refund;
+ }
+
+ public void setRefund(Integer refund) {
+ this.refund = refund;
+ }
+
+ public Integer getPayerRefund() {
+ return payerRefund;
+ }
+
+ public void setPayerRefund(Integer payerRefund) {
+ this.payerRefund = payerRefund;
+ }
}
diff --git a/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/response/order/Payer.java b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/response/order/Payer.java
index 623b97d..7f359f1 100644
--- a/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/response/order/Payer.java
+++ b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/response/order/Payer.java
@@ -11,6 +11,7 @@ package com.egzosn.pay.wx.v3.bean.response.order;
public class Payer {
/**
* 用户在直连商户appid下的唯一标识。
+ * 使用合单appid获取的对应用户openid。是用户在商户appid下的唯一标识。
*/
private String openid;
diff --git a/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/response/order/TradeState.java b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/response/order/TradeState.java
index 6b6afe6..9d49a4c 100644
--- a/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/response/order/TradeState.java
+++ b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/bean/response/order/TradeState.java
@@ -1,7 +1,8 @@
package com.egzosn.pay.wx.v3.bean.response.order;
/**
- * 微信侧返回交易状态
+ * 微信侧返回交易状态,兼容退款状态
+ *
* @author Egan
*
* email egan@egzosn.com
@@ -11,31 +12,28 @@ package com.egzosn.pay.wx.v3.bean.response.order;
public enum TradeState {
/**
* 支付成功
- *
- *
+ * 退款成功
*/
SUCCESS,
/**
* 转入退款
- *
- *
*/
REFUND,
/**
* 未支付
- *
- *
*/
NOTPAY,
/**
* 已关闭
- *
- *
+ * 退款关闭
*/
CLOSED,
+ /**
+ * 退款异常.
+ */
+ ABNORMAL,
/**
* 已撤销(付款码支付)
- *
*/
REVOKED,
/**
@@ -48,7 +46,6 @@ public enum TradeState {
PAYERROR,
/**
* 已接收,等待扣款
- *
*/
ACCEPT,
}
\ No newline at end of file
diff --git a/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/utils/WxConst.java b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/utils/WxConst.java
index 2055d49..941ff10 100644
--- a/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/utils/WxConst.java
+++ b/pay-java-wx/src/main/java/com/egzosn/pay/wx/v3/utils/WxConst.java
@@ -17,7 +17,7 @@ public final class WxConst {
/**
* 微信默认请求地址
*/
- public static final String URI = "https://api.mch.weixin.qq.com/v3/";
+ public static final String URI = "https://api.mch.weixin.qq.com";
/**
* 证书别名
*/
@@ -31,12 +31,20 @@ public final class WxConst {
* 沙箱
*/
public static final String SANDBOXNEW = "sandboxnew/";
+ public static final String COMBINE = "combine_";
public static final String APPID = "appid";
+
+ public static final String COMBINE_APPID = COMBINE + APPID;
public static final String MCH_ID = "mchid";
+ public static final String COMBINE_MCH_ID = COMBINE + MCH_ID;
public static final String SUB_MCH_ID = "sub_mchid";
public static final String SP_MCH_ID = "sp_mchid";
public static final String OUT_TRADE_NO = "out_trade_no";
+ public static final String COMBINE_OUT_TRADE_NO = COMBINE + OUT_TRADE_NO;
public static final String NOTIFY_URL = "notify_url";
+ public static final String TIME_START = "time_start";
+ public static final String TIME_EXPIRE = "time_expire";
+ public static final String SUB_ORDERS = "sub_orders";
public static final String TOKEN_PATTERN = "mchid=\"%s\",nonce_str=\"%s\",timestamp=\"%d\",serial_no=\"%s\",signature=\"%s\"";