1
0
mirror of synced 2026-04-11 02:58:44 +08:00

feat(miniapp): 新增微信小程序服务卡片消息接口

实现以下三个服务卡片消息 API:
- 激活与更新服务卡片(setUserNotify)
- 更新服务卡片扩展信息(setUserNotifyExt)
- 查询服务卡片状态(getUserNotify)

Agent-Logs-Url: https://github.com/binarywang/WxJava/sessions/63aeccb8-2684-4ea7-8b6b-9db7d362044a

Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-04-07 09:17:45 +00:00
committed by GitHub
parent 2392cee28c
commit 08a6540362
8 changed files with 427 additions and 0 deletions

View File

@@ -1,5 +1,9 @@
package cn.binarywang.wx.miniapp.api;
import cn.binarywang.wx.miniapp.bean.WxMaGetUserNotifyRequest;
import cn.binarywang.wx.miniapp.bean.WxMaGetUserNotifyResult;
import cn.binarywang.wx.miniapp.bean.WxMaServiceNotifyExtRequest;
import cn.binarywang.wx.miniapp.bean.WxMaServiceNotifyRequest;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import me.chanjar.weixin.common.bean.subscribemsg.CategoryData;
import me.chanjar.weixin.common.bean.subscribemsg.PubTemplateKeyword;
@@ -113,4 +117,44 @@ public interface WxMaSubscribeService {
*/
void sendSubscribeMsg(WxMaSubscribeMessage subscribeMessage) throws WxErrorException;
/**
* <pre>
* 激活与更新服务卡片
*
* 详情请见: <a href="https://developers.weixin.qq.com/miniprogram/dev/server/API/mp-message-management/subscribe-message/api_setusernotify.html">激活与更新服务卡片</a>
* 接口url格式: POST https://api.weixin.qq.com/wxa/setusernotify?access_token=ACCESS_TOKEN
* </pre>
*
* @param request 请求参数
* @throws WxErrorException .
*/
void setUserNotify(WxMaServiceNotifyRequest request) throws WxErrorException;
/**
* <pre>
* 更新服务卡片扩展信息
*
* 详情请见: <a href="https://developers.weixin.qq.com/miniprogram/dev/server/API/mp-message-management/subscribe-message/api_setusernotifyext.html">更新服务卡片扩展信息</a>
* 接口url格式: POST https://api.weixin.qq.com/wxa/setusernotifyext?access_token=ACCESS_TOKEN
* </pre>
*
* @param request 请求参数
* @throws WxErrorException .
*/
void setUserNotifyExt(WxMaServiceNotifyExtRequest request) throws WxErrorException;
/**
* <pre>
* 查询服务卡片状态
*
* 详情请见: <a href="https://developers.weixin.qq.com/miniprogram/dev/server/API/mp-message-management/subscribe-message/api_getusernotify.html">查询服务卡片状态</a>
* 接口url格式: POST https://api.weixin.qq.com/wxa/getusernotify?access_token=ACCESS_TOKEN
* </pre>
*
* @param request 请求参数
* @return 服务卡片状态
* @throws WxErrorException .
*/
WxMaGetUserNotifyResult getUserNotify(WxMaGetUserNotifyRequest request) throws WxErrorException;
}

View File

@@ -2,6 +2,10 @@ package cn.binarywang.wx.miniapp.api.impl;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.WxMaSubscribeService;
import cn.binarywang.wx.miniapp.bean.WxMaGetUserNotifyRequest;
import cn.binarywang.wx.miniapp.bean.WxMaGetUserNotifyResult;
import cn.binarywang.wx.miniapp.bean.WxMaServiceNotifyExtRequest;
import cn.binarywang.wx.miniapp.bean.WxMaServiceNotifyRequest;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.subscribemsg.CategoryData;
@@ -89,4 +93,32 @@ public class WxMaSubscribeServiceImpl implements WxMaSubscribeService {
throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp));
}
}
@Override
public void setUserNotify(WxMaServiceNotifyRequest request) throws WxErrorException {
String responseContent = this.service.post(SERVICE_NOTIFY_SET_URL, request.toJson());
JsonObject jsonObject = GsonParser.parse(responseContent);
if (jsonObject.get(WxConsts.ERR_CODE).getAsInt() != 0) {
throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp));
}
}
@Override
public void setUserNotifyExt(WxMaServiceNotifyExtRequest request) throws WxErrorException {
String responseContent = this.service.post(SERVICE_NOTIFY_SET_EXT_URL, request.toJson());
JsonObject jsonObject = GsonParser.parse(responseContent);
if (jsonObject.get(WxConsts.ERR_CODE).getAsInt() != 0) {
throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp));
}
}
@Override
public WxMaGetUserNotifyResult getUserNotify(WxMaGetUserNotifyRequest request) throws WxErrorException {
String responseContent = this.service.post(SERVICE_NOTIFY_GET_URL, request.toJson());
JsonObject jsonObject = GsonParser.parse(responseContent);
if (jsonObject.get(WxConsts.ERR_CODE).getAsInt() != 0) {
throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp));
}
return WxMaGsonBuilder.create().fromJson(responseContent, WxMaGetUserNotifyResult.class);
}
}

View File

@@ -0,0 +1,66 @@
package cn.binarywang.wx.miniapp.bean;
import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 查询服务卡片状态请求.
*
* <p>接口文档:
* <a href="https://developers.weixin.qq.com/miniprogram/dev/server/API/mp-message-management/subscribe-message/api_getusernotify.html">
* 查询服务卡片状态</a>
*
* @author GitHub Copilot
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WxMaGetUserNotifyRequest implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户身份标识符.
* <pre>
* 参数openid
* 是否必填:是
* </pre>
*/
@SerializedName("openid")
private String openid;
/**
* 动态更新令牌.
* <pre>
* 参数notify_code
* 是否必填:是
* </pre>
*/
@SerializedName("notify_code")
private String notifyCode;
/**
* 卡片ID.
* <pre>
* 参数notify_type
* 是否必填:是
* </pre>
*/
@SerializedName("notify_type")
private Integer notifyType;
/**
* 转为 JSON 字符串.
*
* @return JSON 字符串
*/
public String toJson() {
return WxMaGsonBuilder.create().toJson(this);
}
}

View File

@@ -0,0 +1,60 @@
package cn.binarywang.wx.miniapp.bean;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* 查询服务卡片状态响应.
*
* <p>接口文档:
* <a href="https://developers.weixin.qq.com/miniprogram/dev/server/API/mp-message-management/subscribe-message/api_getusernotify.html">
* 查询服务卡片状态</a>
*
* @author GitHub Copilot
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class WxMaGetUserNotifyResult extends WxMaBaseResponse {
private static final long serialVersionUID = 1L;
/**
* 卡片状态信息.
*/
@SerializedName("notify_info")
private NotifyInfo notifyInfo;
/**
* 卡片状态详情.
*/
@Data
public static class NotifyInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 卡片ID.
*/
@SerializedName("notify_type")
private Integer notifyType;
/**
* 上次有效推送的卡片状态与状态相关字段,没推送过为空字符串.
*/
@SerializedName("content_json")
private String contentJson;
/**
* code 状态0 正常1 有风险2 异常10 用户拒收本次code.
*/
@SerializedName("code_state")
private Integer codeState;
/**
* code 过期时间,秒级时间戳.
*/
@SerializedName("code_expire_time")
private Long codeExpireTime;
}
}

View File

@@ -0,0 +1,82 @@
package cn.binarywang.wx.miniapp.bean;
import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 更新服务卡片扩展信息请求.
*
* <p>接口文档:
* <a href="https://developers.weixin.qq.com/miniprogram/dev/server/API/mp-message-management/subscribe-message/api_setusernotifyext.html">
* 更新服务卡片扩展信息</a>
*
* @author GitHub Copilot
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WxMaServiceNotifyExtRequest implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户身份标识符.
* <pre>
* 参数openid
* 是否必填:是
* 描述:用户身份标识符。
* 当使用微信支付订单号作为 code 时,需要与实际支付用户一致;
* 当通过前端获取 code 时,需要与点击 button 的用户一致。
* </pre>
*/
@SerializedName("openid")
private String openid;
/**
* 卡片ID.
* <pre>
* 参数notify_type
* 是否必填:是
* 描述卡片ID。
* </pre>
*/
@SerializedName("notify_type")
private Integer notifyType;
/**
* 动态更新令牌.
* <pre>
* 参数notify_code
* 是否必填:是
* 描述:动态更新令牌。
* </pre>
*/
@SerializedName("notify_code")
private String notifyCode;
/**
* 扩展信息.
* <pre>
* 参数ext_json
* 是否必填:是
* 描述:扩展信息,不同卡片的定义不同。
* </pre>
*/
@SerializedName("ext_json")
private String extJson;
/**
* 转为 JSON 字符串.
*
* @return JSON 字符串
*/
public String toJson() {
return WxMaGsonBuilder.create().toJson(this);
}
}

View File

@@ -0,0 +1,93 @@
package cn.binarywang.wx.miniapp.bean;
import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 激活与更新服务卡片请求.
*
* <p>接口文档:
* <a href="https://developers.weixin.qq.com/miniprogram/dev/server/API/mp-message-management/subscribe-message/api_setusernotify.html">
* 激活与更新服务卡片</a>
*
* @author GitHub Copilot
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WxMaServiceNotifyRequest implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户身份标识符.
* <pre>
* 参数openid
* 是否必填:是
* 描述:用户身份标识符。
* 当使用微信支付订单号作为 code 时,需要与实际支付用户一致;
* 当通过前端获取 code 时,需要与点击 button 的用户一致。
* </pre>
*/
@SerializedName("openid")
private String openid;
/**
* 卡片ID.
* <pre>
* 参数notify_type
* 是否必填:是
* 描述卡片ID。
* </pre>
*/
@SerializedName("notify_type")
private Integer notifyType;
/**
* 动态更新令牌.
* <pre>
* 参数notify_code
* 是否必填:是
* 描述:动态更新令牌。
* </pre>
*/
@SerializedName("notify_code")
private String notifyCode;
/**
* 卡片状态与状态相关字段.
* <pre>
* 参数content_json
* 是否必填:是
* 描述:卡片状态与状态相关字段,不同卡片的定义不同。
* </pre>
*/
@SerializedName("content_json")
private String contentJson;
/**
* 微信支付订单号验证字段(可选).
* <pre>
* 参数check_json
* 是否必填:否
* 描述:微信支付订单号验证字段。当将微信支付订单号作为 notify_code 时,在激活时需要传入。
* </pre>
*/
@SerializedName("check_json")
private String checkJson;
/**
* 转为 JSON 字符串.
*
* @return JSON 字符串
*/
public String toJson() {
return WxMaGsonBuilder.create().toJson(this);
}
}

View File

@@ -358,6 +358,15 @@ public class WxMaApiUrlConstants {
/** 发送订阅消息 */
String SUBSCRIBE_MSG_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send";
/** 激活与更新服务卡片 */
String SERVICE_NOTIFY_SET_URL = "https://api.weixin.qq.com/wxa/setusernotify";
/** 更新服务卡片扩展信息 */
String SERVICE_NOTIFY_SET_EXT_URL = "https://api.weixin.qq.com/wxa/setusernotifyext";
/** 查询服务卡片状态 */
String SERVICE_NOTIFY_GET_URL = "https://api.weixin.qq.com/wxa/getusernotify";
}
public interface User {

View File

@@ -1,6 +1,10 @@
package cn.binarywang.wx.miniapp.api.impl;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaGetUserNotifyRequest;
import cn.binarywang.wx.miniapp.bean.WxMaGetUserNotifyResult;
import cn.binarywang.wx.miniapp.bean.WxMaServiceNotifyExtRequest;
import cn.binarywang.wx.miniapp.bean.WxMaServiceNotifyRequest;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import me.chanjar.weixin.common.bean.subscribemsg.CategoryData;
import me.chanjar.weixin.common.bean.subscribemsg.PubTemplateKeyword;
@@ -71,4 +75,41 @@ public class WxMaSubscribeServiceImplTest {
// TODO 待完善补充
this.wxService.getSubscribeService().sendSubscribeMsg(WxMaSubscribeMessage.builder().build());
}
@Test
public void testSetUserNotify() throws WxErrorException {
// TODO 待完善补充,需要真实的 openid、notify_type、notify_code、content_json 参数
WxMaServiceNotifyRequest request = WxMaServiceNotifyRequest.builder()
.openid("test_openid")
.notifyType(1)
.notifyCode("test_notify_code")
.contentJson("{}")
.build();
this.wxService.getSubscribeService().setUserNotify(request);
}
@Test
public void testSetUserNotifyExt() throws WxErrorException {
// TODO 待完善补充,需要真实的 openid、notify_type、notify_code、ext_json 参数
WxMaServiceNotifyExtRequest request = WxMaServiceNotifyExtRequest.builder()
.openid("test_openid")
.notifyType(1)
.notifyCode("test_notify_code")
.extJson("{}")
.build();
this.wxService.getSubscribeService().setUserNotifyExt(request);
}
@Test
public void testGetUserNotify() throws WxErrorException {
// TODO 待完善补充,需要真实的 openid、notify_type、notify_code 参数
WxMaGetUserNotifyRequest request = WxMaGetUserNotifyRequest.builder()
.openid("test_openid")
.notifyCode("test_notify_code")
.notifyType(1)
.build();
WxMaGetUserNotifyResult result = this.wxService.getSubscribeService().getUserNotify(request);
assertThat(result).isNotNull();
System.out.println(result);
}
}