WordPress 解决区块结算页Afterpay支付方式加载过久的问题

Afterpay(Stripe 提供的本地支付方式之一)或者Afterpay提供的支付插件

结算页上:

  • PayPal / 信用卡 先显示
  • Afterpay 总是最后才显示(而且有时 Firefox 慢网速下直接加载失败)

为什么会这样

  1. Afterpay 并不是 WooCommerce 内置的支付网关
    • 它依赖 Stripe 的 Payment Request Button / Payment Element 或额外的 Stripe.js 动态加载
    • 插件会先加载基础网关(Credit Card、PayPal),等 Stripe SDK 初始化完,再去异步请求 Afterpay 的可用性。
  2. 可用性检测机制
    • Stripe 必须根据结算国家、货币、订单总额,动态判断 Afterpay 是否可用。
    • 所以它不像信用卡一样“固定出现”,而是延迟插入到结算方式列表。
    • 如果网络慢,或 Stripe JS 脚本未能正确返回,就会导致 加载失败 / 不显示
  3. 浏览器差异
    • Firefox 对 延迟加载的第三方 iframe/script 更严格,网络慢时更容易出现 timeout。
    • Chrome/Safari 通常会等更久,所以表现不同。

✅ 方案思考

支付逻辑和 UI 分离
在 WooCommerce + Stripe 插件中:

  • 「支付方式标题(label / logo)」只是前端展示。
  • 真正的支付功能依赖的是: <input type="radio" name="payment_method" value="stripe_afterpay" /> 以及 JS 初始化时的 payment_method_stripe_afterpay 绑定。

✅ 即使图标没加载,radio 仍然存在 → 用户仍然可以选择 Afterpay。

Stripe SDK 控制的是支付表单,不是 logo

  • 卡片支付、Afterpay、Klarna 等的核心交互(卡号输入、跳转 Afterpay 授权)都由 Stripe.js 管理。
  • 图标(SVG/logo)只是一个小装饰,不参与 SDK 初始化。

最坏情况:SVG 失败

  • 页面上只是显示“Afterpay”文字(因为我们手动加了 <span class="payment-label-text">Afterpay</span>)。
  • 客户依然可以点击选择并提交订单。

解决方案

/**
 * afterpay-fallback.js
 * WooCommerce Blocks - Afterpay fallback (仅限 label 部分)
 */
(function () {
    "use strict";

    const LOCAL_LOGO = "/wp-content/themes/your-theme/assets/images/afterpay-logo.svg";

    // 检查 square-placement 是否渲染成功
    function isSquarePlacementOk(el) {
        return el && el.offsetWidth > 0 && el.offsetHeight > 0;
    }

    // 替换 label 内的 square-placement
    function replaceWithLocalLogo(el) {
        if (!el) return;

        const img = document.createElement("img");
        img.src = LOCAL_LOGO;
        img.alt = "Afterpay";
        img.className = "afterpay-fallback-logo";

        // 只替换掉 label 内的 square-placement
        el.replaceWith(img);
    }

    // 只处理支付方式 label,每个网站的class不一样,自己替换,不影响 payment_box
    function handleAfterpayFallback() {
        const labels = document.querySelectorAll(
            'label.wc-block-components-radio-control__option span.wc-block-components-radio-control__label square-placement[data-mpid]'
        );
        labels.forEach((el) => {
            if (!isSquarePlacementOk(el)) {
                replaceWithLocalLogo(el);
            }
        });
    }

    // 初次执行
    document.addEventListener("DOMContentLoaded", handleAfterpayFallback);

    // 监听 React 重新渲染
    const observer = new MutationObserver(() => {
        handleAfterpayFallback();
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true,
    });
})();

📂 资源结构

your-theme/
 └── assets/
      ├── js/
      │    └── afterpay-fallback.js
      └── images/
           └── afterpay-logo.svg


📜 functions.php 挂载

add_action( 'enqueue_block_assets', function() {
    if ( function_exists( 'is_checkout' ) && is_checkout() ) {
        wp_enqueue_script(
            'custom-afterpay-fallback',
            get_stylesheet_directory_uri() . '/assets/js/afterpay-fallback.js',
            [ 'wc-blocks-registry' ],
            '1.0',
            true
        );
    }
});

只替换支付方式 label 里的 <square-placement>

不动 payment box 里的 instalment 说明内容(那部分是 Afterpay 脚本在 box 内渲染的)

相关文章

0 0 投票数
文章评分
订阅评论
提醒
0 评论
最旧
最新 最多投票
内联反馈
查看所有评论