在上一篇分享的博客中,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;
}
}
}
?>
看下運行效果
到這裏爲止功能就實現了,需要注意的是第三方接口的調用要注意返回值的處理,防止報錯、異常等,如用戶輸入的城市不存在查不到數據,也要響應錯誤提示給用戶。