如何从注册脚本中读取/解析Signed_Request数据


How to Read/ Parse Data of Signed_Request from Registration Script in Php 5.1.6

我正在尝试实现Facebook注册脚本。

表单正在正常提交,服务器正在接收签名的请求。但是,它不能读取/解析签名的请求。

我使用了注册页面https://developers.facebook.com/docs/plugins/registration/上推荐的脚本(下面的代码),我看到的输出是:

signed_request内容:

我已经验证signed_Request正在被接收。如果我把它传递给:http://developers.facebook.com/tools/echo?signed_request=,我会看到数据。

然而,在我的服务器上,脚本下面什么都没有。

服务器的http不是https和使用php 5.1.6(没有的一些JSON支持)我需要php SDK安装吗?或者json包装器?我已经尝试了jsonwrapper,但没有PHP SDK。

如果你能帮助我解释为什么signed_request不能被读取,我将不胜感激。

下面的代码来自facebook

    <?php
    include ('jsonwrapper/jsonwrapper.php');

    define('FACEBOOK_APP_ID', 'XXX');
    define('FACEBOOK_SECRET', 'XXX');
    function parse_signed_request($signed_request, $secret) {
    list($encoded_sig, $payload) = explode('.', $signed_request, 2); 
  // decode the data
  $sig = base64_url_decode($encoded_sig);
  $data = json_decode(base64_url_decode($payload), true);
  if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
    error_log('Unknown algorithm. Expected HMAC-SHA256');
    return null;
  }
  // check sig
  $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
  if ($sig !== $expected_sig) {
    error_log('Bad Signed JSON signature!');
    return null;
  }
  return $data;
}
function base64_url_decode($input) {
    return base64_decode(strtr($input, '-_', '+/'));
}
if ($_REQUEST) {
  echo '<p>signed_request contents:</p>';
  $response = parse_signed_request($_REQUEST['signed_request'], 
                                   FACEBOOK_SECRET);
  echo '<pre>';
  print_r($response);
  echo '</pre>';
} else {
  echo '$_REQUEST is empty';
}
?> 

输出

" signed_request内容:"

如果我添加:print_r ($ _REQUEST);对于脚本,我确实看到了请求,但无法解析它

您不需要PHP SDK。它可能使做这个和其他各种事情更容易,但如果你想自己做解码,这是不必要的。

你确定你实际上有一个json_decode函数吗?我不认为它通常是jsonwrapper.php的一部分,所以我怀疑你的脚本在那个函数调用上崩溃了。您可以使用以下函数作为替代,只需将调用更改为usr_json_decode并在脚本底部包含以下内容:

function usr_json_decode($json, $assoc=FALSE, $limit=512, $n=0, $state=0, $waitfor=0)
{
  $val=NULL;
  static $lang_eq = array("true" => TRUE, "false" => FALSE, "null" => NULL);
  static $str_eq = array("n"=>"'012", "r"=>"'015", "''"=>"''", '"'=>'"', "f"=>"'f", "b"=>"'b", "t"=>"'t", "/"=>"/");
  for (; $n<strlen($json); /*n*/)
    {
    $c=$json[$n];
    if ($state==='"')
      {
      if ($c=='''')
        {
        $c=$json[++$n];
        if (isset($str_eq[$c]))
          $val.=$str_eq[$c];
        else if ($c=='u')
          {
          $hex=hexdec(substr($json, $n+1, 4));
          $n+=4;
          if ($hex<0x80) $val .= chr($hex);
          else if ($hex<0x800) $val.=chr(0xC0+$hex>>6).chr(0x80+$hex&63);
          else if ($hex<=0xFFFF) $val.=chr(0xE0+$hex>>12).chr(0x80+($hex>>6)&63).chr(0x80+$hex&63);
          }
        else
          $val.="''".$c;
        }
      else if ($c=='"') $state=0;
      else $val.=$c;
      }
    else if ($waitfor && (strpos($waitfor, $c)!==false))
      return array($val, $n);
    else if ($state===']')
      {
      list($v, $n)=usr_json_decode($json, $assoc, $limit, $n, 0, ",]");
      $val[]=$v;
      if ($json[$n]=="]") return array($val, $n);
      }
    else
      {
      if (preg_match("/'s/", $c)) { }
      else if ($c=='"') $state='"';
      else if ($c=="{")
        {
        list($val, $n)=usr_json_decode($json, $assoc, $limit-1, $n+1, '}', "}");
        if ($val && $n) $val=$assoc?(array)$val:(object)$val;
        }
      else if ($c=="[")
        list($val, $n)=usr_json_decode($json, $assoc, $limit-1, $n+1, ']', "]");
      elseif (($c=="/") && ($json[$n+1]=="*"))
        ($n=strpos($json, "*/", $n+1)) or ($n=strlen($json));
      elseif (preg_match("#^(-?'d+(?:'.'d+)?)(?:[eE]([-+]?'d+))?#", substr($json, $n), $uu))
        {
        $val = $uu[1];
        $n+=strlen($uu[0])-1;
        if (strpos($val, ".")) $val=(float)$val;
        else if ($val[0]=="0") $val=octdec($val);
        else $val=(int)$val;
        if (isset($uu[2])) $val*=pow(10, (int)$uu[2]);
        }
      else if (preg_match("#^(true|false|null)'b#", substr($json, $n), $uu))
        {
        $val=$lang_eq[$uu[1]];
        $n+=strlen($uu[1])-1;
        }
      else
        {
        return $waitfor ? array(NULL, 1<<30) : NULL;
        }
      }
    if ($n===NULL) return NULL;
    $n++;
    }
  return ($val);
}

顺便说一句,使用错误日志应该很容易跟踪,打开额外的调试并在必要时添加一些echovar_dump语句。

我也遇到过类似的情况,签名请求返回空白。在您的应用程序中,请确保首先从http://developers.facebook.com/docs/reference/php/下载并包含php sdk。下一步添加

 require_once("facebook.php");

放到你的脚本的顶部,或者你上传的地方。在你的应用设置中,在Facebook中,确保你的应用url中是否有www。例如:在应用程序中,你让它指向example.com/index.php?tab=test,但当你把它放在浏览器中,它总是出现www,example.com/index.php?tab=test。不包括www会把它搞砸的。

EDIT - WORKED FOR ME

    <?php
    #error_reporting(E_ALL);
        include ('{{PATH TO facebook.php}}');

        $appapikey = 'xxxx';
        $appsecret = 'xxxx';
        $facebook = new Facebook($appapikey, $appsecret);
    function parsePageSignedRequest() {
        if (isset($_REQUEST['signed_request'])) {
          $encoded_sig = null;
          $payload = null;
          list($encoded_sig, $payload) = explode('.', $_REQUEST['signed_request'], 2);
          $sig = base64_decode(strtr($encoded_sig, '-_', '+/'));
          $data = json_decode(base64_decode(strtr($payload, '-_', '+/'), true));
          return $data;
        }
        return false;
      }
      function parse_signed_request($signed_request, $secret) {
          list($encoded_sig, $payload) = explode('.', $signed_request, 2); 
          // decode the data
          $sig = base64_url_decode($encoded_sig);
          $data = json_decode(base64_url_decode($payload), true);
          if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
            error_log('Unknown algorithm. Expected HMAC-SHA256');
            return null;
          }
          // check sig
          $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
          if ($sig !== $expected_sig) {
            error_log('Bad Signed JSON signature!');
            return null;
          }
          return $data;
        }
        function base64_url_decode($input) {
          return base64_decode(strtr($input, '-_', '+/'));
        }
    if (isset($_REQUEST['signed_request'])) {
      echo '<p>signed_request contents:</p>';
      $response = parse_signed_request($_REQUEST['signed_request'], 
                                       $appsecret);
      echo '<pre>';
      print_r($response);
      echo '</pre>';
    } else {
      echo '$_REQUEST is empty';
    }
    ?> 
    <iframe src="https://www.facebook.com/plugins/registration.php?
                 client_id=134219456661289&
                 redirect_uri={{YOUR SITE URL ENCODED}}&fields=name,birthday,gender,location,email"
            scrolling="auto"
            frameborder="no"
            style="border:none"
            allowTransparency="true"
            width="100%"
            height="330">
    </iframe>
      function getDefinedVars($varList, $excludeList)
      {
          $temp1 = array_values(array_diff(array_keys($varList), $excludeList));
          $temp2 = array();
          while (list($key, $value) = each($temp1)) {
              global $$value;
              $temp2[$value] = $$value;
          }
          return $temp2;
      }

查看所有SYSTEM变量(除了globals/files/cookies/post/get)以确保已签名请求被传递,您可以使用以下代码片段

      /**
       * @desc   holds the variable that are to be excluded from the list.
       *         Add or drop new elements as per your preference.
       * @var    array
       */
      $excludeList = array('GLOBALS', '_FILES', '_COOKIE', '_POST', '_GET', 'excludeList');
      //some dummy variables; add your own or include a file.
      $firstName = 'kailash';
      $lastName = 'Badu';
      $test = array('Pratistha', 'sanu', 'fuchhi');
      //get all variables defined in current scope
      $varList = get_defined_vars();
      //Time to call the function
      print "<pre>";
      print_r(getDefinedVars($varList, $excludeList));
      print "</pre>";