2016-03-28 91 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中解決,現在應該可以工作,不需要解決方法 –