【问题标题】:Stripe - JSON Circular referenceStripe - JSON 循环参考
【发布时间】:2016-03-28 07:57:18
【问题描述】:

我正在使用 Stripe Checkout.js 创建付款。我正在创建一个处理程序,成功时会向服务器发送一个令牌:

let handler = StripeCheckout.configure({
                key: 'my_key',
                image: 'image.png',
                locale: 'auto',
                token: token => {

                    console.log(token.id);

                    // ... send token to server
                }
            });

然后我使用处理程序创建一个令牌:

handler.open({
    name: 'Test',
    description: 'test',
    billingAddress: false,
    currency: 'eur',
    amount: '1200',
});

这个处理程序触发测试 checkout.js 弹出窗口,我填写并点击支付。成功结束,表示按钮显示为绿色。

但是在按钮显示绿色的那一刻和令牌打印到控制台的那一刻(在处理程序成功回调上)之间,会抛出一个错误:

例外:TypeError:将循环结构转换为 JSON

堆栈跟踪的主要部分是这样的:

TypeError: Converting circular structure to JSON
    at Object.stringify (native)
    at Object.stringify (http://localhost:5000/dist/client/bundle.js:46294:29)
    at RPC.sendMessage (https://checkout.stripe.com/checkout.js:1:18068)
    at RPC.sendMessage (https://checkout.stripe.com/checkout.js:1:16180)
    at https://checkout.stripe.com/checkout.js:1:17137
    at RPC.ready (https://checkout.stripe.com/checkout.js:1:17416)
    at RPC.invoke (https://checkout.stripe.com/checkout.js:1:17084)
    at RPC.invoke (https://checkout.stripe.com/checkout.js:1:16180)
    at RPC.processMessage (https://checkout.stripe.com/checkout.js:1:18899)
    at RPC.processMessage (https://checkout.stripe.com/checkout.js:1:16180)

通过检查代码,我们发现问题出在此处:

        RPC.prototype.sendMessage = function(method, args) {
            var err, id, message, _ref;
            if (args == null ) {
                args = []
            }
            id = ++this.rpcID;
            if (typeof args[args.length - 1] === "function") {
                this.callbacks[id] = args.pop()
            }
            message = JSON.stringify({
                method: method,
                args: args,
                id: id
            });

Checkout.js 似乎创建了一个消息对象,恰好有一个循环引用,然后它尝试在其上调用 JSON.stringify,从而导致错误。

这个错误不是致命的,并且付款已经完成,但是您知道这可能是什么以及如何解决它吗?

或者是否有已知的解决方法。

这是full stack trace

请注意,根据MDN docs,在将对象传递给postMessage之前调用stringify可能是不必要的。

postMessage 根据this 使用支持循环引用的序列化机制。

【问题讨论】:

  • 所以你正在对一些引用自身的对象进行字符串化。只需在没有这些引用的情况下对其进行字符串化。 args 是什么?
  • stringify 在条带结帐代码上,而不是在应用程序代码上。我已经向 Stripe 报告了这个问题,但在这里发布了这个问题,因为也许有人知道解决方法。此外,由于 Angular 2 处于测试阶段,您永远不会知道
  • 你试过用 JSON.stringify 调试这段代码吗?
  • 我也有同样的问题,但是付款没有显示在仪表板上。您的交易是否显示在仪表板上?
  • 是的,至少在测试仪表板上是这样。我还没有尝试过真正的交易。我也试过用 Chrome 和 Firefox,但没有用其他浏览器

标签: angular stripe-payments


【解决方案1】:

问题出在 checkout.js 中(de-minified 文件的第 780 行):

message = JSON.stringify({
    method: method, 
    args: args,
    id: id
});

在 Angular2 中运行时,zone.js 已经用区域信息包装了回调。这意味着 args 参数看起来像:

[5, ZoneTask]

而且,ZoneTask 有一个成员 .zone,其中包含一个循环引用:zone -> _zoneDelegate -> zone

JSON.stringify(args[1].zone)
> Uncaught TypeError: Converting circular structure to JSON(…)

因此,从根本上说,Stripe 的 checkout.js 做出了一个非循环假设,当 Zone.js 进行干预时,该假设不再有效。 Stripe 将不得不解决这个问题。

与此同时,您可以使用以下 可怕的 hack。它是如此可怕和如此骇人听闻,以至于我的眼睛都在流血,但是 在不修改 Stripe 代码的情况下,这是我能想到的最好的修复方法。本质上,您将 JSON.stringify 全局替换为一个版本,该版本打破了要求字符串化的对象中的任何 zone->_zoneDelegate->zone 循环:

const _stringify = JSON.stringify;
JSON.stringify = function (value, ...args) {
  if (args.length) {
    return _stringify(value, ...args);
  } else {
    return _stringify(value, function (key, value) {
      if (value && key === 'zone' && value['_zoneDelegate'] 
          && value['_zoneDelegate']['zone'] === value) {
        return undefined;
      }
      return value;
    });
  }
};  

如果您的眼睛现在流血了,我们深表歉意。它有效。

【讨论】:

  • 你的 hack 对我来说就像一个魅力。我只是将它粘贴到我的支付组件中的 ngOnInit 中,并且还不得不忽略来自 Typescript 编译器的“返回 _stringify ...”行中的“提供的参数与调用目标的任何签名不匹配”错误。非常感谢!
  • 在JSON.stringify赋值给const _stringify时,在JSON.stringify前面加上也可以消除错误。
  • 此错误已在 Stripe Checkout 中修复,现在应该可以正常工作,无需解决方法
猜你喜欢
  • 2012-04-01
  • 2013-06-27
  • 1970-01-01
  • 1970-01-01
  • 2014-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多