Задача: зачем нужны дополнительные поля на странице оплаты WooCommerce?
Иногда стандартного набора полей оформления заказа в WooCommerce недостаточно. Например, требуется собрать дополнительную информацию от клиента — номер ИНН, комментарии по доставке, выбор времени звонка и т.п. В этой статье разберём, как добавить такие поля на страницу оплаты, валидировать их и сохранить в заказе.
Диагностика проблемы: почему стандартные поля WooCommerce не подходят?
WooCommerce по умолчанию предлагает базовые поля для доставки и оплаты, но их нельзя расширить через настройки. Чтобы добавить что-то специфическое, нужно вмешательство в код или использование плагинов. При этом важно:
- Добавить поле, которое корректно отобразится на странице оплаты;
- Проверить валидность введённых данных;
- Сохранить данные в метаданные заказа;
- Отобразить их в админке и в письмах клиенту.
Если не сделать это правильно, данные могут не сохраниться или не отобразиться, что приведёт к неудобству и ошибкам.
Пошаговое решение: добавляем и проверяем дополнительные поля
1. Добавляем поле на страницу оплаты
Для добавления поля используем хук woocommerce_after_order_notes. Например, добавим поле "ИНН" (идентификационный номер налогоплательщика):
add_action('woocommerce_after_order_notes', 'wpbuy_add_custom_checkout_field');
function wpbuy_add_custom_checkout_field($checkout) {
echo '<div id="wpbuy_custom_checkout_field">';
woocommerce_form_field('inn_number', array(
'type' => 'text',
'class' => array('form-row-wide'),
'label' => __('ИНН'),
'placeholder' => __('Введите ИНН'),
'required' => true,
), $checkout->get_value('inn_number'));
echo '</div>';
}2. Валидируем поле при оформлении
Используем хук woocommerce_checkout_process для проверки корректности ИНН (например, проверим, что это 10 или 12 цифр):
add_action('woocommerce_checkout_process', 'wpbuy_validate_custom_checkout_field');
function wpbuy_validate_custom_checkout_field() {
if (empty($_POST['inn_number'])) {
wc_add_notice(__('Пожалуйста, введите ИНН.'), 'error');
} else {
$inn = sanitize_text_field($_POST['inn_number']);
if (!preg_match('/^\d{10}|\d{12}$/', $inn)) {
wc_add_notice(__('ИНН должен содержать 10 или 12 цифр.'), 'error');
}
}
}3. Сохраняем данные в заказе
Для сохранения используем хук woocommerce_checkout_update_order_meta:
add_action('woocommerce_checkout_update_order_meta', 'wpbuy_save_custom_checkout_field');
function wpbuy_save_custom_checkout_field($order_id) {
if (!empty($_POST['inn_number'])) {
update_post_meta($order_id, '_inn_number', sanitize_text_field($_POST['inn_number']));
}
}4. Отображаем поле в админке заказа
Добавим вывод ИНН в метабоксе заказа:
add_action('woocommerce_admin_order_data_after_billing_address', 'wpbuy_display_custom_field_admin_order', 10, 1);
function wpbuy_display_custom_field_admin_order($order){
$inn = get_post_meta($order->get_id(), '_inn_number', true);
if ($inn) {
echo '<p><strong>ИНН:</strong> ' . esc_html($inn) . '</p>';
}
}5. Добавляем поле в письма
Чтобы ИНН отображался в письмах, используем фильтр woocommerce_email_order_meta_fields:
add_filter('woocommerce_email_order_meta_fields', 'wpbuy_add_custom_field_to_emails');
function wpbuy_add_custom_field_to_emails($fields) {
$fields['inn_number'] = array(
'label' => __('ИНН'),
'value' => get_post_meta(get_the_ID(), '_inn_number', true),
);
return $fields;
}Как проверить, что всё работает?
- Перейдите в оформление заказа на сайте и убедитесь, что появилось новое поле "ИНН".
- Попробуйте отправить заказ без ИНН — должна появиться ошибка.
- Введите некорректный ИНН (например, 123) — должна появиться ошибка валидации.
- Оформите заказ с корректным ИНН (10 или 12 цифр).
- В админке WooCommerce откройте заказ и проверьте, что поле "ИНН" отображается.
- Проверьте письма с заказом — поле ИНН должно присутствовать.
Частые ошибки и их исправление
- Поле не отображается на странице оплаты: возможно, тема или плагин переопределяют шаблоны оформления заказа. Проверьте наличие кастомных шаблонов в папке
woocommerce/checkoutвашей темы. - Валидация не срабатывает: убедитесь, что хук
woocommerce_checkout_processдобавлен в functions.php и функция вызывается. - Данные не сохраняются в заказе: проверьте, что ключи в
$_POSTсовпадают с именем поля и используетсяupdate_post_meta. - Поле не видно в письмах: фильтр
woocommerce_email_order_meta_fieldsдолжен возвращать массив с правильными ключами и значениями.
Практические советы по безопасности и производительности
- Используйте
sanitize_text_fieldдля очистки пользовательских данных перед сохранением. - Валидацию лучше делать и на фронтенде (JavaScript), и на сервере (PHP) для лучшего UX и безопасности.
- Избегайте вывода данных напрямую — всегда применяйте
esc_htmlили аналогичные функции для защиты от XSS. - Если добавляете много полей, рассмотрите создание отдельного плагина для удобства поддержки.
Сравнение вариантов реализации
| Способ | Простота | Гибкость | Компромисс |
|---|---|---|---|
| Код в functions.php | Средняя | Высокая | Может быть сложно поддерживать при большом количестве полей |
| Использование плагина (например, Checkout Field Editor) | Высокая | Средняя | Меньше контроля, возможны конфликты с другими плагинами |
| Создание собственного плагина | Сложнее | Максимальная | Требует времени на разработку, но хорошо масштабируется |