PS PrestaShop Intermediate

DataFirefly Subscriptions — Complete Guide (PrestaShop 8 & 9)

Installation, Stripe configuration, subscription plans, renewal cron, dunning and customer area — the complete guide to the subscription module for PrestaShop 8 and 9.

Updated Module version 2.1.0

Overview

DataFirefly Subscriptions turns your PrestaShop 8 or 9 store into a recurring revenue machine. The module is built on a card-on-file architecture: the customer pays once at checkout through a native payment option, their card is securely saved at Stripe, then a daily cron automatically charges the card at each due date and creates a real PrestaShop order for the exact amount, shipping included.

Key architectural points:

  • A single billing engine — no Subscription object at Stripe, everything is driven by your store. Double charges are structurally impossible.
  • Exact amounts — every renewal rebuilds a real cart and computes the total through the PrestaShop pricing engine (discounts, taxes, shipping).
  • 3DS/SCA handled — strong authentication is handled at the initial payment; renewals use the SCA-compliant off-session mechanism.
  • No banking data on PrestaShop — PCI-DSS compliance is carried by Stripe.

Installation

  1. Download the module ZIP from your DataFirefly customer account.
  2. In your PrestaShop back office: Modules → Module Manager → Upload a module, then select the ZIP.
  3. The module automatically creates its tables, its admin tabs (Subscriptions, Plans, Logs, Dashboard) and registers its hooks.
  4. Click Configure to open the configuration page.

Requirements: PrestaShop 8.0 to 9.x, PHP 8.0 to 8.4, a Stripe account (free), and the ability to create a cron job with your host. No Composer dependency is required.

Upgrading from a 1.x version: simply install the new ZIP on top. Migration scripts run automatically and, among other things, register the currency/country/carrier restrictions required for the payment option to appear at checkout.

Stripe configuration

API keys

In the module configuration, enter your Stripe keys. The module handles two separate key sets:

  • Test mode: publishable key pk_test_... and secret key sk_test_... — to validate the full journey without real charges (test card 4242 4242 4242 4242).
  • Live mode: publishable key pk_live_... and secret key sk_live_... — for production.

You will find these keys in your Stripe dashboard: Developers → API keys. Switch between test and live with the module’s Mode toggle.

Webhook

The webhook only handles exceptional events (billing is driven by the cron, not by Stripe). In your Stripe dashboard: Developers → Webhooks → Add an endpoint, using the URL shown in the module configuration (of the form https://yourstore.com/module/dfsubscription/webhook), and subscribe to these three events:

  • payment_method.detached — card deleted at Stripe: the subscription switches to “payment failed” so you are warned before the due date.
  • charge.dispute.created — dispute (chargeback): logged on the related subscription.
  • charge.refunded — refund: logged on the related subscription.

Then copy the signing secret (whsec_...) provided by Stripe into the corresponding configuration field.

Important: in live mode, unsigned webhook requests are rejected. Make sure the signing secret is set before going to production.

Cron configuration

The cron is the renewal engine: every day it detects due subscriptions, charges the saved cards and creates the orders. The token-secured URL is shown in the module configuration and dashboard, of the form:

https://yourstore.com/module/dfsubscription/cron?token=YOUR_TOKEN

Create a daily cron job with your host (cPanel, Plesk, crontab) that calls this URL. Crontab example for a run every day at 6:00 AM:

0 6 * * * curl -s "https://yourstore.com/module/dfsubscription/cron?token=YOUR_TOKEN" > /dev/null 2>&1

One daily run is enough: the module processes all due subscriptions in a single pass, with an extended time limit for large volumes. You can also use an external service such as cron-job.org if your host does not offer cron jobs.

Creating subscription plans

Plans are managed directly from the back-office product page: Catalog → Products → your product → Modules tab / DataFirefly Subscriptions. For each plan, define:

  • Billing frequency — weekly, biweekly, monthly, quarterly, semiannual or annual.
  • Delivery frequency — same as billing, weekly, biweekly or monthly. Example: monthly billing + weekly delivery = weekly box with monthly payment.
  • Discount (%) — the reduction granted to subscribers versus the one-time price. It is displayed on the product page and also applied to every renewal.
  • Minimum commitment — number of cycles before cancellation becomes possible (0 = free cancellation).
  • Maximum cycles — for limited-duration subscriptions (0 = unlimited).
  • Trial days — trial period before the first billing.

A product can offer several plans (e.g. monthly -10% and annual -20%): the customer chooses in the “Subscribe and save” block on the product page.

Customer journey

Product page

A collapsible block presents the available plans with their discounted prices. The customer selects a plan (the selection is stored in database, reliable even across devices), then adds to cart normally.

Checkout and payment

At the payment step, the option “Pay by card and activate my subscription” appears if the cart only contains subscription products and the customer is logged in. The secure Stripe card form is displayed directly in the page:

  1. The customer enters their card; 3D Secure triggers automatically if their bank requires it.
  2. The payment covers the exact cart total, shipping included.
  3. The card is saved at Stripe for future cycles (card on file, with SCA-compliant consent).
  4. The module re-verifies the payment status and amount server-side before creating the order — the browser is never trusted.

Mixed carts (subscription + regular product) are blocked on both client and server side: the customer is asked to check out separately. This is what guarantees renewal amounts always stay consistent.

Renewals

On each cron run, for every subscription that is due:

  1. The module rebuilds a real PrestaShop cart: product, combination, original address and carrier.
  2. The plan discount is applied through a single-use automatic cart rule.
  3. The exact total is computed by the native pricing engine — taxes and shipping included if the “Shipping on renewals” option is enabled (it is by default).
  4. The saved card is charged off-session for precisely that amount.
  5. A standard PrestaShop order is created, with the order status of your choice (configurable, e.g. a dedicated “Renewal” status).
  6. The customer receives the renewal confirmation email; the event is logged.

Every renewal order is visible in Orders like any sale, with its associated Stripe transaction — your accounting exports and stock management keep working unchanged.

Dunning: handling payment failures

When a renewal charge fails (expired card, limit, bank refusal):

  1. The subscription switches to “payment failed” status and the customer immediately receives a reminder email inviting them to update their card.
  2. The cron automatically retries the payment — by default 3 attempts every 3 days, both values being configurable.
  3. After the configured number of consecutive failures, the subscription is automatically cancelled and the customer is informed.

Each attempt and its result are logged on the subscription. In practice, dunning recovers 50 to 70% of payments that would otherwise have been lost.

The “My Subscriptions” customer area

Accessible from the customer account, this area lists subscriptions with their status, next billing and delivery dates. Depending on your settings, the customer can:

  • Pause / resume — dates are recomputed on resume.
  • Skip the next cycle — billing and delivery are postponed together by one period.
  • Cancel — freely, or only after the plan’s minimum commitment. On cancellation, the saved card is automatically detached at Stripe and a confirmation email is sent.

Every action requires a confirmation and follows the POST-redirect-GET pattern: no double submission possible, native PrestaShop confirmation messages.

Back office

  • Dashboard — MRR, active subscriptions, churn rate, failed payments, cron and webhook URLs ready to copy.
  • Subscriptions — list filterable by status, frequency and customer; detailed view with the history of generated orders and logs, and direct links to the order and the customer file.
  • Plans — overview of all existing plans (creation happens from the product page).
  • Logs — all timestamped events: creations, renewals, failures, retries, pauses, cancellations, received webhooks.

Technical FAQ and troubleshooting

The payment option does not appear at checkout

  • Check that the cart only contains products with a selected plan and that the customer is logged in.
  • Check that the Stripe keys for the active mode are set.
  • If you just migrated from a 1.x version: reinstall the module or re-run the upgrade — the currency/country/carrier restrictions are added by the 2.x migration scripts and are required for the option to appear.

Renewals are not triggering

  • Check that the cron job is scheduled and that its URL contains the right token (test the URL in a browser: it must respond with a JSON summary).
  • Check the Logs tab: every cron run leaves a trace there.

A 3DS payment stays “pending”

If the customer closes the page during 3D Secure authentication, no charge happens and no order is created. They can simply order again; the previous payment will expire by itself at Stripe.

How do I test the full journey?

  1. Switch the module to test mode and enter the pk_test/sk_test keys.
  2. Create a plan on a product, place an order with card 4242 4242 4242 4242 (or 4000 0027 6000 3184 to force a 3DS challenge).
  3. In the database, move the subscription’s next_billing_date to yesterday, then call the cron URL: a renewal order must appear.
  4. To test dunning, use card 4000 0000 0000 0341 (fails on off-session charge).

Need help? Open a ticket from your DataFirefly customer account — answered within 24 business hours, in English or French.

Was this page helpful?

Still stuck? Contact support