Panellicense

Set up Stripe Payments in Blesta without the rounding bug

How to install the Stripe Payments gateway in Blesta, set the payment_intent webhook correctly, and avoid the rounded-amount bug from extra events.

4 min readUpdated 2026-05-16blesta · stripe · payment-gateway · webhook
schema: HowToschema: FAQPage

The Stripe Payments gateway in Blesta works on the modern PaymentIntents API, so it handles 3DS, off-session charging, and SCA out of the box. The catch is the webhook configuration. Subscribe to too many event types and the gateway processes the same charge multiple times — each subsequent event arrives without the full intent context and gets recorded as a small rounding-error transaction.

This guide installs the gateway, configures it with live keys, and sets the webhook to the exact event list that avoids the duplicate-charge bug. Doing the WHMCS-to-Blesta move first? Run through the migration checklist before connecting live gateways.

Install the gateway

In Blesta admin go to Settings → Company → Payment Gateways → Available, find Stripe Payments, and click Install. The gateway ships with core Blesta — no separate plugin download needed.

Open Manage on the newly installed gateway and enter:

  • Publishable Keypk_live_... from dashboard.stripe.com/apikeys
  • Secret Keysk_live_... from the same page

Use live keys, not test keys. Blesta does not have a sandbox mode flag on this gateway — test mode is implied by using pk_test/sk_test. Mixing test keys with a live Stripe webhook is the second most common cause of "payments succeed but invoices stay unpaid".

Tick the currencies this gateway should accept. Stripe processes whatever the customer's invoice is denominated in, but Blesta only routes invoices in the listed currencies through this gateway.

Configure the webhook

Stripe needs to call back into Blesta to confirm payment status. The callback URL pattern is:

https://billing.example.com/callback/gw/<company_id>/stripe_payments/

<company_id> is 1 on a single-company install. Find it in Settings → System → Companies if you run multi-company.

In the Stripe dashboard go to Developers → Webhooks → Add endpoint. Paste the URL. Then — and this is the part everyone gets wrong — select events to listen for, not "all events".

The four events you need

payment_intent.succeeded
payment_intent.payment_failed
charge.refunded
charge.dispute.created

That is the complete list. Save the endpoint.

Test before going live

Stripe ships a one-click test card for the dashboard. Create a $1 invoice on a test client, pay it from the client area with 4242 4242 4242 4242, then verify three things:

  1. The Blesta invoice shows Paid within ~5 seconds (the webhook is faster than polling).
  2. The Stripe dashboard shows exactly one Payment Intent and one Charge for $1.00 — no $0.01 stragglers.
  3. The Blesta transaction log (Billing → Transactions) lists one approved transaction tied to the invoice.

If you see two transactions or any amount other than $1.00, the webhook subscription is too broad. Edit it down to the four events above and replay the test.

Handle off-session renewals

Stripe Payments stores the customer's payment method as a reusable pm_... token on first successful charge. Blesta's renewal cron uses that token to charge invoices automatically without user interaction. For 3DS-required cards this triggers an off-session authentication challenge; the gateway emails the customer a link to complete it. No additional config needed — it works as long as the webhook list above is correct.

Refunds and disputes

Process refunds from the Blesta invoice screen (Billing → Invoices → Refund). The gateway calls Stripe's refund API directly; the charge.refunded webhook then confirms back into Blesta and updates the transaction state.

Disputes initiated in Stripe (chargebacks) flow in through charge.dispute.created and mark the transaction as disputed. Blesta does not automatically void the related service — handle that in your fraud workflow.

Why does Blesta record an extra $0.01 transaction for every Stripe payment?+
The Stripe webhook is subscribed to too many event types. Edit the endpoint in dashboard.stripe.com/webhooks and restrict it to exactly four events: payment_intent.succeeded, payment_intent.payment_failed, charge.refunded, charge.dispute.created.
What is the correct Stripe webhook URL for Blesta?+
https://your-billing-domain/callback/gw/<company_id>/stripe_payments/ — company_id is 1 on a single-company install. Find the value in Settings → System → Companies for multi-company setups.
Does Blesta's Stripe gateway support 3D Secure and SCA?+
Yes — it uses PaymentIntents, so SCA challenges fire automatically when the issuer requires them. Off-session renewals on 3DS-required cards trigger an email to the customer to authenticate.
Can I use both test and live Stripe keys in Blesta?+
Not on the same gateway instance. Install Stripe Payments twice as separate gateways — one with pk_test/sk_test for a sandbox company, one with pk_live/sk_live for production. Make sure each has its own webhook endpoint.

Next steps

Switch in an afternoon

Switch from your current reseller — free.

We migrate active cPanel, Plesk, LiteSpeed and CloudLinux licenses from any reseller. We prorate the first month so you never pay twice, and your customers see zero downtime during the swap.