django+小程式傳送模板訊息

葉袖清風發表於2019-04-30

在做小程式的時候需要傳送服務訊息提醒,使用到了小程式模板訊息傳送,現記錄下開發過程。

access_token

使用模板訊息需要使用到access_token,access_token的有效期是7200秒(兩小時),在有效期內,可以一直使用,只有當access_token過期時,才需要再次呼叫介面獲取access_token。

獲取access_token介面的呼叫頻率限制為2000次/天,在實際應用中,我們可以將獲取到的access_token儲存起來,然後定期呼叫access_token介面更新它,以保證隨時取出的access_token都是有效的。

access_token的儲存

在本專案中,我是將獲取的token儲存在資料庫中,使用定時任務,每1小時40分鐘更新一次,獲取新的token更新儲存在資料庫中,前端如果需要,後端就通過介面返回給前端使用。

首先新建資料模型,儲存access_token,如下所示:

class AppItem(models.Model):
    Appid = models.CharField(max_length=128, blank=True, null=True, verbose_name='APPID')  #appid 
    expires_in = models.CharField(max_length=128, blank=True, null=True, verbose_name='expires_in')  #過期時間
    Token = models.CharField(max_length=255,  unique=True, blank=True, null=True, verbose_name='token', db_index=True) #access_token 這裡要注意長度,太短儲存會失敗 token官方給出的長度是512個字元空間

    class Meta:
        verbose_name = '小程式token資訊'
        verbose_name_plural = verbose_name
    def __str__(self):
        return self.Appid
複製程式碼

定時任務獲取更新access_token

在django中我使用了django-crontab模組製作定時任務,

安裝django-crontab模組:

pip install django-crontab

配置(settings.py):

INSTALLED_APPS = [
    ...
    'django_crontab',
    ...
]
#設定定時任務
CRONJOBS  = [
    ('40 */1 * * *', 'activity.crontab_task.update_token', '>> /home/taskcrontab/task_crontab.log')
]
# 每小時的40分鐘執行一次
#  分鐘 小時 
複製程式碼

使用django-crontab需要開啟本機的crontab定時任務,否則無法生效。django-crontab具體的設定引數可以檢視文件

新建crontab_task.py定時任務檔案,如下所示

import requests
from activity.models import *
def update_token():
    appid = 'appid'
    secret = 'secret'

    url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s' % (appid, secret)
    dict_data = requests.get(url)
    token = dict_data.json()['access_token']
    expires_in = dict_data.json()['expires_in']
    
    appitem = AppItem.objects.get(id = 1)
    appitem.Token = token
    appitem.expires_in = expires_in
    appitem.save()
複製程式碼
# dajango-crontab任務使用方法
python manage.py crontab add #新增定時任務
python manage.py crontab show # 檢視定時任務
# 修改定時任務需要重新add啟動
複製程式碼
# 啟動成功後,執行python manage.py crontab show命令即可查詢當前系統下的定時任務,顯示如下:
Currently active jobs in crontab:
0ddad8dd56d2ff42252985ff2cc11edd -> ('40 */1 * * *', 'activity.crontab_task.update_token', '>> /home/taskcrontab/task_crontab.log')

#執行後檢視/home/taskcrontab/task_crontab.log日誌可看到執行的日誌
複製程式碼

後端模板傳送

現在我們已經能夠正確獲取access_token,且保證資料庫中的都是正確且有效的token,然後我們據可以參照官方文件,傳送模板資訊了。

1、獲取模板ID

有兩種方式可以獲取模板ID

  • (1)通過模版訊息管理介面獲取模版ID(詳見服務端==>模版訊息模組)
  • (2)在微信公眾平臺手動配置獲取模版ID(我的模板==>點選詳情==>點選複製或手動複製寫入程式碼中)

img

2、呼叫介面下發模板訊息

我使用https方式呼叫,呼叫地址為POST api.weixin.qq.com/cgi-bin/mes…

具體呼叫方法如下:

class Send_Message(APIView):
    permission_classes = (permissions.IsAuthenticated,)
    def post(self, request):
        form_id = request.data.get('form_id')
        to_url = request.data.get('to_url')
        title = request.data.get('title')
        brief = request.data.get('brief')
        begintime = request.data.get('begintime')
        access_token = AppItem.objects.get(id = 1).Token
        url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=" + access_token
        user = request.user #獲取當前使用者
        postData = {
            "touser": user.username,
            "template_id": "template_id",   #此處更換成正式的模板id從模板庫中可以檢視
            "page": to_url,
            "form_id": form_id,
            "data": {
                "keyword1": {
                    "value": title
                },
                "keyword2": {
                    "value": brief
                },
                "keyword3": {
                    "value": begintime
                }
            },
        }
        res = requests.post(url,data=json.dumps(postData))
        res = res.json()
        return DaoJsonResponse(res,'0','success')
複製程式碼

前端獲取formId,併傳送訊息

模板訊息不能根據自己的想法任意傳送,需要使用一個觸發性事件;比如表單提交(獲取formid)、支付(獲取prepay_id),我這邊只需要表單提交即可

1、首先需要對我的

元件進行發模板訊息的宣告,即設定屬性 report-submit="true"

<form bindsubmit='joinActivity' report-submit='true'>
    <view class="acti-join"><button formType="submit">參加</button></view>
</form>
複製程式碼

2、在對應的js檔案中,增加提交程式碼:

joinActivity(e) {
    let formId = e.detail.formId;
    if ('the formId is a mock one' == formId) {
        return;
    }
    this.sendMessage(formId); //傳送資訊
}
複製程式碼

3、調取傳送訊息的介面,傳入具體模板訊息欄位:

/**傳送模板訊息 */
sendMessage(formid) {
    return requestPromise({
        url: API.sendMessage,
        method: 'post',
        header: app.globalData.header,
        data: {
            "form_id": formid,
            "to_url": `pages/detail/detail?activity_id=${this.data.activity_id}`,
            "title": this.data.detailData.title,
            "brief": this.data.detailData.content
        }
    }).then(res => {
        console.log('傳送成功')
    }).catch(error => {
        console.log(error)
    })
},
複製程式碼

在本地的開發工具中,獲取的formId一律是**"the formId is a mock one"**,要想看到具體的訊息,需使用手機測試

總結

模板訊息的傳送官方文件都寫的很清楚,目前做的都是觸發式傳送資訊,拿到formID直接調取介面傳送,後期會考慮將formID暫存,在過期時間內按照需要去調取,傳送需要的訊息。

相關文章