在上一篇分享的博客中,php程序已经可以区分各种消息,并把识别到的消息类型回复给用户,这次会加入第三方接口的调用回复消息给用户
一 准备工作
百度车联网天气接口(官方文档找不到入口了,因为百度api经常调整,已经无力吐槽了)
获取天气信息的接口工具类代码
<?php
namespace util;
define("AK","你的百度api AK秘钥");
class WeatherServiceUtil{
function getWeatherInfo($city="昆明"){
$ak=AK;
//初始化
$curl = curl_init();
//设置抓取的url
curl_setopt($curl, CURLOPT_URL, "http://api.map.baidu.com/telematics/v3/weather?location=".$city."&output=json&ak=".$ak);
//设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
//执行命令
$data = curl_exec($curl);
//关闭URL请求
curl_close($curl);
$result=json_decode($data,true);
$error=$result["error"];
$resStr="";
if($error==0){
$result=$result["results"][0]["weather_data"][0];
$resStr=$result["weather"].";".$result["wind"].";".$result["temperature"];
}else{
$resStr="天气预报获取出错,请重试或联系管理员";
}
return $resStr;
}
}
?>
上面的代码可以再简化,可使用之前博客写的http或https工具类,进行再次优化
二 把天气预报整合到消息处理类
$postStr = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
//发送方账号(openId)
$fromUsername = $postObj->FromUserName;
//开发者微信号
$toUsername = $postObj->ToUserName;
//消息类型
$MsgType = strtolower($postObj->MsgType);
//消息内容
$keyword = trim($postObj->Content);
需要注意获取微信服务器返回给我们的数据,不同php版本获取的方法有差异,本人使用的是php7.3版本,使用的是file_get_contents("php://input")
下面是主要的业务逻辑
if(strpos($keyword, "天气")!==false){
//字符串替换获取城市
$city=str_replace("天气", "", $keyword);
$weatherUtil=new \util\WeatherServiceUtil();
$result=$weatherUtil->getWeatherInfo($city);
$typeResult=$result;
}else{
$typeResult="你发送的是文本消息";
}
最后来看下全部的代码
<?php
namespace handler;
include_once __DIR__.DIRECTORY_SEPARATOR."util".DIRECTORY_SEPARATOR."MessageUtil.php";
include_once __DIR__.DIRECTORY_SEPARATOR."util".DIRECTORY_SEPARATOR."WeatherServiceUtil.php";
define("TOKEN", "weixinCourse");
// 1 判断请求方法,get请求一般为消息验证,post为其他消息交互
// 2 验证signature是否正确(消息来自微信服务器)
$handler = new \handler\WeixinHandler();
$reqMethod = strtolower($_SERVER["REQUEST_METHOD"]);
if ("get" == $reqMethod && !empty($_GET["echostr"])) {
if ($handler->isValid()) {
$echostr = $_GET["echostr"];
echo $echostr;
exit();
}
} else {
//判断消息类型,返回"你发送的是xxx消息"
$handler->responseMessage();
}
class WeixinHandler
{
function checkSignature()
{
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$tmpArr = array(
TOKEN,
$timestamp,
$nonce
);
sort($tmpArr, SORT_STRING);
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
if ($tmpStr) {
return $tmpStr;
} else {
return "";
}
}
function isValid()
{
$signature = $_GET["signature"];
if ($signature == $this->checkSignature()) {
return true;
} else {
return false;
}
}
function responseMessage(){
$msgUtil = new \util\MessageUtil();
$defaultMsgType="text";
//从请求数据获取FromUserName和ToUserName以及消息类型
$postStr = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");
if(!empty($postStr)){
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
//发送方账号(openId)
$fromUsername = $postObj->FromUserName;
//开发者微信号
$toUsername = $postObj->ToUserName;
//消息类型
$MsgType = strtolower($postObj->MsgType);
//消息内容
$keyword = trim($postObj->Content);
$msgUtil = new \util\MessageUtil();
$typeResult="";
$resultStr="";
if("text"==$MsgType){
if(strpos($keyword, "天气")!==false){
//字符串替换获取城市
$city=str_replace("天气", "", $keyword);
$weatherUtil=new \util\WeatherServiceUtil();
$result=$weatherUtil->getWeatherInfo($city);
$typeResult=$result;
}else{
$typeResult="你发送的是文本消息";
}
}else if("image"==$MsgType){
$typeResult="你发送的是图片消息";
}else if("voice"==$MsgType){
$typeResult="你发送的是语音消息";
}else if("video"==$MsgType){
$typeResult="你发送的是视频消息";
}else if("shortvideo"==$MsgType){
$typeResult="你发送的是短视频消息";
}else if("location"==$MsgType){
$typeResult="你发送的是地理位置消息";
}else if("link"==$MsgType){
$typeResult="你发送的是链接消息";
}else if("event"==$MsgType){
//事件推送处理
$typeResult="事件推送消息";
}else{
$typeResult="你发送的是其他类型的消息";
}
if("text"==$defaultMsgType){
$resultStr=$msgUtil->textMessageToXml($fromUsername, $toUsername,$typeResult);
}
echo $resultStr;
}else{
echo "";
exit;
}
}
}
?>
看下运行效果
到这里为止功能就实现了,需要注意的是第三方接口的调用要注意返回值的处理,防止报错、异常等,如用户输入的城市不存在查不到数据,也要响应错误提示给用户。