20151228更新:百度API对天气信息的返回结果做了改变,指数信息需要重新解析,原有的代码公众号调用时已经无法正常显示指数信息。
20151230更新:28号是百度API升级造成的短暂故障,现已恢复正常,代码不需要更改。
本天气应用,通过发送城市名或位置获取天气信息,利用百度SDK
百度Key申请:http://lbsyun.baidu.com/apiconsole/key
通过上一个链接申请到AK和SK,也可以只申请AK不申请SK,申请了SK的需要计算SN
接口的形式如:http://api.map.baidu.com/telematics/v3/weather?location=北京&output=json&ak=yourkey
申请了SK的接口形式如:http://api.map.baidu.com/telematics/v3/weather?location=北京&output=json&ak=yourkey&sn=yoursn
接口说明:http://developer.baidu.com/map/carapi-7.htm
SN生成算法:http://developer.baidu.com/map/lbs-appendix.htm#.appendix1
其中location=后面接城市名或经纬度,但是跟微信获取到的顺序刚好相反,location=($object->Location_Y,$object->Location_X)
Weather类文件Weather.php
<?php class Weather { var $ak = 'AK'; var $sk = 'SK'; var $url = 'http://api.map.baidu.com/telematics/v3/weather?location=%s&output=%s&ak=%s&sn=%s'; var $uri = '/telematics/v3/weather'; //计算sn function caculateAKSN($ak, $sk, $url, $querystring_arrays, $method = 'GET') { if ($method === 'POST'){ ksort($querystring_arrays); } $querystring = http_build_query($querystring_arrays); return md5(urlencode($url.'?'.$querystring.$sk)); } //$location可填地名或经纬度,$output可填json或xml //locationToWeatherResult('长沙'); //locationToWeatherResult('121.67397,38.793570'); public function locationToWeatherResult($location,$output='json'){ //当前为GBK编码时需要转换 //$location = iconv('GB2312','UTF-8',$location); //构造请求串数组 $querystring_arrays = array ( 'location' => $location, 'output' => $output, 'ak' => $this->ak ); //调用sn计算函数,默认get请求 $sn = $this->caculateAKSN($this->ak, $this->sk, $this->uri, $querystring_arrays); $target = sprintf($this->url, urlencode($location), $output, $this->ak, $sn); $content = file_get_contents($target); return $content; } } ?>
<?php define("TOKEN", "token"); $wechatObj = new wechatCallbackapiTest(); if (!isset($_GET['echostr'])) { $wechatObj->responseMsg(); }else{ $wechatObj->valid(); } class wechatCallbackapiTest { //验证签名 public function valid() { $echoStr = $_GET["echostr"]; $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){ echo $echoStr; exit; } } 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); $result = ""; switch ($RX_TYPE) { case "event": $result = $this->receiveEvent($postObj); break; case "text": $result = $this->receiveText($postObj); break; case "location": $result = $this->receiveLocation($postObj); break; } $this->logger("T ".$result); echo $result; }else { echo ""; exit; } } private function receiveEvent($object) { switch ($object->Event) { case "subscribe": $content = "感谢您关注【微微微时代】"."\n"."微信号:vvvtimes"."\n"."微信原始ID:gh_f420fbb7e319"."\n"; break; } $result = $this->transmitText($object, $content); return $result; } private function receiveText($object) { $keyword = trim($object->Content); require_once './Weather.php'; $weather = new Weather(); $output = $weather->locationToWeatherResult($keyword); $content = json_decode($output, true); $result = $this->transmitNews($object, $content); return $result; } private function receiveLocation($object) { $location_xpoint = $object->Location_X; $location_ypoint = $object->Location_Y; $keyword = $location_ypoint.",".$location_xpoint; require_once './Weather.php'; $weather = new Weather(); $output = $weather->locationToWeatherResult($keyword); $content = json_decode($output, true); $result = $this->transmitNews($object, $content); return $result; } private function transmitText($object, $content) { if (!isset($content) || empty($content)){ return ""; } $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, $weatherContent) { $city = $weatherContent['results'][0]['currentCity']; $index_data = $weatherContent['results'][0]['index'];//指数 $weather_data = $weatherContent['results'][0]['weather_data']; $pm25= $weatherContent['results'][0]['pm25']; if($weatherContent['error']!=0){ return ""; } $itemTpl = "<item> <Title><![CDATA[%s]]></Title> <Description><![CDATA[%s]]></Description> <PicUrl><![CDATA[%s]]></PicUrl> <Url><![CDATA[%s]]></Url> </item>"; $item_str=''; //标题1条,指数6条,天气4条,微信最大是10条图文,所以抽2条指数显示 $title=$city.'天气预报 '."PM2.5:".$pm25; $description=''; $picUrl= ''; $url=''; $item_str = sprintf($itemTpl, $title, $description, $picUrl, $url); $newIndex_data= Array($index_data[0],$index_data[3]); foreach ($newIndex_data as $item){ $title = $item['tipt'].":".$item['des']; $description=''; $picUrl= ''; $url=''; $item_str .= sprintf($itemTpl, $title, $description, $picUrl, $url); } foreach ($weather_data as $item){ $title = $item['date'].$item['weather'].$item['temperature']; $description=''; $picUrl= $item['dayPictureUrl']; $url=''; $item_str .= sprintf($itemTpl, $title, $description, $picUrl, $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($newIndex_data)+count($weather_data)+1); return $result; } private function logger($log_content) { } } ?>
使用时,替换掉百度的AK,SK,替换掉微信的TOKEN即可
效果如下