前言
消息提醒功能是提升用户满意度的最有效方式,基于微信聊天的消息提醒也是现在最常见的消息提醒方式之一,常见的业务场景:从医院里面进行挂号预约,预约成功或是快到预约时间会从微信聊天列表中显示对应的提醒;这种提醒的方式实际上是借助于微信公众号进行实现,当然只是针对于关注公众号的用户进行消息推送.本文主要介绍如何从头开始实现公众号消息推送.
操作步骤
1.创建服务号类型的公众号并进行认证
首先要创建公众号,注意创建的类型一定是服务号,模板消息发送功能只支持服务号,订阅号只能进行消息订阅功能;这里面有坑,不仔细的同学会发现没有申请模板消息的入口,根本原因就是所使用的公众号是订阅号而不是服务号;查看公众号是服务号还是订阅号的方式可以参考下图(公账号登录之后右上角账号信息中),如果是订阅号,模板消息发送功能就不用考虑了.
另外一定要进行认证,才允许申请模板消息.认证入口在这里:
由于已经认证过,所以右边不显示认证入口.认证的流程是补充公司营业执照相关信息、公司对公账号打款、三方电话认证等。这里需要交300认证费的,做过认证的都知道很简单,感觉人家三百赚的真容易.当时周六提交的认证信息,财务还没对公打款,交完三百之后三方的认证电话就打过来了,下午就显示认证通过了,效率确实很快,哈哈哈哈!
2.申请模板消息功能
认证审核通过之后可以添加模板消息功能.添加入口如下:
由于已经添加过,所以广告服务下面不显示,都显示到已开通栏目中了.如果没有开通过但是从广告与服务中找不到模板消息,大概率当前的公众号类型为订阅号.
添加模板信息需要选择两个行业分类,按照业务类型选择对应的分类即可,如果选项中没有符合要求的分类信息可以选择其他.然后简单描述一下添加模板消息的目的.审核速度还可以,基本上两个小时就通过了,跟之前腾讯客服的工作效率截然不同,更别说是周六提审的.怀疑这个审核是不是也委托给了三方.添加模板信息比较简单,这里就不进行截图了.
3.添加消息模板
模板消息功能中我的模板会显示已添加的消息模板(注意模板id发送消息的时候会用到)
对于模板消息,腾讯提供了很多的消息模板进行选择,基本上涵盖当前大部分的消息提醒需求,直接按照内容进行搜索添加就可以,如果当前的业务消息提醒确定没有也可以进行添加,审核通过后会添加到模板库中,所有开发者都能使用.
自定义添加模板消息入口(先搜索,搜索不到才会显示入口):
4.添加模板消息发送接口
4.1获取权限AccessToken
公众号支持的接口基本上都需要权限认证,所以首先要获取AccessToken.获取方式如下:
public String getWxgAccessToken() { // 服务号的appid以及秘钥 String appid="服务号的appid"; String Wxgsecret="服务号的秘钥"; String requestUrl = StrUtil.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}", appid, Wxgsecret); String returnMsg = HttpUtil.get(requestUrl); cn.hutool.json.JSONObject responseJsonObject = JSONUtil.parseObj(returnMsg); if(ObjectUtil.isNull(responseJsonObject)) throw new Exception("响应异常:获取信息为空!"); String accessToken = responseJsonObject.getStr("access_token"); return accessToken; }
请求发送使用hutool中的HttpUtil,引入的依赖如下:
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.2.4</version> </dependency>
4.2获取要发送的用户的openId
这里不提供接口,使用官方在线的接口文档,获取方式如下:
官方文档中有获取关注公众号的所有用户信息接口.调用入口如下:
其中的openId中会显示所有关注公众号的用户openId.
4.3给指定用户发送消息
请求参数:
public class WxgMessageDto { // 消息接收者openId @NotBlank(message = "微信公众平台不允许为空!") private String openId; // 认证token @NotBlank(message = "accessToken不允许为空!") private String accessToken; // 省略get/set }
控制层:
@PostMapping("/sendWxgMessage") public ApiResult sendWxgMessage(@RequestBody @Validated WxgMessageDto wxgMessageDto) throws Exception { smallProgressService.sendWxgMessage(wxgMessageDto); return ApiResult.ok(); }
发送消息具体逻辑:
public void sendWxgMessage(WxgMessageDto wxgMessageDto) { // 组装消息内容 String templateId="模板id"; // 模板id String url="https://www.baidu.com/"; // 跳转路径(小程序之外) String appid=""; // 小程序appid String pagepath=""; // 小程序跳转路径 String client_msg_id=""; // 防重入id String first="朋友,有一个邀请面试通知待查收"; // 副标题 String keyword1=""; // 关键词1 String remark="更多详情信息请点击查看"; // 备注 String keyword1Value="阿里巴巴济南分巴"; // 信息 String keyword2Value="山东金融数字产业园"; // 信息 String keyword3Value="18560152023"; // 信息 String keyword4Value="总是想把世界上最好的给你,却发现世界上最好的是你.........."; // 信息 String color=""; // 颜色 String messageStr="{\n" + " \"touser\":"+"\""+wxgMessageDto.getOpenId()+"\""+",\n" + " \"template_id\":"+"\""+templateId+"\""+",\n" + " \"url\":"+"\""+url+"\""+", \n" + " \"miniprogram\":{\n" + " \"appid\":"+"\""+appid+"\""+",\n" + " \"pagepath\":"+"\""+pagepath+"\""+"\n" + " },\n" + // " \"client_msg_id\":\"MSG_000001\",\n" + " \"data\":{\n" + " \"first\": {\n" + " \"value\":"+"\""+first+"\""+",\n" + " \"color\":\"#173177\"\n" + " },\n" + " \"keyword1\":{\n" + " \"value\":"+"\""+keyword1Value+"\""+",\n" + " \"color\":\"#173177\"\n" + " },\n" + " \"keyword2\": {\n" + " \"value\":"+"\""+keyword2Value+"\""+",\n" + " \"color\":\"#173177\"\n" + " },\n" + " \"keyword3\": {\n" + " \"value\":"+"\""+keyword3Value+"\""+",\n" + " \"color\":\"#173177\"\n" + " },\n" + " \"keyword4\": {\n" + " \"value\":"+"\""+keyword4Value+"\""+",\n" + " \"color\":\"#173177\"\n" + " },\n" + " \"remark\":{\n" + " \"value\":"+" \""+remark+"\""+",\n" + " \"color\":\"#173177\"\n" + " }\n" + " }\n" + " }"; // 发送消息 String accessToken=wxgMessageDto.getAccessToken(); String returnMsg = HttpUtil.post(StrUtil.format("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={}", accessToken), messageStr); cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(returnMsg); String errmsg = jsonObject.getStr("errmsg"); if(!StrUtil.equals("ok",errmsg)) throw new BusinessException("消息发送失败!"); }
关于请求参数拼接直接使用的是官方给出的请求示例,注意里面传参的时候需要进行引号的转义.
5.移动端查看是否接收到已发送消息
测试发送消息接口:
查看消息接收情况: