# checkout-one-time-payments: eight server implementations of the same Stripe Checkout flow

> This Stripe sample shows how to collect a one-time payment with Checkout, with server implementations in eight languages behind one set of routes and two client choices, HTML with vanilla JavaScript or React. This looks at what the sample actually gives you, and what it leaves to you.

**stripe-samples/checkout-one-time-payments** — Use Checkout to quickly collect one-time payments.

- Repository: https://github.com/stripe-samples/checkout-one-time-payments
- Website: https://checkout.stripe.dev/?mode=payment
- Stars: 1,063 · Forks: 538
- Language: CSS
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/stripe-samples-checkout-one-time-payments

## The value is the form you do not have to build

The sample shows how to integrate with Stripe Checkout, and the readme opens by naming the work you would otherwise do: building a payment form UI from scratch is difficult, and input field validation, error message handling and localization are just a few things to think about when designing a simple checkout flow.

That is the argument for a hosted checkout page in one sentence, and it is a good one. The card form, the field validation, the localised error messages, the wallet buttons, the 3D Secure challenge, all of that is a large surface area that most teams should not be building.

The mechanism is short. Once the customer is ready to pay, you use Stripe.js to redirect them to the URL of your Stripe hosted payment page. The flow is therefore: your server creates a Checkout session for a price, hands the session URL to the client, the client redirects to Stripe, the customer pays on Stripe's page, and Stripe redirects back to your site. The `DOMAIN` variable in the configuration is the domain of your website, where Checkout will redirect back to after the customer completes the payment.

The audience is a developer integrating payments for the first time or the second time, and the deliverable is a working example rather than a library. There is no release history in the repository and no package to install, which is what a sample should look like.

## Eight servers, two clients, one set of routes

The sample includes 8 server implementations in Java, JavaScript on Node, PHP, PHP-Slim, Python, Ruby, .NET and Go. All servers implement the same routes for the client to communicate with, and there is an HTML with vanilla JavaScript client as well as a React client implementation.

That symmetry is the point of the repository. The thing being demonstrated is the integration, not the language, and the identical routes mean you can read the same flow in whichever stack you already run. The checkout logic, the session creation, the webhook handling, all of it appears eight times, and a reader can compare them.

The repository layout follows from that. There is a `server/` directory holding the eight implementations, a `client/` directory with the two client choices, `demo-gifs/` with the animated demos, and a `spec/` directory with an `.rspec` file and a `Gemfile`, so the Ruby server is the one with an RSpec test suite. There is also `main.tf`, a Terraform file, and a `.cli.json` that is what makes the repository clonable and configurable through the Stripe CLI.

The client split is also a genuine choice rather than a token one. The HTML and vanilla JavaScript client has no build step, which makes it the fastest path to a running demo, while the React client shows how to integrate the same flow into an application with a modern front end. The two demos in the readme, USD Cards and EUR Cards with iDEAL, and MYR Cards with FPX, are rendered from the same pages with different payment method configuration.

## The Stripe CLI clones and configures the sample for you

The recommended way to get the sample running is the Stripe CLI, which the readme calls the fastest way to clone and configure a sample to run locally.

```sh
stripe samples create checkout-one-time-payments
```

The CLI walks you through picking your integration type, your server language and your client language, and it configures your `.env` file with your Stripe API keys. The CLI is described as useful for cloning samples and for locally testing webhooks and Stripe integrations, and the installation steps are linked for people who do not have it yet.

The manual path is documented too, and it is the one to follow if you want to read the configuration before you run anything. You clone the repository:

```sh
git clone https://github.com/stripe-samples/checkout-one-time-payments
```

and copy the example environment file into the server directory you intend to use:

```sh
cp .env.example server/node/.env
```

The copy is per server directory, which matters because the eight server implementations each expect their own `.env` with a `STATIC_DIR` pointing back at the shared client directory.

## What the environment file actually holds

The `.env.example` at the root is the complete configuration surface, and it is short enough to take in as a whole.

```
STRIPE_PUBLISHABLE_KEY=pk_test...
STRIPE_SECRET_KEY=sk_test...
STRIPE_WEBHOOK_SECRET=whsec_1234...
STATIC_DIR=../../client/html
PRICE=price_abc123...
DOMAIN=http://localhost:4242
PAYMENT_METHOD_TYPES="card"
```

The two API keys come from the developer dashboard, and the readme is explicit that you need a Stripe account to run the demo. `STRIPE_WEBHOOK_SECRET` is required to run the webhook, with the comment pointing at the readme for using the Stripe CLI to set it up. `STATIC_DIR` tells the server where the client files are located and does not need to be modified unless you move the server files. `PRICE` is the identifier of the price you will create in the next step, and `DOMAIN` is where Checkout returns the customer after payment, defaulting to `http://localhost:4242`.

`PAYMENT_METHOD_TYPES` is where the demo matrix comes from. The example ships with `card`, and the commented alternatives show the pattern: `card,ideal` requires `CURRENCY=eur`, and `card,fpx` requires `CURRENCY=myr`. The readme notes that some payment methods support only a subset of currencies, which is a good thing to know before you offer a local payment method in a market where it does not work.

## A Price is required, and the tax setup lives in the dashboard

The sample requires a Price, and the readme explains that you can create Products and Prices in the Dashboard or with the API. The quickest route is the CLI:

```sh
stripe prices create --unit-amount 500 --currency usd -d "product_data[name]=demo"
```

A Price has a unit amount and a currency, and the CLI returns a JSON object that shows the shape of what you will store: an `id` such as `price_1Hh1ZeCZ6qsJgndJaX9fauRl`, a `type` of `one_time`, a `unit_amount` of 500, a `currency` of `usd`, and `livemode` of false. The readme then tells you to set that identifier in the environment file:

```sh
PRICE=price_1Hh1ZeCZ6qsJgndJaX9fauRl
```

The Stripe Tax section adds the part that trips people up. The tax code `txcd_10000000`, described as General, Electronically Supplied Services, has to be set on the product, and it cannot be guessed by the API, so the product is created with the code first:

```sh
stripe products create \
  --name="demo" \
  --tax-code="txcd_10000000"
```

and the price is then created with a tax behaviour of `exclusive`, the example's choice, along with the product id. The readme is clear that the tax behaviour can be `inclusive` or `exclusive`, and that Stripe Tax has to be set up in the dashboard before any of this works, because Stripe needs to know what kind of product is being sold.

## Test cards, the 3D Secure path, and the demo gallery

The demo runs in test mode, and the readme gives the two card numbers you need. `4242424242424242` works as a test card number with any CVC and a future expiration date, which is the card that succeeds. The second one, `4000002500003155`, triggers a 3D Secure challenge flow, which is the card that exercises the authentication path.

The feature list is the argument for the hosted page, and it is worth reading as a checklist of things you would otherwise build. There is localization in different languages, built-in support for Apple Pay and Google Pay, built-in dynamic 3D Secure described as ready for SCA, and support for various payment methods.

Three Checkout capabilities are called out in a table. The prebuilt checkout page is a payment page customizable with your business name and logo. Dynamic checkout amounts let you define product amounts at runtime rather than relying on predefined Prices, which is what the price setup in the previous step is for. And capture payments later lets you split the capture and authorization steps, to place a hold on the card and charge later, which is the mechanism a subscription-like flow or a manual fulfilment flow needs.

The last section of the readme tells you to pick your server language and follow the instructions in that server's directory, which is where the eight implementations diverge.

## Where this sample is the wrong starting point

Three limits are clear.

The first is that the payment page is not yours. Checkout is a Stripe hosted page, and the readme says so directly, so a team whose product requirement is a bespoke payment experience, with the card fields embedded in your own design, is looking at a different integration. The prebuilt page is configurable with your name and logo, which is not the same thing as a custom form.

The second is that this is a sample, and it is configured for local development. The domain is `http://localhost:4242`, the keys are `pk_test` and `sk_test` placeholders, and the webhook secret in the example file is a dummy. There is no persistence, no order record, no retry logic, and no reconciliation, because a sample that demonstrated those would be a product.

The third is the pricing model, and it is a design constraint rather than a defect. The sample is built around a Price with a unit amount and a currency, so a variable amount basket, a metered charge or a multi-item order needs a different object model, and the dynamic checkout amount capability is what covers the simpler version of that.

For context on the state of the repository, the last push was on 2026-06-08 and there are no GitHub releases, since a sample is versioned by the sample name rather than by tags. The licence is MIT, with the licence file at the root, and the project carries a code of conduct and a contributing guide.

## Conclusion

This sample fits a developer who wants a working Stripe Checkout integration in their own stack to read, and who would rather start from a working server than from a snippet in the documentation. It does not fit a team that needs a custom payment page, because the page that takes the card is Stripe's, and it is not a production application, with a `.env` file pointing at localhost and a webhook secret that is a placeholder. Before you build on it, read the price setup step, since the sample requires a Price object, and check the tax code and tax behaviour section if you sell across regions, because that configuration lives outside the code.

## FAQ

### How do I run the Stripe Checkout one-time payments sample locally?

The fastest route is the Stripe CLI with `stripe samples create checkout-one-time-payments`, which walks you through choosing the server and client languages and configures your .env file. Manually, you can clone the repository and copy .env.example into the server directory you want, such as `cp .env.example server/node/.env`.

### Which test card numbers does the sample use?

Use `4242424242424242` with any CVC and a future expiration date for a successful payment, and `4000002500003155` to trigger a 3D Secure challenge flow. The demo runs in test mode.

### What environment variables does the sample need?

STRIPE_PUBLISHABLE_KEY and STRIPE_SECRET_KEY from the developer dashboard, STRIPE_WEBHOOK_SECRET to run the webhook, PRICE for the price you created, DOMAIN as the return URL after payment, STATIC_DIR pointing at the client files, and PAYMENT_METHOD_TYPES listing the methods the store offers.

### Does the sample support Stripe Tax?

Yes, as an optional step. You create the product with a tax code, `txcd_10000000` for General, Electronically Supplied Services, then create the price with a tax behaviour of `inclusive` or `exclusive`, after setting up Stripe Tax in the dashboard.

### Which server languages does the sample cover?

Eight: Java, JavaScript on Node, PHP, PHP-Slim, Python, Ruby, .NET and Go. All of them implement the same routes, and the client side is available as HTML with vanilla JavaScript or as React.

## Sources

- [Issues](https://github.com/stripe-samples/checkout-one-time-payments/issues)
- [License: MIT](https://github.com/stripe-samples/checkout-one-time-payments/blob/main/LICENSE)
- [Project website](https://checkout.stripe.dev/?mode=payment)
- [README](https://github.com/stripe-samples/checkout-one-time-payments/blob/main/README.md)
- [stripe-samples/checkout-one-time-payments on GitHub](https://github.com/stripe-samples/checkout-one-time-payments)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/stripe-samples-checkout-one-time-payments
