# 消息推送
接入微信小程序消息推送服務,可以兩種方式選擇其一:
# 開發者服務器接收消息推送
開發者需要按照如下步驟完成: 填寫服務器配置
驗證服務器地址的有效性
據接口文檔實現業務邏輯,接收消息和事件
# 第一步:填寫服務器配置
登錄小程序后臺后,在「開發」-「開發設置」-「消息推送」中,管理員掃碼啟用消息服務,填寫服務器地址(URL)、令牌(Token) 和 消息加密密鑰(EncodingAESKey)等信息。 URL: 開發者用來接收微信消息和事件的接口 URL。開發者所填寫的URL 必須以 http:// 或 https:// 開頭,分別支持 80 端口和 443 端口。
Token: 可由開發者可以任意填寫,用作生成簽名(該 Token 會和接口 URL 中包含的 Token 進行比對,從而驗證安全性)。
EncodingAESKey: 由開發者手動填寫或隨機生成,將用作消息體加解密密鑰。
同時,開發者可選擇消息加解密方式:明文模式(默認)、兼容模式和安全模式。可以選擇消息數據格式:XML 格式(默認)或 JSON 格式。
模式的選擇與服務器配置在提交后都會立即生效,請開發者謹慎填寫及選擇。切換加密方式和數據格式需要提前配置好相關代碼,詳情請參考 消息加解密說明。
# 第二步:驗證消息的確來自微信服務器
開發者提交信息后,微信服務器將發送GET請求到填寫的服務器地址URL上,GET請求攜帶參數如下表所示:
參數 描述 signature 微信加密簽名,signature結合了開發者填寫的token參數和請求中的timestamp參數、nonce參數。
timestamp 時間戳
nonce 隨機數
echostr 隨機字符串
開發者通過檢驗 signature 對請求進行校驗(下面有校驗方式)。若確認此次 GET 請求來自微信服務器,請原樣返回 echostr 參數內容,則接入生效,成為開發者成功,否則接入失敗。加密/校驗流程如下: 將token、timestamp、nonce三個參數進行字典序排序
將三個參數字符串拼接成一個字符串進行sha1加密
開發者獲得加密后的字符串可與signature對比,標識該請求來源于微信
驗證URL有效性成功后即接入生效,成為開發者。
檢驗signature的PHP示例代碼:
private function checkSignature()
{
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$token = TOKEN;
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr, SORT_STRING);
$tmpStr = implode( $tmpArr );
$tmpStr = sha1( $tmpStr );
if ($tmpStr == $signature ) {
return true;
} else {
return false;
}
}
PHP示例代碼下載:下載
# 第三步:接收消息和事件
當某些特定的用戶操作引發事件推送時(如用戶向小程序客服發送消息、或者進入會話等情況),微信服務器會將消息(或事件)的數據包以 POST 請求發送到開發者配置的 URL,開發者可以依據自身業務邏輯進行響應。
微信服務器在將用戶的消息發給開發者服務器地址后,微信服務器在五秒內收不到響應會斷掉連接,并且重新發起請求,總共重試三次。如果在調試中,發現用戶無法收到響應的消息,可以檢查是否消息處理超時。關于重試的消息排重,有 msgid 的消息推薦使用 msgid 排重。事件類型消息推薦使用 FromUserName + CreateTime 排重。
服務器收到請求必須做出下述回復,這樣微信服務器才不會對此作任何處理,并且不會發起重試,否則,將出現嚴重的錯誤提示。詳見下面說明: 直接回復success(推薦方式)
直接回復空串(指字節長度為0的空字符串,而不是結構體中content字段的內容為空)
若接口文檔有指定返回內容,應按文檔說明返回
對于客服消息,一旦遇到以下情況,微信會在小程序會話中向用戶下發系統提示“該小程序客服暫時無法提供服務,請稍后再試”: 開發者在5秒內未回復任何內容
開發者回復了異常數據
如果開發者希望增強安全性,可以在開發者中心處開啟消息加密,這樣,用戶發給小程序的消息以及小程序被動回復用戶消息都會繼續加密,詳見消息加解密說明。
# 云函數接收消息推送 需開發者工具版本大于 1.02.1904220,目前需 Nightly Build
開通了云開發的小程序可以使用云函數接收消息推送,目前僅支持客服消息推送。
接入步驟如下: 開發者工具中填寫配置并上傳
云函數中處理消息
# 第一步:開發者工具中填寫配置并上傳
在項目根目錄下新建消息推送配置文件 temp-cloud-callback-config.json 并在填寫完成后右鍵該文件選擇上傳配置。
配置文件格式如下(以客服消息推送配置為例):
{
"enable": true,
"callbacks": [
{
"msgType": 1,
"functionName": "云函數名",
"env": "環境ID"
}
]
}
字段說明: enable: 只有為 true 時云函數消息推送才會啟用,否則所有云函數消息推送都不會生效
callbacks: 接收推送的所有云函數配置
callbacks.msgType: 消息的 msgType,客服消息的 msgType 為 1
callbacks.functionName: 接收消息推送的云函數名稱
callbacks.env: 云函數所在環境
寫好后,右鍵該文件,選擇上傳配置。
# 第二步:云函數中處理消息
云函數被觸發時,其 event 參數即是接口所定義的 JSON 結構的對象(統一 JSON 格式,不支持 XML 格式)。
以客服消息為例,接收到客服消息推送時,event 結構如下:
{
"FromUserName": "ohl4L0Rnhq7vmmbT_DaNQa4ePaz0",
"ToUserName": "wx3d289323f5900f8e",
"Content": "測試",
"CreateTime": 1555684067,
"MsgId": "49d72d67b16d115e7935ac386f2f0fa41535298877_1555684067",
"MsgType": "text"
}
此時可調用客服消息發送接口回復消息,一個簡單的接收到消息后統一回復 “收到” 的示例如下:
// 云函數入口文件
const cloud = require('wx-server-sdk')
cloud.init()
// 云函數入口函數
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
await cloud.openapi.customerServiceMessage.send({
touser: wxContext.OPENID,
msgtype: 'text',
text: {
content: '收到',
},
})
return 'success'
}