Stripe - JSON循环引用

Ang*_*ity 15 stripe-payments angular

我使用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
                }
            });
Run Code Online (Sandbox Code Playgroud)

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

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

这个处理程序触发测试checkout.js弹出窗口,我填写并单击Pay.它成功结束,意味着按钮显示为绿色.

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

EXCEPTION:TypeError:将循环结构转换为JSON

stacktrace的主要部分是:

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)
Run Code Online (Sandbox Code Playgroud)

通过检查代码,我们看到问题在这里:

        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
            });
Run Code Online (Sandbox Code Playgroud)

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

这个错误是非致命的,付款通过,但你知道这可能是什么以及如何解决它?

或者是否有一个已知的解决方法.

这是完整的堆栈跟踪

请注意,根据MDN文档,stringify在传递对象之前调用postMessage 可能不是必需的.

postMessage使用的是,根据支持循环引用一个序列化机制.

Ric*_*ich 13

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

message = JSON.stringify({
    method: method, 
    args: args,
    id: id
});
Run Code Online (Sandbox Code Playgroud)

在Angular2中运行时,zone.js已使用区域信息包装回调.这意味着args参数如下所示:

[5, ZoneTask]

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

JSON.stringify(args[1].zone)
> Uncaught TypeError: Converting circular structure to JSON(…)
Run Code Online (Sandbox Code Playgroud)

因此,从根本上说,Stripe的checkout.js会产生一个非循环性假设,当Zone.js干预时它不再有效.Stripe将不得不解决这个问题.

在此期间,您可以使用以下可怕的黑客攻击.它是如此可怕和如此hacky,它让我的眼睛流血,但它是最好的我可以想出修复它而不修改Stripe的代码.从本质上讲,您全局将JSON.stringify替换为一个版本,该版本会破坏任何区域 - > _ zoneDelegate->区域循环中要求它进行字符串化的对象:

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;
    });
  }
};  
Run Code Online (Sandbox Code Playgroud)

抱歉,如果你的眼睛现在流血了.有用.

  • 当JSON.stringify分配给const _stringify时,也可以通过在JSON.stringify前添加<any>来删除该错误. (3认同)