Embedded form
Explore a full, working code sample of an integration with Stripe Checkout that lets your customers pay through an embedded form on your website. The example includes client and server-side code, and an embeddable UI component displays the payment form.
Install the Stripe Ruby library
Install the Stripe ruby gem and require it in your code. Alternatively, if you’re starting from scratch and need a Gemfile, download the project files using the link in the code editor.
Create a Checkout Session
Add an endpoint on your server that creates a Checkout Session, setting the ui_mode to embedded
.
The Checkout Session response includes a client secret, which the client uses to mount Checkout. Return the client_secret in your response.
Supply a return URL
To define how Stripe redirects your customer after payment, specify the URL of the return page in the return_url parameter while creating the Checkout Session. After the payment attempt, Stripe directs your customer to return page hosted on your website.
Include the {CHECKOUT_
template variable in the URL. Before redirecting your customer, Checkout replaces the variable with the Checkout Session ID. You’re responsible for creating and hosting the return page on your website.
Define a product to sell
Define the products you’re selling when you create the Checkout Session by using predefined price IDs.
Always keep sensitive information about your product inventory, such as price and availability, on your server to prevent customer manipulation from the client.
Choose the mode
To handle different transaction types, adjust the mode
parameter. For one-time payments, use payment
. To initiate recurring payments with subscriptions, switch the mode
to subscription
. And for setting up future payments, set the mode
to setup
.
Add Stripe to your React app
To stay PCI compliant by ensuring that payment details go directly to Stripe and never reach your server, install React Stripe.js.
npm install --save @stripe/react-stripe-js @stripe/stripe-js
Load Stripe.js
To configure the Stripe library, call loadStripe()
with your Stripe publishable API key.
Fetch a Checkout Session client secret
Create an asynchronous fetchClientSecret
function that makes a request to your server to create a Checkout Session and retrieve the client secret.
Initialize Checkout
To allow the child components to access the Stripe service via the embedded Checkout consumer, pass the resulting promise from loadStripe
and the client secret as an option
to the embedded Checkout provider.
Create an endpoint to retrieve a Checkout Session
Add an endpoint to retrieve a Checkout Session status.
Add a return component
To display order information to your customer, add a new route and return component for the URL you provided as the Checkout Session return_
. Stripe redirects to this page after the customer completes the checkout.
Retrieve a Checkout session
As soon as your return page loads, immediately make a request to the endpoint on your server. Use the Checkout Session ID in the URL to retrieve the status of the Checkout Session.
Handle session
Handle the result of the session by using its status:
complete
: The payment succeeded. Use the information from the Checkout Session to render a success page.open
: The payment failed or was canceled. Remount Checkout so that your customer can try again.
Run the application
Start your server and navigate to http://localhost:3000/checkout
ruby server.rb
Try it out
Click the pay button to complete the payment, which redirects you to the specified return page.
If you see the return page, and the payment in the list of successful payments in the Dashboard, your integration is successfully working. Use any of the following test cards to simulate a payment:
Congratulations!
You have a basic Checkout integration working. Now learn how to customize the appearance of your checkout page and automate tax collection.
Customize the appearance of the embedded form by:
- Adding your color theme and font in your branding settings.
- Using the Checkout Sessions APIto activate additional features, like collecting addresses and prefilling customer data.
Calculate and collect the right amount of tax on your Stripe transactions. Learn more about Stripe Tax and how to add it to Checkout.
Next steps
Fulfill orders
Set up a webhook to fulfill orders after a payment succeeds. Webhooks are the most reliable way to handle business-critical events.
Receive payouts
Learn how to move funds out of your Stripe account into your bank account.
Refund and cancel payments
Handle requests for refunds by using the Stripe API or Dashboard.
Customer management
Let your customers self-manage their payment details, invoices, and subscriptions
require 'stripe'require 'sinatra'# This test secret API key is a placeholder. Don't include personal details in requests with this key.# To see your test secret API key embedded in code samples, sign in to your Stripe account.# You can also find your test secret API key at https://dashboard.stripe.com/test/apikeys.Stripe.api_key = 'sk_test_BQokikJOvBiI2HlWgH4olfQ2'set :static, trueset :port, 4242YOUR_DOMAIN = 'http://localhost:3000'post '/create-checkout-session' docontent_type 'application/json'session = Stripe::Checkout::Session.create({ui_mode: 'embedded',line_items: [{# Provide the exact Price ID (e.g. pr_1234) of the product you want to sellprice: '{{PRICE_ID}}',quantity: 1,}],mode: 'payment',return_url: YOUR_DOMAIN + '/return?session_id={CHECKOUT_SESSION_ID}',}){clientSecret: session.client_secret}.to_jsonendget '/session-status' dosession = Stripe::Checkout::Session.retrieve(params[:session_id]){status: session.status, customer_email: session.customer_details.email}.to_jsonend
source 'https://rubygems.org/'gem 'sinatra'gem 'stripe'
{"name": "client","version": "0.1.0","private": true,"dependencies": {"@stripe/react-stripe-js": "^2.3.0","@stripe/stripe-js": "^1.0.0","react": "^16.9.0","react-dom": "^16.9.0","react-scripts": "^5.0.1","react-router-dom": "^6.16.0"},"homepage": "http://localhost:3000/checkout","proxy": "http://localhost:4242/","scripts": {"start": "react-scripts start --ignore client","build": "react-scripts build","test": "react-scripts test","eject": "react-scripts eject"},"eslintConfig": {"extends": "react-app"},"browserslist": {"production": [">0.2%","not dead","not op_mini all"],"development": ["last 1 chrome version","last 1 firefox version","last 1 safari version"]}}
import React, { useCallback, useState, useEffect } from "react";import {loadStripe} from '@stripe/stripe-js';import {EmbeddedCheckoutProvider,EmbeddedCheckout} from '@stripe/react-stripe-js';import {BrowserRouter as Router,Route,Routes,Navigate} from "react-router-dom";// Make sure to call `loadStripe` outside of a component’s render to avoid// recreating the `Stripe` object on every render.// This test secret API key is a placeholder. Don't include personal details in requests with this key.// To see your test secret API key embedded in code samples, sign in to your Stripe account.// You can also find your test secret API key at https://dashboard.stripe.com/test/apikeys.const stripePromise = loadStripe("pk_test_TYooMQauvdEDq54NiTphI7jx");const CheckoutForm = () => {const fetchClientSecret = useCallback(() => {// Create a Checkout Sessionreturn fetch("/create-checkout-session", {method: "POST",}).then((res) => res.json()).then((data) => data.clientSecret);}, []);const options = {fetchClientSecret};return (<div id="checkout"><EmbeddedCheckoutProviderstripe={stripePromise}options={options}><EmbeddedCheckout /></EmbeddedCheckoutProvider></div>)}const Return = () => {const [status, setStatus] = useState(null);const [customerEmail, setCustomerEmail] = useState('');useEffect(() => {const queryString = window.location.search;const urlParams = new URLSearchParams(queryString);const sessionId = urlParams.get('session_id');fetch(`/session-status?session_id=${sessionId}`).then((res) => res.json()).then((data) => {setStatus(data.status);setCustomerEmail(data.customer_email);});}, []);if (status === 'open') {return (<Navigate to="/checkout" />)}if (status === 'complete') {return (<section id="success"><p>We appreciate your business! A confirmation email will be sent to {customerEmail}.If you have any questions, please email <a href="mailto:orders@example.com">orders@example.com</a>.</p></section>)}return null;}const App = () => {return (<div className="App"><Router><Routes><Route path="/checkout" element={<CheckoutForm />} /><Route path="/return" element={<Return />} /></Routes></Router></div>)}export default App;
body {display: flex;justify-content: center;background: #ffffff;font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto','Helvetica Neue', 'Ubuntu', sans-serif;height: 100vh;margin: 0;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;}section {display: flex;justify-content: space-between;align-items: center;background: #ffffff;flex-direction: column;width: 400px;height: 112px;border-radius: 6px;}p {font-style: normal;font-weight: 500;font-size: 14px;line-height: 20px;letter-spacing: -0.154px;color: #242d60;height: 100%;width: 100%;padding: 0 20px;box-sizing: border-box;}#checkout {width: 100vw;}
import React from "react";import ReactDOM from "react-dom";import App from "./App";ReactDOM.render(<App />, document.getElementById("root"));
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" /><meta name="viewport" content="width=device-width, initial-scale=1" /><meta name="theme-color" content="#000000" /><meta name="description" content="A demo of a payment on Stripe" /><title>Stripe sample</title></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><!--This HTML file is a template.If you open it directly in the browser, you will see an empty page.You can add webfonts, meta tags, or analytics to this file.The build step will place the bundled scripts into the <body> tag.To begin the development, run `npm start` or `yarn start`.To create a production bundle, use `npm run build` or `yarn build`.--></body></html>
# Accept a Payment with Stripe CheckoutStripe Checkout is the fastest way to get started with payments. Included are some basic build and run scripts you can use to start up the application.## Set Price IDIn the back end code, replace `{{PRICE_ID}}` with a Price ID (`price_xxx`) that you created.## Running the sample1. Build the server~~~bundle install~~~2. Run the server~~~ruby server.rb -o 0.0.0.0~~~3. Build the client app~~~npm install~~~4. Run the client app~~~npm start~~~5. Go to [http://localhost:3000/checkout](http://localhost:3000/checkout)