Facebook XMPP Chat API send Message PHP

13,640

Solution 1

You should send to socket command with your message. Common message format is

<message from="[email protected]" to="[email protected]">
    <body>message body</body>
</message>

So before comment "we made it!" insert function call send_xml with your message template

send_xml($fp, $MESSAGE);
if (!find_xmpp($fp, 'BODY')) {
    return false;
}

Solution 2

It's the standard xmpp/jabber message format: See 4.2 on http://xmpp.org/rfcs/rfc3921.html#stanzas-message

Share:
13,640
thpl
Author by

thpl

I'm a 25 year old passionate Web-Developer from Baden-Württemberg, Germany. I use PHP a lot and I'm interested in software-architecture.

Updated on July 31, 2022

Comments

  • thpl
    thpl almost 2 years

    I am currently messing about with the Facebook Chat API. I want to send chat messages to my facebook contacts via an App.

    Using the example provided by facebook I was able to connect to the facebook chat server. But that had more of an trial and error thing here. I could only vaguely understand how requests and responses are sent and received. It would be great if someone could provide further explanation or further reading.

    My actual question is: How can I send messages after connecting to the chat server?

    <?php
    
    // Copyright 2004-present Facebook. All Rights Reserved.
    
    $STREAM_XML = '<stream:stream '.
      'xmlns:stream="http://etherx.jabber.org/streams" '.
      'version="1.0" xmlns="jabber:client" to="chat.facebook.com" '.
      'xml:lang="en" xmlns:xml="http://www.w3.org/XML/1998/namespace">';
    
    $AUTH_XML = '<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" '.
      'mechanism="X-FACEBOOK-PLATFORM"></auth>';
    
    $CLOSE_XML = '</stream:stream>';
    
    $RESOURCE_XML = '<iq type="set" id="3">'.
      '<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">'.
      '<resource>fb_xmpp_script</resource></bind></iq>';
    
    $SESSION_XML = '<iq type="set" id="4" to="chat.facebook.com">'.
      '<session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></iq>';
    
    $START_TLS = '<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>';
    
    
    function open_connection($server) {
      print "[INFO] Opening connection... ";
    
      $fp = fsockopen($server, 5222, $errno, $errstr);
      if (!$fp) {
        print "$errstr ($errno)<br>";
      } else {
        print "connnection open<br>";
      }
    
      return $fp;
    }
    
    function send_xml($fp, $xml) {
      fwrite($fp, $xml);
    }
    
    function recv_xml($fp,  $size=4096) {
      $xml = fread($fp, $size);
      if ($xml === "") {
         return null;
      }
    
      // parses xml
      $xml_parser = xml_parser_create();
      xml_parse_into_struct($xml_parser, $xml, $val, $index);
      xml_parser_free($xml_parser);
    
      return array($val, $index);
    }
    
    function find_xmpp($fp,  $tag, $value=null, &$ret=null) {
      static $val = null, $index = null;
    
      do {
        if ($val === null && $index === null) {
          list($val, $index) = recv_xml($fp);
          if ($val === null || $index === null) {
            return false;
          }
        }
    
        foreach ($index as $tag_key => $tag_array) {
    
          if ($tag_key === $tag) {
            if ($value === null) {
              if (isset($val[$tag_array[0]]['value'])) {
                $ret = $val[$tag_array[0]]['value'];
              }
              return true;
            }
            foreach ($tag_array as $i => $pos) {
              if ($val[$pos]['tag'] === $tag && isset($val[$pos]['value']) &&
                $val[$pos]['value'] === $value) {
                  $ret = $val[$pos]['value'];
                  return true;
              }
            }
          }
        }
        $val = $index = null;
      } while (!feof($fp));
    
      return false;
    }
    
    
    
    function xmpp_connect($options, $access_token) {
      global $STREAM_XML, $AUTH_XML, $RESOURCE_XML, $SESSION_XML, $CLOSE_XML, $START_TLS;
    
      $fp = open_connection($options['server']);
      if (!$fp) {
        return false;
      }
      print("Connection Opened <br />");  
    
    
      // initiates auth process (using X-FACEBOOK_PLATFORM)
      send_xml($fp,  $STREAM_XML);
      if (!find_xmpp($fp, 'STREAM:STREAM')) {
        return false;
      }
      print_r("XMPP Stream Found <br />");
      if (!find_xmpp($fp,  'MECHANISM', 'X-FACEBOOK-PLATFORM')) {
        return false;
      }
    
      print_r("XMPP Mechanism Found <br />");
      // starting tls - MANDATORY TO USE OAUTH TOKEN!!!!
      send_xml($fp,  $START_TLS);
      if (!find_xmpp($fp, 'PROCEED', null, $proceed)) {
        return false;
      }
      print_r("XMPP Proceed Found <br />");  
      stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
    
      send_xml($fp, $STREAM_XML);
      if (!find_xmpp($fp, 'STREAM:STREAM')) {
        return false;
      }
      if (!find_xmpp($fp, 'MECHANISM', 'X-FACEBOOK-PLATFORM')) {
        return false;
      }
    
      // gets challenge from server and decode it
      send_xml($fp, $AUTH_XML);
      if (!find_xmpp($fp,  'CHALLENGE', null, $challenge)) {
        return false;
      }
      $challenge = base64_decode($challenge);
      $challenge = urldecode($challenge);
      parse_str($challenge, $challenge_array);
    
      // creates the response array
      $resp_array = array(
        'method' => $challenge_array['method'],
        'nonce' => $challenge_array['nonce'],
        'access_token' => $access_token,
        'api_key' => $options['app_id'],
        'call_id' => 0,
        'v' => '1.0',
      );
      // creates signature
      $response = http_build_query($resp_array);
    
      // sends the response and waits for success
      $xml = '<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">'.
        base64_encode($response).'</response>';
      send_xml($fp, $xml);
      if (!find_xmpp($fp, 'SUCCESS')) {
        return false;
      }
    
      // finishes auth process
      send_xml($fp, $STREAM_XML);
      if (!find_xmpp($fp,'STREAM:STREAM')) {
        return false;
      }
      if (!find_xmpp($fp, 'STREAM:FEATURES')) {
        return false;
      }
     send_xml($fp, $RESOURCE_XML);
      if (!find_xmpp($fp, 'JID')) {
        return false;
      }
      send_xml($fp, $SESSION_XML);
      if (!find_xmpp($fp, 'SESSION')) {
        return false;
      }
    
      // we made it!
      send_xml($fp, $CLOSE_XML);
      print ("Authentication complete<br>");
      fclose($fp);
    
      return true;
    }
    
    
    
    //Gets access_token with xmpp_login permission
    function get_access_token($app_id, $app_secret, $my_url){ 
    
      $code = $_REQUEST["code"];
    
      if(empty($code)) {
        $dialog_url = "https://www.facebook.com/dialog/oauth?scope=xmpp_login".
         "&client_id=" . $app_id . "&redirect_uri=" . urlencode($my_url) ;
        echo("<script>top.location.href='" . $dialog_url . "'</script>");
      }
       $token_url = "https://graph.facebook.com/oauth/access_token?client_id="
        . $app_id . "&redirect_uri=" . urlencode($my_url) 
        . "&client_secret=" . $app_secret 
        . "&code=" . $code;
       $access_token = file_get_contents($token_url);
        parse_str($access_token, $output);
    
        return($output['access_token']);
    }
    
    function _main() {
      print "Test platform connect for XMPP<br>";
      $app_id='';
      $app_secret='';
      $my_url = "";
      $uid = '';
      $access_token = get_access_token($app_id,$app_secret,$my_url);
      print "access_token: ".$access_token."<br>";
    
      $options = array(
        'uid' => $uid,
        'app_id' => $app_id,
        'server' => 'chat.facebook.com',
       );
    
      // prints options used
      print "server: ".$options['server']."<br>";
      print "uid: ".$options['uid']."<br>";
      print "app id: ".$options['app_id']."<br>";
    
      if (xmpp_connect($options, $access_token)) {
        print "Done<br>";
    
      } else {
        print "An error ocurred<br>";
      }
    
    }
    
    _main();
    
    ?>
    

    I know there is already a question like this here (facebook chat api - php). But it's a pretty old topic and maybe facebook changed something in their chat api.