實現微信小程式模板訊息不受限制、無限主動推送

來源:互聯網
上載者:User

需求背景

基於的通知渠道,小程式為開發人員提供了可以高效觸達使用者的模板訊息能力,在使用者本人與小程式頁面有互動行為後觸發,通過聊天列表中的服務通知可快捷進入查看訊息,點擊查看詳情還能跳轉到下發訊息的小程式的指定頁面。

小程式允許下發模板訊息的條件分為兩類:支付或者提交表單。通過提交表單來下發模板訊息的限制為“允許開發人員向使用者在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);}

推送模板訊息

下面實現了群發的功能,針對特定使用者類似。

/*** 推送訊息** @param templateId 模板訊息id* @param page       跳轉頁面* @param keyWords   模板內容*/public void push(String templateId, String page, String keyWords) {String logPrefix = "推送訊息";// 擷取access tokenString 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, 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);// 發送訊息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);}}/*** 根據使用者擷取有效推送碼** @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;}

以上方案可以實現在使用者最後一次使用小程式後的7天內,對使用者發送多條模板訊息喚回使用者。

這就是實現小程式模板訊息不受限制、無限主動推送的方法詳細的所有內容。

相關文章:

小程式訊息推送php伺服器驗證

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.