# @stepanjakl/apostrophe-stripe-checkout

> Stripe Checkout For ApostropheCMS

Latest version **0.0.6** (published 2026-07-04) · MIT license · 0 weekly downloads

## Install

```sh
npm install @stepanjakl/apostrophe-stripe-checkout
pnpm add @stepanjakl/apostrophe-stripe-checkout
yarn add @stepanjakl/apostrophe-stripe-checkout
bun add @stepanjakl/apostrophe-stripe-checkout
```

## Health

**Score 45/100 (D)** — status: active.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.0.6 |
| Published | 2026-07-04 |
| First published | 2024-01-22 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 15 |
| Unpacked size | 191.3 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Štěpán Jákl |
| Maintainers | stepanjakl |
| Keywords | apostrophe, apostrophecms, stripe |

## Links

- npm: https://www.npmjs.com/package/@stepanjakl/apostrophe-stripe-checkout
- Repository: https://github.com/stepanjakl/apostrophe-stripe-checkout
- Homepage: https://github.com/stepanjakl/apostrophe-stripe-checkout#readme
- Issues: https://github.com/stepanjakl/apostrophe-stripe-checkout/issues
- npm.io page: https://npm.io/package/@stepanjakl/apostrophe-stripe-checkout

## Dependencies (15)

- [mocha](https://npm.io/package/mocha.md) ^10.4.0
- [eslint](https://npm.io/package/eslint.md) ^8.x.x
- [stripe](https://npm.io/package/stripe.md) ^15.7.0
- [stylelint](https://npm.io/package/stylelint.md) ^16.x.x
- [apostrophe](https://npm.io/package/apostrophe.md) ^4.x.x
- [body-parser](https://npm.io/package/body-parser.md) ^1.20.2
- [read-only-field](https://npm.io/package/read-only-field.md) npm:@stepanjakl/apostrophe-read-only-field@latest
- [eslint-plugin-vue](https://npm.io/package/eslint-plugin-vue.md) ^9.26.0
- [eslint-plugin-node](https://npm.io/package/eslint-plugin-node.md) ^11.1.0
- [eslint-plugin-mocha](https://npm.io/package/eslint-plugin-mocha.md) ^10.4.3
- [eslint-plugin-import](https://npm.io/package/eslint-plugin-import.md) ^2.29.1
- [eslint-plugin-promise](https://npm.io/package/eslint-plugin-promise.md) ^6.1.1
- [eslint-config-standard](https://npm.io/package/eslint-config-standard.md) ^17.1.0
- [eslint-config-apostrophe](https://npm.io/package/eslint-config-apostrophe.md) ^4.3.0
- [stylelint-config-apostrophe](https://npm.io/package/stylelint-config-apostrophe.md) ^4.x.x

## Recent versions

- 0.0.6 (latest) — 2026-07-04
- 0.0.5 — 2024-05-28
- 0.0.4 — 2024-05-24
- 0.0.3 — 2024-05-17
- 0.0.2 — 2024-05-06
- 0.0.1 — 2024-04-25
- 0.0.0 — 2024-01-22

## README

<div align="center">
    <h1>
        Stripe Checkout For ApostropheCMS
    </h1>
    <p>
        <a aria-label="Apostrophe logo" href="https://v3.docs.apostrophecms.org">
            <img src="https://img.shields.io/badge/MADE%20FOR%20APOSTROPHECMS-000000.svg?style=for-the-badge&logo=Apostrophe&labelColor=6516DD">
        </a>
        <a aria-label="Stripe logo" href="https://stripe.com">
            <img src="https://img.shields.io/badge/STRIPE-000000.svg?style=for-the-badge&logo=Stripe&labelColor=635bFF&logoColor=FFFFFF">
        </a>
        <br>
        <a aria-label="Personal logo" href="https://stepanjakl.com">
            <img src="https://img.shields.io/badge/STEPANJAKL.COM%20-000000.svg?style=for-the-badge&labelColor=EED500&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCI+PHBhdGggZmlsbD0iIzAwMDAwMCIgZD0iTTAgMTV2NWgyMFY3LjVIMHY1aDE1LjA1VjE1SDBaTTIwIDBIMHY1aDIwVjBaIiAvPjwvc3ZnPg==">
        </a>
        <a aria-label="License"
           href="https://github.com/apostrophecms/module-template/blob/main/LICENSE.md">
            <img alt="License"
                 src="https://img.shields.io/static/v1?style=for-the-badge&labelColor=000000&label=License&message=MIT&color=3DA639">
        </a>
        <br>
        <br>
        <a aria-label="Unit Tests"
           href="https://github.com/stepanjakl/apostrophe-stripe-checkout/actions/workflows/tests.yml">
            <img alt="Unit Tests"
                 src="https://github.com/stepanjakl/apostrophe-stripe-checkout/actions/workflows/tests.yml/badge.svg?branch=main">
        </a>
    </p>
</div>

<br>

This module adds a custom route to initiate a Stripe Checkout instance and another route triggered by a webhook listener for incoming completed session events and to save them in the database as a piece type that can be easily accessible via the admin UI.

<br>

<table>
    <tr>
        <td colspan="3"><a href="./public/images/checkout.png" target="_blank"><img src="./public/images/checkout.png" alt="Checkout"></a></td>
    </tr>
    <tr>
        <td><a href="./public/images/admin-1.png"><img src="./public/images/admin-1.png" alt="Admin UI 1"></a></td>
        <td><a href="./public/images/admin-2.png"><img src="./public/images/admin-2.png" alt="Admin UI 2"></a></td>
        <td><a href="./public/images/admin-3.png"><img src="./public/images/admin-3.png" alt="Admin UI 3"></a></td>
    </tr>
</table>

<br>

## Installation

Use your preferred package manager to install the module. You'll also need to install the [read-only-field](https://github.com/stepanjakl/apostrophe-read-only-field) package alongside it:

```zsh
npm install stripe-checkout@npm:@stepanjakl/apostrophe-stripe-checkout

npm install read-only-field@npm:@stepanjakl/apostrophe-read-only-field
```

<br>

## Examples

**It is highly recommended to explore the [`apostrophe-stripe-examples`](https://github.com/stepanjakl/apostrophe-stripe-examples) repository, which offers a comprehensive set of examples and full configurations demonstrating how to set up a complete e-commerce store experience.**

<br>

## Usage

First, add installed modules to your configuration in the `app.js` root file:

```js
require('apostrophe')({
  shortName: 'project-name',
  modules: {
    // Custom fields
    'read-only-field': {},

    // Stripe Checkout
    'stripe-checkout': {},
    'stripe-checkout/session': {}
  }
});
```

<br>

Then, set global variables inside the `.env` file. It's important to set the `STRIPE_TEST_MODE` variable to anything other than `false` to enable [test mode](https://docs.stripe.com/test-mode).

```zsh
PORT='4000'
APOS_BASE_URL='http://localhost:4000'
APOS_RELEASE_ID='a4-boilerplate'
APOS_MONGODB_URI='mongodb://localhost:27017/a4-boilerplate'

STRIPE_KEY='sk_test_xyz'
STRIPE_TEST_MODE='false'
STRIPE_DASHBOARD_BASE_URL='https://dashboard.stripe.com'
STRIPE_WEBHOOK_ENDPOINT_SECRET='whsec_xyz'
```

[Read more on how to create a secret Stripe API key](https://docs.stripe.com/keys#create-api-secret-key)

The webhook signing secret is generated and displayed on the initial output of the listen command - more on this below.

<br>

## API Routes

The `stripe-checkout` module comes with two custom API routes:

<br>

#### `'/api/v1/stripe-checkout/sessions/create'`:

This API route handles POST requests to create a new [Stripe Checkout Session](https://docs.stripe.com/payments/checkout/how-checkout-works). It is a central piece of the module and facilitates initiating payment transactions through Stripe. Here's an example of a request using the Fetch API directly in the browser:

```javascript
const requestOptions = {
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    line_items: [
      {
        price: 'price_test_abc',
        quantity: 2
      },
      {
        price: 'price_test_xyz',
        quantity: 1
      }
    ],
    success_url: 'https://example.com/success',
    cancel_url: 'https://example.com/cancel'
  })
};

fetch('/api/v1/stripe-checkout/sessions/create', requestOptions)
  .then(response => {
    if (!response.ok) {
      throw new Error('Failed to create checkout session');
    }
    return response.json();
  })
  .then(data => {
    // Handle the response data, e.g., redirect to the checkout URL
    const checkoutUrl = data.url;
    console.log('Checkout URL:', checkoutUrl);
    // Example: Redirecting to the checkout URL
    window.location.href = checkoutUrl;
  })
  .catch(error => {
    console.error('Error:', error);
    // Handle errors, e.g., show an error message to the user
  });
```

> **Security note:** this route forwards the request body directly to Stripe's
> [`checkout.sessions.create`](https://docs.stripe.com/api/checkout/sessions/create),
> and it is not authenticated — this is intentional, since the client builds the
> checkout (line items, mode, URLs) and the actual prices are defined in your
> Stripe account, not by the caller. However, it does mean anyone who can reach
> your site can create Checkout Sessions. If that matters for your deployment,
> harden it by any of: requiring an authenticated `req.user`, whitelisting the
> fields you forward to Stripe (e.g. `line_items`, `mode`, `ui_mode`, `locale`,
> `success_url`, `cancel_url`, `redirect_on_completion`), and/or validating that
> every `line_items[].price` matches a price synced by
> [`apostrophe-stripe-products`](https://github.com/stepanjakl/apostrophe-stripe-products).

<br>

#### `'/api/v1/stripe-checkout/webhook'`:

This API route is used by the local listener to receive asynchronous Stripe events and save the completed checkout sessions to the database.

Set up event forwarding with the [Stripe CLI](https://docs.stripe.com/stripe-cli) and send all Stripe events to your local webhook endpoint for testing and/or monitoring purposes:

```zsh
stripe listen --events=payment_intent.succeeded --forward-to localhost:5000/api/v1/stripe-checkout/webhook
```

Use the PM2 process manager to run the `listen` command in production:

```zsh
pm2 start --name stripe-listener "stripe listen --events=checkout.session.completed --forward-to localhost:5000/api/v1/stripe-checkout/webhook"
```

[Read more about the Stripe webhooks](https://docs.stripe.com/webhooks/quickstart)

<br>

## TODOs (Improvements)

- Enable checkout session with more than 99 products

---
_Source: https://npm.io/package/@stepanjakl/apostrophe-stripe-checkout · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
