Доступен — Локальные цифровые продукты
HCA · Studio
TR — Контакты ↗
Заметка 12 · WooCommerce

В настройках есть, при оформлении — нет

Плагин активен, настройки сохранены, ошибок нет даже в тестовом режиме — но покупатель не видит способ оплаты на странице оформления. Причина обычно не в плагине, а в типе страницы оформления заказа.

Платформа
WooCommerce 8.3+
Язык
PHP + JS
Симптом
Способа оплаты нет
Короткий ответ

Начиная с WooCommerce 8.3 новые магазины получают блочную страницу оформления заказа, которая выводит способы оплаты в браузере через React. Блочное оформление не показывает автоматически классические шлюзы, унаследованные от WC_Payment_Gateway: каждый способ нужно дополнительно зарегистрировать классом AbstractPaymentMethodType на хуке woocommerce_blocks_payment_method_type_registration и вызовом registerPaymentMethod в JavaScript. Без регистрации ошибки нет — способ просто не отображается. Поскольку тот же плагин работает на классической странице с шорткодом [woocommerce_checkout], проблему легко не заметить.

Симптом

В разделе WooCommerce → Настройки → Платежи способ оплаты включён. Настройки сохранены, в журнале ошибок пусто. Но на странице оформления заказа видны только банковский перевод или оплата при получении — вашего шлюза нет.

Именно с этим мы столкнулись при проверке интеграции виртуального POS банка QNB для Castor Coffee: в одной мультисайт-установке розничный магазин использовал классическую страницу оформления с шорткодом, а оптовый — блочную. Код плагина был верным, расчёт хеша совпадал с тем, что ожидает банк, — но на оптовом сайте способ оплаты не появился бы никогда, даже после заполнения настроек.

Какая страница оформления?

Первый вопрос — не о плагине, а о странице. Посмотрите содержимое страницы оформления заказа:

wp post get $(wp option get woocommerce_checkout_page_id) --field=post_content | head -c 200
  • Начинается с <!-- wp:woocommerce/checkout --> — блочное оформление
  • Содержит [woocommerce_checkout] — классическое оформление

В мультисайте проверяйте каждый сайт отдельно: сайты, созданные в разное время, могут иметь разные типы страницы оформления.

Почему способа нет

Классическая страница оформления формируется на сервере в PHP: WooCommerce перебирает доступные шлюзы и выводит результат payment_fields() каждого. Блочная страница — это приложение на React, работающее в браузере и получающее данные корзины и заказа через Store API. Чтобы показать способ оплаты, ей нужно описание, зарегистрированное на стороне JavaScript.

WooCommerce не выводит это описание из классического шлюза. Итог: шлюз зарегистрирован на сервере, is_available() возвращает true, а блочная страница о нём ничего не знает.

Регистрация в PHP

Сначала пишется класс, который представляет шлюз блочной стороне. Значение $name должно в точности совпадать с id шлюза:

use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;

final class My_Gateway_Blocks extends AbstractPaymentMethodType {
    protected $name = 'my_gateway';   // то же, что WC_Payment_Gateway::$id

    public function initialize() {
        $this->settings = get_option( 'woocommerce_my_gateway_settings', array() );
    }

    public function is_active() {
        $gateways = WC()->payment_gateways()->payment_gateways();
        return isset( $gateways[ $this->name ] ) && $gateways[ $this->name ]->is_available();
    }

    public function get_payment_method_script_handles() {
        wp_register_script( 'my-gateway-blocks', plugins_url( 'assets/blocks.js', __FILE__ ),
            array( 'wc-blocks-registry', 'wc-settings', 'wp-element', 'wp-html-entities' ), '1.0', true );
        return array( 'my-gateway-blocks' );
    }

    public function get_payment_method_data() {
        return array( 'title' => 'Банковская карта', 'supports' => array( 'products' ) );
    }
}

add_action( 'woocommerce_blocks_payment_method_type_registration', function ( $registry ) {
    $registry->register( new My_Gateway_Blocks() );
} );

Важно использовать внутри is_active() собственное решение шлюза is_available(): при отсутствии учётных данных или неподдерживаемой валюте способ скрыт и на блочной странице, и оба типа оформления подчиняются одному правилу.

Также объявите совместимость с блоками в главном файле плагина, иначе редактор может пометить плагин как несовместимый:

add_action( 'before_woocommerce_init', function () {
    \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'cart_checkout_blocks', __FILE__, true );
} );

Регистрация в JavaScript

Данные из get_payment_method_data() доступны в браузере по ключу <name>_data. Минимальная регистрация без сборки:

( function () {
    var settings = window.wc.wcSettings.getSetting( 'my_gateway_data', {} );
    var el = window.wp.element.createElement;
    var label = settings.title || 'Банковская карта';

    window.wc.wcBlocksRegistry.registerPaymentMethod( {
        name: 'my_gateway',                 // то же, что $name в PHP
        label: el( 'span', null, label ),
        ariaLabel: label,
        content: el( 'p', null, 'Вы будете перенаправлены на защищённую страницу оплаты.' ),
        edit: el( 'p', null, 'Вы будете перенаправлены на защищённую страницу оплаты.' ),
        canMakePayment: function () { return true; },
        supports: { features: settings.supports || [ 'products' ] }
    } );
} )();

Шлюзам, которые перенаправляют покупателя на страницу 3D Secure банка, больше ничего не нужно: когда process_payment() возвращает адрес redirect, блочная страница отправляет покупателя туда. Шлюзам, принимающим данные карты на вашей странице, дополнительно нужно событие onPaymentSetup, чтобы передать платёжные данные в Store API.

Тихие ловушки

Если после регистрации способ всё ещё не виден, проверьте по порядку. Ни одна из причин не выдаёт видимой ошибки:

  • Несовпадение имён: id шлюза, $name в PHP и name в JavaScript должны совпадать
  • Отложенный скрипт: если плагин ускорения откладывает скрипты, регистрация выполняется до появления wc.wcBlocksRegistry или не выполняется вовсе — исключите страницу оформления из оптимизации
  • Нет зависимости: без wc-blocks-registry в списке зависимостей в консоли появится wc is not defined
  • is_active() возвращает false: незаполненные настройки, неподдерживаемая валюта или ошибка в условии
  • Кеш: кеш страниц может отдавать старый список скриптов; очистите кеш страницы оформления после изменений

Проверка

Регистрацию на стороне сервера можно проверить через WP-CLI:

wp eval '
$r = Automattic\WooCommerce\Blocks\Package::container()
      ->get( Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry::class );
do_action( "woocommerce_blocks_payment_method_type_registration", $r );
echo implode( ", ", array_keys( $r->get_all_registered() ) );'

Если имени вашего способа нет в списке, проблема в регистрации PHP. Если оно есть, но способ не виден, проверьте в браузере загрузку скрипта и ошибки в консоли, а затем — решение is_active().

Итог

Блочное оформление заказа — отдельная дверь для классических платёжных шлюзов, и открывается она только регистрацией. Диагностика начинается с одной команды: страница оформления блочная или с шорткодом? Если блочная — напишите для шлюза класс AbstractPaymentMethodType и вызов registerPaymentMethod, держите имя одинаковым во всех трёх местах и не откладывайте скрипт. Способ оплаты, который выглядит готовым принимать платежи, но не виден покупателям, — одна из самых дорогих ошибок: никто не жалуется, продажи просто не происходят.

Быстрая справка
Диагностика
Содержимое wp:woocommerce/checkout — блочное, [woocommerce_checkout] — классическое
Причина
Блочное оформление не показывает классические шлюзы автоматически
PHP
AbstractPaymentMethodType + woocommerce_blocks_payment_method_type_registration
JS
wc.wcBlocksRegistry.registerPaymentMethod()
Имя
id шлюза = $name в PHP = name в JS
Зависимости
wc-blocks-registry, wc-settings, wp-element
Совместимость
declare_compatibility( 'cart_checkout_blocks', … )
Ловушка
Отложенный плагином ускорения скрипт тихо ломает регистрацию
Частые вопросы

О блочном оформлении.

Способ оплаты включён в настройках, но не появляется при оформлении заказа. Почему?

Чаще всего потому, что страница оформления блочная. С WooCommerce 8.3 новые магазины получают блочное оформление, которое не показывает классические платёжные шлюзы автоматически. Шлюз нужно дополнительно зарегистрировать классом AbstractPaymentMethodType и вызовом registerPaymentMethod в JavaScript.

Поможет ли возврат к классическому оформлению?

Да: если преобразовать блок оформления в классическую версию с шорткодом, способ сразу появится. Но это не окончательное решение — новые возможности WooCommerce выходят именно для блочного оформления. Сделать плагин совместимым с блоками — разовая работа.

Регистрацию добавил, способа всё равно нет.

Проверьте, что имя совпадает во всех трёх местах: id шлюза, $name в классе PHP и name в JavaScript. Затем проверьте, не откладывает ли скрипт плагин ускорения и возвращает ли is_active() значение true. Ни одна из этих причин не выдаёт видимой ошибки.

Нужен ли дополнительный код для виртуального POS с переходом на страницу 3D Secure банка?

Нет. Когда process_payment() возвращает адрес redirect, блочная страница оформления перенаправляет покупателя. Дополнительный код нужен только шлюзам, принимающим данные карты на вашей странице.

Доступность и смета

Есть идея?
Можно даже одной фразой.