diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxMaErrorMsgEnum.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxMaErrorMsgEnum.java index 9650ce41d..f1ced3fd0 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxMaErrorMsgEnum.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxMaErrorMsgEnum.java @@ -444,6 +444,14 @@ public enum WxMaErrorMsgEnum { CODE_85064(85064, "找不到模版/草稿"), CODE_85065(85065, "模版库已满"), + + /** + * 小程序订阅消息错误码 + * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html + */ + CODE_43101(43101, "用户拒绝接受消息,如果用户之前曾经订阅过,则表示用户取消了订阅关系"), + + CODE_47003(47003, "模板参数不准确,可能为空或者不满足规则,errmsg会提示具体是哪个字段出错"), ; private int code; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaMsgService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaMsgService.java index f0dbccd81..3dec5140f 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaMsgService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaMsgService.java @@ -1,6 +1,7 @@ package cn.binarywang.wx.miniapp.api; import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; +import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage; import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage; import me.chanjar.weixin.common.error.WxErrorException; @@ -15,6 +16,7 @@ import me.chanjar.weixin.common.error.WxErrorException; public interface WxMaMsgService { String KEFU_MESSAGE_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/custom/send"; String TEMPLATE_MSG_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send"; + String SUBSCRIBE_MSG_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send"; String UNIFORM_MSG_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send"; /** @@ -36,6 +38,15 @@ public interface WxMaMsgService { void sendTemplateMsg(WxMaTemplateMessage templateMessage) throws WxErrorException; + /** + *
+ * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html + *+ * 发送订阅消息 + */ + void sendSubscribeMsg(WxMaSubscribeMessage subscribeMessage) throws WxErrorException; + + /** *
* 下发小程序和公众号统一的服务消息 diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImpl.java index c4cb456e2..26ebd74bc 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImpl.java @@ -3,6 +3,7 @@ package cn.binarywang.wx.miniapp.api.impl; import cn.binarywang.wx.miniapp.api.WxMaMsgService; import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; +import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage; import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage; import cn.binarywang.wx.miniapp.constant.WxMaConstants; @@ -27,6 +28,11 @@ public class WxMaMsgServiceImpl implements WxMaMsgService { return responseContent != null; } + /** + *+ * 小程序模板消息接口将于2020年1月10日下线,开发者可使用订阅消息功能 + *+ */ @Override public void sendTemplateMsg(WxMaTemplateMessage templateMessage) throws WxErrorException { String responseContent = this.wxMaService.post(TEMPLATE_MSG_SEND_URL, templateMessage.toJson()); @@ -36,6 +42,15 @@ public class WxMaMsgServiceImpl implements WxMaMsgService { } } + @Override + public void sendSubscribeMsg(WxMaSubscribeMessage subscribeMessage) throws WxErrorException { + String responseContent = this.wxMaService.post(SUBSCRIBE_MSG_SEND_URL, subscribeMessage.toJson()); + JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject(); + if (jsonObject.get(WxMaConstants.ERRCODE).getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + } + @Override public void sendUniformMsg(WxMaUniformMessage uniformMessage) throws WxErrorException { String responseContent = this.wxMaService.post(UNIFORM_MSG_SEND_URL, uniformMessage.toJson()); diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaSubscribeData.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaSubscribeData.java new file mode 100644 index 000000000..048e6dae8 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaSubscribeData.java @@ -0,0 +1,30 @@ +package cn.binarywang.wx.miniapp.bean; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *+ * 参考文档 https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html + *+ */ +@Data +@NoArgsConstructor +public class WxMaSubscribeData { + private String name; + private String value; + private String color; + + public WxMaSubscribeData(String name, String value) { + this.name = name; + this.value = value; + } + + public WxMaSubscribeData(String name, String value, String color) { + this.name = name; + this.value = value; + this.color = color; + } + + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaSubscribeMessage.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaSubscribeMessage.java new file mode 100644 index 000000000..a43fd5b47 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaSubscribeMessage.java @@ -0,0 +1,77 @@ +package cn.binarywang.wx.miniapp.bean; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import lombok.*; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * 订阅消息. + * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class WxMaSubscribeMessage implements Serializable { + + private static final long serialVersionUID = 6846729898251286686L; + + /** + * 接收者(用户)的 openid. + *+ * 参数:touser + * 是否必填: 是 + * 描述: 接收者(用户)的 openid + *+ */ + private String toUser; + + /** + * 所需下发的模板消息的id. + *+ * 参数:template_id + * 是否必填: 是 + * 描述: 所需下发的模板消息的id + *+ */ + private String templateId; + + /** + * 点击模板卡片后的跳转页面,仅限本小程序内的页面. + *+ * 参数:page + * 是否必填: 否 + * 描述: 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。 + *+ */ + private String page; + + /** + * 模板内容,不填则下发空模板. + *+ * 参数:data + * 是否必填: 是 + * 描述: 模板内容,不填则下发空模板 + *+ */ + private Listdata; + + + public WxMaSubscribeMessage addData(WxMaSubscribeData datum) { + if (this.data == null) { + this.data = new ArrayList<>(); + } + this.data.add(datum); + + return this; + } + + public String toJson() { + return WxMaGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java index f01eb33d6..5fab9de74 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java @@ -1,5 +1,6 @@ package cn.binarywang.wx.miniapp.util.json; +import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage; import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage; import cn.binarywang.wx.miniapp.bean.analysis.WxMaRetainInfo; @@ -19,6 +20,7 @@ public class WxMaGsonBuilder { static { INSTANCE.disableHtmlEscaping(); INSTANCE.registerTypeAdapter(WxMaTemplateMessage.class, new WxMaTemplateMessageGsonAdapter()); + INSTANCE.registerTypeAdapter(WxMaSubscribeMessage.class, new WxMaSubscribeMessageGsonAdapter()); INSTANCE.registerTypeAdapter(WxMaUniformMessage.class, new WxMaUniformMessageGsonAdapter()); INSTANCE.registerTypeAdapter(WxMaCodeCommitRequest.class, new WxMaCodeCommitRequestGsonAdapter()); INSTANCE.registerTypeAdapter(WxMaCodeVersionDistribution.class, new WxMaCodeVersionDistributionGsonAdapter()); diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaSubscribeMessageGsonAdapter.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaSubscribeMessageGsonAdapter.java new file mode 100644 index 000000000..d15226a9e --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaSubscribeMessageGsonAdapter.java @@ -0,0 +1,40 @@ +package cn.binarywang.wx.miniapp.util.json; + +import cn.binarywang.wx.miniapp.bean.WxMaSubscribeData; +import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +import java.lang.reflect.Type; + +public class WxMaSubscribeMessageGsonAdapter implements JsonSerializer { + + @Override + public JsonElement serialize(WxMaSubscribeMessage message, Type typeOfSrc, JsonSerializationContext context) { + JsonObject messageJson = new JsonObject(); + messageJson.addProperty("touser", message.getToUser()); + messageJson.addProperty("template_id", message.getTemplateId()); + if (message.getPage() != null) { + messageJson.addProperty("page", message.getPage()); + } + + + JsonObject data = new JsonObject(); + messageJson.add("data", data); + + if (message.getData() == null) { + return messageJson; + } + + for (WxMaSubscribeData datum : message.getData()) { + JsonObject dataJson = new JsonObject(); + dataJson.addProperty("value", datum.getValue()); + data.add(datum.getName(), dataJson); + } + + return messageJson; + } + +} diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImplTest.java index 298a9c934..f5f62cc57 100644 --- a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImplTest.java +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImplTest.java @@ -3,13 +3,10 @@ package cn.binarywang.wx.miniapp.api.impl; import java.text.SimpleDateFormat; import java.util.Date; +import cn.binarywang.wx.miniapp.bean.*; import org.testng.annotations.*; import cn.binarywang.wx.miniapp.api.WxMaService; -import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; -import cn.binarywang.wx.miniapp.bean.WxMaTemplateData; -import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; -import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage; import cn.binarywang.wx.miniapp.test.ApiTestModule; import cn.binarywang.wx.miniapp.test.TestConfig; import com.google.common.collect.Lists; @@ -59,6 +56,21 @@ public class WxMaMsgServiceImplTest { this.wxService.getMsgService().sendTemplateMsg(templateMessage); } + + @Test + public void testSendSubscribeMsg() throws WxErrorException { + TestConfig config = (TestConfig) this.wxService.getWxMaConfig(); + + WxMaSubscribeMessage message = new WxMaSubscribeMessage(); + message.setTemplateId(config.getTemplateId()); + message.setToUser(config.getOpenid()); + message.addData(new WxMaSubscribeData("thing1", "苹果到货啦")); + message.addData(new WxMaSubscribeData("amount3", "¥5")); + message.addData(new WxMaSubscribeData("thing5", "记得领取哦")); + this.wxService.getMsgService().sendSubscribeMsg(message); + } + + @Test public void testSendUniformMsg() throws WxErrorException { TestConfig config = (TestConfig) this.wxService.getWxMaConfig();