@@ -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(); | |||