angular - Stripe - JSON 循环引用

标签 angular stripe-payments

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

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

                    console.log(token.id);

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

然后我使用处理程序创建 token :

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

此处理程序触发测试 checkout.js 弹出窗口,我填写并单击“支付”。成功结束,即按钮显示为绿色。

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

EXCEPTION: TypeError: Converting circular structure to 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,这导致了错误。

此错误不是 fatal error ,付款会成功,但您知道这可能是什么以及如何解决吗?

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

这是full stack trace

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

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

最佳答案

问题出在 checkout.js(去迷你化文件的第 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;
    });
  }
};  

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

关于angular - Stripe - JSON 循环引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36258252/

相关文章:

javascript - 我可以在常规 JS 中监听 AngularJS 中抛出的事件吗(在 Angular 之外?)

javascript - 从firebase数据库表中检索列表中的数据

ios - Stripe 与 iOS 集成

nginx - 将请求重定向到https会中断Stripe Webhook

java - 为什么 stripe 中的 TokenCallback 不起作用?

angular - 如何在 Angular 中创建一个简单的主机组件?

angular - jit_nodeValue_4(...).$any 不是函数 Angular5

php - Wordpress 多站点和 Stripe 订阅?

java - 升级到Java库的最新版本后,Stripe PaymentSource不会扩展

javascript - typescript 'is not a module' 错误