Investigate the payment, subscription and access separately
A paid invoice and an inactive account do not always mean that a webhook failed. The invoice may cover an old period, a different subscription, a one-off item or a balance adjustment. The subscription may have been cancelled after payment. Your application may also use inactive as a local access label that does not correspond to a gateway status.
Start by identifying what each record actually represents. Establish whether the payment or paid invoice entitles this customer workspace to the current service period under the agreed policy. Then investigate the path from billing evidence to product access. Do not solve the discrepancy by collecting another payment or changing every status to active.
The practical output below is a payment-to-access investigation checklist. It preserves the evidence for a justified recovery and covers cases where activation would be wrong. It is an operational procedure to adapt and approve for your product, not permission to override a gateway or change a customer contract.
Step 1: confirm the relevant invoice and payment evidence
Use an authenticated provider dashboard or the verified server-side readback for the actual merchant integration. A customer screenshot or browser success redirect is a useful report, not authoritative proof that your account received the relevant payment. Locate the invoice and its associated payment, credit or settlement information.
Record the merchant account, live/test environment, customer and workspace mapping, invoice/subscription identifiers, currency, amount, billing reason and covered service period. Check whether the invoice is fully paid, partly paid, void or otherwise unresolved. A zero-amount or credit-settled invoice can be paid without a fresh card charge; interpret the record under the product's agreed entitlement rules.
For an eligible Stripe integration, the subscription documentation distinguishes invoice activity from payment and subscription events. Its provisioning example uses a paid invoice with an active subscription. A standalone successful PaymentIntent is not proof that this current subscription period should be activated. Stripe subscription webhooks
If an invoice belongs to another customer, period or subscription, stop the activation path and investigate the mapping. If the provider result remains unknown, record it as unresolved rather than assuming success or failure.
Step 2: read the current subscription lifecycle
Compare the provider subscription state with the application state and their timestamps. Determine why the application says inactive: expired entitlement, unpaid renewal, cancellation, administrative suspension, paused access, provisioning failure or an unrelated access restriction. Retain that reason rather than overwriting it during investigation.
Read current state before replaying old events. A customer may have paid last month's invoice and then cancelled. Replaying the old payment should not reverse the later cancellation. Conversely, the provider can be in the correct eligible state while the local record is stale. Fix the layer that is wrong, and keep the distinction visible in the incident notes.
Check the actual paid period and plan entitlement, not just a generic active flag. If the product intentionally offers an approved grace period or credit arrangement, record that decision separately from confirmed payment. The policy should identify which condition permits which access and for how long.
Step 3: inspect notification receipt and processing
Trace the relevant provider event through receipt, verification, durable storage, worker execution and the final database transaction. A successful HTTP acknowledgement does not prove that the entitlement update finished. A log entry named received does not establish that the handler committed its changes.
Stripe's webhook guidance requires signature verification and describes duplicate and unordered delivery. Use the raw request body for the documented verification procedure, and respond promptly after safely accepting the work. Persist or durably enqueue the verified event before acknowledging it so a crash does not lose the recovery path. Stripe webhook guidance
Keep separate received, verified, pending, processing, completed and failed observations. The precise labels are product design choices. Record the error and retry/recovery history. If a worker claimed the event and crashed, a recoverable lease or equivalent mechanism must allow it to be processed again without adding another paid period.
For Payfast, verify the current merchant notification and validation contract from the integration documentation. Its subscriptions feature page advertises recurring payments and management controls; it does not establish Stripe event names, signatures, payload fields or a specific notification timetable. Do not invent a Payfast equivalent of a Stripe event ID. Payfast subscriptions
Step 4: check entitlement and account mapping
Read the actual access record for the workspace and paid service period. Inspect the feature/seat allowance, entitlement start and expiry, customer membership and any independent suspension. Verify that the user is attempting to access the correct workspace and that a stale session or cache is not hiding a valid entitlement.
Distinguish missing entitlement data from a valid denial. Granting a paid plan does not authorise a user to access another tenant's data. A correct payment record also does not override an independently justified administrative or security restriction; route that condition to its responsible owner.
Test the authenticated journey after a repair: the intended customer can use the paid features, and another workspace cannot. Inspect the server-side entitlement result as well as the visible success screen. Sending a provisioning email alone does not grant product access or prove that the customer received it.
Practical output: payment-to-access investigation checklist
Copy this proposed worksheet into an incident record. The values are blank deliberately: checked facts should replace them, rather than treating example Yes answers as completed evidence.
| Checkpoint | Evidence to record | Decision or next action |
|---|---|---|
| Correct merchant and environment | Account and live/test mode | Reject a mismatched test or merchant record |
| Correct customer and workspace | Trusted customer-to-tenant mapping | Review any ambiguous mapping before granting access |
| Relevant paid invoice | Invoice ID, status, amount/currency, covered period and billing reason | Establish whether it qualifies for the requested entitlement |
| Current subscription lifecycle | Provider/local state, cancellation/pause dates and reason | Do not overwrite a newer valid restriction |
| Verified notification | Provider object/event identifiers and validation result | Retrieve verified evidence if receipt or verification failed |
| Durable processing history | Receipt, queue, worker and committed result | Recover the failed layer rather than charging again |
| Correct entitlement | Plan, quantity, period, expiry and existing grant | Repair only the missing or incorrect entitlement |
| Recovery authority | Operator, reason, policy and expected current version | Use an audited, scoped reconciliation action |
| Readback and customer journey | Persisted result and authenticated access check | Close only after the intended behaviour is verified |
| Communication | Confirmed status, action and customer message | Explain unresolved facts without claiming success |
The record should link the original invoice, payment and processing attempt. Retain the before/after entitlement and the recovery operation's stable ID. Avoid copying sensitive card details or credentials into support notes.
Step 5: choose a scoped recovery
If current verified billing evidence qualifies for the current period, the subscription lifecycle permits service and the entitlement is missing, run the normal idempotent provisioning path again. That is safer than an unstructured manual status edit. If replay is unavailable, use an authorised reconciliation operation with the same eligibility checks and audit history.
Apply the grant once for the specific workspace, subscription and paid period. Use an atomic uniqueness constraint or equivalent durable control, not a check-then-insert race. Commit the entitlement change and completion record together when they share a database. If an external service also needs provisioning, use a durable recovery job with a stable identity and verify its result separately.
Do not create a new charge as part of access reconciliation. If payment is actually unresolved, first reconcile the original attempt and follow the approved billing process. If the invoice is old or the subscription was validly cancelled, preserve the current state and explain the relevant evidence to the customer. A new subscription or refund is a separate customer/finance decision.
Before any manual repair, read the current version again and apply only if the expected state still holds. A simultaneous cancellation or another worker's successful grant should cause the repair to reevaluate, not overwrite the newer state.
Worked hypothetical case: paid period, failed provisioning
Imagine a fictional SaaS merchant with an eligible, verified payment integration. A customer reports that their account is inactive after paying the current renewal. The incident uses illustrative identifiers invoice-example-1, subscription-example-1 and workspace-example-1; these are not real transactions.
- An authorised operator confirms the current invoice's paid state, customer mapping, currency and service period in the provider account.
- The current provider subscription is eligible for service, with no later cancellation or independent suspension.
- The verified notification was durably stored, but the worker failed before committing the period entitlement. No grant exists for that invoice period.
- The operator invokes the existing reconciliation job with the original invoice and stable period key. The transaction creates one grant and marks that processing operation complete.
- Readback shows the correct plan and expiry. An authenticated access check confirms the customer can use the paid feature in the correct workspace.
- Support explains the confirmed resolution and records the customer communication. No second charge is created.
If the worker had instead committed the grant before crashing, replay should find that grant and complete recovery without extending expiry again. If a later cancellation existed, the same paid-invoice evidence would lead to review rather than automatic reactivation.
Failure cases to test before relying on the checklist
| Case | Expected behaviour | Recovery evidence |
|---|---|---|
| Same event delivered twice | One intended paid-period grant | Duplicate processing and unique period record |
| Two distinct events describe the same invoice payment | One paid-period entitlement | Invoice/period business key, not only event deduplication |
| Payment event arrives after cancellation | No automatic resurrection of cancelled service | Current lifecycle and ordered business decision |
| Client redirect says success but provider record is unresolved | No invented paid state | Verified server-side investigation |
| Wrong tenant or test payment supplied | No access to the requested production workspace | Environment and mapping mismatch |
| Crash before durable receipt | Provider retry or reconciliation can still recover | Failed acknowledgement and original payment record |
| Crash after grant but before job acknowledgement | Existing grant remains; no extra period | Committed transaction and idempotent replay |
| Partial payment, refund or dispute | Apply the approved case-specific policy | Billing evidence and responsible-owner decision |
| Access is correct but session is stale | Refresh/reconcile the access view without another charge | Server entitlement and authenticated journey |
A refund or dispute does not universally mean every account must become inactive immediately. Record the event and apply the approved product/risk policy. Do not invent gateway statuses such as disputed invoice if the actual provider represents the dispute on a related payment object.
Keep provider boundaries visible
Stripe's South Africa listing points to its extended network and Paystack. It does not demonstrate direct Stripe Billing access or identical event contracts for a South African merchant. Use the examples only with the actual account/product eligibility verified. Stripe country and extended-network availability
Do not combine one provider's invoice terminology, another provider's subscription management and a third provider's webhook replay into a fictional integration. Record the actual product in the incident and verify its supported readback and recovery procedures. The checklist remains provider-neutral because the evidence and entitlement decision are explicit.
Plan ongoing reconciliation and support
A periodic reconciliation job can identify eligible paid periods missing entitlements before customers report them. It should produce reviewable discrepancies and reuse the same idempotent repair path. Choose a cadence based on support commitments and processing latency, with ownership for unresolved incidents.
Use SaaS pricing models to define payment, credit and grace conditions. The CMS vs custom development guide helps scope custom account behaviour, while the website maintenance cost guide helps plan operational support. Map the report-to-resolution steps using the user journey glossary.
If your business experiences paid-but-inactive account problems, a verified checklist can make recovery more consistent. If you need help implementing reconciliation and entitlement recovery, get in touch with our SaaS development team.
Frequently asked questions
Can we activate the customer after seeing a paid invoice?
First verify the customer, current paid period, subscription lifecycle and entitlement policy. A paid old or unrelated invoice does not justify current access.
Does replaying a webhook charge the customer again?
The recovery handler should perform the intended idempotent access update without initiating a new charge. Verify that behaviour in your implementation before replaying; a replay button alone is not proof of safety.
What closes the incident?
Verified billing evidence, a justified entitlement decision, persisted readback and the correct authenticated access behaviour. Record any remaining provider uncertainty and communicate the actual result.

