Skip to content

Instantly share code, notes, and snippets.

@Filimoa
Last active January 22, 2024 10:26
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Filimoa/fa5b249cfff69e4072cb7ccce9f172bb to your computer and use it in GitHub Desktop.
Save Filimoa/fa5b249cfff69e4072cb7ccce9f172bb to your computer and use it in GitHub Desktop.
FastAPI Stripe Checkout
"""
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)
@Filimoa
Copy link
Author

Filimoa commented Aug 17, 2021

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. 🥳

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment