Last active
March 9, 2025 07:50
-
-
Save Filimoa/fa5b249cfff69e4072cb7ccce9f172bb to your computer and use it in GitHub Desktop.
FastAPI Stripe Checkout
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Based off Stripe's checkout repo, see the link for the Flask analogue. | |
https://github.com/stripe-samples/checkout-one-time-payments/blob/master/server/python/server.py | |
Assumes project is structured like: | |
src/ | |
backend/ | |
app.py | |
frontend/ | |
build/ | |
... | |
""" | |
import os | |
from typing import List, Optional | |
import stripe | |
from fastapi import Cookie, FastAPI, Header, HTTPException, Request | |
from fastapi.staticfiles import StaticFiles | |
from fastapi.responses import FileResponse | |
from pydantic import BaseModel | |
app = FastAPI() | |
app.mount("/static/", StaticFiles(directory="../frontend/build/static"), name="static") | |
stripe.api_key = os.getenv("STRIPE_SECRET_KEY") | |
stripe.api_version = os.getenv("STRIPE_API_VERSION") | |
class StripeEvent(BaseModel): | |
address: str | |
balance: int | |
created: int | |
data: dict | |
@app.get("/api/config") | |
def get_publishable_key(): | |
price = stripe.Price.retrieve(os.getenv("POSTER_PRICE")) | |
return { | |
"publicKey": os.getenv("STRIPE_PUBLISHABLE_KEY"), | |
"unitAmount": price["unit_amount"], | |
"currency": price["currency"], | |
} | |
@app.post("/api/create-checkout-session/{posterID}") | |
def create_checkout_session(posterID: str, userID: str = Cookie(None)): | |
domain_url = os.getenv("DOMAIN") or "http://localhost:3000" | |
album_price = os.getenv("POSTER_PRICE") | |
try: | |
checkout_session = stripe.checkout.Session.create( | |
success_url=domain_url | |
+ "/order-confirmation?session_id={CHECKOUT_SESSION_ID}", | |
cancel_url=domain_url + "/create-poster", | |
client_reference_id=userID, | |
payment_method_types=["card"], | |
mode="payment", | |
metadata={"poster_id": posterID}, | |
line_items=[{"price": album_price, "quantity": 1}], | |
) | |
return {"sessionId": checkout_session["id"]} | |
except Exception as e: | |
raise HTTPException(status_code=403, detail=str(e)) | |
@app.post("/webhook") | |
async def webhook_received( | |
event: dict, | |
request: Request, | |
stripe_signature=Header(None), | |
): | |
webhook_secret = os.getenv("STRIPE_WEBHOOK_SECRET") | |
raw_body = await request.body() | |
try: | |
event = stripe.Webhook.construct_event( | |
payload=raw_body, | |
sig_header=stripe_signature, | |
secret=webhook_secret, | |
) | |
except Exception as e: | |
raise HTTPException(422, detail=str(e)) | |
data = event["data"]["object"] | |
if event["type"] == "checkout.session.completed": | |
# your custom function to run after a successful payment | |
print('Succesful checkout') | |
return 200 | |
@app.get("/{full_path:path}", response_class=FileResponse) | |
def index(request: Request, full_path: str): | |
path = ".././frontend/build/index.html" | |
return FileResponse(path) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Accept payments with Stripe Checkout
This sample shows you how to integrate a FastAPI backend with Stripe Checkout. See https://github.com/stripe-samples/checkout-one-time-payments for the original Flask demo repository.
Building a payment form UI from scratch is difficult -- input field validation, error message handing, and localization are just a few things to think about when designing a simple checkout flow.
Stripe built Checkout to do that work for you so you can focus on building the best storefront experience for your customers. Once your customer is ready to pay, use Stripe.js to redirect them to the URL of your Stripe hosted payment page. 🥳