微信公眾平臺開發(fā)入門教程(SAE方倍工作室)
我們將使用微信公眾賬號方倍工作室作為講解的例子,二維碼見底部。
本系列教程將引導(dǎo)你完成如下任務(wù):
創(chuàng)建新浪云計算平臺應(yīng)用啟用微信公眾平臺開發(fā)模式基礎(chǔ)接口消息及事件微信公眾平臺PHP SDK微信公眾平臺開發(fā)模式原理開發(fā)天氣預(yù)報功能
第一章 申請服務(wù)器資源
創(chuàng)建新浪云計算應(yīng)用
申請賬號
我們使用SAE新浪云計算平臺作為服務(wù)器資源,并且申請PHP環(huán)境+MySQL數(shù)據(jù)庫作為程序運行環(huán)境。
申請地址:http://sae.sina.com.cn/ ,使用新浪微博賬號可以直接登錄SAE,登錄后SAE將贈送500個免費云豆。
創(chuàng)建新應(yīng)用
登錄后點擊頂部【我的首頁】
點擊下側(cè)的創(chuàng)建新應(yīng)用,這時會彈出提示, 禁止放置違法違規(guī)內(nèi)容,點擊繼續(xù)創(chuàng)建,彈出如下窗口。
選擇一個未使用的appid,如果老是已經(jīng)被使用不知道該什么好,就填寫你的QQ號或者手機號吧。
填寫二級域名AppID、應(yīng)用名稱、驗證碼,開發(fā)語言選擇PHP,應(yīng)用類型選擇web應(yīng)用。然后點擊創(chuàng)建應(yīng)用
應(yīng)用創(chuàng)建成功。并自動跳轉(zhuǎn)到應(yīng)用列表中,可以看到已經(jīng)有剛才創(chuàng)建的CCTV-7
創(chuàng)建版本
選擇CCTV-7右側(cè)的應(yīng)用管理下面的代碼管理,
跳轉(zhuǎn)到代碼管理
點擊右側(cè)的
版本號默認為1,點擊創(chuàng)建,成功后如下圖所示:
到這里,就成功創(chuàng)建了一個域名URL為 http://cctv7.sinaapp.com/ 的應(yīng)用了。
上傳代碼
將以下代碼復(fù)制下來,另存為index.php。必須使用專業(yè)的開發(fā)編輯軟件操作,例如Notepad++,不要使用Windows自帶的記事本等。
<?php
/*
方倍工作室 http://www.cnblogs.com/txw1958/
CopyRight 2013 www.doucube.com All Rights Reserved
*/
define("TOKEN", "weixin");
$wechatObj = new wechatCallbackapiTest();
if (isset($_GET['echostr'])) {
$wechatObj->valid();
}else{
$wechatObj->responseMsg();
}
class wechatCallbackapiTest
{
public function valid()
{
$echoStr = $_GET["echostr"];
if($this->checkSignature()){
echo $echoStr;
exit;
}
}
private function checkSignature()
{
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$token = TOKEN;
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr);
$tmpStr = implode( $tmpArr );
$tmpStr = sha1( $tmpStr );
if( $tmpStr == $signature ){
return true;
}else{
return false;
}
}
public function responseMsg()
{
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
if (!empty($postStr)){
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$fromUsername = $postObj->FromUserName;
$toUsername = $postObj->ToUserName;
$keyword = trim($postObj->Content);
$time = time();
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>
</xml>";
if($keyword == "?" || $keyword == "?")
{
$msgType = "text";
$contentStr = date("Y-m-d H:i:s",time());
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}
}else{
echo "";
exit;
}
}
}
?>
然后將index.php文件壓縮成ZIP格式,注意不能用RAR格式
這樣會生成一個index.zip的文件。或者直接下載方倍已經(jīng)壓縮好的zip文件 點此下載
在代碼管理界面中,選擇操作按鈕。
選擇上傳代碼包。
點擊上傳文件,選擇剛才壓縮好的index.zip文件,點擊上傳,上傳成功后如下所示,如果上傳有問題,請在Chrome瀏覽器下重試一下。
點擊操作按鈕下的代碼編輯,
我們可以看到index.php已經(jīng)上傳成功,雙擊可以查看編輯里面的代碼
新浪云應(yīng)用的創(chuàng)建就成功了。
第二章 啟用開發(fā)模式
微信公眾平臺開發(fā)模式
高級功能
微信公眾平臺地址:https://mp.weixin.qq.com
登錄微信公眾平臺后臺,選擇高級功能,進入后就看到兩種模式
我們需要先關(guān)閉編輯模式。點擊編輯模式的進入
滑動關(guān)閉
開發(fā)模式
進入開發(fā)模式里面
點擊成為開發(fā)者
彈出URL和Token填寫框
此處的URL為上篇中介紹的云應(yīng)用的域名,而Token在index.php中定義為weixin。提交后提示你已成為開發(fā)者。
再滑動右上角啟用按鈕。
恭喜,你成功啟用開發(fā)模式。
自動回復(fù)
在上面的例子中,實現(xiàn)了一個發(fā)送“?”就能回復(fù)當(dāng)前時間的功能。
效果如下:
至此,你的微信公眾平臺賬號已經(jīng)實現(xiàn)自動回復(fù)了。
第三章 基礎(chǔ)接口消息及事件
所有賬號在申請之后,都將獲得基礎(chǔ)接口的權(quán)限,基礎(chǔ)接口中將包括接收用戶消息,向用戶回復(fù)消息,接受事件推送等三種服務(wù)。
接收用戶消息
目前普通用戶能向公眾賬號推送五種格式的消息:文本(包括表情)、語音、圖片、視頻、位置、鏈接。
下面就這五種分別詳解如下:
1. 文本(包括表情)
發(fā)送文本及表情
2. 圖片
發(fā)送圖片
3. 語音
發(fā)送語音
4. 視頻
發(fā)送視頻
5. 位置
發(fā)送位置
6. 鏈接
發(fā)送鏈接
向用戶回復(fù)消息
目前普通公眾賬號能向用戶推送六種格式的消息:文本、圖文、音樂、圖片、語音、視頻。其中圖文消息包括單條圖文消息和多條圖文消息,展示方式有一點點不同。
下面就這幾種分別詳解如下:【圖片、語音、視頻由于需要用到和高級接口相關(guān)的media_id,在本教程中暫不討論?!?/P>
1. 文本消息格式
回復(fù)文本
2. 圖文消息格式
2.1 單條圖文消息
回復(fù)單條圖文
2.2 多圖文消息
回復(fù)多圖文
3. 音樂消息
回復(fù)音樂消息
接收事件推送
目前用戶在關(guān)注和取消關(guān)注,以及點擊菜單的時候會自動向公眾平臺發(fā)送事件推送消息:
1. 關(guān)注事件
第四章 微信公眾平臺PHP SDK
方倍工作室開發(fā)了微信公眾平臺的PHPSDK,集成了目前所有消息及事件的接收及發(fā)送,代碼如下:
<?php
/*
方倍工作室
http://www.cnblogs.com/txw1958/
CopyRight 2014 All Rights Reserved
*/
define("TOKEN", "weixin");
$wechatObj = new wechatCallbackapiTest();
if (!isset($_GET['echostr'])) {
$wechatObj->responseMsg();
}else{
$wechatObj->valid();
}
class wechatCallbackapiTest
{
//驗證消息
public function valid()
{
$echoStr = $_GET["echostr"];
if($this->checkSignature()){
echo $echoStr;
exit;
}
}
//檢查簽名
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;
}
}
//響應(yīng)消息
public function responseMsg()
{
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
if (!empty($postStr)){
$this->logger("R ".$postStr);
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$RX_TYPE = trim($postObj->MsgType);
switch ($RX_TYPE)
{
case "event":
$result = $this->receiveEvent($postObj);
break;
case "text":
$result = $this->receiveText($postObj);
break;
case "image":
$result = $this->receiveImage($postObj);
break;
case "location":
$result = $this->receiveLocation($postObj);
break;
case "voice":
$result = $this->receiveVoice($postObj);
break;
case "video":
$result = $this->receiveVideo($postObj);
break;
case "link":
$result = $this->receiveLink($postObj);
break;
default:
$result = "unknown msg type: ".$RX_TYPE;
break;
}
$this->logger("T ".$result);
echo $result;
}else {
echo "";
exit;
}
}
//接收事件消息
private function receiveEvent($object)
{
$content = "";
switch ($object->Event)
{
case "subscribe":
$content = "歡迎關(guān)注方倍工作室 ";
$content .= (!empty($object->EventKey))?("\n來自二維碼場景 ".str_replace("qrscene_","",$object->EventKey)):"";
break;
case "unsubscribe":
$content = "取消關(guān)注";
break;
case "SCAN":
$content = "掃描場景 ".$object->EventKey;
break;
case "CLICK":
switch ($object->EventKey)
{
case "COMPANY":
$content = "方倍工作室提供互聯(lián)網(wǎng)相關(guān)產(chǎn)品與服務(wù)。";
break;
default:
$content = "點擊菜單:".$object->EventKey;
break;
}
break;
case "LOCATION":
$content = "上傳位置:緯度 ".$object->Latitude.";經(jīng)度 ".$object->Longitude;
break;
case "VIEW":
$content = "跳轉(zhuǎn)鏈接 ".$object->EventKey;
break;
default:
$content = "receive a new event: ".$object->Event;
break;
}
$result = $this->transmitText($object, $content);
return $result;
}
//接收文本消息
private function receiveText($object)
{
switch ($object->Content)
{
case "文本":
$content = "這是個文本消息";
break;
case "圖文":
case "單圖文":
$content = array();
$content[] = array("Title"=>"單圖文標(biāo)題", "Description"=>"單圖文內(nèi)容", "PicUrl"=>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
break;
case "多圖文":
$content = array();
$content[] = array("Title"=>"多圖文1標(biāo)題", "Description"=>"", "PicUrl"=>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
$content[] = array("Title"=>"多圖文2標(biāo)題", "Description"=>"", "PicUrl"=>"http://d.hiphotos.bdimg.com/wisegame/pic/item/f3529822720e0cf3ac9f1ada0846f21fbe09aaa3.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
$content[] = array("Title"=>"多圖文3標(biāo)題", "Description"=>"", "PicUrl"=>"http://g.hiphotos.bdimg.com/wisegame/pic/item/18cb0a46f21fbe090d338acc6a600c338644adfd.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
break;
case "音樂":
$content = array("Title"=>"最炫民族風(fēng)", "Description"=>"歌手:鳳凰傳奇", "MusicUrl"=>"http://121.199.4.61/music/zxmzf.mp3", "HQMusicUrl"=>"http://121.199.4.61/music/zxmzf.mp3");
break;
default:
$content = date("Y-m-d H:i:s",time());
break;
}
if(is_array($content)){
if (isset($content[0]['PicUrl'])){
$result = $this->transmitNews($object, $content);
}else if (isset($content['MusicUrl'])){
$result = $this->transmitMusic($object, $content);
}
}else{
$result = $this->transmitText($object, $content);
}
return $result;
}
//接收圖片消息
private function receiveImage($object)
{
$content = array("MediaId"=>$object->MediaId);
$result = $this->transmitImage($object, $content);
return $result;
}
//接收位置消息
private function receiveLocation($object)
{
$content = "你發(fā)送的是位置,緯度為:".$object->Location_X.";經(jīng)度為:".$object->Location_Y.";縮放級別為:".$object->Scale.";位置為:".$object->Label;
$result = $this->transmitText($object, $content);
return $result;
}
//接收語音消息
private function receiveVoice($object)
{
if (isset($object->Recognition) && !empty($object->Recognition)){
$content = "你剛才說的是:".$object->Recognition;
$result = $this->transmitText($object, $content);
}else{
$content = array("MediaId"=>$object->MediaId);
$result = $this->transmitVoice($object, $content);
}
return $result;
}
//接收視頻消息
private function receiveVideo($object)
{
$content = array("MediaId"=>$object->MediaId, "ThumbMediaId"=>$object->ThumbMediaId, "Title"=>"", "Description"=>"");
$result = $this->transmitVideo($object, $content);
return $result;
}
//接收鏈接消息
private function receiveLink($object)
{
$content = "你發(fā)送的是鏈接,標(biāo)題為:".$object->Title.";內(nèi)容為:".$object->Description.";鏈接地址為:".$object->Url;
$result = $this->transmitText($object, $content);
return $result;
}
//回復(fù)文本消息
private function transmitText($object, $content)
{
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
$result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content);
return $result;
}
//回復(fù)圖片消息
private function transmitImage($object, $imageArray)
{
$itemTpl = "<Image>
<MediaId><![CDATA[%s]]></MediaId>
</Image>";
$item_str = sprintf($itemTpl, $imageArray['MediaId']);
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
$item_str
</xml>";
$result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
return $result;
}
//回復(fù)語音消息
private function transmitVoice($object, $voiceArray)
{
$itemTpl = "<Voice>
<MediaId><![CDATA[%s]]></MediaId>
</Voice>";
$item_str = sprintf($itemTpl, $voiceArray['MediaId']);
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
$item_str
</xml>";
$result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
return $result;
}
//回復(fù)視頻消息
private function transmitVideo($object, $videoArray)
{
$itemTpl = "<Video>
<MediaId><![CDATA[%s]]></MediaId>
<ThumbMediaId><![CDATA[%s]]></ThumbMediaId>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
</Video>";
$item_str = sprintf($itemTpl, $videoArray['MediaId'], $videoArray['ThumbMediaId'], $videoArray['Title'], $videoArray['Description']);
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[video]]></MsgType>
$item_str
</xml>";
$result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
return $result;
}
//回復(fù)圖文消息
private function transmitNews($object, $newsArray)
{
if(!is_array($newsArray)){
return;
}
$itemTpl = " <item>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<PicUrl><![CDATA[%s]]></PicUrl>
<Url><![CDATA[%s]]></Url>
</item>
";
$item_str = "";
foreach ($newsArray as $item){
$item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
}
$newsTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<Content><![CDATA[]]></Content>
<ArticleCount>%s</ArticleCount>
<Articles>
$item_str</Articles>
</xml>";
$result = sprintf($newsTpl, $object->FromUserName, $object->ToUserName, time(), count($newsArray));
return $result;
}
//回復(fù)音樂消息
private function transmitMusic($object, $musicArray)
{
$itemTpl = "<Music>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<MusicUrl><![CDATA[%s]]></MusicUrl>
<HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
</Music>";
$item_str = sprintf($itemTpl, $musicArray['Title'], $musicArray['Description'], $musicArray['MusicUrl'], $musicArray['HQMusicUrl']);
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[music]]></MsgType>
$item_str
</xml>";
$result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
return $result;
}
//日志記錄
private function logger($log_content)
{
if(isset($_SERVER['HTTP_APPNAME'])){ //SAE
sae_set_display_errors(false);
sae_debug($log_content);
sae_set_display_errors(true);
}else if($_SERVER['REMOTE_ADDR'] != "127.0.0.1"){ //LOCAL
$max_size = 10000;
$log_filename = "log.xml";
if(file_exists($log_filename) and (abs(filesize($log_filename)) > $max_size)){unlink($log_filename);}
file_put_contents($log_filename, date('H:i:s')." ".$log_content."\r\n", FILE_APPEND);
}
}
}
?>
使用第一章同樣方法,將上述代碼另存為index.php,壓縮成index.zip,或者直接點擊下載,上傳到SAE,你的公眾賬號就能接收及回復(fù)所有消息類型及事件通知了。
在公眾賬號中回復(fù)以下文字,你將得到和上一章一樣的回復(fù)內(nèi)容。
文本
圖文
多圖文
音樂
時間
還可以嘗試以下操作,體驗一下其他消息
發(fā)送一張圖片給公眾賬號
發(fā)送一段語音給公眾賬號
發(fā)送一段視頻給公眾賬號
發(fā)送位置信息給公眾賬號
發(fā)送收藏中的鏈接給公眾賬號第五章 微信公眾平臺開發(fā)模式原理分析
在體驗了上一節(jié)的各種功能之后,我們只是知其然,這一節(jié)里面,將介紹在上面的基礎(chǔ)上介紹微信公眾平臺收發(fā)消息機制及原理,這是知其所以然。
開發(fā)模式成為開發(fā)者時的消息校驗原理
在開發(fā)者首次提交驗證申請時,微信服務(wù)器將發(fā)送GET請求到填寫的URL上,并且?guī)纤膫€參數(shù)(signature、timestamp、nonce、echostr),開發(fā)者通過對簽名(即signature)的效驗,來判斷此條消息的真實性。
此后,每次開發(fā)者接收用戶消息的時候,微信也都會帶上前面三個參數(shù)(signature、timestamp、nonce)訪問開發(fā)者設(shè)置的URL,開發(fā)者依然通過對簽名的效驗判斷此條消息的真實性。效驗方式與首次提交驗證申請一致。
參數(shù) | 描述 |
---|---|
signature | 微信加密簽名,signature結(jié)合了開發(fā)者填寫的token參數(shù)和請求中的timestamp參數(shù)、nonce參數(shù)。 |
timestamp | 時間戳 |
nonce | 隨機數(shù) |
echostr | 隨機字符串 |
開發(fā)者通過檢驗signature對請求進行校驗(下面有校驗方式)。若確認此次GET請求來自微信服務(wù)器,請原樣返回echostr參數(shù)內(nèi)容,則接入生效,成為開發(fā)者成功,否則接入失敗。
加密/校驗流程如下:
1. 將token、timestamp、nonce三個參數(shù)進行字典序排序
2. 將三個參數(shù)字符串拼接成一個字符串進行sha1加密
3. 開發(fā)者獲得加密后的字符串可與signature對比,標(biāo)識該請求來源于微信啟用接口是由代碼中的checkSignature()函數(shù)來實現(xiàn)校驗的。如果對這一原理難以理解,可以暫時不用深究,繼續(xù)看下面。
成為開發(fā)者后消息收發(fā)時的原理
再來看下這個圖,當(dāng)用戶發(fā)送一個“?”時,系統(tǒng)回復(fù)了一個時間
這一原理的消息流程圖如下所示。
從上圖可以看出,用戶在發(fā)送一個?后,微信服務(wù)器將組裝一個消息發(fā)送給我們自己的服務(wù)器,自己的服務(wù)器然后回復(fù)一個時間,并且將該時間也按一定的規(guī)則組裝,回復(fù)給公眾賬號,公眾賬號再回復(fù)給用戶,在這個收發(fā)過程中,發(fā)送方和接收方進行了調(diào)換(ToUserName和FromUserName值互換),收發(fā)都是以xml格式在后臺進行傳輸?shù)模?/P>
所以掌握各種消息類型的收發(fā)就是進行微信公眾平臺開發(fā)的基礎(chǔ)!
下面對前面所述的各種消息類型講解其XML數(shù)據(jù)包的格式。
各種收發(fā)消息的XML數(shù)據(jù)包分析
接收消息
1. 文本(包括表情)
發(fā)送文本及表情
文字后臺格式:
<xml>
<ToUserName><![CDATA[gh_680bdefc8c5d]]></ToUserName>
<FromUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></FromUserName>
<CreateTime>1359028446</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[測試文字]]></Content>
<MsgId>5836982729904121631</MsgId>
</xml>
表情后臺格式
<xml><ToUserName><![CDATA[gh_680bdefc8c5d]]></ToUserName>
<FromUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></FromUserName>
<CreateTime>1359044526</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[/::)/::~/::B/::|/:8-)]]></Content>
<MsgId>5837051792978241864</MsgId>
</xml>
XML格式講解
ToUserName 消息接收方微信號,一般為公眾平臺賬號微信號
FromUserName 消息發(fā)送方微信號
CreateTime 消息創(chuàng)建時間
MsgType 消息類型;文本消息為text
Content 消息內(nèi)容
MsgId 消息ID號
可以看出,文本和表情的消息類型均為文本
2. 圖片
發(fā)送圖片
后臺格式:
<xml><ToUserName><![CDATA[gh_680bdefc8c5d]]></ToUserName>
<FromUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></FromUserName>
<CreateTime>1359028479</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<PicUrl><![CDATA[http://mmbiz.qpic.cn/mmbiz/L4qjYtOibummHn90t1mnaibYiaR8ljyicF3MW7XX3BLp1qZgUb7CtZ0DxqYFI4uAQH1FWs3hUicpibjF0pOqLEQyDMlg/0]]></PicUrl>
<MsgId>5836982871638042400</MsgId>
<MediaId><![CDATA[PGKsO3LAgbVTsFYO7FGu51KUYa07D0C_Nozz2fn1z6VYtHOsF59PTFl0vagGxkVH]]></MediaId>
</xml>
XML格式講解
ToUserName 消息接收方微信號,一般為公眾平臺賬號微信號
FromUserName 消息發(fā)送方微信號
CreateTime 消息創(chuàng)建時間
MsgType 消息類型;圖片消息為image
PicUrl 圖片鏈接地址,可以用HTTP GET獲取
MsgId 消息ID號
3. 語音
發(fā)送語音
后臺格式:
<xml><ToUserName><![CDATA[gh_680bdefc8c5d]]></ToUserName>
<FromUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></FromUserName>
<CreateTime>1359028479</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<PicUrl><![CDATA[http://mmbiz.qpic.cn/mmbiz/L4qjYtOibummHn90t1mnaibYiaR8ljyicF3MW7XX3BLp1qZgUb7CtZ0DxqYFI4uAQH1FWs3hUicpibjF0pOqLEQyDMlg/0]]></PicUrl>
<MsgId>5836982871638042400</MsgId>
<MediaId><![CDATA[PGKsO3LAgbVTsFYO7FGu51KUYa07D0C_Nozz2fn1z6VYtHOsF59PTFl0vagGxkVH]]></MediaId>
</xml>
XML格式講解
ToUserName 消息接收方微信號,一般為公眾平臺賬號微信號
FromUserName 消息發(fā)送方微信號
CreateTime 消息創(chuàng)建時間
MsgType 消息類型;語音消息為voice
MediaId 媒體ID
Format 語音格式,這里為amr
MsgId 消息ID號
附:AMR接口簡介
全稱Adaptive Multi-Rate,主要用于移動設(shè)備的音頻,壓縮比比較大,但相對其他的壓縮格式質(zhì)量比較差,由于多用于人聲,通話,效果還是很不錯的。
4. 視頻
發(fā)送視頻
后臺格式:
xml><ToUserName><![CDATA[gh_680bdefc8c5d]]></ToUserName>
<FromUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></FromUserName>
<CreateTime>1359028186</CreateTime>
<MsgType><![CDATA[video]]></MsgType>
<MediaId><![CDATA[DBVFRIj29LB2hxuYpc0R6VLyxwgyCHZPbRj_IIs6YaGhutyXUKtFSDcSCPeoqUYr]]></MediaId>
<ThumbMediaId><![CDATA[mxUJ5gcCeesJwx2T9qsk62YzIclCP_HnRdfTQcojlPeT2G9Q3d22UkSLyBFLZ01J]]></ThumbMediaId>
<MsgId>5836981613212624665</MsgId>
</xml>
XML格式講解
ToUserName 消息接收方微信號,一般為公眾平臺賬號微信號
FromUserName 消息發(fā)送方微信號
CreateTime 消息創(chuàng)建時間
MsgType 消息類型;視頻消息為video
MediaId 媒體ID
ThumbMediaId 媒體縮略ID?
MsgId 消息ID號
5. 位置
發(fā)送位置
后臺格式:
<xml>
<ToUserName><![CDATA[gh_680bdefc8c5d]]></ToUserName>
<FromUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></FLACFromUserName>
<CreateTime>1359036619</CreateTime>
<MsgType><![CDATA[location]]></MsgType>
<Location_X>22.539968</Location_X>
<Location_Y>113.954980</Location_Y>
<Scale>16</Scale>
<Label><![CDATA[中國廣東省深圳市南山區(qū)華僑城深南大道9789號 郵政編碼: 518057]]></Label>
<MsgId>5837017832671832047</MsgId>
</xml>
XML格式講解
ToUserName 消息接收方微信號,一般為公眾平臺賬號微信號
FromUserName 消息發(fā)送方微信號
CreateTime 消息創(chuàng)建時間
MsgType 消息類型,地理位置為location
Location_X 地理位置緯度
Location_Y 地理位置經(jīng)度
Scale 地圖縮放大小
Label 地理位置信息
MsgId 消息ID號
6. 鏈接
發(fā)送鏈接
后臺格式:
<xml>
<ToUserName><![CDATA[gh_680bdefc8c5d]]></ToUserName>
<FromUserName><![CDATA[oIDrpjl2LYdfTAM-oxDgB4XZcnc8]]></FromUserName>
<CreateTime>1359709372</CreateTime>
<MsgType><![CDATA[link]]></MsgType>
<Title><![CDATA[微信公眾平臺開發(fā)者的江湖]]></Title>
<Description><![CDATA[陳坤的微信公眾號這段時間大火,大家..]]></Description>
<Url><![CDATA[http://israel.duapp.com/web/photo.php]]></Url>
<MsgId>5839907284805129867</MsgId>
</xml>
XML格式講解
ToUserName 消息接收方微信號,一般為公眾平臺賬號微信號
FromUserName 消息發(fā)送方微信號
CreateTime 消息創(chuàng)建時間
MsgType 消息類型,鏈接為link
Title 圖文消息標(biāo)題
Description 圖文消息描述
Url 點擊圖文消息跳轉(zhuǎn)鏈接
MsgId 消息ID號
發(fā)送消息
只介紹三種格式的消息:文本、圖文、音樂。其中圖文消息包括單條圖文消息和多條圖文消息,展示方式有一點點不同。
1. 文本消息格式
回復(fù)文本
后臺格式:
<xml>
<ToUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></ToUserName>
<FromUserName><![CDATA[gh_680bdefc8c5d]]></FromUserName>
<CreateTime>1359036631</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[【深圳】天氣實況 溫度:27℃ 濕度:59% 風(fēng)速:東北風(fēng)3級
11月03日 周日 27℃~23℃ 小雨 東北風(fēng)4-5級
11月04日 周一 26℃~21℃ 陣雨 微風(fēng)
11月05日 周二 27℃~22℃ 陰 微風(fēng)]]></Content>
<FuncFlag>0</FuncFlag>
</xml>
XML格式講解
FromUserName 消息發(fā)送方
ToUserName 消息接收方
CreateTime 消息創(chuàng)建時間
MsgType 消息類型,文本消息必須填寫text
Content 消息內(nèi)容,大小限制在2048字節(jié),字段為空為不合法請求
FuncFlag 星標(biāo)字段
2. 圖文消息格式
2.1 單條圖文消息
回復(fù)單條圖文
后臺格式:
<xml>
<ToUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></ToUserName>
<FromUserName><![CDATA[gh_680bdefc8c5d]]></FromUserName>
<CreateTime>1359011899</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<Content><![CDATA[]]></Content>
<ArticleCount>1</ArticleCount>
<Articles>
<item>
<Title><![CDATA[[蘋果產(chǎn)品信息查詢]]></Title>
<Description><![CDATA[序列號:USE IMEI NUMBER
IMEI號:358031058974471
設(shè)備名稱:iPhone 5C
設(shè)備顏色:
設(shè)備容量:
激活狀態(tài):已激活
電話支持:未過期[2014-01-13]
硬件保修:未過期[2014-10-14]
生產(chǎn)工廠:中國]]>
</Description>
<PicUrl><![CDATA[http://www.doucube.com/weixin/weather/icon/banner.jpg]]></PicUrl>
<Url><![CDATA[]]></Url>
</item>
</Articles>
<FuncFlag>0</FuncFlag>
</xml>
2.2 多圖文消息
回復(fù)多圖文
后臺數(shù)據(jù)格式
<xml>
<ToUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></ToUserName>
<FromUserName><![CDATA[gh_680bdefc8c5d]]></FromUserName>
<CreateTime>1359011829</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<Content><![CDATA[]]></Content>
<ArticleCount>5</ArticleCount>
<Articles>
<item>
<Title><![CDATA[【深圳】天氣實況 溫度:3℃ 濕度:43﹪ 風(fēng)速:西南風(fēng)2級]]></Title>
<Description><![CDATA[]]></Description>
<PicUrl><![CDATA[http://www.doucube.com/weixin/weather/icon/banner.jpg]]></PicUrl>
<Url><![CDATA[]]></Url>
</item>
<item>
<Title><![CDATA[06月24日 周四 2℃~-7℃ 晴 北風(fēng)3-4級轉(zhuǎn)東南風(fēng)小于3級]]></Title>
<Description><![CDATA[]]></Description>
<PicUrl><![CDATA[http://www.doucube.com/weixin/weather/icon/d00.gif]]></PicUrl>
<Url><![CDATA[]]></Url>
</item>
<item>
<Title><![CDATA[06月25日 周五 -1℃~-8℃ 晴 東南風(fēng)小于3級轉(zhuǎn)東北風(fēng)3-4級]]></Title>
<Description><![CDATA[]]></Description>
<PicUrl><![CDATA[http://www.doucube.com/weixin/weather/icon/d00.gif]]></PicUrl>
<Url><![CDATA[]]></Url>
</item>
<item>
<Title><![CDATA[06月26日 周六 -1℃~-7℃ 多云 東北風(fēng)3-4級轉(zhuǎn)東南風(fēng)小于3級]]></Title>
<Description><![CDATA[]]></Description>
<PicUrl><![CDATA[http://www.doucube.com/weixin/weather/icon/d01.gif]]></PicUrl>
<Url><![CDATA[]]></Url>
</item>
<item>
<Title><![CDATA[06月27日 周日 0℃~-6℃ 多云 東南風(fēng)小于3級轉(zhuǎn)東北風(fēng)3-4級]]></Title>
<Description><![CDATA[]]></Description>
<PicUrl><![CDATA[http://www.doucube.com/weixin/weather/icon/d01.gif]]></PicUrl>
<Url><![CDATA[]]></Url>
</item>
</Articles>
<FuncFlag>0</FuncFlag>
</xml>
XML格式講解
FromUserName 消息發(fā)送方
ToUserName 消息接收方
CreateTime 消息創(chuàng)建時間
MsgType 消息類型,圖文消息必須填寫news
Content 消息內(nèi)容,圖文消息可填空
ArticleCount 圖文消息個數(shù),限制為10條以內(nèi)
Articles 多條圖文消息信息,默認第一個item為大圖
Title 圖文消息標(biāo)題
Description 圖文消息描述
PicUrl 圖片鏈接,支持JPG、PNG格式,較好的效果為大圖640*320,小圖80*80
Url 點擊圖文消息跳轉(zhuǎn)鏈接
FuncFlag 星標(biāo)字段
3. 音樂消息
回復(fù)音樂消息
后臺格式:
<xml>
<ToUserName><![CDATA[ollB4jqgdO_cRnVXk_wRnSywgtQ8]]></ToUserName>
<FromUserName><![CDATA[gh_b629c48b653e]]></FromUserName>
<CreateTime>1372310544</CreateTime>
<MsgType><![CDATA[music]]></MsgType>
<Music>
<Title><![CDATA[最炫民族風(fēng)]]></Title>
<Description><![CDATA[鳳凰傳奇]]></Description>
<MusicUrl><![CDATA[http://zj189.cn/zj/download/music/zxmzf.mp3]]></MusicUrl>
<HQMusicUrl><![CDATA[http://zj189.cn/zj/download/music/zxmzf.mp3]]></HQMusicUrl>
</Music>
<FuncFlag>0</FuncFlag>
</xml>
XML格式講解
ToUserName 接收方帳號(收到的OpenID)
FromUserName 開發(fā)者微信號
CreateTime 消息創(chuàng)建時間
MsgType 消息類型,此處為music
Title 音樂標(biāo)題
Description 音樂描述
MusicUrl 音樂鏈接
HQMusicUrl 高質(zhì)量音樂鏈接,WIFI環(huán)境優(yōu)先使用該鏈接播放音樂
FuncFlag 位0x0001被標(biāo)志時,星標(biāo)剛收到的消息。
事件消息類型
目前用戶在關(guān)注和取消關(guān)注,以及點擊菜單的時候會自動向公眾平臺發(fā)送事件推送消息:
1. 關(guān)注事件
<xml>
<ToUserName><![CDATA[gh_b629c48b653e]]></ToUserName>
<FromUserName><![CDATA[ollB4jv7LA3tydjviJp5V9qTU_kA]]></FromUserName>
<CreateTime>1372307736</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
<EventKey><![CDATA[]]></EventKey>
</xml>
2. 取消關(guān)注事件
<xml>
<ToUserName><![CDATA[gh_b629c48b653e]]></ToUserName>
<FromUserName><![CDATA[ollB4jqgdO_cRnVXk_wRnSywgtQ8]]></FromUserName>
<CreateTime>1372309890</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[unsubscribe]]></Event>
<EventKey><![CDATA[]]></EventKey>
</xml>
3. 菜單點擊事件
<xml>
<ToUserName><![CDATA[gh_680bdefc8c5d]]></ToUserName>
<FromUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></FromUserName>
<CreateTime>1377886191</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[CLICK]]></Event>
<EventKey><![CDATA[天氣深圳]]></EventKey>
</xml>
XML格式講解
ToUserName 接收方微信號
FromUserName 發(fā)送方微信號,若為普通用戶,則是一個OpenID
CreateTime 消息創(chuàng)建時間
MsgType 消息類型,event
Event 事件類型,subscribe(訂閱)、unsubscribe(取消訂閱)、CLICK(自定義菜單點擊事件)
EventKey 事件KEY值,與自定義菜單接口中KEY值對應(yīng)
第六章 開發(fā)天氣預(yù)報功能
這一章里,我們來快速開發(fā)天氣預(yù)報功能、我們使用方倍工作室的相應(yīng)接口來實現(xiàn)。下面代碼實現(xiàn)了這樣該功能。
<?php
/*
方倍工作室
CopyRight 2014 All Rights Reserved
*/
define("TOKEN", "weixin");
$wechatObj = new wechatCallbackapiTest();
if (!isset($_GET['echostr'])) {
$wechatObj->responseMsg();
}else{
$wechatObj->valid();
}
class wechatCallbackapiTest
{
public function valid()
{
$echoStr = $_GET["echostr"];
if($this->checkSignature()){
echo $echoStr;
exit;
}
}
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;
}
}
public function responseMsg()
{
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
if (!empty($postStr)){
$this->logger("R ".$postStr);
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$RX_TYPE = trim($postObj->MsgType);
switch ($RX_TYPE)
{
case "event":
$result = $this->receiveEvent($postObj);
break;
case "text":
$result = $this->receiveText($postObj);
break;
}
$this->logger("T ".$result);
echo $result;
}else {
echo "";
exit;
}
}
private function receiveEvent($object)
{
$content = "";
switch ($object->Event)
{
case "subscribe":
$content = "歡迎關(guān)注方倍工作室 ";
break;
}
$result = $this->transmitText($object, $content);
return $result;
}
private function receiveText($object)
{
$keyword = trim($object->Content);$url = "http://apix.sinaapp.com/weather/?appkey=".$object->ToUserName."&city=".urlencode($keyword);
$output = file_get_contents($url);
$content = json_decode($output, true);
$result = $this->transmitNews($object, $content);
return $result;
}
private function transmitText($object, $content)
{
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
$result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content);
return $result;
}
private function transmitNews($object, $newsArray)
{
if(!is_array($newsArray)){
return;
}
$itemTpl = " <item>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<PicUrl><![CDATA[%s]]></PicUrl>
<Url><![CDATA[%s]]></Url>
</item>
";
$item_str = "";
foreach ($newsArray as $item){
$item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
}
$newsTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<Content><![CDATA[]]></Content>
<ArticleCount>%s</ArticleCount>
<Articles>
$item_str</Articles>
</xml>";
$result = sprintf($newsTpl, $object->FromUserName, $object->ToUserName, time(), count($newsArray));
return $result;
}
private function logger($log_content)
{
}
}
?>
在公眾賬號中使用的命令如下:
1.發(fā)送城市名稱,如“深圳”,可以查詢該城市的天氣
在你的公眾賬號輸入相應(yīng)的命令,實現(xiàn)效果類似如下所示:
第七章 小結(jié)
總的來說,通過本教程,你得到了以下收獲:
1. 你通過本教程得到了一個免費的云計算空間2. 你成功啟用了開發(fā)模式,并且實現(xiàn)了時間的自動回復(fù)3. 你非??焖俚鼐腕w驗了各種消息接收及發(fā)送,比方倍當(dāng)年自己摸索所用的時間短了很多4. 你了解了微信公眾平臺開發(fā)的原理,并且熟悉了各種消息及發(fā)送是怎么一回事5. 你使用方倍工作室的接口,成功的開發(fā)了你的第一個微信公眾平臺功能——天氣預(yù)報。
接下來該做什么呢?你可以學(xué)習(xí)開發(fā)一些基礎(chǔ)的常用功能,推薦:方倍工作室 編寫,機械工業(yè)出版社 出版的《微信公眾平臺開發(fā)最佳實踐》,里面包含很多php開發(fā)技巧、數(shù)據(jù)庫使用、及近30項微信公眾平臺實用功能或技術(shù) 。
相關(guān)文章
Android 8.0 讀取內(nèi)部和外部存儲以及外置SDcard的方法
今天小編就為大家分享一篇Android 8.0 讀取內(nèi)部和外部存儲以及外置SDcard的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08RecyclerView仿應(yīng)用列表實現(xiàn)網(wǎng)格布局
這篇文章主要為大家詳細介紹了RecyclerView仿應(yīng)用列表實現(xiàn)網(wǎng)格布局,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-09-09朋友圈實現(xiàn)圖片+文字轉(zhuǎn)發(fā)功能(必看篇)
下面小編就為大家?guī)硪黄笥讶崿F(xiàn)圖片+文字轉(zhuǎn)發(fā)功能(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-03-03協(xié)程作用域概念迭代RxTask?實現(xiàn)自主控制
這篇文章主要為大家介紹了協(xié)程作用域概念迭代RxTask實現(xiàn)自主控制詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10Android App中讀取XML與JSON格式數(shù)據(jù)的基本方法示例
這篇文章主要介紹了Android App中讀取XML與JSON格式數(shù)據(jù)的基本方法示例,Android中自帶的JSONObject非常好用,需要的朋友可以參考下2016-03-03Android組件間通信--深入理解Intent與IntentFilter
本篇文章是對Android組件間通信Intent與IntentFilter進行了詳細的分析介紹,需要的朋友參考下2013-05-05