← Writing

Integrating Stripe Checkout in a Rust fullstack app

2026-06-22#rust#stripe#payments#dioxus

The goal

Accept payments for digital products (plugins) and physical goods on my personal site without pulling in a heavyweight Stripe SDK.

Why raw reqwest?

The async-stripe crate is excellent but versioning can be fiddly in a fullstack workspace. Since reqwest was already a dependency and Stripe's REST API is well-documented, calling it directly kept things simple.

The flow

  1. Client calls create_stripe_session(email, name) — a Dioxus server function.
  2. Server reads the cart from the DB, builds Stripe line items, and POST-s to /v1/checkout/sessions.
  3. Server returns the hosted checkout URL.
  4. Client calls window.location().assign(url) to redirect.
  5. After payment Stripe sends the user to /checkout/success?session_id=cs_....
  6. Success page calls confirm_stripe_payment(session_id), which retrieves the session from Stripe, verifies payment_status == "paid", and creates the order record.

Idempotency

The confirm function checks for an existing order with the same stripe_session_id before doing anything. Safe to call multiple times.

Lessons

  • Store cart_id, email, and name in Stripe session metadata so you can recover them after the redirect even if the cookie is gone.
  • The {CHECKOUT_SESSION_ID} placeholder in success_url must be literal curly braces — escape them in a Rust format string with {{ and }}.