Recurring billing
OSubscribe's billing engine is gateway-agnostic. The OSub_Charge_Worker enqueues charges on the osub/cron/charge_dispatch schedule (every 5 minutes) and a per-gateway adapter executes them off-session.
Charge lifecycle
Each renewal walks the lifecycle in wp_osub_charges:
- Scheduled -
scheduled_atset,status='scheduled' - Attempted -
attempted_atset, gateway called off-session with an idempotency key - Outcome - one of
succeeded,failed,retrying,requires_action(3DS/SCA) - Order - on success, a corresponding Woo order is created and the
order_idcolumn is filled
Idempotent retries
Every charge attempt carries an idempotency key. If the same charge is dispatched twice (cron racing, manual retry), the gateway-side dedupe returns the prior result without double-charging.
Subscription product modes
Seven modes from OSub_Product_Meta::MODES:
pure_subscription- only sold as a subscriptionsubscribe_and_save- one-time OR subscription with discountsignup_plus_recurring- one-time fee + recurringtrial_to_paid- N-day trial, then paidtiered- multiple plans on one productbundle- multiple products, one billingmix_and_match- pick N from a list
Trial handling
When the product is trial_to_paid, OSub_Products sets status='trial' and trial_ends_at to the trial end. The first next_charge_at is the trial end date; the charge runs through the same worker.
Proration
OSub_Proration handles mid-cycle upgrades and frequency changes by computing the unused portion of the current period and applying a credit (or invoicing the delta).
SCA / 3DS challenge resume
When Stripe returns requires_action, OSub_Stripe_SCA records the next-action URL and emits a magic link to the customer. They confirm the 3DS challenge on a hosted Stripe.js v3 page and the worker resumes the charge automatically.
Pre-renewal emails
OSub_Pre_Renewal runs on the daily metrics cron and notifies subscribers a configurable number of days before their next charge. Useful for annual renewals.

