一:
1.定义一个专门用于发送api请求和处理api接收数据的类
2.类中定义两个方法:1个用于生成连接api所用的url,一个用于连接api并且处理返回数据
3. 请求地址:https://api.seniverse.com/v3/weather/now.json
4.阅读心知天气api文档和心知天气api示例代码(php)
5.容易出问题的地方:
1)在连接api和处理消息方法中,用cURL进行连接,tips:curl连接的时候不要使用服务器验证!!!,不设置hedding,不设置host,否则连接不了api,正确示范如官方提供的demo参考。
2)api返回的是json格式,用php提供的json转数组函数可以转数组,这个数组是一个多维的数组,注意取值的时候不要出错,数组为索引数组+关联数组混合,如下面代码所示
$output['results'][0]['location']['name']
这里取到的就是城市名字。
6.整体思路:在回复文本消息方法中调用生成URL链接函数,将用户发送的城市名字传过来;URL链接函数调用连接方法,在连接方法中返回处理完成的字符串,可供被动回复文本消息方法直接回复。
7.实例code demo :wether.php
<?php
/*调用心知天气api demo
*/
//自动转数组并返回查询结果字符串
class wetherReplay
{
function httpGet($url)
{
$ch = curl_init();//c初始化一个cURL会话
curl_setopt($ch, CURLOPT_URL, $url);//将URL设置为我们需要的URL
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$output = curl_exec($ch);//获取json返回数据
curl_close($ch);
$output = json_decode($output, true);//将获取到的json转化成php数组
$retStr = "您查询的城市:" .$output['results'][0]['location']['name'] . "\n" . "今日天气:" .$output['results'][0]['now']['text']
. "\n" . "温度:" .$output['results'][0]['now']['temperature'] ."摄氏度";
return $retStr;
}
// 心知天气接口调用凭据
public function wetherCallBackTest($pos)
{
$key = '6wd17nam8wcitv0f'; // 测试用 key,请更换成您自己的 Key
$uid = 'U270B81E1D'; // 测试用 用户 ID,请更换成您自己的用户 ID
// 参数
$api = 'https://api.seniverse.com/v3/weather/now.json'; // 接口地址
$location = $pos; // 城市名称。除拼音外,还可以使用 v3 id、汉语等形式
// 生成签名。文档:https://www.seniverse.com/doc#sign
$param = [
'ts' => time(),
'ttl' => 300,
'uid' => $uid,
];
$sig_data = http_build_query($param); // http_build_query 会自动进行 url 编码
// 使用 HMAC-SHA1 方式,以 API 密钥(key)对上一步生成的参数字符串(raw)进行加密,然后 base64 编码
$sig = base64_encode(hash_hmac('sha1', $sig_data, $key, TRUE));
// 拼接 url 中的 get 参数。文档:https://www.seniverse.com/doc#daily
$param['sig'] = $sig; // 签名
$param['location'] = $location;
$param['start'] = 0; // 开始日期。0 = 今天天气
$param['days'] = 1; // 查询天数,1 = 只查一天
// 构造 url
$url = $api . '?' . http_build_query($param);
return $this->httpGet($url);
}
}
二:被动回复消息类:
1.在文本消息中分辨出用户是否发送询问天气消息,自定义判断规则 eg:用户发送南阳天气时,strstr()识别出字符串是否有天气两字,若有,进入到回复天气模块,没有,正常进入回复模块;
2.城市名字是不一定两个字的,所以使用mb_strlen()来判断用户输入的字符个数,然后减去2就是城市名字的字符个数,再使用mb_substr()来截取这个字符长度的城市名字
3.code demo replay.php
<?php
require 'wether.php';//包含文件,以使可以调用该文件的方法
//$wetherReplay = new wetherReplay();
//回复消息类
class ReplyMsageUntion{
//回复消息选择器
public function messageSwitch()
{
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
if (!empty($postStr)) {
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
switch ($postObj->MsgType) {
case 'text':
$this->replayText($postObj);
break;
case 'image':
$this->replayImage($postObj);
break;
case 'voice':
$this->replayAudio($postObj);
case 'video';
$this->replayVideo($postObj);
}
}else
echo "";
}
//文本消息回复函数
private function replayText($postObj)
{
$wetherReplay = new wetherReplay();//new一个对象才可以调用生成URL方法
$fromUser = $postObj->FromUserName;
$toUser = $postObj->ToUserName;
$mType = $postObj->MsgType;
$keyWord = trim($postObj->Content);
$time = date("Y:m:d H:i:s", time());
//如果消息中包含天气,则回复天气预报
if(strstr($keyWord,"天气")){//strstr()用来检测是否有固定字符串出现
$lenthContent = mb_strlen($keyWord,'utf-8');//判断用户输入的字符串长度
$pos = mb_substr($keyWord,0,$lenthContent-2,'utf-8');//截取城市名字
$wetherRet = $wetherReplay->wetherCallBackTest($pos);//调用天气生成URL方法
$textStr = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>
</xml>";
$resultStr = sprintf($textStr,$fromUser,$toUser, $time, $mType,$wetherRet);
echo $resultStr;
}else{
// $time = date("Y:m:d H:i:s", time());
$textStr = "<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)){
$contentStr = "已收到您的消息:".$postObj->Content ."\n" ."发送时间" .$time;
$resultStr = sprintf($textStr,$fromUser,$toUser, $time, $mType,$contentStr);
echo $resultStr;
}
}
//图片消息回复函数
private function replayImage($postObj){
$fromUser = $postObj->FromUserName;
$toUser = $postObj->ToUserName;
$mType = $postObj->MsgType;
$time = date("Y:m:d H:i:s", time());
$imageStr = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Image>
<MediaId><![CDATA[%s]]></MediaId>
</Image>
</xml>";
// $contentStr = "您发送的是一张图片,点击以下链接查看:"."\n" .$postObj->MediaId;
$resultStr = sprintf($imageStr,$fromUser,$toUser,$time,$mType,$postObj->MediaId);
echo $resultStr;
}
//回复语音消息
private function replayAudio($postObj){
$fromUser = $postObj->FromUserName;
$toUser = $postObj->ToUserName;
$mType = $postObj->MsgType;
$time = date("Y:m:d H:i:s", time());
$audeoStr = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Voice>
<MediaId><![CDATA[%s]]></MediaId>
</Voice>
</xml>";
$resultStr = sprintf($audeoStr,$fromUser,$toUser,$time,$mType,$postObj->MediaId);
echo $resultStr;
}
//回复视频消息
private function replayVideo(){
$fromUser = $postObj->FromUserName;
$toUser = $postObj->ToUserName;
$mType = $postObj->MsgType;
$time = time();
$videoStr = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Video>
<MediaId><![CDATA[%s]]></MediaId>
// <Title><![CDATA[%s]]></Title>
// <Description><![CDATA[%s]]></Description>
</Video>
</xml>";
// $contentTitle = "视频消息";
// $contentDesc = "点击即可观看";
$resultStr = sprintf($videoStr,$fromUser,$toUser,$time,$mType,$postObj->MediaId);
echo $resultStr;
}
}
三 入口文件
1.服务器绑定校验签名 tips:签名不用每次请求都绑定,所以要加一个判断条件
2.code demo api.php
<?php
require 'replay.php';
define("TOKEN","flyingman");
$wechatObj = new wechatCallBackTest();
$replayMseeg = new ReplyMsageUntion();
if (!(isset($_GET["echostr"]))){
$replayMseeg->messageSwitch();
}else{
$wechatObj->valid();
}
class wechatCallBackTest{
//校验签名
public function valid()
{
$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) {
echo $_GET["echostr"];
}
}
}
四 总结
1.以上code可以实现微信被动回复文本,语音,图片,天气查询
2. 天气查询限定格式:城市名+天气