# How to integrate Stripe with Bubble.io: Step-by-Step Guide

- Tool: Bubble
- Difficulty: Beginner
- Time required: 20-25 min
- Compatibility: All Bubble plans (live payments require Starter+ for custom domain)
- Last updated: March 2026

## TL;DR

Integrate Stripe payment processing into your Bubble app for one-time charges, subscriptions, and checkout sessions. This tutorial covers installing the official Stripe plugin, configuring test and live API keys, creating Stripe Checkout sessions, handling webhooks for payment confirmation, and switching from test to live mode when you are ready to accept real payments.

## Overview: Integrating Stripe with Bubble

Stripe is the most popular payment processor for Bubble apps, powering everything from one-time product purchases to recurring subscriptions. This tutorial walks through the complete setup: installing the official Stripe plugin, configuring API keys, building a checkout workflow, handling payment confirmation via webhooks, and preparing for production. Whether you are selling products, services, or subscriptions, this guide gives you a working Stripe integration.

## Before you start

- A Bubble account with an app
- A Stripe account (sign up at stripe.com — no approval needed for test mode)
- Basic understanding of Bubble workflows
- A page with a product or service that needs payment functionality

## Step-by-step guide

### 1. Install the Stripe plugin and add API keys

Go to the Plugins tab in your Bubble editor and click Add plugins. Search for 'Stripe' and install the official Stripe plugin by Bubble (it has the most installs). Click the plugin name to open its settings. Go to your Stripe dashboard (dashboard.stripe.com) → Developers → API keys. Make sure the 'Test mode' toggle is on. Copy the Publishable key (starts with pk_test_) and paste it into the plugin's 'Publishable key (dev)' field. Copy the Secret key (starts with sk_test_) and paste it into the 'Secret key (dev)' field. Leave the live key fields empty for now.

> Pro tip: Never paste live Stripe keys until you have fully tested the payment flow. Stripe provides test card numbers like 4242 4242 4242 4242 for testing.

**Expected result:** The Stripe plugin is installed with test API keys configured and ready for development.

### 2. Create a Stripe Checkout session for one-time payments

On your product or cart page, add a Pay Now button. Create a workflow: When Pay Now is clicked → add the action Plugins → Stripe - Checkout (or Stripe.js - Checkout). Configure the checkout settings: set the line item name to your product name (dynamic or static), the amount in cents (e.g., 2999 for $29.99), the currency code (usd), and the quantity. Set the Success URL to your confirmation page and the Cancel URL back to the product page. Stripe handles the entire payment form — credit card input, validation, and processing — on their hosted checkout page.

**Expected result:** Clicking Pay Now redirects the customer to Stripe's hosted checkout page with the correct product and price.

### 3. Store order records in your Bubble database

Before the Stripe Checkout action, add a Create new thing action to create an Order record in your database with fields: Customer (Current User), Amount, Status (set to Pending), and Created_Date (Current date/time). After the Stripe Checkout action, add another action: Make changes to the Order → set Stripe_Session_ID to the checkout session ID from the Stripe response. This links your Bubble order to the Stripe payment session. On the success page, you can display the order details by looking up the Order with the session ID from the URL parameter.

> Pro tip: Always create the Order record before redirecting to Stripe. If you wait until the success redirect, you risk losing the order if the customer closes their browser.

**Expected result:** An Order record is created in your database linked to the Stripe checkout session before the customer is redirected.

### 4. Set up Stripe webhooks for payment confirmation

In your Stripe dashboard, go to Developers → Webhooks → Add endpoint. Enter your Bubble backend workflow URL: https://yourapp.bubbleapps.io/api/1.1/wf/stripe-payment-webhook. Select the event checkout.session.completed. Copy the Webhook Signing Secret. In Bubble, go to the Workflow tab → pages dropdown → Backend workflows. Create a new backend workflow called stripe-payment-webhook. Add parameters for the incoming Stripe event data. In the workflow actions: search for the Order whose Stripe_Session_ID matches the event's session ID, then Make changes to it → set Status to Paid. This confirms payment server-side regardless of what happens in the browser.

> Pro tip: For production apps with subscriptions, refunds, or complex billing, RapidDev can help architect a robust webhook handling system that processes all Stripe events reliably.

**Expected result:** Stripe sends a webhook to your Bubble backend when payment completes, automatically updating the order status.

### 5. Test the full payment flow with Stripe test cards

Preview your app and go through the entire payment flow. Click the Pay Now button, and on the Stripe Checkout page, use the test card number 4242 4242 4242 4242 with any future expiration date, any 3-digit CVC, and any name. Complete the payment. Verify: the success page loads, your Order record status changed to Paid (check in Data tab → App data → Orders), and the payment appears in your Stripe dashboard under Payments (in test mode). Also test failure scenarios: use card 4000 0000 0000 0002 for a declined card to verify your error handling works.

**Expected result:** Test payments complete successfully, orders update to Paid status, and declined cards are handled gracefully.

### 6. Switch to live mode when ready for production

When your payment flow is fully tested, go to your Stripe dashboard and turn off the 'Test mode' toggle. Copy your live Publishable key (pk_live_) and Secret key (sk_live_). In Bubble, go to Plugins → Stripe and paste the live keys into the 'Publishable key (live)' and 'Secret key (live)' fields. Update your webhook endpoint in Stripe to use the live webhook signing secret. In Bubble Settings, make sure your app is deployed to live. Important: the live keys only work when your Bubble app is deployed, not in preview/development mode.

**Expected result:** Your Bubble app processes real Stripe payments in live mode with production API keys.

## Complete code example

File: `Workflow summary`

```text
STRIPE INTEGRATION — WORKFLOW SUMMARY
======================================

SETUP:
  Plugins tab → Install 'Stripe' plugin (official)
  Configure: Publishable key (dev) = pk_test_...
             Secret key (dev) = sk_test_...

DATA TYPE: Order
  Customer (User), Amount (number), Status (text),
  Stripe_Session_ID (text), Created_Date (date)

PAGE WORKFLOW: Pay Now clicked
  1. Create new Order (Customer=Current User, Amount=price,
     Status=Pending, Created_Date=Current date/time)
  2. Stripe Checkout action
     - Line item: Product name, amount in cents, quantity
     - Success URL: /payment-success?session_id={CHECKOUT_SESSION_ID}
     - Cancel URL: /product-page
  3. Make changes to Order → Stripe_Session_ID = session ID

BACKEND WORKFLOW: stripe-payment-webhook
  Trigger: Incoming webhook from Stripe
  Event: checkout.session.completed
  1. Search for Order (Stripe_Session_ID = event session ID)
  2. Make changes → Status = Paid
  3. Optional: Send confirmation email

STRIPE DASHBOARD:
  Developers → Webhooks → Add endpoint
  URL: https://yourapp.bubbleapps.io/api/1.1/wf/stripe-payment-webhook
  Events: checkout.session.completed

TEST CARDS:
  Success: 4242 4242 4242 4242
  Decline: 4000 0000 0000 0002
  3D Secure: 4000 0025 0000 3155

GOING LIVE:
  1. Stripe dashboard → Turn off Test mode
  2. Copy live keys (pk_live_, sk_live_)
  3. Paste into Stripe plugin live key fields
  4. Update webhook signing secret
  5. Deploy Bubble app to live
```

## Common mistakes

- **Sending dollar amounts instead of cents to Stripe** — Stripe expects amounts in the smallest currency unit. Sending 29 instead of 2900 charges $0.29 instead of $29.00. Fix: Always multiply dollar amounts by 100 before passing them to the Stripe Checkout action.
- **Using test API keys in the live key fields (or vice versa)** — Test keys only work in development/preview mode and live keys only work when deployed. Mixing them causes payment failures. Fix: Put pk_test_/sk_test_ in the dev fields and pk_live_/sk_live_ in the live fields. Never mix them.
- **Relying only on the success redirect to confirm payment** — Customers can close their browser, experience network issues, or manually navigate away before the redirect completes. Fix: Always set up a Stripe webhook as the authoritative payment confirmation. Update order status in the webhook handler, not on the success page.
- **Not testing with Stripe's declined card numbers** — Only testing happy paths misses edge cases like insufficient funds, expired cards, and fraud blocks. Fix: Test with Stripe's special test card numbers for declines (4000 0000 0000 0002), insufficient funds (4000 0000 0000 9995), and 3D Secure (4000 0025 0000 3155).

## Best practices

- Always create order records before redirecting to Stripe Checkout
- Use Stripe webhooks as the authoritative source for payment confirmation
- Test with multiple Stripe test card numbers including decline and 3D Secure scenarios
- Store Stripe Session IDs and Payment Intent IDs in your database for reconciliation
- Add email notifications for successful payments to both the customer and the business
- Monitor the Stripe dashboard for failed payments and disputed charges
- Keep test and live API keys strictly separated in the plugin configuration
- Add a loading indicator on the Pay button to prevent double-clicks during checkout creation

## Frequently asked questions

### Does Stripe charge fees on test transactions?

No. Test mode transactions are free and use fake card numbers. Stripe only charges fees (2.9% + $0.30 per transaction) on live mode payments with real cards.

### Can I accept payments on Bubble's Free plan?

You can test Stripe payments in preview mode on the Free plan. However, to accept live payments, you need a paid Bubble plan with a custom domain, since Stripe requires a consistent domain for checkout redirects.

### How do I handle refunds?

You can issue refunds directly from the Stripe dashboard, or set up a Stripe API call via the API Connector to automate refunds from a Bubble admin workflow.

### What currencies does Stripe support in Bubble?

Stripe supports 135+ currencies. Set the currency code in the Checkout action (e.g., usd, eur, gbp). Ensure your Stripe account is activated for the currencies you want to use.

### How do I add Apple Pay and Google Pay?

Stripe Checkout automatically shows Apple Pay and Google Pay buttons when available on the customer's device. No additional configuration is needed in Bubble — Stripe handles it on their hosted checkout page.

### Can RapidDev help with complex Stripe integrations?

Yes. RapidDev specializes in advanced Stripe setups including subscription billing, usage-based pricing, Stripe Connect for marketplaces, and custom checkout experiences within Bubble apps.

---

Source: https://www.rapidevelopers.com/bubble-tutorial/integrate-stripe-with-bubble
© RapidDev — https://www.rapidevelopers.com/bubble-tutorial/integrate-stripe-with-bubble
