diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/MemberCardAuthorizeNotifyResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/MemberCardAuthorizeNotifyResult.java new file mode 100644 index 00000000..0372d9d7 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/MemberCardAuthorizeNotifyResult.java @@ -0,0 +1,52 @@ +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_partner/apis/chapter8_6_6.shtml + *+ * + * @author thinsstar + */ +@NoArgsConstructor +@Data +public class MemberCardAuthorizeNotifyResult implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户标识 + *
+ * 顾客授权时使用的小程序上的openid + * 示例值:oUpF8uMuAJ2pxb1Q9zNjWeS6o + */ + @SerializedName("openid") + private String openid; + + /** + * 会员在card_id下的唯一标识, + */ + @SerializedName("code") + private String code; + + /** + * 用户开会员卡时的商圈商户号 + */ + @SerializedName("mchid") + private String mchid; + + /** + * 用户授权类型 + * REGISTERED_MODE :会员开卡(进卡包) + 未授权会员积分服务 + * REGISTERED_AND_AUTHORIZATION_MODE:会员开卡(进卡包)+授权会员积分服务 + */ + @SerializedName("auth_type") + private String authType; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/MemberCardAuthorizeResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/MemberCardAuthorizeResult.java new file mode 100644 index 00000000..07c59363 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/MemberCardAuthorizeResult.java @@ -0,0 +1,53 @@ +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_partner/apis/chapter8_6_4.shtml + *+ * + * @author thinsstar + */ +@NoArgsConstructor +@Data +public class MemberCardAuthorizeResult implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户标识 + *
+ * 顾客授权时使用的小程序上的openid + * 示例值:oUpF8uMuAJ2pxb1Q9zNjWeS6o + */ + @SerializedName("openid") + private String openid; + + /** + * 顾客授权商圈积分结果 + * UNAUTHORIZED:未授权 + * AUTHORIZED:已授权 + * DEAUTHORIZED:已取消授权 + */ + @SerializedName("authorize_state") + private String authorizeState; + + /** + * 顾客成功授权商圈积分的时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE + */ + @SerializedName("authorize_time") + private String authorizeTime; + + /** + * 顾客关闭授权商圈积分的时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE + */ + @SerializedName("deauthorize_time") + private String deauthorizeTime; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/ParkingNotifyRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/ParkingNotifyRequest.java new file mode 100644 index 00000000..66b24b42 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/ParkingNotifyRequest.java @@ -0,0 +1,103 @@ +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_partner/apis/chapter8_6_5.shtml + *+ * + * @author thinsstar + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ParkingNotifyRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + *
+ * 字段名:商圈商户ID + * 变量名:sub_mchid + * 是否必填:否 + * 类型:string[1,64] + * 描述: + * 当以服务商模式管理商圈积分能力时,则要带上商圈商户ID,否则留空 + * 示例值:1234567890 + *+ */ + @SerializedName(value = "sub_mchid") + private String subMchid; + + /** + *
+ * 调用方商户号对应的品牌brandid,调用方商户号需为此品牌brandid的品牌主商户号或品牌服务商商户号 + *+ */ + @SerializedName(value = "brandid") + private String brandid; + + /** + *
+ * 字段名:小程序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; + + /** + *
+ * 首位需为省份的中文简称,第二位起支持大写字母、数字、中文 + *+ */ + @SerializedName(value = "plate_number") + private String plateNumber; + + /** + *
+ * 停车状态,服务商模式下必传 + * IN:入场,用户开车进入商圈 + * OUT:离场,用户开车离开商圈 + *+ */ + @SerializedName(value = "state") + private String state; + + /** + *
+ * 在场状态更新时间,按照使用rfc3339所定义的格式,格式为yyyy-MM-DDThh:mm:ss+TIMEZONE + *+ */ + @SerializedName(value = "time") + private String time; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PointsCommitStatusResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PointsCommitStatusResult.java new file mode 100644 index 00000000..2cfa4d42 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/businesscircle/PointsCommitStatusResult.java @@ -0,0 +1,31 @@ +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_partner/apis/chapter8_6_7.shtml + *+ * + * @author thinsstar + */ +@NoArgsConstructor +@Data +public class PointsCommitStatusResult implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 商圈会员待积分状态 + * PENDING:有积分待提交,商圈会员有待提交的积分记录,可引导会员跳转插件提交积分申请 + * FINISHED:无积分可提交,商圈会员没有待提交的积分记录 + */ + @SerializedName("points_commit_status") + private String pointsCommitStatus; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardActivateResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardActivateResult.java new file mode 100644 index 00000000..af777c37 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardActivateResult.java @@ -0,0 +1,82 @@ +package com.github.binarywang.wxpay.bean.membercard; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 商圈支付结果通知内容 + *
+ * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_32.shtml + *+ * + * @author thinsstar + */ +@NoArgsConstructor +@Data +public class MemberCardActivateResult implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 业务细分事件类型,枚举值: + * MEMBER_CARD_ACTIVATE:激活会员卡 + * + * USER_VIEW_MEMBERCARD:用户查看会员卡详情 + * USER_DELETE_MEMBERCARD:用户删除会员卡 + * USER_MODIFY_INFORMATION:用户修改个人信息 + */ + @SerializedName("event_type") + private String eventType; + + /** + * 商户创建微信会员卡模板成功后系统返回的会员卡模板id + */ + @SerializedName("card_id") + private String cardId; + + /** + * 会员在card_id下的唯一标识, + */ + @SerializedName("code") + private String code; + + /** + * 事件发生时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE + */ + @SerializedName("event_time") + private String eventTime; + + /** + * 激活场景,用于区分用户新开卡激活或删卡后重新领取激活。枚举值: + * NEW_ACTIVATE 新开卡激活 + * RECOVER 删卡后重新领取激活 + */ + @SerializedName("activate_scene") + private String activateScene; + + /** + * 用户标识 + *
+ * 顾客授权时使用的小程序上的openid + * 示例值:oUpF8uMuAJ2pxb1Q9zNjWeS6o + */ + @SerializedName("openid") + private String openid; + + /** + * 微信用户在同一个微信开放平台账号下的唯一用户标识,unionid获取方式请参见《UnionID机制说明》文档。 + */ + @SerializedName("unionid") + private String unionid; + + /** + * 自定义场景值,商户可以用于标记投放场景,如门店/来源等。只能录入数字及中英文/半角标点 + * 匹配正则表达式: ^[0-9a-zA-Z\u0000-\u00FF\u4e00-\u9fa5]+$ + */ + @SerializedName("outer_str") + private String outerStr; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardNotifyData.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardNotifyData.java new file mode 100644 index 00000000..72ef8d27 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardNotifyData.java @@ -0,0 +1,93 @@ +package com.github.binarywang.wxpay.bean.membercard; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 会员卡回调通知对象 + *
+ * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_32.shtml + * https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_33.shtml + *+ * + * @author thinsstar + */ +@NoArgsConstructor +@Data +public class MemberCardNotifyData 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/membercard/MemberCardResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardResult.java new file mode 100644 index 00000000..d95f50ec --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardResult.java @@ -0,0 +1,360 @@ +package com.github.binarywang.wxpay.bean.membercard; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * 查询用户会员卡信息API + *
+ * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_6.shtml + *+ * + * @author thinsstar + */ +@NoArgsConstructor +@Data +public class MemberCardResult implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 商户创建微信会员卡模板成功后系统返回的会员卡模板id + */ + @SerializedName("card_id") + private String cardId; + + /** + * 会员在card_id下的唯一标识,用户领取会员卡后获得的code + */ + @SerializedName("code") + private String code; + + /** + * 用户在会员卡绑定品牌appid下的唯一标识,如通过手机号同步会员身份且用户未领取到卡包,无法查询该字段 + */ + @SerializedName("openid") + private String openid; + + /** + * 在用户会员卡上展示的会员卡编号,默认使用会员卡code作为membership_number。只能录入数字/英文/半角标点。商家可通过修改用户单张会员卡信息更新 + */ + @SerializedName("membership_number") + private String membershipNumber; + + /** + * 用户会员等级 + */ + @SerializedName("level") + private String level; + + /** + * 用户的微信昵称,如通过手机号同步会员身份且用户未领取到卡包,无法查询该字段 + */ + @SerializedName("nickname") + private String nickname; + + /** + * 用户的微信头像url,如通过手机号同步会员身份且用户未领取到卡包,无法查询该字段 + */ + @SerializedName("head_image_url") + private String headImageUrl; + + /** + * 商家给当前用户设置的会员卡背景图。仅支持通过《图片上传API》接口获取的图片URL地址。支持JPG/JPEG/PNG格式,且图片小于1M。 + */ + @SerializedName("background_picture_url") + private String backgroundPictureUrl; + + /** + * 用户储值的最新余额,单位分 + */ + @SerializedName("balance") + private Integer balance; + + /** + * 用户当前的卡状态: + * NOT_ACTIVATE:未激活 + * EFFECTIVE:生效中 + * EXPIRE:已过期 + * UNAVAILABLE:已失效 + * DELETE:已删除 + * IMPORTED:已导入 + */ + @SerializedName("user_card_status") + private String userCardStatus; + + /** + * 用户开卡时填写的个人信息 + */ + @SerializedName("user_information") + private UserInformation userInformation; + + /** + * 用户当前的积分值 + */ + @SerializedName("bonus_value") + private Integer bonusValue; + + /** + * 用户当前的积分值 + */ + @SerializedName("service_modules") + private List
+ * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_23.shtml + *+ * + * @author thinsstar + */ +@NoArgsConstructor +@Data +public class MemberCardRightsRequest implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 变更前的用户的积分值 + */ + @SerializedName("before_bonus_value") + private Integer beforeBonusValue; + + /** + * 变更后的用户最新积分值,该值会展示在会员卡详页上 + */ + @SerializedName("bonus_value") + private Integer bonusValue; + + /** + * 本次变更的积分值 + */ + @SerializedName("add_bonus_value") + private Integer addBonusValue; + + /** + * 商户凭据号。商户自定义,注意保持唯一性,仅供参考的格式:商户id+日期+流水号。可包含英文字母,数字,|,_,*,-等内容,不允许出现其他不合法符号。 + */ + @SerializedName("out_request_no") + private String outRequestNo; + + /** + * 积分变更时是否触发系统模板消息,默认为true + */ + @SerializedName("need_inform_bonus") + private Boolean needInformBonus; + + /** + * 用户会员卡详情页会员优惠栏目中的会员专享价文案 + */ + @SerializedName("member_price_word") + private String memberPriceWord; + + /** + *发票栏跳转小程序的引导文案 + */ + @SerializedName("fapiao_jump_word") + private String fapiaoJumpWord; + + /** + *设置商家联系人员的名字、头像和联系方式 + */ + @SerializedName("guide") + private Guide guide; + + @Data + public static class Guide implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 设置商家咨询联系人的名称 + */ + @SerializedName("staff_name") + private String staffName; + + /** + * 设置商家咨询联系人的头像。仅支持通过《图片上传API》接口获取的图片URL地址。 + */ + @SerializedName("head_image_url") + private String headImageUrl; + + /** + * 展示说明商家咨询联系人的联系方式,例如“微信号”“企业微信号” + */ + @SerializedName("contact_information_name") + private String contactInformationName; + + /** + * 展示说明商家咨询联系人的联系方式信息,例如“weixin123”“135266664” + */ + @SerializedName("contact_information_value") + private String contactInformationValue; + + /** + * 商家咨询联系人的联系电话 + */ + @SerializedName("phone_number") + private String phoneNumber; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardUpdRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardUpdRequest.java new file mode 100644 index 00000000..d697c8a5 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/membercard/MemberCardUpdRequest.java @@ -0,0 +1,95 @@ +package com.github.binarywang.wxpay.bean.membercard; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * 修改用户会员卡信息API + *
+ * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_8.shtml + *+ * + * @author thinsstar + */ +@NoArgsConstructor +@Data +public class MemberCardUpdRequest implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 在用户会员卡上展示的会员卡编号,默认使用会员卡code作为membership_number。只能录入数字/英文/半角标点。商家可通过修改用户单张会员卡信息更新 + */ + @SerializedName("membership_number") + private String membershipNumber; + + /** + * 商家给当前用户设置的会员卡背景图。仅支持通过《图片上传API》接口获取的图片URL地址。支持JPG/JPEG/PNG格式,且图片小于1M。 + */ + @SerializedName("background_picture_url") + private String backgroundPictureUrl; + + /** + * 用户会员等级 + */ + @SerializedName("level") + private String level; + + /** + * 商户据号。商户自定义,注意保持唯一性,仅供参考的格式:商户id+日期+流水号。可包含英文字母,数字,|,_,*,-等内容,不允许出现其他不合法符号。 + */ + @SerializedName("out_request_no") + private String outRequestNo; + + /** + * 用户储值变更信息 + */ + @SerializedName("balance_information") + private BalanceInformation balanceInformation; + + /** + * 用户储值变更信息 + */ + @SerializedName("need_inform_balance") + private Boolean needInformBalance; + + /** + * 用户储值变更信息 + */ + @SerializedName("need_inform_level") + private Boolean needInformLevel; + + + @Data + public static class BalanceInformation implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 用户储值的更新前余额,单位分 + */ + @SerializedName("before_balance") + private Integer beforeBalance; + + /** + * 用户储值的更新后余额,单位分 + */ + @SerializedName("balance") + private Integer balance; + + /** + * 用户储值余额本次的变动值,单位分,等于balance减去before_balance,传入正数表示余额增加,传入负数表示余额减少 + */ + @SerializedName("add_balance") + private Integer addBalance; + + /** + * 商家自定义储值金额消耗记录,不超过30个字 + */ + @SerializedName("balance_remark") + private String balanceRemark; + + } +} 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 index d3e662f8..c397e930 100644 --- 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 @@ -1,9 +1,6 @@ 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.businesscircle.*; import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; import com.github.binarywang.wxpay.exception.WxPayException; @@ -32,4 +29,31 @@ public interface BusinessCircleService { PaidResult decryptPaidNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException; RefundResult decryptRefundNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException; + + MemberCardAuthorizeNotifyResult decryptMemberCardAuthorizeNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException; + + /** + * 授权查询 + * https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_6_4.shtml + * @return + * @throws WxPayException + */ + MemberCardAuthorizeResult getAuthorizations(String openid) throws WxPayException; + + /** + * 查询待积分状态 + * @param brandid + * @param openid + * @return + * @throws WxPayException + */ + PointsCommitStatusResult getPointsCommitStatus(String brandid,String openid) throws WxPayException; + + /** + * 停车状态同步 + * https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_6_5.shtml + * @param request + * @throws WxPayException + */ + void notifyParkings(ParkingNotifyRequest request) throws WxPayException; } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MemberCardService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MemberCardService.java new file mode 100644 index 00000000..6d91325e --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MemberCardService.java @@ -0,0 +1,50 @@ +package com.github.binarywang.wxpay.service; + +import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; +import com.github.binarywang.wxpay.bean.membercard.*; +import com.github.binarywang.wxpay.exception.WxPayException; + +/** + *
+ * 会员卡相关接口 + *+ * + * @author thinsstar + */ +public interface MemberCardService { + + MemberCardNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException; + + MemberCardActivateResult decryptActivateNotifyDataResource(MemberCardNotifyData data) throws WxPayException; + + /** + * 查询会员卡信息 + * https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_6.shtml + * @param card_id + * @param code + * @return + * @throws WxPayException + */ + MemberCardResult getMemberCard(String card_id,String code) throws WxPayException; + + /** + * 修改用户会员卡信息API + * https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_8.shtml + * @param card_id + * @param code + * @param request + * @throws WxPayException + */ + void updMemberCard(String card_id, String code, MemberCardUpdRequest request) throws WxPayException; + + /** + * 设置用户会员权益信息api + * https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_23.shtml + * @param card_id + * @param code + * @param request + * @throws WxPayException + */ + void setMemberCardRights(String card_id,String code,MemberCardRightsRequest request) 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 0451a922..9bfa69d7 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 @@ -155,6 +155,13 @@ public interface WxPayService { */ BusinessCircleService getBusinessCircleService(); + /** + * 获取会员卡服务类 + * + * @return the business circle service + */ + MemberCardService getMemberCardService(); + /** * 特约商户进件服务 * 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 c68e11d4..76fa3852 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 @@ -61,6 +61,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService { private ProfitSharingService profitSharingService = new ProfitSharingServiceImpl(this); private RedpackService redpackService = new RedpackServiceImpl(this); private BusinessCircleService businessCircleService = new BusinessCircleServiceImpl(this); + private MemberCardService memberCardServiceService = new MemberCardServiceImpl(this); private Applyment4SubService applyment4SubService = new Applyment4SubServiceImpl(this); private MerchantMediaService merchantMediaService = new MerchantMediaServiceImpl(this); private BankService bankService = new BankServiceImpl(this); @@ -85,6 +86,11 @@ public abstract class BaseWxPayServiceImpl implements WxPayService { return this.businessCircleService; } + @Override + public MemberCardService getMemberCardService(){ + return this.memberCardServiceService; + } + @Override public RedpackService getRedpackService() { return this.redpackService; 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 index 89905df5..9e9b5220 100644 --- 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 @@ -1,9 +1,6 @@ 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.businesscircle.*; import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.BusinessCircleService; @@ -86,4 +83,43 @@ public class BusinessCircleServiceImpl implements BusinessCircleService { throw new WxPayException("解析报文异常!", e); } } + + @Override + public MemberCardAuthorizeNotifyResult decryptMemberCardAuthorizeNotifyDataResource(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), MemberCardAuthorizeNotifyResult.class); + } catch (GeneralSecurityException | IOException e) { + throw new WxPayException("解析报文异常!", e); + } + } + + @Override + public MemberCardAuthorizeResult getAuthorizations(String openid) throws WxPayException { + String url = String.format("%s/v3/businesscircle/user-authorizations/%s?sub_mchid=%s&appid=%s", + this.payService.getPayBaseUrl(),openid,this.payService.getConfig().getSubMchId(),this.payService.getConfig().getAppId()); + String response = this.payService.getV3WithWechatPaySerial(url); + return GSON.fromJson(response,MemberCardAuthorizeResult.class); + } + + @Override + public PointsCommitStatusResult getPointsCommitStatus(String brandid, String openid) throws WxPayException { + String url = String.format("%s/v3/businesscircle/user/%s/points/commit_status?sub_mchid=%s&brandid=%s&appid=%s", + this.payService.getPayBaseUrl(),openid,this.payService.getConfig().getSubMchId(),brandid,this.payService.getConfig().getAppId()); + String response = this.payService.getV3WithWechatPaySerial(url); + return GSON.fromJson(response,PointsCommitStatusResult.class); + } + + @Override + public void notifyParkings(ParkingNotifyRequest request) throws WxPayException { + request.setAppid(this.payService.getConfig().getAppId()); + request.setSubMchid(this.payService.getConfig().getSubMchId()); + String url = String.format("%s/v3/businesscircle/parkings", this.payService.getPayBaseUrl()); + RsaCryptoUtil.encryptFields(request, this.payService.getConfig().getVerifier().getValidCertificate()); + this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request)); + } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MemberCardServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MemberCardServiceImpl.java new file mode 100644 index 00000000..6e503e99 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MemberCardServiceImpl.java @@ -0,0 +1,87 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; +import com.github.binarywang.wxpay.bean.membercard.*; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.MemberCardService; +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; + +/** + * 会员卡相关 + * + * @author thinsstar + */ +@Slf4j +@RequiredArgsConstructor +public class MemberCardServiceImpl implements MemberCardService { + private static final Gson GSON = new GsonBuilder().create(); + private final WxPayService payService; + + /** + * 校验通知签名 + * + * @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 MemberCardNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException { + if (Objects.nonNull(header) && !this.verifyNotifySign(header, data)) { + throw new WxPayException("非法请求,头部信息验证失败"); + } + return GSON.fromJson(data, MemberCardNotifyData.class); + } + + @Override + public MemberCardActivateResult decryptActivateNotifyDataResource(MemberCardNotifyData data) throws WxPayException { + MemberCardNotifyData.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), MemberCardActivateResult.class); + } catch (GeneralSecurityException | IOException e) { + throw new WxPayException("解析报文异常!", e); + } + } + + @Override + public MemberCardResult getMemberCard(String card_id, String code) throws WxPayException { + String url = String.format("%s/v3/marketing/membercard-open/cards/%s/codes/%s", this.payService.getPayBaseUrl(),card_id,code); + String response = this.payService.getV3WithWechatPaySerial(url); + return GSON.fromJson(response,MemberCardResult.class); + } + + @Override + public void updMemberCard(String card_id, String code, MemberCardUpdRequest request) throws WxPayException { + String url = String.format("%s/v3/marketing/membercard-open/cards/%s/codes/%s", this.payService.getPayBaseUrl(),card_id,code); + RsaCryptoUtil.encryptFields(request, this.payService.getConfig().getVerifier().getValidCertificate()); + this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request)); + } + + @Override + public void setMemberCardRights(String card_id, String code, MemberCardRightsRequest request) throws WxPayException { + String url = String.format("%s/v3/marketing/membercard-open/cards/%s/codes/%s/rights", this.payService.getPayBaseUrl(),card_id,code); + RsaCryptoUtil.encryptFields(request, this.payService.getConfig().getVerifier().getValidCertificate()); + this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request)); + } + +}