2016-03-28 7 views
14

Im przy użyciu Stripe Checkout.js do utworzenia płatności. Tworzę obsługi, że na sukces wysyła token do serwera:Stripe - JSON Circular reference

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

        console.log(token.id); 

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

Potem korzystania z obsługi, aby utworzyć token:

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

Ten uchwyt uruchamia okienko checkout.js testowe , które wypełniam i klikam Pay. Kończy się pomyślnie, co oznacza, że ​​przycisk wyświetla się na zielono.

Ale od chwili przycisk na zielono, a moment, że znak jest drukowany na konsoli (na zwrotnego sukcesu handler), zostanie zgłoszony błąd:

EXCEPTION: TypeError: Converting circular structure to JSON

Główną częścią stacktrace jest to:

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) 

sprawdzając kod, widzimy, że problem jest tutaj:

 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 
      }); 

Wygląda na to, że plik Checkout.js tworzy obiekt komunikatu, który ma cykliczne odwołanie, a następnie próbuje wywołać na nim JSON.stringify, co powoduje błąd.

Ten błąd nie jest krytyczny, a płatność przechodzi, ale czy wiesz, co to może być i jak to naprawić?

Czy istnieje znane obejście tego problemu.

to full stack trace

Zauważ, że wywołanie stringify przed przekazaniem obiektu do postMessagemoże nie być konieczne w zależności od MDN docs.

postMessage wykorzystuje mechanizm serializacji obsługujący odwołania kołowe zgodnie z this.

+1

Więc szarpiesz jakiś obiekt, który ma odniesienia do siebie. Uporządkuj go bez tych odniesień. Czym jest "args"? – dfsq

+0

stringify jest w kodzie kasowym, a nie w kodzie aplikacji. Zgłosiłem problem Stripe, ale opublikowałem to tutaj, ponieważ być może ktoś wie o obejściu tego problemu. Również z Angular 2 będąc w wersji beta, nigdy nie wiesz –

+1

Czy próbowałeś debugować ten fragment kodu za pomocą JSON.stringify? – dfsq

Odpowiedz

12

Problemem jest checkout.js (w linii 780 w pliku DE-minified)

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

Podczas działania w Angular2, zone.js jest owinięte zwrotnego z informacjami strefy. Oznacza to, że parametr args wygląda następująco:

[5, ZoneTask]

I ZoneTask ma członkowskim, .zone, który zawiera odwołanie cykliczne:

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

Więc w gruncie paskiem za checkout.js marki założenie o nieokrągłości, które nie jest już ważne, gdy Zone.js się wtrąca. Paski będą musiały to naprawić.

W międzyczasie możesz użyć hackera: horrendous. Jest tak przerażający i tak odurzający, że sprawia, że ​​moje oczy krwawią, ale najlepiej wymyślić, jak to naprawić, bez modyfikacji kodu Stripe'a. Zasadniczo globalnie zastępujesz JSON.stringify z wersji, która łamie każdą strefę -> _> zoneDelegate- cykle stref w obiekcie jest on proszony o stringify:

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; 
    }); 
    } 
}; 

Przeprosiny jeśli twoje oczy są teraz krwawienie. To działa.

+1

Twój hack działał jak urok dla mnie. Właśnie wkleiłem go do ngOnInit w moim komponencie płatniczym, a także musiałem zignorować błąd "dostarczone parametry nie pasują do sygnatury docelowego połączenia" z kompilatora Typescript w linii "return _stringify ...". Wielkie dzięki! –

+3

Błąd można również usunąć, dodając przed JSON.stringify, gdy jest on przypisany do const _stringify. –

+0

Ten błąd został naprawiony w Stripe Checkout i powinien działać teraz, nie ma potrzeby obejścia –