ReCurr – Release Notes
Professional changelog for ReCurr – Recurring Billing for WooCommerce
About Version Numbers
ReCurr follows semantic versioning (e.g., 2.4.26). The version numbers reflect iterative development and testing to ensure reliability and stability. We release updates frequently to improve features, fix bugs, and enhance your experience.
Current Version: 2.8.8
Released: 20 October 2026
ReCurr is a mature, stable subscription billing plugin designed specifically for South African businesses using WooCommerce and PayFast.
For the recent release history with customer-facing context, see Recent Releases below.
Plans & Pricing
ReCurr is available in three tiers. Every tier includes all core subscription billing features. Plus unlocks advanced billing tools, and Pro adds a complete CRM and Affiliate platform on top.
Standard — R99/mo
Everything you need to start selling simple subscriptions.
Plus — R159/mo
Advanced billing features for businesses that want flexible pricing (variable subscriptions) and plan management.
Pro — R349/mo
Plus features + the ReCurr Pro plugin (separate install) which adds a complete CRM, marketing automation, email campaigns, and an affiliate / referral platform with PayFast Split commission payments. The Pro key unlocks both base ReCurr (all Plus features) and the ReCurr Pro plugin from a single licence.
See the full feature breakdown below, and the Plan Comparison table for a side-by-side view.
Feature Overview
This section highlights the key features available in ReCurr, organized by category. Features marked with (Plus) require a Plus licence.
Core Subscription Features (All Plans)
Flexible Billing Cycles
Monthly Billing
- Pro-rata billing for mid-month signups
- Aligned with South African billing practices (25th invoice, 1st payment)
- Automatic date calculations
- Smart extension logic for end-of-month signups
Quarterly Billing
- Anniversary-based renewals every 3 months
- Full payment upfront
- Consistent renewal dates
Annual Billing
- Anniversary-based renewals once per year
- Full payment upfront
- Maximum value for customers
Weekly Billing
- Anniversary-based renewals every 7 days
- Ideal for short-term services
- Flexible micro-subscriptions
Pro-rata Intelligence
Automatic Calculations:
- Charges only for remaining days when customer signs up mid-month
- Applies exclusively to monthly subscriptions
- Clear explanation shown at checkout
Smart Extension Logic:
- If signup occurs within 7 days of month-end, automatically extends billing
- If pro-rata amount is less than R5.00 (PayFast minimum), combines months
- Charges current partial month + full next month
- Sets next payment to +2 months automatically
Customer Communication:
- Yellow information box at checkout explains pro-rata charges
- Email notifications detail billing breakdown
- Transparent pricing always displayed
Free Trial Periods
7-Day Free Trial — No Card Required (All Plans):
- Customers start their trial instantly with no credit card and no payment
- The trial licence/access is granted immediately at signup
- Before the trial ends, customers receive reminder emails with a one-click magic link to add their card and continue
- If they add a card, the subscription converts automatically (pro-rata first charge on monthly plans)
- If they do nothing, the trial simply ends — no charge is ever made
- A short grace period after trial end lets late-converters reactivate via the same link
Why no card? Removing the card requirement at signup dramatically lowers the barrier to trying your product, and it sidesteps the PayFast R5 minimum that previously blocked R0 trial tokenisation on South African bank cards. Card details are collected later, only when the customer chooses to continue.
Trials bought alongside another product (v2.7.11):
A basket holding a trial subscription and a once-off product is not a no-card signup — there is real money to collect at checkout, so the customer pays for the once-off item there and then, and their card is stored in the process. From 2.7.11 ReCurr treats that trial accordingly:
- The trial still runs free for its full term; only the once-off item is paid for at checkout
- Emails for these customers say what will actually happen — that the subscription continues on the card they already gave, and how to change it or cancel — rather than asking for a card ReCurr already holds
- When the trial ends the pro-rated amount is charged automatically, the subscription goes active, and no magic link is involved
- A declined charge holds the subscription for 7 days and cancels it if unsettled, exactly as a lapsed no-card trial does
A basket holding a trial on its own is unchanged in every respect — it remains the no-card flow described above.
Flexible Trial Durations (Plus):
- Choose 7, 14, 21, or 28-day trial periods per product
- Standard plans are limited to 7-day trials
Trial length must fit the billing period (v2.7.12):
A trial may not be longer than one billing period — a 28-day trial on a weekly product would give the customer four billing periods free. Exactly one period is fine and always was: “your first week free” on a weekly product is a real offer and is unaffected.
- The maximum trial for each term is: day 1, week 7, month 31, quarter 92, year 366 days
- These maximums are multiplied by your billing interval, so an “every 2 weeks” product allows up to 14 days and an “every 30 days” product up to 30
- The shortest trial ReCurr offers is 7 days, so a product billed daily (or every few days) cannot carry a trial in practice
- If you save a product with a trial that doesn’t fit, ReCurr switches the trial off and tells you why, naming the product, the trial length, the billing term and the maximum for that term. The duration you picked stays in the field so you can correct it
- Products using the billing cycle toggle (Plus) are judged against the shortest cycle you offer, since that is the one a customer can choose. Offering monthly alongside anything longer means the monthly term sets the limit — 31 days — so every trial ReCurr offers still fits. Your product’s own billing term counts too: it is what bills if a customer never touches the toggle
Self-Service Subscription Management
Customer Cancellation:
- Customers can cancel their own subscriptions from My Account
- Subscription remains active until the end of the current billing period
- Trial cancellations are immediate with no charge
- Clear confirmation messages
Plus (v2.7.0): stores on a Plus licence can optionally add pro-rata refunds on cancellation, a retention save flow, and pause & resume on top of this. See Plus Features below.
Manual Invoice Pay Now
Online Payment for EFT Invoices:
- Customers receive a Pay Now link on manual EFT invoices
- Pay securely via PayFast (Instant EFT or card)
- One-click payment from the invoice email
- Admin can also trigger payment from the subscription dashboard
- However the invoice is settled — paid online by the customer, or marked paid by you — the subscription is renewed the same way: licence extended, payment recorded, renewal email sent (v2.7.22)
Update Payment Details
Customer Card Management:
- Customers update their card from My Account through a R5.00 card registration, credited in full to their account (it comes off the next payment) — a real charge, so the bank runs its normal 3D Secure with an OTP (default again from v2.7.26)
- PayFast’s free “Update card details” page is available as an opt-in for stores that want it; some South African banks refuse its zero-amount check (v2.7.24, opt-in from v2.7.26)
- The failed-payment email links the customer to their subscription page in My Account, where Update Card lives (v2.7.26)
- New card used for all future renewals
- No disruption to the active subscription
- A subscription with no usable card on file registers one through a R5.00 verification charge that is credited back to their account
- Each card registration is credited once: a later PayFast notification for a charge to that card is recorded in the Activity Log and changes nothing else (v2.8.5)
- The “Payment method updated” email states what the next renewal will actually charge, less any account credit — on a free trial, the first payment in full (v2.8.6)
- The card it replaced is cancelled at PayFast once the new card is stored, so it can no longer be charged from the PayFast dashboard — never a card another subscription uses (v2.8.8)
- Offered on card subscriptions only — a Manual EFT subscription is paid by invoice (v2.8.8)
Plus Features (Plus Plans)
Billing Cycle Toggle
Customer Choice at Checkout:
- Customers choose between monthly, quarterly, and annual billing on the product page
- Real-time price update as they toggle between cycles
- Savings displayed for longer commitments
- One product listing covers all billing options
- Every renewal charges the chosen cycle’s price (v2.8.7): a card subscription bought quarterly or annually renews at the quarterly or annual price it was bought at
Quarterly & Annual Discounts
Flexible Discount Types:
- Percentage discounts – e.g., 20% off annual subscriptions
- Fixed amount discounts – e.g., R200 off annual price
- Configure quarterly and annual discounts independently
- One price on every path (v2.7.29): the price the product page shows is what checkout charges, what the subscription records, what a trial converts at, what a manual EFT invoice asks and what a plan switch charges. A Custom Annual Price or Custom Quarterly Price is used as it stands; an annual or quarterly product without the billing cycle toggle, with no discount and no custom price, is charged its Regular price once per billing period
Real-time Preview:
- Admin sees calculated discounted price while editing product
- Savings amount displayed automatically
- Monthly equivalent pricing shown
Customer Display:
- Clear savings message on product page
- Discounted price vs monthly equivalent comparison
- Encourages long-term commitments
Example:
Monthly price: R99
Annual base: R1,188 (R99 x 12 months)
Discount: 20%
Final annual price: R950.40
Customer saves: R237.60 per year
Plan Switching (Upgrade / Downgrade)
Next-Cycle Plan Changes (default):
- Customers request a plan change from My Account
- Change is queued and applies at the next renewal date
- No disruption to current billing period
- Admin and customer notified of pending change
Plan Groups:
- Group related products together (e.g., Basic, Standard, Premium)
- Customers can only switch between products in the same group
- Prevents invalid plan combinations
Cancel Pending Changes:
- Customers can cancel a queued plan change before it takes effect
- Original plan continues unchanged
Pricing (v2.7.29):
- The Change Plan page quotes the price the switch charges — the new plan’s own price for the chosen billing cycle, discount included
- A plan can be switched to on the billing cycles the page offers for it; a request for any other cycle is refused
Immediate Pro-Rata Plan Switching (v2.7.0 — opt-in)
Instant upgrades for quarterly and annual customers:
- An annual customer who wants to upgrade no longer waits up to 12 months — the change applies immediately
- ReCurr credits the unused portion of the current term and charges only the difference
- Credit is valued at the plan’s full monthly rate, so the unearned share of the annual/quarterly discount is forfeited on early exit — completing the term remains the way to earn the discount
- Credit can never go negative (no charge-backs); a credit larger than the new plan’s price carries forward to the next renewal
- Billing date resets to the switch date; the new-tier licence key is issued and the old key expired
- Downgrades and lateral moves stay queued to renewal (with an optional lever to make downgrades immediate too)
- A server-computed consent screen shows the credit, the exact amount charged now, and the new billing date before anything is charged
- Handles the PayFast R5 minimum by charging exactly R5 and holding the small balance back as credit — the customer’s total cost is unchanged to the cent
- Optional Plan rank field per product; by default plans are ranked by monthly price, so most stores need no setup
- Off by default — with the setting off, plan switching behaves exactly as before
Cancellation Refunds & Retention (v2.7.0 — opt-in)
Pro-rata refunds on cancellation:
- Refund a quarterly/annual customer for time they haven’t used when they cancel mid-term
- Same fair formula as plan switching — unused time at the full monthly rate; the free-month benefit is not refundable
- Money refunded via the PayFast Refund API, with a native WooCommerce refund recorded on the order
- Access ends within 24 hours (the licence key is expired immediately)
- A failed refund aborts the cancellation cleanly — the subscription stays active
- If PayFast refuses a refund (v2.8.7), the customer is told it could not be processed and how to reach you; PayFast’s reply goes to a note on the subscription and to the log. Test one small refund with your own card before you rely on it
Retention “save” flow:
- Replaces the bare “are you sure?” prompt with a short reason survey
- Offers a tailored alternative — a change-plan link for price/usage objections, or a support contact for feature/technical issues
- Cancellation reasons are saved and emailed to you for personal follow-up
- Both off by default — each is an independent setting
Pause & Resume (v2.7.0 — opt-in)
Freeze a subscription instead of losing the customer:
- Customers pause from My Account; admins can pause from the subscription screen
- No payment is taken while paused — paused subscriptions are simply never selected for renewal
- On resume, the next payment date, end date, and licence expiry all shift forward by exactly the paused duration
- Term length and discount are unchanged — nothing is banked and nothing is forfeited
- 90-day cap with auto-resume (adjustable, or removable for unlimited pauses)
- Works on any billing period and any payment method
- Off by default — and a paused customer can always resume even if you later switch the feature off
Variable Subscription Products (v2.8.0 — opt-in)
Sell each option of a variable product as a subscription:
- Sizes, colours, plans (monthly or yearly), or “buy once” beside “subscribe” — each option (variation) with its own price
- Each option can carry its own billing period and interval, free trial, and annual or quarterly pricing, or use the parent product’s settings (“Same as parent”)
- The product page shows a price range with each option’s billing period; choosing an option shows its own price and period
- The subscription records the option and the attributes the customer chose; every renewal order and My Account name them, and stock comes off the option
- Subscriptions → Add New offers the options for manual EFT subscriptions
- Off by default (Subscriptions → Settings → General → Variable subscription products). Once you sell variable subscriptions, leave it on
- Not yet available: moving an existing subscription to another option (cancel and subscribe again)
Payment Processing (All Plans)
PayFast Integration
Secure Recurring Payments:
- Card tokenisation for automatic renewals
- PCI-compliant payment processing
- Secure storage of payment methods
- South African payment gateway built for local businesses
Ad Hoc Billing:
- Automatic charging on renewal dates
- No customer action required
- PayFast Ad Hoc API integration
- The WooCommerce order number sent as the PayFast Payment ID, on every payment and card registration (v2.8.4)
- Signed by PayFast’s official PHP library (payfast-php-sdk 1.1.6), bundled inside ReCurr, and sent through WordPress’s own HTTP functions with a timeout (v2.8.8)
Payment Gateway Features:
- Sandbox mode for testing
- Live mode for production
- ITN (Instant Transaction Notification) support
- Passphrase security
- Payment forms signed by PayFast’s official PHP library, with their fields in PayFast’s documented order (v2.8.8)
- PayFast’s payment confirmation for you sent as set in your PayFast account (Settings → Integration → Email Confirmation), never to your customer (v2.8.8)
- A card replaced through Update Card cancelled at PayFast (v2.8.8)
Supported Payment Methods:
- Visa and Mastercard (credit and debit)
- Instant EFT (for invoice payments)
- All payment methods supported by PayFast
Payment Failure Handling
Automatic Retry Logic:
- Configurable retry attempts (default: 3)
- Automatic retry schedule
- Customer notifications on failures, carrying PayFast’s decline reason and its update-card link (v2.7.23)
- A declined card is read from PayFast’s reply itself, not its outer status — a charge counts as paid only with a confirmed transaction ID (v2.7.23)
Unpaid Renewals Screen (v2.7.23):
- Lists every payment recorded as paid with no PayFast transaction behind it, with the total never taken
- Retry the stored card, or start the failed-payment reminders, per subscriber or all at once
- Keeps the billing anniversary and the licence expiry where a real payment would have put them
Subscription Status Management:
- Active – Billing normally
- Trial – Free trial period (no card on file until conversion, unless the trial was bought alongside a paid item)
- On Hold – After failed payment retries, or after a trial ended without converting — either no card was added, or the trial-end charge was declined (7-day grace period either way)
- Paused – Deliberately frozen by the customer or admin; never billed while paused (Plus, v2.7.0)
- Cancelled – Customer or admin cancelled
- Expired – Subscription ended
Email Notifications (All Plans)
Every ReCurr email — to your customers and to you — comes from your store’s “From” name and address (WooCommerce → Settings → Emails), and customers’ replies go to that address (v2.8.8).
Customer Emails
Subscription Activation:
- Welcome email upon successful signup
- Subscription details and billing schedule
- Next payment date clearly stated
Trial Started:
- Trial confirmation with end date — sent immediately (no card needed)
- Clear explanation that no payment has been taken
- What to expect when the trial ends, and how to continue
- (v2.7.11) Where the trial was bought alongside a paid item, the email instead confirms the trial is free, names the date the subscription continues on the card already given, and points to My Account to change the card or cancel
Trial Reminder:
- Sent at 72h / 48h / 24h before trial end
- No card on file: a one-click magic link to securely add a card and continue, with reassurance that the trial ends with no charge if no action is taken
- Card on file (v2.7.11): states the exact amount and date of the first charge, and links to My Account to change the card or cancel — no magic link, because no card is needed
Trial Conversion Confirmation (v2.7.11):
- When a trial with a card on file converts, the customer receives the standard payment confirmation
- On monthly plans the pro-rata confirmation email is sent alongside it — the one that explains why this first charge differs from the recurring amount. It is deferred from checkout to trial end, which is the point the charge is actually taken
Trial Ended / Grace Expired:
- Sent when a trial lapses without converting
- Distinguishes the two causes: no card was ever added, or the card on file was declined — the customer is never told they failed to give a card when they did
Renewal Notifications:
- Payment confirmation emails
- Receipt with transaction details
- Invoice number and reference
- Where account credit paid part of a renewal, the amount less the credit, and the next payment and its date (v2.8.8)
Payment Failed Alerts:
- Immediate notification on payment failure
- Instructions to update payment method
- Grace period information
Plan Change Notifications (Plus):
- Confirmation when plan change is queued
- Details of new plan and effective date
- Notification when switch takes effect
- Immediate upgrade confirmation (v2.7.0): full breakdown — old and new plan, credit applied, amount charged, any R5 hold-back, new billing date, and the new licence key
Cancellation Refund Notifications (Plus, v2.7.0):
- Refund amount and when access ends; PayFast also emails the customer about the refund (v2.8.8)
- Admin copy, plus a separate cancellation feedback email with the customer’s stated reason
Pause & Resume Notifications (Plus, v2.7.0):
- Subscription paused confirmation (with an admin copy)
- Subscription resumed confirmation, stating the new billing date — and noting when the 90-day cap triggered an automatic resume
Manual EFT Invoices:
- Monthly invoice emails with bank details
- Unique EFT reference for payment tracking
- Pay Now link for online payment
- PDF invoice attachment (when plugin installed)
- The customer’s emails and My Account name the next invoice and when it falls due — “Next invoice: 25 October 2026 (payment due 1 November 2026)” (v2.8.8)
Admin Notifications
New Subscription Created:
- Instant notification when customer subscribes
- Customer details included
- Subscription amount and billing cycle
Subscription Reactivated (v2.8.8):
- When a subscription becomes active again, with the status it came from — “[New Subscription]” is only for a first activation
Payment Received:
- Confirmation when recurring payment successful
- Transaction reference included
- Subscription renewal details
Manual EFT Subscriptions (All Plans)
Corporate Client Support
Admin-Created Subscriptions:
- Create subscriptions for corporate clients
- No credit card required
- EFT (Electronic Funds Transfer) payment method
- Perfect for enterprise accounts
Customer Search:
- Search existing customers by name or email
- Create new customers directly from subscription page
- WooCommerce customer integration
Product Selection:
- Choose from existing subscription products
- View product details and pricing
- Select the billing period from the product’s own: a product with the billing-cycle choice offers its cycles, each at the price the cart charges; any other product its own billing period (v2.8.8)
Flexible Billing:
- A product with the billing-cycle choice (Plus) billed monthly, quarterly or annually, at its own cycle prices (v2.8.8)
- Bill Every (v2.8.0): invoice once every 1 to 12 billing periods — for example every 2 months — each invoice one period’s amount
- Automatic discount application based on billing period
- Live price calculation preview
Invoice Management
Automatic Invoice Generation:
- Invoices generated on configured day (default: 25th)
- Quarterly and annual invoices on the last invoice day on or before the anniversary, ahead of the period billed (v2.8.8)
- A missed invoice run caught up at the next run — every period invoiced once (v2.8.8)
- Sent automatically via email
- PDF attachment included (with WooCommerce PDF Invoices plugin)
- Delivery failures recorded and flagged as “Not sent” beside a Resend button (v2.7.21)
Overdue Chasing (v2.7.21):
- Automatic reminders on the due date, a week later, and a final notice a week after that
- Each carries the same bank details, reference and Pay Now link as the original invoice
- Daily summary to the administrator naming every overdue invoice and what is owed
- Unpaid invoices listed on the subscription screen, in red once past due
- Nothing is suspended or cancelled automatically — that stays your decision
Bank Details on Invoices:
- Configure your business bank details once
- Displayed on all invoices automatically
- Includes: Bank name, account name, account number, branch code, branch name (optional, v2.7.3), account type
Unique EFT References:
- Auto-generated reference for each subscription
- Format: SUB-12345
- Easy payment tracking and reconciliation
Mark as Paid:
- Admin marks invoice payment as received from subscription dashboard
- Customer and admin receive confirmation emails
- Payment recorded in subscription history
Subscription Management (All Plans)
Admin Dashboard
Subscriptions Menu:
- Dedicated subscriptions menu in WordPress admin
- View all subscriptions at a glance
- Filter by status (Active, Trial, Pending, On Hold, Cancelled, Expired)
- Search by customer email or name
Subscription Details View:
- Customer information
- Subscription items and pricing
- Billing cycle and next payment date
- Change the next payment date — the date only, nothing charged (v2.8.2)
- Payment history
- Related orders
- Activity log
- Account credit — balance and every ledger entry (v2.7.27)
- Manual status changes
Quick Actions:
- Set subscription to Active
- Put subscription On Hold
- Cancel subscription
- Mark invoice as Paid
- View customer details
- View related orders
Settings Configuration
General Settings:
- Failed payment retry count
- Configurable retry attempts (1-10)
- Default: 3 attempts
Manual EFT Settings:
- Invoice day configuration (1st-28th)
- Payment terms in days (v2.7.21) — the invoice due date, and when chasing starts
- Bank details for invoices
- Payment instructions customisation
Customer Experience (All Plans)
WooCommerce My Account Integration
Subscriptions Tab:
- Dedicated “Subscriptions” section in My Account
- View all active subscriptions
- Subscription details at a glance
Subscription Information:
- Product name and details
- Current status (including trial indicator)
- Next payment date — on a Manual EFT subscription, the next invoice and when it falls due (v2.8.8)
- Payment amount
- Billing cycle
Self-Service Actions:
- Cancel subscription
- Update payment details (on PayFast’s card-update page, no charge)
- View payment history
- Change plan (Plus)
- Pause and resume a subscription (Plus, v2.7.0)
Related Orders:
- View all orders related to subscription
- Payment history
- Download invoices
Checkout Experience
Clear Pricing Display:
- Subscription billing cycle shown clearly
- Pro-rata charges explained (monthly subscriptions)
- Trial period details displayed
- Total amount displayed prominently
Billing Cycle Toggle (Plus):
- Customer selects monthly, quarterly, or annual billing
- Price updates in real-time
- Savings displayed for longer commitments
Payment Method Selection:
- Credit/Debit Card (Recurring) for automated billing
- Manual EFT (admin-created only)
Information Boxes:
- Yellow pro-rata notice for monthly subscriptions
- Trial period notice: trial end date and how continuation works — “No card required” is shown only on a trial-only basket, where it is true (v2.7.8), and only where the trial fits inside one billing period (v2.7.12)
- Explanation of combined billing (when applicable)
- Mixed cart notifications (subscription + one-time products)
- One renewal schedule per order: a second subscription product on a different billing schedule is refused when it is added to the cart, and a cart already holding two schedules is refused at checkout (v2.7.28)
Secure Checkout:
- PayFast secure payment processing
- SSL/HTTPS required
- PCI-compliant card storage
WooCommerce Blocks Support:
- Full compatibility with the new WooCommerce Blocks checkout
- Trial and pro-rata information displayed in Blocks checkout
- Seamless experience on both Classic and Blocks checkout
Technical Features
Database Management
Custom Tables:
- Efficient subscription storage
- Optimised query performance
- Relationship tracking
Subscription Meta:
- Detailed subscription information storage
- Pro-rata calculation details
- Extension reason tracking
- Payment history
Scheduled Tasks
Automated Renewals:
- WP-Cron based scheduling
- Automatic payment processing on renewal dates
- Retry logic for failed payments
Invoice Generation:
- Scheduled monthly invoice creation (Manual EFT)
- A missed run caught up the next morning (v2.8.8)
- Automatic email sending
- PDF attachment generation
Trial Lifecycle (hourly):
- Reminder emails at 72h / 48h / 24h before trial end
- Trial-end processing — converts and charges where a card is on file, or holds and invites a card where none is (v2.7.11)
- Grace-period expiry — cancels trials that never converted, whether no card was added or the charge was declined
- Cleanup of signups abandoned at PayFast, restricted to those genuinely sent there for a card (re-enabled v2.7.11)
Date Calculations:
- Accurate next payment date calculations
- Timezone handling
- Month-end date edge cases handled
Self-Healing:
- Renewal, payment-retry and trial jobs reschedule themselves if a site’s scheduled events are lost (migration, cron-reset plugin, database restore)
- Deactivating ReCurr clears all of its scheduled jobs
Integration Support
WooCommerce Integration:
- Native WooCommerce product types
- Order system integration
- Customer account integration
- Email template system
- WooCommerce Blocks checkout support
PayFast API:
- Ad Hoc billing API
- ITN (Instant Transaction Notification)
- Tokenisation API
- Refunds — the pro-rata refund and the account-credit refund on cancel
- Card cancellation — a card replaced through Update Card (v2.8.8)
- Every API request signed by PayFast’s official PHP library (v2.8.8)
- Sandbox and live modes
Optional Plugin Support:
- WooCommerce PDF Invoices & Packing Slips (invoice PDFs)
- SMTP plugins (reliable email delivery)
Licence Management
Automatic Updates:
- Enter your licence key in the plugin settings
- Receive automatic update notifications in WordPress
- One-click updates from the Plugins page
Tier Detection:
- Plugin automatically detects your plan (Standard or Plus) from your licence key
- Features unlock based on your active plan
- Upgrade seamlessly by purchasing a Plus licence
Plan Comparison
Feature Standard Plus Pro All billing periods (monthly, quarterly, annual, weekly) Yes Yes Yes Pro-rata billing (monthly) Yes Yes Yes 7-day free trial (no card required) Yes Yes Yes PayFast tokenised payments Yes Yes Yes Manual EFT subscriptions Yes Yes Yes Manual EFT invoiced every 1-12 periods (Bill Every) (v2.8.0) Yes Yes Yes Invoice Pay Now (Instant EFT) Yes Yes Yes Update payment details Yes Yes Yes Customer self-cancellation Yes Yes Yes Admin dashboard Yes Yes Yes Email notifications Yes Yes Yes WooCommerce Blocks support Yes Yes Yes Auto-updates from WP dashboard Yes Yes Yes Pre-payment renewal reminders Yes Yes Yes USD price display Yes Yes Yes Flexible trial durations (7/14/21/28 days) † – Yes Yes Billing cycle toggle (customer chooses) – Yes Yes Quarterly discounts – Yes Yes Annual discounts – Yes Yes Plan switching (upgrade/downgrade) – Yes Yes Plan groups – Yes Yes Immediate pro-rata plan upgrades (v2.7.0) – Yes Yes Pro-rata refunds on cancellation (v2.7.0) – Yes Yes Cancellation retention / save flow (v2.7.0) – Yes Yes Pause & resume a subscription (v2.7.0) – Yes Yes Variable subscription products (v2.8.0) – Yes Yes CRM (Pro plugin) — contacts, lifecycle stages, tags, segments, tasks – – Yes Email campaigns — segmented send, merge tags, open/click tracking – – Yes Marketing automation — 18 triggers, 10 actions, branching workflows – – Yes Affiliate / referral platform — single-level commissions, PayFast Split payouts, fraud detection – – Yes PayFast Split for automatic commission payments – – Yes Reports & analytics — MRR, churn, LTV, growth, affiliate performance – – Yes † Trial length is capped by the billing period on every tier — a trial may not be longer than one billing period (week 7 days, month 31, quarter 92, year 366, multiplied by your billing interval). See Trial length must fit the billing period above.
About the Pro tier: Pro features ship in a separate plugin (ReCurr Pro). A
RECPRO-licence key authorises both plugins simultaneously — one key, one bill. See the ReCurr Pro Installation Guide for setup.
Recent Releases
This section covers recent releases with customer-facing context — what each release means for you, why it shipped, and whether you need to update. Earlier versions are summarised in the Version History Summary further down.
2.8.8 — 20 October 2026 — PayFast’s official library, refunds that go through, emails from your store, and fixes for free trials, account credit and Manual EFT invoices
ReCurr now needs PHP 8.1 or newer. WordPress does not install this update on a site with older PHP: such a site stays on 2.8.7, and can update once its PHP is upgraded. If this version is copied onto a site with older PHP some other way, ReCurr does not start, and administrators see a notice saying why, instead of an error. You can check your version under Tools → Site Health → Info → Server.
What it means for you: ReCurr now uses PayFast’s official PHP library to sign its requests to PayFast and its payment forms. PayFast refunds — the pro-rata refund on cancel and the refund of account credit on cancel — now go through. A card replaced through Update Card is cancelled at PayFast. ReCurr’s emails come from your store’s own “From” name and address, and PayFast’s payment confirmation meant for you no longer reaches your customer. Free trials, account credit, Manual EFT invoicing, plan changes and several emails are fixed. A customer paying at PayFast sees nothing new. No new setting.
New — ReCurr now uses PayFast’s official PHP library (payfast-php-sdk 1.1.6). Its requests to PayFast’s API — renewal charges, refunds and the new card cancellation — are signed by the library and sent through WordPress’s own HTTP functions, with a timeout. The library, and the HTTP library it needs, are bundled inside ReCurr under ReCurr’s own names, so they cannot clash with another plugin that bundles its own copy.
The payment forms are signed by PayFast’s library too — checkout, Update Card, a Manual EFT invoice’s Pay Now and a trial’s activation — with their fields in the order PayFast documents. A customer sees nothing new. Where the library cannot sign a form the way PayFast’s documentation does — a passphrase holding a character other than letters, digits, “-“, “_” and “.”, or a subscription with no passphrase set — ReCurr signs it as before, and WooCommerce → Status → Logs says why; nothing is refused.
Fixed — PayFast refused every refund ReCurr asked for: the refund when a customer cancels with a pro-rata refund, and the refund of account credit when a subscription is cancelled. Since 2.8.7 refunds were sent to PayFast’s refund address, but PayFast requires every refund request to say whether PayFast emails the customer about the refund, and ReCurr’s request did not, so PayFast answered “Failed”. Nothing was refunded and no money moved: the cancellation with a refund was not made, and the credit stayed on the cancelled subscription for you to refund by hand. The request now says it, set so that PayFast also emails the customer, as PayFast’s own library does.
Refunds refused before this update are not repeated. Find them in the Account Credit box and the Activity Log (“Cancel-with-credit refund: … failed”) of your cancelled subscriptions, and refund them in your PayFast dashboard.
New — when a customer replaces their card with Update Card, ReCurr now cancels the card it replaced at PayFast, once the new card is stored. PayFast keeps every saved card active in its Tokenization list until it is cancelled, and a card there can still be charged by hand from PayFast’s dashboard. ReCurr never charges a replaced card, so it is now cancelled. A card is cancelled only when ReCurr is certain it is out of use: never when another subscription uses the same card, never when the card did not change, and never on a store that has moved its billing to the ReCurr platform. If PayFast does not cancel it — it refuses, or does not answer within 15 seconds — the card update still stands, and the subscription’s Activity Log and the card-update order’s notes say so; you can then cancel the card by hand in PayFast’s Tokenization list. To keep replaced cards active, add add_filter( 'crb_payfast_cancel_replaced_card', '__return_false' ). Cards replaced before this update are not touched: ReCurr does not keep a replaced card, so it cannot find them.
Changed — ReCurr’s emails now come from your store: the “From” name and address set in WooCommerce → Settings → Emails, the sender WooCommerce uses for its own emails. Before, ReCurr’s subscription, renewal, trial and invoice emails, and the notifications it sends you, arrived from “WordPress” <wordpress@your-site> unless a mail plugin set the sender (a mail plugin that sets its own sender still decides). Customers’ replies go to that address, and it is the address customers are asked to write to — in the card-update email, on the cancellation page and in its refund message (it was your site’s administration email address). Your notifications still go to the administration email address, or to the address under “Send renewal notifications to”.
Fixed — PayFast’s payment confirmation meant for you was sent to your customer (“You received R… from …”, and PayFast’s refund notice). ReCurr’s payment forms named the customer’s address for it. They now name none: PayFast sends it as set in your PayFast account (Settings → Integration → Email Confirmation). Customers still receive PayFast’s own receipt.
Free trials and their activation:
- Fixed — a free trial without a card whose customer then registered a card with Update Card still ended as a trial without a card. The R5.00 card registration was taken and credited, but when the trial ended the subscription was put on hold and the customer was asked for a card again; the card they had registered was never charged. Now a card registered while the trial runs is charged the first payment when the trial ends, exactly as for a trial that started with a card, and the R5.00 credit comes off the renewal after it; the trial’s reminders and the card-update email say so.
- New — once a trial without a card has ended unpaid, its page in My Account offers Activate Subscription instead of Update Card: the first payment is due, and the activation page takes it, less any account credit. A card registration that PayFast confirms only after such a trial has ended is recorded and credited, and the subscription waits for the customer to activate it.
- Fixed — with pro-rata billing switched off (Subscriptions → Settings), a monthly free trial with a card still charged a pro-rata first payment when it ended. It now charges the full month, and the next payment falls a month after the trial ends — as a sign-up without a trial, and a trial activated by the customer, already did. Trials that began before this update keep the figure their reminders name.
- Fixed — the reminder sent before a trial with a card ends could name a different amount from the one charged (on an annual or quarterly trial, and on a monthly trial with pro-rata billing off, it named a part-month figure). It now names the payment the trial’s end takes.
- Fixed — after a free trial with a card ended with a part-month (pro-rata) payment, the “Payment received” email, and your “[Subscription Payment]” email, named the trial’s end plus one month as the next payment, while the subscription bills on the 1st; the licence expiry was worked out from the same date. Both emails now name the date the subscription bills on, and the licence follows it. Nothing was charged on a wrong date.
- Fixed — activating a free trial that had account credit counted part of the credit twice when the credit was more than half the first payment. The activation page took the whole credit off the first payment, but the payment then marked only as much credit as the customer paid by card as used, and the rest came off the next renewal again (R159 a month, activated with R80.00 of credit: R37.97 paid, R37.97 of credit used, and R42.03 taken again at the next renewal). The credit is now used exactly as the page took it, once.
- Fixed — when account credit covered the whole first payment, activating the trial charged R5.00, used only R5.00 of the credit and still started a full period (R159 a month with R200.00 of credit: R5.00 paid, R5.00 of credit used, R195.00 kept). The card is now charged R5.00 — the minimum card payment — and the credit covers the rest of the first payment (R5.00 paid, R112.97 of credit used, R87.03 kept for later payments). The next payment date the activation page quotes is now always the one set, including when the first payment also covers next month.
- Fixed — account credit that left between R0.01 and R4.99 of the first payment to pay sent the customer to a payment PayFast refuses, so the trial could not be activated (an R8 plan with R5.00 of credit: R0.94). The credit now always leaves at least R5.00 to pay by card.
- Fixed — the activation priced the first payment from the product’s current price instead of the subscription’s own. A subscription to a variation, whose parent product has no price of its own, was activated for R5.00, and a price changed during the trial changed the first payment but not the renewals. The first payment now comes from the subscription’s own price (the variation’s, the billing cycle’s, the quantity’s), and the activation’s order carries the variation the customer chose.
- Fixed — after an activated subscription was put on hold (by failed renewals, for example), the “add your card” link sent when its trial ended could still open the activation page and take a part-month first payment again. The page now opens only for a running trial or one that ended without its first payment.
- The trial activation page shows the account credit the first payment actually uses — “(R117.97 gross, R112.97 credit applied)” — and what stays on the subscription (“R87.03 of your account credit stays on your subscription for later payments.”). Before, it showed the whole credit balance, and R0.00 where R5.00 was charged.
Account credit and card updates:
- Fixed — Update Card was offered on Manual EFT subscriptions. A Manual EFT subscription is paid by invoice and never charged to a card, so the R5.00 card registration bought nothing, and its credit was never taken off an invoice. Update Card is no longer offered on a Manual EFT subscription. Credit already registered on one stays in its Account Credit box and is refunded if the subscription is cancelled.
- Fixed — on a Manual EFT subscription, the Account Credit box said its credit comes off the next renewal; invoices do not take account credit. It now says the credit is refunded to the customer’s card if the subscription is cancelled — as does the card-update email of a card registration opened before this update, which also names the next invoice instead of a card charge.
- Fixed — when a subscription was cancelled and its account credit could not be refunded to the customer’s card (for example R5.00 from a card update), nothing said so; the credit simply stayed on the cancelled subscription. Now the customer’s cancellation email says “Your account credit of R5,00 could not be refunded to your card. We will be in touch to settle it.”, your cancellation email says the same so you can make contact, and the subscription’s Account Credit box says the amount could not be refunded and should be refunded by hand in PayFast. The card-update email no longer promises that the refund happens “automatically”. When a free trial is cancelled at the end of its grace period after a card was registered, its email no longer says that no card was added or that nothing was charged: it says the card registration charge was refunded, or that it could not be.
- Fixed — Update Card said the R5.00 card registration is credited to your next invoice. PayFast’s payment page, the link to register a new card and the registration’s order now say it is credited to your account; the card-update email says which payment it comes off.
- Fixed — when PayFast sent a card update’s notification twice at almost the same time (it sends one again when a slow site has not yet answered), both copies were recorded: the R5.00 card registration was credited twice and the customer emailed twice. The copies are now handled one at a time, and the second changes nothing.
- Fixed — once a card-update order had been refunded in WooCommerce, given another status by hand, or marked failed by PayFast’s notice of a later failed charge, the next charge on that card could credit the R5.00 card registration again. A card update is now completed once, whatever happens to its order afterwards. (PayFast’s notice of a later failed charge can still mark the card-update order Failed: nothing is credited or charged by it.)
- Fixed — a payment PayFast confirmed without a card token (a card update or a free trial’s activation) was marked Failed and recorded nowhere but at PayFast. It is now recorded (the card registration’s R5.00 credited, or the activation’s payment), the order is put On hold with a note for your review, and you are emailed. The card on file is unchanged; a trial whose activation is held this way is not cancelled at the end of its grace period, and its activation page takes no second payment while the order is on hold.
- Fixed — when a credit entry was split between a payment and what was left of it, the remainder was written without a check: if the database refused it, the remainder was lost. The remainder is now checked; if it cannot be written, the entry is kept whole for later payments and the failure is logged.
Manual EFT invoicing and Subscriptions → Add New:
- Fixed — a monthly Manual EFT subscription added on Subscriptions → Add New on or after the invoice day was never invoiced for one month. An invoice raised on the invoice day is for the next month (the 25th’s invoice is paid around the 1st), but a subscription added on, say, 26 September had a first invoice for the rest of September only, and its first scheduled invoice, on 25 October, billed November: October was never invoiced. With Send first invoice immediately ticked, the first invoice is now the rest of the month and the next month in full (R550 a month, added 26 September: R641.67); unticked, the first scheduled invoice carries every month up to the one it bills (added 10 September: R935.00 on 25 September; added 26 September: R1,191.67 on 25 October). Without pro-rata the first invoice is the full price, as before; unticked and added on or after the invoice day, the first scheduled invoice now also carries the month that was lost (R1,100.00). Subscriptions billed every 2 to 12 months, and invoices already raised, are unchanged.
- Fixed — a quarterly or annual Manual EFT subscription showed its anniversary as the next payment date, while its invoice went out on the invoice day after it, up to a month later (added 9 October: shown 9 January, invoiced 25 January). It is now invoiced on the last invoice day on or before its anniversary — ahead of the period it bills, as a monthly one is (25 December, payment due 1 January) — and that is the date shown: on the subscription screen, in My Account, in the emails, and in Change next payment date, which for these subscriptions now names the invoice day on or before the date you pick. A subscription added before this update is invoiced on the invoice day before its date; when you update, one whose invoice day has just passed is invoiced at the next daily run. Until that first invoice, your subscription list and the subscription’s screen still show its anniversary, while My Account, the emails and the Change next payment date panel already name the invoice day. With Send first invoice immediately unticked, the first quarter or year is now invoiced on the next invoice day — before, it was never invoiced.
- Fixed — a morning on which the Manual EFT invoice run did not run (a site with no visitor that morning, a scheduled task that failed) lost a monthly subscription’s invoice for that month, and made a quarterly or annual one a month late. The run now looks at every subscription every day and catches up at the next run: every period is invoiced once, one invoice per subscription per run, and every date stays on the invoice day. A subscription set back to Active with its date behind is invoiced for every period not yet invoiced, one each morning, until it is current; to stop billing for a while, use Pause, which moves the dates on when the subscription resumes.
- Fixed — the Invoice Day (Subscriptions → Settings → Manual EFT) could be stored as 0 (no invoice ever went out) or as a day above 28 (months without that day had no invoice). It is now kept to the 1st to the 28th however it is saved, and a value that is not a number is the 25th.
- Fixed — Subscriptions → Add New priced a product with the billing-cycle choice as monthly (quarterly as three months, its quarterly price or discount ignored: for example R207.00 where the customer’s cart charges R196.65) and offered every billing period whatever cycles the product has. Add New now offers only the product’s own cycles (any other product its own billing period), starts on its Billing Period, and prices each one exactly as the cart does — in the subscription it saves, in the product list and in the Recurring Amount it shows.
- Fixed — the Manual EFT invoice PDF asked for the invoice number as the payment reference, while the invoice email gives the subscription’s EFT reference. The PDF now gives the EFT reference too (the invoice number only when there is none).
- A Manual EFT subscription’s customer emails and My Account now name the next invoice and when it falls due — “Next invoice: 25 October 2026 (payment due 1 November 2026)”: the invoice day plus your Payment Terms — instead of a “Next payment” date that was the day the invoice is sent. Card subscriptions are unchanged.
- Subscriptions → Add New: the first-invoice line under Pro-rata First Invoice now shows what the first invoice will be, with the next month or months it carries, and follows Send first invoice immediately.
Plan changes, orders and emails:
- Fixed — on a store selling variable subscription products, Change Plan offered a variable product as a plan to switch to and queued the change at R0.00 (the product has no price of its own), and at the renewal the subscription was switched to it at R0.00. Change Plan no longer offers a variable product or one of its options (switching between a product’s options is not available yet), and a change of that kind queued before this update is not applied: the subscription renews on its current plan, and its Activity Log says so.
- Fixed — for a subscription taken out on an option of a variable product, an immediate plan change, and a cancellation with a pro-rata refund, valued the time already used at R0.00, so the whole amount paid was credited or refunded however much of the term had passed. The time used is now valued at that option’s price.
- Fixed — changing plan on a subscription bought with a quantity above 1 kept one unit at one unit’s price. A plan change now keeps the quantity: the plans are shown, queued, charged and renewed at the price for every unit, and the credit for an immediate change values the time used for every unit, as a cancellation with a pro-rata refund now does.
- Fixed — an order made in WooCommerce → Orders → Add order with subscriptions on two different billing schedules (for example a monthly and an annual one) could be paid through its payment link, and became one subscription billed on one schedule. Such an order is now refused at payment, before anything is charged, with a message to the customer and a note on the order: make one order per schedule. (Carts have refused this since 2.7.28.)
- New — the renewal email now says why its amount differs and what comes next. When account credit paid part of a renewal it reads, for example, “Amount: R10,00 (R15,00 less R5,00 account credit)”, and it ends with the next payment and its date — “Your next payment of R15,00 is on 10 November 2026.” — less any account credit still to be used; a Manual EFT subscription’s names its next invoice and the day it is sent. Amounts are written in your store’s price format. Your “[Subscription Payment]” email names the credit on its Amount Paid line.
- Fixed — the card-update email on a card subscription said the account credit comes off the next invoice; it says the next payment. Your “[New Subscription]” email shows the amount paid on a sign-up and, when it differs, the recurring amount; your “[Subscription Payment]” email says “this payment” on a card subscription, and on a Manual EFT subscription names the next invoice and when it falls due.
- Fixed — you received a “[New Subscription]” email each time a subscription became active again (a missed payment paid, a card updated while on hold, a status set by hand). ReCurr now sends “[Subscription Reactivated] Subscription #N reactivated”, with the status it came from. “[New Subscription]” is sent when a subscription is first activated.
Smaller changes:
- Subscriptions → Settings now checks every value before it is saved, as the WordPress Plugin Check standard requires. The Failed Payment Retry Count and the Manual EFT Payment Terms are kept as whole numbers — a retry count left empty or not a number is saved as 3, the default (before, an empty count was saved as it was, and a failed card renewal then put the subscription on hold without a retry) — and the Manual EFT bank details as plain text. Values you have already saved do not change.
- The subscription screen’s Activity Log: a long entry wraps inside the box, and a recorded consent (cancelling with a refund, changing plan) reads as a short list instead of raw data.
- Subscription screen → Change next payment date: the range now reads “You can choose any date from today up to <date> – one billing cycle after the current next payment date.” (it read like a payment date).
- ReCurr’s log lines (WooCommerce → Status → Logs, source “recurr”) now all begin with “ReCurr”.
- With WP_DEBUG on, ReCurr no longer writes about ten start-up lines on every page load (one of them the plugin’s path on your server), so the payment lines are easier to find.
- Fixed — with WordPress 6.7 or later and WP_DEBUG on, a “translation loading for the recurr domain was triggered too early” notice was written to the debug log on every request. ReCurr now reads its own version without loading its translations early.
Never affected: paying at PayFast — a customer sees nothing new; a card subscription’s texts — its emails and My Account still name its next payment (the Manual EFT wording above is for Manual EFT subscriptions only); Manual EFT subscriptions billed every 2 to 12 months, and invoices already raised.
What to do: before you update, make sure your site runs PHP 8.1 or newer (Tools → Site Health → Info → Server); if it does not, ask your host to upgrade PHP — until then WordPress keeps your site on 2.8.7. After the update: check the “From” name and address under WooCommerce → Settings → Emails — ReCurr’s emails now use them, and customers are asked to write to that address; in your PayFast dashboard, check Settings → Integration → Email Confirmation, where PayFast now sends its payment confirmation for you; look for credit that was not refunded on your cancelled subscriptions (above) and refund it in your PayFast dashboard; and if you offer Cancel with pro-rata refund (Subscriptions → Settings → General), test one small refund with your own card before you rely on it. A Manual EFT subscription you set back to Active with its date behind is invoiced for every period not yet invoiced, one each morning — to stop billing for a while, use Pause.
Do you need to update? Yes — every store, once its site runs PHP 8.1 or newer. Below PHP 8.1, WordPress does not offer you this update and your store keeps running on 2.8.7 until your host upgrades PHP. As soon as you can if you offer Cancel with pro-rata refund, or your customers hold account credit (such as the R5.00 card registration), because until you do, PayFast refuses those refunds; and if you have Manual EFT subscriptions or sell free trials, for the fixes above.
2.8.7 — 12 October 2026 — Quarterly and annual card subscriptions renew at the price they were bought at, and PayFast refunds go through
What it means for you: if you sell products with the billing-cycle choice (Monthly, Quarterly or Annually), a card subscription bought Quarterly or Annually now renews at the quarterly or annual price. Until now its renewals charged one month’s price. Your existing subscriptions are corrected once, automatically, when you update. This release also makes PayFast refunds work again, both the pro-rata refund on cancel and the refund of account credit on cancel, and fixes the “&” on the cancel window’s button. No new setting.
Fixed — a card subscription on a product with the billing-cycle choice, bought Quarterly or Annually, renewed at the monthly price. The first payment was right, for example R196.65 for a quarter. Every renewal after it charged one month’s price, for example R69.00, while the subscription’s Recurring Total, the next-payment-date panel and the emails all showed the quarterly figure. The subscription kept the product’s monthly price on its product line, and every renewal is built from that line. ReCurr now keeps the price of the chosen billing period on the line, so each renewal charges what the customer signed up for. It affected card subscriptions and free trials on such products, billed quarterly or annually, in every earlier version.
Your existing subscriptions are corrected when you update. The first time ReCurr runs after the update, before any renewal is taken, it checks every subscription that is not cancelled or expired, once. It corrects only those whose figures leave no doubt:
- a card subscription of the kind above: its product line is set to its Recurring Total, so its next renewal charges the quarterly or annual price;
- a subscription created before ReCurr 2.7.29 on an annual or quarterly product, whose Recurring Total was recorded higher than the price the customer was shown and has always been charged: its Recurring Total is set to that price. What is charged does not change;
- a Manual EFT subscription whose product line showed a different figure from its Recurring Total: the line now shows the Recurring Total. What is invoiced does not change.
Each corrected subscription gets a note on its screen. ReCurr leaves exactly as it is anything it cannot decide from the figures alone, for example two products on one subscription, a quantity above one, or a plan change waiting to apply. A notice in your dashboard says how many subscriptions were corrected and names the ones for you to review, and WooCommerce → Status → Logs (source “recurr”) lists them all.
Renewals already charged at the monthly price are not charged again. To find them, open each subscription the notice reports as corrected and compare its renewal payments with its Recurring Total. Whether to ask the customer for the difference is your decision. We suggest you tell these customers before their next renewal that it will be the quarterly or annual price they signed up for.
Fixed — a subscription bought with a quantity above one now records every unit in its Recurring Total, as its renewals already charged. Before, the Recurring Total, the payment at the end of a card trial and the next-payment-date panel counted one unit.
Fixed — a plan change that took effect at renewal was charged at the previous plan’s price for that one renewal. The subscription’s Recurring Total and the plan-change email named the new plan’s price, but that renewal was built from the previous plan’s product line. ReCurr now builds it from the new plan.
New — a renewal whose products add up to a different amount from the subscription’s Recurring Total now says so in the renewal order’s notes and in the log. The amount charged does not change.
Fixed — refunds through PayFast did not go through. When a customer cancelled with a pro-rata refund, the refund was refused and the subscription stayed active. When a subscription that still held account credit (for example the R5.00 card registration) was cancelled, the subscription was cancelled but the credit was not refunded. ReCurr sent refunds to an address PayFast does not offer. It now uses PayFast’s refund address. No money moved in the failed attempts. If PayFast refuses a refund, the customer is told that the refund could not be processed and how to reach you. PayFast’s reply goes to a note on the subscription’s screen and to the log, not to the customer.
Credit that was not refunded: open your cancelled subscriptions’ Account Credit boxes and activity logs and look for “Cancel-with-credit refund: … failed”. Refund that credit from your PayFast dashboard.
Fixed — the cancel window’s “Accept Refund & Cancel Now” button showed “&” in place of “&”. The same care now applies to every message ReCurr shows from JavaScript on your shop, checkout and account pages and on the Add Subscription screen, so a translation that uses &, <, > or quotes shows them as written.
Never affected: what is charged for monthly subscriptions, for products without the billing-cycle choice and for Manual EFT invoices; how Add New prices a subscription; the payment at the end of a trial, apart from a quantity above one; account credit and the R5.00 PayFast minimum.
What to do after updating: open your dashboard once. If the notice names subscriptions to review, open each one and check its product line against its Recurring Total. If you offer Cancel with pro-rata refund (Subscriptions → Settings → General), test one small refund with your own card before you rely on it.
Coming soon — PHP 8.1 or newer. An upcoming release is planned to adopt PayFast’s official PHP library, which needs PHP 8.1 or newer. If your site still runs PHP 7.4 or 8.0, nothing breaks: WordPress simply will not offer you that release, and your store keeps running on the last version that supports your PHP until your host moves you to PHP 8.1 or newer. You can check your version under Tools → Site Health → Info → Server.
Do you need to update? Yes — as soon as you can if you sell products with the billing-cycle choice, because until you do, their quarterly and annual card subscriptions renew at the monthly price. Yes — if you offer Cancel with pro-rata refund, because until you do, those refunds fail. Every other store: recommended.
2.8.6 — 10 October 2026 — PayFast payments by customers named O’Brien are recorded, two emails corrected, and the WordPress Plugin Check standard
What it means for you: a PayFast payment by a customer whose name or email address contains an apostrophe is no longer lost. This release also corrects two emails, saves text with an apostrophe exactly as typed, moves ReCurr’s log lines to a screen you can read in your browser, and brings ReCurr up to the WordPress Plugin Check standard. No schema change, no migration, no new setting.
Fixed — a PayFast payment by a customer whose name or email address contains an apostrophe, a quotation mark or a backslash (for example O’Brien) is now recorded. Until now PayFast took the payment, but ReCurr turned its payment notification away: WordPress puts a backslash in front of those characters before ReCurr checks PayFast’s signature, so the check failed. The order stayed Pending payment and the subscription Pending, with no card saved and no emails sent. It affected every PayFast payment by such a customer — a sign-up, a card update, a Manual EFT invoice paid online, the payment that activates a free trial — in every earlier version of ReCurr; and every PayFast payment on a store whose translation of ReCurr’s payment descriptions contains an apostrophe. ReCurr now removes the backslashes WordPress added and checks exactly what PayFast sent; the checks themselves are unchanged.
Payments it missed: in your PayFast dashboard under Transactions, look for a completed payment whose WooCommerce order still shows Pending payment — or Cancelled, if WooCommerce cancelled it as unpaid. Since 2.8.4 the Payment ID is the order number, so each one leads you straight to its order.
What to do about them: update ReCurr first. Then refund the payment in your PayFast dashboard and ask the customer to repeat it — pay the order again from My Account → Orders (or buy again if the order was cancelled), use Update Card again, or activate the trial again — and ReCurr records it, saves the card and sends the usual emails. A Manual EFT invoice paid online needs no refund: open the subscription and click Mark as Paid on that invoice while its order still shows Pending payment.
Fixed — the “Payment method updated” email states what the next renewal will actually charge: the subscription price less any account credit, such as the R5.00 card registration credit. When the credit covers the whole payment, it says nothing will be charged. A subscription still in its free trial is the exception: on a trial with a card, the first payment is charged in full when the trial ends, so the email names it in full and says the credit comes off the renewal after it; on a trial that needs no card, it says the credit comes off the payment that activates the subscription. Amounts in this email are written in your store’s price format.
Fixed — the first invoice email for a Manual EFT subscription now says the invoice can be paid online “via PayFast Instant EFT or card”, as the reminder email does. Before, it mentioned Instant EFT only.
Fixed — text with an apostrophe or a quote is saved exactly as typed: notes on a subscription (including the notes your customers see), the Manual EFT bank details shown on invoices, and the EFT reference set on Add Subscription. Before, a backslash appeared in front of it (for example “J O’Brien”). Text saved earlier keeps the backslash until you edit it. Searching subscriptions or customers for a name such as O’Brien now finds it.
Fixed — the update notice that came back after an update. Until now WordPress could offer the version you had just installed as an update again, for ReCurr or ReCurr Pro, and a second update was needed to clear it. ReCurr now checks for updates against the version installed at that moment. This takes effect from the update after this one: the update to 2.8.6 is still checked by the version it replaces, so the notice may come back once more (for ReCurr Pro too, if you update both together), and a second update clears it as before.
Changed — ReCurr’s log lines are under WooCommerce → Status → Logs (source “recurr”), where you can read them in your browser, instead of the PHP error log or wp-content/debug.log. What is logged, and when, is unchanged, except for the two places that wrote payment details: with WP_DEBUG on, a saved-card charge now logs only the first 8 characters of the card token, and the PayFast payment form’s lines show [redacted] in place of your merchant key and the customer’s name, email address and phone number. Most lines still appear only when WP_DEBUG is on. If WooCommerce’s logging is switched off, ReCurr writes no log lines either. WooCommerce keeps them for its log retention period (30 days by default).
Changed — the WordPress Plugin Check standard. ReCurr now follows it for how it reads form input, verifies requests, builds database queries and redirects, and escapes everything it prints on its admin screens, at checkout and in My Account. Every text that carries a value has a note for translators, and every direct database query carries a note saying why it is direct and not cached. What your screens and emails show is unchanged, and subscription, payment and credit data are never cached.
Also changed: on a site that is not in English, five texts in ReCurr’s checkout template and the PDF invoice’s “Bill To:” show in English until ReCurr is translated (they used WooCommerce’s and the PDF Invoices plugin’s translations); the notice shown when WooCommerce is not active now names ReCurr; and a refund sent to PayFast without a reason of its own now shows “Refund issued by ReCurr” in your PayFast dashboard.
Never affected: what is charged and sent to PayFast (apart from that refund reason), how payment notifications are checked (apart from the fix above), renewals, dates, statuses and your screens and emails apart from the changes listed here.
Coming soon — PHP 8.1 or newer. An upcoming release is planned to adopt PayFast’s official PHP library, which needs PHP 8.1 or newer. If your site still runs PHP 7.4 or 8.0, nothing breaks: WordPress simply will not offer you that release, and your store keeps running on the last version that supports your PHP until your host moves you to PHP 8.1 or newer. You can check your version under Tools → Site Health → Info → Server; most South African hosts let you change it from your hosting control panel.
Do you need to update? Yes — every store. Until you do, a PayFast payment by a customer whose name contains an apostrophe is taken by PayFast but never recorded. After updating, look for payments it missed, as described above.
2.8.5 — 6 October 2026 — A renewal no longer books a second card-registration credit
What it means for you: a card registration is credited once, and only once. When a customer registers a new card through Update Card, the R5.00 registration is credited to their next renewal. Until now, a PayFast payment notification for a later renewal charged to that card could be taken for a second card registration. No schema change, no migration, no new setting.
Fixed — a renewal could be booked as a second card registration. When a customer registers a new card through Update Card, ReCurr charges R5.00 and credits it to their next renewal. If PayFast then sent a payment notification for a later renewal charged to that card, ReCurr treated it as another card registration: it booked another R5.00 credit, which the next renewal deducted, and emailed the customer “Payment method updated” again. Each such renewal was charged R5.00 short. ReCurr now completes each card registration once; a later notification for it is recorded in the subscription’s Activity Log and changes nothing else.
Also fixed: a late or repeated PayFast notification for a subscription’s first payment no longer records that payment a second time or re-sends the new-subscription emails.
Who is affected: stores whose customers have used Update Card, on a PayFast account that sends a notification for every card charge (PayFast’s default).
How to spot an affected subscription: in its Account Credit box, a “Card registration” credit whose PayFast transaction is a renewal’s rather than the card registration’s; or a “Payment method updated” email after a renewal in which the card did not change.
What to do: update. Credits booked before the update stay on the subscription and are deducted from its next renewal, as every credit is. If you would rather not allow them, contact ReCurr support before that renewal.
Never affected: the R5.00 card registration and its single credit, renewals, sign-up, trial conversion and manual invoice payments, and the PayFast Payment ID.
Do you need to update? Yes, if your customers use Update Card — from the update on, each card registration is credited once and every renewal on the new card is charged in full. Every other store should update too: a late or repeated notification for a first payment is no longer recorded twice.
2.8.4 — 5 October 2026 — The order number is now the PayFast Payment ID, and amounts are sent to the cent
What it means for you: each PayFast payment can now be matched to its WooCommerce order. Until now ReCurr sent PayFast no Payment ID, so the Payment ID column in your PayFast Transactions and Tokenization lists stayed blank, and matching a payment to its order meant comparing amounts and dates. No schema change, no migration, no new setting.
New — the Payment ID. PayFast now shows the WooCommerce order number as the Payment ID on every subscription payment, renewal and card registration, so each payment can be matched to its order in your PayFast Transactions and Tokenization lists. Cards saved before this update keep a blank Payment ID in the Tokenization list; their payments carry it from the next renewal.
Fixed — amounts to the cent. Renewal charges and refunds are now sent to PayFast to the exact cent: before this update, some amounts (for example R72.60) were charged or refunded one cent short.
Who is affected: every store that takes payments through PayFast. The Payment ID goes with every sign-up, card update, manual invoice paid by card and saved-card charge from this update on. The missing cent affected about one amount in twenty-two (R72.60, R19.99 and R8.20 among them) on charges made with a saved card — renewals and their retries, plan changes and trial-end charges — and on refunds; the payment page at sign-up always sent the exact amount.
What to do: update ReCurr. There is nothing to set up.
Never affected: how payments are recorded — PayFast’s payment notifications are matched to their orders exactly as before; everything else sent to PayFast; amounts, dates, statuses and emails, apart from the one-cent correction above; ReCurr Pro’s split payments.
Do you need to update? Yes, every store that takes payments through PayFast should — from the update on, every payment carries its order number in your PayFast lists, and saved-card charges and refunds are exact to the cent.
2.8.3 — 5 October 2026 — The card is kept when a free trial is activated, and when a card is updated on hold
What it means for you: a subscription activated from a free trial without a card now renews on the card the customer paid with. When a customer activated their trial through the activation link, they paid at PayFast and the subscription became active — but the card was not saved for renewals. The first renewal after activation then failed with “No payment token found for renewal”, and the subscription went into failed-payment retries. This happened whether the customer activated while the trial was still running or after it had ended. No schema change, no migration, no new setting.
Fixed — the card is saved when a free trial is activated. The card used for the activation payment is now kept on the subscription, and its renewals are charged to it.
Fixed — a card updated while a subscription is on hold is now the card that is charged. When a customer used Update Card on an on-hold subscription, the subscription was reactivated but the previous card was put back, so the next renewal was charged to the old card, or failed again. The new card is now kept.
Also: the activation order and the card-update order now record the card reference, as the order of a sign-up with a card always has.
Who is affected: stores that offer a free trial without a card — every subscription activated through the activation link before this update — and any subscription whose card was updated while it was on hold.
How to spot an affected subscription: open it (Subscriptions → open the subscription) and look at its Activity Log. A subscription activated from a free trial without a card whose first renewal failed with “No payment token found for renewal” is affected. So is a subscription whose card was updated while it was on hold and whose next renewal was charged to the old card.
What to do: update ReCurr. The update cannot put back a card that was already lost — the card reference is held only at PayFast — so a subscription activated before the update still has no card on file. Ask the customer to open the subscription in My Account and use Update Card to register their card again; the R5.00 registration is credited to their next payment. After a card was updated on hold, the previous card stays on file: if the customer wants the new card charged, they use Update Card once more. If a customer cannot do this, contact support.
Never affected: signing up with a card, and the renewals of every other subscription; a card updated while a subscription was active; amounts — the activation charge itself, account credit, and the card registration and its credit; dates, statuses and emails.
Do you need to update? Yes, if your store offers a free trial without a card — every subscription activated through the activation link from now on keeps its card. Every other store can update as usual; it changes nothing for you, and it keeps a card updated on hold.
2.8.2 — 29 September 2026 — Change a subscription’s next payment date from its screen
What it means for you: you can now move a subscription’s next payment date yourself, from the subscription’s screen. Open a subscription (Subscriptions → open a subscription): the Details box now has Change next payment date under Next Payment. Use it to line a subscriber’s payment up with their payday, or to set the date back where you want it after a pause. It changes the date only — nothing is charged, refunded or credited, and the time of day stays the same. No schema change, no migration, no new setting.
New — change the next payment date:
- Any date from today to one billing cycle after the current one. Before you confirm, the form shows how many days later or earlier the new date is.
- Choosing today asks you to confirm again and says what will happen: a card subscription is charged on the next hourly renewal run; a manual EFT subscription still gets its invoice only on your invoice day, and the form names that day.
- Licences: a later date moves the licence expiry on by the same number of days; an earlier date never shortens a licence.
- Every change is recorded in the subscription’s Notes (visible to administrators only) and its Activity Log. Your customer is not emailed.
- Not offered while a subscription is paused, in its free trial, has a failed payment being retried, or has an unpaid invoice — the screen says why instead.
Who it is for: every ReCurr licence, Standard and Plus.
Unchanged, deliberately: your customers cannot change their own date — My Account is as before. Renewals, amounts, invoices and your invoice day work exactly as before; only a date you choose to move moves.
Do you need to update? Yes, if you want to move a subscriber’s payment date — until now that could not be done from the subscription’s screen. Otherwise update as usual; nothing changes for you until you use the new link.
2.8.1 — 28 September 2026 — Licence activation refused with “Verification API secret key is invalid”
What it means for you: on the very few sites where it happens, ReCurr can activate its licence again. ReCurr identifies itself to the licence server with an API key. This is not your licence key: ReCurr keeps it on your site, protected with your site’s WordPress security keys. On a site whose WordPress security keys have changed — regenerated by a host or a security plugin, or after moving the site — reading it back normally failed and ReCurr stored it again straight away; but about 1 time in 250 it read back as a wrong value, and ReCurr then sent that wrong value with every licence request. The same could happen, also about 1 time in 250, whenever ReCurr stored the key — when it was first activated, too, with no change to the security keys at all. No schema change, no migration, no new setting.
Fixed — ReCurr now checks the API key it sends to the licence server, and repairs it by itself when it is wrong. On an affected site the licence server refused every request with “Verification API secret key is invalid”: activating a licence key failed, and the Licence page showed the previous key again, because a refused activation saves nothing. The daily licence check was refused too, so the licence showed as not active. ReCurr now compares what it reads back with the key it expects; when they differ it stores the key again, once, and sends the right one — and it now always stores the key in a form that reads back correctly. Deactivating and reactivating ReCurr did not clear this; the update does. ReCurr Pro takes the same key from ReCurr, so its licence checks are repaired too.
Who is affected: very few sites — about 1 in 250 of the sites whose WordPress security keys have changed since ReCurr stored its key, and about 1 site in 250 from the day ReCurr was first activated on it. An affected site sees “Verification API secret key is invalid” on every licence request; a site that does not see it is not affected.
Never affected: licence keys, their statuses and their expiry dates; billing — every subscription, renewal, amount and date; and every site whose key reads back correctly, whose licence requests are exactly as before, with nothing written.
Do you need to update? Yes, if your site shows “Verification API secret key is invalid” — update ReCurr, then enter your licence key on ReCurr → Licence and click Activate. If ReCurr does not offer the update on your site (for example because its licence key has expired), contact support for the zip and install it by hand: Plugins → Add New → Upload Plugin, then Replace current with uploaded. Every other site can update as usual; it changes nothing for you, and it protects your site if its security keys change in future.
2.8.0 — 27 September 2026 — Variable products sold as subscriptions, and manual EFT invoices every few months
What it means for you: on ReCurr Plus you can now sell each option of a variable product — a size, a plan, “buy once” or “subscribe” — as a subscription with its own price and terms, and on every plan you can invoice a manual EFT subscription once every 2 to 12 months. Variable subscription products sit behind a new setting, Variable subscription products (Subscriptions → Settings → General), which is off by default. While it is off, your simple subscription products are sold, charged and renewed exactly as before. This release also carries the manual EFT invoicing fixes prepared as 2.7.30, which was never released on its own — see Also fixed below.
New — variable subscription products (ReCurr Plus and above). With the setting on:
- Each variation can carry its own subscription terms — billing period and interval, free trial, and annual or quarterly pricing — and uses the parent product’s settings wherever it sets none.
- The product page shows a price range with each option’s billing period, and choosing an option shows that option’s price and period. An annual or quarterly discount applies to the option’s price as shown and as charged.
- The subscription records the option the customer chose — its price, its terms and the attributes chosen (size, colour and so on). Every renewal order names that option and those attributes, and My Account shows them on the subscription.
- Subscriptions → Add New offers variable subscription products, with a choice of option.
- One order, one renewal schedule, as before: two options on different schedules cannot be checked out together.
- Not yet available: moving an existing subscription to another option. To change option, cancel and subscribe again.
- On ReCurr Standard a variation shows an upgrade note instead of the subscription fields, and a variable subscription product cannot be bought. Subscriptions already sold keep renewing on every plan.
Once you sell variable subscriptions, leave the setting on. If you turn it off again, subscriptions already sold keep renewing at the same amount on the same dates, but each renewal order names the parent product without the options chosen, stock is taken from the parent product, and My Account no longer lists the options. The step-by-step guide is Plus Tutorial 7, and Plus Tutorial 8 explains every message you can meet.
Changed — with the setting off, a variable product marked as a subscription can no longer be bought. Until now such a product was sold on the parent product’s price and billing period whichever option the customer chose, so the subscription could record an amount and a period the customer never saw. Adding it to the cart, or checking out with it already in the cart, is now refused with “Sorry, “(product)” cannot be bought on this store at the moment.”, and on most themes the product page shows its options as unavailable. This includes a variable product that was converted from a simple subscription product — it is refused after the update even if you have never turned the setting on. To sell it once-off, switch it to a simple product, untick Enable Subscription, save, and switch it back to variable. To sell it as a subscription, turn Variable subscription products on (ReCurr Plus or higher) and set up its variations. Subscriptions → Add New likewise no longer offers such a product while the setting is off, and refuses a form that names one.
New — Bill Every for manual EFT subscriptions (every plan). On Subscriptions → Add New, a manual EFT subscription can now be invoiced once every 1 to 12 billing periods — monthly, quarterly or yearly — for example R550.00 every 2 months. Each invoice is one period’s amount (the Recurring Amount, or the Custom Amount); Bill Every only spaces the invoices. A monthly subscription’s first scheduled invoice falls on the Nth invoice day after the day it is added; a quarterly or annual one’s on its anniversary N periods on. Above 1, the pro-rata first invoice is not offered. The payment confirmation email and My Account word the term the same way. At 1 — the default — nothing changes.
Fixed — Subscriptions → Add New no longer fails with a critical error on a product that has no price. Choosing a product saved without a price stopped the screen with “There has been a critical error on this website” — after an Active subscription with no product had already been created, one more on every attempt. Such a form is now refused with “”(product)” has no price, so it cannot be added as a subscription. Enter a price on the product (Products → Edit product) and try again – a Custom Amount does not replace it.”, and nothing is created, with or without a Custom Amount. The update does not remove a subscription left behind by an earlier attempt: look on the Subscriptions list for an Active subscription with no product.
Fixed — an annual or quarterly product with its discount ticked and no price no longer raises an error where its price is shown — the shop, the product page and the Products list. It shows its price without a savings line and stays unpurchasable, as WooCommerce intends.
Fixed — a quarterly or annual subscription’s first invoice from Subscriptions → Add New is no longer labelled “(Pro-rata first invoice)”. It was always charged in full; only the label was wrong.
Fixed — the cart names the whole period a combined first payment covers. When a monthly subscription is bought in the last seven days of a month (or its pro-rata amount is below R5.00), the first payment covers the rest of that month plus the whole of next month, and the next payment falls on the 1st of the month after. The checkout said so, but the cart’s box said only “pro-rated for the remaining 4 days of this month (until 30 September 2026)” — as if the customer were paying for four days. It now adds “plus next month’s fee (until 31 October 2026)”, the checkout’s order summary reads “4 days pro-rata + 1 month”, and both are headed Pro-rata Billing (was Pro-rata Deducted). Only the wording changed: the amount, the dates and the emails were always right.
Also fixed — the first scheduled invoice of a monthly manual EFT subscription added on Subscriptions → Add New (prepared as 2.7.30, released here):
- A monthly subscription added on 29, 30 or 31 January, 31 March, 31 May, 31 August or 31 October no longer skips a month. Its first scheduled invoice was set two months on — added on 31 January, the first scheduled invoice fell on the invoice day in March, not February — so the month in between was never invoiced. The first scheduled invoice is now on the first invoice day after the day the subscription is added.
- A pro-rata first invoice is charged once. With Pro-rata First Invoice and Send first invoice immediately both ticked — both are on by default — the pro-rata invoice was sent straight away, and the first scheduled invoice then charged the pro-rata amount a second time instead of the full monthly amount: at R550 a month, added on 10 September, R385.00 on 10 September and R385.00 again on 25 September, where the second should have been R550.00. The first scheduled invoice is now the full amount whenever an invoice has already been raised for the subscription — including subscriptions added before the update whose first scheduled invoice is still to come.
- These fixes do not change an invoice already raised or a date already set. Look over the monthly manual EFT subscriptions added on Subscriptions → Add New: where the first scheduled invoice asked the pro-rata amount again, invoice the difference; where a month was skipped, raise that month’s invoice by hand — or, if the first scheduled invoice has not been raised yet, bring the next payment date forward by a month.
Never affected: card subscriptions — every date and amount; subscriptions already sold, simple or variable, which keep renewing at the same amount on the same dates; quarterly and annual manual EFT subscriptions’ first scheduled invoice, which falls on the anniversary as before; and, with Variable subscription products off, simple subscription products, which are sold, charged and renewed exactly as before apart from the fixes above.
Do you need to update? Yes, if you add manual EFT subscriptions on Subscriptions → Add New — until you do, a monthly one can skip a month or be charged its pro-rata amount twice — and if you want to sell variable products as subscriptions on Plus. Before you update, check whether any variable product in your store is marked as a subscription (for example, one converted from a simple subscription product): after the update it cannot be bought until you either turn Variable subscription products on (Plus) or clear its subscription setting, as described above.
2.7.29 — 24 September 2026 — One price per billing period for annual and quarterly products
What it means for you: an annual or quarterly subscription product is now charged one amount on every path — and if you sell annual or quarterly products, check a few of your subscriptions. ReCurr worked out the price of one billing period in more than one place. The product page, the cart, the first charge and every card renewal used one calculation. The amount a new subscription records — which the card charge at the end of a free trial and every manual EFT invoice take — used another, and the card-less trial conversion from My Account and plan switching each worked out their own. For some product settings the figures disagreed, so a customer could be charged an amount the product page never showed. Every path now asks one rule. The figures below are for a product with a Regular price of R100. No schema change, no migration, no new setting.
Fixed — an annual product with neither Enable Annual Discount nor a Custom Annual Price, a quarterly product with neither a quarterly discount nor a Custom Quarterly Price, and a product billed every two years or more now record the price the product page shows. Such a subscription recorded R1 200 for an annual product whose page showed R100 (R300 for a quarterly one, and one year’s figure for a product billed every two years). A card trial on such a product converted at that amount, and manual EFT invoices asked it, while card renewals charged the page price. The page and checkout price do not change. ReCurr Standard has no annual or quarterly price settings, so an annual or quarterly product set up on Standard is in this group: the Regular price you enter is what is charged once per billing period. On Standard, enter the yearly (or quarterly) price as the Regular price. On Plus, to bill a year at twelve times a monthly Regular price, less any discount, tick Enable Annual Discount or enter a Custom Annual Price.
Changed — a Custom Annual Price without Enable Annual Discount, a quarterly discount, and a Custom Quarterly Price now set the product page and checkout price too. The page and checkout showed and charged R100 while the subscription recorded, the trial notice quoted and the EFT invoices asked the figure you configured (for example R999 a year, or R285 or R270 a quarter). Your configured figure now applies on every path, so for new customers the page and checkout price of these products rises to it. What such a subscription records, the trial notice and the EFT invoice do not change. If you meant the lower figure, clear the setting.
Fixed — a free-trial line stays free at checkout. On an annual product with both a Custom Annual Price and Enable Annual Discount set, the trial line’s R0 was charged at the custom price.
Fixed — a card-less trial converting from My Account is charged its product’s discounted or custom price. Both were ignored: an annual product at 10 % off (R1 080 on the page) converted at R1 200.
Fixed — a plan switch to an annual plan with a discount is priced at that plan’s own price. A switch to an annual plan at 10 % off was priced, and stored for every later renewal, at R11 664 instead of R1 080. The change-plan page now quotes the figure the switch charges.
Changed — credit for unused time on an annual plan with a discount is valued at the plan’s monthly price. Time already used was valued at the plan’s yearly price per month, so the credit fell to nothing within weeks. This applies to Immediate plan switching and to Pro-rata cancellation refunds, which both value unused time at the full monthly rate: on an annual plan at 10 % off, R1 080 paid and cancelled 30 days in, the refund was R14.79 and is now R981.37. Where neither plan has a Plan rank, the same monthly price decides whether a switch between such plans is an upgrade or a downgrade.
Changed — a plan change to a billing cycle the plan does not offer is refused. The Change Plan page offers each plan its own billing cycle, or the cycles it lists when the billing cycle toggle is on; a request for any other cycle is now refused with “Invalid billing period.” Every cycle the page offers is accepted as before.
Changed — a price another extension sets on a cart line is used as it was set. On an annual product with Enable Annual Discount set, such a price was annualised a second time.
Fixed — the Add Subscription screen’s product list previews the amount the subscription records. It previewed R1 200 for an annual product recorded at R100, and R11 664 for an annual product at 10 % off recorded at R1 080. An annual product with Enable Annual Discount set and no price no longer raises an error when it is shown; it stays unpurchasable, as WooCommerce intends.
Existing subscriptions are not changed. A subscription keeps the amount it recorded, and a plan switch already queued keeps its price and billing cycle when it applies. Before the next charge, open any subscription on an annual or quarterly product that is still in its free trial or is paid by manual EFT, and correct its recorded amount if it differs from the product page. Cancel any pending plan switch to an annual plan with a discount, and let the customer queue it again after you update.
Never affected: monthly, weekly and daily products; products with the billing cycle toggle on — every price, on every path; the page and checkout price of an annual product with Enable Annual Discount set; and card renewals of existing subscriptions, which charge what they charged before.
Do you need to update? Yes, if you sell subscription products billed yearly, quarterly or every two years or more, or offer plan switching to an annual plan with a discount. Until you do, a trial or manual EFT subscription on such a product can be charged an amount its product page never showed.
2.7.28 — 23 September 2026 — One order, one renewal schedule
What it means for you: a customer can no longer put two subscription products with different renewal schedules in one order — and if any of your subscriptions carries more than one product line, check it. Every subscription product in an order goes onto one subscription, and that subscription renews on one schedule: the schedule of the first subscription product added to the cart. A second subscription product on a different schedule was never given its own. It was billed on the first product’s schedule at its own full price. A monthly product and then an annual one in the same cart meant the annual price was charged every month; the other way round, the monthly product was charged once a year. Which of the two a customer got depended on the order they clicked in. Nothing refused the cart, because the only cart check ReCurr had told subscription products from once-off products. Nothing here changes how any amount is calculated for a correctly formed order. No schema change, no migration, no new setting.
Fixed — a second subscription on a different renewal schedule is refused at add-to-cart. A schedule is the billing period and the interval together, so every 2 months and every month are different schedules, and a product with the billing cycle toggle counts on the cycle the customer chose. The customer sees: “Subscriptions in one order share one renewal schedule. Your cart already holds a subscription that renews every month, and this one renews every year. Please complete your current order first, then come back for this one.” The classic add-to-cart button, the AJAX button and the block-based store all go through the same check.
Fixed — a cart that already holds two schedules is refused at checkout. A cart filled before this update, a saved cart merged on login or a re-ordered past order can still hold both. The cart page and the checkout page show “The subscriptions in your cart renew on different schedules (every month and every year). One order can carry one schedule only. Please remove one of them and order it separately.”, and neither the classic checkout nor the block checkout places the order until one of them is removed.
Changed — the same billing-cycle-toggle product can no longer be bought twice on two cycles in one order. The cart accepted it, and the order could not honour it. The second cycle is now refused with the same message.
Subscriptions already created from such a cart are not changed. They keep billing exactly as they do today. Open any subscription that carries more than one product line and check that every line renews on the schedule the customer bought. If it does not, split it by hand into one subscription per schedule, or refund it and sell the products again.
Never affected: two or more subscription products on the same schedule in one order — still allowed, and still one subscription; a once-off product beside a subscription, with the mixed-cart notice as before; any order with a single subscription product, with or without a chosen billing cycle; and everything at renewal — no amount, date, schedule or charge changes for any existing subscription.
Do you need to update? Yes, if you sell subscription products on more than one renewal schedule. Until you do, a customer who puts two of them in one cart is billed on the wrong schedule for the second one.
2.7.27 — 20 September 2026 — See a customer’s account credit on the subscription screen
What it means for you: you can now see the credit a customer is holding, and where it went. ReCurr has kept a credit ledger for some time. The R5.00 from a card registration goes onto it, as do plan-switch credits and trial overages, and it comes off the customer’s next renewal by itself. Until now the only trace in the admin was a line in the activity log.
Added — an “Account Credit” box under Notes on the subscription screen. The heading shows the balance available. Below it is every ledger entry, newest first: the date, the amount, the reason (card registration, plan switch, trial overage or manual), whether it is still available, applied or refunded, the PayFast transaction it came from, and a link to the order it was applied to.
Nothing about billing changes. The box is read-only. How credit is earned, applied to the next renewal, held back under PayFast’s R5.00 minimum charge and refunded on cancellation is exactly as before, and your customer’s own view of their credit in My Account is untouched.
Do you need to update? Yes — this release also carries everything in 2.7.26 below, which is the one that matters if your customers update their own cards.
2.7.26 — 20 September 2026 — Update Card works for every customer again
What it means for you: every customer can update their card again, whichever bank they are with. 2.7.24 sent customers to PayFast’s free card-update page, and 2.7.25 added the R5.00 card registration as a way through for a card that page refused. In the field that was not enough. PayFast’s page verifies the new card with a zero-amount 3D Secure check, and the list of banks refusing it grew with every report: an FNB card on our first live test, then both an ABSA and a Capitec card for the same customer — cards that need an OTP and never received one. The alternative only appeared to a customer who came back through PayFast’s own return button. One who closed the tab never saw it, and pressing Update Card again sent them straight back to the page that had refused them.
Changed — Update Card uses the R5.00 card registration for everyone, exactly as it worked before 2.7.24. It is a real charge, so the bank runs its normal 3D Secure with an OTP, the new card replaces the old one, and the R5.00 is credited in full to the customer’s next invoice.
Fixed — the failed-payment email no longer sends customers to PayFast’s page. Since 2.7.23 that email carried the card link PayFast returns with a decline. It leads to the same zero-amount page, and a customer refused there had no route to the card registration at all. The email now links to the customer’s subscription page in My Account, where Update Card is. PayFast’s link is still kept on the order note for you.
Check one setting in your PayFast account. PayFast dashboard → Settings → Payment Methods → Credit Card → Minimum amount should read R5.00, which is PayFast’s default. PayFast applies your payment-method minimums to a card registration, and Visa and Mastercard debit and cheque cards are processed under the Credit Card method. If that minimum has been raised, PayFast stops the customer before they see a card form, with “400 Bad Request. The subscription amount is outside the limits set by the merchant or PayFast.”
If you would rather keep a higher minimum, raise the registration to match — it is all credited back to the customer:
add_filter('crb_card_registration_amount', function () { return 10.00; });
Added — that filter, crb_card_registration_amount. The registration amount used to be fixed in the code; it is one adjustable figure now, R5.00 unless you change it. If you do change it, a registration a customer left unpaid at the old amount is closed and replaced, so they are not sent back to the amount PayFast refused.
If you want PayFast’s free page back, it is one line, and you then get the 2.7.24 behaviour complete with the R5.00 alternative on the way back:
add_filter('crb_payfast_hosted_card_update_available', '__return_true');
If you had added that filter with __return_false to turn the page off, you can remove it — it now does nothing.
What this does not change: whether a bank approves a charge. A card declined for insufficient funds will be declined again on the retry unless there is money in the account. Renewals, retries, amounts and dates are untouched.
Do you need to update? Yes. Until you do, a customer whose bank refuses PayFast’s zero-amount check can be left with no way to put a new card on file.
2.7.25 — 19 September 2026 — A way back when the bank will not accept the card at PayFast
What it means for you: if a customer’s bank refuses the card on PayFast’s update page, they now have somewhere else to go. We tested 2.7.24 on our own live store the day it shipped. The page itself works exactly as described: the card is replaced, the token is unchanged, nothing is charged, and PayFast emails you to say the buyer updated their card details. But it verifies the new card with a zero-amount 3D Secure check, and some South African banks will not accept one. An FNB debit card was refused on that page with “3DSecure transaction was unsuccessful”, and a Capitec card went through on the same subscription minutes later. The refused card pays other merchants without any trouble. The bank decides, and neither you nor your customer can tell in advance.
That left the customer stuck: 2.7.24 sends everyone with a card on file to PayFast’s page, and pressing Update Card again just sends them back to it.
Added — “register a new card instead.” When a customer comes back from PayFast, the message on their subscription page now offers the older R5.00 registration as an alternative, saying plainly what it costs and that it is credited to their next invoice. It is a link they choose. A customer whose card was accepted can ignore it, and nothing sends anyone down that road automatically. PayFast returns them to your store whether they saved a card or cancelled, so the offer is there either way.
Why the R5.00 route works where the free one does not: it is a real charge, and a real charge passes 3D Secure. That is exactly why it replaced the R0.00 card registrations that were failing at South African banks in May 2026.
The free route is still the default, because it costs your customer nothing and most cards go through it. If you would rather put everyone through the R5.00 registration, one line still turns the hosted page off store-wide: the filter crb_payfast_hosted_card_update_available.
Do you need to update? Yes, if your customers update their own cards — without it, a customer whose bank refuses PayFast’s check has no way to finish. Nothing about renewals, retries, amounts or dates changes.
2.7.24 — 19 September 2026 — Updating a card no longer costs R5.00
What it means for you: a customer who needs to put a new card on a subscription now does it on PayFast’s own card-update page, and nothing is charged. Until now the Update Card button in My Account created a real R5.00 order and sent the customer to PayFast to register a new card from scratch; the R5.00 was credited back against their next renewal, but it still showed on their statement, from a page whose whole message is that nothing will be charged. It was only ever a workaround for PayFast’s R5.00 transaction floor.
Changed — Update Card uses PayFast’s “Update card details” page. The customer enters the new card at PayFast, the card token already on file stays the same, and the next renewal simply uses the new card. No order, no charge, no credit to book. The subscription’s activity log records that the customer was sent there and that they came back; PayFast does not say whether they saved a card or cancelled, so the notice they see on return is worded accordingly. It is the same link ReCurr has put in the failed-payment email since 2.7.23.
Kept — the R5.00 verification charge where it is still needed. A subscription with no usable card on file — none stored, one that cannot be read, or one PayFast has refused — still has to have a card attached, and registering a new card is the only way to do that. So does a subscription on hold: a completed charge is what proves the new card works and what reactivates the subscription, and PayFast’s page cannot report that. ReCurr chooses the right path by itself; you do not have to.
Fixed — a card update the customer abandoned put the subscription on hold. PayFast’s callback for an incomplete R5.00 update was handled as a failed renewal. The card already on file was untouched, so the subscription now stays exactly as it was; only the R5.00 order is marked failed.
One thing to know before you test it: PayFast does not offer the card-update page for its sandbox, so a store in test mode keeps the R5.00 flow. Test the new path on a live store — nothing is charged there either.
Do you need to update? Recommended for every store whose customers update their own cards. Nothing about renewals, retries or the amounts charged changes.
2.7.23 — 19 September 2026 — A declined card was recorded as a paid renewal
What it means for you: install this one if you take card payments at all, then open Subscriptions → Unpaid renewals. When a subscriber’s bank declined a renewal charge, every version before this one recorded the renewal as paid: the order was marked paid, the payment appeared in Payment History, the next payment date moved on, the licence was extended, and the customer was emailed “Payment received”. No money had moved, no retry was made, and no failed-payment email went out. Nothing here changes how any amount is calculated or when anybody is billed. No schema change, no migration, no new setting.
We found it on our own store on 1 September and a ReCurr store reported the same thing in the same month: the first months went through, then several subscribers “renewed” without paying. That is exactly the shape of it. A subscriber base has to be a few months old before cards start to decline, and declines cluster at the start of the month, so it looks like something that worked and then broke. Nothing changed. PayFast answers a declined card with the same outer “success” it uses for a charged one; the decline is inside the reply, with no transaction ID. ReCurr read the outer part only.
Fixed — a declined card is now a failed payment, which is what it always was. A stored-card charge counts as paid only when PayFast confirms it and returns a transaction ID. Anything else goes down the failed-payment path you already know: the order is marked failed, the customer gets the failed-payment email, the charge is retried in 3 days and again in 7, and the subscription goes on hold if all three fail. The reason PayFast gave (“insufficient funds”, “expired card”) is written to the order and the activity log, and PayFast’s own update-card link for that subscriber is now included in the failed-payment email, so fixing the card is one click for them.
Added — Subscriptions → Unpaid renewals. This is how you recover the money. The screen lists every payment on record that was booked as paid with no PayFast transaction behind it — who, which order, how much, when, and what the subscription looks like now — with the total never taken. Retry charge now reopens that same order and charges the stored card: if it goes through, the real payment is recorded, the billing anniversary is kept, the licence ends up exactly where a real payment on the original date would have put it, and the customer gets a “Payment received” email that is now true. If the card declines again, the ordinary failed-payment path takes over. Mark as failed skips the charge and starts the reminders straight away. Retry all does the whole list. A notice on every Subscriptions screen tells you how many are outstanding until the list is empty. The false payment is marked reversed in Payment History, never deleted, so the record shows what happened.
Read the list before you press anything. Every retry emails the customer its result, so if you have subscribers who were told “payment received” three weeks ago, a short note from you before the retry is kinder than the email arriving cold. Where a subscription has been paid since the false payment, the tool leaves its schedule exactly alone and will not start reminders for the old amount.
The tell, if you want to check your own store first: in a subscription’s Payment History, a Completed payment with a blank Transaction ID (—) is one that was never taken. The activity log for the same moment reads “Renewal payment successful. Transaction ID:” with nothing after it.
Also in this release: the refund API was read the same way and is now checked properly; and the PayFast passphrase was being written to the WordPress debug log when debugging was switched on — it no longer is.
Never affected: manual EFT subscriptions, invoice payments by Instant EFT, renewals fully covered by account credit, and any charge PayFast refused outright (a cancelled token, a bad request) — those were always handled correctly. Only bank declines were misread.
Do you need to update? Yes — everyone with card subscriptions, as soon as you can. Until you do, the next declined card on your store will be recorded as paid.
2.7.22 — 9 September 2026 — Paying an invoice online did not renew the subscription
What it means for you: install this one if you invoice by manual EFT and your invoices carry a Pay Now link. When a customer paid one of those invoices online, the invoice was marked paid and the payment was recorded — and the subscription’s licence key was not extended, and no renewal email went out. Nothing here changes how any amount is calculated or when anybody is billed. No schema change, no migration, no new setting.
This is the sibling of the fault in 2.7.21 and it was found the same way, on the same subscription, the day after. Everything that happens when a subscription renews — the licence extension, the payment recorded against the subscription, the last-payment date, clearing the overdue flag, waking a subscription that had gone on hold, and the renewal email — all hangs off one internal step. Marking a WooCommerce order as paid does not trigger it. The online invoice payment path marked the order paid, wrote the payment record itself by hand, and stopped there.
Fixed — a customer paying their invoice with PayFast Instant EFT now actually renews their subscription. This is the damaging shape of the problem, and worth understanding even though it is fixed: because that path did write the payment record, the payment appears on the subscription’s Payment History exactly as it should. The one screen you would open to check is the one screen that looks right, while the licence quietly runs down to its expiry date underneath it. And because it is the customer who triggers it, nobody is watching when it happens. Everything now runs through a single shared step, so there is no longer a path that can do half the job.
Fixed — an invoice can no longer be recorded as paid twice. If a customer paid online and you also pressed Mark as Paid on the same invoice, the subscription took two payments in its history and sent two renewal emails. Whichever happens first now wins, and the second does nothing.
Your own Mark as Paid button was never affected. It always did the full job — licence extension, payment history, renewal email — and it still does. If that is how you settle every invoice, this release changes nothing you can observe.
This release does not repair invoices already paid this way. Their payment records are correct, but the licences were never extended, so those expiry dates need setting by hand. The tell is on the licence record itself: a key whose subscription has been renewed at least once reads CONVERT-<id> in its transaction field, and one that has never been extended still reads SUB-<id>.
Deliberately unchanged: paying an invoice still does not move the billing anniversary. A manual EFT subscription’s schedule is set when it is created and advanced when the next invoice is raised — never by the date a payment happens to arrive. That guard is untouched, so nobody is invoiced for a different amount or on a different date because of this release. Card subscriptions were never exposed to any of this.
Do you need to update? Yes, if your manual EFT invoices carry a Pay Now link and you use the licensing features — that combination is exactly where this bites, and it bites silently. If you settle every invoice yourself with Mark as Paid, or you take card payments only, this can wait for your next routine update.
2.7.21 — 9 September 2026 — Unpaid invoices were being deleted, and nothing ever chased them
What it means for you: install this one if you invoice anybody by manual EFT. Three separate faults stacked up so that an invoice could go out, never be paid, and leave no trace anywhere on your site that money was owed — on a subscription that carried on reading as perfectly healthy, with a future next payment date. Nothing here changes how any amount is calculated or when anybody is billed. No schema change, no migration.
We found it on our own store on 9 September. A quarterly manual EFT subscription at R477.00 was invoiced on schedule on 25 August. The activity log said “Invoice #5920 generated”. The invoice did not exist. The customer had never paid it, the subscription still showed a next payment of 25 November, and the licence key still read active with an expiry date that had already gone by.
Fixed — WooCommerce was quietly deleting your unpaid invoices. A manual EFT invoice has to sit in the pending status until it is paid, because that is exactly what keeps its Pay Now link alive. Pending is also precisely what WooCommerce → Settings → Accounts & Privacy → “Retain pending orders” deletes: it moves every pending order past that age to the trash, on a daily job, with no notice anywhere. That field was set to one week on our store, so every unpaid invoice was in the trash six days before the customer’s fourteen-day licence grace even ran out — and the invoice, their Pay Now link, and your own Invoices → Unpaid list all went at the same moment. Neither side could see the debt. Your invoices are now exempt from that sweep, and from the matching failed-order and cancelled-order rules. The field is blank by default, so if you have never set it, this was never happening to you.
Fixed — nothing ever chased an unpaid invoice. The next payment date moves forward the instant an invoice is raised, before any money arrives, and manual EFT is deliberately excluded from the automatic renewal, retry and reminder runs because there is no card to charge. Between the two, a customer who simply never paid stayed active indefinitely and nobody was ever told. There is now a daily check that emails the customer a reminder on the due date, again a week later, and a final notice a week after that — each carrying the same bank details, reference and Pay Now link as the original invoice, because the commonest reason an invoice goes unpaid is that the first email never arrived — and sends you a summary naming every invoice, what is owed on it, and how late it is.
Fixed — your subscription screen now says when money is owed. Because the next payment date moves at invoice time, the Details panel showed 25 November whether or not August had ever been paid; and Payment History reads the payments table, so an unpaid invoice was never going to appear there either. There was no screen in the plugin on which that subscription looked wrong. A notice at the top of the subscription now lists every unpaid invoice with its amount and its age, in red once it is past due.
Fixed — a failed invoice email is no longer silent. The invoice email’s success or failure was thrown away, so an invoice that never reached the customer was indistinguishable from one that did — the activity log said the invoice went out while your customer waited for an email that was never coming. The result is now recorded on the invoice, shown as “Not sent” on the Invoices screen next to the Resend button, and written to the subscription’s activity log.
Fixed — licence keys past their expiry date now actually expire. This one only matters if you use the licensing features. Expiry depended on a daily task that Software License Manager schedules once, when it is activated, and never checks on again. No re-arm, no reschedule on update. Any plugin update, cron-reset tool or database restore stops all licence expiry permanently and silently: the key stays active, keeps its registered domain, and keeps taking updates for a customer who stopped paying months ago. ReCurr now does the expiry itself rather than depending on somebody else’s scheduled task and somebody else’s checkbox, and puts the missing task back for anything else that relies on it. On the first run this may expire a backlog of keys at once if yours has been stopped for a while. A key expired this way comes straight back to life the moment its subscription is paid — the domain is restored too, and your customer does not re-activate anything.
New setting — Payment Terms, under Settings → Manual EFT, default 7 days. This is the due date printed on the invoice and the point the overdue reminders count from, so the date you give a customer and the date you start chasing them can no longer drift apart.
Fixed for stores on older order storage: when linking a guest’s past orders to a new customer account, the query meant to select just that subscription’s orders was not filtering at all unless High-Performance Order Storage was switched on. It could attach orders to a customer that were never part of the subscription being linked. If your store runs HPOS — which is WooCommerce’s default on any recent install — this was never happening to you.
Deliberately unchanged: nothing is suspended or cancelled automatically. Withdrawing service for non-payment stays your decision, and the licence expiry already handles entitlement on its own schedule. What was broken here is that nobody was told, and that is what is fixed. The new checks email, log and flag, and stop there. The invoice also stays in the pending status rather than moving to on-hold, which would have survived the deletion on its own but would have killed the Pay Now link with it — the status was never the thing that was wrong.
Card subscriptions were never exposed to any of this and are untouched: their renewal orders are paid at the moment they are created, they already have failed-payment chasing, and their licence expiry is pushed forward on every successful renewal.
This release cannot bring back invoices already deleted. It stops the next ones going. WooCommerce moves them to the trash rather than erasing them, so anything trashed in the last 30 days can still be restored from there — after that WordPress has emptied the trash and the invoice has to be raised again. Our own 25 June invoice was long gone; the 25 August one was recovered with three weeks to spare.
Known limitation, found while fixing this and not addressed here. A customer’s email address is held in more than one place, and the only screen that offers an Email field — the licence record — is the one that affects nothing, because no email is ever sent to it. The address your invoices actually go to is the customer’s WordPress account email; the address the Resend button uses is the one stored on that individual invoice; and the address every future invoice is stamped with is held on the subscription itself, which no screen can currently edit at all. Until there is an editor for it, change the address on the WordPress user account and on any unpaid invoice before resending. We hit this ourselves on the same day: the licence record was updated on the customer’s request, the invoice was resent, and it went to the old address anyway. An editor is next on the list.
Do you need to update? Yes, if you raise manual EFT invoices — and check that “Retain pending orders” field before you do anything else, because that one is deleting your invoices right now if it is set. If you take card payments only, this changes nothing you can observe and can wait for your next routine update.
2.7.20 — 30 August 2026 — A converted trial was billed twice for the same month
What it means for you: install this one, and then check your existing subscriptions. Unlike the two releases before it, which only ever acted on stores that had moved to the ReCurr platform, this sits on the ordinary path that every store with monthly pro-rata billing runs. It is a live double charge, and it has been wrong for as long as converting a trial by magic link has existed. Nothing here changes how any amount is calculated. No schema change, no migration, no new setting.
Fixed — a trial converted late in the month was charged for the next month, and then charged for it again. When a customer converts a trial and fewer than eight days remain in the month — or their plan is cheap enough that the part-month comes to less than PayFast’s R5.00 minimum — ReCurr combines the rest of that month with the whole of the next into a single charge, and says so on the confirmation page before they commit. That is correct and it has not changed. What was wrong is what happened next: their next payment date was set to the 1st of the following month, the very month that charge had just paid for. On the 1st, they were billed for it again.
The arithmetic is the clearest way to see it. A R159/month subscription converted on 25 August: R35.90 for the last seven days of August, plus R159.00 for September, taken together as R194.90 — right, and disclosed. The next payment was then set to 1 September, when it should have been 1 October. September would have been paid for twice.
The amount was always right. Only the date was wrong. No customer was ever over-charged at the moment of conversion, and no first charge changes in this release. What changes is when the second one falls.
What was never affected, and is not touched here: conversions from the 1st to the 24th of a long month, ordinary sign-ups with pro-rata, trials that end with a card already on file, anniversary billing, and quarterly and annual subscriptions. The fault was specific to the conversion and to where in the calendar it landed — the state of the trial itself was never part of it, so an early conversion from a running trial and a conversion after a lapsed one were equally exposed.
Check your existing subscriptions, because this release cannot repair them. It changes what future conversions record; a date already stored stays exactly as it is. If you have converted a trial in the last week of any month, open that subscription and check its next payment date before your next billing run — if it is a month earlier than the combined charge paid for, correct it. We found this on our own store with two days to spare before the second charge would have gone out.
Your licence keys need no attention. Key expiry is worked out from the next payment date, so on an affected subscription it was one month short. It corrects itself at the next successful renewal, which always falls before the short expiry — so no customer loses access to updates, and no key needs reissuing.
Also fixed, quietly: a converted subscription now records the same pro-rata detail that a paying sign-up records, so the note on the customer’s account page and the pro-rata email describe a combined first charge properly, instead of reading as though no combination had happened.
Do you need to update? Yes — and sooner than usual if you run trials on monthly pro-rata billing.
2.7.19 — 27 August 2026 — Nobody can charge a card this engine has handed over
What it means for you: nothing at all, unless you move your billing to the ReCurr platform at recurr.co.za. Everything in this release runs only on a store that has completed that move, and no store anywhere has yet made it — checked against the platform’s own records on 24 August 2026, not assumed. If you are running ReCurr as your billing engine, which is every store today, this release changes nothing you can observe. No schema change, no migration, and no change to how any amount is calculated, how any renewal is charged, or how any existing subscription bills.
The background, briefly. ReCurr the plugin and the ReCurr platform are two different products, and a store can move from one to the other. They cannot see each other. 2.7.18 added a guard so that once a store has moved, this plugin stops charging its subscribers rather than charging them a second time — but it only stopped the four things ReCurr does on a timer: the renewal run, the failed-payment retries, the trial-end conversion, and the manual EFT invoice run.
Fixed — everything a customer could still do for themselves. On a store that had moved, a subscriber could still open My Account and update their card, convert their trial, switch plans, or cancel with a refund — and every one of those charges or refunds a card the platform is already handling. All four now stop, explain to the customer in plain language that billing has moved and that nothing has been charged, and record it in the log. Underneath them, the single function through which every stored card is charged now refuses as well, so a path added in a future release cannot charge somebody by accident.
Fixed — three trial jobs that set their own schedules. Trial reminder emails, trial grace expiry and phantom-trial cleanup all schedule themselves rather than going through the renewal scheduler, so 2.7.18 stopped none of them. On a store that had moved, one of them told subscribers about a charge this engine would never make, and the other two cancelled the subscription here and emailed the customer about it while the platform carried on billing their card, with nobody involved.
Fixed, and this one needed the most care — a payment page that outlives the button that made it. When a customer updates their card, ReCurr creates a real R5.00 order and sends them to WooCommerce’s ordinary order-pay page — not a ReCurr page. That page is in their browser history and in mail already sent, and it keeps working perfectly after the My Account page that created it has been closed. Simply withdrawing ReCurr’s own gateway there is not enough: that page offers every payment method your store has available, and the standard PayFast gateway does not look at the order at all before offering itself — so the customer would have paid through that one instead, and the double charge would have arrived through the fix for the double charge. The order itself is now marked as not needing payment, which no payment method can override, and the customer is told why.
Manual EFT invoices stay payable there, deliberately. They are a bill for a period that has already been served. The rule this release is built on: the guard stops ReCurr starting new billing, and it does not cancel debts already owed to you or trap money owed back to your customer. For the same reason a customer can always still cancel, and any credit still sitting pending on their account is still refunded to them when they do.
Changed — the subscription pages become read-only rather than disappearing. On a store that has moved, My Account still shows the subscription as this store last recorded it, marked as billed by ReCurr, with the actions removed. If the ReCurr Connector says it has taken those pages over, ReCurr stands aside entirely and the connector renders alone. Withdrawing unconditionally was the obvious approach and is the wrong one — connector 0.5.0 stands down when it finds this engine installed, so both sides withdrawing would leave your customer looking at a blank page.
Three places go quiet without explaining themselves, and they are named here rather than left to be discovered: the Pay button on My Account → Orders is not shown for those orders; WooCommerce’s own invoice emails stop including a pay link for them; and Customer payment page → on the admin order screen is not drawn. In each case something simply is not there, with nowhere to print a reason beside it. A pay link in mail already sent still works, and lands on the order-pay page, which does explain itself. The two routes a customer actually arrives on both carry the explanation. The admin link is deliberately not exempted — it hands you a URL leading straight to the double charge, and if you genuinely want that payment you can still mark the order paid directly.
Do you need to update? Not urgently, and not at all if you are staying on ReCurr as your billing engine. Nothing here repairs damage, because none of it has ever been able to happen: this is a gap closed before it can fire. Update it before you migrate, and take it with your next routine update otherwise.
Also in this release, and worth one line: two comments in the shared billing engine that had quietly become misleading — the note recording that the connector calls into decrypt_token(), which was split across separate blocks where documentation tools only ever read the last one, and a note on the credit ledger stamped with a version number that made shipped behaviour read as future work. Comments only, in both plugins, with not one token of executable code changed in either.
2.7.18 — 24 August 2026 — Two billing engines cannot be pointed at the same customers
What it means for you: nothing changes unless you have connected this store to the ReCurr platform at recurr.co.za. If you have not, this release changes nothing you can observe. No schema change, no migration, and no change to how any amount is calculated, how any renewal is charged, or how any existing subscription bills.
Added — ReCurr stops billing once your store has moved to the ReCurr platform.
The plugin and the platform are two separate products, and they cannot see each other. The platform does not deactivate this plugin when you migrate — so a merchant who moves, later reactivates the engine while troubleshooting something, and leaves it running has two billing engines charging the same cards on the same dates. Nothing errors, nothing looks wrong anywhere, and the customer simply pays twice.
ReCurr now reads a marker the ReCurr Connector writes once, immediately after the platform confirms your cut-over, and never clears. If it is there, the platform is charging your subscribers and this plugin does not. What stops, precisely: the renewal run, the failed-payment retry run, the trial-end conversion, and the manual EFT invoice run. Nothing is cancelled and nothing is lost — subscriptions, renewal dates, trial dates and stored cards stay exactly as they are, and renewals resume from their existing dates if billing ever moves back here. Nothing is backdated and no missed renewal is caught up.
It keys on the cut-over and deliberately not on the connection. Connecting your store is step 2 of a six-step migration and the platform bills nobody until step 6. Keyed on the connection instead, the guard would have stopped renewals on every migrating store for the whole window between those two steps — and from the first page load after connecting, not the next scheduled run. A store that is connected but has not cut over gets the opposite treatment: a dismissible notice saying ReCurr is still your biller and not to deactivate it yet. Notice only, never a refusal.
Added — a way back, because the marker is never cleared. A merchant who moves to the platform and later brings billing back here would otherwise be locked out of their own engine permanently. An administrator ticks “I confirm the ReCurr platform no longer bills this store’s subscribers” and billing resumes on the next request. It is a confirmation of fact rather than a preference, because it asserts the one thing the plugin cannot check for itself. Who turned it on and when is recorded, a standing warning stays up for as long as it is off, and one click re-arms it.
Activation is never refused, deliberately. Refusing to activate on the strength of an option written by a different plugin would leave a merchant unable to activate at all, with no way back in. Installing is not billing — the same line 2.7.17 drew for the licence. Tables, roles, options and scheduled jobs are all created as usual; the refusal happens where money moves.
Known gap, stated rather than hidden: a store that cut over on connector 0.4.0 has no marker, because that version does not write one, and would get the notice-only treatment rather than the refusal. The platform team’s position is that no store has cut over on 0.4.0, and it is ours too, but they have told us plainly that they have not verified it against their production records. That is why the notice-only branch exists at all rather than nothing.
Do you need to update? Only if a move to the ReCurr platform is on your horizon, and then yes, before you start. Otherwise it costs one read of one setting per page load and changes nothing else. The admin screens, My Account, checkout and the gateway all still load on a store that has moved — you still need to read your own subscription data. Only billing stops.
2.7.17 — 18 August 2026 — Three ways billing could stop, or charge twice, without telling anyone
What it means for you: install this one. Every fault below is silent — no error message, no email, no failed checkout, nothing in any report. That is precisely why none of them was caught sooner, and why we would rather you did not wait on this release. Two of them stop money reaching you. One of them takes it twice. None of them needs your customer to do anything unusual.
Nothing here changes how any amount is calculated, how any renewal is charged, or how any existing subscription bills. No schema change, no migration, and no stored data is rewritten.
Fixed — an expired licence quietly stopped charging every one of your subscribers.
ReCurr only started up if its licence validated. If it did not — the licence expired, the site moved to a new domain, or the key was activated elsewhere — the renewal job stayed scheduled with nothing behind it. Renewals simply stopped. Nothing failed, nothing was logged, no email went anywhere, and the only signal was a notice on the WordPress dashboard that somebody had to log in and read. A subscriber whose renewal quietly stops does not complain; they keep the product free until somebody notices.
If your licence has been active throughout, none of this has happened to you and nothing about this release changes your day-to-day.
From this release, a store that has been licensed gets a 30-day grace window if its licence stops validating. During that window your subscribers keep being charged exactly as before, and you are told three times: an email when the licence first fails, another when a week is left, and another if billing actually stops. The dashboard notice now says which of those is happening and gives the date. Reactivating your licence at any point clears the window completely, with nothing to repair. If billing does stop, nothing is cancelled and no data is lost — renewals pick up where they left off the moment the licence is active again.
Deliberately unchanged during the window: ReCurr runs exactly as it does on a fully licensed store — every feature, every screen, every setting. We did not build a reduced “billing-only” mode, because that would be a state the plugin has never run in, and a lapsed licence is the worst possible moment to be the first person testing one. A store that has never activated a licence gets no window — it has never billed anybody, and the window is protection for your existing subscribers, not a trial.
Fixed — installing ReCurr before entering your licence key created none of its database tables.
ReCurr’s setup routine ran only once the licence had validated. On a brand-new install there is no licence key yet, by definition — so activating the plugin first and entering the key afterwards, which is the obvious order to do it in, meant the subscriptions table, the user roles, the default settings and the scheduled jobs were never created. The only thing that fixed it was deactivating and reactivating the plugin after the key was in. Setup now runs on activation regardless of licence state. Installing is not a licensed act; billing is. Existing working stores are unaffected — their tables already exist and nothing is recreated or altered.
Fixed — a stored card that could not be read was reported as a customer who never had one.
ReCurr encrypts your customers’ stored PayFast cards using a security key from your WordPress configuration (AUTH_KEY). Regenerating those WordPress security keys is standard hardening advice — it is in every security guide, it is what the “salt shaker” plugins do, and it is the first thing most people do after a suspected compromise. The moment it happens, every stored card on the store becomes unreadable at once.
Until now ReCurr could not tell an unreadable card from a customer who had never given one. It would have worked through your entire subscriber base one at a time, treating each as having no card, sending each into failed-payment chasing for a card that was never actually declined, and eventually cancelling them — while the logs said those customers never had cards.
Now an unreadable card is treated as what it is: an incident. It is recorded distinctly, you are emailed, and that renewal is held rather than failed — no order is created, no payment chasing starts, your customer is not emailed and nothing is cancelled. If several in a row cannot be read, ReCurr stops the whole run and waits for a person rather than working through the rest. The subscription screen now shows “Stored but unreadable” where it previously showed nothing at all.
Please read this part honestly: once the old AUTH_KEY value is gone, the stored cards are not recoverable. If you still have the previous value, putting it back in wp-config.php makes them readable again. If you do not, those customers have to enter their card again through My Account → Subscriptions → Update Payment Method. This release makes the failure visible and stops it doing damage — it cannot undo it.
Fixed — every time the Update Payment Method link was opened, it created another R5.00 order.
That link creates a real R5.00 order and sends your customer to PayFast to register their new card. Nothing checked whether one already existed, and a WordPress security token stays valid for 12–24 hours — so the same link kept working. Three completely ordinary ways in: pressing back after landing on PayFast, double-clicking the link, and a link-preview fetch by a mail or chat app, which needs nobody to touch anything at all.
Each one left an orphan R5.00 pending order sitting in your store, indistinguishable from a genuine abandoned checkout. Worse, a customer who reloaded and then paid sent R10.00 as two separate R5.00 debits — both credited back to them by the ledger in the end, but both on their bank statement, from a page whose entire message is that it will not cost them anything. An order already waiting for payment for that subscription is now reopened rather than duplicated.
Existing orphan orders are left exactly as they are. This release stops new ones being created; tidying up the ones already in your order list is your call about your own records, not something an update should do behind you.
Do you need to update? Yes. If your licence has been active, your WordPress keys have never been regenerated and nobody has used the Update Payment Method link, then nothing has gone wrong on your store — and this release closes three faults before they can. Nothing about how a PayFast charge is built, signed or sent has changed, and no existing subscription, date, amount or stored card is touched.
Known limitation, stated rather than left to be discovered: subscription settings appear on Simple products only. A variable product — sizes, tiers, seat counts — cannot carry subscription settings, and there is nothing to diagnose because the fields simply are not shown. This is longstanding and deliberate; it is written down here so it stays on the roadmap as a known limitation.
2.7.16 — 17 August 2026 — Groundwork for affiliate renewal commissions
What it means for you: nothing changes in how ReCurr behaves. No fix, no new setting, no schema change, and no money moves differently. This release exists so that ReCurr Pro 3.0.11 can do something it previously could not, and it is only worth installing for that reason.
Added — two extension points on the renewal charge.
When ReCurr renews a subscription it charges the customer’s stored card through PayFast. That charge previously had no way for another plugin to add anything to it, even a field PayFast itself supports. The initial checkout has had such a hook for a long time; the renewal charge had none at all. Two were added, and until something registers on them they do nothing whatsoever.
Why it matters: ReCurr Pro pays affiliate commissions on renewals by asking PayFast to split each renewal charge. Without a way to attach that instruction to a renewal charge, Pro could not send it — which is one half of why recurring affiliate commissions have never actually been paid. ReCurr Pro 3.0.11 uses these hooks to fix that.
Do you need to update? Only if you use ReCurr Pro — and then yes, before updating to ReCurr Pro 3.0.11, which requires this version. If you do not use ReCurr Pro, this release changes nothing for you and can safely wait until the next one.
2.7.15 — 15 August 2026 — A cancellation could record, and email, an end date already in the past
What it means for you: install this one. Unlike 2.7.14 below, this needs no pausing to reach — the route that matters is an ordinary failed-card cancellation, which every store has. No money has moved incorrectly and nobody lost access early. What was wrong is what your customer was told on the way out, and a stored date that contradicted itself.
Fixed — a subscription cancelled after a failed payment was given an end date before the cancellation.
When a subscription is cancelled, ReCurr records the date access runs to, on the reasoning that a customer keeps the period they have already paid for. That is the next payment date — which holds only while the next payment date is still ahead. In dunning it is not. A failed payment schedules a retry; it never advances the payment date. So a subscription sitting on hold with a failed card has a due date in the past by definition — that is exactly why the renewal job picked it up in the first place. Cancelling it recorded an end date earlier than the cancellation, and sent the customer an email reading “you will retain access until the end of your current billing period on” a date that had already passed. A paused subscription reaches the same state the other way: pausing freezes the clock and only resuming moves the payment date, so a pause that outlives the time remaining on the period leaves the date behind it.
The date is now clamped forward to the moment of cancellation and never backwards. A cancellation with a genuine future date is completely unchanged — nothing is extended, and no paused time is credited back, which is the same position 2.7.14 sets out. When the clamp does apply it is written into that subscription’s own log, so you can see it happened.
Fixed — the cancellation email and the cancel dialog both quoted that date without checking it.
The email now says plainly that no time remained and access ends now. The cancel dialog says the same before your customer confirms, with wording of its own for a paused subscription: that paused time is not carried over or refunded. Neither is a promise that has changed — only one that is now true.
Fixed — reactivating a cancelled subscription left the end date on it.
The end date is written when a subscription stops and nothing ever cleared it, so a subscription you reactivated carried a date saying its access had already run out. Two things read that date: the cancellation email quotes it, and the pause resume shift moves it forward if it is set, carrying the dead value along on the next pause. Reactivating now clears it — an active subscription has no end date — and records what it cleared.
Do you need to update? Yes. Nothing enforces the end date — the renewal job works off status and payment date, and a licence is deactivated by the cancellation itself — so no customer has been cut off early and no refund has been miscalculated. But any customer who has cancelled out of a failed payment has been sent an impossible date, and that is worth stopping. Existing records are not rewritten: a past end date already sitting on a cancelled subscription stays as it is. No schema change, no migration, and the refunded-cancel path is untouched.
2.7.14 — 15 August 2026 — An abandoned pause could hand back months of unbilled service
What it means for you: install this one if you have pausing switched on. Nothing here touches trials, mixed baskets, pro-rata or checkout. The only behaviour that changes is what happens to a pause that ends without being resumed. If pausing has never been used on your store, or your subscribers have only ever paused and resumed normally, there is nothing to repair.
Fixed — a pause that ended any way other than “resume” was never cleared, and the next pause inherited its date.
ReCurr records the moment a subscription is paused, and uses it on resume to push every forward-looking date by exactly the time paused. That record was cleared in exactly one place — the pause → active resume — so a pause ending any other way left it behind. Worse, the write that sets it declined to overwrite an existing value, so the next pause inherited the abandoned one’s date instead of stamping its own. Resuming then measured the pause from the wrong month and pushed the next payment date, the end date and (where licence automation is in use) the licence expiry forward by the entire span since the abandoned pause. Unbounded, always in the customer’s favour, and silent: the renewal job selects on the next payment date, so nothing errors and nothing retries. The first sign is a renewal that simply never arrives.
A pause is now cleared on every exit that is not a resume, and a fresh pause always stamps the current date.
This was reachable without you doing anything unusual. Cancelling a paused subscription and later reactivating it is one route, but a status change has no fixed transition table, so the admin status box also offers paused → on-hold and paused → pending. The route that needs nobody at all: a customer pauses, a payment later fails and moves the subscription to on-hold, then the customer updates their card and PayFast reactivates the subscription on successful re-tokenisation. That is fully self-service, start to finish.
Fixed — the auto-resume marker could describe the wrong pause.
The marker set when a pause reaches its maximum length, used to word the “your subscription has resumed” email, could survive onto a later pause and describe it wrongly. A new pause now starts with it cleared.
Deliberately not done — no date shift is applied on the way out. Time paused before a cancellation is not credited back, and time spent on hold is not billable, so shifting there would return dunning time as free service. Any goodwill credit for an abandoned pause stays your decision.
Do you need to update? Yes, if you have ever paused a subscription. An ordinary pause → resume shifts exactly as it always has, by the real paused duration. No schema change, no migration, and no change to the pause maximum, the auto-resume job, or any email.
2.7.13 — 10 August 2026 — “No card is required” was shown over an order about to be charged
What it means for you: install this one. Two of the faults below are older than 2.7.12 and are live on any store running 2.7.8 or later. Both concern a mixed basket — a free-trial subscription bought in the same order as an ordinary product. Trial-only baskets are unaffected by everything here, and no money has moved incorrectly on any store: your customers were charged the right amount, and were told the wrong thing about it.
Fixed — the classic checkout told mixed-basket customers no card was required, immediately before charging them.
On the classic checkout the free-trial notice sits directly above the payment button. It was the one place that never checked whether the whole basket was a trial, so a customer buying a free-trial subscription alongside an ordinary product read “No payment is taken today and no card is required” on the page, then went straight to PayFast and paid for the ordinary product. This has been live since 2.7.8, when the mixed-basket check was added to the other notice and this one was missed. It now carries the same check. Block Checkout was never affected. A genuine trial-only basket shows exactly the notice it always did, including on themes where the notice renders late.
Fixed — stock was not reduced on anything bought alongside a trial.
A trial order told WooCommerce not to reduce stock, but that instruction applies to the whole order, not the trial line. So a stock-managed product bought alongside a free trial was paid for and shipped without ever being decremented: your stock count stayed high and the sale looked as though it had never happened. Stock is now left alone only when every line in the order is a qualifying trial and the order total is zero — which is exactly when nothing is charged. Any order with money in it reduces stock normally. If you sell stock-managed products alongside trials, your counts may currently be overstated; this release stops it happening again, and does not attempt to reconstruct past orders.
Fixed — the product page advertised a trial that checkout would decline.
A product whose trial is longer than its billing period showed a “✓ N-day free trial” badge on the catalogue and product pages, promising a trial 2.7.12 refuses at the payment step.
Changed — the billing cycle toggle no longer exempts a product from the trial rule.
2.7.12 exempted products using the billing cycle toggle, on the reasoning that the toggle only offers monthly, quarterly and annual, so whichever cycle the customer picks is longer than any trial. The cycle list is right, but nothing required the toggle to be usable: the cycle selector only appears once you have ticked at least two cycles, so a weekly product with a 28-day trial and the toggle ticked went on billing weekly with every check skipped — the exact configuration 2.7.12 exists to refuse. A trial is now measured against the shortest term the product can actually be bought on. This is stricter, and it also catches an annual product that offers a monthly cycle: it is now judged on the month rather than the year. A product on the ordinary configuration keeps its trial — monthly with all three cycles offered is judged on the month, 31 days, against a maximum trial of 28.
Added — the billing cycle toggle now refuses to switch on with fewer than two cycles.
The field has always said “At least 2 must be selected” and nothing enforced it. Ticking the toggle with one cycle selected left it switched on doing nothing at all: no selector on the product page, no warning, no effect. Saving that combination now leaves the toggle off and tells you why. The cycles you ticked are kept, so adding a second one and re-ticking the box is all it takes.
Fixed — two problems on one save no longer hide each other. A product save that refused both an over-long trial and the cycle toggle showed only one of the two notices; the other refusal happened with no explanation on screen.
Do you need to update? Yes, if you sell free trials — and especially if a customer can put a trial and an ordinary product in the same basket. Every trial that fits its billing period behaves exactly as it did in 2.7.12, and every trial-only basket looks and prices exactly as before. No pro-rata arithmetic, no billing date, no existing subscription and no stored data is touched.
2.7.12 — 10 August 2026 — A trial can no longer outlast the period it precedes
What it means for you: this is a guard, not a repair. Nothing was billing wrongly, and this release changes no data and no dates. It closes a configuration ReCurr had never refused: a free trial longer than the billing period it precedes — a 28-day trial on a weekly product, which hands the customer four billing periods free and leaves the trial-end machinery reasoning about a trial that has outlived its own term. Nothing stopped that being set up: not the product screen, not the cart, not the gateway. Recommended for everyone; urgent for nobody.
Added — the product screen now refuses the combination.
Save a product whose trial is longer than one billing period and the trial is switched off, with a notice naming the product, the trial length, the billing term and the maximum for that term. The duration you picked is left in the field so the screen still shows what you intended when you come back to correct it. It is never dropped silently — a trial you ticked and saw no error about would look like it was running.
The maximums are day 1, week 7, month 31, quarter 92, year 366 days, multiplied by your billing interval (so “every 2 weeks” allows up to 14). They are deliberately ceilings rather than averages: a legitimate 31-day “first month free” is not refused for the accident of being saved in February. A trial of exactly one period is fine and always was — “your first week free” on a weekly product is untouched, and is what the Standard tier configures by default.
Added — checkout can no longer promise a free trial it cannot honour.
The no-card trial path completes the order at R0 and never stores a card, so a subscription created from a non-fitting product would have had nothing to charge when the trial ended. Such a basket now takes the ordinary PayFast path: the sale still completes, the customer still gets the product, and a card is on file. The cart, Block Checkout and the subscription writer all ask the same single question about a product. (One classic-checkout notice was missed and still answered it on its own; 2.7.13 brings it into line — see below.)
Added — products configured before this release are handled, not rejected.
A subscription created from an already-saved non-fitting product is billed on its normal term and records a note in its own log saying the trial was not applied. It is not failed: the customer has checked out and paid, and refusing the subscription over a configuration mistake would turn a pricing fault into a lost sale.
Changed — the note under the trial settings told everyone they were giving a 7-day trial, including merchants who had just selected 28. It now reflects the duration actually configured.
Also: three options seeded at install (crb_enable_trials, crb_trial_period, crb_trial_interval) that nothing has ever read are no longer created. One global trial length applied across products with different billing periods is this same fault in another form. Rows already on your site are left alone.
Do you need to update? Take it with your next update. Every product whose trial fits its billing period behaves exactly as it did in 2.7.11 — each guard is a single extra condition on a check that already existed, and anything ReCurr cannot judge is treated as fitting, so a gap in your data can never become a failed checkout. No pro-rata arithmetic, no billing date, no existing subscription and no stored data is touched, and none of the mixed-basket work from 2.7.7 → 2.7.11 changes.
2.7.11 — 9 August 2026 — Trials bought alongside a once-off product
What it means for you: the mixed-basket work of 2.7.7 → 2.7.9 fixed what those customers were charged at checkout. This release fixes what happens to them when the trial ends — which, it turns out, was nothing. A trial bought in the same basket as a once-off product was never charged at trial end; the subscription went on hold and stayed there. Update immediately if you sell once-off products alongside trial subscriptions. A basket holding a trial on its own is untouched by every fault below.
Fixed (important) — the trial-end charge was never taken, and the subscription stalled on hold.
That basket is not a free-trial signup: the customer pays for the once-off item at checkout and their card is stored in the process. Trial-end processing did not know this — it treated every ending trial as though no card existed, so it put the subscription on hold, emailed the customer a magic link asking for the card they had already given, and never took the pro-rated amount their checkout had quoted. Nothing then moved the subscription on, so it sat on hold indefinitely, neither billing nor cancelling.
A trial now ends according to whether a card is actually on file. No card: the existing hold-and-ask flow, completely unchanged. Card on file: the pro-rated amount is charged, the subscription goes active, and the customer gets the confirmation explaining the amount.
Worth checking: any subscription sitting at On Hold whose trial has already ended is this fault.
Fixed (important) — the code that should have taken that payment had never run.
It has been present but unreachable since 2.4.13 — nothing ever called it. It was rewritten rather than simply connected, because as written it would have been worse than the stall it was meant to fix: a declined card left the subscription in trial, where the hourly job would have found it again and re-charged the card every hour until it went through. It also dated an extended first payment a month early, and put the charge on a fee line with no product line and no tax.
A declined charge now puts the subscription on hold for 7 days and cancels it if unsettled — exactly as a lapsed no-card trial does — and the cancellation email says the card was declined rather than claiming no card was ever added.
Fixed — signups abandoned at PayFast left stranded trial subscriptions.
A mixed-basket signup that never completed at PayFast left a trial subscription with no card on it: nothing could charge it and nothing could cancel it. The hourly cleanup built for exactly this was switched off in 2.4.13 and is running again, narrowed so it can only ever see subscriptions genuinely sent to PayFast for a card. No-card trials are outside its reach entirely, by two independent checks.
Fixed — every trial email these customers received was written for someone with no card.
The welcome email opened with “No payment has been taken and no card is on file” — sent to a customer who had just paid for the once-off item. The three reminders then asked them to add a card and repeated that they would not be charged, before the trial-ended email asked a fourth time. All four now match what will actually happen: a customer with a card on file is told what will be charged and when, and pointed to My Account to change the card or cancel. Wording for no-card trials is unchanged and still sent word for word.
Also fixed — the cancellation email could contradict the customer’s own checkout.
A customer whose trial-end charge was declined was told their trial ended “without a payment card being added”. Their card was on file and had been tried. The two cases are now told apart. (This one was introduced by the routing added in this release group and fixed before shipping.)
For developers: crb_trial_completed now passes the order as a third argument, a new crb_trial_completion_failed fires alongside it, and the trial-end order fires crb_renewal_order_created rather than crb_prorata_order_created. Neither old hook has ever fired in any installation, since the code that would have fired them was unreachable.
Do you need to update? Yes if you sell once-off products alongside trial subscriptions — this is revenue that was quoted to the customer and never collected. Nothing here touches a trial-only basket, a paid subscription, manual EFT, or any renewal.
2.7.10 — 8 August 2026 — Repeat payments, the payment hand-off, and order details
What it means for you: three fixes on the path a customer takes after placing an order. One of them is important: paying a pending order a second time created a second subscription. The other two are display and reliability fixes on the same journey. Nothing here changes a price, a billing date, or how a renewal is charged. Recommended for everyone.
Fixed (important) — paying a pending order twice created a second subscription.
When a customer leaves without completing payment — cancelling at PayFast, closing the tab, a card that declines — the order stays pending, and WooCommerce offers them a Pay button for it. Taking that button ran the subscription setup again from the beginning, with no knowledge that it had already run once. The customer ended up with two subscriptions for one order: the second one live and billing them, the first left pending forever, and where a trial was involved, two trials. Nothing ever cleaned the first one up.
An order can now only ever own one subscription. A repeat payment reuses the subscription the order already created — keeping its billing cycle, its trial and its dates — and records a note on the order saying so. A cancelled or expired subscription is deliberately not revived: paying an old order creates a fresh subscription, exactly as before.
Worth checking: this prevents new duplicates but does not clean up existing ones. In Subscriptions, look for two subscriptions sharing a single parent order — the older one will be sitting at Pending with no payments against it.
Fixed — the hand-off to PayFast could show a page with nothing on it.
After placing an order the customer is sent to a page that hands off to PayFast. The details of that hand-off were held only in the browsing session, and any visit that arrived without it produced the order summary followed by nothing at all — no payment form, no button, and no error message either, because the error was queued for the next page rather than printed on that one. This affected refreshing the page, returning later to pay a pending order, opening the customer payment page from the order screen, and any checkout whose session did not carry across. Every detail of the hand-off comes from the order itself, so the page now rebuilds it when the session has nothing.
Fixed — the order summary showed the wrong amount as the first payment.
The grey summary printed under a subscription on the customer’s order page showed the whole order total as that subscription’s “Initial Payment (Pro-rata)”. On a basket holding a subscription and a once-off product together, that figure is the once-off product’s money, printed under the subscription and labelled as its first payment — which reads as though the once-off item had become the recurring charge. It now shows the subscription’s own line total.
On a trial signup the same box read “You were charged a pro-rated amount for the remaining days of this month” over an amount of zero. Nothing is charged on the day a trial starts. It now states no charge today, the date the trial runs until, the pro-rated amount due when it ends, and the recurring amount after that — and that pro-rated figure is the one actually stored against the subscription, which was previously never displayed anywhere despite being what the box claimed to show.
Also: the payment method now appears on the pay-for-order page only for orders it is responsible for, rather than for every order on that page; and paying a pending order no longer empties the customer’s shopping basket, which was previously cleared unconditionally.
Do you need to update? Yes if you take card subscriptions — the duplicate-subscription fault affects any store where a customer can abandon payment and come back to it, which is every store.
2.7.7 → 2.7.9 — 8 August 2026 — Mixed baskets: trials, billing cycles and once-off products
What it means for you: if you sell once-off products alongside subscriptions, this group of releases matters a great deal. A basket holding a subscription and a once-off product took a wrong turn in several separate places — one of which gave products away for nothing, and one of which billed a customer the wrong amount for the life of their subscription. Update immediately if you sell mixed baskets. A basket holding a subscription on its own was never affected by any of it.
Fixed (important) — a paid order could complete without taking payment (2.7.7).
A free-trial signup is meant to be a zero-total order, completed on your site without the payment gateway ever being called. The check that recognised a trial signup stopped at the first trial product it found in the basket — it never asked whether the basket held anything else, and never looked at the total. A customer who added a trial subscription and a once-off product together received the once-off product for nothing. The result is a completed order with no payment against it, which is easy to miss because it looks like every other successful order.
A trial signup now requires every line in the order to be a trial product. A trial alongside a once-off item is treated as an ordinary paid checkout — the customer is charged, the card is stored, and the subscription still starts in trial. As a second line of defence, the no-card path now refuses to mark an order paid when the total is above zero. Worth checking your orders: a completed order containing a trial product, with a total above zero and no payment recorded, is this fault.
Fixed (important) — the billing cycle your customer chose was discarded (2.7.9).
The code that reads the chosen cycle off an order looked at the first line only, and WooCommerce does not order line items by type — so on a mixed basket it just as easily read the once-off product, which carries no cycle at all. Finding nothing, it fell back to the product’s default period, which is monthly. A customer who selected Annual got a monthly subscription, at the monthly price, renewing monthly.
Fixed (important) — a once-off product was charged again on every renewal (2.7.9).
Every line in the order was written into the subscription’s stored items, and renewal orders are rebuilt from those items — so a setup fee or once-off charge, paid once at checkout, was billed again for the life of the subscription, and inflated every renewal total on top of that. Only subscription lines are stored now. This fixes new sign-ups only: a subscription already carrying a once-off item keeps it until you remove it.
Fixed (important) — the free trial was dropped entirely (2.7.9).
Trial settings were read from the first line and the search stopped there, so the once-off product’s “no trial” answer ended it. The subscription was created with no trial at all — no trial status, no trial end date, the first payment a full billing period out, and no trial-started email — while the basket had already priced the trial line at zero.
Fixed (important) — the checkout promised “no card required” on a basket it was about to charge (2.7.8).
On the block-based checkout, a basket holding a trial subscription alongside a once-off product still presented itself as a free trial activation: the payment method read “Activate Trial — no card required”, the description promised no payment would be taken, the trial banner showed, and the order button read ACTIVATE TRIAL — all above a real total the gateway was about to charge. The money was correct from 2.7.7 onwards and the customer was charged as they should have been; what the checkout told them was not. The block-based checkout has its own trial decision, separate from the classic checkout’s, and only the classic one had been fixed.
Also in this group: on the block-based checkout the safety net that re-saves the chosen billing cycle onto the order never ran, because it was attached to an action only the classic checkout fires; and the mixed-basket warning notice could appear several times on one page.
2.7.4 → 2.7.6 — 6 August 2026 — Licence expiry, domains and plan changes
What it means for you: three releases about licensing. None of them affects billing — your subscriptions keep charging normally throughout, and an expired or replaced licence never switches the plugin off. What a licence problem costs you is plugin updates, and the recurring theme here is that it used to cost you those silently.
Fixed (important) — an expired licence reported itself as active (2.7.4).
The licence screen showed a green “Licence is active and valid!” banner directly above an expiry date already in the past, while plugin updates had quietly stopped working. Expiry is now checked and stated plainly, together with a note that billing continues and only updates are affected.
Fixed (important) — licences expired on the day the renewal invoice was raised (2.7.4).
Expiry was set to the next payment date plus one billing cycle, but at the moment a licence is issued that date can still be the invoice just raised rather than the one after it — which collapses the intended cycle of grace to nothing. A quarterly manual-EFT customer invoiced on the 25th had a licence that lapsed the same morning the invoice reached them. Expiry now carries an explicit grace period on top of the billing cycle, set by the new crb_license_grace_days option and filter (default 14 days).
Fixed (important) — updates refused for a licence with nothing wrong with it (2.7.5).
Activation identified your site by one name and the update check by another, so the update server was asked about a domain that had never been registered against your key. WordPress reported only “Automatic update is unavailable for this plugin”, with no indication why. Both now use your site’s own address, and a valid licence holding no registered domain repairs itself on its next update check.
Fixed (important) — a replaced licence key looked fine indefinitely (2.7.6).
When a plan change replaces a licence key, this site had no way to find out: the licence check reports success for any key the licence server has ever issued, without checking whether that key is still the current one. The licence page kept showing the same green tick, and the first sign of trouble came weeks later when an update refused to install. A replaced key is now reported as replaced, on the licence page and as an admin notice, naming the plan it was replaced for.
Fixed — a move to a lower plan now actually takes effect (2.7.6).
Your feature tier was read from the licence key and then cached, and only re-read when a key was activated or deactivated — so a site that moved down a plan kept the higher plan’s features indefinitely. The tier only ever steps down; an upgrade’s features still arrive with the new key you enter.
Also in this group: guest-checkout subscriptions were invisible in My Account even after the customer created an account, and are now adopted automatically by matching email address (billing was never affected); and for stores issuing their own keys through Software License Manager, an expired licence never released its registered domain.
2.7.3 — 5 August 2026 — First payments, billing dates and licence emails
What it means for you: a group of fixes around the first payment on a subscription, plus two licence-email faults. Recommended for everyone, and important if you use manual EFT.
Fixed (important) — the amount recorded against a payment was wrong.
A pro-rata first invoice, or any invoice carrying a credit, was written to the payment history and announced in both the customer and admin emails at the full subscription price rather than the amount actually paid.
Fixed (important) — paying a manual EFT invoice moved the billing date.
The invoice schedule is owned by the Invoice Day setting and the renewal scheduler, but every payment recalculated the next payment date from the day it was received — so an invoice settled a few days late shifted the billing anniversary by those days, permanently. Manual EFT invoices now leave the schedule alone.
Fixed (important) — auto-issued licence keys were never emailed.
On manual EFT subscriptions the key was generated and visible in the admin, but the email carrying it only fired on a status change these subscriptions never make. The key is now sent when it is issued, and cannot be sent twice.
Fixed (important) — licence emails named the wrong vendor.
The activation steps that ship with a licence key were written for one specific shop — they sent your customers to that shop’s downloads page and named its plugin. They are now built from your own site. Two new filters, crb_license_email_instructions and crb_license_change_email_instructions, replace the wording entirely if your activation flow differs.
Also: a subscription’s first payment was announced as “renewed successfully” and now gets its own message; and there is a new optional Branch Name field under Manual EFT settings, shown on invoice PDFs and emails.
2.7.2 — 31 July 2026 — Manual EFT invoice dates
What it means for you: only affects manual EFT subscriptions on a quarterly or annual cycle. If you run card subscriptions or monthly manual EFT, nothing here changes.
Fixed (important) — quarterly and annual manual-EFT dates could jump a whole period.
The next payment date was worked out from the day the invoice was raised rather than the due date it was raised for, so an invoice generated on any other date permanently shifted the billing anniversary and gave the customer a free period. A quarterly subscription due 25 August, invoiced on 25 June, moved to 25 September instead of staying on 25 August. Monthly subscriptions invoiced on their due date produce exactly the same dates as before.
Also fixed: the billing interval was ignored when working out the next manual EFT invoice date, so an “every 2 months” plan was invoiced monthly; and month arithmetic overflowed on long months when the invoice day was set to 29, 30 or 31 (31 January plus one month gave 3 March, skipping February). Dates are now clamped to the last valid day of the target month.
2.7.1 — 20 July 2026 — Maintenance and hardening
What it means for you: a housekeeping release from a full code audit. There are no new features and nothing changes in how your subscriptions bill. One real bug is fixed, two security items are tightened, and some long-standing clutter is cleared out. Recommended for everyone, and safe to install without any configuration changes.
Fixed — checkout could hang instead of showing an error.
If creating a subscription failed during checkout, the payment step returned nothing at all rather than a failure result. WooCommerce had nothing to act on, so the spinner turned indefinitely and the customer never saw the reason. This affected the standard checkout path and, in the internal build, the free-trial paths as well — including the “one trial per customer” block, where a returning customer attempting a second trial would simply hang instead of being told to pick a paid plan. All of these now return a proper failure so the message is displayed and the customer can act on it.
Hardened — PayFast notification source-IP check.
Incoming PayFast payment notifications are checked against PayFast’s own server addresses. That check previously read the left-most X-Forwarded-For header value, which any caller can set to whatever they like. It now prefers Cloudflare’s CF-Connecting-IP header, falls back to the right-most forwarded entry (the one added by the nearest proxy, which a caller cannot forge), and finally to the direct connection address. Genuine notifications are unaffected; the signature check and server-side validate-back were always in place alongside this.
Hardened — conflicting-plugin protection.
ReCurr and the internal Custom Recurring Billing Platform share the same billing engine. Activating both used to produce a fatal error. ReCurr now detects the conflict and stops with a clear admin notice explaining that one of the two must be deactivated.
Removed — the file-integrity checker.
ReCurr shipped a checker meant to detect modified plugin files by comparing them against a manifest of file hashes. The build script that generated that manifest was retired some releases ago, so the manifest shipped empty and the check never actually verified anything — it only logged a warning each time it ran. Rather than leave a security feature that has never worked, it has been removed. Protection against unlicensed copies continues to come from the signed, licence-gated update service, which is unaffected. The Code Integrity clause in the licence agreement has been reworded to reflect this; the restrictions it places on you are unchanged.
Housekeeping.
Diagnostic output that was being written into page source and the debug log on every checkout has been removed (diagnostics that only run with WP_DEBUG enabled are untouched). Deactivating ReCurr now correctly cancels all of its scheduled background jobs — four were previously left behind, including the daily licence check.
2.7.0 — 15 July 2026 — Subscription lifecycle controls
What it means for you: three new Plus tools that give your customers real options short of cancelling — instant upgrades, fair refunds, and the ability to pause. Every one of them is off by default: install 2.7.0 and nothing changes until you deliberately enable a setting.
New — Immediate pro-rata plan switching (Plus, opt-in).
Until now, a plan change always waited for the next renewal — so an annual subscriber who wanted to upgrade was stranded for up to 12 months. With Immediate plan switching enabled, a quarterly or annual customer upgrading on a card subscription now switches straight away:
- ReCurr credits the unused portion of their current term and charges only the difference.
- The credit values consumed time at the plan’s full monthly rate, so the unearned part of the annual/quarterly discount is forfeited on early exit — the discount is still earned by completing the term. If you offer no discount, the maths reduces to a plain linear pro-rata with nothing forfeited.
- The credit never goes negative (no charge-backs), and a credit larger than the new plan’s price carries forward to reduce the next renewal.
- A consent screen shows the customer their credit, the exact amount to be charged, and their new billing date before anything is charged. A failed charge aborts the switch cleanly — the plan is untouched.
- The PayFast R5 minimum is handled by charging exactly R5 and holding the small balance back as credit, so the customer’s total cost is unchanged to the cent.
- Downgrades and lateral moves still queue to renewal (a separate lever can make downgrades immediate too). Monthly/weekly and manual-EFT customers keep the queued behaviour.
- Optional per-product Plan rank field; by default ReCurr ranks plans by monthly price, so normally-priced stores need no setup at all.
New — Cancellation refunds & retention (Plus, opt-in).
- Pro-rata refunds on cancellation: refund a quarterly/annual customer for the time they haven’t used, using the same fair formula (unused time at the full monthly rate; the free-month benefit is not refundable). The money goes back via the PayFast Refund API with a matching WooCommerce refund record, and access ends within 24 hours. A failed refund aborts the cancellation cleanly, so you can never cancel someone without refunding them. Late in the term, when no refundable value remains, the customer is simply offered a normal end-of-period cancellation.
- Retention save flow: a short reason survey replaces the bare “are you sure?” prompt, then offers a relevant alternative — a change-plan link for price/usage objections, or a support contact for feature and technical problems. Either way the reason is saved and emailed to you, so you can follow up personally and spot patterns.
New — Pause & resume (Plus, opt-in).
Customers can freeze a subscription rather than cancelling it. Nothing is charged while paused, and on resume the next payment date, end date, and licence expiry all shift forward by exactly the paused duration — the term and any discount are completely unchanged. Pauses are capped at 90 days with an automatic resume (adjustable, or removable for unlimited pauses). Pause works on any billing period and any payment method. Admins can pause and resume from the subscription screen too, and a paused customer can always resume even if you later turn the feature off.
Also in this release:
- New Paused subscription status, with filters and badges throughout the customer and admin views.
- New emails: immediate-upgrade confirmation, cancellation refund, cancellation feedback (admin), subscription paused, and subscription resumed.
Do you need to update? Safe for everyone — with all the new settings off, behaviour is identical to 2.4.32. Recommended if you sell quarterly or annual plans, where these tools address the two biggest sources of avoidable churn: customers stuck on the wrong plan, and customers who’d have paused if you’d let them.
2.4.32 — 25 June 2026 (Manual-EFT quarterly/annual invoicing fix)
What it means for you: quarterly and annual manual-EFT subscriptions are no longer invoiced every month.
- Fixed (important): the manual-EFT invoice scheduler generated an invoice for every active manual-EFT subscription on the invoice day each month, without checking the subscription’s billing period — so quarterly and annual subscriptions were invoiced monthly instead of every 3 / 12 months. An invoice is now only generated when the subscription is actually due. Monthly subscriptions are unaffected.
Do you need to update? Essential if you run quarterly or annual manual-EFT subscriptions; recommended for everyone else.
2.4.31 — 24 June 2026 (Trial signup + licence-status fixes)
What it means for you: free trials on annual/quarterly products no longer create a full-price “paid” order, and licence statuses now reflect whether a key is actually in use.
- Fixed (important): a free-trial signup on an annual or quarterly product — or any trial when the store’s Pro-rata toggle was off — was not zeroed to R0.00 in the cart, so the order was created at the full recurring price and the no-card flow then marked it “Paid” even though nothing was charged. Trial price-zeroing now applies to every billing period, regardless of the toggle. Annual/quarterly trials convert at the full term price (pro-rata is monthly-only).
- Changed: newly issued licences now show as Pending until you activate the key on a domain, after which they automatically become Active. Previously a freshly issued, never-installed licence showed as Active. Nothing to do on your side — a Pending status on a brand-new key is normal, not an error.
- Added: the proprietary
LICENSE.txtlicence agreement is now bundled in the plugin zip.
Do you need to update? Strongly recommended for any store offering free trials, especially on quarterly or annual products.
2.4.30 — 12 June 2026 (Pro-rata billing toggle + reliability fixes)
What it means for you: you can now choose how monthly subscriptions bill.
- New — Pro-rata billing toggle. Under Subscriptions → Settings → General there is now a Pro-rata billing (monthly) switch.
- On (default): unchanged — the first payment is pro-rated for the rest of the month and renewals fall on the 1st (South African style).
- Off: anniversary billing — the customer is charged the full price on signup and renews on the same day each month.
- Applies to new monthly sign-ups and trial conversions only. Existing subscriptions keep their current renewal dates. Weekly/quarterly/annual cycles are unaffected. (For manually-created EFT subscriptions, the per-subscription “Pro-rata First Invoice” checkbox now defaults to this store setting and can still be overridden.)
- Fixed (important): PayFast could reject checkout with a “signature does not match” / HTTP 400 error when an optional billing field was left blank (for example, a customer who didn’t enter a phone number). Blank fields were sent to PayFast but excluded from the signed request, so the two signatures no longer matched. Blank fields are now removed before signing, keeping the signed and submitted data identical. Affects card signup, manual-EFT Instant EFT payments, and the card-update flow.
- Fixed: quarterly trial conversions could set an incorrect next-payment date; corrected.
- Fixed: renewal/anniversary dates now clamp to month-end — a subscription dated on the 29th/30th/31st (or 29 Feb) no longer drifts forward (e.g. 31 Jan → 28 Feb, not 3 Mar; 29 Feb → 28 Feb the next year). Applies to monthly, quarterly and annual.
- Fixed: guest subscriptions now reliably receive their lifecycle emails.
- Reliability: renewal, payment-retry and trial-end background jobs now self-heal if a site’s scheduled events are ever lost (migration, cron-reset plugin, database restore).
Do you need to update? Recommended for all stores. Safe to update with no change in behaviour unless you deliberately switch the new toggle off.
2.4.29 — 9 June 2026 (No-card trial conversion fix)
What it means for you: an important fix for free trials. No-card trials were not sending the “add your card to continue” email when the trial ended — so trials quietly lapsed instead of giving the customer a chance to convert. The trial-end conversion email and the one-click “add card” flow now work correctly.
Do you need to update? Strongly recommended for any store offering free trials.
2.4.28 — 9 June 2026 (Guest-checkout licences + renewal expiry-roll)
What it means for you: three reliability fixes around licences and renewals.
- Guest sign-ups now get their licence. Previously, a customer who checked out without creating an account did not receive a licence key, because licence creation required a user account. ReCurr now reads the customer’s name and email from the order, so guest sign-ups receive their key reliably.
- Monthly licences no longer expire while customers are still paying. A monthly subscription’s licence could show as expired roughly two months after sign-up even though billing continued. Every successful renewal (and manual EFT mark-as-paid) now rolls the licence expiry date forward automatically.
- Subscriptions now require a customer account at checkout. Anyone buying a subscription creates an account, so they always have a My Account area to retrieve their licence key and manage their subscription. Guest checkout remains available for non-subscription purchases.
Do you need to update? Recommended for every store — especially if you allow guest checkout.
2.4.27 — 1 June 2026 (Admin subscription page layout fix)
What it means for you: the admin subscription detail page could render too wide on some sites, causing horizontal scrolling. The layout now fits correctly. Admin-side only — no customer impact.
2.4.26 — 30 May 2026 (Update Payment Method — Display Fix)
Why this release matters: When an existing customer updated their saved card from My Account, the page reused the new-signup checkout flow and showed confusing messaging — a “7-Day Free Trial” banner, an “Initial Payment (Pro-rata)” breakdown, and a generic “Pay for order” heading. Customers updating a card could be alarmed by pro-rata/charge wording that didn’t apply to them.
What changed for you:
- The trial-signup banner no longer appears on the card-update (or order confirmation) page.
- The order now shows a clear “Payment method updated” note explaining the small R5 verification charge that is credited back to the customer’s next invoice — instead of a pro-rata breakdown.
- The page heading reads “Update Payment Method”, and the redirect message explains the card-registration step.
- The same wording fixes also tidy the trial-conversion screen.
What did not change: The R5 verification mechanism, payment processing, credit handling, normal new-signup checkout, manual EFT invoices, and genuine pro-rata first payments are all untouched — this is a display-only fix.
Who needs to update: Recommended for everyone offering Update Payment Method to customers.
2.4.20 → 2.4.25 — 28-29 May 2026 (Trial Checkout Polish on Divi & Block Checkout)
Why this release series matters: A run of focused improvements to make the no-card trial checkout look and read correctly across themes — especially Divi sites and the WooCommerce Blocks checkout, where theme styling and React re-rendering were interfering with the trial UI.
What changed for you:
- Simplified trial signup form (2.4.20): the no-card trial checkout now asks for only First name, Last name, Email, and Country. The full billing address is collected later, only when the customer adds their card to continue. Less friction, fewer abandoned signups.
- Repeat-trial guard (2.4.22): customers who have already used their one free trial now see a clear notice on the cart/checkout page immediately (“you’ve already used your free trial — this signup will be billed at the full price”), and the trial UI is suppressed so the price shown is accurate. No more discovering the block only after filling in the form.
- Trial banner readability (2.4.21, 2.4.23-2.4.25): the yellow “No card required” trial banner and the payment-method labels now render with correct colours and contrast on Divi’s dark and light checkout sidebars, where theme styles were previously washing the text out to near-invisible grey. The banner now also sits cleanly below the site navigation.
Who needs to update: Recommended for everyone running trials, and important for any store on a Divi theme or the Blocks checkout.
2.4.16 → 2.4.19 — 27-28 May 2026 (Trial Checkout Reliability)
Why this release series matters: Hardening of the no-card trial checkout so it works reliably on every theme and checkout type, including the classic shortcode checkout that most stores use.
What changed for you:
- The trial signup notice and the “Activate Trial” button text now render correctly on the classic checkout, not just Block Checkout — covering the theme setup most ReCurr stores run.
- Fixed a bug where clicking “Activate Trial” could leave the page spinning without completing the signup. Trial activation now always resolves cleanly, either completing or showing a clear message.
- A theme-agnostic safety net ensures the trial banner and button text appear correctly even on themes that rebuild the checkout after the page loads.
Who needs to update: Everyone running trials — these fixes ensure the trial flow completes reliably regardless of theme.
2.4.13 / 2.4.14 / 2.4.15 — 26-27 May 2026 (No-Card Trials — Major Change)
Note (added in 2.7.11): “trials are now no-card” describes a basket holding a trial subscription on its own, which is the overwhelming majority of trial signups. A trial bought in the same basket as a once-off product has real money to collect at checkout, so it does go through PayFast and does store a card — and from 2.7.11 it is billed and emailed accordingly. See 2.7.11.
Why this release matters: This is the biggest change to how free trials work. Previously, starting a trial required the customer to enter and tokenise a card upfront — which failed on South African bank cards because PayFast rejects the R0 tokenisation below its R5 minimum. Trials are now no-card.
What changed for you:
- Free trials no longer require a card. Customers start their trial instantly — no card, no payment, no PayFast redirect at signup.
- Magic-link conversion: before the trial ends, customers get reminder emails (72h / 48h / 24h before) containing a secure one-click link to add their card and continue. The link auto-logs them in and is single-use.
- No-charge guarantee: if the customer does nothing, the trial simply ends and the subscription is cancelled automatically — no charge is ever made. A short grace period after trial end lets late-converters still reactivate via the link.
- Update Payment Method now uses a R5 verification charge: because PayFast can’t tokenise a card for R0, updating a saved card charges R5 (the PayFast minimum) and immediately credits that R5 back to the customer’s account, applied to their next invoice (net-zero for the customer).
- Checkout re-branding (2.4.14-2.4.15): the gateway on trial-only carts now reads “Activate Trial — no card required” with honest wording, and the trial experience reached full parity on the WooCommerce Blocks checkout.
What did not change: Paid (non-trial) subscriptions, manual EFT, plan switching, and renewals all work exactly as before. The no-card flow applies only to free-trial signups.
Who needs to update: Everyone offering free trials — especially stores whose South African customers were hitting card-tokenisation failures at trial signup. This release fixes that class of problem entirely.
2.4.10 — 14 May 2026 (Admin Notice Cleanup)
Why this release matters: A small admin-side polish fix.
What changed for you:
- The “License activation required” admin notice was rendering twice on every admin page, and the two copies could flicker out of sync after clicking “Check License Status”. It now renders once, cleanly.
Who needs to update: Optional — purely an admin-cosmetic fix with no customer-facing or billing impact.
2.4.9 — 12 May 2026 (Self-Healing Licence Activation)
Why this release matters: Some installs were showing a confusing “Verification API secret key is invalid” error on the licence page — typically where the plugin’s activation step hadn’t run, or where the site’s WordPress security keys had been rotated.
What changed for you:
- The licence page now repairs this condition automatically on the next page load — no support ticket needed.
- Because base ReCurr and ReCurr Pro share this secret, the single fix repairs both plugins’ licence validation at once.
- Healthy installs are unaffected.
Who needs to update: Recommended for anyone who has ever seen a “secret key invalid” message on the licence page.
2.4.8 — 7 May 2026 (Trial Cancellation Fix)
Note (updated for 2.7.11): This fix predates the v2.4.13 move to no-card trials, and its cleanup cron was switched off in that release on the reasoning that a no-card signup has no tokenisation step to abandon. That reasoning holds for a trial-only basket but not for a trial bought alongside a once-off product, which does go to PayFast for a card and can therefore be abandoned there. The cron is running again as of 2.7.11, restricted to signups that were genuinely sent to PayFast; no-card trials remain outside its reach.
Why this release matters: Customers who cancelled at the PayFast page during trial signup were still receiving a misleading “trial activated” email and leaving a phantom subscription in the database that could never charge. This release closes that gap end-to-end.
What changed for you:
- The “trial started” email now defers until PayFast ITN confirms successful card tokenisation. Customers who abandon the PayFast page no longer get a misleading activation email.
- A new hourly cleanup cron (
crb_cleanup_phantom_trials) finds trial subscriptions older than 1 hour with no payment token, cancels them, and sends the customer a clear “trial signup couldn’t be started” email. - Defence-in-depth: the trial-end cron also guards against phantoms in case the cleanup cron missed one.
- New
crb_payment_token_storedaction hook fires from the PayFast ITN handler, available for custom integrations.
Who needs to update: Everyone running trials — this fixes a real customer-experience bug.
2.4.7 — 17 April 2026 (PayFast Partner Compliance)
Why this release matters: Patch release applied to satisfy PayFast’s published integration requirements ahead of partner-programme submission. No functional changes for existing flows.
What changed for you:
- PayFast ITN amount verification — the handler now compares
amount_grossagainst the WooCommerce order total (with a 0.01 tolerance for rand/cents float rounding) and rejects mismatches. R0.00 trial signups and payment-update re-tokenisations are correctly skipped. - PayFast ITN source-IP allowlist hardened — resolved IPs are cached in a 12-hour transient and mirrored to a persistent option (
crb_payfast_itn_ip_fallback). On DNS failure the fallback is used; if no fallback exists the request now fails closed instead of fail-open. - No functional changes for existing flows — token storage, renewals, and trial handling unchanged.
Who needs to update: Recommended for everyone — strengthens payment-notification verification with no behavioural impact for normal traffic.
2.4.6 — 11 April 2026 (Security Release)
Why this release matters: Patch release applying six security-audit recommendations from a routine third-party review. No functional changes.
What changed for you:
- Admin action handlers (status change, note add/delete) now require
manage_woocommercecapability in addition to the nonce check — defence in depth against leaked nonces. - PayFast ITN hardened with source-IP allowlist (DNS-resolved PayFast hostnames, fails open on DNS outage) and server-side validation POST-back to
/eng/query/validate. - Payment tokens are now written with AES-256-GCM (
enc2:prefix). Legacyenc:(CBC) and plain tokens still decrypt for backwards compatibility — no migration needed. - Removed
print_r($_POST)and nonce dumps from AJAX debug logging — debug mode now logs only the subscription ID. - PHPDoc clarifies that the SLM shared API key is not a cryptographic secret (the AUTH_KEY wrapping is cosmetic database-dump defence only).
Who needs to update: Everyone. This is a no-brainer security update.
2.4.5 — 8 April 2026 (PDF Invoice Fix)
Why this release matters: Manual EFT invoice PDFs were rendering with a large white space pushing content to a third page. Customers thought their invoice was incomplete.
What changed for you:
- DOMPDF was interpreting an mPDF-only
htmlpagefootertag as an in-flow block — now collapsed correctly. .crb-payment-box { height: 100% }was stretching bank-details boxes to fill the full page — fixed toheight: autoso boxes size to their content.- Manual EFT invoice PDFs now render as a single tidy page.
Who needs to update: Anyone using manual EFT invoices.
2.4.4 — 1 April 2026 (Manual EFT & Add-Subscription Polish)
Why this release matters: Two small but visible fixes for the manual EFT and admin Add-Subscription flows, plus a Pro-licensing cleanup.
What changed for you:
- Bank details now display correctly on manual EFT invoice PDFs (previously affected by inherited table styles).
- The billing-cycle dropdown in the Add Subscription form now shows only the cycles that are actually configured on the selected product, instead of every possible cycle.
- The “licence activation required” warning no longer shows on the base plugin when ReCurr Pro is active and licensed (Pro licence already authorises base).
2.4.3 — 31 March 2026 (Renewal Reminders + USD Display)
Why this release matters: Two customer-experience additions — proactive renewal reminders so customers aren’t surprised by upcoming charges, and USD pricing on product pages for international visitors.
What changed for you:
- New: Pre-payment renewal reminder email sent 24 hours before each subscription charge. Customers see the upcoming amount and date so they can update their card if needed.
- New: USD equivalent display below ZAR prices on product pages and the cart, using a live API rate (cached daily).
- New: Currency Display settings tab — enable/disable USD display, set a manual rate override, configure cache duration.
- PDF invoice / quote blank white-gap fixed (page-break rules removed that were forcing DOMPDF to push sections to a new page).
Who needs to update: Recommended — renewal reminders meaningfully reduce involuntary churn from expired cards.
2.4.1 — 16 March 2026 (Auto-Updates Launch)
Why this release matters: Before 2.4.1, updating ReCurr meant downloading a zip from your account and uploading it manually. From this release onwards, ReCurr behaves like every other WordPress plugin: new versions appear in Dashboard → Updates and update with one click.
What changed for you:
- One-click updates from the WordPress dashboard, with the standard View version X.Y.Z details link opening a changelog modal.
- Licence-gated downloads — auto-updates require an active licence; lapsed installs continue running their current version but stop receiving updates until renewal.
- Pro licence unlocks all base plugin features — no separate Standard / Plus key needed when running Pro.
- Auto licence issuance on new subscription creation (for licence-product subscriptions).
- Licence page display cleanup when Pro is active.
- Upgrade-path notices — cancel the old subscription when Pro becomes active.
- Pro-specific email instructions on plan switch.
- Purchase link URL on licence page corrected.
Who needs to update: Everyone who wants automatic updates from this point forward. You’ll need to update to 2.4.1 manually one last time (download from My Account → Downloads, upload via Plugins → Add New). After that, every future update is one click.
Version History Summary
Version 2.8.x Series – Variable Subscription Products
PHP 8.1, PayFast’s official library, refunds that go through, and emails from your store (2.8.8):
- (2.8.8) Needs PHP 8.1 or newer (WordPress keeps an older-PHP site on 2.8.7; copied on some other way, ReCurr does not start and shows administrators why). PayFast’s official PHP library (payfast-php-sdk 1.1.6), bundled under ReCurr’s own names, signs every API request (renewal charges, refunds, the card cancellation – sent through WordPress’s HTTP functions with a timeout) and the payment forms in PayFast’s documented order (ReCurr’s own signing kept, and logged, for a passphrase with other characters or none). Fixed: PayFast refused every refund (the request did not say whether PayFast emails the customer) – pro-rata refunds on cancel and credit refunds on cancel now go through; earlier refusals are not repeated. New: a card replaced by Update Card is cancelled at PayFast (never one another subscription uses;
crb_payfast_cancel_replaced_cardkeeps them). ReCurr’s emails come from WooCommerce’s “From” name and address, which customers are asked to write to; PayFast’s merchant confirmation no longer goes to the customer (PayFast’s Email Confirmation setting decides) - (2.8.8) Free trials: a card registered during a no-card trial is charged at the trial’s end; an ended unpaid trial offers Activate Subscription; with pro-rata off, a monthly card trial charges the full month; the reminder names the amount charged; the “Payment received” next date after a pro-rata trial end; the activation’s account credit used once, never leaving under R5.00 to pay, the first payment priced from the subscription’s own price, the page showing the credit it uses
- (2.8.8) Account credit and card updates: no Update Card on Manual EFT, and true credit texts there; a credit refund that fails on cancellation is said (emails and the Account Credit box); “credited to your account”; a card update credited once (a doubled notification, a later status change); a payment confirmed without a card token recorded and held for review; a credit split’s remainder checked
- (2.8.8) Manual EFT: a monthly subscription added on or after the invoice day invoiced for every month; quarterly and annual invoiced on the last invoice day on or before the anniversary, and that date shown; a missed invoice run caught up (a reactivated subscription invoiced for every period not yet invoiced – use Pause to stop billing); the Invoice Day kept to 1-28; Add New offers and prices only the product’s own cycles (a monthly product without the billing-cycle choice no longer offered quarterly or yearly); the PDF’s EFT reference; “Next invoice: … (payment due …)” in customer texts
- (2.8.8) Plan changes and emails: Change Plan no longer offers variable products (a queued one not applied); the time used valued at a variation’s price; the quantity kept; an admin-made order on two schedules refused at payment; the renewal email explains credit and names the next payment; “[Subscription Reactivated]” instead of a second “[New Subscription]”; settings checked before they are saved (an empty retry count saved as 3); the Activity Log wraps and reads consents; log lines all begin “ReCurr”; no start-up lines or early-translation notice under WP_DEBUG
Renewals at the billing period’s price, and PayFast refunds (2.8.7):
- (2.8.7) Fixed: a card subscription on a product with the billing-cycle choice, bought Quarterly or Annually, renewed at the monthly price (the product line kept the monthly price; every renewal is built from it), in every earlier version; the line now carries the chosen period’s price. Existing subscriptions corrected once on update where the figures leave no doubt (card lines set to the Recurring Total; pre-2.7.29 annual/quarterly Recurring Totals set to the price charged; Manual EFT lines shown as the Recurring Total), each with a note; the rest named in a dashboard notice and the log for review; past renewals not re-charged. Fixed: a quantity above one counted in the Recurring Total; a plan change at renewal charged at the new plan’s price; PayFast refunds (pro-rata refund on cancel, account credit refunded on cancel) sent to PayFast’s refund address, with a clear message to the customer and PayFast’s reply in a note and the log if refused; “&” on the cancel window’s button, and every JavaScript message shown as written. New: a renewal whose products differ from the Recurring Total is noted. Monthly subscriptions, products without the cycle choice, Manual EFT invoices, Add New pricing, trial payments (apart from quantity), account credit and the R5.00 minimum unchanged
PayFast payments by customers named O’Brien, two email fixes and the update notice (2.8.6):
- (2.8.6) Fixed: a PayFast payment by a customer whose name or email address contains an apostrophe, a quotation mark or a backslash was taken by PayFast but not recorded (the order stayed Pending payment, the subscription Pending, no card, no emails), in every earlier version; find the missed ones in PayFast Transactions (a completed payment whose order is still Pending payment or Cancelled), refund them and ask the customer to repeat the payment, or Mark as Paid a Manual EFT invoice paid online. Fixed: the “Payment method updated” email states the real next charge (price less account credit; on a free trial, the first payment in full); the first Manual EFT invoice email says “via PayFast Instant EFT or card”; text with an apostrophe is saved as typed and found by search; the update notice clears after one update, from the update after 2.8.6. Changed: log lines under WooCommerce → Status → Logs (source “recurr”), with no card token, merchant key or customer details; the WordPress Plugin Check standard (input, requests, queries, redirects, escaping, translator notes, query notes); the refund reason “Refund issued by ReCurr”. Coming soon: PHP 8.1 or newer required. Charges, notification checks (apart from the fix), renewals, dates and statuses unchanged
Card registration credited once (2.8.5):
- (2.8.5) Fixed: a PayFast notification for a renewal charged to a card registered through Update Card was taken for a second card registration — another R5.00 credit was booked (so each such renewal was charged R5.00 short) and “Payment method updated” was emailed again; each card registration is now completed once, and a later notification for it is recorded in the Activity Log and changes nothing else. Also fixed: a late or repeated notification for a first payment is no longer recorded twice nor re-sends the new-subscription emails. Credits booked before the update stay and are deducted from the next renewal. The R5.00 registration and its single credit, renewals, sign-up, trial conversion, manual invoice payments and the Payment ID unchanged
Payment ID and amounts to the cent (2.8.4):
- (2.8.4) New: PayFast shows the WooCommerce order number as the Payment ID on every subscription payment, renewal and card registration, in the Transactions and Tokenization lists; cards saved before the update keep a blank Payment ID in the Tokenization list, their payments carry it from the next renewal. Fixed: saved-card charges (renewals, retries, plan changes, trial-end charges) and refunds were sent one cent short on about one amount in twenty-two (for example R72.60); now exact. Payment recording, other fields sent to PayFast, dates, statuses, emails and ReCurr Pro’s splits unchanged
Card kept on trial activation (2.8.3):
- (2.8.3) Fixed: a subscription activated from a free trial without a card (through the activation link) did not keep the card — its first renewal failed with “No payment token found for renewal”; the card is now saved. Fixed: a card updated while a subscription was on hold was replaced by the previous card on reactivation; the new card is now kept. The activation and card-update orders now record the card reference. Subscriptions activated before the update: the customer uses Update Card. Sign-up, other renewals, amounts, dates and emails unchanged
Change next payment date (2.8.2):
- (2.8.2) New: change a subscription’s next payment date from its screen (Change next payment date, under Next Payment) — any date from today to one billing cycle ahead; the date only, nothing charged; a later date moves a licence’s expiry on, an earlier one never shortens it; recorded in Notes and the Activity Log, no customer email; not offered while paused, in trial, in payment retry or with an unpaid invoice. Every licence, Standard and Plus. Customers cannot change their own date
Licence fix (2.8.1):
- (2.8.1) Fixed: licence activation and the daily licence check refused with “Verification API secret key is invalid” on the very few sites (about 1 in 250) whose stored API key read back wrong — after a WordPress security-key change, or from first activation. ReCurr now checks the key it sends and repairs it by itself; ReCurr Pro’s licence checks are repaired too. Licence keys, statuses and billing unchanged
Variable subscription products and Bill Every (2.8.0):
- (2.8.0) New setting Variable subscription products (Subscriptions → Settings → General, off by default; ReCurr Plus and above): each option of a variable product is sold as a subscription on its own terms — billing period and interval, trial, annual or quarterly pricing — with the parent’s settings as defaults; the product page shows a price range with each option’s period; the subscription, every renewal order and My Account name the option and the attributes chosen; Subscriptions → Add New offers the options. Moving a subscription to another option is not available yet. With the setting off, a variable product marked as a subscription — one converted from a simple subscription product included — can no longer be bought, where it used to be sold on the parent’s price and period
- (2.8.0) Bill Every on Subscriptions → Add New (every plan): a manual EFT subscription invoiced once every 1 to 12 billing periods, each invoice one period’s amount
- (2.8.0) Fixed: Add New’s critical error on a product with no price (it left an Active subscription with no product on every attempt); the error where an annual or quarterly product with its discount ticked and no price is shown; a quarterly or annual first invoice labelled “(Pro-rata first invoice)”; the cart’s pro-rata box on a combined first payment, which named only the rest of this month and now names next month too (“plus next month’s fee”, “+ 1 month”, headed “Pro-rata Billing”)
- (2.8.0, prepared as 2.7.30) Manual EFT subscriptions added on Add New: a monthly one added on 29-31 January, 31 March, 31 May, 31 August or 31 October no longer skips a month, and a pro-rata first invoice sent straight away is no longer charged a second time by the first scheduled invoice
Version 2.7.x Series – Lifecycle Controls, Licensing & Mixed Baskets
Major Additions (2.7.0):
- Immediate pro-rata plan switching for quarterly/annual upgrades (Plus, opt-in)
- Pro-rata refunds on cancellation via the PayFast Refund API, plus a retention save flow (Plus, opt-in)
- Pause & resume with a 90-day cap and auto-resume, on any billing period and payment method (Plus, opt-in)
- New Paused status, and five new emails covering the above
Maintenance & Licensing (2.7.1 → 2.7.6):
- Full code audit: checkout failures now surface instead of hanging; PayFast ITN source-IP check hardened; the never-functional file-integrity checker removed
- Manual-EFT date accuracy — invoices dated from the due date rather than the raise date, billing interval honoured, month-end overflow clamped
- Licence correctness — expiry stated honestly, a grace period added on top of the billing cycle, replaced keys reported as replaced, downgrades actually applied, and the activation/update domain mismatch that silently blocked updates
- First-payment amounts recorded and emailed at the amount actually paid; auto-issued licence keys actually sent; licence email wording built from your own site rather than a hardcoded vendor
Mixed Baskets — subscription + once-off product (2.7.7 → 2.7.11):
- A trial alongside a once-off product no longer completes the order without taking payment
- The chosen billing cycle, the trial settings, and the subscription’s own line total are all read from the subscription line rather than whichever line happened to come first
- Once-off products are no longer written into the subscription and re-charged on every renewal
- The block-based checkout no longer promises “no card required” above a total it is about to charge
- One order can only ever own one subscription — paying a pending order twice no longer duplicates it
- (2.7.11) Trials with a card on file are charged at trial end, converted, and emailed accordingly, instead of stalling on hold forever
Trial configuration guard (2.7.12):
- A free trial may no longer be configured longer than the billing period it precedes — refused on save with an explanatory notice, and kept off the no-card checkout path
- Products saved before the guard existed are billed on their normal term rather than given the over-long trial
- Three never-read trial options dropped from the installer
Lifecycle dates (2.7.14 → 2.7.15):
- (2.7.14) A pause that ended without being resumed left its start date behind, and the next pause inherited it — resuming then pushed every forward date, and the licence expiry, by the whole span since the abandoned pause. Cleared on every exit now, and a fresh pause always stamps its own date
- (2.7.15) A cancellation recorded the next payment date as the end of access even when that date had already passed, which in dunning it always has — subscriptions cancelled after a failed payment were given an end date before the cancellation, and emailed it. Now clamped forward, never backwards
- (2.7.15) Reactivating a cancelled or expired subscription clears the end date instead of carrying it forward
ReCurr Pro groundwork (2.7.16):
- (2.7.16) Two extension points added to the renewal charge, which previously had none at all — the initial checkout has had one for a long time. Nothing in base ReCurr registers on them and no behaviour changes. ReCurr Pro 3.0.11 requires this version: it uses them to attach affiliate split instructions to renewal charges, which is what makes recurring affiliate commissions payable for the first time
Silent failures (2.7.17):
- (2.7.17) A licence that stopped validating stopped charging every subscriber, silently — the renewal job stayed scheduled with nothing behind it. A store that has been licensed now gets a 30-day grace window in which billing continues, with an email when the licence fails, when a week is left, and if billing stops. During the window ReCurr runs exactly as it does when licensed; a store that has never activated a licence gets no window
- (2.7.17) Activating ReCurr before entering a licence key created none of its database tables, roles, settings or scheduled jobs — setup only ran once the licence validated. Setup now runs on activation regardless
- (2.7.17) A stored card that could not be decrypted was reported as a customer who never had one, so regenerating the WordPress security keys would have sent the entire subscriber base into failed-payment chasing for cards that were never declined. Now recorded distinctly, emailed to the administrator, and the renewal is held rather than failed — with the whole run stopped if several fail in a row
- (2.7.17) Every load of the Update Payment Method link created another R5.00 order — reachable by the back button, a double-click, or a link-preview fetch. An existing pending order is now reopened instead of duplicated; orphans already created are left alone
Cut-over to the ReCurr platform (2.7.18 → 2.7.19):
- (2.7.18) ReCurr and the ReCurr platform at recurr.co.za cannot see each other, and the platform does not deactivate the plugin when a store migrates — so an engine left running beside it charges the same cards on the same dates, silently. ReCurr now stops its renewal run, retry run, trial-end conversion and manual EFT invoicing once a store’s cut-over is confirmed, with nothing cancelled and every date, trial and stored card left as it was. Keyed on the cut-over rather than on the connection, because the platform bills nobody for the four steps in between. An administrator can confirm the platform no longer bills the store and resume billing here in one click
- (2.7.19) The same guard extended to everything a customer can reach on their own: updating a card, converting a trial, switching plans and cancelling with a refund; the three trial jobs that schedule themselves rather than going through the renewal scheduler; and the stored-card charge underneath all of them. Each refusal tells the customer that billing has moved and that nothing has been charged
- (2.7.19) A card-update or trial-conversion order-pay page — an ordinary WooCommerce page, still live in browser history and in mail already sent — is made unpayable by any payment method rather than only by ReCurr’s, because the standard PayFast gateway offers itself without looking at the order and would otherwise have taken the payment ReCurr had just refused. Manual EFT invoices stay payable: they are a bill for a period already served
- (2.7.19) Subscription pages become read-only rather than disappearing, and stand aside entirely when the ReCurr Connector says it has taken them over. Cancelling is never refused and pending credit is always refunded — the guard stops new billing starting, it does not cancel debts owed to you or trap money owed back to your customer
Trial conversion (2.7.20):
- (2.7.20) A trial converted in the last seven days of a month — or on a plan whose part-month fell under PayFast’s R5.00 minimum — was charged for the rest of that month plus the whole of the next, correctly and with the combination disclosed on the confirmation page, and then had its next payment set to the 1st of the following month: the month that charge had just bought. The second charge billed it twice. The combined amount was always right and does not change; only the date was wrong, and it is now the 1st of the month after next. Conversions from the 1st to the 24th, ordinary pro-rata sign-ups, and trials ending with a card already on file were never affected. Dates already stored are not repaired — check any trial converted in the last week of a month
Declined cards (2.7.23):
- (2.7.23) A renewal charge the bank declined was recorded as paid — order marked paid, payment listed in Payment History with a blank transaction ID, next payment date advanced, licence extended, “Payment received” emailed — with no retry and no failed-payment email. PayFast reports a decline inside the same outer “success” it uses for a charged card, and only the outer part was read. A charge now counts as paid only when PayFast confirms it and returns a transaction ID; everything else goes down the ordinary failed-payment path, with PayFast’s reason logged and its update-card link in the customer’s email. Payments already recorded this way are not silently changed — the new Subscriptions → Unpaid renewals screen lists them with the total never taken, and retries the stored card or starts reminders at the press of a button, keeping the billing anniversary and the licence expiry where a real payment would have put them
- (2.7.23) The refund API was read the same way and is now checked properly. The PayFast passphrase no longer appears in the debug log
Card updates and account credit (2.7.24 – 2.7.27):
- (2.7.24) Update Card in My Account now sends the customer to PayFast’s own “Update card details” page for the token already on file — no R5.00 order, no charge, no credit to book, and the token is unchanged. The R5.00 re-tokenisation remains only for a subscription with no usable token (none stored, unreadable, or refused by PayFast) or one on hold, where a completed charge is what proves the new card and reactivates it. A card update the customer abandoned no longer puts the subscription on hold
- (2.7.25) PayFast’s card-update page verifies the new card with a zero-amount 3D Secure check, and some South African banks refuse it — an FNB debit card was refused there while a Capitec card went through on the same subscription. The customer is now offered the R5.00 registration as a way through, as a link on their subscription page when they come back from PayFast, stating the amount and the credit. A real charge passes 3D Secure where a zero-amount check does not
- (2.7.26) The R5.00 card registration is the default route for Update Card again, for every customer. PayFast’s zero-amount check was refused by FNB, ABSA and Capitec cards, and the 2.7.25 alternative was only shown to a customer who came back through PayFast’s return button. PayFast’s free page is now an opt-in (
crb_payfast_hosted_card_update_availablereturning true). The failed-payment email links to the subscription page in My Account instead of PayFast’s card link. New filtercrb_card_registration_amountfor a store whose PayFast Credit Card minimum is above R5.00 — PayFast otherwise refuses the registration with “400 — the subscription amount is outside the limits” - (2.7.27) New Account Credit box under Notes on the admin subscription screen: the available balance and every ledger entry (date, amount, reason, status, PayFast transaction, the order it was applied to). Read-only; billing is unchanged
One order, one renewal schedule (2.7.28):
- (2.7.28) Every subscription product in an order goes onto one subscription, which renews on the schedule of the first subscription product added to the cart — so a second product on a different schedule was billed on that schedule at its own full price: an annual product after a monthly one was charged its annual price every month, and a monthly one after an annual one once a year. A second subscription product on a different renewal schedule (period and interval together; a toggle product on the cycle chosen) is now refused at add-to-cart with a message, and a cart already holding two schedules is refused on the cart page and at both checkouts until one is removed. Same-schedule products in one order, a once-off product beside a subscription, single-subscription orders and everything at renewal are unchanged. Subscriptions already created from such a cart are not changed — check any subscription that carries more than one product line
One price per billing period (2.7.29):
- (2.7.29) An annual or quarterly product’s billing period was priced by one calculation on the product page, cart and card renewals, and by others for the amount a subscription records (which trial-end charges and manual EFT invoices take), the card-less trial conversion and plan switching — so a trial on an annual product with no discount converted at twelve times its page price, a switch to an annual plan at 10 % off was stored at R11 664 instead of R1 080, and a card-less conversion ignored the discount. Every path now asks one rule: where the page ignored a Custom Annual Price, a quarterly discount or a Custom Quarterly Price, the setting now sets the page price too; otherwise the page’s price wins. Credit on a discounted annual plan is valued at its monthly price; a plan change to a cycle the plan does not offer is refused. Monthly and billing-cycle-toggle products are unchanged. Existing subscriptions and queued switches are not changed — check trial and manual EFT subscriptions on annual and quarterly products
Invoice payments (2.7.22):
- (2.7.22) A manual EFT invoice paid online by the customer (PayFast Instant EFT) marked the invoice paid and wrote its own payment record, but never ran the renewal step — so the licence was not extended, the last-payment date did not move, the overdue flag was not cleared, an on-hold subscription was not woken, and no renewal email was sent. Because the payment record was written, the subscription’s Payment History looked correct while the licence ran down. All settlement paths now share one step. Licences already missed are not repaired — a key still reading
SUB-<id>rather thanCONVERT-<id>in its transaction field has never been extended - (2.7.22) A customer paying online and an administrator pressing Mark as Paid on the same invoice each recorded a payment and each sent a renewal email. The first one through now wins. The Mark as Paid button itself was never affected and always ran the full renewal
Manual EFT invoicing (2.7.21):
- (2.7.21) WooCommerce’s “Retain pending orders” privacy setting was moving unpaid invoices to the trash. A manual EFT invoice must stay in the pending status to keep its Pay Now link alive, which is exactly what that sweep deletes — so the invoice, the customer’s payment link and your own Invoices → Unpaid list all disappeared together, while the activity log still recorded the invoice as generated. ReCurr’s invoices are now exempt from the pending, failed and cancelled sweeps. The setting is blank by default, so a store that never set it was never affected. Invoices already deleted are not recovered — anything trashed within 30 days can still be restored from the WordPress trash
- (2.7.21) Nothing ever chased an unpaid invoice. The next payment date advances the moment an invoice is raised, and manual EFT is excluded from the renewal, retry and reminder runs, so a customer who never paid stayed active indefinitely with nobody told. A daily check now emails the customer on the due date, a week later and a week after that, and sends the administrator a summary. Nothing is suspended or cancelled automatically — that stays a commercial decision
- (2.7.21) No screen showed that money was owed: the Details panel shows the already-advanced next payment date, and Payment History only lists actual payments. The subscription screen now lists every unpaid invoice with its amount and age, in red once past due
- (2.7.21) A failed invoice email was discarded silently, so an invoice that never reached the customer looked identical to one that did. Now recorded on the invoice, shown as “Not sent” beside the Resend button, and written to the activity log
- (2.7.21) Licence keys past their expiry date never expired. Expiry relied on a daily task Software License Manager schedules once at activation and never re-arms, so any cron reset or database restore stopped all expiry permanently and silently. ReCurr now does it itself and restores the missing task; a key expired this way is revived, domain included, the moment its subscription is paid. The first run may clear a backlog in one pass
- (2.7.21) New Payment Terms setting (Settings → Manual EFT, default 7 days) — the due date printed on the invoice and the point overdue reminders count from, so the two cannot drift apart
- (2.7.21) On stores not using High-Performance Order Storage, the query that links a guest’s past orders to a new account was not filtering by subscription at all, and could attach orders that were never part of the subscription being linked
Version 2.4.x Series – No-Card Trials, Auto-Updates, Security & Compliance
Major Additions (2.4.1 → 2.4.8):
- Auto-update system via WordPress dashboard (licence-gated)
- Pre-payment renewal reminder emails (24h before charge)
- USD equivalent display on product pages and cart
- Pro tier unlocks all base features without separate key
- PayFast partner compliance (ITN amount verification + IP allowlist hardening)
- AES-256-GCM payment-token encryption
- Phantom-trial cleanup cron + deferred trial-started email
Major Additions (2.4.9 → 2.4.26):
- No-card free trials (Model B) — trials start with no card; magic-link conversion via reminder emails; no charge if the customer does nothing
- R5 verification-charge flow for Update Payment Method (credited back to the customer), working around the PayFast R5 minimum
- Simplified 4-field trial signup form; one-trial-per-customer guard with clear messaging
- Full trial + pro-rata parity on WooCommerce Blocks checkout and Divi themes
- Trial banner / payment-label readability fixes on Divi dark & light sidebars
- Update Payment Method display fix (accurate “payment method updated” wording)
- Self-healing licence activation; duplicate admin-notice cleanup
Version 2.x Series – Advanced Billing & Licence Tiers
Major Additions:
- Two-tier licence system (Standard, Plus) with feature gating
- Plan switching – customers upgrade or downgrade at next renewal
- Plan groups for organising switchable products
- Manual invoice Pay Now via PayFast (Instant EFT or card)
- Update Payment Details – customers re-tokenise their card from My Account
- WooCommerce Blocks checkout support
- Trial period support with pro-rata first charge
Improvements:
- CRB and ReCurr codebase parity maintained
- Improved Mark as Paid handler with email confirmations
- Enhanced gateway display for invoice payments
- Better trial cancellation messaging
Version 1.2.x Series – Manual EFT & Refinements
Major Addition:
- Manual EFT subscription creation for corporate clients
- Admin can create subscriptions without credit cards
- Automatic invoice generation and email delivery
- Bank details configuration and display
Improvements:
- Date calculation accuracy enhancements
- Amount display corrections
- PDF invoice attachment reliability
- Enhanced admin interface
Version 1.1.x Series – Pro-rata Intelligence
Major Addition:
- Pro-rata extension logic for end-of-month signups
- Smart billing to meet PayFast minimum amounts
- Combined billing (current + next month) when needed
- Enhanced email templates
Improvements:
- Better checkout notices and explanations
- Extension metadata tracking
- Improved date calculation logic
Version 1.0.x Series – Initial Release
Core Features:
- Monthly, quarterly, weekly, and annual billing cycles
- Pro-rata billing for monthly subscriptions (SA billing cycle)
- PayFast integration with tokenisation
- Automated recurring payments
- Admin subscription dashboard
- Customer My Account integration
- Email notifications
Stay Informed About New Releases
ReCurr is in active development. New releases are announced via:
- In-dashboard updates — when a new version is available, you’ll see it under Dashboard → Updates in WordPress (auto-update support added in 2.4.1)
- Email — release announcements go out to the address on your CyberDummies account
- Support page — recent releases are listed at cyberdummies.co.za/recurr
Have a feature request? Email us at [email protected] — customer feedback drives what gets built next.
Note on analytics & reporting: MRR, churn, and customer LTV reporting are now available in ReCurr Pro (R349/mo tier). The base ReCurr plugin focuses on subscription billing; cross-cutting business analytics live in Pro.
Security & Compliance
Data Security:
- No credit card data stored on your server
- PayFast tokenisation handles sensitive data
- PCI-compliant payment processing
- Secure HTTPS required
WordPress Security:
- Nonce verification on all forms
- Data sanitisation and validation
- SQL injection prevention
- XSS protection
- Permission checks on all admin actions
PayFast Security:
- Passphrase validation required
- ITN signature verification
- IP address verification
- Secure API communication
Quick Troubleshooting
Payments Not Processing:
- Verify PayFast credentials (Merchant ID, Key, Passphrase)
- Check ITN URL is set correctly in PayFast dashboard
- Ensure SSL certificate is valid
- Review WooCommerce logs for errors
Subscriptions Not Creating:
- Confirm “Enable Subscription Billing” is checked on product
- Verify billing period is configured
- Check PayFast gateway is enabled
- Test with sandbox mode first
Emails Not Sending:
- Install SMTP plugin (recommended: MailerSend)
- Test WooCommerce email settings
- Check spam/junk folders
- Verify hosting provider allows email sending
Plus Features Not Showing:
- Verify your licence key starts with
RECPLUS- - Re-activate your licence key in ReCurr > Licence settings
- Check the Licence page shows your correct plan tier
- Contact support if your tier is not detected correctly
Built for South Africa
ReCurr is designed specifically for South African businesses:
- PayFast Integration – South Africa’s leading payment gateway
- SA Billing Cycle – 25th invoice, 1st payment (monthly subscriptions)
- Rand (R) Currency – All examples and defaults in ZAR
- Local Support – South African support team (SAST timezone)
- Local Business Practices – Manual EFT for corporate clients
- Compliance – Designed for SA business requirements
Contact & Licensing
Licence Information
- Licence Type: Proprietary — see LICENSE.txt
- Usage: Licensed for use on your own sites while your licence is active; redistribution and resale are not permitted (see LICENSE.txt for full terms)
- Updates: Included with active licence
- Support: Included with active licence
Purchase & Renewals
- Purchase: https://cyberdummies.co.za/recurr/
- Licence Activation: Automatic upon purchase
- Renewal: Monthly subscription for continued updates and support
- Upgrade: Purchase a higher tier to unlock additional features
Support
- Email: [email protected]
- Hours: Monday – Thursday, 9:00 AM – 4:00 PM SAST; Friday, 9:00 AM – 12:00 PM SAST
- Response Time: Within 24 business hours (usually much sooner)
Thank you for choosing ReCurr!
We’re committed to providing the best subscription billing solution for South African WooCommerce stores. Your feedback helps us improve – please don’t hesitate to reach out with suggestions or questions.
ReCurr – Recurring Billing Made Easy for South Africa
Version 2.8.8 | Built by CyberDummies | Powered by PayFast
Last Updated: 20 October 2026