在32位服务器上的Facebook支付平台64bit order_id

时间:2013-01-17 19:06:52

标签: php facebook callback 32bit-64bit payment

由于我似乎无法解决的问题,我目前正遇到一堵巨大的墙。

问题在于,当您通过Facebook支付平台(Facebook javascript sdk)发出付款时,它会将数据发送到您的回调页面,该页面应该在后台处理付款。

这一切都很不错,但有一个问题:facebook使用的订单ID是64位ID,而我的服务器是32位服务器,因此当它被保存到回调中的变量时,它会丢失ID的精度页。这最终导致最终无法获得正确的order_ID,因为它无法保存ID。

此论坛的几个页面已对此问题进行了描述,例如:

facebook credit callback, order_id changes format changes after moving to a new server

PHP: Converting a 64bit integer to string

然而,在这两个页面上都没有解决问题的方法,我似乎无法解决这个问题。 我试图将facebook发送到我的回调页面的json数据转换为字符串数据而不是带有整数的数组(这发生在facebook提供的基本代码中),但我无法让它工作。

看到其他人已经克服了这个问题(无需将所有内容迁移到64位服务器),我想知道如何。

有人能够对这个问题有所了解吗?

编辑: 我已经尝试过转换为字符串,这是一个被调用来解码json数据的标准facebook代码(由facebook提供的代码):

$request = parse_signed_request($_POST['signed_request'], $app_secret);

这会调用函数parse_signed_request,它执行:

function parse_signed_request($signed_request, $secret) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);

$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;
}

此函数解码来自facebook的加密json数据(使用app secret),并将json数据解码为PHP数组。

该函数使用以下函数(确切地说:

function base64_url_decode($input) {
  return base64_decode(strtr($input, '-_', '+/'));
}

现在,上面的代码会导致订单ID无法正确保存,并且会失去其精度,从而导致ID如下:4.8567130814993E + 14

我试图使用以下函数以某种方式将json数据解码为字符串(因此64位整数ID不会失去其精度),但无济于事:

  function largeint($rawjson) {
    $rawjson = substr($rawjson, 1, -1);
    $rawjson = explode(',' , $rawjson);
    array_walk($rawjson, 'strfun');
    $rawjson = implode(',', $rawjson);
    $rawjson = '{' . $rawjson . '}';
    $json = json_decode($rawjson);
    return $json;
  }


function strfun(&$entry, $key) {
    $data = explode(':', $entry);
    if (FALSE === strpos($data[1], '"')) {
    $data[1] = '"' . $data[1] . '"';
    $entry = implode(':', $data);
    }
}

编辑(Eugenes回答):

如果我在使用json_decode使其成为php变量之前尝试修改JSON数据,我应该使用preg_replace函数吗? 以下是发送到回调页面以启动付款流程的初始JSON数据的示例。 在这里你已经可以看到问题所在(这是在使用json_decode之后,id和其他数据失去了它们的精度)。 ID被修改为不反映任何实际数据。 如果您比较顶部的买方ID和底部的用户ID,您可以看到精度丢失。

Array
(
[algorithm] => HMAC-SHA256
[credits] => Array
    (
        [buyer] => 1.0055555551318E+14
        [receiver] => 1.0055555551318E+14
        [order_id] => 5.2555555501665E+14
        [order_info] => {"item_id":"77"}
        [test_mode] => 1
    )

[expires] => 1358456400
[issued_at] => 1358452270
[oauth_token] => AAAH4s2ZCCEMkBAPiGSNsmj98HNdTandalotmoredata
[user] => Array
    (
        [country] => nl
        [locale] => nl_NL
        [age] => Array
            (
                [min] => 21
            )

    )

[user_id] => 100555555513181
)

编辑#3:

我已尝试以下操作使JSON数据中的所有整数看作字符串,但这会导致facebook平台出错。然而它确实将整数更改为字符串,因此我不会失去精度(太糟糕了,现在没有其他工作xD)

preg_replace('/([^\\\])":([0-9]{10,})(,|})/', '$1":"$2"$3', $a)

1 个答案:

答案 0 :(得分:1)

您运行的是哪个版本的PHP?

如果您运行的是支持JSON“JSON_BIGINT_AS_STRING”选项的PHP版本,那么这可能就是您的答案。您可能必须在使用json_decode添加该选项的任何地方修改其库。见http://php.net/manual/en/function.json-decode.php

如果您的PHP版本不支持JSON_BIGINT_AS_STRING,那么您的选项仅限于:

hacky选项:对JSON字符串执行某种正则表达式操作,因为它从FB API返回并用双引号包装那么大的内联,这样它们就可以解码为字符串而不是大的int。

理想选择:咬紧牙关并迁移到64位环境。从长远来看,它可以帮助您避免许多麻烦。