2016-03-28 104 views
14

Im使用Stripe Checkout.js创建付款。我创建一个处理程序,即在成功将令牌发送到服务器:Stripe - JSON循环参考

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弹出,我填写并点击付款。它结束成功,意味着按钮显示绿色。

但当下的按钮显示为绿色,而此刻令牌被打印到控制台(在处理器成功回调),抛出一个错误:

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,这会导致错误。

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

还是有一个已知的解决方法。

这是full stack trace

注意,传递一个对象postMessage之前调用stringify可能不按MDN docs是必要的。

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

+1

所以你正在对一些对自身有引用的对象进行字符串化。只是没有这些引用就把它串起来。什么是'args'? – dfsq

+0

stringify在分条签出代码上,而不是在应用程序代码上。我已经向Stripe报告了这个问题,但是在这里发布了这个消息,也许有人知道解决方法。同样,在Angular 2处于Beta版时,你永远不会知道 –

+1

你是否尝试用JSON.stringify调试这段代码? – dfsq

回答

12

的问题是在checkout.js(在去精缩文件线780):

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

当Angular2运行,zone.js已包裹着区域信息的回调。这意味着,args参数是这样的:

[5, ZoneTask]

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

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

所以,从根本上条纹的checkout.js品牌一个非循环的假设,当Zone.js一直在干预时不再有效。条纹将不得不解决这个问题。

在此期间,您可以使用以下可怕的黑客。这是如此可怕,如此hacky,它使我的眼睛流血,但 这是最好的,我可以拿出来修复它,而无需修改Stripe的代码。基本上,你全局替换JSON。与打破任何区域版本字符串化 - > _ 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; 
    }); 
    } 
}; 

道歉,如果你的眼睛现在出血。有用。

+1

你的黑客对我来说就像是一种魅力。我只是将它粘贴到我的付款组件中的ngOnInit中,并且还必须忽略'return _stringify ...'行上的Typescript编译器的'提供的参数不匹配'调用目标的任何签名'错误'。非常感谢! –

+3

错误也可以通过在JSON.stringify前面添加来解决,当它被分配给const _stringify时。 –

+0

此错误已在Stripe Checkout中解决,现在应该可以工作,不需要解决方法 –