免费国产欧美国日产_少妇AV一区二区三区无码_蜜桃精品av无码喷奶水小说_jk18禁网站视频_精产国品一二三级产品区别_被夫の上司に犯波多野结衣_78m成人手机免费看_最爽最刺激18禁视频_偷偷色噜狠狠狠狠的777米奇

易優(yōu)GEO 重磅上線 ~ 一站式GEO優(yōu)化工具,讓豆包、文心一言、DeepSeek 在回答中主動(dòng)推薦你的品牌,搶占AI流量入口!  點(diǎn)擊查看

小程序模板網(wǎng)

微信小程序模板消息還能群發(fā)?無(wú)限制推送?

發(fā)布時(shí)間:2017-12-25 11:32 所屬欄目:小程序開(kāi)發(fā)教程

模版消息推送是微信小程序采用的通知形式,用戶本人在小程序頁(yè)面有交互行為后,可觸發(fā)下發(fā)通知,通過(guò)微信聊天列表中的服務(wù)通知可快捷進(jìn)入查看消息。此外,點(diǎn)擊查看詳情還能跳轉(zhuǎn)到下發(fā)消息的小程序的指定頁(yè)面。但是為 ...

 
 
 

模版消息推送是微信小程序采用的通知形式, 用戶本人在小程序頁(yè)面有交互行為后,可觸發(fā)下發(fā)通知 ,通過(guò)微信聊天列表中的服務(wù)通知可快捷進(jìn)入查看消息。此外,點(diǎn)擊查看詳情還能跳轉(zhuǎn)到下發(fā)消息的小程序的指定頁(yè)面。但是為了避免這種通知被濫用,帶來(lái)不好的用戶體驗(yàn),小程序也對(duì)模板消息推送做了相應(yīng)的限制。為了更好的優(yōu)化小打卡小程序的打卡通知功能,我在開(kāi)發(fā)的過(guò)程中自行摸索了一套突破推送限制的解決方案??梢詫?shí)現(xiàn) 7天內(nèi)向用戶推送多條模板消息,甚至向用戶群發(fā)消息的功能 。

注意:請(qǐng)務(wù)必在嚴(yán)格遵守小程序運(yùn)營(yíng)規(guī)范的前提下使用本方案。

消息通知有什么作用?

消息通知是一個(gè)很重要的功能,如QQ空間的回復(fù)狀態(tài)通知,QQ郵箱的郵件通知,微信支付成功提通知等。這種常規(guī)的 服務(wù)跟蹤類(lèi) 消息,便于用戶掌握產(chǎn)品對(duì)自身服務(wù)的進(jìn)度,方便客戶獲取必要的信息,提高效率;保證用戶的知情權(quán),讓用戶有安全感。同時(shí),對(duì)于產(chǎn)品本身來(lái)說(shuō),可以引導(dǎo)用戶進(jìn)行下一步行為, 增加了產(chǎn)品的曝光率,便于用戶留存,增強(qiáng)用戶粘性。

模板消息長(zhǎng)什么樣子?

服務(wù)通知及模板消息

如上圖,呈現(xiàn)在微信聊天列表的 服務(wù)通知 ,收納了各個(gè)小程序向用戶推送模板消息,這個(gè)服務(wù)通知是用戶查看模板消息的入口,用戶點(diǎn)擊服務(wù)通知后可以查看到通知列表頁(yè)面,每條通知以卡片的形式呈現(xiàn),包括小程序的logo、名稱(chēng)、通知時(shí)間、通知內(nèi)容等信息。

模板消息是什么?

所謂『模板消息』,就如上面的通知卡片,首先通知卡片形式樣子是固定的,其實(shí)卡片中的通知內(nèi)容部分,可以看到每天通知的內(nèi)容都具備日程描述、日程主題、日程時(shí)間等要素,通知之間不同的地方在于這些要素后面的文案,將這些通知要素制作成模板,每次針對(duì)不同的通知內(nèi)容 只需要填充每條要素對(duì)應(yīng)的具體的文本 即可推送給用戶。上面圖中兩條模板消息的日程主題和時(shí)間不一樣,其他的信息要素保持一致,這就是模板消息。

使用模板消息有哪些好處?

提到模板消息的好處,第一印象是 "多、快、好、省" 的特點(diǎn)。

"快"即快捷,體現(xiàn)在微信用戶側(cè)的通知體驗(yàn),由于在微信客戶端服務(wù)通知在聊天列表中,保留了用戶以往處理聊天通知的習(xí)慣,所以用戶可以很 便捷地觸及服務(wù)通知 ,查看小程序推送的模板消息。

"好"即效果好,小程序的模板消息具備 跳轉(zhuǎn)直達(dá)小程序特定頁(yè)面 的能力,這樣用戶接收消息后,查看消息的通知就能便捷地回到小程序進(jìn)行相應(yīng)的業(yè)務(wù)處理、信息查看等后續(xù)操作,一定程度上提升了用戶的活躍度,小打卡小程序的近30天訪問(wèn)來(lái)源數(shù)據(jù)顯示,有20%左右的用戶通過(guò)模板消息這個(gè)入口進(jìn)入小打卡,在各種來(lái)源中排名第三位,可以見(jiàn)模板消息是用戶使用你的小程序的重要入口。

"省"即省錢(qián)唄,有了模板推送,自然 降低了消息通知的成本 ,節(jié)省費(fèi)用。消息通知優(yōu)先通過(guò)模板消息這種方式來(lái)推送給指定用戶,只有才無(wú)法觸及用戶的情況下,才使用傳統(tǒng)的付費(fèi)短信推送等形式。

"多"呢?上面提到"無(wú)法觸及用戶的情況",其實(shí)是因?yàn)樾〕绦虿痪邆?quot;多"的特點(diǎn)。物以稀為貴,模板消息雖好,但是微信小程序官方為了保證用戶體驗(yàn), 平衡通知和騷擾行為 ,對(duì)模板推送做了相應(yīng)限制。接下來(lái)就聊聊這個(gè)限制。

微信對(duì)模板消息有什么樣的限制?

微信小程序允許下發(fā)模板消息的條件分為兩類(lèi), 支付或者提交表單 。

目前支付的限制有所放開(kāi),即1次支付可以下發(fā)3條模板消息。通過(guò)提交表單來(lái)下發(fā)模板消息的方式限制為一次的觸發(fā)行為,7天內(nèi)可以向用戶推送一條模板消息。 這種消息的控制放的太寬的話,很容易對(duì)用戶的體驗(yàn)造成很大沖擊,給用戶帶來(lái)一定的騷擾。

但是,用戶1次觸發(fā)、7天內(nèi)推送1條通知明顯是不夠用的,比如小打卡小程序利用模板消息的推送來(lái)提醒用戶每天打卡,只能在用戶前一天打卡的情況下,獲取一次推送模板消息的機(jī)會(huì),然后用于第二天向用戶發(fā)送打卡通知。但是很多情況下,用戶如果某一天忘記打卡,小打卡便 失去了提醒用戶的權(quán)限,和用戶斷開(kāi)了聯(lián)系 。

在小打卡中還有一個(gè)迫切需要多條模板消息推送的場(chǎng)景,比如打卡活動(dòng)每次有新的成員進(jìn)入,需要通知管理員進(jìn)行審核,這種情況也需要及時(shí)地通知管理員,以便管理員快速響應(yīng),處理成員的審核請(qǐng)求并通知成員審核結(jié)果。

注意到下發(fā)條件中,每次觸發(fā)的到的 推送碼可以在未來(lái)7天內(nèi)使用,多次提交觸發(fā)下發(fā)的消息條數(shù)獨(dú)立,相互不影響 ,那能不能突破模板消息的發(fā)送限制,更好地優(yōu)化打卡提醒功能呢?

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

微信小程序官方最近已經(jīng)透露出可能對(duì)模板消息進(jìn)一步放寬限制的信號(hào),不過(guò)在這之前,我們可以在遵守官方相關(guān)運(yùn)營(yíng)規(guī)范、保證用戶體驗(yàn)的情況下,倒騰一個(gè) "讓用戶一次觸發(fā)、多次推送,甚至群發(fā)模板消息" 的解決方案。

其實(shí)仔細(xì)分析消息下發(fā)條件"1次提交表單可下發(fā)1條,多次提交下發(fā)條數(shù)獨(dú)立,相互不影響",突破口就明顯了,只需 收集到足夠推送碼 ,即每次提交表單時(shí)獲取到的formId就是我們所需的“推送權(quán)限”。它是一次性的,代表著開(kāi)發(fā)者有向當(dāng)前用戶推送模板消息的權(quán)限。

為了打造這樣一個(gè)突破限制的模版消息推送功能,做到7天內(nèi)任性推送,我們將小程序前后端的工作明確一下,小程序前端,即運(yùn)行在用戶微信上的小程序負(fù)責(zé) 收集推送碼 ,小程序后端,即運(yùn)行在服務(wù)器上的應(yīng)用程序負(fù)責(zé)將推送碼 存儲(chǔ)到數(shù)據(jù)庫(kù) 中,并在需要推送的模版消息的時(shí)候從中取出推送碼formId判斷有效性并加以運(yùn)用。整個(gè)方案的前后端業(yè)務(wù)流程如下:

                                                                                                               方案前后端流程

接下來(lái)我們?cè)O(shè)計(jì)一個(gè)能夠突破當(dāng)前模板消息推送限制的方案。結(jié)合 小程序前端界面、小程序邏輯層、服務(wù)器程序、數(shù)據(jù)庫(kù)、異步任務(wù)系統(tǒng) 各自分工,來(lái)實(shí)現(xiàn)將小程序模板消息推送所需的推送碼收集、上報(bào)、存儲(chǔ)、調(diào)用。最終做到7日內(nèi)更好地推送模板消息、觸及用戶。

一.前端頁(yè)面如何盡可能多地收集推送碼?

每次表單提交可以觸發(fā)一次下發(fā)模版消息的機(jī)會(huì),表單組件

 
如下:

 

Page({
  formSubmit: function(e) {
    let formId = event.detail.formId;
    console.log('form發(fā)生了submit事件,推送碼為:', formId)
  }
})
組件中屬性report-submit為true時(shí),代表需要請(qǐng)求發(fā)模板消息的推送碼,此時(shí)點(diǎn)擊按鈕提交表單可以獲取formId,用于發(fā)送模板消息。接下來(lái)只需要對(duì)原來(lái)的頁(yè)面進(jìn)行改造,將用戶原來(lái)綁定了點(diǎn)擊事件的界面用表單組件中的button按鈕組件來(lái)代替,也就是 把用戶的交互點(diǎn)擊的bindtap事件通過(guò)表單bindsubmit來(lái)取代 ,從而捕獲用戶的點(diǎn)擊事件來(lái)產(chǎn)生更多的推送碼formId,這里還需要對(duì)按鈕組件的樣式進(jìn)行稍微的修改,以便更好地包裹原來(lái)界面的代碼。
/*wxss*/
/*修改按鈕樣式,使其能夠包裹其他組件*/
.btn {
  border:none;
  text-align:left;
  padding:0;
  margin:0;
  line-height:1.5;
}
//js
Page({
  formSubmit: function(e) {
    let formId = e.detail.formId;
    this.dealFormIds(formId); //處理保存推送碼
    let type = e.detail.target.dataset.type;
    //根據(jù)type的值來(lái)執(zhí)行相應(yīng)的點(diǎn)擊事件
    //...
  },
  dealFormIds: function(formId) {
    let formIds = app.globalData.gloabalFomIds;//獲取全局?jǐn)?shù)據(jù)中的推送碼gloabalFomIds數(shù)組
    if (!formIds) formIds = [];
    let data = {
      formId: formId,
      expire: parseInt(new Date().getTime() / 1000)+604800 //計(jì)算7天后的過(guò)期時(shí)間時(shí)間戳
    }
    formIds.push(data);//將data添加到數(shù)組的末尾
    app.globalData.gloabalFomIds = formIds; //保存推送碼并賦值給全局變量
  },
})

上面的代碼主要實(shí)現(xiàn)了模擬表單提交事件來(lái)取代原來(lái)的點(diǎn)擊事件,用戶在點(diǎn)擊界面進(jìn)行交互的同時(shí),能夠獲得多個(gè)推送碼保存app.js的全局變量globalData中,等待用戶下一次發(fā)起網(wǎng)絡(luò)請(qǐng)求時(shí),即可將gloabalFomIds數(shù)組數(shù)據(jù)發(fā)送給服務(wù)器。

小打卡上的點(diǎn)擊區(qū)域

上圖以小打卡的打卡詳情頁(yè)為例,用戶在這個(gè)頁(yè)面的點(diǎn)擊操作可以很快收集到多個(gè)formId,所以將界面上用戶高頻點(diǎn)擊的事件用表單的形式重新封裝后,可以靜默、快速收集到所需的"模板消息推送權(quán)限" 。

二.小程序邏輯層如何傳遞推送碼給服務(wù)器?

Page({
   onLoad:function(){
    this. saveFormIds();
  },
  saveFormIds: function(){
    var formIds = app.globalData.gloabalFomIds; // 獲取gloabalFomIds
    if (formIds.length) {//gloabalFomIds存在的情況下 將數(shù)組轉(zhuǎn)換為JSON字符串
      formIds = JSON.stringify(formIds);
      app.globalData.gloabalFomIds = '';
    }
    wx.request({//通過(guò)網(wǎng)絡(luò)請(qǐng)求發(fā)送openId和formIds到服務(wù)器
      url: 'https://www.x.com', 
      method: 'GET',
      data: {
        openId: 'openId',
        formIds: formIds
      },
      success: function(res) {
      }
    });
  },
})

在小程序的邏輯層中,通過(guò)全局變量gloabalFomIds收集到多個(gè)formId后,可以在新頁(yè)面載入時(shí),在onLoad生命周期函數(shù)中發(fā)送網(wǎng)絡(luò)請(qǐng)求獲取數(shù)據(jù), gloabalFomIds不為空時(shí),把gloabalFomIds數(shù)組格式化為字符串發(fā)送到服務(wù)器,并清空當(dāng)前的gloabalFomIds ,以便繼續(xù)獲取新的formId。

三.后端程序如何保存推送碼formId?

因?yàn)檫@個(gè)保存是一個(gè)高頻IO的操作,我們 后端以PHP結(jié)合高性能的key-value數(shù)據(jù)庫(kù)Redis來(lái)實(shí)現(xiàn)推送碼的存儲(chǔ) 。相關(guān)關(guān)鍵代碼如下,簡(jiǎn)單表達(dá)了思路,針對(duì)不同的后端環(huán)境和開(kāi)發(fā)語(yǔ)言,你可能需要做相應(yīng)的調(diào)整。

//關(guān)鍵代碼
public function saveFormIds(){
    $openId = $_GET['openId'];
    $formIds = $_GET['formIds'];;//獲取formIds數(shù)組
    if($formIds){
        $formIds = json_decode($formIds,TRUE);//JSON解碼為數(shù)組
        $this -> _saveFormIdsArray($openId,$formIds);//保存
    }
}
private function _get($openId){
    $cacheKey = md5('user_formId'.$openId);
    $data = $this->cache->redis->get($cacheKey);//修改為你自己的Redis調(diào)用方式
    if($data)return json_decode($data,TRUE);
    else return FALSE;
}
private function _save($openId,$data){
    $cacheKey = md5('user_formId'.$openId);
    return $this->cache->redis->save($cacheKey,json_encode($data),60*60*24*7);//修改為你自己的Redis調(diào)用方式
}
private function _saveFormIdsArray($openId,$arr){
    $res = $this->_get($openId);
    if($res){
        $new = array_merge($res, $arr);//合并數(shù)組
        return $this->_save($openId,$new);
    }else{
        $result = $arr;
        return $this->_save($openId,$result);
    }
}

這一步主要是構(gòu)建服務(wù)器程序高效存儲(chǔ)用戶的推送碼formId,這下推送機(jī)會(huì)有了,接下來(lái)我們考慮如何 利用后端程序來(lái)想特定用戶發(fā)送模板消息 ,考慮怎樣去合理運(yùn)用推送機(jī)會(huì)。

四.如何實(shí)現(xiàn)高性能的模板消息推送?

構(gòu)建高性能的服務(wù)器端異步任務(wù)推送,可以滿足 模板消息的群發(fā)、以及定時(shí)發(fā)送 的需求,如小打卡就采用了高性能分布式內(nèi)存隊(duì)列系統(tǒng) BEANSTALKD,來(lái)實(shí)現(xiàn)模板消息的異步定時(shí)推送。實(shí)現(xiàn)發(fā)送模板消息的群發(fā)、定時(shí)發(fā)送分為2個(gè)步驟:

  1. 設(shè)置任務(wù)執(zhí)行時(shí)間并將該發(fā)送任務(wù)推送到異步任務(wù)隊(duì)列。
  2. 通過(guò)任務(wù)發(fā)送服務(wù)輪詢(xún)執(zhí)行任務(wù),獲取access_token、指定你需要推送消息的用戶的openId,根據(jù)openId獲取用戶的推送碼formId,并結(jié)合模板id拼裝模板上的通知內(nèi)容,調(diào)用模板消息發(fā)送接口來(lái)異步發(fā)送。

普通的模板消息的發(fā)送就不贅述了,可參考 官方文檔中的模板消息功能 一步步進(jìn)行操作,我們重點(diǎn)來(lái)看高性能異步任務(wù)推送的實(shí)現(xiàn)方法。涉及到的關(guān)鍵代碼如下:

//設(shè)置異步任務(wù)
public function put_task($data,$priority=2,$delay=3,$ttr=60){//任務(wù)數(shù)據(jù)、優(yōu)先級(jí)、時(shí)間定時(shí)、任務(wù)處理時(shí)間
    $pheanstalk = new Pheanstalk('127.0.0.1:11300');
    return $pheanstalk ->useTube('test') ->put($data,$priority,$delay,$ttr);
}
//執(zhí)行異步任務(wù)
public function run() {
    while(1) {
        $job = $this->pheanstalk->watch('test')->ignore('default')->reserve();//監(jiān)聽(tīng)任務(wù)
        $this->send_notice_by_key($job->getData());//執(zhí)行模板消息的發(fā)送
        $this->pheanstalk->delete($job);//刪除任務(wù)
        $memory = memory_get_usage();
        usleep(10);
    }
}
//1.取出一個(gè)可用的用戶openId對(duì)應(yīng)的推送碼
public function getFormId($openId){
    $res = $this->_get($openId);
    if($res){
        if(!count($res)){
            return FALSE;
        }
        $newData = array();
        $result = FALSE;
        for($i = 0;$i < count($res);$i++){
            if($res[$i]['expire'] > time()){
                $result = $res[$i]['formId'];//得到一個(gè)可用的formId
                for($j = $i+1;$j < count($res);$j++){//移除本次使用的formId
                    array_push($newData,$res[$j]);//重新獲取可用formId組成的新數(shù)組
                }
                break;
            }
        }
           $this->_save($openId,$newData);
        return $result;
    }else{
        return FALSE;
    }
}
//2.拼裝模板,創(chuàng)建通知內(nèi)容
private function create_template($openId,$formId,$content){
    $templateData['keyword1']['value'] = '打卡即將開(kāi)始';
    $templateData['keyword1']['color'] = '#d81e06';
    $templateData['keyword2']['value'] = '打卡名稱(chēng)';
    $templateData['keyword2']['color'] = '#1aaba8';
    $templateData['keyword3']['value'] = '05:00';
    $templateData['keyword4']['value'] = '備注說(shuō)明';
    $data['touser'] = $openId;
    $data['template_id'] = '模板id';
    $data['page'] = 'pages/detail/detail?id=1000';//用戶點(diǎn)擊模板消息后的跳轉(zhuǎn)頁(yè)面
    $data['form_id'] = $formId;
    $data['data'] = $templateData;
    return json_encode($data);
}

//3.執(zhí)行模板消息發(fā)布
public function send_notice($key){
    $openId = '用戶openId';
    $formId = $this -> getFormId($openId);//獲取formId
    $access_token = '獲取access_token';
    $content='通知內(nèi)容';//可通過(guò)$key作為鍵來(lái)獲取對(duì)應(yīng)的通知數(shù)據(jù)
    if($access_token){
        $templateData = $this->create_template($openId,$formId,$content);//拼接模板數(shù)據(jù)
        $res = json_decode($this->http_post('https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token='.$access_token,$templateData));
        if($res->errcode == 0){
            return $res;
        }else{
            return false;
        }
    }
}

Beanstalkd是一個(gè) 高性能、輕量級(jí)的分布式內(nèi)存隊(duì)列系統(tǒng) ,我們通過(guò)Beanstalkd將模板消息推送任務(wù)的創(chuàng)建以及任務(wù)的執(zhí)行分開(kāi)進(jìn)行。

在創(chuàng)建推送任務(wù)時(shí), 設(shè)置任務(wù)的執(zhí)行時(shí)間以及定義推送消息的類(lèi)型和通知內(nèi)容等數(shù)據(jù) 。

在任務(wù)執(zhí)行時(shí),通過(guò)Beanstalkd的任務(wù)監(jiān)聽(tīng)函數(shù)來(lái)捕獲任務(wù)。通過(guò)預(yù)先在創(chuàng)建任務(wù)時(shí)標(biāo)記的數(shù)據(jù)來(lái)確定模板消息的具體推送內(nèi)容,比如用戶openId,通過(guò)用戶openId獲取一個(gè)可用的推送碼formId,獲取推送內(nèi)容等,最后在調(diào)用微信小程序模板消息下發(fā)接口完成推送。

getFormId函數(shù)主要實(shí)現(xiàn)每次取出一個(gè)未過(guò)期可用的推送碼formId,并且刪除不可用的邀請(qǐng)碼和當(dāng)前已選中的邀請(qǐng)碼,以保證一定數(shù)額的推送碼formId在未來(lái)一周內(nèi)可用。

關(guān)于Beanstalkd的使用介紹,可用參考一下文章,深入研究。

高性能分布式內(nèi)存隊(duì)列系統(tǒng)beanstalkd(轉(zhuǎn))

beanstalkd消息隊(duì)列使用

最后總結(jié)一下,整個(gè)方案涉及到的關(guān)鍵詞有 表單、按鈕、formId、模板消息、Redis、Beanstalkd 等,涉及了多項(xiàng)技術(shù)的組合,包括 前端開(kāi)發(fā)、后端開(kāi)發(fā)、數(shù)據(jù)庫(kù)技術(shù) 等,且前后端分工明確,共同支撐整個(gè)方案地實(shí)現(xiàn)。

模板消息推送方案

正如我之前文章里所說(shuō)的, 微信小程序開(kāi)發(fā)的難點(diǎn)不在于小程序本身,小程序開(kāi)發(fā)技術(shù)是前后端一系列的技術(shù)的組合,開(kāi)發(fā)者需要持續(xù)學(xué)習(xí),掌握、提升更多的相關(guān)開(kāi)發(fā)技術(shù),來(lái)更好地支撐產(chǎn)品的功能實(shí)現(xiàn) 。最后,這個(gè)方案可以在用戶最后一次使用小程序后的7天內(nèi),對(duì)用戶發(fā)送多條模板消息喚回用戶,但是請(qǐng) 一定要在遵循微信官方的運(yùn)營(yíng)規(guī)范的前提下 ,合理使用這樣的模板消息推送功能。



易優(yōu)小程序(企業(yè)版)+靈活api+前后代碼開(kāi)源 碼云倉(cāng)庫(kù):starfork
本文地址:http://www.szcjxy.com/wxmini/doc/course/18233.html 復(fù)制鏈接 如需定制請(qǐng)聯(lián)系易優(yōu)客服咨詢(xún): 點(diǎn)擊咨詢(xún)
在線客服