Диагностика задачи: зачем нужно автоматическое создание заказа
В классическом WooCommerce заказ создаётся в момент оформления корзины на сайте, а оплата привязывается к этому заказу. Но при интеграции с некоторыми внешними платежными системами (например, через API или webhook) может быть ситуация, когда оплата происходит вне сайта, и нужно на основе данных из платежной системы автоматически создать заказ в WooCommerce, чтобы корректно вести учёт и управлять статусами.
Основная проблема: как синхронизировать внешний платёж с внутренней базой WooCommerce, создать заказ программно, не нарушая логику WooCommerce и не создавая дубликатов.
Пошаговое решение задачи
1. Получение и обработка данных из внешней платежной системы
Вам нужно реализовать endpoint (REST API или webhook), который будет принимать уведомления об оплате от внешней системы. Обычно данные содержат сумму, ID пользователя, список товаров или SKU, уникальный идентификатор платежа.
2. Проверка данных и поиск пользователя
Для создания заказа нужно сопоставить оплату с пользователем в WordPress. Если пользователь не зарегистрирован, создайте гостевой заказ.
3. Создание заказа программно через WooCommerce API
Для создания заказа используйте класс WC_Order. Ниже пример кода, который создаёт заказ с одним товаром и устанавливает статус "processing":
function create_order_from_external_payment($user_id, $product_id, $quantity, $payment_id) {
if (!$user_id) {
$user_id = 0; // Гость
}
// Проверяем, не создавался ли уже заказ по этому платежу
$existing = wc_get_orders(array(
'limit' => 1,
'meta_key' => '_external_payment_id',
'meta_value' => $payment_id
));
if (!empty($existing)) {
return $existing[0]; // Заказ уже есть
}
$order = wc_create_order(array('customer_id' => $user_id));
$order->add_product(wc_get_product($product_id), $quantity);
$order->set_payment_method('external_gateway');
$order->set_payment_method_title('Внешняя платежная система');
$order->set_status('processing');
$order->update_meta_data('_external_payment_id', $payment_id);
$order->calculate_totals();
$order->save();
return $order;
}
4. Реализация endpoint для приёма webhook
Пример простого REST API endpoint, который вызывает функцию создания заказа:
add_action('rest_api_init', function () {
register_rest_route('external-payment/v1', '/create-order', array(
'methods' => 'POST',
'callback' => 'handle_external_payment_webhook',
'permission_callback' => '__return_true',
));
});
function handle_external_payment_webhook(WP_REST_Request $request) {
$data = $request->get_json_params();
$user_id = isset($data['user_id']) ? intval($data['user_id']) : 0;
$product_id = isset($data['product_id']) ? intval($data['product_id']) : 0;
$quantity = isset($data['quantity']) ? intval($data['quantity']) : 1;
$payment_id = isset($data['payment_id']) ? sanitize_text_field($data['payment_id']) : '';
if (!$product_id || !$payment_id) {
return new WP_Error('invalid_data', 'Отсутствуют необходимые параметры', array('status' => 400));
}
$order = create_order_from_external_payment($user_id, $product_id, $quantity, $payment_id);
if (is_wp_error($order)) {
return $order;
}
return array('order_id' => $order->get_id());
}
Проверка результата после внедрения
- Отправьте тестовый POST-запрос на
/wp-json/external-payment/v1/create-orderс корректным JSON с данными оплаты. - Проверьте в админке WooCommerce, появился ли заказ с указанным ID, статусом processing и правильным товаром.
- Убедитесь, что при повторном вызове с тем же
payment_idзаказ не дублируется. - Проверьте, что пользователь привязан корректно или заказ оформлен как гость.
Частые ошибки и как исправить
- Дублирование заказов: если не проверять по уникальному ID платежа, заказы создаются повторно. Обязательно проверяйте существование заказа по мета-данным.
- Неправильный пользователь: неверный user_id или его отсутствие ведёт к созданию заказов без пользователя — лучше предусмотреть гостевой заказ или создать пользователя программно.
- Отсутствие товаров: если product_id не передан или товар не существует, заказ создастся пустым. Добавьте проверку существования товара перед добавлением.
- Ошибки безопасности: endpoint должен иметь проверку подлинности, если это возможно (например, по секретному ключу в заголовках), чтобы не создавать заказы посторонним.
Практические советы по безопасности и производительности
- Используйте проверку nonce или секретный токен в заголовках webhook, чтобы исключить посторонние вызовы.
- Логируйте входящие запросы для аудита и отладки (например, через
error_log()или сторонние сервисы). - Добавляйте минимальную валидацию входных данных, чтобы избежать инъекций и ошибок.
- Используйте транзакции или проверяйте целостность данных, если создаёте несколько позиций заказа.
- Для массовых заказов с множеством товаров оптимизируйте добавление товаров через цикл с минимальным количеством вызовов сохранения.
Сравнение способов реализации автоматического создания заказа
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
| Использование стандартного REST API WooCommerce | Создание заказа через официальные endpoint с аутентификацией | Безопасно, поддерживается сообществом | Сложнее настроить внешнюю систему, требует OAuth или ключей |
| Свой REST API endpoint (пример выше) | Программируемый endpoint для приёма webhook и создания заказа | Гибкость, можно добавить логику валидации и обработки | Нужно продумать безопасность, больше кода |
| Использование плагинов интеграции с платежными системами | Готовые решения для популярных платежных шлюзов | Простота, поддержка и обновления | Не всегда подходит для кастомных систем, ограничены функционалом |