From 30155b316ba9ca88f7d62a2fda35dfdfa45a4571 Mon Sep 17 00:00:00 2001 From: thinsstar <43289204+thinsstar@users.noreply.github.com> Date: Tue, 9 Mar 2021 16:12:11 +0800 Subject: [PATCH] =?UTF-8?q?:new:=20#2022=20=E3=80=90=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E6=94=AF=E4=BB=98=E3=80=91=E5=A2=9E=E5=8A=A0=E6=99=BA=E6=85=A7?= =?UTF-8?q?=E5=95=86=E5=9C=88=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3=E5=92=8C?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E6=94=AF=E4=BB=98=E8=90=A5=E9=94=80=E4=BB=A3?= =?UTF-8?q?=E9=87=91=E5=88=B8=E6=A0=B8=E9=94=80=E5=9B=9E=E8=B0=83=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E7=9A=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 增加解析支付营销代金券核销回调消息解析 * 增加微信支付智慧商圈接口和回调解析 Co-authored-by: 黄星 --- .../BusinessCircleNotifyData.java | 93 ++++++ .../wxpay/bean/businesscircle/PaidResult.java | 112 +++++++ .../businesscircle/PointsNotifyRequest.java | 154 +++++++++ .../bean/businesscircle/RefundResult.java | 121 +++++++ .../marketing/FavorCallbacksSaveResult.java | 9 +- .../marketing/FavorCouponsCreateResult.java | 9 +- .../bean/marketing/FavorCouponsGetResult.java | 11 +- .../marketing/FavorCouponsQueryResult.java | 8 +- .../bean/marketing/FavorCouponsUseResult.java | 315 ++++++++++++++++++ .../marketing/FavorStocksCreateRequest.java | 10 + .../marketing/FavorStocksCreateResult.java | 9 +- .../marketing/FavorStocksFlowGetResult.java | 9 +- .../bean/marketing/FavorStocksGetResult.java | 13 +- .../marketing/FavorStocksItemsGetResult.java | 8 +- .../FavorStocksMerchantsGetResult.java | 8 +- .../marketing/FavorStocksQueryResult.java | 8 +- .../marketing/FavorStocksStartResult.java | 9 +- .../wxpay/bean/marketing/UseNotifyData.java | 89 +++++ .../wxpay/service/BusinessCircleService.java | 35 ++ .../wxpay/service/MarketingFavorService.java | 29 +- .../wxpay/service/WxPayService.java | 7 + .../service/impl/BaseWxPayServiceImpl.java | 6 + .../impl/BusinessCircleServiceImpl.java | 89 +++++ .../impl/MarketingFavorServiceImpl.java | 42 +++ .../impl/BusinessCircleServiceImplTest.java | 79 +++++ 25 files changed, 1226 insertions(+), 56 deletions(-) create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/BusinessCircleNotifyData.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PaidResult.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PointsNotifyRequest.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/RefundResult.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsUseResult.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/UseNotifyData.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/BusinessCircleService.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BusinessCircleServiceImpl.java create mode 100644 weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/BusinessCircleServiceImplTest.java diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/BusinessCircleNotifyData.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/BusinessCircleNotifyData.java new file mode 100644 index 0000000000..f8f0a1ef95 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/BusinessCircleNotifyData.java @@ -0,0 +1,93 @@ +package com.github.binarywang.wxpay.bean.businesscircle; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 智慧商圈回调通知对象 + *
+ *   文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_1.shtml
+ *   https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_3.shtml
+ * 
+ * + * @author thinsstar + */ +@NoArgsConstructor +@Data +public class BusinessCircleNotifyData implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 通知ID + */ + @SerializedName("id") + private String id; + + /** + * 通知创建时间 + */ + @SerializedName("create_time") + private String createTime; + + /** + * 通知类型 + */ + @SerializedName("event_type") + private String eventType; + + /** + * 通知数据类型 + */ + @SerializedName("resource_type") + private String resourceType; + + /** + * 回调摘要 + * summary + */ + @SerializedName("summary") + private String summary; + + /** + * 通知数据 + */ + @SerializedName("resource") + private Resource resource; + + @Data + public static class Resource implements Serializable { + private static final long serialVersionUID = 1L; + /** + * 加密算法类型 + */ + @SerializedName("algorithm") + private String algorithm; + + /** + * 数据密文 + */ + @SerializedName("ciphertext") + private String cipherText; + + /** + * 附加数据 + */ + @SerializedName("associated_data") + private String associatedData; + + /** + * 随机串 + */ + @SerializedName("nonce") + private String nonce; + + /** + * 原始回调类型 + */ + @SerializedName("original_type") + private String originalType; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PaidResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PaidResult.java new file mode 100644 index 0000000000..ded872c79b --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PaidResult.java @@ -0,0 +1,112 @@ +package com.github.binarywang.wxpay.bean.businesscircle; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 商圈支付结果通知内容 + *
+ *  文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_1.shtml
+ * 
+ * + * @author thinsstar + */ +@NoArgsConstructor +@Data +public class PaidResult implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商户号 + *

+ * 微信支付分配的商户号 + * 示例值:1230000109 + */ + @SerializedName("mchid") + private String mchid; + + /** + * 商圈商户名称 + *

+ * 商圈商户名称 + * 示例值:微信支付 + */ + @SerializedName("merchant_name") + private String merchantName; + + /** + * 门店名称 + *

+ * 门店名称,商圈在商圈小程序上圈店时填写的门店名称 + * 示例值:微信支付 + */ + @SerializedName("shop_name") + private String shopName; + + /** + * 门店编号 + *

+ * 门店编号,商圈在商圈小程序上圈店时填写的门店编号,用于跟商圈自身已有的商户识别码对齐 + * 示例值:123456 + */ + @SerializedName("shop_number") + private String shop_number; + + /** + * 小程序APPID + *

+ * 顾客授权积分时使用的小程序的appid + * 示例值:wxd678efh567hg6787 + */ + @SerializedName("appid") + private String appid; + + /** + * 用户标识 + *

+ * 顾客授权时使用的小程序上的openid + * 示例值:oUpF8uMuAJ2pxb1Q9zNjWeS6o + */ + @SerializedName("openid") + private String openid; + + /** + * 交易完成时间 + *

+ * 交易完成时间,遵循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年05月20日13点29分35秒(需要增加所有跟时间有关的参数的描述) + * 示例值:2015-05-20T13:29:35+08:00 + */ + @SerializedName("time_end") + private String timeEnd; + + /** + * 金额 + *

+ * 用户实际消费金额,单位(分) + * 示例值:200 + */ + @SerializedName("amount") + private Integer amount; + + /** + * 微信支付订单号 + *

+ * 微信支付订单号 + * 示例值:1234567890 + */ + @SerializedName("transaction_id") + private String transactionId; + + /** + * 手动提交积分标记 + *

+ * 手动提交积分标记,自动提交时无该字段,用于区分用户手动申请后推送的积分数据 + * 示例值:oUpF8uMuAJ2pxb1Q9zNjWUHsd + */ + @SerializedName("commit_tag") + private String commitTag; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PointsNotifyRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PointsNotifyRequest.java new file mode 100644 index 0000000000..541335ef91 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PointsNotifyRequest.java @@ -0,0 +1,154 @@ +package com.github.binarywang.wxpay.bean.businesscircle; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 商圈积分同步 + *

+ *   文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_2.shtml
+ * 
+ * + * @author thinsstar + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PointsNotifyRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + *
+   * 字段名:商圈商户ID
+   * 变量名:sub_mchid
+   * 是否必填:否
+   * 类型:string[1,64]
+   * 描述:
+   *  当以服务商模式管理商圈积分能力时,则要带上商圈商户ID,否则留空
+   *  示例值:1234567890
+   * 
+ */ + @SerializedName(value = "sub_mchid") + private String subMchid; + + /** + *
+   * 字段名:微信订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string[1,64]
+   * 描述:
+   *  微信支付推送的商圈内交易通知里携带的微信订单号
+   *  示例值:1217752501201407033233368018
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:小程序appid
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string[1,128]
+   * 描述:
+   *  顾客授权积分时使用的小程序的appid
+   *  示例值:wx1234567890abcdef
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:用户标识
+   * 变量名:openid
+   * 是否必填:是
+   * 类型:string[1,64]
+   * 描述:
+   *  顾客授权时使用的小程序上的openid
+   *  示例值:oWmnN4xxxxxxxxxxe92NHIGf1xd8
+   * 
+ */ + @SerializedName(value = "openid") + private String openid; + + /** + *
+   * 字段名:是否获得积分
+   * 变量名:earn_points
+   * 是否必填:是
+   * 类型:boolean
+   * 描述:
+   *  用于标明此单是否获得积分,
+   *  true为获得积分,
+   *  false为未获得
+   *  示例值:true
+   * 
+ */ + @SerializedName(value = "earn_points") + private Boolean earnPoints; + + /** + *
+   * 字段名:订单新增积分值
+   * 变量名:increased_points
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  顾客此笔交易新增的积分值
+   *  示例值:100
+   * 
+ */ + @SerializedName(value = "increased_points") + private Integer increasedPoints; + + /** + *
+   * 字段名:积分更新时间
+   * 变量名:points_update_time
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  为顾客此笔交易成功积分的时间
+   *  示例值:2020-05-20T13:29:35.120+08:00
+   * 
+ */ + @SerializedName(value = "points_update_time") + private String pointsUpdateTime; + + /** + *
+   * 字段名:未获得积分的备注信息
+   * 变量名:no_points_remarks
+   * 是否必填:否
+   * 类型:string[1,128]
+   * 描述:
+   *  当未获得积分时,提供未获得积分的原因等备注信息
+   *  示例值:商品不参与积分活动
+   * 
+ */ + @SerializedName(value = "no_points_remarks") + private String noPointsRemarks; + + /** + *
+   * 字段名:顾客积分总额
+   * 变量名:total_points
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  当前顾客积分总额
+   *  示例值:888888
+   * 
+ */ + @SerializedName(value = "total_points") + private Integer totalPoints; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/RefundResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/RefundResult.java new file mode 100644 index 0000000000..d3fdb3103d --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/RefundResult.java @@ -0,0 +1,121 @@ +package com.github.binarywang.wxpay.bean.businesscircle; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 商圈退款成功通知内容 + *
+ *  文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_3.shtml
+ * 
+ * + * @author thinsstar + */ +@NoArgsConstructor +@Data +public class RefundResult implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商户号 + *

+ * 微信支付分配的商户号 + * 示例值:1230000109 + */ + @SerializedName("mchid") + private String mchid; + + /** + * 商圈商户名称 + *

+ * 商圈商户名称 + * 示例值:微信支付 + */ + @SerializedName("merchant_name") + private String merchantName; + + /** + * 门店名称 + *

+ * 门店名称,商圈在商圈小程序上圈店时填写的门店名称 + * 示例值:微信支付 + */ + @SerializedName("shop_name") + private String shopName; + + /** + * 门店编号 + *

+ * 门店编号,商圈在商圈小程序上圈店时填写的门店编号,用于跟商圈自身已有的商户识别码对齐 + * 示例值:123456 + */ + @SerializedName("shop_number") + private String shop_number; + + /** + * 小程序APPID + *

+ * 顾客授权积分时使用的小程序的appid + * 示例值:wxd678efh567hg6787 + */ + @SerializedName("appid") + private String appid; + + /** + * 用户标识 + *

+ * 顾客授权时使用的小程序上的openid + * 示例值:oUpF8uMuAJ2pxb1Q9zNjWeS6o + */ + @SerializedName("openid") + private String openid; + + /** + * 退款完成时间 + *

+ * 退款完成时间,遵循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年05月20日13点29分35秒(需要增加所有跟时间有关的参数的描述) + * 示例值:2015-05-20T13:29:35+08:00 + */ + @SerializedName("refund_time") + private String refundTime; + + /** + * 消费金额 + *

+ * 用户实际消费金额,单位(分) + * 示例值:100 + */ + @SerializedName("pay_amount") + private Integer payAmount; + + /** + * 退款金额 + *

+ * 用户退款金额,单位(分) + * 示例值:100 + */ + @SerializedName("refund_amount") + private Integer refundAmount; + + /** + * 微信支付订单号 + *

+ * 微信支付订单号 + * 示例值:1234567890 + */ + @SerializedName("transaction_id") + private String transactionId; + + /** + * 微信支付退款单号 + *

+ * 微信支付退款单号 + * 示例值:1217752501201407033233368999 + */ + @SerializedName("refund_id") + private String refundId; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCallbacksSaveResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCallbacksSaveResult.java index 55015a6ac6..eedc16b548 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCallbacksSaveResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCallbacksSaveResult.java @@ -3,7 +3,8 @@ import com.google.gson.annotations.SerializedName; import lombok.Data; import lombok.NoArgsConstructor; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; + +import java.io.Serializable; /** * 设置消息通知地址返回结果对象 @@ -12,11 +13,9 @@ */ @NoArgsConstructor @Data -public class FavorCallbacksSaveResult { +public class FavorCallbacksSaveResult implements Serializable { - public static FavorCallbacksSaveResult fromJson(String json) { - return WxGsonBuilder.create().fromJson(json, FavorCallbacksSaveResult.class); - } + private static final long serialVersionUID = 1L; /** * 修改时间 diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsCreateResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsCreateResult.java index e3530e80e1..67c820e0fa 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsCreateResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsCreateResult.java @@ -3,7 +3,8 @@ import com.google.gson.annotations.SerializedName; import lombok.Data; import lombok.NoArgsConstructor; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; + +import java.io.Serializable; /** * 发放代金券返回结果对象 @@ -12,11 +13,9 @@ */ @NoArgsConstructor @Data -public class FavorCouponsCreateResult { +public class FavorCouponsCreateResult implements Serializable { - public static FavorCouponsCreateResult fromJson(String json) { - return WxGsonBuilder.create().fromJson(json, FavorCouponsCreateResult.class); - } + private static final long serialVersionUID = 1L; /** * 代金券id diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsGetResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsGetResult.java index b6f6dd854b..3b89cec058 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsGetResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsGetResult.java @@ -3,7 +3,6 @@ import com.google.gson.annotations.SerializedName; import lombok.Data; import lombok.NoArgsConstructor; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; import java.io.Serializable; @@ -14,11 +13,9 @@ */ @NoArgsConstructor @Data -public class FavorCouponsGetResult { +public class FavorCouponsGetResult implements Serializable { - public static FavorCouponsGetResult fromJson(String json) { - return WxGsonBuilder.create().fromJson(json, FavorCouponsGetResult.class); - } + private static final long serialVersionUID = 1L; /** * 创建批次的商户号 @@ -156,6 +153,8 @@ public static FavorCouponsGetResult fromJson(String json) { @Data @NoArgsConstructor public static class CutToMessage implements Serializable { + + private static final long serialVersionUID = 1L; /** * 可用优惠的商品最高单价 *

@@ -178,6 +177,8 @@ public static class CutToMessage implements Serializable { @Data @NoArgsConstructor public static class NormalCouponInformation implements Serializable { + + private static final long serialVersionUID = 1L; /** * 面额 *

diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsQueryResult.java index 2c47a99fd5..bf1f15bcf3 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsQueryResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsQueryResult.java @@ -3,8 +3,8 @@ import com.google.gson.annotations.SerializedName; import lombok.Data; import lombok.NoArgsConstructor; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import java.io.Serializable; import java.util.List; /** @@ -14,11 +14,9 @@ */ @NoArgsConstructor @Data -public class FavorCouponsQueryResult { +public class FavorCouponsQueryResult implements Serializable { - public static FavorCouponsQueryResult fromJson(String json) { - return WxGsonBuilder.create().fromJson(json, FavorCouponsQueryResult.class); - } + private static final long serialVersionUID = 1L; /** * 查询结果总数 diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsUseResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsUseResult.java new file mode 100644 index 0000000000..3f7ff45a8c --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorCouponsUseResult.java @@ -0,0 +1,315 @@ +package com.github.binarywang.wxpay.bean.marketing; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * 核销事件回调内容 + * + * @author thinsstar + */ +@NoArgsConstructor +@Data +public class FavorCouponsUseResult implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 创建批次的商户号 + *

+ * 批次创建方商户号 + * 示例值:9800064 + */ + @SerializedName("stock_creator_mchid") + private String stockCreatorMchid; + + /** + * 批次号 + *

+ * 微信为每个代金券批次分配的唯一id。 + * 示例值:9865888 + */ + @SerializedName("stock_id") + private String stockId; + + /** + * 代金券id + *

+ * 微信为代金券唯一分配的id。 + * 示例值:98674556 + */ + @SerializedName("coupon_id") + private String couponId; + + /** + * 单品优惠特定信息 + *

+ * 单品优惠特定信息。 + */ + @SerializedName("singleitem_discount_off") + private SingleitemDiscountOff singleitemDiscountOff; + + /** + * 减至优惠特定信息 + *

+ * 减至优惠限定字段,仅减至优惠场景有返回。 + */ + @SerializedName("discount_to") + private DiscountTo discountTo; + + /** + * 代金券名称 + *

+ * 代金券名称 + * 示例值:微信支付代金券 + */ + @SerializedName("coupon_name") + private String couponName; + + /** + * 代金券状态 + *

+ * 代金券状态: + * SENDED:可用 + * USED:已实扣 + * EXPIRED:已过期 + * 示例值:EXPIRED + */ + @SerializedName("status") + private String status; + + /** + * 使用说明 + *

+ * 代金券描述说明字段。 + * 示例值:微信支付营销 + */ + @SerializedName("description") + private String description; + + /** + * 领券时间 + *

+ * 领券时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss.sss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示,北京时间2015年5月20日 13点29分35秒。 + * 示例值: 2015-05-20T13:29:35.120+08:00 + */ + @SerializedName("create_time") + private String createTime; + + /** + * 券类型 + *

+ * 券类型: + * NORMAL:满减券 + * CUT_TO:减至券 + * 示例值:CUT_TO + */ + @SerializedName("coupon_type") + private String couponType; + + /** + * 是否无资金流 + *

+ * 枚举值: + * true:是 + * false:否 + * 示例值:true + */ + @SerializedName("no_cash") + private Boolean noCash; + + /** + * 可用开始时间 + *

+ * 可用开始时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss.sss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示,北京时间2015年5月20日 13点29分35秒。 + * 示例值: 2015-05-20T13:29:35.120+08:00 + */ + @SerializedName("available_begin_time") + private String availableBeginTime; + + /** + * 可用结束时间 + *

+ * 可用结束时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss.sss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示,北京时间2015年5月20日 13点29分35秒。 + * 示例值: 2015-05-20T13:29:35.120+08:00 + */ + @SerializedName("available_end_time") + private String availableEndTime; + + /** + * 是否单品优惠 + *

+ * 枚举值: + * true:是 + * false:否 + * 示例值:true + */ + @SerializedName("singleitem") + private Boolean singleitem; + + /** + * 普通满减券信息 + *

+ * 普通满减券面额、门槛信息。 + */ + @SerializedName("normal_coupon_information") + private NormalCouponInformation normalCouponInformation; + + /** + * 实扣代金券信息 + *

+ * 普通满减券面额、门槛信息。 + */ + @SerializedName("consume_information") + private ConsumeInformation consumeInformation; + + @Data + @NoArgsConstructor + public static class SingleitemDiscountOff implements Serializable { + + private static final long serialVersionUID = 1L; + /** + * 单品最高优惠价格 + *

+ * 单品最高优惠价格,单位:分。 + * 示例值:100 + */ + @SerializedName(value = "single_price_max") + private Integer singlePriceMax; + } + + @Data + @NoArgsConstructor + public static class DiscountTo implements Serializable { + + private static final long serialVersionUID = 1L; + /** + * 减至后优惠单价 + *

+ * 减至后优惠单价,单位:分。 + * 示例值:100 + */ + @SerializedName(value = "cut_to_price") + private Integer cutToPrice; + + /** + * 最高价格 + *

+ * 可享受优惠的最高价格,单位:分。 + * 示例值:20 + */ + @SerializedName(value = "max_price") + private Integer maxPrice; + } + + @Data + @NoArgsConstructor + public static class NormalCouponInformation implements Serializable { + + private static final long serialVersionUID = 1L; + /** + * 面额 + *

+ * 面额,单位:分。 + * 示例值:100 + */ + @SerializedName(value = "coupon_amount") + private Integer couponAmount; + + /** + * 门槛 + *

+ * 使用券金额门槛,单位:分。 + * 示例值:100 + */ + @SerializedName(value = "transaction_minimum") + private Integer transactionMinimum; + } + + @Data + @NoArgsConstructor + public static class ConsumeInformation implements Serializable { + + private static final long serialVersionUID = 1L; + /** + * 核销时间 + *

+ * 代金券核销时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss.sss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示,北京时间2015年5月20日 13点29分35秒。 + * 示例值:2015-05-20T13:29:35.120+08:00 + */ + @SerializedName(value = "consume_time") + private String consumeTime; + + /** + * 核销商户号 + *

+ * 核销代金券的商户号。 + * 示例值:9856081 + */ + @SerializedName(value = "consume_mchid") + private String consumeMchid; + + /** + * 核销订单号 + *

+ * 核销订单号 + * 示例值:2345234523 + */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + * 单品信息 + *

+ * 商户下单接口传的单品信息。 + */ + @SerializedName("goods_detail") + private List goodsDetail; + } + + @Data + @NoArgsConstructor + public static class GoodsDetail implements Serializable { + + private static final long serialVersionUID = 1L; + /** + * 单品编码 + *

+ * 单品券创建时录入的单品编码。 + * 示例值:a_goods1 + */ + @SerializedName(value = "goods_id") + private String goodsId; + + /** + * 单品数量 + *

+ * 单品数据 + * 示例值:7 + */ + @SerializedName(value = "quantity") + private Integer quantity; + + /** + * 单品单价 + *

+ * 单品单价 + * 示例值:1 + */ + @SerializedName(value = "price") + private Integer price; + + /** + * 优惠金额 + *

+ * 优惠金额 + * 示例值:4 + */ + @SerializedName(value = "discount_amount") + private Integer discountAmount; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksCreateRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksCreateRequest.java index 9b75008208..2225009075 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksCreateRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksCreateRequest.java @@ -210,6 +210,8 @@ public class FavorStocksCreateRequest implements Serializable { @Data @NoArgsConstructor public static class StockUseRule implements Serializable { + + private static final long serialVersionUID = 1L; /** *

      * 字段名:发放总上限
@@ -312,6 +314,8 @@ public static class StockUseRule implements Serializable {
   @Data
   @NoArgsConstructor
   public static class PatternInfo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
     /**
      * 
      * 字段名:使用说明
@@ -393,6 +397,8 @@ public static class PatternInfo implements Serializable {
   @Data
   @NoArgsConstructor
   public static class CouponUseRule implements Serializable {
+
+    private static final long serialVersionUID = 1L;
     /**
      * 
      * 字段名:券生效时间
@@ -666,6 +672,8 @@ public static class CouponUseRule implements Serializable {
   @Data
   @NoArgsConstructor
   public static class FixedNormalCoupon implements Serializable {
+
+    private static final long serialVersionUID = 1L;
     /**
      * 
      * 字段名:面额
@@ -703,6 +711,8 @@ public static class FixedNormalCoupon implements Serializable {
   @Data
   @NoArgsConstructor
   public static class LimitCard implements Serializable {
+
+    private static final long serialVersionUID = 1L;
     /**
      * 
      * 字段名:银行卡名称
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksCreateResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksCreateResult.java
index 26ea1796b4..74ac6fd205 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksCreateResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksCreateResult.java
@@ -3,7 +3,8 @@
 import com.google.gson.annotations.SerializedName;
 import lombok.Data;
 import lombok.NoArgsConstructor;
-import me.chanjar.weixin.common.util.json.WxGsonBuilder;
+
+import java.io.Serializable;
 
 /**
  * 创建代金券批次返回结果对象
@@ -12,11 +13,9 @@
  */
 @NoArgsConstructor
 @Data
-public class FavorStocksCreateResult {
+public class FavorStocksCreateResult implements Serializable {
 
-  public static FavorStocksCreateResult fromJson(String json) {
-    return WxGsonBuilder.create().fromJson(json, FavorStocksCreateResult.class);
-  }
+  private static final long serialVersionUID = 1L;
 
   /**
    * 批次号
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksFlowGetResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksFlowGetResult.java
index 1c7259da8f..f4176d0fad 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksFlowGetResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksFlowGetResult.java
@@ -3,7 +3,8 @@
 import com.google.gson.annotations.SerializedName;
 import lombok.Data;
 import lombok.NoArgsConstructor;
-import me.chanjar.weixin.common.util.json.WxGsonBuilder;
+
+import java.io.Serializable;
 
 /**
  * 获取下载结果对象
@@ -12,11 +13,9 @@
  */
 @NoArgsConstructor
 @Data
-public class FavorStocksFlowGetResult {
+public class FavorStocksFlowGetResult implements Serializable {
 
-  public static FavorStocksFlowGetResult fromJson(String json) {
-    return WxGsonBuilder.create().fromJson(json, FavorStocksFlowGetResult.class);
-  }
+  private static final long serialVersionUID = 1L;
 
   /**
    * 下载链接
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksGetResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksGetResult.java
index cdde077bc7..7622a19fad 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksGetResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksGetResult.java
@@ -3,7 +3,6 @@
 import com.google.gson.annotations.SerializedName;
 import lombok.Data;
 import lombok.NoArgsConstructor;
-import me.chanjar.weixin.common.util.json.WxGsonBuilder;
 
 import java.io.Serializable;
 import java.util.List;
@@ -15,11 +14,9 @@
  */
 @NoArgsConstructor
 @Data
-public class FavorStocksGetResult {
+public class FavorStocksGetResult implements Serializable {
 
-  public static FavorStocksGetResult fromJson(String json) {
-    return WxGsonBuilder.create().fromJson(json, FavorStocksGetResult.class);
-  }
+  private static final long serialVersionUID = 1L;
 
   /**
    * 批次号
@@ -180,6 +177,8 @@ public static FavorStocksGetResult fromJson(String json) {
   @Data
   @NoArgsConstructor
   public static class CutToMessage implements Serializable {
+
+    private static final long serialVersionUID = 1L;
     /**
      * 可用优惠的商品最高单价
      * 

@@ -202,6 +201,8 @@ public static class CutToMessage implements Serializable { @Data @NoArgsConstructor public static class StockUseRule implements Serializable { + + private static final long serialVersionUID = 1L; /** * 发放总上限 *

@@ -298,6 +299,8 @@ public static class StockUseRule implements Serializable { @Data @NoArgsConstructor public static class FixedNormalCoupon implements Serializable { + + private static final long serialVersionUID = 1L; /** * 面额 *

diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksItemsGetResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksItemsGetResult.java index 6b3153eb48..e1f36b5040 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksItemsGetResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksItemsGetResult.java @@ -3,8 +3,8 @@ import com.google.gson.annotations.SerializedName; import lombok.Data; import lombok.NoArgsConstructor; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import java.io.Serializable; import java.util.List; /** @@ -14,11 +14,9 @@ */ @NoArgsConstructor @Data -public class FavorStocksItemsGetResult { +public class FavorStocksItemsGetResult implements Serializable { - public static FavorStocksItemsGetResult fromJson(String json) { - return WxGsonBuilder.create().fromJson(json, FavorStocksItemsGetResult.class); - } + private static final long serialVersionUID = 1L; /** * 可用单品编码总数 diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksMerchantsGetResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksMerchantsGetResult.java index 0e0284b8a2..d080b1dc7a 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksMerchantsGetResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksMerchantsGetResult.java @@ -3,8 +3,8 @@ import com.google.gson.annotations.SerializedName; import lombok.Data; import lombok.NoArgsConstructor; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import java.io.Serializable; import java.util.List; /** @@ -14,11 +14,9 @@ */ @NoArgsConstructor @Data -public class FavorStocksMerchantsGetResult { +public class FavorStocksMerchantsGetResult implements Serializable { - public static FavorStocksMerchantsGetResult fromJson(String json) { - return WxGsonBuilder.create().fromJson(json, FavorStocksMerchantsGetResult.class); - } + private static final long serialVersionUID = 1L; /** * 可用商户总数量 diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksQueryResult.java index 79259206b0..358d782ad0 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksQueryResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksQueryResult.java @@ -3,8 +3,8 @@ import com.google.gson.annotations.SerializedName; import lombok.Data; import lombok.NoArgsConstructor; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import java.io.Serializable; import java.util.List; /** @@ -14,11 +14,9 @@ */ @NoArgsConstructor @Data -public class FavorStocksQueryResult { +public class FavorStocksQueryResult implements Serializable { - public static FavorStocksQueryResult fromJson(String json) { - return WxGsonBuilder.create().fromJson(json, FavorStocksQueryResult.class); - } + private static final long serialVersionUID = 1L; /** * 批次总数 diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksStartResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksStartResult.java index a66a1740b4..07e07cb313 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksStartResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/FavorStocksStartResult.java @@ -3,7 +3,8 @@ import com.google.gson.annotations.SerializedName; import lombok.Data; import lombok.NoArgsConstructor; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; + +import java.io.Serializable; /** * 激活代金券批次返回结果对象 @@ -12,11 +13,9 @@ */ @NoArgsConstructor @Data -public class FavorStocksStartResult { +public class FavorStocksStartResult implements Serializable { - public static FavorStocksStartResult fromJson(String json) { - return WxGsonBuilder.create().fromJson(json, FavorStocksStartResult.class); - } + private static final long serialVersionUID = 1L; /** * 生效时间 diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/UseNotifyData.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/UseNotifyData.java new file mode 100644 index 0000000000..9b8f331d49 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/UseNotifyData.java @@ -0,0 +1,89 @@ +package com.github.binarywang.wxpay.bean.marketing; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 核销事件回调通知对象 + * + * @author thinsstar + */ +@NoArgsConstructor +@Data +public class UseNotifyData implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 通知ID + */ + @SerializedName("id") + private String id; + + /** + * 通知创建时间 + */ + @SerializedName("create_time") + private String createTime; + + /** + * 通知类型 + */ + @SerializedName("event_type") + private String eventType; + + /** + * 通知数据类型 + */ + @SerializedName("resource_type") + private String resourceType; + + /** + * 回调摘要 + * summary + */ + @SerializedName("summary") + private String summary; + + /** + * 通知数据 + */ + @SerializedName("resource") + private Resource resource; + + @Data + public static class Resource implements Serializable { + private static final long serialVersionUID = 1L; + /** + * 加密算法类型 + */ + @SerializedName("algorithm") + private String algorithm; + + /** + * 数据密文 + */ + @SerializedName("ciphertext") + private String cipherText; + + /** + * 附加数据 + */ + @SerializedName("associated_data") + private String associatedData; + + /** + * 随机串 + */ + @SerializedName("nonce") + private String nonce; + + /** + * 原始回调类型 + */ + @SerializedName("original_type") + private String originalType; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/BusinessCircleService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/BusinessCircleService.java new file mode 100644 index 0000000000..21af39ae16 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/BusinessCircleService.java @@ -0,0 +1,35 @@ +package com.github.binarywang.wxpay.service; + +import com.github.binarywang.wxpay.bean.businesscircle.BusinessCircleNotifyData; +import com.github.binarywang.wxpay.bean.businesscircle.PaidResult; +import com.github.binarywang.wxpay.bean.businesscircle.PointsNotifyRequest; +import com.github.binarywang.wxpay.bean.businesscircle.RefundResult; +import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; +import com.github.binarywang.wxpay.exception.WxPayException; + +/** + *

+ * 微信支付智慧商圈API
+ * 
+ * + * @author thinsstar + */ +public interface BusinessCircleService { + /** + *
+   * 智慧商圈接口-商圈积分同步API
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_2.shtml
+   * 接口链接:https://api.mch.weixin.qq.com/v3/businesscircle/points/notify
+   * 
+ * + * @param request 请求对象 + * @throws WxPayException the wx pay exception + */ + void notifyPoints(PointsNotifyRequest request) throws WxPayException; + + BusinessCircleNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException; + + PaidResult decryptPaidNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException; + + RefundResult decryptRefundNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MarketingFavorService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MarketingFavorService.java index 94efa81c4c..5da11aabf3 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MarketingFavorService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MarketingFavorService.java @@ -1,5 +1,6 @@ package com.github.binarywang.wxpay.service; +import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; import com.github.binarywang.wxpay.bean.marketing.*; import com.github.binarywang.wxpay.exception.WxPayException; @@ -172,13 +173,39 @@ public interface MarketingFavorService { * 接口链接:https://api.mch.weixin.qq.com/v3/marketing/favor/callbacks *
* - * @param request 批次号 + * @param request 请求对象 * @return FavorCallbacksSaveResult 微信返回的结果信息。 * @throws WxPayException the wx pay exception */ FavorCallbacksSaveResult saveFavorCallbacksV3(FavorCallbacksSaveRequest request) throws WxPayException; + /** + *
+   * 代金券接口-暂停代金券批次API
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/marketing/convention/chapter3_13.shtml
+   * 接口链接:https://api.mch.weixin.qq.com/v3/marketing/favor/stocks/{stock_id}/pause
+   * 
+ * + * @param request 请求对象 + * @return FavorCallbacksSaveResult 微信返回的结果信息。 + * @throws WxPayException the wx pay exception + */ FavorStocksStartResult pauseFavorStocksV3(String stockId, FavorStocksSetRequest request) throws WxPayException; + /** + *
+   * 代金券接口-重启代金券批次API
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/marketing/convention/chapter3_14.shtml
+   * 接口链接:https://api.mch.weixin.qq.com/v3/marketing/favor/stocks/{stock_id}/restart
+   * 
+ * + * @param request 请求对象 + * @return FavorCallbacksSaveResult 微信返回的结果信息。 + * @throws WxPayException the wx pay exception + */ FavorStocksStartResult restartFavorStocksV3(String stockId, FavorStocksSetRequest request) throws WxPayException; + + UseNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException; + + FavorCouponsUseResult decryptNotifyDataResource(UseNotifyData data) throws WxPayException; } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java index 366b2907ee..0caba53c2f 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java @@ -153,6 +153,13 @@ public interface WxPayService { */ EcommerceService getEcommerceService(); + /** + * 获取微信支付智慧商圈服务类 + * + * @return the business circle service + */ + BusinessCircleService getBusinessCircleService(); + /** * 获取微信支付通用媒体服务类 * diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java index 23d06c4b46..35dcf1d890 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java @@ -60,6 +60,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService { private final RedpackService redpackService = new RedpackServiceImpl(this); private final PayScoreService payScoreService = new PayScoreServiceImpl(this); private final EcommerceService ecommerceService = new EcommerceServiceImpl(this); + private final BusinessCircleService businessCircleService = new BusinessCircleServiceImpl(this); private final MerchantMediaService merchantMediaService = new MerchantMediaServiceImpl(this); private final MarketingMediaService marketingMediaService = new MarketingMediaServiceImpl(this); private final MarketingFavorService marketingFavorService = new MarketingFavorServiceImpl(this); @@ -91,6 +92,11 @@ public EcommerceService getEcommerceService() { return ecommerceService; } + @Override + public BusinessCircleService getBusinessCircleService() { + return this.businessCircleService; + } + @Override public MerchantMediaService getMerchantMediaService() { return this.merchantMediaService; diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BusinessCircleServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BusinessCircleServiceImpl.java new file mode 100644 index 0000000000..ee0874aa8a --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BusinessCircleServiceImpl.java @@ -0,0 +1,89 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.bean.businesscircle.BusinessCircleNotifyData; +import com.github.binarywang.wxpay.bean.businesscircle.PaidResult; +import com.github.binarywang.wxpay.bean.businesscircle.PointsNotifyRequest; +import com.github.binarywang.wxpay.bean.businesscircle.RefundResult; +import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.BusinessCircleService; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.v3.util.AesUtils; +import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.security.GeneralSecurityException; +import java.util.Objects; + +/** + * 微信支付-微信支付智慧商圈service + * + * @author thinsstar + */ +@Slf4j +@RequiredArgsConstructor +public class BusinessCircleServiceImpl implements BusinessCircleService { + private static final Gson GSON = new GsonBuilder().create(); + private final WxPayService payService; + + @Override + public void notifyPoints(PointsNotifyRequest request) throws WxPayException { + String url = String.format("%s/v3/businesscircle/points/notify", this.payService.getPayBaseUrl()); + RsaCryptoUtil.encryptFields(request, this.payService.getConfig().getVerifier().getValidCertificate()); + this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request)); + } + + /** + * 校验通知签名 + * + * @param header 通知头信息 + * @param data 通知数据 + * @return true:校验通过 false:校验不通过 + */ + private boolean verifyNotifySign(SignatureHeader header, String data) { + String beforeSign = String.format("%s%n%s%n%s%n", header.getTimeStamp(), header.getNonce(), data); + return payService.getConfig().getVerifier().verify(header.getSerialNo(), + beforeSign.getBytes(StandardCharsets.UTF_8), header.getSigned()); + } + + @Override + public BusinessCircleNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException { + if (Objects.nonNull(header) && !this.verifyNotifySign(header, data)) { + throw new WxPayException("非法请求,头部信息验证失败"); + } + return GSON.fromJson(data, BusinessCircleNotifyData.class); + } + + @Override + public PaidResult decryptPaidNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException { + BusinessCircleNotifyData.Resource resource = data.getResource(); + String cipherText = resource.getCipherText(); + String associatedData = resource.getAssociatedData(); + String nonce = resource.getNonce(); + String apiV3Key = this.payService.getConfig().getApiV3Key(); + try { + return GSON.fromJson(AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key), PaidResult.class); + } catch (GeneralSecurityException | IOException e) { + throw new WxPayException("解析报文异常!", e); + } + } + + @Override + public RefundResult decryptRefundNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException { + BusinessCircleNotifyData.Resource resource = data.getResource(); + String cipherText = resource.getCipherText(); + String associatedData = resource.getAssociatedData(); + String nonce = resource.getNonce(); + String apiV3Key = this.payService.getConfig().getApiV3Key(); + try { + return GSON.fromJson(AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key), RefundResult.class); + } catch (GeneralSecurityException | IOException e) { + throw new WxPayException("解析报文异常!", e); + } + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MarketingFavorServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MarketingFavorServiceImpl.java index c8efc20500..8917db7d95 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MarketingFavorServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MarketingFavorServiceImpl.java @@ -1,9 +1,11 @@ package com.github.binarywang.wxpay.service.impl; +import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; import com.github.binarywang.wxpay.bean.marketing.*; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.MarketingFavorService; import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.v3.util.AesUtils; import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -11,6 +13,11 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.security.GeneralSecurityException; +import java.util.Objects; + /** * 微信支付-营销代金券接口 * @@ -161,4 +168,39 @@ public FavorStocksStartResult restartFavorStocksV3(String stockId, FavorStocksSe String result = this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request)); return GSON.fromJson(result, FavorStocksStartResult.class); } + + /** + * 校验通知签名 + * + * @param header 通知头信息 + * @param data 通知数据 + * @return true:校验通过 false:校验不通过 + */ + private boolean verifyNotifySign(SignatureHeader header, String data) { + String beforeSign = String.format("%s%n%s%n%s%n", header.getTimeStamp(), header.getNonce(), data); + return payService.getConfig().getVerifier().verify(header.getSerialNo(), + beforeSign.getBytes(StandardCharsets.UTF_8), header.getSigned()); + } + + @Override + public UseNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException { + if (Objects.nonNull(header) && !this.verifyNotifySign(header, data)) { + throw new WxPayException("非法请求,头部信息验证失败"); + } + return GSON.fromJson(data, UseNotifyData.class); + } + + @Override + public FavorCouponsUseResult decryptNotifyDataResource(UseNotifyData data) throws WxPayException { + UseNotifyData.Resource resource = data.getResource(); + String cipherText = resource.getCipherText(); + String associatedData = resource.getAssociatedData(); + String nonce = resource.getNonce(); + String apiV3Key = this.payService.getConfig().getApiV3Key(); + try { + return GSON.fromJson(AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key), FavorCouponsUseResult.class); + } catch (GeneralSecurityException | IOException e) { + throw new WxPayException("解析报文异常!", e); + } + } } diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/BusinessCircleServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/BusinessCircleServiceImplTest.java new file mode 100644 index 0000000000..d07392f17e --- /dev/null +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/BusinessCircleServiceImplTest.java @@ -0,0 +1,79 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.bean.businesscircle.BusinessCircleNotifyData; +import com.github.binarywang.wxpay.bean.businesscircle.PaidResult; +import com.github.binarywang.wxpay.bean.businesscircle.PointsNotifyRequest; +import com.github.binarywang.wxpay.bean.businesscircle.RefundResult; +import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.testbase.ApiTestModule; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +/** + *
+ *  智慧商圈测试类
+ * 
+ * + * @author thinsstar + */ +@Slf4j +@Test +@Guice(modules = ApiTestModule.class) +public class BusinessCircleServiceImplTest { + + @Inject + private WxPayService wxPayService; + + private static final Gson GSON = new GsonBuilder().create(); + + @Test + public void testNotifyPointsV3() throws WxPayException { + PointsNotifyRequest request = new PointsNotifyRequest(); + String subMchid = "商圈商户ID"; + String transactionId = "微信订单号"; + String appId = "公众号id"; + String openId = "微信openid"; + request.setSubMchid(subMchid); + request.setTransactionId(transactionId); + request.setAppid(appId); + request.setOpenid(openId); + request.setEarnPoints(true); + request.setIncreasedPoints(10); + request.setPointsUpdateTime("2021-03-03T13:29:35.120+08:00"); + wxPayService.getBusinessCircleService().notifyPoints(request); + } + + @Test + public void testDecryptPaidNotifyDataResource() throws WxPayException { + SignatureHeader header = new SignatureHeader(); + header.setSerialNo("Wechatpay-Serial"); + header.setTimeStamp("Wechatpay-Timestamp"); + header.setNonce("Wechatpay-Nonce"); + header.setSigned("Wechatpay-Signature"); + String data = "body"; + BusinessCircleNotifyData notifyData = wxPayService.getBusinessCircleService().parseNotifyData(data, header); + PaidResult result = wxPayService.getBusinessCircleService().decryptPaidNotifyDataResource(notifyData); + + log.info("result: {}", GSON.toJson(result)); + } + + @Test + public void testDecryptRefundNotifyDataResource() throws WxPayException { + SignatureHeader header = new SignatureHeader(); + header.setSerialNo("Wechatpay-Serial"); + header.setTimeStamp("Wechatpay-Timestamp"); + header.setNonce("Wechatpay-Nonce"); + header.setSigned("Wechatpay-Signature"); + String data = "body"; + BusinessCircleNotifyData notifyData = wxPayService.getBusinessCircleService().parseNotifyData(data, header); + RefundResult result = wxPayService.getBusinessCircleService().decryptRefundNotifyDataResource(notifyData); + + log.info("result: {}", GSON.toJson(result)); + } +}