最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

微信小程序模板消息限制實(shí)現(xiàn)無限制主動(dòng)推送的示例代碼

 更新時(shí)間:2019年08月27日 11:39:44   作者:極樂叔  
這篇文章主要介紹了微信小程序模板消息限制實(shí)現(xiàn)無限制主動(dòng)推送的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

需求背景

基于微信的通知渠道,微信小程序?yàn)殚_發(fā)者提供了可以高效觸達(dá)用戶的模板消息能力,在用戶本人與小程序頁面有交互行為后觸發(fā),通過微信聊天列表中的服務(wù)通知可快捷進(jìn)入查看消息,點(diǎn)擊查看詳情還能跳轉(zhuǎn)到下發(fā)消息的小程序的指定頁面。

微信小程序允許下發(fā)模板消息的條件分為兩類:支付或者提交表單。通過提交表單來下發(fā)模板消息的限制為“允許開發(fā)者向用戶在7天內(nèi)推送有限條數(shù)的模板消息(1次提交表單可下發(fā)1條,多次提交下條數(shù)獨(dú)立,相互不影響)”。

然而,用戶1次觸發(fā)7天內(nèi)推送1條通知是明顯不夠用的。比如,簽到功能利用模板消息的推送來提醒用戶每天簽到,只能在用戶前一天簽到的情況下,獲取一次推送模板消息的機(jī)會(huì),然后用于第二天向該用戶發(fā)送簽到提醒。但是很多情況下,用戶在某一天忘記簽到,系統(tǒng)便失去了提醒用戶的權(quán)限,導(dǎo)致和用戶斷開了聯(lián)系;再比如,系統(tǒng)想主動(dòng)告知用戶即將做某活動(dòng),然而由于微信小程序被動(dòng)觸發(fā)通知的限制,系統(tǒng)將無法主動(dòng)推送消息。

如何突破模板消息的推送限制?

突破口:“1次提交表單可下發(fā)1條,多次提交下發(fā)條數(shù)獨(dú)立,相互不影響”

為了突破模板消息的推送限制,實(shí)現(xiàn)7天內(nèi)任性推送,只需收集到足夠的推送碼,即每次提交表單時(shí)獲取到的formId。一個(gè)formId代表著開發(fā)者有向當(dāng)前用戶推送模板消息的一次權(quán)限。

客戶端

收集推送碼

當(dāng)表單組件中的屬性report-submit=true時(shí)表示發(fā)送模板消息,提交表單便可以獲取formId。接下來只要對(duì)原先的頁面進(jìn)行改造,將用戶原先綁定了點(diǎn)擊事件的界面用表單組件中的button按鈕組件來代替,即把用戶的交互點(diǎn)擊的bindtap事件由表單bindsubmit來代替,從而捕獲用戶的點(diǎn)擊事件來生成更多的推送碼。

// 收集推送碼
Page({
  formSubmit: funcition(e) {
let formId = e.detail.formId;
this.collectFormIds(formId); //保存推送碼
let type = e.detail.target.dataset.type; // 根據(jù)type執(zhí)行點(diǎn)擊事件
},
 
  collectFormIds: function(formId) { 
let formIds = app.globalData.globalFormIds; // 獲取全局推送碼數(shù)組
if (!formIds)
      formIds = [];
let data = {
      formId: formId,
      expire: new Data().getTime() + 60480000 // 7天后的過期時(shí)間戳
}
    formIds.push(data);
    app.globalData.globalFormIds = formIds;
},
})

上報(bào)推送碼

等待用戶下一次發(fā)起網(wǎng)絡(luò)請(qǐng)求時(shí),將globalFormIds發(fā)送給服務(wù)器。

// 上報(bào)推送碼
Page({
  onLoad: funcition(e) {
this.uploadFormIds(); //上傳推送碼
},
 
  collectFormIds: function(formId) { 
var formIds = app.globalData.globalFormIds; // 獲取全局推送碼
if (formIds.length) {
      formIds = JSON.stringify(formIds); // 轉(zhuǎn)換成JSON字符串
      app.globalData.gloabalFomIds = ''; // 清空當(dāng)前全局推送碼
}
    wx.request({ // 發(fā)送到服務(wù)器
      url: 'http://xxx',
      method: 'POST',
      data: {
        openId: 'openId',
        formIds: formIds
},
      success: function(res) {
}
});
},
})

服務(wù)端

存儲(chǔ)推送碼

高頻IO,采用Redis來存儲(chǔ)推送碼。

/**
* 收集用戶推送碼
*
* @param openId    用戶的openid
* @param formTemplates 用戶的表單模板
*/
public void collect(String openId, List<FormTemplateVO> formTemplates) {
  redisTemplate.opsForList().rightPushAll("mina:openid:" + openId, formTemplates);
}

推送模板消息

下面實(shí)現(xiàn)了群發(fā)的功能,針對(duì)特定用戶類似。

/**
* 推送消息
*
* @param templateId 模板消息id
* @param page    跳轉(zhuǎn)頁面
* @param keyWords  模板內(nèi)容
*/
public void push(String templateId, String page, String keyWords) {
String logPrefix = "推送消息";
 
// 獲取access token
String accessToken = this.getAccessToken();
 
// 創(chuàng)建消息通用模板
MsgTemplateVO msgTemplateVO = MsgTemplateVO.builder().template_id(templateId).build();
// 跳轉(zhuǎn)頁面
  msgTemplateVO.setPage(StringUtils.isNotBlank(page) ? page : "");
// 模板內(nèi)容
if (StringUtils.isNotBlank(keyWords)) {
String[] keyWordArr = keyWords.split(BaseConsts.COMMA_STR);
Map<String, MsgTemplateVO.KeyWord> keyWordMap = new HashMap<>(8);
for (int i = 0; i < keyWordArr.length; i++) {
MsgTemplateVO.KeyWord keyWord = msgTemplateVO.new KeyWord(keyWordArr[i]);
      keyWordMap.put(MsgTemplateVO.KEYWORD + (i + 1), keyWord);
}
    msgTemplateVO.setData(keyWordMap);
} else {
    msgTemplateVO.setData(Collections.emptyMap());
}
 
// 獲取所有用戶
List<String> openIdList = minaRedisDao.getAllOpenIds();
 
for (String openId : openIdList) {
// 獲取有效推送碼
String formId = minaRedisDao.getValidFormId(openId);
if (StringUtils.isBlank(formId)) {
      LOGGER.error("{}>>>openId={}>>>已無有效推送碼[失敗]", logPrefix, openId);
continue;
}
 
// 指派消息
MsgTemplateVO assignMsgTemplateVO = msgTemplateVO.assign(openId, formId);
 
// 發(fā)送消息
Map<String, Object> 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("{}>>>openId={}>>>{}[失敗]", logPrefix, openId, e.getMessage(), e);
continue;
}
 
if ((int) resultMap.get(ResponseConsts.Mina.CODE) != 0) {
      LOGGER.error("{}>>>openId={}>>>{}[失敗]", logPrefix, openId, resultMap.get(ResponseConsts.Mina.MSG));
continue;
}
 
    LOGGER.info("{}>>>openId={}>>>[成功]", logPrefix, openId);
}
}
 
/**
* 根據(jù)用戶獲取有效的推送碼
*
* @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 < (size = formTemplates.size()); i++) {
if (formTemplates.get(i).getExpire() > 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;
}

以上方案可以實(shí)現(xiàn)在用戶最后一次使用小程序后的7天內(nèi),對(duì)用戶發(fā)送多條模板消息喚回用戶。

相關(guān)文章

  • javascript對(duì)象的多種合并方式詳解

    javascript對(duì)象的多種合并方式詳解

    這篇文章主要介紹了JavaScript中的多種對(duì)象合并方法,通過代碼的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下,希望能夠給你帶來幫助
    2021-08-08
  • JavaScript實(shí)現(xiàn)循環(huán)輪播圖

    JavaScript實(shí)現(xiàn)循環(huán)輪播圖

    這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)循環(huán)輪播圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • 小程序使用webview內(nèi)嵌h5頁面 wx.miniProgram.getEnv失效問題

    小程序使用webview內(nèi)嵌h5頁面 wx.miniProgram.getEnv失效問題

    本文主要介紹了小程序使用webview內(nèi)嵌h5頁面 wx.miniProgram.getEnv失效問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • js delete 用法(刪除對(duì)象屬性及變量)

    js delete 用法(刪除對(duì)象屬性及變量)

    js delete可以刪除對(duì)象屬性及變量,下面是一些示例,感興趣的朋友可以看看
    2014-08-08
  • JS實(shí)現(xiàn)圖片上下切換

    JS實(shí)現(xiàn)圖片上下切換

    這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)圖片上下切換,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • javascript,jquery閉包概念分析

    javascript,jquery閉包概念分析

    偶爾聽人說javascript閉包,讓我聯(lián)想起以前學(xué)編譯原理和數(shù)字邏輯里講的閉包,以前上課講的閉包很難懂,而且含有遞歸的意思在里面,現(xiàn)在不想再查看里面的閉包概念。
    2010-06-06
  • javascript實(shí)現(xiàn)跳轉(zhuǎn)菜單的具體方法

    javascript實(shí)現(xiàn)跳轉(zhuǎn)菜單的具體方法

    這篇文章介紹了javascript實(shí)現(xiàn)跳轉(zhuǎn)菜單的具體方法,有需要的朋友可以參考一下
    2013-07-07
  • JS對(duì)象屬性的檢測(cè)與獲取操作實(shí)例分析

    JS對(duì)象屬性的檢測(cè)與獲取操作實(shí)例分析

    這篇文章主要介紹了JS對(duì)象屬性的檢測(cè)與獲取操作,結(jié)合實(shí)例形式分析了JS針對(duì)ES5、ES6實(shí)現(xiàn)對(duì)象屬性的檢測(cè)與獲取常見操作技巧,需要的朋友可以參考下
    2020-03-03
  • js怎么只刷新當(dāng)前頁面一次

    js怎么只刷新當(dāng)前頁面一次

    Javascript刷新頁面的幾種方法:location.reload()、location.replace(location)、history.go(0)、location=location、location.assign(location)、document.execCommand('Refresh')、window.navigate(location)、document.URL=location.href,js怎么只刷新當(dāng)前頁面一次呢
    2023-09-09
  • 深入理解JavaScript系列(29):設(shè)計(jì)模式之裝飾者模式詳解

    深入理解JavaScript系列(29):設(shè)計(jì)模式之裝飾者模式詳解

    這篇文章主要介紹了深入理解JavaScript系列(29):設(shè)計(jì)模式之裝飾者模式詳解,裝飾者用用于包裝同接口的對(duì)象,不僅允許你向方法添加行為,而且還可以將方法設(shè)置成原始對(duì)象調(diào)用(例如裝飾者的構(gòu)造函數(shù)),需要的朋友可以參考下
    2015-03-03

最新評(píng)論

盐城市| 巴马| 西乡县| 九龙县| 涿鹿县| 常德市| 平塘县| 景泰县| 玉屏| 营山县| 北辰区| 尤溪县| 庆城县| 武宁县| 朝阳区| 车险| 湖口县| 兖州市| 思南县| 咸宁市| 竹溪县| 柳江县| 聂拉木县| 卢龙县| 玉山县| 南安市| 白山市| 岑巩县| 建始县| 宣武区| 霍山县| 乌兰察布市| 民丰县| 海淀区| 乐山市| 台东市| 香格里拉县| 中西区| 营山县| 积石山| 洛阳市|