我正在使用Stripe Checkout.js创建付款。我正在创建一个处理程序,成功时会向服务器发送一个令牌:
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弹出窗口,我填写并单击Pay。它成功结束,意味着按钮显示为绿色。
但是,在按钮显示绿色的那一刻,以及将令牌打印到控制台的那一刻(在处理程序成功回调上),会抛出错误:
EXCEPTION:TypeError:将循环结构转换为JSON
stacktrace的主要部分是:
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,这会导致错误。
这个错误是非致命的并且付款通过,但你知道这可能是什么以及如何解决它?
或者是否有已知的解决方法。
请注意,根据MDN docs,在将对象传递给stringify
之前调用postMessage
可能不需要。
postMessage
使用支持根据this的循环引用的序列化机制。
答案 0 :(得分:13)
问题出在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将不得不解决这个问题。
与此同时,您可以使用以下可怕的黑客攻击。它是如此可怕和如此hacky,它让我的眼睛流血,但是 在没有修改Stripe代码的情况下,这是我能想到的最好的解决方法。从本质上讲,您全局将JSON.stringify替换为在要求字符串化的对象中打破任何zone-> _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;
});
}
};
道歉,如果你的眼睛现在流血了。它有效。