Не изменяется статус платежа в Woocommerce, в чём может быть проблема?

Ссылка скопирована
1 ответ

Сделал плагин кастомной оплаты заказа, способ - редирект.
Вот код:

<?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, но статус платежа не меняется. в логах ошибок нет, всё работает.
Может у кого был опыт?

Не изменяется статус платежа в Woocommerce, в чём может быть проблема?

Дополнительно

Ответы:

Михаил Р., может при таком описании получится понять?

  • zutov позже, ближе к началу следующей недели, к сожалению, пока нет времени вникать, т.к. это надо тестировать на своем магазине.
  • Михаил Р., Спасибо, жду фидбека
  • Михаил Р., привет, очень жду
  • zutov, добрый день! Времени по прежнему в обрез, поэтому попробуем методом тыка. Покажите значения всех переменных (комментарием в коде), после проведения платежа.
Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Алексей Денисов Ответ

В кастомном платёжном шлюзе WooCommerce статус заказа меняется не сам по себе. После редиректа на платёжную страницу нужно иметь callback/webhook или return URL, где вы проверяете оплату и вызываете методы заказа: payment_complete(), update_status(), reduce_order_stock().

Типовой порядок:

  1. В process_payment() создать/получить платёжную ссылку.
  2. Вернуть WooCommerce массив с result => success и redirect => URL.
  3. После оплаты платёжная система вызывает webhook на ваш сайт.
  4. В webhook вы проверяете подпись и сумму.
  5. Меняете статус заказа.

process_payment() должен вернуть именно так:

return [
    'result'   => 'success',
    'redirect' => $payment_url,
];

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');
});

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.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно