zoukankan      html  css  js  c++  java
  • php中引入facebook的messenger消息接口

    前一段时间需要开发一个messenger的消息接口,但是facebook的官方文档似是而非,而且由于在国内比较小众,之前也没有另外的人写过中文的开发教程,只好自己进行了一番研究并完成了一个demo,希望给后来的人能带来一点方便。

    一.创建Facebook应用和主页

    https://developers.facebook.com/docs/messenger-platform/guides/quick-start

    直接按照官方文档的第一步去完成即可

    二.设置webhook

    这里的webhook实际上就是你的第三方服务器,这里facebook的主页类似于微信的公众号。其中webhook的callback url就是回调函数的地址。类似于微信的服务器验证方式,这里的webhook也需要返回给facebook服务器指定的信息。

    在 webhook 网址中,添加身份验证代码。此代码应对应上述验证口令,并以验证请求中发送的 challenge 为响应。点击“新建主页订阅”窗口中的“验证并保存”,以便通过 GET 请求调用 Webhook

    然后给了一个官方案例,返回信息

    app.get('/webhook', function(req, res) {
      if (req.query['hub.mode'] === 'subscribe' &&
          req.query['hub.verify_token'] === <VERIFY_TOKEN>) {
        console.log("Validating webhook");
        res.status(200).send(req.query['hub.challenge']);
      } else {
        console.error("Failed validation. Make sure the validation tokens match.");
        res.sendStatus(403);          
      }  
    });

    我不是很熟悉node.js,发现get[‘hub.verify_token’]并不能拿到并返回验证的信息,这里贴出我的php的验证方式

    private function setupWebhook()
        {
            if(isset($_REQUEST['hub_challenge']) && isset($_REQUEST['hub_verify_token']) && $this->getValidationToken()==$_REQUEST['hub_verify_token'])
            {
                echo $_REQUEST['hub_challenge'];
                exit;
            }
        }

     

    hub_verify_token就是你自己设定的token,需要验证每次get的token,然后echo出hub_challenge

    三.获取主页访问口令并订阅主页

    建议把所有配置信息放在单独的文件里面,方便调用和修改。生成的口令不会在此界面保存。每次选择此主页都会生成一个新的口令。但之前生成的任何口令仍然有效。

    四.接收消息
    完成订阅后,系统需要在 webhook 中侦听 POST 调用。所有回调都将向此 webhook 发出。

    Messenger Platform 的所有回调都使用相同的结构。

    {
      "object":"page",
      "entry":[
        {
          "id":"PAGE_ID",
          "time":1458692752478,
          "messaging":[
            {
              "sender":{
                "id":"USER_ID"
              },
              "recipient":{
                "id":"PAGE_ID"
              },
    
              ...
            }
          ]
        }
      ]
    } 

    纯文字信息的详细结构

    {
      "object":"page",
      "entry":[
        {
          "id":"PAGE_ID",
          "time":1458692752478,
          "messaging":[
            {
              "sender":{
                "id":"USER_ID"
              },
              "recipient":{
                "id":"PAGE_ID"
              },
              "timestamp":1458692752478,
              "message":{
                "mid":"mid.1457764197618:41d102a3e1ae206a38",
                "seq":73,
                "text":"hello, world!",
                "quick_reply": {
                  "payload": "DEVELOPER_DEFINED_PAYLOAD"
                }
              }
            }
          ]
        }
      ]
    } 

    附上webhook的参考文档的地址

    https://developers.facebook.com/docs/messenger-platform/webhook-reference
    • 1

    关于具体处理消息的过程,我贴上我的代码
    入口文件

    require_once 'config.php';
    require_once 'FacebookBot.php';
    $bot = new FacebookBot(FACEBOOK_VALIDATION_TOKEN, FACEBOOK_PAGE_ACCESS_TOKEN);
    $bot->run();
    $messages = $bot->getReceivedMessages();
     foreach ($messages as $message)
     {
        $recipientId = $message->senderId;
        $text=$message->text;
        if($text)
        {
            $bot->sendTextMessage($recipientId, $text);
        }
        elseif($message->attachments)
        {
            $bot->sendTextMessage($recipientId, "Attachment received");
        }
    }

    定义类的文件

    <?php
    require_once 'config.php';
    class FacebookBot
    {
        private $_validationToken;
        private $_pageAccessToken;
        private $_receivedMessages;
        public function __construct($validationToken, $pageAccessToken)
        {
            $this->_validationToken = $validationToken;
            $this->_pageAccessToken = $pageAccessToken;
            $this->setupWebhook();
        }
        public function getReceivedMessages()
        {
            $this->run();
            return $this->_receivedMessages;
        }
        public function getPageAccessToken()
        {
            return $this->_pageAccessToken;
        }
        public function getValidationToken()
        {
            return $this->_validationToken;
        }
        private function setupWebhook()
        {
            if(isset($_REQUEST['hub_challenge']) && isset($_REQUEST['hub_verify_token']) && $this->getValidationToken()==$_REQUEST['hub_verify_token'])
            {
                echo $_REQUEST['hub_challenge'];
                exit;
            }
        }
        public function sendTextMessage($recipientId, $text)
        {
            $url = "https://graph.facebook.com/v2.6/me/messages?access_token=%s";
            $url = sprintf($url, FACEBOOK_PAGE_ACCESS_TOKEN);
            $recipient = new stdClass();
            $recipient->id = $recipientId;
            $message = new stdClass();
            $message->text = $text;
            $parameters = ['recipient' => $recipient, 'message' => $message];
            $response = self::executePost($url, $parameters, true);
            if($response)
            {
                $responseObject = json_decode($response);
                return is_object($responseObject) && isset($responseObject->recipient_id) && isset($responseObject->message_id);
            }
            return false;
        }
    
        public function run()
        {
            $request = self::getJsonRequest();
            //var_dump($request);
            if(!$request) return;
            $entries = isset($request->entry) ? $request->entry : null;
            if(!$entries) return;
            $messages = [];
            foreach ($entries as $entry)
            {
                $messagingList = isset($entry->messaging) ? $entry->messaging : null;
                if(!$messagingList) continue;
                foreach ($messagingList as $messaging)
                {
                    $message = new stdClass();
                    $message->entryId = isset($entry->id) ? $entry->id : null;
                    $message->senderId = isset($messaging->sender->id) ? $messaging->sender->id : null;
                    $message->recipientId = isset($messaging->recipient->id) ? $messaging->recipient->id : null;
                    $message->timestamp = isset($messaging->timestamp) ? $messaging->timestamp : null;
                    $message->messageId = isset($messaging->message->mid) ? $messaging->message->mid : null;
                    $message->sequenceNumber = isset($messaging->message->seq) ? $messaging->message->seq : null;
                    $message->text = isset($messaging->message->text) ? $messaging->message->text : null;
                    $message->attachments = isset($messaging->message->attachments) ? $messaging->message->attachments : null;
                    $messages[] = $message;
                }
            }
            $this->_receivedMessages = $messages;
        }
        private static function getJsonRequest()
        {
            $content = file_get_contents("php://input",true);
            $return=json_decode($content, false, 512, JSON_BIGINT_AS_STRING);
            return $return;
        }
        private static function executePost($url, $parameters, $json = false)
        {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            if($json)
            {
                $data = json_encode($parameters);
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
                curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
                curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Content-Length: ' . strlen($data)));
            }
            else
            {
                curl_setopt($ch, CURLOPT_POST, count($parameters));
                curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($parameters));
            }
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
            $response = curl_exec($ch);
            curl_close($ch);
            return $response;
        }
    }


    我这里做测试,返回的就是复述发送者的信息
    这里写图片描述

    六.测试
    接入第三方平台和自己开发的差别还是很大的,起码报错消息你是看不见的,所以光从messenger那里发消息给主页是不方便调试的。
    我这次用了shell下的curl来进行测试,用主页访问口令向 https://graph.facebook.com/v2.6/me/messages?access_token= 发出 POST 请求。负载必须以如下所述的 JSON 格式提供:

    curl -X POST -H "Content-Type: application/json" -d '{
      "recipient":{
        "id":"USER_ID"
      },
      "message":{
        "text":"hello, world!"
      }
    }' "https://graph.facebook.com/v2.6/me/messages?access_token=PAGE_ACCESS_TOKEN"

    windows和linux略有区别。windows下建议用git bash等基于linux的环境而不要用cmd,例如上面的post请求,在cmd下其引号会失效,必须手动进行转义

    七.关于一些坑
    首先是facebook会偶尔向你的绑定的回调地址get消息,如果8个小时之内没有正确的返回的话,它就会自动解绑,我前一天晚上绑定的url第二天早上自动失效了,发现没有消息返回之后调了半天,才发现了这个问题。
    其次是post回messenger的时候用了curl,需要开启php的curl,linux下的安装和windows不太一样,装的时候不要装错了php的版本,否则是不能生效的。
    最后是messenger的应用没有提交审核之前是只能开发者发消息才有作用~

    messenger的开发文档不算友好,全文算是译文吧,有的地方感觉比较生硬,比如它说的接受消息和发送消息是以用户做主体的,和一般人的理解还有一点出入。

  • 相关阅读:
    WPF一步一脚印系列(1):万事起头难
    php设置时区
    关于我的几个博客
    php如何实现页面跳转
    穷人与富人的区别
    如何抓取关键字在百度搜索的排名
    我的博客园开通了
    在Foxmail中出现SSL连接错误应该如何解决
    javascript实现键盘按下回车时触发
    关于网站分页
  • 原文地址:https://www.cnblogs.com/cqlb/p/9505236.html
Copyright © 2011-2022 走看看