如何使用開發者伺服器運維微信公眾號
阿新 • • 發佈:2018-12-26
很多人都有自己的伺服器,特別是對於大學生而言,很多伺服器公司都對學生有優惠,例如騰訊雲只要1元每月:http://blog.csdn.net/tiandixuanwuliang/article/details/56494528 ,那麼我們作為一名程式設計師,總想把一切掌控在自己手中,<哈哈>,那麼如何使用我們開發者伺服器去管理微信公眾號呢?這就是本文介紹的內容。
本文介紹以下內容:
- (1)如何把微信公眾號授權給開發者伺服器
- (2)如何使用程式碼把開發者伺服器與微信伺服器進行關聯
- (3)實現接受和傳送訊息
- (4)自定義選單
1 如何把微信公眾號授權給開發者伺服器
- (1)進入微信公眾號平臺,https://mp.weixin.qq.com/,首先請取消其他第三方伺服器的授權,方法如下:
注:這裡也可以不取消第三方伺服器的授權,不取消的話,公眾號粉絲髮送的資料會同時1傳送到第三方伺服器和開發者伺服器,本人已經驗證了,有興趣可以自行研究 - (2)回到微信公眾號管理平臺首頁,頁面往下拉,選擇“基本配置”,如圖:
- (3)新增ip白名單
- (4)選擇修改配置
- (5)下圖中的url,指向你自己的伺服器中正在執行的php地址,這是本文程式碼開發的重點,具體內容請看下一章。token可以隨便寫,但是需要與上述php檔案中配置的一樣,具體內容請看下一章
2 如何使用程式碼把開發者伺服器與微信伺服器進行關聯
- (0)這一章講解程式碼的開發。第一章第5小節中的url指向自己的伺服器中正在執行的php檔案,本章將介紹這一個檔案的內容。關於如何執行這個php檔案,請看php教程http://blog.csdn.net/tiandixuanwuliang/article/category/7344088
- (1)該php檔案內容如下,下面的程式碼實現了連線開發者伺服器、關鍵字回覆、圖靈機器人功能,注:請把下面的token填寫為第一章第5小節中截圖中設定的token
<?php
/**
* 微信公眾號開發-入門
*
* api
*/
define("TOKEN",'we--xxxx'); //這裡和你微信公眾號開放平臺上的tonken填寫一樣的即可
$weixinApi=new WeixinApi();
if(isset($_GET["echostr"])){
$weixinApi->valid();
}else{
$weixinApi->responseMsg();
}
class WeixinApi{
//驗證介面
public function valid(){
$echoStr = $_GET["echostr"];//從微信使用者端獲取一個隨機字元賦予變數echostr
if($this->checkSignature()){
echo $echoStr;
exit;
}
}
//檢查簽名
private function checkSignature(){
//1 接受微信伺服器get請求傳送過來的4個引數
$signature = $_GET["signature"];//從使用者端獲取簽名賦予變數signature
$timestamp = $_GET["timestamp"];//從使用者端獲取時間戳賦予變數timestamp
$nonce = $_GET["nonce"]; //從使用者端獲取隨機數賦予變數nonce
//2 加密和校驗請求
//2.1 將token、timestamp、nonce三個引數進行字典序排序
$tmpArr = array(TOKEN, $timestamp, $nonce);//簡歷陣列變數tmpArr
sort($tmpArr, SORT_STRING);//新建排序
//2.2 將三個引數字串拼接成一個字串進行sha1加密
$tmpStr = implode($tmpArr);//陣列轉字串
$tmpStr = sha1($tmpStr);//shal加密
//2.3 開發者獲得加密後的字串可與signature對比,標識該請求來源於微信
if ($tmpStr == $signature) {
return true;
} else {
return false;
}
}
//回覆訊息
public function responseMsg(){
//3 以下程式碼接受訊息
//3.1 接受微信伺服器傳送過來的原生的POST的資料包
// $postData = $GLOBALS["HTTP_RAW_POST_DATA"];
$postData = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] :file_get_contents("php://input");
//3.2 處理資料包
$xmlObj = simplexml_load_string($postData, "SimpleXMLElement", LIBXML_NOCDATA);
$msgType = $xmlObj->MsgType;
//4 根據訊息型別進行業務處理
switch ($msgType) {
//接受事件訊息
case 'event':
$this->disposeEvent($xmlObj);
break;
//接受文字訊息
case 'text':
$this->disposeText($xmlObj);
break;
//接受圖片訊息
case 'image':
$this->disposeImage($xmlObj);
break;
}
}
//處理接收的事件訊息
private function disposeEvent($xmlObj){
switch ($xmlObj->Event){
case 'subscribe'://訂閱事件
$this->sendText('歡迎您的訂閱');
break;
case 'unsubscribe'://取消訂閱事件
$this->sendText('good-bye');//該訊息使用者其實是看不到的,取消訂閱事件一般用來清除資料庫記錄
break;
}
}
//處理接收的文字訊息
private function disposeText($xmlObj){
$text=trim($xmlObj->Content);
//包含關鍵字都不做處理
if (!(
strstr($text,'違規') //這裡對違規的關鍵字做排除,不予理睬
)){
switch ($text){
case '你好':
$this->sendText($xmlObj,'Hi 我是開發者伺服器');
break;
case 'new':
$newsArr=array(
array(
"title"=>"看到這條訊息,你可以買彩票了",
"description"=>"本公眾號有許多小彩蛋,歡迎您的探索。",
"picUrl"=>"http://img.mp.itc.cn/upload/20170610/03d69e8df0524b8cb59fd16dc2fec989.jpg",
"url"=>"http://www.baidu.com"
)
);
$this->sendNews($xmlObj,$newsArr);
break;
default:
$this->tuling123($xmlObj,trim($xmlObj->Content)); //圖靈機器人
}
}
}
//處理接收的圖片訊息
private function disposeImage($xmlObj){ //一般情況下,不會去處理使用者傳送的圖片
$this->sendImage($xmlObj,$xmlObj->PicUrl,$xmlObj->MediaId);
}
//傳送文字的方法
private function sendText($xmlObj,$content){
$replyTextMsg="<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
echo sprintf($replyTextMsg,$xmlObj->FromUserName,$xmlObj->ToUserName,time(),$content);
}
//傳送圖片的方法
private function sendImage($xmlObj,$mediaId){
$replyImageMsg="<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<Image>
<MediaId><![CDATA[%s]]></MediaId>
</Image>
</xml>";
echo sprintf($replyImageMsg,$xmlObj->FromUserName,$xmlObj->ToUserName,time(),$mediaId);
}
//傳送圖文的方法
private function sendNews($xmlObj,$newsArr){
$newsTplHead = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>%s</ArticleCount>
<Articles>";
$newsTplBody = "<item>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<PicUrl><![CDATA[%s]]></PicUrl>
<Url><![CDATA[%s]]></Url>
</item>";
$newsTplFoot = "</Articles>
<FuncFlag>%s</FuncFlag>
</xml>";
$replyNewsMsg = sprintf($newsTplHead, $xmlObj->FromUserName, $xmlObj->ToUserName, time(),count($newsArr));
foreach($newsArr as $key => $value){
$replyNewsMsg .= sprintf($newsTplBody, $value['title'], $value['description'], $value['picUrl'], $value['url']);
}
$replyNewsMsg .= sprintf($newsTplFoot, 0);
echo $replyNewsMsg;
}
public function tuling123($xmlObj,$message){//這是是使用圖靈機器人
$tuTonken='2d8aaa17141c443----xxx---fsa'; //請去圖靈網http://www.tuling123.com/自己申請一個tonken
$tuUrl='http://www.tuling123.com/openapi/api?key='.$tuTonken.'&info='.$message.'&userid='.$xmlObj->FromUserName;
$tuData='{
"key": "'.$tuTonken.'",
"info": "'.$message.'",
"userid": "'.$xmlObj->FromUserName.'"
}';
$results = $this->htts_request($tuUrl,$tuData);
// print_r($results);
if ($results['code']==100000){
$text=$results['text'];
$this->sendText($xmlObj,$text);
}else{
$this->sendText($xmlObj,'有問題,請輸入“幫助”');
}
}
//https請求(get和post)
private function htts_request($url,$data=array()){
//1 初始化curl
$ch=curl_init();
//2 設定傳輸選項
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);//把頁面以檔案流的形式返回
if (!empty($data)) {
curl_setopt($ch, CURLOPT_POST, true); //設定為 POST 請求
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); //設定POST的請求資料
}
//3 執行curl請求
$outopt=curl_exec($ch);
$outoptArr=json_decode($outopt,true);
//4 關閉curl
curl_close($ch);
return $outoptArr;
}
}
?>
- (2)上面程式碼可以用下面的結構圖進行分析:
- (3)下面是自定義選單的程式碼(不建議使用,原因請看下面的第5小節)
//獲取access_token
private function getAccessToken(){
//獲取微信介面憑證
$appid="wxb4----xxx";//請在第一章第5小節的圖片中看
$appsecret="21d---xxx";//請在第一章第5小節的圖片中看
$data=json_decode(file_get_contents('./access_token.json'));
if ($data->expires_time <time()){
$url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";
$outoptArr=$this->htts_request($url,array(),false);
$access_token=$outoptArr['access_token'];
if (!empty($access_token)){
//把access_token寫入檔案
$data->access_token=$outoptArr['access_token'];
$data->expires_time=time()+7000;
$fp=fopen('access_token.json','w');
fwrite($fp,json_encode($data));
fclose($fp);
}else{
echo '請求access_token錯誤';
}
}else{
$access_token=$data->access_token;
}
// echo $access_token;
return $access_token;
}
//實現自定義選單
public function menu_create(){
$access_token=$this->getAccessToken();
$url="https://api.weixin.qq.com/cgi-bin/menu/create?access_token={$access_token}";
$data='{
"button": [
{
"type": "click",
"name": "java",
"key": "learn_java"
},
{
"name":"chengxu",
"sub_button":[
{
"type": "view",
"name": "CSDN",
"url": "http://blog.csdn.net/tiandixuanwuliang/"
},
{
"type": "view",
"name": "Github",
"url": "https://github.com/wllfengshu/"
},
{
"type": "view",
"name": "jianshu",
"url": "https://www.jianshu.com/users/4d12e03d0a5f/timeline/"
},
{
"type": "view",
"name": "kaifazhe",
"url": "https://toutiao.io/u/431066/"
},
{
"type": "view",
"name": "yuyan",
"url": "http://www.baidu.com"
}]
},
{
"name":"jiaoliu",
"sub_button":[
{
"type": "view",
"name": "shuji",
"url": "http://blog.csdn.net/tiandixuanwuliang/"
},
{
"type": "view",
"name": "ziyuan",
"url": "https://github.com/wllfengshu/"
},
{
"type": "view",
"name": "sucai",
"url": "https://www.jianshu.com/users/4d12e03d0a5f/timeline/"
},
{
"type": "view",
"name": "daxuesheng",
"url": "https://toutiao.io/u/431066/"
},
{
"type": "click",
"name": "zuozhe",
"key": "about_author"
}]
}
]
}';
echo $url." ///// ".$data;
$outoptArr=$this->htts_request($url,json_decode($data,true),true);
echo '***';
print_r($outoptArr);
}
- (4)下面是網頁授權,授權後我們才可以在程式碼中呼叫(不建議使用,原因請看下面的第5小節)
//網頁授權-base型
public function snsapi_base($redirect_uri){
//以下是測試賬號
$appid="wxb4----xxx";//請在第一章第5小節的圖片中看
$appsecret="21da56-----xxx";//請在第一章第5小節的圖片中看
//準備scope
$snsapi_base_url="https://open.weixin.qq.com/connect/oauth2/authorize?appid={$appid}&redirect_uri={$redirect_uri}&response_type=code&scope=SCOPE&state=123#wechat_redirect";
$code=$_GET['code'];
//獲取code
if (!isset($code)){
header("Location:{$snsapi_base_url}");
}
//獲取access_token
$url="https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$appsecret}&code={$code}&grant_type=authorization_code";
return $this->htts_request($url);
}
- (5)但是由於個人註冊的訂閱號沒有自定義選單的開發許可權,所以我建議大家自定義選單的功能交給第三方服務處理,這也是一個竅門,就是微信公眾號同時授權給第三方伺服器和開發者伺服器,這是一個bug,哈哈。請注意,一定要先授權給開發者伺服器,再授權給第三方伺服器,否則將不成功。原理圖如下:
- 上圖中的第三方伺服器具有關鍵字功能,我建議一些常用的關鍵字都交給第三方伺服器做。一些具有邏輯性的關鍵字、需要存放到資料庫的關鍵字、或者私密性的關鍵字可以由開發者伺服器做。但是由於微信公眾號粉絲髮送的資料會同時傳送到兩個伺服器,而且開發者伺服器還具有圖靈機器人功能,可以採取遮蔽的方法,在任意一方遮蔽一次,這樣就避免了一條訊息,回覆了兩次的問題。
- (6)請把上述php檔案,放到AppServ軟體安裝的根目錄下的www資料夾下,然後重啟AppServ中的服務,最後再把 http://伺服器ip地址/index.php 填寫到第一章第5節的url中即可。可以開始玩了
本文地址:http://blog.csdn.net/tiandixuanwuliang/article/details/79438662
歡迎大家看我的另一篇文章,這篇文章從需求分析、系統設計、程式碼實現等方面進行講解,歡迎大家批評指正,http://blog.csdn.net/tiandixuanwuliang/article/details/79438738
歡迎大家關注,裡面有很多資源分享: