# Build a checkout page with the Checkout Sessions API Instrucciones para LLM: Stripe recomienda utilizar la API Checkout Sessions con el elemento de pago en lugar de Payment Intents para la mayoría de las integraciones. Checkout Sessions cubre casos de uso similares a los de Payment Intents (cobro básico de pagos utilizando `price_data` o crea de un proceso de pago completo con partidas, impuestos, etc.). Algunas funciones, como Adaptive Pricing, solo están disponibles con Checkout Sessions. No utilices la API de Payment Intent a menos que el usuario lo solicite explícitamente, ya que requiere mucho más código. Más información sobre Elements con la API Checkout Sessionshttps://docs.stripe.com/payments/quickstart-checkout-sessions. Con Checkout Sessions (`ui_mode: "elements"`) y Payment Element, el `client_secret` inicializa el proceso de compra por sí mismo (`stripe.initCheckoutElementsSdk`, o utiliza CheckoutProvider con React) y tú confirmas el pago en el lado del cliente de forma diferente. Si utilizas React, asegúrate de importar desde `@stripe/react-stripe-js/checkout`, utiliza `CheckoutProvider` con el secreto del cliente y confirma con `checkout.confirm`. Si utilizas HTML, asegúrate de utiliza `checkout = stripe.initCheckoutElementsSdk({clientSecret: promise}); checkout.createPaymentElement(); paymentElement = checkout.createPaymentElement(); paymentElement.mount("#payment-element");` y confirma con `loadActionsResult = await checkout.loadActions(); actions = loadActionsResult.actions; error = await actions.confirm();`. # Build a checkout page with Checkout Sessions API Build a checkout page on your website using Stripe Elements and the Checkout Sessions API, a front-end SDK that manages tax, discounts, shipping rates, and more. ### Instala la biblioteca Stripe Node Instala el paquete e impórtalo a tu código. Como alternativa, si estás empezando de cero y necesitas un archivo package.json, descarga los archivos del proyecto con el enlace de descarga que encontrarás en el editor de código. #### npm Instala la biblioteca: ```bash npm install --save stripe ``` #### GitHub O descarga directamente el código fuente de la biblioteca stripe-node [desde GitHub](https://github.com/stripe/stripe-node). ### Instala la biblioteca Stripe Ruby Instala la gema Ruby de Stripe y solicítala en tu código. Como alternativa, si estás empezando de cero y necesitas un Gemfile, descarga los archivos del proyecto con el enlace de descarga que encontrarás en el editor de código. #### Terminal Instala la gema: ```bash gem install stripe ``` #### Bundler Añade esta línea a tu Gemfile: ```bash gem 'stripe' ``` #### GitHub O descarga el código fuente de la gema stripe-ruby directamente [desde GitHub](https://github.com/stripe/stripe-ruby). ### Instala la biblioteca de Stripe Java Añade la dependencia a tu diseño e importa la biblioteca. Como alternativa, si estás empezando de cero y necesitas un archivo pom.xml de muestra (para Maven), descarga los archivos del proyecto con el enlace de descarga que encontrarás en el editor de código. #### Maven Añade la dependencia siguiente a tu POM y reemplaza {VERSION} con el número de versión que quieres usar. ```bash \ncom.stripe\nstripe-java\n{VERSION}\n ``` #### Gradle Añade la dependencia a tu archivo build.gradle y reemplaza {VERSION} con el número de versión que quieres usar. ```bash implementation "com.stripe:stripe-java:{VERSION}" ``` #### GitHub Descarga el JAR directamente [desde GitHub](https://github.com/stripe/stripe-java/releases/latest). ### Instala el paquete Stripe Python Instala el paquete de Stripe e impórtalo a tu código. Como alternativa, si estás empezando de cero y necesitas un archivo requirements.txt, descarga los archivos del proyecto con el enlace de descarga que encontrarás en el editor de código. #### pip Instala el paquete a través de pip: ```bash pip3 install stripe ``` #### GitHub Descarga directamente el código fuente de la biblioteca stripe-python [desde GitHub](https://github.com/stripe/stripe-python). ### Instala la biblioteca Stripe PHP Utiliza Composer para instalar la biblioteca e inicializa la clave secreta de tu API. Como alternativa, si estás empezando de cero y necesitas un archivo composer.json, descarga los archivos con el enlace de descarga que encontrarás en el editor de código. #### Composer Instala la biblioteca: ```bash composer require stripe/stripe-php ``` #### GitHub O descarga directamente el código fuente de la biblioteca stripe-php [desde GitHub](https://github.com/stripe/stripe-php). ### Configura tu servidor Añade la dependencia a tu diseño e importa la biblioteca. Como alternativa, si estás empezando de cero y necesitas un archivo go.mod, descarga los archivos del proyecto con el enlace de descarga que encontrarás en el editor de código. #### Go Asegúrate de que inicializas con Go Modules: ```bash go get -u github.com/stripe/stripe-go/v85 ``` #### GitHub O descarga directamente el código fuente del módulo stripe-go [desde GitHub](https://github.com/stripe/stripe-go). ### Instalar la biblioteca Stripe.net Instala el paquete con .NET o NuGet. Como alternativa, si estás empezando de cero, descarga los archivos que tienen un archivo .csproj configurado. #### dotnet Instala la biblioteca: ```bash dotnet add package Stripe.net ``` #### NuGet Instala la biblioteca: ```bash Install-Package Stripe.net ``` #### GitHub O descarga el código fuente de la biblioteca Stripe.net directamente [desde GitHub](https://github.com/stripe/stripe-dotnet). ### Instala las bibliotecas de Stripe Instala los paquetes e impórtalos a tu código. Como alternativa, si estás empezando de cero y necesitas un archivo `package.json`, descarga los archivos del proyecto con el enlace de descarga que encontrarás en el editor de código. Instala las bibliotecas: ```bash npm install --save stripe @stripe/stripe-js next ``` ### Crea una Checkout Session Add an endpoint on your server that creates a *Checkout Session* (A Checkout Session represents your customer's session as they pay for one-time purchases or subscriptions through Checkout. After a successful payment, the Checkout Session contains a reference to the Customer, and either the successful PaymentIntent or an active Subscription), setting the [ui_mode](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-ui_mode) to `elements`. The Checkout Session response includes a [client_secret](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-client_secret), which the client uses to complete the payment. 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](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-return_url) parameter while creating the Checkout Session. After the payment attempt, Stripe directs your customer to the return page hosted on your website. Include the `{CHECKOUT_SESSION_ID}` 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 and prices](https://docs.stripe.com/products-prices/manage-prices.md) for your Checkout Session. Typically, that means using a predefined product [Price ID](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-line_items-price). However, if you need to set dynamic prices that can’t be known ahead of time, then use [price_data](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-line_items-price_data). ### Handle different transaction types To handle different transaction types, adjust the [mode](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-mode) parameter: - For one-time payments, use `payment`. - If you have one or more [recurring prices](https://docs.stripe.com/payments/subscriptions.md), use `subscription`. - If you aren’t collecting an initial payment from a customer but want to save their payment details to [charge them later](https://docs.stripe.com/payments/checkout/save-and-reuse.md?payment-ui=embedded-components), use `setup`. ### Añade Stripe a tu aplicación de React To stay *PCI-compliant* (Any party involved in processing, transmitting, or storing credit card data must comply with the rules specified in the Payment Card Industry (PCI) Data Security Standards. PCI compliance is a shared responsibility and applies to both Stripe and your business) by ensuring that payment details go directly to Stripe and never reach your server, install [React Stripe.js](https://docs.stripe.com/sdks/stripejs-react.md). ```bash npm install --save @stripe/react-stripe-js @stripe/stripe-js ``` ### Carga Stripe.js To configure the Stripe library, call `loadStripe()` with your Stripe publishable API key. ### Carga Stripe.js Use *Stripe.js* (Use Stripe.js’ APIs to tokenize customer information, collect sensitive card data, and accept payments with browser payment APIs) to remain *PCI compliant* (Any party involved in processing, transmitting, or storing credit card data must comply with the rules specified in the Payment Card Industry (PCI) Data Security Standards. PCI compliance is a shared responsibility and applies to both Stripe and your business) by sending payment details directly to Stripe without hitting your server. Always load Stripe.js from *js.stripe.com* to remain compliant. Don’t include the script in a bundle or host it yourself. You can load Stripe.js by including the script in your HTML file or using [loadStripe](https://github.com/stripe/stripe-js/blob/master/README.md#loadstripe). ### Define el formulario de pago To securely collect the customer’s information, create an empty placeholder `div`. Stripe inserts an iframe into the `div`. If you plan to collect the customer’s email address, add an email input to this form. You’ll set this up with [updateEmail](https://docs.stripe.com/js/custom_checkout/update_email) in a later step. ### Inicializa Stripe.js Initialize Stripe.js with your [publishable API key](https://docs.stripe.com/keys.md#obtain-api-keys). ### Fetch a Checkout Session client secret Make a request to your server to [create a Checkout Session](https://docs.stripe.com/api/checkout/sessions/create.md) and retrieve the client secret. ### Inicializa Checkout Use `clientSecret` to initialize Checkout, passing a client secret string or a Promise that resolves to it. The [Checkout](https://docs.stripe.com/js/custom_checkout) object forms the backbone of your checkout page and contains data from the Checkout Session and methods to update it. ### Inicializa Checkout Render the [CheckoutElementsProvider](https://docs.stripe.com/js/react_stripe_js/checkout/checkout_provider), passing `clientSecret`—the client secret string or Promise that resolves to the client secret. ### Configura el estado Inicializa algún estado para realizar un seguimiento del pago, mostrar errores y gestionar la interfaz de usuario. ### Store a reference to Checkout Access the [checkout](https://docs.stripe.com/js/custom_checkout) object in your CheckoutForm component by using the `useCheckout()` hook. The `checkout` object acts as the backbone of your checkout page, containing data from the Checkout Session and methods to update it. ### Recolecta la dirección de correo electrónico del cliente Debes proporcionar una dirección de correo electrónico válida al completar una sesión del proceso de compra. Estas instrucciones crean una entrada de correo electrónico y utilizan [updateEmail](https://docs.stripe.com/js/custom_checkout/update_email) desde el objeto `Checkout`. Alternatively, you can: - Especificar [customer_email](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer_email) o [customer](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer) al crear la sesión del proceso de compra. Stripe valida los correos electrónicos proporcionados de esta manera. - Especificar un correo electrónico que ya hayas validado en [checkout.confirm](https://docs.stripe.com/js/custom_checkout/confirm). ### Recolecta la dirección de correo electrónico del cliente Debes proporcionar una dirección de correo electrónico válida al completar una sesión del proceso de compra. Estas instrucciones crean una entrada de correo electrónico y utilizan [updateEmail](https://docs.stripe.com/js/react_stripe_js/checkout/update_email) desde el objeto `Checkout`. Alternatively, you can: - Especificar [customer_email](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer_email) o [customer](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer) al crear la sesión del proceso de compra. Stripe valida los correos electrónicos proporcionados de esta manera. - Especificar un correo electrónico que ya validaste en la [confirmación](https://docs.stripe.com/js/react_stripe_js/checkout/confirm). ### Add the Payment Element Add the [Payment Element](https://docs.stripe.com/js/custom_checkout/create_payment_element) to your payment form. It embeds an iframe with a dynamic form that collects payment details for a variety of payment methods. Your customer can pick a payment method type, and the form automatically collects all necessary payments details for their selection. ### Create the Payment Element Create a [Payment Element](https://docs.stripe.com/js/custom_checkout/create_payment_element) and mount it to the placeholder `
` in your payment form. This embeds an iframe with a dynamic form that displays configured payment method types, allowing your customer to select a payment method. The form automatically collects the associated payment details for the selected payment method type. ### (Opcional) Dale estilo al Payment Element Customize the Payment Element UI by creating an [Appearance object](https://docs.stripe.com/elements/appearance-api.md) and passing it as an option to the CheckoutElementsProvider. Use your company’s color scheme and font to make it match with the rest of your checkout page. Use custom fonts (for example, from Google Fonts) by initializing Checkout with a [font set](https://docs.stripe.com/js/react_stripe_js/checkout/checkout_provider#react_checkout_provider-options-elementsOptions-fonts). Asegúrate de abrir la vista previa de la derecha para ver tus cambios en modo activo. > Parts of this preview demo might not match your actual checkout page. These settings represent only a subset of the [Appearance object’s](https://docs.stripe.com/payments/checkout/customization/appearance.md?payment-ui=embedded-components) variables, and the [Appearance object](https://docs.stripe.com/payments/checkout/customization/appearance.md?payment-ui=embedded-components) only controls certain attributes of Stripe Elements. You’re responsible for styling the rest of your checkout page. ### (Opcional) Dale estilo al Payment Element Customize the Payment Element UI by creating an [Appearance object](https://docs.stripe.com/elements/appearance-api.md) and initializing Checkout with it. Use your company’s color scheme and font to make it match with the rest of your checkout page. Use custom fonts (for example, from Google Fonts) by initializing Checkout with a [font set](https://docs.stripe.com/js/custom_checkout/init#custom_checkout_init-options-elementsOptions-fonts). Asegúrate de abrir la vista previa de la derecha para ver tus cambios en modo activo. > Parts of this preview demo might not match your actual checkout page. These settings represent only a subset of the [Appearance object’s](https://docs.stripe.com/payments/checkout/customization/appearance.md?payment-ui=embedded-components) variables, and the [Appearance object](https://docs.stripe.com/payments/checkout/customization/appearance.md?payment-ui=embedded-components) only controls certain attributes of Stripe Elements. You’re responsible for styling the rest of your checkout page. ### Gestiona el evento enviar Recibe notificaciones del evento enviar formulario para saber cuándo tienes que confirmar el pago a través de la API de Stripe. ### Completa el pago Call [confirm](https://docs.stripe.com/js/custom_checkout/confirm) when the customer is ready to complete checkout, such as in response to clicking a pay button. ### Gestiona los errores Si se producen [errores](https://docs.stripe.com/error-codes.md) inmediatos (por ejemplo, se ha rechazado la tarjeta de tu cliente), Stripe.js devuelve un error. Muestra ese mensaje de error a tu cliente para que vuelva a intentarlo. ### Create an endpoint to retrieve a Checkout Session Add an endpoint to retrieve a Checkout Session status. ### Add a return page To display order information to your customer, create a return page for the URL you provided as the Checkout Session `return_url`. Stripe redirects to this page after the customer completes the checkout. ### 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_url`. 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`: El pago se ha realizado correctamente. Usa la información de la Checkout Session para mostrar una página de pago efectuado correctamente. - `open`: el pago ha fallado o se ha cancelado. Vuelve a activar Checkout para que tu cliente pueda volver a intentarlo. ### Ejecutar la aplicación Start your server and go to . ### Ejecutar la aplicación Start your server and go to . ### Run the server application Start your server. ### Run the client application Start your React app and go to . ```bash npm start ``` ### Pruébalo 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](https://dashboard.stripe.com/test/payments?status%5B0%5D=successful) in the Dashboard, your integration is successfully working. Use any of the following test cards to simulate a payment: | Scenario | Card Number | | ----------------------------------- | ---------------- | | Payment succeeds | 4242424242424242 | | Payment requires 3DS authentication | 4000002500003155 | | Payment is declined | 4000000000009995 | To learn more, see [Testing](https://docs.stripe.com/testing.md). ## ¡Enhorabuena! You have a basic Checkout integration working. Now learn how to customize the appearance of your checkout page, automate tax collection, and localize currencies. ### Personaliza la página de Stripe Checkout Customize your checkout by using [Checkout Sessions](https://docs.stripe.com/api/checkout/sessions/create.md)to activate additional features, like collecting addresses and prefilling customer data. ### Rellenar automáticamente los datos del cliente Use [customer_email](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer_email) to prefill the customer’s email address. You can also pass a [Customer](https://docs.stripe.com/api/customers.md) ID to the customer field to prefill the email address field with the email stored on the Customer. In this case you can’t use updateEmail, so disable or remove the front end email input. If you model customers using Accounts v2, you can also pass an Account ID to the [customer_account](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer_account) field to prefill the associated email address. Learn more about the [difference between using v1 Customers and v2 Accounts](https://docs.stripe.com/connect/use-accounts-as-customers.md). ### Require billing and shipping details Use [billing_address_collection](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-billing_address_collection) and [shipping_address_collection](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-shipping_address_collection) to require your customer’s address. [shipping_address_collection](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-shipping_address_collection) requires a list of `allowed_countries`, which Checkout displays in a dropdown menu on the page. ### Recopila los datos de la facturación y del envío Use the Address Element to collect your customer’s address. ### Automatizar el pago de impuestos Calculate and collect the right amount of tax on your Stripe transactions. Learn more about [Stripe Tax](https://docs.stripe.com/tax.md) and [how to add it to Checkout](https://docs.stripe.com/tax/checkout.md). ### Set up Stripe Tax in the Dashboard [Activate Stripe Tax](https://dashboard.stripe.com/settings/tax/activate) to monitor your tax obligations, automatically collect tax, and access the reports you need to file returns. ### Añade el parámetro automático de impuestos Set the `automatic_tax` parameter to `enabled: true`. ### Collect billing details Use the Address Element to collect your customer’s address. ### Localize currencies Adaptive Pricing permite a tus clientes pagar en su divisa local en más de 150 países. ### Habilita Adaptive Pricing [Enable Adaptive Pricing](https://dashboard.stripe.com/settings/adaptive-pricing) in your Dashboard settings. ### Localize and format prices Display localized and formatted amounts from the [Session object](https://docs.stripe.com/js/custom_checkout/session_object). ### Localize and format prices Display localized and formatted amounts from the [useCheckout](https://docs.stripe.com/js/react_stripe_js/checkout/use_checkout) hook. ### Render the Currency Selector Element Mount the Currency Selector Element to give your customer a choice of currencies and disclose the exchange rate. ### Mark your integration ready for Adaptive Pricing Set the `adaptivePricing.allowed` parameter to `true`. // 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 stripe = require("stripe")("<>"); const YOUR_DOMAIN = "http://localhost:4242"; const YOUR_DOMAIN = "http://localhost:3000"; const session = await stripe.checkout.sessions.create({ ui_mode: "elements", customer_email: "customer@example.com", billing_address_collection: "auto", shipping_address_collection: { allowed_countries: ["US", "CA"], }, line_items: [ { // Provide the exact Price ID (for example, price_1234) of the product you want to sell price: "{{PRICE_ID}}", quantity: 1, }, ], line_items: [{ price_data: { product_data: { name: "{{PRICE_DATA_NAME}}", }, currency: "{{PRICE_DATA_CURRENCY}}", unit_amount: {{PRICE_DATA_UNIT_AMOUNT}}, }, quantity: 1, }], line_items: [{ price_data: { product_data: { name: "{{PRICE_DATA_NAME}}", }, currency: "{{PRICE_DATA_CURRENCY}}", unit_amount: {{PRICE_DATA_UNIT_AMOUNT}}, recurring: { interval: "{{PRICE_DATA_INTERVAL}}", interval_count: {{PRICE_DATA_INTERVAL_COUNT}}, }, }, quantity: 1, }], mode: {{CHECKOUT_MODE}}, return_url: `${YOUR_DOMAIN}/complete?session_id={CHECKOUT_SESSION_ID}`, return_url: `${YOUR_DOMAIN}/complete.html?session_id={CHECKOUT_SESSION_ID}`, automatic_tax: {enabled: true}, }); res.send({ clientSecret: session.client_secret }); app.get("/session-status", async (req, res) => { const session = await stripe.checkout.sessions.retrieve(req.query.session_id, {expand: ["payment_intent"]}); res.send({ status: session.status, payment_status: session.payment_status, payment_intent_id: session.payment_intent.id, payment_intent_status: session.payment_intent.status }); }); { "name": "stripe-sample", "version": "1.0.0", "description": "A sample Stripe implementation", "main": "server.js", "scripts": { "start": "node server.js" }, "author": "stripe-samples", "license": "ISC", "dependencies": { "express": "^4.17.1", "stripe": "^21.0.1" } } { "name": "stripe-sample", "version": "0.1.0", "dependencies": { "@stripe/react-stripe-js": "^3.7.0", "@stripe/stripe-js": "^7.3.0", "express": "^4.17.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "^3.4.0", "stripe": "21.0.1" }, "devDependencies": { "concurrently": "4.1.2" }, "homepage": "http://localhost:3000/checkout", "proxy": "http://localhost:4242", "scripts": { "start-client": "react-scripts start", "start-server": "node server.js", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", "start": "concurrently \"yarn start-client\" \"yarn start-server\"" }, "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" ] } } \# 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 = '<>' Stripe.api_version = '2026-03-25.dahlia' YOUR_DOMAIN = 'http://localhost:4242' YOUR_DOMAIN = 'http://localhost:3000' session = Stripe::Checkout::Session.create({ ui_mode: 'elements', customer_email: 'customer@example.com', billing_address_collection: 'required', shipping_address_collection: { allowed_countries: ['US', 'CA'], }, line_items: [{ \# Provide the exact Price ID (for example, price_1234) of the product you want to sell price: '{{PRICE_ID}}', quantity: 1, }], line_items: [{ price_data: { product_data: { name: '{{PRICE_DATA_NAME}}', }, currency: '{{PRICE_DATA_CURRENCY}}', unit_amount: {{PRICE_DATA_UNIT_AMOUNT}}, }, quantity: 1, }], line_items: [{ price_data: { product_data: { name: '{{PRICE_DATA_NAME}}', }, currency: '{{PRICE_DATA_CURRENCY}}', unit_amount: {{PRICE_DATA_UNIT_AMOUNT}}, recurring: { interval: '{{PRICE_DATA_INTERVAL}}', interval_count: {{PRICE_DATA_INTERVAL_COUNT}}, }, }, quantity: 1, }], mode: {{CHECKOUT_MODE}}, return_url: YOUR_DOMAIN + '/complete.html?session_id={CHECKOUT_SESSION_ID}', return_url: YOUR_DOMAIN + '/complete?session_id={CHECKOUT_SESSION_ID}', automatic_tax: {enabled: true}, }) { clientSecret: session.client_secret }.to_json get '/session-status' do session = Stripe::Checkout::Session.retrieve({id: params[:session_id], expand: ["payment_intent"]}) { status: session.status, payment_status: session.payment_status, payment_intent_id: session.payment_intent.id, payment_intent_status: session.payment_intent.status }.to_json end import stripe \# 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 = '<>' stripe.api_version = '2026-03-25.dahlia' YOUR_DOMAIN = 'http://localhost:4242' YOUR_DOMAIN = 'http://localhost:3000' session = stripe.checkout.Session.create( ui_mode = 'elements', customer_email='customer@example.com', billing_address_collection='auto', shipping_address_collection={ 'allowed_countries': ['US', 'CA'], }, line_items=[ { \# Provide the exact Price ID (for example, price_1234) of the product you want to sell 'price': '{{PRICE_ID}}', 'quantity': 1, }, ], line_items=[ { 'price_data': { 'product_data': { 'name': '{{PRICE_DATA_NAME}}', }, 'currency': '{{PRICE_DATA_CURRENCY}}', 'unit_amount': {{PRICE_DATA_UNIT_AMOUNT}}, }, 'quantity': 1, }, ], line_items=[ { 'price_data': { 'product_data': { 'name': '{{PRICE_DATA_NAME}}', }, 'currency': '{{PRICE_DATA_CURRENCY}}', 'unit_amount': {{PRICE_DATA_UNIT_AMOUNT}}, 'recurring': { 'interval': '{{PRICE_DATA_INTERVAL}}', 'interval_count': {{PRICE_DATA_INTERVAL_COUNT}}, }, }, 'quantity': 1, }, ], mode={{CHECKOUT_MODE}}, return_url=YOUR_DOMAIN + '/complete.html?session_id={CHECKOUT_SESSION_ID}', return_url=YOUR_DOMAIN + '/complete?session_id={CHECKOUT_SESSION_ID}', automatic_tax={'enabled': True}, ) return jsonify(clientSecret=session.client_secret) @app.route('/session-status', methods=['GET']) def session_status(): session = stripe.checkout.Session.retrieve(request.args.get('session_id'), expand=["payment_intent"]) return jsonify(status=session.status, payment_status=session.payment_status, payment_intent_id=session.payment_intent.id, payment_intent_status=session.payment_intent.status) certifi==2026.1.4 chardet==5.2.0 click==8.3.1 Flask==3.1.2 idna==3.11 itsdangerous==2.2.0 Jinja2==3.1.6 MarkupSafe==3.0.3 requests==2.32.5 stripe==15.0.0 toml==0.10.2 Werkzeug==3.1.5 $stripe = new \Stripe\StripeClient([ "api_key" => $stripeSecretKey, "stripe_version" => "2026-03-25.dahlia" ]); $YOUR_DOMAIN = 'http://localhost:4242'; $YOUR_DOMAIN = 'http://localhost:3000'; $checkout_session = $stripe->checkout->sessions->create([ 'ui_mode' => 'elements', 'customer_email' => 'customer@example.com', 'billing_address_collection' => 'required', 'shipping_address_collection' => [ 'allowed_countries' => ['US', 'CA'], ], 'line_items' => [[ \# Provide the exact Price ID (for example, price_1234) of the product you want to sell 'price' => '{{PRICE_ID}}', 'quantity' => 1, ]], 'line_items' => [[ 'price_data' => [ 'product_data' => [ 'name' => '{{PRICE_DATA_NAME}}', ], 'currency' => '{{PRICE_DATA_CURRENCY}}', 'unit_amount' => {{PRICE_DATA_UNIT_AMOUNT}}, ], 'quantity' => 1, ]], 'line_items' => [[ 'price_data' => [ 'product_data' => [ 'name' => '{{PRICE_DATA_NAME}}', ], 'currency' => '{{PRICE_DATA_CURRENCY}}', 'unit_amount' => {{PRICE_DATA_UNIT_AMOUNT}}, 'recurring' => [ 'interval' => '{{PRICE_DATA_INTERVAL}}', 'interval_count' => {{PRICE_DATA_INTERVAL_COUNT}}, ], ], 'quantity' => 1, ]], 'mode' => {{CHECKOUT_MODE}}, 'return_url' => $YOUR_DOMAIN . '/complete.html?session_id={CHECKOUT_SESSION_ID}', 'return_url' => $YOUR_DOMAIN . '/complete?session_id={CHECKOUT_SESSION_ID}', 'automatic_tax' => [ 'enabled' => true, ], ]); echo json_encode(array('clientSecret' => $checkout_session->client_secret)); try { // retrieve JSON from POST body $jsonStr = file_get_contents('php://input'); $jsonObj = json_decode($jsonStr); $session = $stripe->checkout->sessions->retrieve($jsonObj->session_id, ['expand' => ['payment_intent']]); echo json_encode(['status' => $session->status, 'payment_status' => $session->payment_status, 'payment_intent_id' => $session->payment_intent->id, 'payment_intent_status' => $session->payment_intent->status]); http_response_code(200); } catch (Error $e) { http_response_code(500); echo json_encode(['error' => $e->getMessage()]); } $stripeSecretKey = '<>'; // 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. services.AddSingleton(new StripeClient("<>")); var domain = "http://localhost:4242"; var domain = "http://localhost:3000"; UiMode = "elements", CustomerEmail = "customer@example.com", BillingAddressCollection = "auto", ShippingAddressCollection = new SessionShippingAddressCollectionOptions { AllowedCountries = new List { "US", "CA", }, }, LineItems = new List { new SessionLineItemOptions { // Provide the exact Price ID (for example, price_1234) of the product you want to sell Price = "{{PRICE_ID}}", Quantity = 1, }, }, LineItems = new List { new SessionLineItemOptions { PriceData = new SessionLineItemPriceDataOptions { ProductData = new SessionLineItemPriceDataProductDataOptions { Name = "{{PRICE_DATA_NAME}}", }, Currency = "{{PRICE_DATA_CURRENCY}}", UnitAmount = {{PRICE_DATA_UNIT_AMOUNT}}, }, Quantity = 1, }, }, LineItems = new List { new SessionLineItemOptions { PriceData = new SessionLineItemPriceDataOptions { ProductData = new SessionLineItemPriceDataProductDataOptions { Name = "{{PRICE_DATA_NAME}}", }, Currency = "{{PRICE_DATA_CURRENCY}}", UnitAmount = {{PRICE_DATA_UNIT_AMOUNT}}, Recurring = new SessionLineItemPriceDataRecurringOptions { Interval = "{{PRICE_DATA_INTERVAL}}", IntervalCount = {{PRICE_DATA_INTERVAL_COUNT}}, }, }, Quantity = 1, }, }, Mode = {{CHECKOUT_MODE}}, ReturnUrl = domain + "/complete.html?session_id={CHECKOUT_SESSION_ID}", ReturnUrl = domain + "/complete?session_id={CHECKOUT_SESSION_ID}", AutomaticTax = new SessionAutomaticTaxOptions { Enabled = true }, Session session = _client.V1.Checkout.Sessions.Create(options); return Json(new {clientSecret = session.ClientSecret}); [Route("session-status")] [ApiController] public class SessionStatusController : Controller { private readonly StripeClient _client; public SessionStatusController(StripeClient client) { _client = client; } [HttpGet] public ActionResult SessionStatus([FromQuery] string session_id) { var options = new SessionGetOptions(); options.AddExpand("payment_intent"); Session session = _client.V1.Checkout.Sessions.Get(session_id, options); return Json(new {status = session.Status, payment_status = session.PaymentStatus, payment_intent_id = session.PaymentIntent.Id, payment_intent_status = session.PaymentIntent.Status}); } } "github.com/stripe/stripe-go/v85" sc := stripe.NewClient("<>") domain := "http://localhost:4242" domain := "http://localhost:3000" params := &stripe.CheckoutSessionCreateParams{ UIMode: stripe.String("elements"), ReturnURL: stripe.String(domain + "/complete.html?session_id={CHECKOUT_SESSION_ID}"), ReturnURL: stripe.String(domain + "/complete?session_id={CHECKOUT_SESSION_ID}"), CustomerEmail: stripe.String("customer@example.com"), BillingAddressCollection: stripe.String("auto"), ShippingAddressCollection: &stripe.CheckoutSessionCreateShippingAddressCollectionParams{ AllowedCountries: stripe.StringSlice([]string{ "US", "CA", }), }, LineItems: []*stripe.CheckoutSessionCreateLineItemParams{ { // Provide the exact Price ID (for example, price_1234) of the product you want to sell Price: stripe.String("{{PRICE_ID}}"), Quantity: stripe.Int64(1), }, }, LineItems: []*stripe.CheckoutSessionCreateLineItemParams{ { PriceData: &stripe.CheckoutSessionCreateLineItemPriceDataParams{ ProductData: &stripe.CheckoutSessionCreateLineItemPriceDataProductDataParams{ Name: stripe.String("{{PRICE_DATA_NAME}}"), }, Currency: stripe.String("{{PRICE_DATA_CURRENCY}}"), UnitAmount: stripe.Int64({{PRICE_DATA_UNIT_AMOUNT}}), }, Quantity: stripe.Int64(1), }, }, LineItems: []*stripe.CheckoutSessionCreateLineItemParams{ { PriceData: &stripe.CheckoutSessionCreateLineItemPriceDataParams{ ProductData: &stripe.CheckoutSessionCreateLineItemPriceDataProductDataParams{ Name: stripe.String("{{PRICE_DATA_NAME}}"), }, Currency: stripe.String("{{PRICE_DATA_CURRENCY}}"), UnitAmount: stripe.Int64({{PRICE_DATA_UNIT_AMOUNT}}), Recurring: &stripe.CheckoutSessionCreateLineItemPriceDataRecurringParams{ Interval: stripe.String("{{PRICE_DATA_INTERVAL}}"), IntervalCount: stripe.Int64({{PRICE_DATA_INTERVAL_COUNT}}), }, }, Quantity: stripe.Int64(1), }, }, Mode: {{CHECKOUT_MODE}}, AutomaticTax: &stripe.CheckoutSessionCreateAutomaticTaxParams{Enabled: stripe.Bool(true)}, } s, err := sc.V1CheckoutSessions.Create(context.TODO(), params) if err != nil { log.Printf("sc.V1CheckoutSessions.Create: %v", err) } writeJSON(w, struct { ClientSecret string `json:"clientSecret"` }{ ClientSecret: s.ClientSecret, }) func retrieveCheckoutSession(sc *stripe.Client, w http.ResponseWriter, r *http.Request) { params := &stripe.CheckoutSessionRetrieveParams{} params.AddExpand("payment_intent") s, _ := sc.V1CheckoutSessions.Retrieve(context.TODO(), r.URL.Query().Get("session_id"), params) writeJSON(w, struct { Status string `json:"status"` PaymentStatus string `json:"payment_status"` PaymentIntentId string `json:"payment_intent_id"` PaymentIntentStatus string `json:"payment_intent_status"` }{ Status: string(s.Status), PaymentStatus: string(s.PaymentStatus), PaymentIntentId: string(s.PaymentIntent.ID), PaymentIntentStatus: string(s.PaymentIntent.Status), }) } require github.com/stripe/stripe-go/v85 v85.0.0 // 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.apiKey = "<>"; String YOUR_DOMAIN = "http://localhost:4242"; String YOUR_DOMAIN = "http://localhost:3000"; SessionCreateParams params = SessionCreateParams.builder() .setUiMode(SessionCreateParams.UiMode.ELEMENTS) .setCustomerEmail("customer@example.com") .setBillingAddressCollection(SessionCreateParams.BillingAddressCollection.REQUIRED) .setShippingAddressCollection( SessionCreateParams.ShippingAddressCollection.builder() .addAllowedCountry(SessionCreateParams.ShippingAddressCollection.AllowedCountry.CA) .addAllowedCountry(SessionCreateParams.ShippingAddressCollection.AllowedCountry.US) .build()) .setMode({{CHECKOUT_MODE}}) .setReturnUrl(YOUR_DOMAIN + "/complete?session_id={CHECKOUT_SESSION_ID}") .setReturnUrl(YOUR_DOMAIN + "/complete.html?session_id={CHECKOUT_SESSION_ID}") .setAutomaticTax( SessionCreateParams.AutomaticTax.builder() .setEnabled(true) .build()) .addLineItem( SessionCreateParams.LineItem.builder() .setQuantity(1L) // Provide the exact Price ID (for example, price_1234) of the product you want to sell .setPrice("{{PRICE_ID}}") .build()) .addLineItem( SessionCreateParams.LineItem.builder() .setQuantity(1L) .setPriceData( SessionCreateParams.LineItem.PriceData.builder() .setProductData( SessionCreateParams.LineItem.PriceData.ProductData.builder() .setName("{{PRICE_DATA_NAME}}") .build()) .setCurrency("{{PRICE_DATA_CURRENCY}}") .setUnitAmount({{PRICE_DATA_UNIT_AMOUNT}}L) .build()) .build()) .addLineItem( SessionCreateParams.LineItem.builder() .setQuantity(1L) .setPriceData( SessionCreateParams.LineItem.PriceData.builder() .setProductData( SessionCreateParams.LineItem.PriceData.ProductData.builder() .setName("{{PRICE_DATA_NAME}}") .build()) .setCurrency("{{PRICE_DATA_CURRENCY}}") .setUnitAmount({{PRICE_DATA_UNIT_AMOUNT}}L) .setRecurring( SessionCreateParams.LineItem.PriceData.Recurring.builder() .setInterval(SessionCreateParams.LineItem.PriceData.Recurring.Interval.{{PRICE_DATA_INTERVAL}}) .setIntervalCount({{PRICE_DATA_INTERVAL_COUNT}}L) .build()) .build()) .build()) .build(); Map map = new HashMap(); map.put("clientSecret", session.getRawJsonObject().getAsJsonPrimitive("client_secret").getAsString()); return map; get("/session-status", (request, response) -> { RequestOptions options = RequestOptions.builder().build(); SessionRetrieveParams params = SessionRetrieveParams.builder().addExpand("payment_intent").build(); Session session = Session.retrieve(request.queryParams("session_id"), params, options); Map map = new HashMap(); map.put("status", session.getRawJsonObject().getAsJsonPrimitive("status").getAsString()); map.put("payment_status", session.getRawJsonObject().getAsJsonPrimitive("payment_status").getAsString()); map.put("payment_intent_id", session.getRawJsonObject().getAsJsonObject("payment_intent").getAsJsonPrimitive("id").getAsString()); map.put("payment_intent_status", session.getRawJsonObject().getAsJsonObject("payment_intent").getAsJsonPrimitive("status").getAsString()); return map; }, gson::toJson);

Billing Address

Billing Address

Shipping Address

Payment

const stripe = Stripe("<>"); const emailInput = document.getElementById("email"); const emailErrors = document.getElementById("email-errors"); const validateEmail = async (email) => { const updateResult = await actions.updateEmail(email); const isValid = updateResult.type !== "error"; return { isValid, message: !isValid ? updateResult.error.message : null }; }; const promise = fetch("/create-checkout-session", { method: "POST", headers: { "Content-Type": "application/json" }, }) .then((r) => r.json()) .then((r) => r.clientSecret); const promise = fetch('/create.php', { method: 'POST', headers: {'Content-Type': 'application/json'}, }) .then((r) => r.json()) .then((r) => r.clientSecret); const appearance = { {{APPEARANCE}} }; checkout = stripe.initCheckoutElementsSdk({ clientSecret: promise, elementsOptions: { appearance }, adaptivePricing: { allowed: true }, }); checkout.on('change', (session) => { // Handle changes to the checkout session document.getElementById('submit').disabled = !session.canConfirm; document.querySelector("#button-text").textContent = `Pay ${ session.total.total.amount } now`; }); emailInput.addEventListener("input", () => { // Clear any validation errors emailErrors.textContent = ""; emailInput.classList.remove("error"); }); emailInput.addEventListener("blur", async () => { const newEmail = emailInput.value; if (!newEmail) { return; } const { isValid, message } = await validateEmail(newEmail); if (!isValid) { emailInput.classList.add("error"); emailErrors.textContent = message; } }); const paymentElement = checkout.createPaymentElement(); paymentElement.mount("#payment-element"); const billingAddressElement = checkout.createBillingAddressElement(); billingAddressElement.mount("#billing-address-element"); const billingAddressElement = checkout.createBillingAddressElement(); billingAddressElement.mount("#billing-address-element"); const shippingAddressElement = checkout.createShippingAddressElement(); shippingAddressElement.mount("#shipping-address-element"); const currencySelectorElement = checkout.createCurrencySelectorElement(); currencySelectorElement.mount("#currency-selector-element"); async function handleSubmit(e) { e.preventDefault(); setLoading(true); const email = document.getElementById("email").value; const { isValid, message } = await validateEmail(email); if (!isValid) { emailInput.classList.add("error"); emailErrors.textContent = message; showMessage(message); setLoading(false); return; } const { error } = await actions.confirm(); // This point will only be reached if there is an immediate error when // confirming the payment. Otherwise, your customer will be redirected to // your `return_url`. For some payment methods like iDEAL, your customer will // be redirected to an intermediate site first to authorize the payment, then // redirected to the `return_url`. showMessage(error.message); setLoading(false); } const queryString = window.location.search; const urlParams = new URLSearchParams(queryString); const sessionId = urlParams.get("session_id"); if (!sessionId) { console.log("No session ID found"); setErrorState(); return; } const response = await fetch(`/session-status?session_id=${sessionId}`); const response = await fetch("/status.php", { headers: { Accept: "application/json", "Content-Type": "application/json", }, method: "POST", body: JSON.stringify({ session_id: sessionId }), }); const session = await response.json(); setSessionDetails(session); { "name": "stripe-sample", "version": "0.1.0", "dependencies": { "@stripe/react-stripe-js": "^6.0.0", "@stripe/stripe-js": "^9.0.0", "express": "^4.17.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "^5.0.1", "react-router-dom": "^6.16.0", "stripe": "^8.202.0" }, "devDependencies": { "concurrently": "4.1.2" }, "homepage": "http://localhost:3000/checkout", "proxy": "http://localhost:4242", "scripts": { "start-client": "react-scripts start", "start-server": "node server.js", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", "start": "concurrently \"yarn start-client\" \"yarn start-server\"" }, "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" ] } } { "name": "client", "version": "0.1.0", "private": true, "dependencies": { "@stripe/react-stripe-js": "^6.0.0", "@stripe/stripe-js": "^9.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "^5.0.1", "react-router-dom": "^6.16.0" }, "homepage": "http://localhost:3000/checkout", "proxy": "http://127.0.0.1:4242", "scripts": { "start": "react-scripts start", "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, { useMemo } from "react"; import {loadStripe} from '@stripe/stripe-js'; import { CheckoutElementsProvider } from '@stripe/react-stripe-js/checkout'; // Make sure to call `loadStripe` outside of a component’s render to avoid // recreating the `Stripe` object on every render. // This is a public sample test API key. // Don’t submit any personally identifiable information in requests made with this key. // Sign in to see your own test publishable API key embedded in code samples. const stripePromise = loadStripe("<>"); const clientSecret = useMemo(() => { return fetch('/create-checkout-session', { method: 'POST', }) .then((res) => res.json()) .then((data) => data.clientSecret); }, []); const clientSecret = useMemo(() => { return fetch('/create.php', { method: 'POST', }) .then((res) => res.json()) .then((data) => data.clientSecret); }, []); const appearance = { {{APPEARANCE}} }; } /> } /> BillingAddressElement, BillingAddressElement, ShippingAddressElement, CurrencySelectorElement, const validateEmail = async (email, checkout) => { const updateResult = await checkout.updateEmail(email); const isValid = updateResult.type !== "error"; return { isValid, message: !isValid ? updateResult.error.message : null }; } const EmailInput = ({ checkout, email, setEmail, error, setError }) => { const handleBlur = async () => { if (!email) { return; } const { isValid, message } = await validateEmail(email, checkout); if (!isValid) { setError(message); } }; const handleChange = (e) => { setError(null); setEmail(e.target.value); }; return ( <> {error &&
{error}
} ); }; const [email, setEmail] = useState(''); const [emailError, setEmailError] = useState(null); const [message, setMessage] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); const checkoutState = useCheckout(); if (checkoutState.type === 'loading') { return (
Loading...
); } if (checkoutState.type === 'error') { return (
Error: {checkoutState.error.message}
); } const handleSubmit = async (e) => { e.preventDefault(); const {checkout} = checkoutState; setIsSubmitting(true); const { isValid, message } = await validateEmail(email, checkout); if (!isValid) { setEmailError(message); setMessage(message); setIsSubmitting(false); return; } const confirmResult = await checkout.confirm(); // This point will only be reached if there is an immediate error when // confirming the payment. Otherwise, your customer will be redirected to // your `return_url`. For some payment methods like iDEAL, your customer will // be redirected to an intermediate site first to authorize the payment, then // redirected to the `return_url`. if (confirmResult.type === 'error') { setMessage(confirmResult.error.message); } setIsSubmitting(false); };

Billing Address

Billing Address

Shipping Address

`Pay ${checkoutState.checkout.total.total.amount} now` const [status, setStatus] = useState(null); const [paymentIntentId, setPaymentIntentId] = useState(''); const [paymentStatus, setPaymentStatus] = useState(''); const [paymentIntentStatus, setPaymentIntentStatus] = useState(''); const [iconColor, setIconColor] = useState(''); const [icon, setIcon] = useState(''); const [text, setText] = useState(''); useEffect(() => { const SuccessIcon = ; const ErrorIcon = ; const queryString = window.location.search; const urlParams = new URLSearchParams(queryString); const sessionId = urlParams.get('session_id'); fetch("/status.php", { headers: { Accept: "application/json", "Content-Type": "application/json", }, method: "POST", body: JSON.stringify({ session_id: sessionId }), }) fetch(`/session-status?session_id=${sessionId}`) .then((res) => res.json()) .then((data) => { setStatus(data.status); setPaymentIntentId(data.payment_intent_id); setPaymentStatus(data.payment_status); setPaymentIntentStatus(data.payment_intent_status); if (data.status === 'complete') { setIconColor('#30B130'); setIcon(SuccessIcon); setText('Payment succeeded'); } else { setIconColor('#DF1B41'); setIcon(ErrorIcon); setText('Something went wrong, please try again.'); } }); }, []); return (
{icon}

{text}

Payment Intent ID {paymentIntentId}
Status {status}
Payment Status {paymentStatus}
Payment Intent Status {paymentIntentStatus}
View details Test another payment
) \## Set Price ID In the back end code, replace `{{PRICE_ID}}` with a Price ID (`price_xxx`) that you created. 1. Build the server ~~~ pip3 install -r requirements.txt ~~~ 1. Build the server ~~~ bundle install ~~~ 1. Build the server ~~~ composer install ~~~ 1. Build the server ~~~ dotnet restore ~~~ 1. Build the server ~~~ mvn package ~~~ 2. Run the server ~~~ export FLASK_APP=server.py python3 -m flask run --port=4242 ~~~ 2. Run the server ~~~ ruby server.rb -o 0.0.0.0 ~~~ 2. Run the server ~~~ php -S 127.0.0.1:4242 --docroot=public ~~~ 2. Run the server ~~~ dotnet run ~~~ 2. Run the server ~~~ java -cp target/sample-jar-with-dependencies.jar com.stripe.sample.Server ~~~ 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) 3. Go to [http://localhost:4242/checkout.html](http://localhost:4242/checkout.html) 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) 3. Go to [http://localhost:4242/checkout.html](http://localhost:4242/checkout.html) 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) 3. Go to [http://localhost:4242/checkout.html](http://localhost:4242/checkout.html) 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) 3. Go to [http://localhost:4242/checkout.html](http://localhost:4242/checkout.html) 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) 3. Go to [http://localhost:4242/checkout.html](http://localhost:4242/checkout.html) 1. Run the server ~~~ go run server.go ~~~ 2. Build the client app ~~~ npm install ~~~ 3. Run the client app ~~~ npm start ~~~ 4. Go to [http://localhost:3000/checkout](http://localhost:3000/checkout) 1. Run the server ~~~ go run server.go ~~~ 2. Go to [http://localhost:4242/checkout.html](http://localhost:4242/checkout.html) 1. Build the application ~~~ npm install ~~~ 2. Run the application ~~~ npm start ~~~ 3. Go to [http://localhost:3000/checkout](http://localhost:3000/checkout) 1. Build the server ~~~ npm install ~~~ 2. Run the server ~~~ npm start ~~~ 3. Go to [http://localhost:4242/checkout.html](http://localhost:4242/checkout.html) \### Development 1. Build the application ~~~shell $ npm install ~~~ 2. _Optional_: download and run the [Stripe CLI](https://stripe.com/docs/stripe-cli) ~~~shell $ stripe listen --forward-to localhost:3000/api/webhooks ~~~ 3. Run the application ~~~shell $ STRIPE_WEBHOOK_SECRET=$(stripe listen --print-secret) npm run dev ~~~ 4. Go to [localhost:3000](http://localhost:3000) ### Production 1. Build the application ~~~shell $ npm install $ npm build ~~~ 2. Run the application ~~~shell $ npm start ~~~ ## Next steps #### [Dynamically update line items](https://docs.stripe.com/payments/checkout/dynamically-update-line-items.md) Learn how to dynamically modify line items in your Checkout Session as users add, remove, or change products. #### [Fulfill orders](https://docs.stripe.com/checkout/fulfillment.md?payment-ui=embedded-components) Set up a webhook to fulfill orders after a payment succeeds. Webhooks are the most reliable way to handle business-critical events. #### [Receive payouts](https://docs.stripe.com/payouts.md) Learn how to move funds out of your Stripe account into your bank account. #### [Refund and cancel payments](https://docs.stripe.com/refunds.md) Handle requests for refunds by using the Stripe API or Dashboard. #### [Customer management](https://docs.stripe.com/customer-management.md) Let your customers self-manage their payment details, invoices, and subscriptions. #### [One-click payment buttons](https://docs.stripe.com/elements/express-checkout-element/accept-a-payment.md?payment-ui=embedded-components#create-and-mount) Use the Express Checkout Element to accept payments through one-click payment method buttons.