Im using Stripe Checkout.js to create a payment. I'm creating a handler, that on success sends a token to the server:
let handler = StripeCheckout.configure({
key: 'my_key',
image: 'image.png',
locale: 'auto',
token: token => {
console.log(token.id);
// ... send token to server
}
});
Then I use the handler to create a token:
handler.open({
name: 'Test',
description: 'test',
billingAddress: false,
currency: 'eur',
amount: '1200',
});
This handler triggers the test checkout.js popup, that I fill in and click Pay. It ends successfully, meaning the button displays green.
But between the moment the button shows green, and the moment that the token is printed to the console (on the handler success callback), an error is thrown:
EXCEPTION: TypeError: Converting circular structure to JSON
The main part of the stacktrace is this:
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)
By inspecting the code, we see the issue is here:
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
});
It seems that Checkout.js creates a message object, that happens to have a circular reference, then it attempts to call JSON.stringify on it, which causes the error.
This error is non fatal and the payment goes through, but do you know what this could be and how to fix it?
Or is there a known workaround.
this is the full stack trace
Note that calling stringify
before passing an object to postMessage
might not be necessary according to the MDN docs.
postMessage
uses a serialization mechanism that supports circular references according to this.
The problem is in checkout.js (at line 780 in the de-minified file):
message = JSON.stringify({
method: method,
args: args,
id: id
});
When running in Angular2, zone.js has wrapped the callback with zone information. This means that the args parameter looks like:
[5, ZoneTask]
And, ZoneTask has a member, .zone, which contains a circular reference: zone -> _zoneDelegate -> zone
JSON.stringify(args[1].zone)
> Uncaught TypeError: Converting circular structure to JSON(…)
So, fundamentally Stripe's checkout.js makes a non-circularity assumption which is no longer valid when Zone.js has been meddling. Stripe are going to have to fix this.
In the meantime you can use the following horrendous hack. It's so horrendous and so hacky that it makes my eyes bleed, but it's the best I could come up with to fix it without modifying Stripe's code. Essentially, you globally replace JSON.stringify with a version that breaks any zone->_zoneDelegate->zone cycles in the object it is being asked to 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;
});
}
};
Apologies if your eyes are now bleeding. It works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With