微信小程序结合微信公众号进行消息发送
由于小程序的模板消息已经废弃了,官方让使用订阅消息功能。而订阅消息的使用限制比较大,用户必须得订阅、需要获取用户同意接收消息的权限、用户必须得和小程序有交互的时候才能发送且只能发送一次。而我们的需求有可能是不限时间不限“次数”的发送消息。那么就可以使用官方提供的统一服务消息。
统一服务消息该功能还是有一点的使用限制的。
第一:小程序和公众号的主体必须是同一个。
第二:用户必须关注公众号。
第三:我们得有消息模板,小程序消息模板和公众号消息模板都可以。
注意:获得的token结果可以放在redis里面,设置上过期时间,防止应用重复获取access_token!
第二:构造请求 构造请求url根据官方提供的接口再加上我们的获取的access_token进行构造
POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=ACCESS_TOKEN 构造请求参数根据官方文档,我们一步一步来构造请求参数对象,我们用的是公众号的消息模板,所以这里没有weapp_template_msg参数
@Data @AllArgsConstructor @NoArgsConstructor public class ReqSendMessageData { /** * 消息接收者 */ private String touser; /** * 公众号模板消息信息 */ private MpTemplateMsg mp_template_msg; }构造mp_template_msg对象
@Data @NoArgsConstructor @AllArgsConstructor public class MpTemplateMsg { /** 公众号openId */ private String appid; /** 公众号模板id */ private String template_id; /** 跳转到公众号的地址,文档上写的必填,我没填,没有报错 */ private String url; /** 公众号绑定的小程序信息 */ private Miniprogram miniprogram; /** 数据 */ private Map<String,Object> data; }构造小程序信息
@Data @AllArgsConstructor @NoArgsConstructor public class Miniprogram { /** 小程序appid */ private String appid; /** 要跳转到小程序的页面 */ private String page; }贴出httpClient发送post请求的方式
public static String postSendJsonParam(String url, String param) { CloseableHttpClient httpClient = HttpClients.createDefault(); String result = null; // 请求方式 HttpPost httpPost = null; // 响应 CloseableHttpResponse httpResponse = null; httpPost = new HttpPost(url); httpPost.setHeader("Connection", REQUEST_HEADER_CONNECTION); httpPost.setHeader("User-Agent", REQUEST_HEADER_USER_AGENT); httpPost.addHeader("content-type", "application/json;charset=utf-8"); httpPost.addHeader("accept", "application/json"); httpPost.setEntity(new StringEntity(param, "UTF-8")); try { httpResponse = httpClient.execute(httpPost); HttpEntity httpEntity = httpResponse.getEntity(); result = EntityUtils.toString(httpEntity); } catch (IOException e) { e.printStackTrace(); } finally { if (httpClient != null) { try { httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } return result; }构造返回值对象,我们根据错误代码进行扩展操作
@Data public class ResSendMessageDTO { /** 错误代码 */ private String errcode; /** 错误信息 */ private String errmsg; }最后我们可以把这些封装成一个service交给spring管理。
public interface MessageService { /** * @author: taoym * @date: 2020/7/2 9:08 * @desc: 推送消息 */ ResSendMessageDTO sendMessage(ReqSendMessageData data); }具体实现不展示了。
封装消息发送者
@Component public class MessageSender { @Autowired private MessageService messageService; /** * @param first 消息标题 * @param keywordMap 消息内容 * @param page 要跳转到小程序的页面 * @param templateId 模板消息编号 * @param touser 消息接收者openId * @author: taoym * @date: 2020/9/28 11:25 * @desc: 消息发送者 */ public ResSendMessageDTO sendMessage(String first, Map<String, Keyword> keywordMap, String touser, String page, String templateId) { // 消息模板上的数据 Map<String, Object> messageData = Maps.newHashMap(); // first,可以理解为 标题 messageData.put("first", new First(first)); // keywordMap 可以理解为内容 messageData.putAll(keywordMap); ReqSendMessageData reqSendMessageData = new ReqSendMessageData(); reqSendMessageData.setTouser(PasswordUtils.decrypt(touser)); MpTemplateMsg mpTemplateMsg = new MpTemplateMsg(); Miniprogram miniprogram = new Miniprogram(); miniprogram.setPage(page); mpTemplateMsg.setMiniprogram(miniprogram); mpTemplateMsg.setData(messageData); mpTemplateMsg.setTemplate_id(templateId); reqSendMessageData.setMp_template_msg(mpTemplateMsg); ResSendMessageDTO resSendMessageDTO = messageService.sendMessage(reqSendMessageData); // 0为成功的标志 if (!resSendMessageDTO.getErrcode().equals("0")) { throw new ExceptionCore(resSendMessageDTO.getErrcode(), resSendMessageDTO.getErrmsg()); } return resSendMessageDTO; } }最后我们只需要根据模板消息的内容构造合理的参数,然后调用该方法即可发送消息。