Facebook XMPP 聊天 API 发送消息 PHP

8

我目前正在研究Facebook聊天API。我想通过一个应用程序向我的Facebook联系人发送聊天消息。

使用Facebook提供的示例,我能够连接到Facebook聊天服务器。但这更像是一个试错过程。我只能模糊地理解请求和响应是如何发送和接收的。如果有人能够提供进一步的说明或进一步阅读资料,那将非常好。

我的实际问题是:在连接到聊天服务器后,我该如何发送消息?

<?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();

?>

我知道这里已经有一个类似的问题了 (facebook chat api - php),但这是一个相当古老的话题,也许Facebook在他们的聊天API中进行了一些更改。

2个回答

11
你应该使用套接字发送命令,并将你的消息包含在其中。通用的消息格式为:
<message from="-sender_ID@chat.facebook.com" to="-receiver_ID@chat.facebook.com">
    <body>message body</body>
</message>
在发表评论 "we made it!" 之前,插入使用您的消息模板调用send_xml函数。
send_xml($fp, $MESSAGE);
if (!find_xmpp($fp, 'BODY')) {
    return false;
}

这个答案对我很有帮助。接下来我需要解决的问题是性能...我的脚本大约需要1分15秒才能执行(建立连接,发送消息,关闭连接)。我从FB示例代码开始,就像OP在他们的问题中包含的那样。我该怎么做才能加快速度?有什么想法吗? - John Erck
你是怎么知道你发布的消息格式的?除了这个SO帖子之外,它在其他地方有在线文档吗? - John Erck

4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接