Не изменяется статус платежа в Woocommerce, в чём может быть проблема?
Сделал плагин кастомной оплаты заказа, способ - редирект.
Вот код:
<?php /* Plugin Name: ***** Pay Gateway Description: Custom Payment Gateway for ***** Pay Author: Zutov Version: 1.0 */ add_filter('woocommerce_payment_gateways', '*****_pay_add_gateway_class'); function ****_pay_add_gateway_class($gateways) { $gateways[] = 'WC_****_Pay_Gateway'; return $gateways; } add_action('plugins_loaded', '*****_pay_init_gateway_class'); function *****_pay_init_gateway_class() { class WC_*****_Pay_Gateway extends WC_Payment_Gateway { public function __construct() { $this->id = '*****_pay'; $this->method_title = '***** Pay'; $this->method_description = 'Custom Payment Gateway for ***** Pay'; $this->init_form_fields(); $this->init_settings(); $this->title = $this->get_option('title'); $this->description = $this->get_option('description'); $this->enabled = $this->get_option('enabled'); $this->testmode = $this->get_option('testmode') === 'yes' ? true : false; add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options')); } public function init_form_fields(){ $this->form_fields = array( 'enabled' => array( 'title' => 'Включить/Выключить', 'type' => 'checkbox', 'label' => 'Включить ***** Pay Gateway', 'default' => 'no' ), 'title' => array( 'title' => 'Название', 'type' => 'text', 'description' => 'Название метода оплаты, которое видит пользователь при оформлении заказа.', 'default' => '***** Pay', 'desc_tip' => true, ), 'description' => array( 'title' => 'Описание', 'type' => 'textarea', 'description' => 'Описание метода оплаты, которое видит пользователь при оформлении заказа.', 'default' => 'Оплата с помощью ***** Pay.', ), 'testmode' => array( 'title' => 'Тестовый режим', 'type' => 'checkbox', 'label' => 'Включить тестовый режим', 'default' => 'yes', 'description' => 'В этом режиме платежи будут симулироваться, как если бы они проходили через платёжный шлюз ***** Pay.', ), 'api_key' => array( 'title' => 'API ключ', 'type' => 'text', 'description' => 'Ваш API ключ от ***** Pay.', ), ); } public function process_payment($order_id) { $order = wc_get_order($order_id); $total = $order->get_total(); $currency = get_woocommerce_currency(); $return_url = $this->get_return_url($order); $callback_url = 'https://*******tech.com/*****_pay_callback'; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => 'https://***********/payment-invoices', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS =>'{ "data": { "type": "payment-invoices", "attributes": { "reference_id": "'. $order_id .'", "description": "Payment by order#'. $order_id .'", "currency": "'. $currency .'", "amount": '. $total .', "service": "payment_card_eur_hpp", "return_url": "'. $return_url .'", "callback_url": "'. $callback_url .'", "test_mode": true } } }', CURLOPT_HTTPHEADER => array( 'Authorization: Basic Y29tYV9OZ0dsU0I2VWdidUFCc1pYOjVqQWw0MkdzbGZTcjhVcTllRFF3bTBjNU1YVDM3MDFXYTZmaWh6Q00tVEU=', 'Content-Type: application/json' ), )); $response = curl_exec($curl); error_log('***** Pay API Response: ' . print_r($response, true)); curl_close($curl); $response_body = json_decode($response, true); if (isset($response_body['data']['attributes']['hpp_url'])) { $redirect_url = $response_body['data']['attributes']['hpp_url']; return array( 'result' => 'success', 'redirect' => $redirect_url, ); } else { wc_add_notice('Ошибка при обработке платежа.', 'error'); return; } } } } // Добавление endpoint для обработки callback от ***** Pay function add_*****_pay_callback_endpoint() { add_rewrite_endpoint('*****_pay_callback', EP_ROOT); } add_action('init', 'add_*****_pay_callback_endpoint'); // Обработка запросов к endpoint function handle_*****_pay_callback() { global $wp_query; if (!isset($wp_query->query_vars['*****_pay_callback'])) { return; } $request_body = file_get_contents('php://input'); $data = json_decode($request_body, true); error_log('***** Pay Callback Data: ' . print_r($data, true)); if (isset($data['status'])) { $order_id = $data['reference_id']; $order = wc_get_order($order_id); if (!$order) { error_log('Order not found: ' . $order_id); return; } switch ($data['status']) { case 'processed': $order->update_status('completed', 'Платеж успешно обработан через ***** Pay'); break; case 'process_failed': $order->update_status('failed', 'Ошибка при обработке платежа через ***** Pay'); break; case 'process_pending': $order->update_status('processing', 'Платёж в обработке через ***** Pay'); break; } } status_header(200); echo 'Callback received and processed'; exit; } add_action('template_redirect', 'handle_*****_pay_callback'); |
<?php /* Plugin Name: ***** Pay Gateway Description: Custom Payment Gateway for ***** Pay Author: Zutov Version: 1.0 */ add_filter('woocommerce_payment_gateways', '*****_pay_add_gateway_class'); function ****_pay_add_gateway_class($gateways) { $gateways[] = 'WC_****_Pay_Gateway'; return $gateways; } add_action('plugins_loaded', '*****_pay_init_gateway_class'); function *****_pay_init_gateway_class() { class WC_*****_Pay_Gateway extends WC_Payment_Gateway { public function __construct() { $this->id = '*****_pay'; $this->method_title = '***** Pay'; $this->method_description = 'Custom Payment Gateway for ***** Pay'; $this->init_form_fields(); $this->init_settings(); $this->title = $this->get_option('title'); $this->description = $this->get_option('description'); $this->enabled = $this->get_option('enabled'); $this->testmode = $this->get_option('testmode') === 'yes' ? true : false; add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options')); } public function init_form_fields(){ $this->form_fields = array( 'enabled' => array( 'title' => 'Включить/Выключить', 'type' => 'checkbox', 'label' => 'Включить ***** Pay Gateway', 'default' => 'no' ), 'title' => array( 'title' => 'Название', 'type' => 'text', 'description' => 'Название метода оплаты, которое видит пользователь при оформлении заказа.', 'default' => '***** Pay', 'desc_tip' => true, ), 'description' => array( 'title' => 'Описание', 'type' => 'textarea', 'description' => 'Описание метода оплаты, которое видит пользователь при оформлении заказа.', 'default' => 'Оплата с помощью ***** Pay.', ), 'testmode' => array( 'title' => 'Тестовый режим', 'type' => 'checkbox', 'label' => 'Включить тестовый режим', 'default' => 'yes', 'description' => 'В этом режиме платежи будут симулироваться, как если бы они проходили через платёжный шлюз ***** Pay.', ), 'api_key' => array( 'title' => 'API ключ', 'type' => 'text', 'description' => 'Ваш API ключ от ***** Pay.', ), ); } public function process_payment($order_id) { $order = wc_get_order($order_id); $total = $order->get_total(); $currency = get_woocommerce_currency(); $return_url = $this->get_return_url($order); $callback_url = 'https://*******tech.com/*****_pay_callback'; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => 'https://***********/payment-invoices', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS =>'{ "data": { "type": "payment-invoices", "attributes": { "reference_id": "'. $order_id .'", "description": "Payment by order#'. $order_id .'", "currency": "'. $currency .'", "amount": '. $total .', "service": "payment_card_eur_hpp", "return_url": "'. $return_url .'", "callback_url": "'. $callback_url .'", "test_mode": true } } }', CURLOPT_HTTPHEADER => array( 'Authorization: Basic Y29tYV9OZ0dsU0I2VWdidUFCc1pYOjVqQWw0MkdzbGZTcjhVcTllRFF3bTBjNU1YVDM3MDFXYTZmaWh6Q00tVEU=', 'Content-Type: application/json' ), )); $response = curl_exec($curl); error_log('***** Pay API Response: ' . print_r($response, true)); curl_close($curl); $response_body = json_decode($response, true); if (isset($response_body['data']['attributes']['hpp_url'])) { $redirect_url = $response_body['data']['attributes']['hpp_url']; return array( 'result' => 'success', 'redirect' => $redirect_url, ); } else { wc_add_notice('Ошибка при обработке платежа.', 'error'); return; } } } } // Добавление endpoint для обработки callback от ***** Pay function add_*****_pay_callback_endpoint() { add_rewrite_endpoint('*****_pay_callback', EP_ROOT); } add_action('init', 'add_*****_pay_callback_endpoint'); // Обработка запросов к endpoint function handle_*****_pay_callback() { global $wp_query; if (!isset($wp_query->query_vars['*****_pay_callback'])) { return; } $request_body = file_get_contents('php://input'); $data = json_decode($request_body, true); error_log('***** Pay Callback Data: ' . print_r($data, true)); if (isset($data['status'])) { $order_id = $data['reference_id']; $order = wc_get_order($order_id); if (!$order) { error_log('Order not found: ' . $order_id); return; } switch ($data['status']) { case 'processed': $order->update_status('completed', 'Платеж успешно обработан через ***** Pay'); break; case 'process_failed': $order->update_status('failed', 'Ошибка при обработке платежа через ***** Pay'); break; case 'process_pending': $order->update_status('processing', 'Платёж в обработке через ***** Pay'); break; } } status_header(200); echo 'Callback received and processed'; exit; } add_action('template_redirect', 'handle_*****_pay_callback');
Коллбеки доходят до endpoint, но статус платежа не меняется. в логах ошибок нет, всё работает.
Может у кого был опыт?
Дополнительно
Ответы:
Михаил Р., может при таком описании получится понять?
- zutov позже, ближе к началу следующей недели, к сожалению, пока нет времени вникать, т.к. это надо тестировать на своем магазине.
- Михаил Р., Спасибо, жду фидбека
- Михаил Р., привет, очень жду
- zutov, добрый день! Времени по прежнему в обрез, поэтому попробуем методом тыка. Покажите значения всех переменных (комментарием в коде), после проведения платежа.
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос

В кастомном платёжном шлюзе WooCommerce статус заказа меняется не сам по себе. После редиректа на платёжную страницу нужно иметь callback/webhook или return URL, где вы проверяете оплату и вызываете методы заказа:
payment_complete(),update_status(),reduce_order_stock().Типовой порядок:
process_payment()создать/получить платёжную ссылку.result => successиredirect => URL.process_payment()должен вернуть именно так:return [ 'result' => 'success', 'redirect' => $payment_url, ];
Если вы просто делаете
wp_redirect()внутри checkout AJAX, WooCommerce может показать ошибку платежа, потому что ожидает JSON-ответ от метода оплаты.Webhook endpoint можно зарегистрировать через WooCommerce API callback:
add_action('woocommerce_api_my_gateway', function () { $order_id = absint($_GET['order_id'] ?? 0); $order = wc_get_order($order_id); if (! $order) { status_header(404); exit; } // Проверить подпись/статус у платёжной системы $order->payment_complete(); exit('OK'); });
Не ставьте статус paid только по факту возврата пользователя на сайт. Return URL пользователь может открыть вручную. Подтверждение оплаты должно приходить от платёжной системы или проверяться запросом к её API.