๐Ÿ’ฐStripe Integration

Handling Stripe payments and webhooks.

Adding Stripe Payment

To get started, ensure you have a Stripe account and access the Developers section in the Stripe Dashboard.

1. Setting up Payment Integration with the Stripe Embeddable Pricing Table

Pricing Table is a no code solution from stripe and is specifically designed for first-time purchases. It simplifies the process by allowing you to integrate an iframe directly into your webpage. This iframe will display various pricing options available to your new customers.

Setting up with the pricing table ( detailed instruction )
  1. In the Dashboard, go to More > Product catalog > pricing tables.

  2. Click +Create pricing table.

  3. Add products relevant to your customers (up to four per pricing interval). Optionally, include a free trial.

  4. Adjust the look and feel in Display settings. You can highlight a specific product and customize the language, colors, font, and button design.

  5. Configure payment settings by clicking Continue. Customize what customers see on the payments page and whether to display a confirmation page or redirect customers back to your site after a successful purchase.

  6. Configure the customer portal by clicking Continue.

  7. Click Copy code to copy the generated code and embed it into your website

2. Embedding Pricing Table over the UI

Prompt Databutton to create a new UI component and paste the pricing table code to embed it.

Embed this stripe table and create a PricingTable UI component :
<paste the pricing table embed code that we copied earlier>

Alternatively, copy the template code given below and paste over a page/UI components. Make sure to replace with your actual pricing-table-id and publishable-key.

import { useEffect } from "react";

// Declare the custom element
declare global {
  namespace JSX {
    interface IntrinsicElements {
      "stripe-pricing-table": any;
    }
  }
}

export default function App() {
  useEffect(() => {
    const script = document.createElement("script");
    script.src = "https://js.stripe.com/v3/pricing-table.js";
    script.async = true;
    document.head.appendChild(script);
  }, []);
  const clientReferenceId = "your_client_reference_id"; // Replace with actual client reference ID

  return (
    <div>
      <stripe-pricing-table
        pricing-table-id="prctbl_XXXX"
        publishable-key="pk_test_XXXX"
        client-reference-id={clientReferenceId}
      ></stripe-pricing-table>
    </div>
  );
}

3. API for handling webhook

The stripe_webhook endpoint gets triggered when Stripe sends a POST request to your webhook URL. This happens when specific events occur in your Stripe account, such as a successful payment through Stripe Checkout.

Generating Webhook API via prompting

Databutton can generate this API on prompting and guide through the entire process. Example prompt :

I would like to create a stripe webhook on sucessfull payment checkout.

Also, store the event details as json over databutton storage. Guide me on how to perform each steps in details.  

Generating stripe_webhook API manually

This step requires : STRIPE_SECRET_KEY key and STRIPE_WEBHOOK_SECRET key and add it to Databutton secrets. For adding over to Databutton secrets hover to Config (โš™๏ธ). Instruction given below on how to obtain the secret keys.

How to get the Stripe API Key and add over Databutton:

How to configure the Webhook Endpoint and fetch the Webhook:

  • Go to the Stripe Dashboard.

  • Navigate to Developers.

  • Click on the Webhooks tab.

  • Click "Add endpoint"

  • In order to enter the endpoint URL, we need two things (a) Project ID of the current Databutton App and (b) Router name of the wehbhook API. Then, we need to replace them in the following URL ; https://api.databutton.com/_projects/<ProjectID>/dbtn/prodx/app/routes/<RouterName> (replace <projectID> and <router_name> with your specific information)

  • Project ID can be found over the current browser url : https://databutton.com/projects/<projectID>/ui/App/build

  • router_name : In the template code given below, the router name used is webhook. Here's the ref line @router.post("/webhook") . You can find the entire code for the API below.

  • Copy the webhook secret ("whsec_xxxxxx") and paste it into Databutton/config/secrets

  • While selecting events to send, you can choose specific events, such as those related to the customer (e.g., checkout.session.completed)

While adding the endpoint url, the Correct Project ID and Router Name is important.

API (stripe_webhook)

from fastapi import APIRouter, Request, HTTPException
import stripe
import databutton as db

router = APIRouter()

# Initialize Stripe with the secret key
stripe.api_key = db.secrets.get("STRIPE_SECRET_KEY")


# Webhook endpoint to handle Stripe events
@router.post("/webhook")
async def stripe_webhook(request: Request):
    print("Received stripe-webhook")
    payload = await request.body()
    sig_header = request.headers.get("Stripe-Signature")
    webhook_secret = db.secrets.get("STRIPE_WEBHOOK_SECRET")

    try:
        event = stripe.Webhook.construct_event(payload, sig_header, webhook_secret)

        # Check for the specific event type
        if event["type"] == "checkout.session.completed":
            session = event["data"]["object"]
            session_id = session.get("id")
            customer_email = session["customer_details"]["email"]
            customer_id = session.get("customer")
            client_reference_id = session.get("client_reference_id")
            subscription_id = session.get("subscription")
            payment_intent_id = session.get("payment_intent")
            invoice_id = session.get("invoice")
            payment_status = session.get("payment_status")
            currency = session.get("currency")
            amount_subtotal = session.get("amount_subtotal")
            total_details = session.get("total_details")

            product_details = []

            # Retrieve the full Checkout Session details including line items
            checkout_session = stripe.checkout.Session.retrieve(session_id, expand=["line_items"])
            line_items = checkout_session["line_items"]["data"]

            for item in line_items:
                product_details.append(
                    {
                        "product_id": item["price"]["product"],
                        "price_id": item["price"]["id"],
                        "quantity": item["quantity"],
                        "amount_total": item["amount_total"],
                    }
                )

            # Store specific details from the event
            event_details = {
                "id": event["id"],
                "type": event["type"],
                "created": event["created"],
                "client_reference_id": client_reference_id,
                "customer_email": customer_email,
                "customer_id": customer_id,
                "subscription_id": subscription_id,
                "payment_intent_id": payment_intent_id,
                "invoice_id": invoice_id,
                "payment_status": payment_status,
                "currency": currency,
                "amount_subtotal": amount_subtotal,
                "total_details": total_details,
                "product_details": product_details,
            }
            db.storage.json.put(f"stripe-webhook-event-details-{event['id']}", event_details)

    except ValueError:
        # Invalid payload
        raise HTTPException(status_code=400, detail="Invalid payload")
    except stripe.error.SignatureVerificationError:
        # Invalid signature
        raise HTTPException(status_code=400, detail="Invalid signature")

    return {"status": "success"}

Note: In the above example code, we use databutton storage to monitor the event details with db.storage.json.put("stripe-webhook-event", event), which can be useful for verifying that the webhook integration is working correctly and can be extended for database storage, security checks, and automated processing.

Add stripe package, when adding the API code manually

Note : The app must be deployed for a successfull webhook call.

Last updated