The most expensive WHMCS problem is not a crash. It is a client who paid, an invoice that still says Unpaid, and an automated suspension that follows a week later. Almost every case comes down to one thing: the gateway took the money but never told WHMCS. This guide sets up Stripe and PayPal so that callback always arrives, and shows where to look when it does not.
How a payment is recorded
- The client clicks Pay on the invoice and is sent to the gateway.
- The gateway charges the card.
- The gateway calls a callback URL on your WHMCS to say "invoice 4234 was paid".
- WHMCS marks the invoice paid, logs the transaction and provisions the service.
Step 3 is the one that fails. If the callback URL is wrong, blocked, or unreachable over HTTPS, steps 1 and 2 still happen and the money still moves.
Stripe
Configuration → System Settings → Payment Gateways → Visit Apps & Integrations → Stripe → Activate. Enter the publishable key and secret key from the Stripe dashboard (Developers → API keys). Use the live keys; the test keys only work while Stripe is in test mode and are a common reason nothing is recorded after launch.
Then register the webhook, which is how Stripe reports payments and disputes. In Stripe, Developers → Webhooks → Add endpoint:
https://billing.yourbrand.com/modules/gateways/callback/stripe.phpSelect the events WHMCS needs: payment_intent.succeeded, payment_intent.payment_failed, charge.refunded, charge.dispute.created, customer.subscription.deleted. Copy the webhook signing secret into the Stripe settings in WHMCS. Without the secret, WHMCS rejects every webhook as unverified, which looks exactly like "nothing happens".
Stripe stores cards, so clients can be charged automatically on renewal. Turn on Enable Auto Capture in the gateway settings for that.
PayPal
Use PayPal Checkout, not the older PayPal Payments Standard module. Activate it, then under Configuration → System Settings → Payment Gateways → PayPal Checkout connect your PayPal business account with the Connect button, which creates the API credentials for you.
PayPal reports payments through IPN (Instant Payment Notification). In your PayPal account, Account Settings → Notifications → Instant payment notifications, enable it and set the URL:
https://billing.yourbrand.com/modules/gateways/callback/paypal.phpIf IPN is disabled, WHMCS only learns about payments when the client happens to return to your site after paying, which many do not.
Read the Gateway Log
Billing → Gateway Log records every callback WHMCS received, with the raw data and the result. Search it by invoice number or transaction ID.
- A callback is there and says "Successful": the invoice should be paid. If it is not, the invoice ID in the callback does not match, which happens when the client paid an old invoice link.
- A callback is there and says "Invoice ID Not Found" or "Invalid signature": the webhook secret or IPN URL is wrong, or WHMCS was moved to a new domain.
- Nothing is there at all: the gateway never reached you. Check that the callback URL loads in a browser (it should show a blank page, not a 403 or 404). A security plugin, a rule in Plesk's web application firewall, or an IP allow-list on the WHMCS directory will block it.
Other reasons an invoice stays unpaid
Currency mismatch. The invoice is in GBP but the gateway is configured for USD only. Stripe charges in the invoice currency; enable the currency under System Settings → Currencies and in the gateway.
The client paid from a different email. PayPal matches on the email address; a payment from a personal account against a business client shows in the Gateway Log as unmatched. Apply it manually under the invoice's Add Payment.
Test mode still on. Stripe in test mode records nothing to the live account. Switch both the Stripe dashboard and the WHMCS keys to live together.
The cron is down. Payments are recorded instantly by the callback, but provisioning and the paid-invoice email are done by the cron. See WHMCS cron not running.
Applying a missed payment by hand
When a client sends proof of payment and the log is empty, open the invoice, Add Payment, enter the transaction ID and amount, and pick the gateway. This marks it paid and provisions the service. Then fix the callback so it does not happen again.
Test before your first client
Create a product priced at 1.00, order it with a test client, pay with a real card, and refund it in the gateway. Check the invoice went paid on its own and the Gateway Log shows the callback. Ten minutes now saves the suspension email you would otherwise send to your first paying customer.