为什么在 Ajax 请求后 Google Pay 无法从 iPhone Safary 运行?

问题描述 投票:0回答:2

我尝试在网站上添加 Googla Pay 按钮。我遵循 Google Pay 实施教程 (https://developers.google.com/pay/api/web/guides/tutorial)。

有代码:

var paymentsClient = getGooglePaymentsClient();
paymentsClient.isReadyToPay(getGoogleIsReadyToPayRequest())
    .then(function(response) {
        //...
    })
    .catch(function(err) {
        //...
    });

在调用上述代码之前,我需要从服务器端获取一些数据,以便执行 http post 请求。在我的发布请求的成功处理程序中,我调用上面的代码。它在我的 Android 浏览器和笔记本电脑浏览器中运行良好。但它在 Safari 上不起作用。我收到“意外的开发人员错误,请稍后重试”错误。如果我在没有 ajax 请求的情况下调用它,它也可以在 Safari 中运行。有人可以建议解决方案吗?

iphone mobile-safari google-pay
2个回答
3
投票

感谢您提供 jsfiddle。

它不起作用的原因是,当您在 Safari 中调用

loadPaymentData
时,Google Pay 会尝试打开一个弹出窗口。当单击事件(用户启动的操作)触发新窗口时,弹出窗口将按预期打开。当它被非用户启动的操作触发时,Google Pay 会加载到同一窗口中,最终导致它失败。

看起来当您在点击处理程序中发出 ajax 请求然后调用

loadPaymentData
时,Safari 会认为这是一个非用户启动的操作。

在 Safari 中查看以下示例

const ajaxButton = document.getElementById('ajax');
const nojaxButton = document.getElementById('nojax');

ajaxButton.addEventListener('click', event => {
  $.get('/echo/json/', () => {
    window.open('about:blank');
  });
});

nojaxButton.addEventListener('click', event => {
  window.open('about:blank');
});

我建议避免在

loadPaymentData
之前对按钮单击事件进行任何 http 调用。如果您可以在单击按钮之前获取数据,那么就这样做。

出于兴趣,您要获取什么样的数据?


0
投票

我不知道3年前是什么情况,但现在Safari默认阻止弹出窗口,但不会阻止用户交互后打开的弹出窗口,例如点击并在时间内弹出打开(

window.open()
)< 1 second. Within that 1 second you can do anything - synchronous and asynchronous code (whatever callback, setTimeout, Promise.then(), async/await.

在我们的例子中使用 1 秒。实际上,我们在用户点击 Google Pay 按钮之前提前迁移了 JS Google Pay 脚本加载,并且我们对后面支付处理器服务器上的 eur 服务器的 AJAX 请求始终需要不到 1 秒的时间。

请注意非常有趣的事情,以避免 Google Pay 无法工作。当您在 ajax 结果中的代码中并想要调用 PaymentsClient.loadPaymentData() 时,您必须以异步方式调用它,例如

setTimeout(() => { PaymentsClient.loadPaymentData(...) }, 1)
或前置 noop,例如
await sleepInMs(1)
。我不知道为什么需要它,但它确实有效。如果没有这个黑客,带有谷歌付款单的弹出窗口将被阻止,我们的页面将被重定向到 pay.goole.com,并出现错误
OR_BIBED_15
,这可能意味着弹出窗口被阻止 - 但我根本找不到错误代码定义。

© www.soinside.com 2019 - 2024. All rights reserved.