Привет! Меня зовут Артём, я бэкенд-разработчик. Сегодня опять про REST API, но на этот раз со стороны WordPress и WooCommerce. Кейс родился из реального проекта: интернет-магазин на WooCommerce, к которому мы делали интеграцию с CRM. Менеджеры добавляли комментарий к заказу из CRM, он записывался в кастомное поле, а покупатель в email-уведомлении видел только стандартные данные — без нашего комментария.
Казалось бы, данные в заказе — они и в письме должны быть. Но WooCommerce так не думает.
Как мы добавляли кастомное поле
Через REST API всё просто — отправляем запрос на /wp-json/wc/v3/orders/{id} с нашим полем:
{
"meta_data": [
{
"key": "_crm_manager_comment",
"value": "Передана в доставку 15 мая"
}
]
}
Поле сохраняется, в админке на странице заказа мы его видим (после того как добавили колонку через woocommerce_admin_order_item_headers). Но когда покупатель получает email «Заказ выполнен», кастомного поля там нет. Вообще.
Почему WooCommerce email-шаблоны «слепые» к meta_data
WooCommerce email-шаблоны жёстко закодированы. Шаблон emails/customer-completed-order.php рендерит только те данные, которые явно прописаны в нём: номер заказа, дату, позиции, итоговую сумму и billing/shipping адреса. Массив meta_data заказа в шаблоне никто не перебирает. Это сделано намеренно — WooCommerce не знает, какие из ваших кастомных полей стоит показывать покупателю, а какие — внутренние (например, ID в CRM или хэш для вебхука).
Новички часто копируют шаблон письма в свою тему (woocommerce/emails/...) и вручную дописывают вывод поля. Это работает, но создаёт проблему: при обновлении WooCommerce ваш кастомный шаблон перестанет получать улучшения безопасности и новые фичи.
Способ 1: Хук woocommerce_email_order_meta_fields (правильный)
WooCommerce предоставляет специальный хук woocommerce_email_order_meta_fields, который отрисовывает дополнительную секцию в письме с таблицей произвольных полей. Вам нужно только указать, какие ключи показывать:
add_action('woocommerce_email_order_meta_fields', function($fields, $sent_to_admin, $order) {
$comment = $order->get_meta('_crm_manager_comment');
if (!empty($comment)) {
$fields['_crm_manager_comment'] = [
'label' => __('Комментарий менеджера', 'my-theme'),
'value' => esc_html($comment),
];
}
return $fields;
}, 10, 3);
Этот подход не требует копирования шаблонов. Поля появятся в разделе «Custom fields» в каждом email-шаблоне заказа. Минус — вы не можете контролировать позицию: секция всегда рендерится после таблицы товаров и перед totals.
Способ 2: Хук woocommerce_order_details_after_order_table
Если вам нужно больше контроля над разметкой, используйте хук для встраивания произвольного HTML:
add_action('woocommerce_order_details_after_order_table', function($order) {
$comment = $order->get_meta('_crm_manager_comment');
if (empty($comment)) return;
echo '<h2>' . __('Комментарий менеджера', 'my-theme') . '</h2>';
echo '<p style="margin: 0 0 20px; color: #555;">' . esc_html($comment) . '</p>';
}, 10, 1);
Этот хук срабатывает и в email, и на странице «Мой аккаунт» (страница просмотра заказа). Если хотите, чтобы кастомный блок появлялся только в email, используйте проверку:
add_action('woocommerce_order_details_after_order_table', function($order) {
// Проверяем, что мы в контексте email
if (!is_email_context()) return;
// ...
});
Однако is_email_context() работает не всегда надёжно. Более надёжный способ — проверить наличие глобальной переменной $email:
global $email;
if (!$email instanceof WC_Email) return;
Способ 3: Кастомный email-шаблон (только если нужно кардинально изменить layout)
Если ни один из хуков не даёт нужного результата, можно скопировать шаблон в тему и отредактировать его напрямую. Скопируйте wp-content/plugins/woocommerce/templates/emails/customer-completed-order.php в wp-content/themes/your-theme/woocommerce/emails/customer-completed-order.php. После этого добавьте вывод поля в нужном месте шаблона.
Важно: при обновлении WooCommerce система не перезапишет ваш файл, но и не уведомит о том, что оригинальный шаблон изменился. Рекомендую установить плагин WooCommerce Template Status Checker или регулярно сравнивать ваши шаблоны с оригинальными после обновлений.
Проблема с кэшированием meta_data
Ещё одна грабля, с которой я столкнулся: если вы обновляете meta_data через REST API, а email уже стоит в очереди на отправку (WooCommerce ставит email в очередь через wp_cron), заказ может быть прочитан из object cache до вашего обновления. WooCommerce кэширует объекты заказов внутри текущего запроса.
Решение: после обновления заказа через API вызовите wp_cache_delete($order_id, 'posts') или используйте метод wc_delete_shop_order_transients($order_id) для полной очистки кэша заказа. Без этого покупатель получит email с устаревшими данными.
Пока нет комментариев
Будьте первым, кто оставит комментарий к этой статье