Решение проблемы с дублирующимися лицензиями в подписках WooCommerce

Диагностика проблемы дублирующихся лицензий в подписках WooCommerce

При использовании подписок WooCommerce совместно с системой лицензирования плагинов часто возникает ситуация, когда одна и та же лицензия выдается несколько раз одному пользователю. Это приводит к конфликтам при активации плагина и ошибкам обновлений. Основные признаки проблемы:

  • В панели администратора WooCommerce в заказах несколько одинаковых лицензионных ключей на одного пользователя.
  • При попытке обновить плагин лицензия определяется как уже используемая.
  • Отчеты по использованию лицензий показывают избыточное количество активаций с одной лицензии.

Проблема чаще всего связана с тем, как WooCommerce Subscriptions обрабатывает повторяющиеся заказы и их метаданные, а также с отсутствием уникализации ключей при автоматическом продлении.

Причина возникновения дублирующихся лицензий

WooCommerce Subscriptions создает новый заказ при каждом автоматическом продлении. Если генерация лицензионного ключа привязана к заказу, а не к подписке, то при каждом продлении создается новая лицензия. Также часто отсутствует проверка на существование активной лицензии для пользователя или подписки.

Типичные ошибки в коде генерации ключей:

function generate_license_key( $order_id ) {
    // Генерация ключа без проверки существующих
    $key = strtoupper( wp_generate_password( 16, false ) );
    update_post_meta( $order_id, '_license_key', $key );
    return $key;
}

Этот код всегда создает новый ключ для каждого заказа без учета подписки.

Пошаговое решение: уникализация лицензий по подписке

Чтобы избежать дублирования, нужно связать лицензию с подпиской, а не с каждым заказом. Для этого необходимо:

  1. Получить ID подписки из заказа.
  2. Проверить, есть ли уже лицензия, связанная с этой подпиской.
  3. Если лицензия есть — вернуть ее, если нет — создать новую.

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

function get_or_create_license_key_by_subscription( $order_id ) {
    if ( ! class_exists( 'WC_Subscriptions_Manager' ) ) {
        return false; // Subscriptions не активен
    }

    // Получаем подписки, связанные с заказом
    $subscriptions = wcs_get_subscriptions_for_order( $order_id, array( 'order_type' => 'any' ) );
    if ( empty( $subscriptions ) ) {
        return false;
    }

    foreach ( $subscriptions as $subscription ) {
        $subscription_id = $subscription->get_id();
        $license_key = get_post_meta( $subscription_id, '_license_key', true );
        if ( $license_key ) {
            return $license_key; // Лицензия уже есть
        } else {
            $license_key = strtoupper( wp_generate_password( 16, false ) );
            update_post_meta( $subscription_id, '_license_key', $license_key );
            return $license_key;
        }
    }

    return false;
}

Этот код гарантирует, что лицензия создается один раз для подписки, а не для каждого заказа.

Как внедрить решение в процесс покупки и обновлений

Вызов функции get_or_create_license_key_by_subscription необходимо интегрировать в хуки, связанные с обработкой заказа и активацией лицензии, например:

add_action( 'woocommerce_order_status_completed', 'process_license_on_subscription_order', 20, 1 );

function process_license_on_subscription_order( $order_id ) {
    $license_key = get_or_create_license_key_by_subscription( $order_id );
    if ( $license_key ) {
        // Сохраняем или отправляем лицензию пользователю
        // Например, добавим в email или мета пользователя
    }
}

Проверка результата после внедрения

  • Создайте новую подписку и проверьте, что сгенерирован один лицензионный ключ, привязанный к подписке (проверьте мета _license_key у поста-субскрипшена).
  • При автоматическом продлении заказа убедитесь, что ключ не меняется и не создается дубликат.
  • Проверьте в админке WooCommerce, что в заказах нет повторяющихся ключей.
  • Протестируйте активацию плагина с этим ключом, чтобы убедиться, что он работает корректно.

Частые ошибки и как их исправить

  • Генерация ключей на каждый заказ: исправить, привязав ключ к подписке, как описано выше.
  • Отсутствие проверки класса WC_Subscriptions: нужен class_exists, чтобы избежать ошибок, если плагин подписок отключен.
  • Ключи хранятся в мета заказов, а не подписок: храните ключи в мета подписок для единой точки контроля.
  • Отсутствие обработки автопродления: используйте хук woocommerce_order_status_completed, который срабатывает и при обновлениях заказов подписки.

Практические советы по безопасности и производительности

  • Не храните лицензионные ключи в открытом виде в пользовательских метаданных — используйте защиту доступа к метаданным или шифрование, если это необходимо.
  • Кэшируйте результаты функции получения ключа, если она вызывается часто.
  • Внедрите логирование генерации ключей для отладки и аудита.
  • Если используете REST API для проверки лицензий, ограничьте доступ с помощью nonce и прав пользователя.

Сравнение вариантов хранения лицензий

ВариантГде хранится ключПлюсыМинусы
В мета заказовpostmeta заказовПросто реализоватьДубликаты ключей при продлении
В мета подписокpostmeta подписок (WC_Subscription)Уникальность ключа, удобство управленияНужна интеграция с WC Subscriptions API
Отдельная таблица базыСобственная таблица лицензийМаксимальный контроль, масштабируемостьСложнее реализовать, требует миграций
Как сделать автотестирование лицензий WordPress плагинов
05.01.2026
Ограничение активации лицензии WordPress плагина по ролям пользователей
17.04.2026
Как автоматизировать обновления WordPress плагинов с обратной связью
20.11.2025
Как автоматизировать проверку лицензий WordPress плагинов с помощью WP-Cron
21.03.2026
Решение проблем с лицензиями в WooCommerce при использовании комплексных подписок
04.05.2026