5.PHP微信公眾平臺開發 - 天氣預報功能開發

發表於2019-05-11

【PHP微信公眾平臺開發系列】
01.配置微信介面
02.公眾平臺示例程式碼分析
03.訂閱事件(subscribe)處理
04.簡單回覆功能開發
05.API天氣預報功能開發


本文地址:http://www.phpchina.com/archives/view-43387-1.html
本系列由PHPChina特邀作者@David_Tang供稿,轉載請註明作者資訊與本文地址。

一、簡介
前面幾篇文章對PHP微信公眾平臺的開通及簡單使用做了簡單的介紹,但都沒有涉及到實際使用中的問題,例如天氣查詢,公交查詢,快遞查詢等。接下來的幾篇文章將對實際生活中會經常使用到的一些功能進行開發講解,以供讀者參考。
這一篇文章將對大家每天都會關心的天氣查詢進行開發,例如,使用者傳送訊息 “蘇州天氣”,則會返回蘇州實時天氣狀況,以及未來兩天甚至未來五天的天氣狀況。
二、思路分析
首先要對使用者傳送過來的訊息進行判斷,判斷訊息裡是否含有“天氣”關鍵字,如果含有,則需要繼續提取地區資訊,然後再通過中國天氣網(http://www.weather.com.cn)提供的開放API進行相關地區天氣查詢。
三、關鍵字判斷與地區讀取
使用者傳送過來查詢天氣的訊息的格式是固定好的,即 “地區+天氣”,所以首先擷取後兩個字,判斷是否為 “天氣” 關鍵字。
使用php函式 mb_substr() 擷取,關於該函式的用法:

mb_substr — 獲取字串的部分

  string mb_substr ( string $str , int $start [, int $length [, string $encoding ]] ) 說明:根據字元數執行一個多位元組安全的 substr() 操作。 位置是從 str 的開始位置進行計數。 第一個字元的位置是 0。第二個字元的位置是 1,以此類推。 引數: str
從該 string 中提取子字串。

start
str 中要使用的第一個字元的位置。
正數 -> 從字串開頭指定位置開始;
負數 -> 從字串結尾指定位置開始;

length
str 中要使用的最大字元數。
正數 -> 從 start 處開始最多包括 length 個字元;
負數 -> string 末尾處的 length 個字元將會被漏掉(若 start 是負數則從字串開頭算起)。  encoding
encoding 引數為字元編碼。如果省略,則使用內部字元編碼。 返回值: mb_substr() 函式根據 start 和 length 引數返回 str 中指定的部分。


$str = mb_substr($keyword,-2,2,"UTF-8");
從訊息的結尾數第二個字元開始擷取,擷取兩個字元,然後加以判斷是否為 “天氣” 關鍵字。
下面進行地區提取,還是使用 mb_substr() 函式。
$str_key = mb_substr($keyword,0,-2,"UTF-8");
從訊息的開頭開始,截掉末尾的兩個字元(天氣),既得地區關鍵字。
然後進行判斷,繼而呼叫函式查詢天氣資料。
if($str == '天氣' && !empty($str_key))
{ //呼叫函式查詢天氣資料 }

四、呼叫 weather() 函式查詢
我們這裡呼叫的是中國國家氣象局提供的天氣預報API介面,介面地址:http://m.weather.com.cn/data/101190401.html
URL中的數字指代城市的編號101190401(蘇州),其他城市對應關係將在下面提供。
該介面返回資訊比較全面,也是以json格式提供,格式如下:

{"weatherinfo":{ //基本資訊; "city":"蘇州","city_en":"suzhou",
"date_y":"2013年7月9日","date":"","week":"星期二","fchh":"18","cityid":"101190401", //攝氏溫度 "temp1":"30℃~37℃",
"temp2":"30℃~37℃",
"temp3":"29℃~35℃",
"temp4":"27℃~33℃",
"temp5":"27℃~31℃",
"temp6":"27℃~35℃", //華氏溫度; "tempF1":"86℉~98.6℉",
"tempF2":"86℉~98.6℉",
"tempF3":"84.2℉~95℉",
"tempF4":"80.6℉~91.4℉",
"tempF5":"80.6℉~87.8℉",
"tempF6":"80.6℉~95℉", //天氣描述; "weather1":"晴轉多雲",
"weather2":"晴轉多雲",
"weather3":"晴轉多雲",
"weather4":"多雲",
"weather5":"雷陣雨轉中雨",
"weather6":"雷陣雨轉多雲", //天氣描述圖片序號 "img1":"0",
"img2":"1",
"img3":"0",
"img4":"1",
"img5":"0",
"img6":"1",
"img7":"1",
"img8":"99",
"img9":"4",
"img10":"8",
"img11":"4",
"img12":"1", //圖片名稱; "img_single":"1",
"img_title1":"晴",
"img_title2":"多雲",
"img_title3":"晴",
"img_title4":"多雲",
"img_title5":"晴",
"img_title6":"多雲",
"img_title7":"多雲",
"img_title8":"多雲",
"img_title9":"雷陣雨",
"img_title10":"中雨",
"img_title11":"雷陣雨",
"img_title12":"多雲",
"img_title_single":"多雲", //風速描述 "wind1":"西南風3-4級",
"wind2":"西南風3-4級",
"wind3":"東南風3-4級",
"wind4":"東南風3-4級轉4-5級",
"wind5":"東南風4-5級轉西南風3-4級",
"wind6":"西南風3-4級轉4-5級", //風速級別描述 "fx1":"西南風",
"fx2":"西南風",
"fl1":"3-4級",
"fl2":"3-4級",
"fl3":"3-4級",
"fl4":"3-4級轉4-5級",
"fl5":"4-5級轉3-4級",
"fl6":"3-4級轉4-5級", //今日穿衣指數; "index":"炎熱",
"index_d":"天氣炎熱,建議著短衫、短裙、短褲、薄型T恤衫等清涼夏季服裝。", //48小時穿衣指數 "index48":"炎熱",
"index48_d":"天氣炎熱,建議著短衫、短裙、短褲、薄型T恤衫等清涼夏季服裝。", //紫外線及48小時紫外線 "index_uv":"中等",
"index48_uv":"中等", //洗車指數 "index_xc":"適宜", //旅遊指數 "index_tr":"較不宜", //舒適指數 "index_co":"很不舒適",
"st1":"36",
"st2":"28",
"st3":"36",
"st4":"28",
"st5":"34",
"st6":"27", //晨練指數 "index_cl":"較適宜", //晾曬指數 "index_ls":"適宜", //過敏指數 "index_ag":"不易發"}}


我們可以通過解析JSON,獲取相應城市的天氣資料。
weather() 函式如下:

private function weather($n){ include("weather_cityId.php"); $c_name=$weather_cityId[$n]; if(!empty($c_name)){ $json=file_get_contents("http://m.weather.com.cn/data/".$c_name.".html"); return json_decode($json);
    } else { return null;
    }
}


這裡include 了一個城市對應關係檔案 weather_cityId.php,格式如下:
<?php $weather_cityId = array("北京"=>"101010100","上海"=>"101020100","蘇州"=>"101190401"); ?>

根據傳入的城市名,得到城市程式碼,如果不為空,則呼叫中國天氣網的API進行查詢,返回json格式的資料,然後進行解析並返回資料,如果為空,則返回null值。
五、組織回覆訊息形式
判斷返回資料是否為空,若為空,則 $contentStr = "抱歉,沒有查到\"".$str_key."\"的天氣資訊!";
若返回資料不為空,則:
$contentStr = "【".$data->weatherinfo->city."天氣預報】\n".$data->weatherinfo->date_y." ".$data->weatherinfo->fchh."時釋出"."\n\n實時天氣\n".$data->weatherinfo->weather1." ".$data->weatherinfo->temp1." ".$data->weatherinfo->wind1."\n\n溫馨提示:".$data->weatherinfo->index_d."\n\n明天\n".$data->weatherinfo->weather2." ".$data->weatherinfo->temp2." ".$data->weatherinfo->wind2."\n\n後天\n".$data->weatherinfo->weather3." ".$data->weatherinfo->temp3." ".$data->weatherinfo->wind3;

說明:
$data->weatherinfo->city  //獲取城市名,這裡為蘇州
$data->weatherinfo->date_y  //獲取日期,這裡為2013年7月9日
$data->weatherinfo->fchh  //資料釋出時間
$data->weatherinfo->weather1  //實時天氣
$data->weatherinfo->temp1  //實時溫度
$data->weatherinfo->wind1  //實時風向和風速
$data->weatherinfo->index_d  //穿衣指數
weather2, temp2, wind2 分別代表了明天的天氣,溫度和風向風速,其他的以此類推。
\n  //表示換行
六、測試

七、完整程式碼

<?php /**
  * wechat php test */ //define your token define("TOKEN", "zhuojin"); $wechatObj = new wechatCallbackapiTest(); $wechatObj->responseMsg(); //$wechatObj->valid(); class wechatCallbackapiTest
{ /*public function valid()
    {
        $echoStr = $_GET["echostr"];

        //valid signature , option
        if($this->checkSignature()){
            echo $echoStr;
            exit;
        }
    }*/ public function responseMsg()
    { //get post data, May be due to the different environments $postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; //extract post data if (!empty($postStr)){ $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); $RX_TYPE = trim($postObj->MsgType); switch($RX_TYPE)
                { case "text": $resultStr = $this->handleText($postObj); break; case "event": $resultStr = $this->handleEvent($postObj); break; default: $resultStr = "Unknow msg type: ".$RX_TYPE; break;
                } echo $resultStr;
        }else { echo ""; exit;
        }
    } public function handleText($postObj)
    { $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(!empty( $keyword ))
        { $msgType = "text"; //天氣 $str = mb_substr($keyword,-2,2,"UTF-8"); $str_key = mb_substr($keyword,0,-2,"UTF-8"); if($str == '天氣' && !empty($str_key)){ $data = $this->weather($str_key); if(empty($data->weatherinfo)){ $contentStr = "抱歉,沒有查到\"".$str_key."\"的天氣資訊!";
                } else { $contentStr = "【".$data->weatherinfo->city."天氣預報】\n".$data->weatherinfo->date_y." ".$data->weatherinfo->fchh."時釋出"."\n\n實時天氣\n".$data->weatherinfo->weather1." ".$data->weatherinfo->temp1." ".$data->weatherinfo->wind1."\n\n溫馨提示:".$data->weatherinfo->index_d."\n\n明天\n".$data->weatherinfo->weather2." ".$data->weatherinfo->temp2." ".$data->weatherinfo->wind2."\n\n後天\n".$data->weatherinfo->weather3." ".$data->weatherinfo->temp3." ".$data->weatherinfo->wind3;
                }
            } else { $contentStr = "感謝您關注【卓錦蘇州】"."\n"."微訊號:zhuojinsz"."\n"."卓越錦繡,名城蘇州,我們為您提供蘇州本地生活指南,蘇州相關資訊查詢,做最好的蘇州微信平臺。"."\n"."目前平臺功能如下:"."\n"."【1】 查天氣,如輸入:蘇州天氣"."\n"."【2】 查公交,如輸入:蘇州公交178"."\n"."【3】 翻譯,如輸入:翻譯I love you"."\n"."【4】 蘇州資訊查詢,如輸入:蘇州觀前街"."\n"."更多內容,敬請期待...";
            } $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); echo $resultStr;
        }else{ echo "Input something...";
        }
    } public function handleEvent($object)
    { $contentStr = ""; switch ($object->Event)
        { case "subscribe": $contentStr = "感謝您關注【卓錦蘇州】"."\n"."微訊號:zhuojinsz"."\n"."卓越錦繡,名城蘇州,我們為您提供蘇州本地生活指南,蘇州相關資訊查詢,做最好的蘇州微信平臺。"."\n"."目前平臺功能如下:"."\n"."【1】 查天氣,如輸入:蘇州天氣"."\n"."【2】 查公交,如輸入:蘇州公交178"."\n"."【3】 翻譯,如輸入:翻譯I love you"."\n"."【4】 蘇州資訊查詢,如輸入:蘇州觀前街"."\n"."更多內容,敬請期待..."; break; default : $contentStr = "Unknow Event: ".$object->Event; break;
        } $resultStr = $this->responseText($object, $contentStr); return $resultStr;
    } public function responseText($object, $content, $flag=0)
    { $textTpl = "<xml>
                    <ToUserName><![CDATA[%s]]></ToUserName>
                    <FromUserName><![CDATA[%s]]></FromUserName>
                    <CreateTime>%s</CreateTime>
                    <MsgType><![CDATA[text]]></MsgType>
                    <Content><![CDATA[%s]]></Content>
                    <FuncFlag>%d</FuncFlag>
                    </xml>"; $resultStr = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content, $flag); return $resultStr;
    } private function weather($n){ include("weather_cityId.php"); $c_name=$weather_cityId[$n]; if(!empty($c_name)){ $json=file_get_contents("http://m.weather.com.cn/data/".$c_name.".html"); return json_decode($json);
        } else { return null;
        }
    } 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;
        }
    }
} ?>


關於城市對應關係檔案 weather_cityId.php,目前更新到了2564個城市,以後還會繼續增加,請到 樂思樂享 官方論壇(URL:http://www.joythink.net/)下載吧。
評論(2)

相關文章