【问题标题】:Facebook payment platform 64bit order_id on 32bit serverFacebook 支付平台 32 位服务器上的 64 位 order_id
【发布时间】:2013-01-17 19:06:52
【问题描述】:

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

问题是,当您通过 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 数据(使用应用程序密钥),并应将 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);
    }
}

编辑(尤金斯回答):

如果我在使用 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)

【问题讨论】:

  • 是的,您需要使用字符串。向我们展示您尝试过但没有奏效的方法 - 发布一些代码。
  • 我已经发布了很多信息来回应你的评论和尤金的评论。我尝试了几件事,但又一次没有成功。我还向我的托管服务提供商邮寄了有关将系统升级到 64 位(或 php 5.4)的可能性。
  • 因此,因为您正在更改 JSON 对象,您的 HMAC 哈希签名将不匹配。作为策略的额外牺牲,您可能不得不绕过该安全功能。 EG:你必须修改库并绕过哈希签名检查。

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


【解决方案1】:

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

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

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

hacky 选项:对从 FB API 返回的 JSON 字符串执行某种正则表达式操作,并将大整数用双引号括起来,以便它们解码为字符串而不是大整数。

理想的选择:硬着头皮迁移到 64 位环境。从长远来看,它会让你免于很多麻烦。

【讨论】:

  • 当前使用的PHP版本是5.2.17。我曾尝试在 json_decode 中使用 JSON_BIGINT_AS_STRING 参数,但结果为空(因此我猜它不起作用)。我通过将代码更改为: $data = json_decode(base64_url_decode($payload), true, 512, JSON_BIGINT_AS_STRING);
  • 我很确定 5.2 不会支持该功能。实际上,我认为您需要使用 5.4 才能正常工作。
  • 有没有办法让它与 php 5.2 一起工作?我现在真的没有升级 php 或服务器的选项。我假设人们已经在 32 位安装上使用了一些解决方法。是否可以克隆 JSON 结果并从该结果中获取数据,同时保留原始结果?或者克隆是否会自动转换为 32 位?
  • 在 PHP 5.2 的 32 位系统上绕过它的唯一方法是弄乱 JSON 对象,使其反序列化为字符串而不是 int - 这会产生其他问题正如你所遇到的,通常不是我认为的好习惯。您在这方面处于困境和艰难的境地...呼吁升级服务器或升级 php 安装的权力。
  • 我终于设法解决了这个问题。我的托管服务提供商只给了我升级到 php 5.3 的选项,这只能部分解决问题。因此,我刚刚克隆了已签名的请求并在我的数据库中使用了该订单 ID(使用 preg_replace 以从订单 ID 中获取字符串数据)。原始签名请求因此未被触及,因此与哈希匹配。它终于似乎起作用了。然而,从长远来看,我将检查我的 64 位服务器安装选项。非常感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2016-11-30
  • 2011-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-10
相关资源
最近更新 更多