The development of this version has cost €4,250. The cost of the first version was €38,000. The total cost since the first version is €46,610, but the cost for you is only the license from €80.
New 3.0.x branch of the plugin Advanced Subscriptions for WooCommerce. It is a major version: it introduces purchase options on the product page ("One-time purchase" or "Subscribe and save"), the optional subscribe and save discount with its own rules, complete Spanish translation, and the ability for the customer to change the quantity and frequency of their subscription from My Account. Additionally, it brings a complete security audit and a long list of fixes in renewals, plan changes, discounts, and payment gateways.
Branch versions
3.0.0
Important:
- Recommended update for all stores: includes security and billing fixes in the included gateways, in My Account, and in renewals.
- The "One-time purchase / Subscription" selector that appeared under the price disappears and is replaced by the new purchase options widget. If your theme or any code snippet depended on it, review it before updating.
- The custom start date module is disabled in 3.0.0 and its settings section is not displayed, also in stores that had it enabled: it showed the chosen date, but the subscription started and was charged at the moment. It will return, finished, in a later version.
- The renewal reminder email is disabled by default. If you had it saved as enabled, it will be disabled once you update so that your customers do not receive surprise emails; you can reactivate it whenever you want.
- Upon updating, subscriptions that were left "Pending cancellation" will be canceled on their next payment date, or within twelve hours if that date has already passed. You will then receive their cancellation emails.
- Upon updating, active subscriptions with the next payment date in the past and nothing scheduled will start charging on the next date of their cycle. The overdue period is not charged and a note remains on the subscription.
New:
- Purchase options on the product page: "One-time purchase" or "Subscribe and save", as a native and manageable group of options with the keyboard, with the savings highlighted in a label. It works on simple and variable products (by variation) and in classic and block themes. The preselected option is chosen in the settings.
- Subscribe and save (disabled by default; nothing changes until you activate it): the subscription price is the normal product price minus a percentage (from 1% to 50%), which can come from a product or variation setting, the first matching rule, or the global setting. You can also discount the first order and limit the number of discounted orders. Everything is saved in the subscription upon signing up, so changing the settings later never changes its price.
- New WooCommerce › Subscribe & Save screen with rules ordered by conditions (price above or below an amount, category, tag, or specific products). The first matching rule wins. Rules can be moved up, down, dragged to reorder, and deleted in two steps.
- The customer can choose the delivery frequency within the periods and limits allowed by the store, unless the product has it blocked.
- In the classic cart, each line that allows it can be switched between one-time purchase and subscription, with its frequency. The cart and payment totals (classic and block) show a row with the savings from Subscribe and save.
- In My Account, the customer can change the quantity and frequency of their subscription. The change applies from the next renewal, with a preview of the new amount and new date.
- Each line of a product that offers both options shows "Purchase: one-time purchase" or "Purchase: subscription", with its conditions, in the cart, payment (classic and block), order, My Account, order confirmation, and emails. A subscription of N units is created and renewed for N units.
- Renewal discount tiers can be added to the Subscribe and save discount or applied after it: first Subscribe and save while it lasts and then the tiers (it is a setting). A plan change takes the tiers from the new product.
- Spanish translation included: the entire plugin, with the included gateways of Redsys, Bizum, Google Pay, and Inespay. A Spanish store no longer shows texts in English at checkout, in My Account, in emails, or in settings.
- Upon updating, subscriptions that renew with a cycle different from their product appear in an admin notice with the "Align with the product" button to align them.
Fixed:
- The translations included in the plugin folder
languages/are truly loaded. In WordPress 6.7 and later, they were searched in a folder that does not exist, so only those installed inwp-content/languages/plugins/. - A subscription canceled by the customer in My Account, or by the store from the admin, now truly ends. If it had no end date, it remained forever in "Pending cancellation": it was never canceled, the canceled subscription email did not go out, and a store that grants access based on subscription status continued to do so. Now it cancels when the already paid period ends. New filter
aswc_prepaid_term_end. - A payment retry charges each period at most once. With a pending charge, or one that expired after the bank approved it, the retry could create and charge a second renewal of the same period.
- When a retry pays a failed renewal with a new renewal order, the customer can no longer also pay the failed order (in checkout, in My Account, or with the admin action "Retry pending order payment"). If there was already a payment in progress when the retry was executed, it is marked on both orders for you to decide on the refund.
- Two simultaneous renewal executions for the same subscription (multiple Action Scheduler batches, or a WP-CLI executor alongside WP-Cron) can no longer charge it both.
- Stripe: a renewal whose response is lost (a timeout, a server stopping halfway through the request, a proxy error) is no longer marked as failed, which left it payable and allowed a retry to charge the period twice. Now it remains pending with a note on the order, is not charged in the meantime, and is checked in Stripe an hour later: it completes if the charge was made and goes to normal retries if not.
- Stripe: while a renewal is held waiting to confirm its charge, reactivating the subscription no longer allows the next execution to create and charge another renewal of the same period. The hold is also noted on the subscription.
- Stripe: a late notice of "payment failed" no longer fails a renewal that is already paid. Stripe and PayPal: a renewal no longer recharges the card that the customer had replaced.
- PayPal: when PayPal does not respond (timeout, connection error, or server error), the renewal is held for you to review, instead of being marked as failed and retried, which could charge it twice.
- PayPal and WooPayments: a renewal never remains payable when the payment plugin fails with an internal error after sending the charge. PayPal renewals are held for you to review and WooPayments ones are reconciled. Previously, a retry could charge them a second time.
- A subscription without a valid billing cycle no longer renews every day: it takes the cycle of its product or is put on hold and never charged. It is also not charged by a payment retry or manual store actions (Create Pending Renewal Order, Retry Pending Order Payment, and Retry Renewal Payment), which now reject it with a note.
- Upon updating to 3.0.0, subscriptions without a billing cycle take that of their product.
- The billing interval of a subscription product, and that of each variation, is no longer preselected to "Days": it must be chosen, or the product is not saved as a subscription.
- The "Payment" and "Billing Period" of an existing subscription are saved from its scheduling box, and an empty cycle is no longer shown as "Days".
- Billing cycle checks accept periods added by other plugins, never modify a subscription just for displaying it, and send at most one email per day to the store about subscriptions without a cycle.
- A subscription with a trial period renews on the day the trial ends, not the day it was purchased (the second charge came less than a month after the first).
- A new subscription is dated at the actual moment it is created. Its creation date was the local store time saved as UTC, so in a store east of UTC it appeared later than it actually was (two hours in Spain during summer) and new subscriptions were ordered below older ones. Subscriptions created before 3.0.0 retain their date.
- A renewal order paid by the customer is recorded: a failed renewal paid on the order checkout page, or a manual renewal, now moves the date of the next payment by an interval and schedules that payment. Previously, the subscription would reactivate without anything scheduled and would never renew again.
- A renewal with nothing to pay (a 100% recurring coupon) is recorded like any other: the subscription remains active and its next renewal is scheduled.
- The daily check of the schedule restores the missing payment action in stores with high-performance order storage (HPOS). It only searched for subscriptions among the entries and found none.
- A subscription or an order canceled, refunded, or expired after scheduling its start date no longer activates when that date arrives.
- A deleted subscription, canceled by an administrator, or refunded while a failed renewal waits for its retry no longer keeps that retry scheduled.
- Reactivating a paused subscription in My Account no longer schedules a payment retry.
- A full refund of the first order of a subscription cancels it again. The store treated that first order as a renewal, so a refunded customer remained subscribed and was charged at the next renewal.
- Renewal discount tiers apply to all renewals for which they were configured: the counter of paid renewals never advanced, so a tier starting at the second renewal or later was never applied. Now each paid renewal counts once, and a refunded renewal continues to count.
- Editing the renewal discount tiers of a product no longer changes the price of existing subscriptions. The tiers are saved when the subscription starts and are maintained as sold, including those from coupons.
- Renewal discount tiers set in a coupon, and tiers by customer role, now apply to renewals. They were saved but never used. Those from a coupon also apply to a product without its own tiers, even if 'Override Product Discounts' is unchecked.
- Payment no longer ends with a fatal error when the product has renewal discount tiers.
- The discount on the first payment applies only once and only on the first payment. It was applied twice and carried over to all renewals. It does not apply to a trial period or a plan change.
- A product with a discount on the first payment shows its actual renewal price at checkout. Both checkouts showed the discounted first payment as the price for all renewals, even though renewals were charged at full price.
- A product with a trial period purchased with a recurring coupon renews at its discounted price. It was saved with a renewal amount of 0 and renewed for free.
- The sign-up fee is charged once per subscription, regardless of the amount. A subscription purchased with quantity 3 paid the fee three times.
- With prices entered including taxes, the recurring total of the subscription is saved rounded to the store's decimals.
- Plan changes: the change is charged on the date of the next payment shown by the subscription, and the new date counts from the change (previously an upgrade granted a full period). A change never grants the trial period of the new product; the credit for the unused period is what was actually paid for it; a second line of change for the same subscription is rejected and a change order confirmed twice at once is applied only once.
- Plan changes with proration: the credit from the previous subscription applies once per line, not once per unit.
- A plan change to a variation that takes the billing period of the variable product is recognized as what it is. Previously, it was always treated as a downgrade, regardless of the prices.
- A downgrade to a variation that inherits the interval of its parent product receives its credit. It was calculated as infinite and never applied.
- A plan change maintains the billing of a subscription without an end date when its credit is added as days, the new period starts on the day of the change, and retains the discount tiers of a sign-up coupon.
- 'Stop Downgrade' and 'Allow switching only to the same interval' are disabled unless you check them. Once the settings are saved, they were read as activated and all downgrades and all changes between intervals were rejected.
- Synchronized renewal day: the first monthly renewal is on this month's day if it hasn't passed yet; all renewals remain on that day; the product sheet announces the date that is charged; 'Last day of the month' renews on the last day of each month, and a site east of UTC no longer advances the first renewal by a day at the end of its day.
- 'Let the customer choose the expiry' in a variable subscription: the expiry field offers the billing period of the product (previously it fell into 'Days') and rejects an expiry shorter than the billing interval. The same applies to a subscription created from an upsell from CartFlows.
- The limit of cancellations for trial periods of a product applies: after the indicated number of canceled trials, the customer can no longer cancel the next one.
- The Payment block shows in the order summary the billing period ('/ 1 month'), as the Cart block already did.
- The renewal figures of the Payment block follow the cart: after a coupon or a change in quantity or shipping, they no longer retain the previous amounts until the page is reloaded.
- Payment block: the first charge of a free trial (the sign-up fee, or nothing) no longer appears as an offer. The line shows what is charged now, the trial, and the renewal price.
- A variable product that mixes subscription variations and one-time purchase no longer shows its price range with a billing period, which presented the one-time purchase price as monthly. New helper function and filter.
aswc_variable_product_has_one_time_variation(). - The Redsys card icon (and the default icons of the other included gateways) no longer occupies the entire payment box in the classic checkout with a block theme. Your own logo is untouched.
- Included Redsys gateway: a renewal charged with the saved card no longer saves it again. Each renewal added another identical card to the customer's account. Upon updating, duplicates saved by previous versions are removed, retaining the one used for renewals.
- Redsys: a renewal charges the customer's most recently saved card, not the oldest, and a card already saved is never saved again for customers with more than ten cards.
- A cancellation in Redsys, Bizum, or Google Pay cancels the order in the store. Previously, it remained pending.
- Payments with cash on delivery, transfer, or check, and manual subscriptions, send the customer the renewal invoice with the link to pay it. Previously, the customer knew nothing until the store used 'Retry Renewal Payment'. New filter.
aswc_send_manual_renewal_invoice. - 'Retry Renewal Payment' is offered again in a pending renewal order, and the email the store receives about a failed renewal indicates that it is a renewal and names its subscription.
- The store receives the email of a failed renewal only once. The plugin sent its own copy along with WooCommerce's.
- The renewal reminder email is sent before the renewal when the store activates it. It was scheduled and never sent.
- The email 'Subscription on hold to active' is sent when the store reactivates a subscription on hold from its editing screen.
- The default subject of five emails (canceled, expired, on hold, paused, and reactivated) misspelled 'Subscription'.
- The admin links to the subscriptions screen work again: the plugin settings link, the subscription link in the order notes, the return after pausing, reactivating, or canceling, 'Go Back', and the CSV export ended in 'Sorry, you do not have permission to access this page'.
- The trash of the subscriptions list offers 'Restore' and 'Delete permanently', to restore or delete a specific subscription.
- The REST route
aswc-view-subscriptionreturns the subscriptions. It filtered by a metadata key without its underscore and returned none. - A JavaScript error disappears on the classic cart and checkout pages: the block script was executing where there are no blocks.
- WordPress 6.7 and later no longer logs the warning 'translation loading was triggered too early' on each request. Two PHP warnings also disappear in the store and on the product editing screen.
- The translation template (.pot) again covers all texts: about 360 could not be translated, including the HTML invoice email for renewal.
- Accessibility: all fields of the product subscription panel (simple, multi-product, and by variation) now have a name that announces it to the screen reader.
- Saving a subscription at the beginning of an admin request (for example, from admin-ajax or admin-post) no longer ends with a fatal error.
- Uninstalling the plugin also removes its transient data.
Security:
- Redsys, Bizum, and Google Pay only accept the result of a payment when its signature is valid. A forged return to the store could mark an order as paid.
- Payment notifications from Inespay are authenticated. A notification whose signed amount does not match the order leaves it pending, and a repeated notification for an already paid order is ignored.
- The administration links to pause and reactivate a subscription require permission to edit orders, a valid link, and the expected status. A reactivation could be triggered without being logged in.
- License and update checks always verify the server certificate, and an update package is only accepted if it comes from the license server via https.
- In My Account, the details of a subscription, its list of renewals, and its payment method change (including Stripe) are only available to the customer to whom it belongs.
- Customer actions to pause, reactivate, and cancel are decided based on the saved state of the subscription and the store settings, so the minimum period and trial cancellation limit can no longer be skipped. A link shown before updating fails once; upon reloading the page, a working one appears.
- The start date submitted by a customer is only accepted if it is one of those offered by the product.
- The Payment block always creates the subscription when the cart contains it; a request parameter could skip it.
- A plan change only gives prorated credit for a customer's own active subscription, and each credit is spent only once. A refunded period does not generate credit.
- Reinforcements of the security audit of 3.0.0: the update routines and the configuration of the vault of PayPal are only executed for administrators; the bulk action of custom start date checks the user and the request; an end-of-period action only ends subscriptions that are waiting to end; the scheduling restorer never retries holds decided by the store, and the included Redsys gateways no longer write the signature key to the debug log.
- The product discount tab and the discount fields of each variation are only saved for a user who can edit that product (defense in depth).
Development:
- The "One-time purchase / Subscription" selector that was printed under the price has been removed; it is replaced by the new widget. The AJAX action
aswc_onetime_purchaseis still logged as obsolete and does nothing (it is logged at most once a day withWP_DEBUG). Checkdocs/reference/hooks-and-extension-points.md. - It is removed
ASWC_Admin::aswc_admin_reactivate_onhold_subscription()and its hook frominit: it was the handler of a link that no screen displayed. - New filters:
aswc_prepaid_term_end,aswc_send_manual_renewal_invoiceandaswc_variable_product_has_one_time_variation.
Compatibility:
- Tested up to WordPress 7.1 and WooCommerce 11.1.0.
- Requires WordPress 6.5 or higher, WooCommerce 8.0 or higher, and PHP 7.4 or higher.
- Fully compatible with WooCommerce high-performance order storage (HPOS) and with the Cart and Payment blocks.
- Still works autonomously, without relying on the WooCommerce Subscriptions extension.







