Payments & gateways
How customers pay you, and how the money that moves after checkout gets recorded.
Admin → Settings → Payment
What you get without doing anything
Two payment methods are on from the first day and need no account, no keys and no internet connection to a provider:
- Cash on delivery — the customer pays when the order arrives.
- Offline payment — you write your own instructions, such as a bank transfer, and they appear at checkout.
A shop that only ever uses these two is a complete installation. Nothing below is required.
Adding a card gateway
Stripe and PayPal are both optional and both stay switched off until you save your own keys. Until then the application makes no request to either provider.
You need your own account with the provider. No keys are supplied with the product, and the keys you save are stored in your own database on your own server.
Creating your Stripe API keys
- Create a Stripe account, or sign in.
- Turn Test mode on with the toggle at the top right while you are testing.
- Open Developers → API keys (test), or API keys (live) when you go live.
- Copy the Publishable key (
pk_test_…) and reveal and copy the Secret key (sk_test_…).
- Turn Stripe on.
- Publishable key — starts
pk_. - Secret key — starts
sk_. - Webhook signing secret — starts
whsec_; you get it from the webhook below.
Press Save settings.
Creating your PayPal API credentials
- Sign in to the PayPal Developer Dashboard.
- Open Apps & Credentials → Sandbox for testing, or Live for production.
- Choose Create App and open it.
- Copy the Client ID and Secret.
- Turn PayPal on.
- Mode — Sandbox or Live; match the tab your keys came from.
- Client ID.
- Client secret.
- Webhook ID — you get it from the webhook below.
Press Save settings.
Webhooks, and why they are not optional
Checkout settles itself: the customer’s browser comes back to your site and the order is marked paid. A webhook is how you hear about money that moves when nobody is looking at a browser — above all the monthly renewal of a restaurant’s plan.
Without a webhook, a renewal is charged by the provider and never recorded here. The restaurant pays and their term is not extended.
Adding the Stripe webhook
- Open Developers → Webhooks and choose Add endpoint.
- Set the endpoint URL to
https://your-site.com/webhook/stripe. - Subscribe to these five events:
Event What it tells the application payment_intent.succeededA customer’s card order was paid. invoice.paidA subscription charge — the first one and every renewal. invoice.payment_failedA renewal was declined; the term enters its grace period. customer.subscription.updatedAn agreement was cancelled or suspended. customer.subscription.deletedThe agreement ended; renewal stops. - Save, reveal the signing secret (
whsec_…) and paste it into Webhook signing secret in Settings → Payment.
Adding the PayPal webhook
- In the same PayPal app, scroll to Webhooks and choose Add Webhook.
- Set the URL to
https://your-site.com/webhook/paypal. - Subscribe to
PAYMENT.CAPTURE.COMPLETED,PAYMENT.SALE.COMPLETED,BILLING.SUBSCRIPTION.ACTIVATED,BILLING.SUBSCRIPTION.CANCELLED,BILLING.SUBSCRIPTION.SUSPENDED,BILLING.SUBSCRIPTION.EXPIREDandBILLING.SUBSCRIPTION.PAYMENT.FAILED. - Save and copy the Webhook ID into Settings → Payment.
PayPal gives you an ID rather than a secret. Each callback is verified by asking PayPal about that ID using your Client ID and Secret, so the webhook must belong to the same app as the credentials you saved.
How to tell it is working
Take one test payment. Settings → Payment then shows a badge beside the webhook field:
| Badge | What it means |
|---|---|
| Webhook verified, green | A callback arrived and its signature checked out. The event and time are shown underneath. |
| Rejected, red | A callback arrived but the signature did not match — usually the wrong signing secret. |
| No webhook received yet, grey | Nothing has arrived. The endpoint is missing, the URL is wrong, or no payment has been made. |
The badge always shows the most recent result, not a history. A rejection that you have since fixed disappears as soon as a good callback arrives.
When it doesn’t work
Payments succeed but nothing is recorded, and the provider shows no deliveries
The webhook is almost certainly in a different account from your keys. Stripe has both a legacy Test mode inside your main account and separate Sandbox accounts; an endpoint created in one never receives events produced by keys belonging to the other.
Check which account your keys belong to: the account identifier is inside the key itself, straight
after 51 — a key beginning sk_test_51ABCDEFGH… belongs to account
acct_1ABCDEFGH…. Every object that account creates repeats the same fragment in its
own identifier, so you can confirm at a glance that you are looking in the right place.
The badge says Rejected
The signing secret does not match the endpoint. Each endpoint has its own secret; copying one from a different endpoint, or from a different account, fails every time. Reveal the secret on the endpoint you actually created and paste it again.
Nothing arrives on a local installation
Neither provider can reach localhost or a machine behind a private network. Checkout
still works, because the browser return settles it — but renewals cannot record. Test webhooks on
a public address.