问题描述
我正在尝试为我的 Flutter 应用程序集成 Braintree 付款。我有一个用于处理 iOS/Android 的插件,并且正在为 Web 编写自定义实现。
我认为这是一个相当简单的解决方案,我使用 Braintree Javascript SDK/Drop in UI (GitHub tutorial) 来使用 HTML 呈现付款屏幕。这部分我开始工作了,但是为了正确处理这些付款,我需要检索 JavaScript 函数的响应 - 特别是付款随机数的字符串。
为此,我使用了一些通道方法和飞镖魔法来调用这个 javascript 函数
async function payment(auth) {
braintree.dropin.create({
authorization: auth,selector: '#dropin-container'
},function (errCreate,instance) {
document.getElementById("submit-button").addEventListener('click',function () {
if(errCreate) {
console.log("Error",errCreate);
return;
}
instance.requestPaymentMethod(function (requestPaymentMethodErr,payload) {
if (requestPaymentMethodErr) {
console.log('Error',requestPaymentMethodErr);
return;
}
return payload.nonce;
});
});
});
}
这个函数似乎在工作,返回数据和支付随机数等等。在我实际渲染小部件的(单独的)dart 文件中,我像这样声明了函数:
// EXTERNAL JAVASCRIPT ==========================================
@JS()
external void initBraintree(auth);
@JS()
external payment(String auth);
这似乎有效,它在按钮单击时调用函数,所以很好。问题是,当我调用这个异步函数时,它返回一个承诺,理论上 dart 不应该知道如何处理这个问题,但幸运的是,他们有一个名为 promisetoFuture 的方法可以处理这个问题。我是这样用的:
Future<BraintreeDropInResult> start(BuildContext context,BraintreeDropInRequest request) async {
// create div with html embedded
String htmlL = """<div id="checkout-message"></div>
<div id="dropin-container"></div>
<button id="submit-button">Submit payment</button>""";
var paymentDiv = html.divelement()..appendHtml(htmlL);
// attach to payment container
ui.platformViewRegistry.registerViewFactory('braintree-container',(int viewId) => paymentDiv);
// call js function
var promise = payment(request.clientToken);
String nonce = await promisetoFuture(promise);
...
但是它只是不起作用。 JavaScript 函数似乎正在返回一个 promise 对象,但是 promisetoFuture 函数从不等待它,每次都立即返回 null。
已经为此工作了一段时间,终于感觉非常接近,但这对我来说是一个真正的刺,所以非常感谢任何帮助!
解决方法
你可以做这样的事情。即创建一个承诺,一旦一切正常——点击按钮——它将用随机数解决。
当然,这仅适用于第一次点击按钮。因为,一旦承诺被解决或拒绝,它就不会再改变它的状态和结果。
async function payment(auth) {
return new Promise((resolve,reject) => {
braintree.dropin.create({
authorization: auth,selector: '#dropin-container'
},(createError,instance) => {
//probably there is no need to attach the eventhandler
//if the was an error
if (createError) {
console.log("Error",createError);
return reject(createError);
}
document.getElementById("submit-button").addEventListener("click",() => {
instance.requestPaymentMethod((rpmError,payload) => {
if (rpmError) {
console.log("Error",rpmError);
return reject(rpmError);
}
resolve(payload.nonce);
});
});
}
);
});
}