@@ -444,6 +444,14 @@ public enum WxMaErrorMsgEnum { | |||||
CODE_85064(85064, "找不到模版/草稿"), | CODE_85064(85064, "找不到模版/草稿"), | ||||
CODE_85065(85065, "模版库已满"), | 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; | private int code; | ||||
@@ -1,6 +1,7 @@ | |||||
package cn.binarywang.wx.miniapp.api; | package cn.binarywang.wx.miniapp.api; | ||||
import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; | 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.WxMaTemplateMessage; | ||||
import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage; | import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage; | ||||
import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||
@@ -15,6 +16,7 @@ import me.chanjar.weixin.common.error.WxErrorException; | |||||
public interface WxMaMsgService { | public interface WxMaMsgService { | ||||
String KEFU_MESSAGE_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/custom/send"; | 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 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"; | 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; | 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> | * <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.WxMaMsgService; | ||||
import cn.binarywang.wx.miniapp.api.WxMaService; | import cn.binarywang.wx.miniapp.api.WxMaService; | ||||
import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; | 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.WxMaTemplateMessage; | ||||
import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage; | import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage; | ||||
import cn.binarywang.wx.miniapp.constant.WxMaConstants; | import cn.binarywang.wx.miniapp.constant.WxMaConstants; | ||||
@@ -27,6 +28,11 @@ public class WxMaMsgServiceImpl implements WxMaMsgService { | |||||
return responseContent != null; | return responseContent != null; | ||||
} | } | ||||
/** | |||||
* <pre> | |||||
* 小程序模板消息接口将于2020年1月10日下线,开发者可使用订阅消息功能 | |||||
* </pre> | |||||
*/ | |||||
@Override | @Override | ||||
public void sendTemplateMsg(WxMaTemplateMessage templateMessage) throws WxErrorException { | public void sendTemplateMsg(WxMaTemplateMessage templateMessage) throws WxErrorException { | ||||
String responseContent = this.wxMaService.post(TEMPLATE_MSG_SEND_URL, templateMessage.toJson()); | 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 | @Override | ||||
public void sendUniformMsg(WxMaUniformMessage uniformMessage) throws WxErrorException { | public void sendUniformMsg(WxMaUniformMessage uniformMessage) throws WxErrorException { | ||||
String responseContent = this.wxMaService.post(UNIFORM_MSG_SEND_URL, uniformMessage.toJson()); | 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; | 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.WxMaTemplateMessage; | ||||
import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage; | import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage; | ||||
import cn.binarywang.wx.miniapp.bean.analysis.WxMaRetainInfo; | import cn.binarywang.wx.miniapp.bean.analysis.WxMaRetainInfo; | ||||
@@ -19,6 +20,7 @@ public class WxMaGsonBuilder { | |||||
static { | static { | ||||
INSTANCE.disableHtmlEscaping(); | INSTANCE.disableHtmlEscaping(); | ||||
INSTANCE.registerTypeAdapter(WxMaTemplateMessage.class, new WxMaTemplateMessageGsonAdapter()); | INSTANCE.registerTypeAdapter(WxMaTemplateMessage.class, new WxMaTemplateMessageGsonAdapter()); | ||||
INSTANCE.registerTypeAdapter(WxMaSubscribeMessage.class, new WxMaSubscribeMessageGsonAdapter()); | |||||
INSTANCE.registerTypeAdapter(WxMaUniformMessage.class, new WxMaUniformMessageGsonAdapter()); | INSTANCE.registerTypeAdapter(WxMaUniformMessage.class, new WxMaUniformMessageGsonAdapter()); | ||||
INSTANCE.registerTypeAdapter(WxMaCodeCommitRequest.class, new WxMaCodeCommitRequestGsonAdapter()); | INSTANCE.registerTypeAdapter(WxMaCodeCommitRequest.class, new WxMaCodeCommitRequestGsonAdapter()); | ||||
INSTANCE.registerTypeAdapter(WxMaCodeVersionDistribution.class, new WxMaCodeVersionDistributionGsonAdapter()); | 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.text.SimpleDateFormat; | ||||
import java.util.Date; | import java.util.Date; | ||||
import cn.binarywang.wx.miniapp.bean.*; | |||||
import org.testng.annotations.*; | import org.testng.annotations.*; | ||||
import cn.binarywang.wx.miniapp.api.WxMaService; | 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.ApiTestModule; | ||||
import cn.binarywang.wx.miniapp.test.TestConfig; | import cn.binarywang.wx.miniapp.test.TestConfig; | ||||
import com.google.common.collect.Lists; | import com.google.common.collect.Lists; | ||||
@@ -59,6 +56,21 @@ public class WxMaMsgServiceImplTest { | |||||
this.wxService.getMsgService().sendTemplateMsg(templateMessage); | 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 | @Test | ||||
public void testSendUniformMsg() throws WxErrorException { | public void testSendUniformMsg() throws WxErrorException { | ||||
TestConfig config = (TestConfig) this.wxService.getWxMaConfig(); | TestConfig config = (TestConfig) this.wxService.getWxMaConfig(); | ||||