Другое

Как исправить ошибку 'Invalid Order' в шаблонах PDF для WooCommerce

Узнайте, как исправить ошибку 'Invalid Order' при создании пользовательских шаблонов PDF в плагине WooCommerce PDF Invoices & Packing Slips с правильной регистрацией и мерами безопасности.

Как исправить ошибку “Invalid Order” при генерации второго пользовательского шаблона PDF в плагине WooCommerce PDF Invoices & Packing Slips?

Я использую плагин WooCommerce PDF Invoices & Packing Slips от WP Overnight и создал второй пользовательский шаблон PDF (версия ваучера без цен). Я добавил кнопку на страницу Thank You для загрузки этого второго шаблона, но при нажатии на кнопку я получаю ошибку “Invalid Order”. Передаваемый ID заказа правильный (я дважды проверил значение и оно соответствует только что завершенному заказу).

Что я сделал:

  • Создал второй шаблон в дочерней теме: wp-content/themes/child-theme/woocommerce/pdf/voucher.php
  • Зарегистрировал его через фильтр, добавив пользовательскую кнопку на страницу Thank you

Вот мой код:

php
add_action('woocommerce_thankyou', 'add_voucher_pdf_button', 20);
function add_voucher_pdf_button($order_id) {
    if (!$order_id) return;
    
    $order = wc_get_order($order_id);
    if (!$order) return;

    // Nonce для безопасности, должен соответствовать типу документа (invoice)
    $nonce = wp_create_nonce('generate_wpo_wcpdf');
    
    // Построить правильный AJAX URL
    $pdf_url = add_query_arg(array(
        'action'       => 'generate_wpo_wcpdf',
        'document'     => 'invoice', // оставить как invoice, так как voucher не зарегистрированный тип
        'order_ids'    => $order->get_id(),
        'voucher_pdf'  => 1,
        '_wpnonce'     => $nonce,
    ), admin_url('admin-ajax.php'));
    
    echo '<a href="' . esc_url($pdf_url) . '" target="_blank" class="button alt" style="margin-top:20px;">Скачать PDF ваучера</a>';
}


add_filter('wpo_wcpdf_template_file', 'load_voucher_template_conditionally', 10, 3);
function load_voucher_template_conditionally($template, $type, $order) {
    if (!empty($_GET['voucher_pdf']) && $_GET['voucher_pdf'] == 1) {
        $voucher_template = get_stylesheet_directory() . '/woocommerce/pdf/voucher-template/' . basename($template);
        
        if (file_exists($voucher_template)) {
            return $voucher_template;
        }
    }
    return $template;
}

Есть ли какие-либо идеи или примеры по правильной реализации второго пользовательского шаблона PDF в плагине WooCommerce PDF Invoices & Packing Slips?

Ошибка “Недействительный заказ” при создании второго пользовательского PDF-шаблона в WooCommerce PDF Invoices & Packing Slips

Ошибка “Недействительный заказ” при создании второго пользовательского PDF-шаблона в WooCommerce PDF Invoices & Packing Slips обычно возникает из-за неправильной регистрации шаблона или отсутствия проверки заказа в процессе загрузки пользовательского шаблона. Проблема часто связана со строгой проверкой заказа в плагине, который не распознает пользовательские типы документов или параметры, передаваемые через AJAX-запрос.

Содержание

Понимание проблемы

Ошибка “Недействительный заказ” возникает потому, что в плагине WooCommerce PDF Invoices & Packing Slips встроены механизмы проверки, которые определяют, существует ли заказ и может ли быть обработан. При создании пользовательского шаблона и попытке доступа к нему через измененный AJAX-запрос, плагин может не распознать ваши пользовательские параметры или не пройти проверку заказа.

Из обсуждения на Stack Overflow, это известная проблема при попытке создания пользовательских PDF-шаблонов вне стандартного рабочего процесса плагина. Плагин ожидает определенные типы документов и следует конкретному процессу проверки.

Основные причины включают:

  • Неправильную регистрацию шаблона
  • Неправильную обработку параметров AJAX
  • Сбои проверки заказа
  • Проблемы с путем к файлу шаблона

Решение 1: Правильная регистрация шаблона

Наиболее надежный подход - правильно зарегистрировать ваш пользовательский шаблон с помощью встроенных хуков плагина. Вместо попытки изменения параметра типа документа, вы должны зарегистрировать вашу квитанцию как пользовательский тип документа.

php
// Регистрация пользовательского типа документа квитанции
add_filter('wpo_wcpdf_document_types', 'register_voucher_document_type', 10, 1);
function register_voucher_document_type($document_types) {
    $document_types['voucher'] = array(
        'title' => __('Квитанция', 'woocommerce-pdf-invoices-packing-slips'),
        'description' => __('Пользовательский шаблон квитанции без цен', 'woocommerce-pdf-invoices-packing-slips'),
        'settings' => array(),
    );
    return $document_types;
}

// Добавление кнопки квитанции на страницу благодарности
add_action('woocommerce_thankyou', 'add_voucher_pdf_button', 20);
function add_voucher_pdf_button($order_id) {
    if (!$order_id) return;
    
    $order = wc_get_order($order_id);
    if (!$order) return;

    // Создание nonce для безопасности
    $nonce = wp_create_nonce('generate_wpo_wcpdf');
    
    // Построение URL AJAX с пользовательским типом документа
    $pdf_url = add_query_arg(array(
        'action'       => 'generate_wpo_wcpdf',
        'document'     => 'voucher', // Используем зарегистрированный тип документа
        'order_ids'    => $order->get_id(),
        '_wpnonce'     => $nonce,
    ), admin_url('admin-ajax.php'));
    
    echo '<a href="' . esc_url($pdf_url) . '" target="_blank" class="button alt" style="margin-top:20px;">Скачать PDF квитанции</a>';
}

// Загрузка шаблона квитанции при запросе
add_filter('wpo_wcpdf_template_file', 'load_voucher_template', 10, 3);
function load_voucher_template($template, $type, $order) {
    if ($type === 'voucher') {
        $voucher_template = get_stylesheet_directory() . '/woocommerce/pdf/voucher-template/' . basename($template);
        
        if (file_exists($voucher_template)) {
            return $voucher_template;
        }
    }
    return $template;
}

Этот подход следует предполагаемому рабочему процессу плагина путем регистрации квитанции как правильного типа документа, что должно решить проблемы проверки.


Решение 2: Альтернативный подход с пользовательским типом документа

Если первое решение не работает, вы можете реализовать более надежный подход, создав обработчик пользовательского типа документа:

php
// Регистрация пользовательского типа документа
add_filter('wpo_wcpdf_document_types', 'register_custom_voucher_document', 10, 1);
function register_custom_voucher_document($document_types) {
    $document_types['voucher'] = array(
        'title' => __('Квитанция', 'woocommerce-pdf-invoices-packing-slips'),
        'description' => __('Пользовательский шаблон квитанции', 'woocommerce-pdf-invoices-packing-slips'),
        'settings' => array(),
    );
    return $document_types;
}

// Создание пользовательского обработчика AJAX для квитанции
add_action('wp_ajax_generate_wpo_wcpdf_voucher', 'generate_custom_voucher_pdf');
add_action('wp_ajax_nopriv_generate_wpo_wcpdf_voucher', 'generate_custom_voucher_pdf');
function generate_custom_voucher_pdf() {
    check_ajax_referer('generate_wpo_wcpdf', '_wpnonce');
    
    if (!isset($_GET['order_ids']) || empty($_GET['order_ids'])) {
        wp_die('Недействительный заказ');
    }
    
    $order_ids = is_array($_GET['order_ids']) ? $_GET['order_ids'] : array($_GET['order_ids']);
    
    // Проверка каждого заказа
    foreach ($order_ids as $order_id) {
        $order = wc_get_order($order_id);
        if (!$order) {
            wp_die('Недействительный заказ: ' . $order_id);
        }
    }
    
    // Установка типа документа в квитанцию
    $_GET['document'] = 'voucher';
    $_GET['order_ids'] = $order_ids;
    
    // Подключение основного файла плагина
    if (!defined('WPO_WCPDF_VERSION')) {
        wp_die('Плагин PDF Invoices & Packing Slips не найден');
    }
    
    // Генерация PDF с помощью основной функции плагина
    $pdf = wpo_wcpdf_get_document('voucher', $order_ids);
    if (!$pdf) {
        wp_die('Не удалось создать PDF-документ');
    }
    
    $pdf->output();
}

// Добавление кнопки квитанции на страницу благодарности
add_action('woocommerce_thankyou', 'add_custom_voucher_button', 20);
function add_custom_voucher_button($order_id) {
    if (!$order_id) return;
    
    $order = wc_get_order($order_id);
    if (!$order) return;

    $nonce = wp_create_nonce('generate_wpo_wcpdf');
    
    // Использование пользовательского действия AJAX
    $pdf_url = add_query_arg(array(
        'action'       => 'generate_wpo_wcpdf_voucher',
        'order_ids'    => $order->get_id(),
        '_wpnonce'     => $nonce,
    ), admin_url('admin-ajax.php'));
    
    echo '<a href="' . esc_url($pdf_url) . '" target="_blank" class="button alt" style="margin-top:20px;">Скачать PDF квитанции</a>';
}

// Загрузка шаблона квитанции
add_filter('wpo_wcpdf_template_file', 'load_custom_voucher_template', 10, 3);
function load_custom_voucher_template($template, $type, $order) {
    if ($type === 'voucher') {
        $voucher_template = get_stylesheet_directory() . '/woocommerce/pdf/voucher-template.php';
        
        if (file_exists($voucher_template)) {
            return $voucher_template;
        }
    }
    return $template;
}

Этот подход создает выделенный обработчик AJAX для вашего типа документа квитанции, который обходит некоторые проблемы проверки плагина, сохраняя при этом безопасность и функциональность.


Решение 3: Использование хуков плагина для выбора шаблона

Другой эффективный метод - использование существующих хуков плагина для условного выбора вашего пользовательского шаблона:

php
// Регистрация пользовательского типа документа
add_filter('wpo_wcpdf_document_types', 'add_voucher_document_type', 10, 1);
function add_voucher_document_type($document_types) {
    $document_types['voucher'] = array(
        'title' => __('Квитанция', 'woocommerce-pdf-invoices-packing-slips'),
        'description' => __('Шаблон квитанции без цен', 'woocommerce-pdf-invoices-packing-slips'),
    );
    return $document_types;
}

// Добавление логики выбора шаблона
add_filter('wpo_wcpdf_use_external_settings', 'use_external_voucher_settings', 10, 2);
function use_external_voucher_settings($use_external, $document_type) {
    if ($document_type === 'voucher') {
        return true;
    }
    return $use_external;
}

// Добавление кнопки квитанции
add_action('woocommerce_thankyou', 'add_voucher_download_button', 20);
function add_voucher_download_button($order_id) {
    if (!$order_id) return;
    
    $order = wc_get_order($order_id);
    if (!$order) return;

    $nonce = wp_create_nonce('generate_wpo_wcpdf');
    
    // Использование типа документа invoice в качестве базы с выбором шаблона квитанции
    $pdf_url = add_query_arg(array(
        'action'       => 'generate_wpo_wcpdf',
        'document'     => 'invoice', // Использование типа invoice в качестве базы
        'order_ids'    => $order->get_id(),
        'voucher_mode' => 'true',
        '_wpnonce'     => $nonce,
    ), admin_url('admin-ajax.php'));
    
    echo '<a href="' . esc_url($pdf_url) . '" target="_blank" class="button alt" style="margin-top:20px;">Скачать PDF квитанции</a>';
}

// Переопределение шаблона на основе пользовательского параметра
add_filter('wpo_wcpdf_template_file', 'get_voucher_template', 10, 3);
function get_voucher_template($template, $type, $order) {
    if ($type === 'invoice' && !empty($_GET['voucher_mode']) && $_GET['voucher_mode'] === 'true') {
        $voucher_template = get_stylesheet_directory() . '/woocommerce/pdf/voucher-template.php';
        
        if (file_exists($voucher_template)) {
            return $voucher_template;
        }
    }
    return $template;
}

// Добавление настроек шаблона для квитанции
add_filter('wpo_wcpdf_get_document_settings', 'add_voucher_settings', 10, 2);
function add_voucher_settings($settings, $document_type) {
    if ($document_type === 'invoice' && !empty($_GET['voucher_mode']) && $_GET['voucher_mode'] === 'true') {
        $settings['template'] = 'voucher';
    }
    return $settings;
}

Этот подход использует существующий тип документа invoice в плагине, но переопределяет выбор шаблона на основе пользовательского параметра, что может быть более надежным, чем создание совершенно нового типа документа.


Лучшие практики для пользовательских шаблонов

При работе с пользовательскими PDF-шаблонами в WooCommerce PDF Invoices & Packing Slips, следуйте этим лучшим практикам:

Структура файлов шаблона

ваша-дочерняя-тема/
└── woocommerce/
    └── pdf/
        ├── invoice/
        │   └── invoice.php (шаблон по умолчанию)
        ├── packing-slip/
        │   └── packing-slip.php (шаблон по умолчанию)
        └── voucher/
            └── voucher.php (ваш пользовательский шаблон)

Вопросы безопасности

  • Всегда используйте wp_create_nonce() и check_ajax_referer() для безопасности
  • Проверяйте ID заказов перед обработкой
  • Очищайте все пользовательские входные данные и параметры запроса

Оптимизация производительности

  • Кэшируйте файлы шаблонов при возможности
  • Минимизируйте запросы к базе данных в файлах шаблонов
  • Используйте правильный синтаксис PHP и избегайте устаревших функций

Разработка шаблонов

  • Копируйте существующие шаблоны в качестве отправной точки
  • Тестируйте с разными типами и статусами заказов
  • Используйте инструменты отладки плагина для разработки

Отладка и устранение неполадок

Если вы продолжаете испытывать проблемы, вот несколько шагов отладки:

Включение режима отладки

php
// Добавьте в functions.php вашей темы или пользовательский плагин
add_filter('wpo_wcpdf_debug_mode', '__return_true');

Проверка разрешений файлов шаблона

Убедитесь, что ваши файлы шаблонов доступны для чтения веб-сервером:

bash
chmod 644 wp-content/themes/ваша-дочерняя-тема/woocommerce/pdf/voucher/voucher.php

Проверка объекта заказа

Добавьте код отладки для проверки объекта заказа:

php
add_action('woocommerce_thankyou', 'debug_order_object', 25);
function debug_order_object($order_id) {
    if (!$order_id) return;
    
    $order = wc_get_order($order_id);
    if (!$order) {
        error_log('Объект заказа равен null для ID: ' . $order_id);
        return;
    }
    
    error_log('Детали заказа: ' . print_r($order->get_data(), true));
}

Проверка совместимости плагина

Убедитесь, что вы используете совместимую версию плагина WooCommerce PDF Invoices & Packing Slips. Согласно документации плагина, всегда проверяйте наличие обновлений и совместимость с вашей версией WooCommerce.

Просмотр журналов ошибок

Проверьте журналы ошибок WordPress и сервера на наличие предупреждений или уведомлений PHP, которые могут вызывать проблему.


Заключение

Ошибка “Недействительный заказ” при создании второго пользовательского PDF-шаблона в WooCommerce PDF Invoices & Packing Slips обычно возникает из-за неправильной регистрации шаблона или проблем проверки заказа. Наиболее эффективные решения включают:

  1. Правильную регистрацию вашего пользовательского шаблона в качестве типа документа с помощью хуков плагина
  2. Создание выделенного обработчика AJAX для вашего пользовательского типа документа
  3. Использование существующих типов документов с переопределением шаблонов на основе пользовательских параметров

Следуя подходам, описанным выше, и реализуя надлежащие меры безопасности, вы должны успешно создавать и получать доступ к вашему пользовательскому шаблону квитанции без encountering ошибки “Недействительный заказ”. Не забывайте тщательно тестировать с разными типами заказов и убедиться, что ваши файлы шаблонов правильно структурированы и доступны.

Источники

  1. Stack Overflow - Ошибка “Недействительный заказ” при создании второго пользовательского PDF-шаблона
  2. WordPress.org - Поддержка плагина PDF Invoices & Packing Slips
  3. Документация WP Overnight - Создание пользовательского PDF-шаблона
  4. GitHub - Плагин WooCommerce PDF Invoices & Packing Slips
  5. Документация WooCommerce - Построитель PDF-накладных и счетов
Авторы
Проверено модерацией
Модерация