| @@ -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; | |||
| @@ -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; | |||
| /** | |||
| * <pre> | |||
| * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html | |||
| * </pre> | |||
| * 发送订阅消息 | |||
| */ | |||
| void sendSubscribeMsg(WxMaSubscribeMessage subscribeMessage) throws WxErrorException; | |||
| /** | |||
| * <pre> | |||
| * 下发小程序和公众号统一的服务消息 | |||
| @@ -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; | |||
| } | |||
| /** | |||
| * <pre> | |||
| * 小程序模板消息接口将于2020年1月10日下线,开发者可使用订阅消息功能 | |||
| * </pre> | |||
| */ | |||
| @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()); | |||
| @@ -0,0 +1,30 @@ | |||
| package cn.binarywang.wx.miniapp.bean; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| /** | |||
| * <pre> | |||
| * 参考文档 https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html | |||
| * </pre> | |||
| */ | |||
| @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; | |||
| } | |||
| } | |||
| @@ -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. | |||
| * <pre> | |||
| * 参数:touser | |||
| * 是否必填: 是 | |||
| * 描述: 接收者(用户)的 openid | |||
| * </pre> | |||
| */ | |||
| private String toUser; | |||
| /** | |||
| * 所需下发的模板消息的id. | |||
| * <pre> | |||
| * 参数:template_id | |||
| * 是否必填: 是 | |||
| * 描述: 所需下发的模板消息的id | |||
| * </pre> | |||
| */ | |||
| private String templateId; | |||
| /** | |||
| * 点击模板卡片后的跳转页面,仅限本小程序内的页面. | |||
| * <pre> | |||
| * 参数:page | |||
| * 是否必填: 否 | |||
| * 描述: 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。 | |||
| * </pre> | |||
| */ | |||
| private String page; | |||
| /** | |||
| * 模板内容,不填则下发空模板. | |||
| * <pre> | |||
| * 参数:data | |||
| * 是否必填: 是 | |||
| * 描述: 模板内容,不填则下发空模板 | |||
| * </pre> | |||
| */ | |||
| private List<WxMaSubscribeData> data; | |||
| 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); | |||
| } | |||
| } | |||
| @@ -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()); | |||
| @@ -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<WxMaSubscribeMessage> { | |||
| @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; | |||
| } | |||
| } | |||
| @@ -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(); | |||