微信公眾平臺-公眾賬號接收非文字訊息?

在微信公眾平臺上使用者都是用使用文字在進行互動的,但是有時候使用圖片、語音、視訊以及地理位置等可以實現一些非常棒的功能,比如“語音提醒”公眾號裡的傳送語音就可以實現定時的事件提醒功能

微信公眾平臺-公眾賬號接收非文字訊息

工具/原料

智慧手機

微信APP

電腦

方法/步驟

相信拍照是目前智慧手機使用者用得最多的功能沒有之一,在微信裡也是一樣,看看每天朋友圈裡分享的那些照片就知道了,那麼如何接收和儲存使用者照片捏,首先我們得了解使用者傳送的圖片訊息結構,如下圖:

微信公眾平臺-公眾賬號接收非文字訊息

大家可以看到圖片訊息除了固定的訊息傳送使用者ID、接收公眾號ID、生成時間等固定欄位外,多了一個圖片連結PicUrl,這個就是使用者向公眾賬號傳送圖片後,儲存到微信的伺服器上返回給公眾號的連結,

也就是說我們如果要把圖片儲存到本地伺服器,就要先將圖片從微信伺服器上抓取下來,當然你也可以直接儲存這個連結以後直接訪問,這個看具體應用了。今天要講的是圖片儲存到本地伺服器上,請看下面程式碼:

微信公眾平臺-公眾賬號接收非文字訊息

由於圖片訊息是另一種訊息型別,因此程式碼新增位置可以位於文字訊息上面或者下面,只要別在文字訊息的判斷語句內就行。然後我來解釋下每個語句的作用:

第20行,判斷訊息型別是否為圖片訊息,條件為$form_MsgType==image;

第24行,獲取圖片訊息資料中的圖片連結並賦值給$from_PicUrl;

第26行,生成要儲存到本地伺服器的圖片名稱,為了避免重複新圖片命名使用了傳送使用者的OPENID+當前時間戳,檔案的字尾名我是直接設定為jpg檔案。(由於從圖片連結上無法獲取到圖片字尾名,又懶得通過標頭檔案獲取圖片格式,就直接固定死了JPG格式,貌似沒有什麼問題,哈哈哈);

第28行,SAE上的內建介面類很多,SaeFetchurl是一個用來抓取遠端網頁的類,使用這個類就可以很方便的實現抓取其他網站的內容,否則使用PHP的curl或者file_get_contents這些估計還得解釋半天,這句程式碼是新建一個抓取類的物件。

第30行,執行抓取圖片連結,其中抓取的函式是fetch(),圖片連結是之前賦值的$from_PicUrl,抓取後的結果賦值給$res;

第32行,判斷抓取結果,errno()返回的是抓取結束後的錯誤程式碼,如果為0則成功,其他的就是不成功。

第35行,圖片抓取成功後,新建一個Storage的物件,我們要儲存圖片了。

第37行,這句程式碼其實已經在以前出現多次,這次將抓取的內容($res)寫入指定的檔案($filename),並儲存到Storage裡,請注意把“weixincourse”替換成自己建立的Storage空間名。

第39行到41行,儲存成功後給使用者提示圖片上傳成功。

第45行到48行,檔案沒有抓取到提示使用者圖片上傳失敗。

當然我們如果嚴謹一點,還要判斷圖片檔案是否儲存成功,可以把第37行後面改寫一下,如下圖:

微信公眾平臺-公眾賬號接收非文字訊息

大家可以嘗試把Storage的空間名字故意寫錯,看看會有什麼樣的提示。如果提示上傳成功,我們到SAE的Storage列表裡就應該可以看到剛上傳的檔案了。

手機上基於地理位置的APP很多,是個應用現在都得跟LBS扯上點關係,SoLoMo裡重要的一環就是地理位置,微信裡也有很多應用是跟地理位置相關的,比如查個本地天氣、附近酒店餐館啥的。今天舉的例子是查本地天氣。先了解下地理位置訊息的結構,如下圖:

微信公眾平臺-公眾賬號接收非文字訊息

地理位置訊息多了四項,分別是經緯度的X和Y座標、地圖縮放比例以及地址資訊,而實際上由於網路原因我們經常是收不到地址資訊的,只有座標資訊,因此地理位置的開發基本圍繞著座標來。先來看本地天氣查詢程式碼吧,如下圖:

微信公眾平臺-公眾賬號接收非文字訊息

程式碼新增位置同圖片訊息,另起一個訊息型別判斷語句,可以放在圖片訊息前面或者後面。前面說了我們主要使用的是經緯度,經緯度是可以通過一些地圖api介面來獲取實際地址、周邊商家等資訊的,天氣程式碼這裡我用的是百度地圖API介面,主要是因為它有URL介面,程式碼解釋開始:

第21行,訊息型別判斷語句,訊息型別為location;

第24行到27行,將使用者推送地理訊息的經緯度、地圖比例、地址資訊分別賦值。經緯度分別為Location_X和Location_Y,相當於用經線和緯線的交叉點來標註地理位置。Scale是使用者傳送地理位置時地圖的縮放比例。Label是地址資訊(經常是獲取不到的,獲取了也沒啥用,因為都是連在一起的,無法提取地市縣資訊)。

第29行,定義百度地圖API介面的反向地址解析URL,反向地址解析是指通過經緯度獲取當前位置的地址資訊。

第31行,由於各家地圖不一樣因此傳輸過來的經緯度也會有所偏差,這裡我選的是wgs84即手機GPS的座標。

第33行,又要抓頁面了,先建個抓取類的物件。

第35行,百度地圖API介面的反向地址解析規則是URL+座標型別+座標值,其中$map_api_url.$map_coord_type兩個變數拼接就是URL+座標型別,然後再加上經緯度引數,用location=經度,緯度來賦值。

這裡說下URL的規則,URL就是大家常看到的網頁連結,一般由HTTP://後面加網址加引數組成,主要說下引數,引數一般是“引數名=賦值”組成,普通的URL引數格式是跟在網址後面第一個引數前用“?”號分隔,第二個引數開始用“&”分隔,引數在程式裡是可以獲取到的,我們上面獲取座標解析的實際地址形式為:

微信公眾平臺-公眾賬號接收非文字訊息

接收的實際地址為獲取到的引數是coord_type和location,值為相應後面跟著的。

第37行,判斷是否抓取成功,如果抓取成功$geocoder的資料實際是如下格式:

微信公眾平臺-公眾賬號接收非文字訊息

這裡一大堆資訊裡只需要提取城市,即CITY這個標籤內的資料。

第40行,這是一個正則表示式,比較複雜,作用就是根據規則將$geocoder裡的 北京市 資料提取出來賦予$city這個變數,如果成功這個資料是會是一個多維陣列,其中city標籤內的資料即北京市是儲存在$city[1][0]裡的,$city[0][0]的值是“ 北京市 ”;

第41行,將$city[1][0]的值即“北京市”提取出來,同時使用str_replace函式將“市”替換掉再重新賦值給$city,str_replace按照字面意思就是字串替換,用法是:str_replace(要替換的內容,替換成的內容,字串);其中替換的內容和替換成的內容可以使用陣列,也可以使用單個字串,我這裡是用了陣列,即將市縣區都替換成了空,替換的用處是因為後面查天氣預報的介面只支援城市名稱,不能有市縣區啥的……經過這一步$city的值就是“北京”;

第43行,定義天氣API介面的URL;

第45行,做了三件事,第一個使用iconv()函式將$city的字元編碼從UTF-8轉換成GBK,第二件是使用urlencode將漢字轉換成英文編碼方便URL傳值,第三件是將URL中的“&city=”的引數名拼接了。

關於字元,有時候我們上網的時候會發現網頁有亂碼,大部分是因為字元編碼不對造成的,可以調節瀏覽器的編碼來切換,在程式裡也是一樣,由於新浪介面接收的字串是GBK的,而我們程式裡使用UTF-8,所以需要轉碼後才能通訊,否則新浪介面收到的就是亂碼。

PS:GBK或者GB2312是中文簡體編碼,屬於ANSI編碼,但是同個ANSI編碼值在不同國家的編碼對應是不同的文字,會非常混亂,所以有了Unicode以及UTF-8,這是國際通用的文字編碼格式,所有文字都被分配了不同的編碼,也就不怕亂碼了。

第46行,查詢天氣日期,0表示當天,1表示明天,以此類推……

第49行,抓取天氣內容並賦值給$weather,這裡不需要再建立抓取類的物件了,因為之前已經建立了可以直接用。

第51行,判斷是否抓到天氣,這裡我多加了一個

微信公眾平臺-公眾賬號接收非文字訊息

strstr函式是用來檢查$weather裡是否存在“Weather”這個字串,&&表示並且,這裡的判斷就是不僅要抓取成功並且在抓取到的內容裡存在“Weather”。這樣寫的目的是因為新浪天氣介面不管有沒有查詢到天氣都會返回資料,而判斷資料裡是否有天氣資訊,只有判斷返回內容裡有木有“Weather”這個字串。成功抓取到的會是如下內容:

微信公眾平臺-公眾賬號接收非文字訊息

這又是一個XML,然後用的是一些拼音首字母做了標籤,把這個回覆給使用者估計會瘋的,我們要進行一些整理,方法嘛就是用正則表示式來提取我們需要的內容,我這裡提取的標籤是city(城市)、status2-status1(天氣變化)、temperature2-temperature1(溫度變化)、direction2-power2(風向風力)、chy_shuoming(穿著建議)、savedate_weather(資訊釋出時間)

第54行到62行就是提取這些資料的正則表示式,可以發現其實改動的只是標籤名和賦值的引數,如果大家還想加寫資料的可以參照著提取;

第64行到71行判斷天氣變化是否相同,比如上面顯示的天氣1和天氣2其實都是陰,如果不做判斷就會返回給使用者“陰轉陰”,非常2,所以這裡判斷如果兩個天氣是一致的則將任意一個天氣賦值給$w_status變數,否則就按照天氣2轉天氣1賦值給$w_status變數,最後輸出時用$w_status這個變數。

第73行到81行新建一個數組,將前面獲取到的天氣資料新增為陣列元素,格式就是$weather_res=array();然後在括號裡用逗號分割每個天氣資料,最後一個後面不要加逗號,這樣做的好處是避免程式碼行過長,而且很清晰。

第82行,將陣列用implode()函式轉化成陣列,用"\n"這個換行符來分割。

其實73到82行完成的就是將所有資料拼接成一個字串,使用“.”一個個拼也可以,不過效率低下而且程式碼也不夠清晰。

相關問題答案