Subscriptions
The subscriptions module adds products with recurring payments. Customers buy subscriptions with manual renewal, and the administrator manages them in WooCommerce.
How it works
Section titled “How it works”- The administrator marks an ordinary product as a subscription, with a cycle and a price, on the Polski Pro tab of the product editor
- The customer purchases a subscription and pays the first order
- The plugin creates a subscription with “Active” status
- Before the renewal date, the customer receives a reminder email
- On the renewal date, the plugin creates a renewal order
- The customer pays the renewal order (manual renewal)
- The cycle repeats until the subscription is cancelled
Configuration
Section titled “Configuration”Since Polski PRO 1.22.0 subscriptions have their own row on Polski > Modules (module key subscriptions). Switch the module on there, and set the store-wide values on the same row; saving writes them into the polski_subscriptions option. The module ships off.
The row does not expose every key the module reads. Anything missing from it can still be set on the option directly, for example with WP-CLI:
wp option patch update polski_subscriptions reminder_first_days 10Per-product values (whether a product is a subscription at all, and its cycle) are on the Polski Pro tab of the product editor, see Per-product settings.
Settings the module reads
Section titled “Settings the module reads”| Key | Default | Description |
|---|---|---|
show_on_single |
true |
Show the subscription options on the product page |
reminder_first_days |
14 |
Days before renewal for the first reminder email |
reminder_second_days |
7 |
Days before renewal for the second reminder email |
allow_cancellation |
true |
Let the customer cancel from My Account |
allow_pause |
true |
Let the customer pause and resume from My Account |
show_in_account / account_label |
true / Subscriptions |
My Account section listing subscriptions |
date_format |
d.m.Y |
Date format in customer-facing output |
Reminder and renewal emails, the status names and the cycle wording each have their own key (reminder_subject, renewal_intro_text, status_paused and so on). The defaults live in Polski\Pro\Service\SubscriptionService. Renewal reminders and renewal orders run on the polski_daily_maintenance cron event.
Creating a subscription product
Section titled “Creating a subscription product”There is no “Subscription” product type. A subscription is an ordinary product with the subscription meta set on it, and since Polski PRO 1.26.0 the Polski Pro tab in the product data box writes that meta:
- Go to Products > Add New and build an ordinary product. Its price is the amount charged per billing period.
- Open the Polski Pro tab in the Product data box and tick Sell as a subscription.
- Configure the cycle:
| Field | Meta key | Description |
|---|---|---|
| Bill every | _polski_subscription_interval |
Number of periods between charges, at least 1 |
| Billing period | _polski_subscription_period |
Day, week, month or year; month when unset |
| Number of payments | _polski_subscription_length |
0 renews until the customer cancels |
| Sign-up fee | _polski_subscription_signup_fee |
Charged once, with the first payment |
| Trial days | _polski_subscription_trial_days |
Days before the first charge, 0 for no trial |
- Publish the product
See Per-product settings for the whole tab.
First payment vs renewal payment
Section titled “First payment vs renewal payment”Two fields make the first payment differ from the ones after it:
- Sign-up fee is added once, to the first order only.
- Trial days pushes the first charge out by that many days, and the subscription starts in the
trialstatus instead ofactive.
There is no separate “initial price” field. Everything else is the product price, charged again each billing period.
Subscription lifecycle
Section titled “Subscription lifecycle”Pending -> Active -> On Hold -> Active -> ... -> Expired -> Cancelled| Status | Description |
|---|---|
| Pending | Awaiting payment of the first order |
| Active | Active - customer has access to the product |
| On Hold | Suspended - renewal order awaiting payment |
| Expired | Expired - renewal count reached the limit or grace period passed |
| Cancelled | Cancelled by the customer or administrator |
Renewals
Section titled “Renewals”Manual renewal
Section titled “Manual renewal”In the current version, the plugin supports manual renewals. This means that:
- The plugin creates a renewal order with “Pending payment” status
- The customer receives an email with a link to pay the order
- The customer pays the order using their chosen payment method
- After payment, the subscription is renewed for the next period
Renewal process
Section titled “Renewal process”The plugin checks subscriptions due for renewal daily using WP cron:
polski_daily_maintenanceThe cron task runs once daily and performs:
- checking subscriptions whose renewal date falls on today or earlier
- creating renewal orders for subscriptions requiring renewal
- suspending subscriptions that have exceeded the grace period
- expiring subscriptions that have reached the renewal limit
Email reminders
Section titled “Email reminders”The plugin sends email reminders before the renewal date:
| When | Content | |
|---|---|---|
| Renewal reminder | X days before renewal | Information about the upcoming renewal, amount, link to the panel |
| Renewal order | On the renewal date | Order to pay with a payment link |
| Subscription suspended | After payment due date passes | Information about suspension, link to pay |
| Subscription expired | After grace period passes | Information about expiration, link to repurchase |
Email templates can be customized in WooCommerce > Settings > Emails.
My Account panel
Section titled “My Account panel”The module adds a /polski-subscriptions endpoint to the customer’s My Account panel. The endpoint is available at:
/moje-konto/polski-subscriptions/Subscription list
Section titled “Subscription list”The customer sees a table with subscriptions:
| Column | Description |
|---|---|
| Product | Subscription product name |
| Status | Current subscription status |
| Price | Amount per period |
| Next renewal | Next renewal date |
| Actions | Cancel / Pay renewal |
Subscription details
Section titled “Subscription details”After clicking on a subscription, the customer sees:
- full subscription data (product, price, cycle, dates)
- renewal history (list of associated orders)
- subscription cancellation button
- button to pay a pending renewal (if applicable)
Cancelling a subscription
Section titled “Cancelling a subscription”The customer can cancel an active subscription from the My Account panel. Cancellation:
- changes the subscription status to “Cancelled”
- the subscription remains active until the end of the current paid period
- the customer is informed about the access end date
polski_pro/subscription/status_changed
Section titled “polski_pro/subscription/status_changed”Action fired after a subscription status change.
/** * @param int $subscription_id ID subskrypcji * @param string $new_status Nowy status * @param string $old_status Poprzedni status */do_action('polski_pro/subscription/status_changed', int $subscription_id, string $new_status, string $old_status);Example:
add_action('polski_pro/subscription/status_changed', function (int $subscription_id, string $new_status, string $old_status): void { if ($new_status === 'cancelled') { $subscription = polski_pro_get_subscription($subscription_id); // Wysłanie ankiety o powód rezygnacji wp_mail( $subscription->get_customer_email(), 'Szkoda, że odchodzisz', 'Powiedz nam, dlaczego anulujesz subskrypcję: https://example.com/ankieta' ); }}, 10, 3);polski_pro/subscription/renewal_created
Section titled “polski_pro/subscription/renewal_created”Action fired after a renewal order is created.
/** * @param int $order_id ID zamówienia odnowienia * @param int $subscription_id ID subskrypcji */do_action('polski_pro/subscription/renewal_created', int $order_id, int $subscription_id);Example:
add_action('polski_pro/subscription/renewal_created', function (int $order_id, int $subscription_id): void { $order = wc_get_order($order_id); $order->add_order_note( sprintf('Zamówienie odnowienia dla subskrypcji #%d', $subscription_id) );}, 10, 2);polski_pro/subscription/renewal_paid
Section titled “polski_pro/subscription/renewal_paid”Action fired after a renewal order is paid.
/** * @param int $order_id ID zamówienia odnowienia * @param int $subscription_id ID subskrypcji */do_action('polski_pro/subscription/renewal_paid', int $order_id, int $subscription_id);Renewal reminder hooks (1.8.2+)
Section titled “Renewal reminder hooks (1.8.2+)”The reminder engine (14 + 7 days before renewal by default) exposes filters and actions:
// Customise windows (days before renewal)add_filter('polski_subscription_reminder_windows', fn ($w) => ['first' => 21, 'second' => 7, 'last' => 1]);
// Subject / body / headers filtersadd_filter('polski_subscription_reminder_subject', fn ($s, $sub, $type) => "[$type] $s", 10, 3);add_filter('polski_subscription_reminder_body', fn ($b, $sub, $type) => $b . "\n\nThanks!", 10, 3);add_filter('polski_subscription_reminder_headers', fn () => ['Content-Type: text/html; charset=UTF-8']);
// Skip a specific subscriptionadd_filter('polski_subscription_skip_reminder', fn ($skip, $sub) => $sub->productId === 42, 10, 2);
// Observe dispatchadd_action('polski_subscription_reminder_sent', fn ($sub, $type, $days) => null, 10, 3);add_action('polski_subscription_reminder_failed', fn ($sub, $type) => null, 10, 2);Price-change notifications (1.8.3+)
Section titled “Price-change notifications (1.8.3+)”SubscriptionRepository::updateRecurringAmount() detects an amount change and emails the customer with old/new price, effective next billing date and a one-click cancel link (EU consumer-protection requirement).
add_action('polski_subscription_amount_changed', function (int $id, float $prev, float $next) { error_log("Subscription $id: $prev -> $next");}, 10, 3);
add_filter('polski_subscription_amount_change_body', fn ($body, $sub, $prev, $next) => $body, 10, 4);add_action('polski_subscription_amount_change_notified', fn ($sub, $prev, $next, $sent) => null, 10, 4);Admin panel
Section titled “Admin panel”Subscription list
Section titled “Subscription list”Go to WooCommerce > Subscriptions. The table contains:
- subscription ID
- customer (first name, last name, email)
- product
- status
- price and cycle
- next renewal date
- creation date
Available filters: status, product, creation date.
Editing a subscription
Section titled “Editing a subscription”The administrator can:
- change the subscription status
- change the next renewal date
- change the price (affects subsequent renewals)
- add a note
- browse status history and associated orders
Common issues
Section titled “Common issues”Renewal orders are not being created
Section titled “Renewal orders are not being created”- Check if WP-Cron is working properly (
wp_cronis being called) - Go to Tools > Scheduled Actions and check if the
polski_daily_maintenancetask is scheduled - Verify that the subscription has “Active” status and a correct renewal date
Customer does not receive reminders
Section titled “Customer does not receive reminders”- Check the WooCommerce email configuration
- Verify that the reminder email template is enabled
- Check the “Reminder days” setting - whether it is greater than 0
Subscription does not change status after payment
Section titled “Subscription does not change status after payment”- Check if the renewal order has a correct association with the subscription
- Verify WooCommerce logs for errors
- Check if the payment gateway correctly changes the order status