Stripe and PayPal in WHMCS: Setup, and Why Invoices Stay Unpaid

Configure Stripe and PayPal in WHMCS, set the webhook and IPN URLs, read the Gateway Log, and fix the case where the client paid but the invoice stays unpaid.

Published
Reading time
4 min

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

  1. The client clicks Pay on the invoice and is sent to the gateway.
  2. The gateway charges the card.
  3. The gateway calls a callback URL on your WHMCS to say "invoice 4234 was paid".
  4. 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.php

Select 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.php

If 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.

#whmcs#stripe#paypal#payment-gateway#invoices

Keep reading

More from WHMCS

All guides

WHMCS

How to Upgrade to WHMCS 9 Safely (PHP 8.2, ionCube 13, Templates)

A pre-flight checklist for WHMCS 9: back up, move to PHP 8.2 or 8.3, update ionCube to 13, test templates and hooks, upgrade in order, and roll back if needed.

4 min read →

WHMCS

Selling Domains in WHMCS: Registrar Modules, TLD Pricing and Sync

Connect a registrar to WHMCS, import TLD costs with Registrar TLD Sync, set your markup, configure renewals and nameservers, and never sell a domain at a loss.

3 min read →

WHMCS

How to Set Up Products, Pricing and Configurable Options in WHMCS

Create product groups and hosting products in WHMCS, set billing cycles and prices, add configurable options and addons, and build the order form clients see.

4 min read →