最近在用sanic框架寫微信小程序,其中寫了一個微信消息推送,還挺有意思的,寫了個小demo
具體見官方文檔:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/template-message/sendTemplateMessage.html
文檔其實寫的很詳細清除了,包括返回數據的類型,報錯信息
大致流程就是:調用微信小程序的接口,獲取access_token,然后再調用發送模板信息的接口,發送消息
獲取access_token
access_token的有效期目前為2個小時,需定時刷新,重復獲取將導致上次獲取的access_token失效。------>我們后台可以用edis存儲,然后定時任務,2小時失效
獲取access_token調用接口:
#https請求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

#參數說明 #參數 是否必須 說明 grant_type 是 獲取access_token填寫client_credential appid 是 第三方用戶唯一憑證 secret 是 第三方用戶唯一憑證密鑰,即appsecret #返回說明 #正常情況下,微信會返回下述JSON數據包給公眾號: {"access_token":"ACCESS_TOKEN","expires_in":7200} #參數說明 #參數 說明 access_token 獲取到的憑證 expires_in 憑證有效時間,單位:秒 #錯誤時微信會返回錯誤碼等信息,JSON數據包示例如下(該示例為AppID無效錯誤): {"errcode":40013,"errmsg":"invalid appid"} #返回碼說明 #返回碼 說明 -1 系統繁忙,此時請開發者稍候再試 0 請求成功 40001 AppSecret錯誤或者AppSecret不屬於這個公眾號,請開發者確認AppSecret的正確性 40002 請確保grant_type字段值為client_credential 40164 調用接口的IP地址不在白名單中,請在接口IP白名單中進行設置。(小程序及小游戲調用不要求IP地址在白名單內。)
發送模板信息請求地址
POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=ACCESS_TOKEN

#參數 string access_token #接口調用憑證:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183 string touser #接收者(用戶)的 openid string template_id #所需下發的模板消息的id string page #點擊模板卡片后的跳轉頁面,僅限本小程序內的頁面。支持帶參數,(示例index?foo=bar)。該字段不填則模板無跳轉。 string form_id #表單提交場景下,為 submit 事件帶上的 formId;支付場景下,為本次支付的 prepay_id string data #模板內容,不填則下發空模板 string emphasis_keyword #模板需要放大的關鍵詞,不填則默認無放大
接口判斷返回值

#返回值 #Object #返回的 JSON 數據包 #屬性 類型 說明 支持版本 errcode number 錯誤碼 errmsg string 錯誤信息 errcode 的合法值 #值 說明 40037 template_id不正確 41028 form_id不正確,或者過期 41029 form_id已被使用 41030 page不正確 45009 接口調用超過限額(目前默認每個帳號日調用限額為100萬) POST 數據格式:JSON #請求數據示例 { "touser": "OPENID", "template_id": "TEMPLATE_ID", "page": "index", "form_id": "FORMID", "data": { "keyword1": { "value": "339208499" }, "keyword2": { "value": "2015年01月05日 12:30" }, "keyword3": { "value": "騰訊微信總部" } , "keyword4": { "value": "廣州市海珠區新港中路397號" } }, "emphasis_keyword": "keyword1.DATA" } #返回數據示例 { "errcode": 0, "errmsg": "ok", "template_id": "wDYzYZVxobJivW9oMpSCpuvACOfJXQIoKUm0PY397Tc" }
全部代碼展示
這里面有個特別的參數是
string form_id
表單提交場景下,為 submit 事件帶上的 formId;支付場景下,為本次支付的 prepay_id
如果想鑽空子,如果服務端想主動發送模板消息,可以提前手機formId
構建formId 池,每次將用戶提交的表單都搜集起來存入formId池,需要發送通知的時候從中取出即可。
將用戶有可能點擊的區域覆蓋一層不可見的button,並將整個頁面用於傳輸formId的button包裹在一Form標簽內,一旦用戶有點擊按鈕的操作,就將獲取到的formId傳送走。
import requests import json as osjson import configparser from Model.RedisDB import VideoData _cf = configparser.ConfigParser() _cf.read("/septnet/config/ServerConf_V2.conf") # 獲取微信access_token async def get_access_token(): try: payload = { 'grant_type': 'client_credential', 'appid': _cf.get("wechat","APPID"), 'secret': _cf.get("wechat","APPSECRET") } req = requests.get('https://api.weixin.qq.com/cgi-bin/token', params=payload, timeout=3, verify=False) access_token = req.json().get('access_token',"") print('access_token', access_token) return access_token except Exception as e: print(e) # 發送模板消息 def template_push(openid,form_id,date,access_token): data = { "touser": openid, "template_id": _cf.get("wechat","TEMPLATE_ID"), "form_id": form_id, 'page': 'pages/selectDetail/selectDetail?chooseSubjectTaskId=5b8de9ac705deb7cfa927abc', "data": { 'keyword1': { 'value': date }, 'keyword2': { 'value': '收到消息請盡快進入小程序中接收視頻邀請,在2分鍾內如未進行操作,視頻無法成功接通,需對方再次重新發起視頻邀請' } }, "emphasis_keyword": '' } push_url = 'https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token={}'.format(access_token) result = requests.post(push_url, json=data, timeout=3, verify=False) return result # 發送視頻通話模板消息 async def sendTemplateMessage(key,openid, form_id, date): req=await VideoData.get(key) if not req: access_token=get_access_token() if not access_token: return False try: req_push=template_push(openid, form_id, date, access_token) req_redis = await VideoData.set(key,access_token,ex=2*60*60) if not req_redis: return False errcode = req_push.json().get("errcode") if errcode==0: return True return False except Exception as e: print(e) access_token = osjson.loads(req) template_push(openid, form_id, date, access_token) return True