登录  /  注册

实现微信小程序模板消息不受限制、无限主动推送

韦小宝
发布: 2018-03-01 14:55:59
原创
9173人浏览过

需求背景

基于微信的通知渠道,微信小程序为开发者提供了可以高效触达用户的模板消息能力,在用户本人与小程序页面有交互行为后触发,通过微信聊天列表中的服务通知可快捷进入查看消息,点击查看详情还能跳转到下发消息的小程序的指定页面。

微信小程序允许下发模板消息的条件分为两类:支付或者提交表单。通过提交表单来下发模板消息的限制为“允许开发者向用户在7天内推送有限条数的模板消息(1次提交表单可下发1条,多次提交下条数独立,相互不影响)”。

然而,用户1次触发7天内推送1条通知是明显不够用的。比如,签到功能利用模板消息的推送来提醒用户每天签到,只能在用户前一天签到的情况下,获取一次推送模板消息的机会,然后用于第二天向该用户发送签到提醒。但是很多情况下,用户在某一天忘记签到,系统便失去了提醒用户的权限,导致和用户断开了联系;再比如,系统想主动告知用户即将做某活动,然而由于微信小程序被动触发通知的限制,系统将无法主动推送消息。

如何让模板消息的推送不被限制?

突破口:“1次提交表单可下发1条,多次提交下发条数独立,相互不影响”

为了突破模板消息的推送限制,实现7天内任性推送,只需收集到足够的推送码,即每次提交表单时获取到的formId。一个formId代表着开发者有向当前用户推送模板消息的一次权限。

客户端

收集推送码

表单组件中的属性report-submit=true时表示发送模板消息,提交表单便可以获取formId。接下来只要对原先的页面进行改造,将用户原先绑定了点击事件的界面用表单组件中的button按钮组件来代替,即把用户的交互点击的bindtap事件由表单bindsubmit来代替,从而捕获用户的点击事件来生成更多的推送码。

// 收集推送码
Page({
   formSubmit: funcition(e) {
let formId = e.detail.formId;
this.collectFormIds(formId); //保存推送码
let type = e.detail.target.dataset.type; // 根据type执行点击事件
},

   collectFormIds: function(formId) { 
let formIds = app.globalData.globalFormIds; // 获取全局推送码数组
if (!formIds)
           formIds = [];
let data = {
           formId: formId,
           expire: new Data().getTime() + 60480000 // 7天后的过期时间戳
}
       formIds.push(data);
       app.globalData.globalFormIds = formIds;
},
})
登录后复制

上报推送码

等待用户下一次发起网络请求时,将globalFormIds发送给服务器。

// 上报推送码
Page({
   onLoad: funcition(e) {
this.uploadFormIds(); //上传推送码
},

   collectFormIds: function(formId) { 
var formIds = app.globalData.globalFormIds; // 获取全局推送码
if (formIds.length) {
            formIds = JSON.stringify(formIds); // 转换成JSON字符串
            app.globalData.gloabalFomIds = ''; // 清空当前全局推送码
}
       wx.request({ // 发送到服务器
           url: 'http://xxx',
           method: 'POST',
           data: {
               openId: 'openId',
               formIds: formIds
},
           success: function(res) {
}
});
},
})
登录后复制

服务端

存储推送码

高频IO,采用Redis来存储推送码。

/**
* 收集用户推送码
*
* @param openId        用户的openid
* @param formTemplates 用户的表单模板
*/
public void collect(String openId, List<formtemplatevo> formTemplates) {
   redisTemplate.opsForList().rightPushAll("mina:openid:" + openId, formTemplates);
}</formtemplatevo>
登录后复制

推送模板消息

下面实现了群发的功能,针对特定用户类似。

/**
* 推送消息
*
* @param templateId 模板消息id
* @param page       跳转页面
* @param keyWords   模板内容
*/
public void push(String templateId, String page, String keyWords) {
String logPrefix = "推送消息";

// 获取access token
String accessToken = this.getAccessToken();

// 创建消息通用模板
MsgTemplateVO msgTemplateVO = MsgTemplateVO.builder().template_id(templateId).build();
// 跳转页面
   msgTemplateVO.setPage(StringUtils.isNotBlank(page) ? page : "");
// 模板内容
if (StringUtils.isNotBlank(keyWords)) {
String[] keyWordArr = keyWords.split(BaseConsts.COMMA_STR);
Map<string> keyWordMap = new HashMap(8);
for (int i = 0; i  openIdList = minaRedisDao.getAllOpenIds();

for (String openId : openIdList) {
// 获取有效推送码
String formId = minaRedisDao.getValidFormId(openId);
if (StringUtils.isBlank(formId)) {
           LOGGER.error("{}&gt;&gt;&gt;openId={}&gt;&gt;&gt;已无有效推送码[失败]", logPrefix, openId);
continue;
}

// 指派消息
MsgTemplateVO assignMsgTemplateVO = msgTemplateVO.assign(openId, formId);

// 发送消息
Map<string> resultMap;
try {
String jsonBody = JsonUtils.getObjectMapper().writeValueAsString(assignMsgTemplateVO);

String resultBody = OkHttpUtils.getInstance().postAsString(messageUrl + accessToken, jsonBody);
           resultMap = JsonUtils.getObjectMapper().readValue(resultBody, Map.class);
} catch (IOException e) {
           LOGGER.error("{}&gt;&gt;&gt;openId={}&gt;&gt;&gt;{}[失败]", logPrefix, openId, e.getMessage(), e);
continue;
}

if ((int) resultMap.get(ResponseConsts.Mina.CODE) != 0) {
           LOGGER.error("{}&gt;&gt;&gt;openId={}&gt;&gt;&gt;{}[失败]", logPrefix, openId, resultMap.get(ResponseConsts.Mina.MSG));
continue;
}

       LOGGER.info("{}&gt;&gt;&gt;openId={}&gt;&gt;&gt;[成功]", logPrefix, openId);
}
}

/**
* 根据用户获取有效的推送码
*
* @param openId 用户的openid
* @return 推送码
*/
public String getValidFormId(String openId) {
List<formtemplatevo> formTemplates = redisTemplate.opsForList().range("mina:openid:" + openId, 0, -1);

String validFormId = "";
int trimStart = 0;

int size;
for (int i = 0; i  System.currentTimeMillis()) {
           validFormId = formTemplates.get(i).getFormId();
           trimStart = i + 1;
break;
}
}

// 移除本次使用的和已过期的
   redisTemplate.opsForList().trim(KEY_MINA_PUSH + openId, trimStart == 0 ? size : trimStart, -1);

return validFormId;
}</formtemplatevo></string></string>
登录后复制

以上方案可以实现在用户最后一次使用小程序后的7天内,对用户发送多条模板消息唤回用户。

这就是实现微信小程序模板消息不受限制、无限主动推送的方法详细的所有内容。

相关文章:

微信小程序消息推送php服务器验证

以上就是实现微信小程序模板消息不受限制、无限主动推送的详细内容,更多请关注php中文网其它相关文章!

智能AI问答
PHP中文网智能助手能迅速回答你的编程问题,提供实时的代码和解决方案,帮助你解决各种难题。不仅如此,它还能提供编程资源和学习指导,帮助你快速提升编程技能。无论你是初学者还是专业人士,AI智能助手都能成为你的可靠助手,助力你在编程领域取得更大的成就。
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2024 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号