參考官方文檔和部分資料,總結小程序模板消息推送以及相關注意事項,樓主踩過的坑,特來與大家分享。
一、開發准備:
1. 在微信公眾平台 - 小程序的模板中心申請消息模板
二、實現原理:
文檔示例:小程序 + 接口(PHP)
小程序部分:
話不多說,先上效果圖:
示例代碼:
<form bindsubmit="formSubmit" report-submit='true' > <view class="btn-area"><button formType="submit">Submit</button></view> </form> formSubmit: function (e) { console.log('form發生了submit事件,formId為:', e.detail) var that = this; wx.request({ url: 'https://api.XXX.com/sendTemplateMessage.api', data: { uid: uid, formId: e.detail.formId }, method: 'post', header: {'content-type': 'application/x-www-form-urlencoded'}, //使用這種方式后台才能實現獲取到數據 success: function (res) { console.log("發送模板:" + res.data) } })
注意事項:
小程序通 submit 點擊事件獲 formid 在安卓和 IOS 是不一樣的,安卓系統中為 13 位時間戳,而 IOS 系統中為 32 位字符串,在做接口請求時,不需要做額外處理。
安卓系統
IOS系統
PHP 接口部分:
1. 根據微信公眾平台 -- 設置 -- 消息推送 -- URL (服務器地址),在 PHP 項目配置入口文件,實現請求分發。
2. 驗證入口文件,傳遞 token 令牌(消息推送的 token),進行 Signature 簽名有效性驗證,完成之后才能進行消息模板的服務器 URL 地址配置。
<?php define('SS_START_TIME', microtime(true)); define('RUN_SS', true); require '../ss/ss.php'; $ss = new ss('xcx'); $ss->execute('xcx', 'valid', 'xcx'); ?> <?php // 小程序驗證入口文件 public function xcx(){ $type = $token; //Token(令牌) if ($this->checkSignature($type) && isset($_GET['echostr'])){ echo $_GET['echostr']; exit(); } } /** * 校驗微信加密簽名 * [[@return](https://learnku.com/users/31554)](https://learnku.com/users/31554) bool */ private function checkSignature($type = ''){ // 微信服務器配置Token $token = $type; // 1.將timestamp,token,nonce按字典序排序 $timestamp = $_GET['timestamp']; $nonce = $_GET['nonce']; $signature = $_GET['signature']; $arr = array($timestamp, $token, $nonce); sort($arr, SORT_STRING); // 2.拼接為字符串並sha1加密 $tmpStr = implode($arr); $tmpStr = sha1($tmpStr); // 3.與signature對比判斷是否來自微信服務器 if ($tmpStr == $signature){ return true; }else{ return false; } } ?>
可在 https://mp.weixin.qq.com/debug/ 調試獲取 access_token
3. 微信公眾平台 - 設置 - 開發設置配置消息推送(需要先將入口文件上傳服務器)
4. 在微信公眾平台獲取相關參數:
AppID (小程序 ID)、AppSecret (小程序密鑰)、Token (令牌)、TemplateId(模板 id)、EncodingAESKey (消息加密密鑰)
4.1 小程序模板接口
/* *小程序模板消息 *@param uid 用戶id *$param template_id 模板id *@param form_id 表單提交場景下formId(只能用一次) *@param emphasis_keyword 消息加密密鑰 */ public function sendTemplateMessage($uid,$form_id,$template_id){ // 檢驗uid合法性 防止非法越界 $nickname = "nickname"; // 用戶昵稱 // 此openid為小程序的openid切勿與微信自動登錄的openid混淆 $xcx_open['openid'] = "用戶openid"; // openid可以通過PHP接口或者小程序獲取 if ($xcx_open['openid']) { $temp_msg = array( 'touser' => "{$xcx_open['openid']}", 'template_id' => "{$template_id}", 'page' => "/pages/index/index", 'form_id' => "{$form_id}", 'data' => array( 'keyword1' => array( 'value' => "{$nickname}", ), 'keyword2' => array( 'value' => date('Y-m-d H:i:s', time()), ), 'keyword3' => array( 'value' => "好友已完成測試,快去看看吧!", ), 'keyword4' => array( 'value' => "你收到1封新信件,快去看看吧~", ), ), 'emphasis_keyword'=> "{$emphasis_keyword}" ); $res = $this->sendXcxTemplateMsg(json_encode($temp_msg)); echo "<pre>";var_dump($res);exit; } }
4.2 發送小程序模板消息
/** * 發送小程序模板消息 * @param $data * [[@return](https://learnku.com/users/31554)](https://learnku.com/users/31554) array */ public function sendXcxTemplateMsg($data,$appid = "",$appsecret = "") { // 具體模板格式參考公眾平台申請的template_id if (!$appid || !$appsecret) { $appid = ''; //小程序id $appsecret = ''; //小程序秘鑰 } $access_token = $this->getXcxAccessToken($appid,$appsecret); $url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token={$access_token}"; return $this->http_request($url, $data); }
請求數據格式如下:
{ "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" }
4.3 獲取 access_token
/** * 獲取微信接口調用憑證 * @param string $appid * @param string $appsecret * [[@return](https://learnku.com/users/31554)](https://learnku.com/users/31554) mixed */ public function getXcxAccessToken($appid = '', $appsecret = '') { if (!$appid || !$appsecret) { $appid = ''; $appsecret = ''; } // 緩存獲取 $cache = &factory::cache(); if (!$cache->get($appid.'xcx_access_token')) { $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}"; $res = $this->http_request($url); // access_token設置到緩存中 $cache->set($appid.'xcx_access_token', $res['access_token'], 7000); return $res['access_token']; } return $cache->get($appid.'xcx_access_token'); }
4.4 CURL 模擬 HTTP 請求(POST)`
/** * curl模擬http請求GET/POST * @param $url * @param null $data * [[@return](https://learnku.com/users/31554)](https://learnku.com/users/31554) array */ public function http_request($url, $data = null) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); // 以文件流形式返回 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); if (!empty($data)) { // POST請求 curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); } $output = curl_exec($ch); curl_close($ch); // 返回數組 return json_decode($output, true); }
傳遞參數:根據定義接口傳遞相關參數,用戶 uid 通過 uid 獲取 openid,此 openid 為小程序的 openid, formId 為表單提交場景下,為 submit 事件帶上的 formId,formid 在安卓和 ios 下的數據格式和長度不一致,而且小程序獲取 formid 只支持真機調試。
接口調試:errcode 的合法值
值 說明
40037 template_id 不正確
41028 form_id 不正確,或者過期
41029 form_id 已被使用
41030 page 不正確
45009 接口調用超過限額(目前默認每個帳號日調用限額為 100 萬)
請求成功:
{ "state": 1, "data": { "errcode": 0, "errmsg": "ok" }, "info": "successful!" }
至此,推送功能完整實現!