# Crear una página de suscripción prediseñada con Stripe Checkout

# Página de suscripción prediseñada con Stripe Checkout

Empieza con nuestra aplicación de ejemplo para ejecutar una integración de suscripciones completa y funcional con [Stripe Billing](https://docs.stripe.com/billing.md) y [Stripe Checkout](https://docs.stripe.com/payments/checkout.md).

La aplicación de ejemplo muestra cómo redirigir a tus clientes desde tu sitio a una página de pago prediseñada alojada en Stripe. Las API de Stripe Billing crean y gestionan suscripciones, facturas y pagos recurrentes, mientras que Checkout proporciona la interfaz de usuario prediseñada, segura y alojada en Stripe para recopilar los datos de los pagos.

Puedes representar a los clientes en tu integración ya sea como [objetos de cuenta configurada para el cliente](https://docs.stripe.com/api/v2/core/accounts/create.md#v2_create_accounts-configuration-customer) o como objetos [Customer](https://docs.stripe.com/api/customers/object.md). Para obtener más información sobre las diferencias entre estas opciones, consulta [Usar cuentas como clientes](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md).

Haz clic en cada paso para ver el código de muestra correspondiente. A medida que interactúas con los pasos, como agregar datos de precios, el creador actualiza el código de muestra.

Descarga y personaliza la aplicación de muestra a nivel local para probar tu integración.

### Agrega tus productos y precios

Crea o selecciona *Productos* (Products represent what your business sells—whether that's a good or a service) y *Precios* (Prices define how much and how often to charge for products. This includes how much the product costs, what currency to use, and the interval if the price is for subscriptions) que puedas usar en este ejemplo.

> Inicia sesión en tu cuenta de Stripe para configurar tus productos y precios.

### Agrega funcionalidades a tu producto

Crea funciones, como un regalo de cumpleaños anual, y asócialas a tu suscripción para [otorgarles este derecho](https://docs.stripe.com/billing/entitlements.md) a los nuevos suscriptores.

Escucha los [eventos de resumen de derechos activos](https://docs.stripe.com/billing/entitlements.md#webhooks) de tu [destino de eventos](https://docs.stripe.com/event-destinations.md) y usa la [API de lista de derechos activos](https://docs.stripe.com/api/entitlements/active-entitlement/list.md) de un cliente determinado para cumplir con los derechos de tu cliente.

### (Opcional) Habilitar métodos de pago adicionales

Usa tu [Dashboard](https://dashboard.stripe.com/settings/payment_methods) para habilitar los [métodos de pago admitidos](https://docs.stripe.com/payments/payment-methods/payment-method-support.md) que quieras aceptar además de tarjetas. Checkout muestra de forma dinámica los métodos de pago habilitados en orden de relevancia, según la ubicación del cliente y otras características.

### Agregar una página de vista previa de las tarifas

Agrega una página a tu sitio que muestre tu producto y permita que tus clientes se suscriban a él. Al hacer clic en **Confirmación de compra**, se los redirige a una página de [Checkout](https://docs.stripe.com/payments/checkout.md) alojada en Stripe, que finaliza el pedido y evita modificaciones.

Considera la posibilidad de insertar un [cuadro de tarifas](https://docs.stripe.com/payments/checkout/pricing-table.md) para mostrar dinámicamente tu información de tarifas a través del Dashboard. Al hacer clic en una opción de tarifas, el cliente será redirigido a la página de pago.

### Agregar un botón de pago

El botón de la página de vista previa del pedido redirige al cliente a la página de pago alojada por Stripe y utiliza la `lookup_key` de tu producto para recuperar el `price_id` del servidor.

### Agregar una página de confirmación

Crea una página de confirmación para mostrarle al cliente un mensaje de confirmación del pedido u otros detalles. Asocia esta página con la `success_url` de la sesión de Checkout, a la que Stripe redirige al cliente cuando finaliza correctamente el proceso de compra.

### Agregar un botón para el portal de clientes

Agrega un botón que redirija al portal de clientes para permitir que los clientes gestionen su suscripción. Cuando tu cliente haga click en ese botón, se le redirigirá al portal de clientes alojado en Stripe.

### Redirigir a la sesión del portal de clientes

Haz una solicitud al punto de conexión de tu servidor para redirigir a una nueva sesión del portal de clientes. En este ejemplo, se utiliza `session_id` de [Checkout Session](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-id) para demostrar cómo se recupera el `customer_id`. En un entorno de producción, se recomienda almacenar este valor junto con el usuario autenticado en la base de datos.

### Instalar la biblioteca de Stripe Node

Instala el paquete e impórtalo en tu código. Como alternativa, si empiezas de cero y necesitas un archivo package.json, descarga los archivos del proyecto mediante el enlace de descarga que encontrarás en el editor de código.

#### npm

Instala la biblioteca:

```bash
npm install --save stripe
```

#### GitHub

O bien, descarga el código fuente de la biblioteca de stripe-node directamente [desde GitHub](https://github.com/stripe/stripe-node).

### Instalar la biblioteca de Stripe Ruby

Instala la gema en Ruby de Stripe y pídela en tu código. Como alternativa, si empiezas de cero y necesitas un Gemfile, descarga los archivos del proyecto mediante el enlace que encontrarás en el editor de código.

#### Terminal

Instala la gema:

```bash
gem install stripe
```

#### Paquete

Agrega esta línea a tu Gemfile:

```bash
gem 'stripe'
```

#### GitHub

O bien, descarga el código fuente de la gema en Ruby de Stripe directamente [desde GitHub](https://github.com/stripe/stripe-ruby).

### Instalar la biblioteca de Stripe Java

Agrega la dependencia para compilar e importar la biblioteca. Como alternativa, si empiezas de cero y necesitas un archivo pom.xml de muestra (para Maven), descarga los archivos del proyecto mediante el enlace que encontrarás en el editor de código.

#### Maven

Agrega la siguiente dependencia a tu POM y reemplaza {VERSION} con el número de versión que quieres usar.

```bash
<dependency>\n<groupId>com.stripe</groupId>\n<artifactId>stripe-java</artifactId>\n<version>{VERSION}</version>\n</dependency>
```

#### Gradle

Agrega 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).

### Instalar el paquete de Stripe Python

Instala el paquete de Stripe e impórtalo en tu código. Como alternativa, si empiezas de cero y necesitas un archivo requirements.txt, descarga los archivos del proyecto mediante el enlace que encontrarás en el editor de código.

#### pip

Instala el paquete a través de pip:

```bash
pip3 install stripe
```

#### GitHub

Descargar el código Source de la biblioteca stripe-python directamente [desde GitHub](https://github.com/stripe/stripe-python).

### Instalar la biblioteca de Stripe PHP

Usa Composer para instalar la biblioteca e inicializa con la clave secreta de tu API. Como alternativa, si empiezas de cero y necesitas un archivo composer.json, descarga los archivos mediante el enlace que encontrarás en el editor de código.

#### Composer

Instala la biblioteca:

```bash
composer require stripe/stripe-php
```

#### GitHub

O bien, descarga el código fuente de la biblioteca de stripe-php directamente [desde GitHub](https://github.com/stripe/stripe-php).

### Configurar tu servidor

Agrega la dependencia para compilar e importar la biblioteca. Como alternativa, si empiezas de cero y necesitas un archivo go.mod, descarga los archivos del proyecto mediante el enlace que encontrarás en el editor de código.

#### Go

Asegúrate de inicializar con Go Modules:

```bash
go get -u github.com/stripe/stripe-go/v86
```

#### GitHub

O bien, descarga el código fuente de stripe-go module directamente [desde GitHub](https://github.com/stripe/stripe-go).

### Instalar la biblioteca de Stripe.net

Instala el paquete con .NET or NuGet. Como alternativa, si empiezas de cero, descarga los archivos que contengan 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 bien, descarga el código fuente de la biblioteca de Stripe.net directamente [desde GitHub](https://github.com/stripe/stripe-dotnet).

### Instalar las bibliotecas de Stripe

Instala los paquetes e impórtalos en tu código. Como alternativa, si empiezas de cero y necesitas un archivo `package.json`, descarga los archivos del proyecto mediante el enlace que encontrarás en el editor de código.

Instala las bibliotecas:

```bash
npm install --save stripe @stripe/stripe-js next
```

### Crear una sesión de Checkout

La [sesión de Checkout](https://docs.stripe.com/api/checkout/sessions.md) controla lo que tu cliente puede ver en la página de pago alojada en Stripe, como las partidas de factura, el importe y la moneda del pedido, y los métodos de pago aceptados.

### Usar la clave de búsqueda para obtener el precio

Especifica la clave de búsqueda que definiste para tu producto en el punto de conexión [Price](https://docs.stripe.com/api/prices/list.md) para aplicar el precio al pedido.

### Definir los ítems de factura

Mantén siempre en tu servidor la información confidencial sobre tu inventario de productos, como los precios y la disponibilidad, para evitar que el cliente la manipule. Especifica el ID de precio predefinido que recuperaste antes.

### Configura el modo

Define el modo en `subscription`. Checkout también admite los modos [pago](https://docs.stripe.com/checkout/quickstart.md) y [configuración](https://docs.stripe.com/payments/save-and-reuse.md) para pagos no recurrentes.

### Proporciona la URL de éxito.

Especifica una URL pública a la que Stripe pueda redirigir a los clientes después de completar el proceso con éxito. Agrega el parámetro de consulta `session_id` al final de tu URL para que luego puedas recuperar al cliente y para que Stripe pueda generar el Dashboard alojado del cliente.

### Redireccionamiento desde Checkout

Después de crear la sesión, redirige al cliente a la URL devuelta en la respuesta (ya sea de confirmación o de cancelación).

### Crear una sesión en el portal de clientes

Inicia [sesión en el portal de clientes](https://docs.stripe.com/api/customer_portal/sessions/create.md) de manera segura y alojada en Stripe que les permita a tus clientes gestionar sus suscripciones y datos de facturación.

### Redirigir al portal de clientes

Después de crear la sesión en el portal, redirige a tu cliente a la URL devuelta en la respuesta.

### Completa la suscripción

Crea un punto de conexión `/webhook` y obtén tu clave secreta de webhooks en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench para recibir notificaciones de los eventos relacionados con la actividad de suscripciones. Después de que el pago se efectúe correctamente y se lo redirija a la página de confirmación, verifica que el estado de la suscripción sea `active` y otorga a tu cliente acceso a los productos y funcionalidades a los que se suscribió.

### Ejecuta el servidor

Configura la variable de entorno `STRIPE_WEBHOOK_SECRET` con tu clave secreta de firma del webhook. Encuentra esta clave secreta en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) del Workbench.

Inicie su servidor y vaya a <http://localhost:4242/>

```bash
npm start
```

### Ejecuta el servidor

Configura la variable de entorno `STRIPE_WEBHOOK_SECRET` con tu clave secreta de firma del webhook. Encuentra esta clave secreta en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) del Workbench.

Inicia tu servidor. Automáticamente se abrirá una ventana en el navegador a <http://localhost:3000/checkout>

```bash
npm start
```

### Ejecuta el servidor

Configura la variable de entorno `STRIPE_WEBHOOK_SECRET` con tu clave secreta de firma del webhook. Encuentra esta clave secreta en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) del Workbench.

Inicie su servidor y vaya a <http://localhost:4242/>

```bash
ruby server.rb
```

### Ejecuta el servidor

Configura la variable de entorno `STRIPE_WEBHOOK_SECRET` con tu clave secreta de firma del webhook. Encuentra esta clave secreta en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) del Workbench.

Inicia tu servidor. Automáticamente se abrirá una ventana en el navegador a <http://localhost:3000/checkout>

```bash
ruby server.rb
```

### Ejecuta el servidor

Configura la variable de entorno `STRIPE_WEBHOOK_SECRET` con tu clave secreta de firma del webhook. Encuentra esta clave secreta en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) del Workbench.

Inicie su servidor y vaya a <http://localhost:4242/>

```bash
python3 -m flask run --port=4242
```

### Ejecuta el servidor

Configura la variable de entorno `STRIPE_WEBHOOK_SECRET` con tu clave secreta de firma del webhook. Encuentra esta clave secreta en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) del Workbench.

Inicia tu servidor. Automáticamente se abrirá una ventana en el navegador a <http://localhost:3000/checkout>

```bash
python3 -m flask run --port=4242
```

### Ejecuta el servidor

Configura la variable de entorno `STRIPE_WEBHOOK_SECRET` con tu clave secreta de firma del webhook. Encuentra esta clave secreta en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) del Workbench.

Inicie su servidor y vaya a <http://localhost:4242/>

```bash
php -S 127.0.0.1:4242 --docroot=public
```

### Ejecuta el servidor

Configura la variable de entorno `STRIPE_WEBHOOK_SECRET` con tu clave secreta de firma del webhook. Encuentra esta clave secreta en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) del Workbench.

Inicia tu servidor. Automáticamente se abrirá una ventana en el navegador a <http://localhost:3000/checkout>

```bash
php -S 127.0.0.1:4242 --docroot=public
```

### Ejecuta el servidor

Configura la variable de entorno `STRIPE_WEBHOOK_SECRET` con tu clave secreta de firma del webhook. Encuentra esta clave secreta en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) del Workbench.

Inicie su servidor y vaya a <http://localhost:4242/>

```bash
dotnet run
```

### Ejecuta el servidor

Configura la variable de entorno `STRIPE_WEBHOOK_SECRET` con tu clave secreta de firma del webhook. Encuentra esta clave secreta en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) del Workbench.

Inicia tu servidor. Automáticamente se abrirá una ventana en el navegador a <http://localhost:3000/checkout>

```bash
dotnet run
```

### Ejecuta el servidor

Configura la variable de entorno `STRIPE_WEBHOOK_SECRET` con tu clave secreta de firma del webhook. Encuentra esta clave secreta en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) del Workbench.

Inicie su servidor y vaya a <http://localhost:4242/>

```bash
go run server.go
```

### Ejecuta el servidor

Configura la variable de entorno `STRIPE_WEBHOOK_SECRET` con tu clave secreta de firma del webhook. Encuentra esta clave secreta en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) del Workbench.

Inicia tu servidor. Automáticamente se abrirá una ventana en el navegador a <http://localhost:3000/checkout>

```bash
go run server.go
```

### Ejecuta el servidor

Configura la variable de entorno `STRIPE_WEBHOOK_SECRET` con tu clave secreta de firma del webhook. Encuentra esta clave secreta en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) del Workbench.

Inicie su servidor y vaya a <http://localhost:4242/>

```bash
java -cp target/sample-jar-with-dependencies.jar com.stripe.sample.Server
```

### Ejecuta el servidor

Configura la variable de entorno `STRIPE_WEBHOOK_SECRET` con tu clave secreta de firma del webhook. Encuentra esta clave secreta en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) del Workbench.

Inicia tu servidor. Automáticamente se abrirá una ventana en el navegador a <http://localhost:3000/checkout>

```bash
java -cp target/sample-jar-with-dependencies.jar com.stripe.sample.Server
```

### Pruébalo

Haz clic en el botón confirmación de compra. En la página de pago alojada por Stripe, utiliza alguna de estas tarjetas de prueba para simular un pago.

| Scenario | Card Number |
| --- | --- |
| Payment succeeds | 4242424242424242 |
| Payment requires 3DS authentication | 4000002500003155 |
| Payment is declined | 4000000000009995 |

## Agrega funcionalidades de personalización

Si te suscribiste correctamente a tu producto en la prueba, ya tienes una integración básica del proceso de compra de suscripciones. Usa los botones a continuación para ver cómo personalizar este ejemplo con funcionalidades adicionales.

### Agregar pruebas

Asocia un período de prueba a una sesión de Checkout.

### Agregar un período de prueba

Usa `subscription_data` para agregar un número entero que represente la cantidad de `trial_period_days` antes de cobrarle al cliente por primera vez. El valor no puede ser menor que `1`.

Si comienzas una prueba sin cargo sin método de pago, establece el campo `trial_settings[end_behavior][missing_payment_method]` en `pausar` o `cancelar` la suscripción para que no continúe si la prueba finaliza sin método de pago. Aplica este parámetro en `suscription_data` cuando crees una sesión de confirmación de Checkout o actualízalo en la suscripción en otro momento. Consulta [Usar períodos de prueba](https://docs.stripe.com/billing/subscriptions/trials/free-trials.md#create-free-trials-without-payment) para obtener más información.

### Establecer la fecha del ciclo de facturación

Especificar un anclaje de ciclo de facturación al crear una sesión de Checkout.

### Anclar el ciclo de facturación de una suscripción

Usa `subscription_data` para establecer una marca de tiempo `billing_cycle_anchor` para la próxima fecha de facturación de una suscripción. Consulta [Configuración de la fecha del ciclo de facturación en Checkout](https://docs.stripe.com/payments/checkout/billing-cycle.md) para obtener más información.

### Automatizar el cobro de impuestos

Calcula y cobra el importe correcto de los impuestos para tus transacciones de Stripe. Obtén más información sobre [Stripe Tax](https://docs.stripe.com/tax.md) y [cómo agregarlo a Checkout](https://docs.stripe.com/tax/checkout.md). [Activa Stripe Tax](https://dashboard.stripe.com/tax) en el Dashboard antes de la integración.

### Agregar el parámetro de impuestos automático

Establece el parámetro `automatic_tax` en `enabled: true`.

    <script src="https://js.stripe.com/endive/stripe.js"></script>
      <div class="product">
        <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14px" height="16px" viewBox="0 0 14 16" version="1.1">
            <defs/>
            <g id="Flow" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
                <g id="0-Default" transform="translate(-121.000000, -40.000000)" fill="#E184DF">
                    <path d="M127,50 L126,50 C123.238576,50 121,47.7614237 121,45 C121,42.2385763 123.238576,40 126,40 L135,40 L135,56 L133,56 L133,42 L129,42 L129,56 L127,56 L127,50 Z M127,48 L127,42 L126,42 C124.343146,42 123,43.3431458 123,45 C123,46.6568542 124.343146,48 126,48 L127,48 Z" id="Pilcrow"/>
                </g>
            </g>
        </svg>
        <div class="description">
          <h3>{{PRODUCT_NAME}}</h3>
          <h5>{{FORMATTED_RECURRING_PRICE}}</h5>
        </div>
      </div>
      <form action="/create-checkout-session" method="POST">
        <!-- Add a hidden field with the lookup_key of your Price -->
        <input type="hidden" name="lookup_key" value="{{PRICE_LOOKUP_KEY}}" />
        <button id="checkout-and-portal-button" type="submit">Checkout</button>
      </form>
      <form action="/create-checkout-session.php" method="POST">
        <!-- Add a hidden field with the lookup_key of your Price -->
        <input type="hidden" name="lookup_key" value="{{PRICE_LOOKUP_KEY}}" />
        <button id="checkout-and-portal-button" type="submit">Checkout</button>
      </form>
<body>
  <section>
    <div class="product Box-root">
      <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14px" height="16px" viewBox="0 0 14 16" version="1.1">
          <defs/>
          <g id="Flow" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
              <g id="0-Default" transform="translate(-121.000000, -40.000000)" fill="#E184DF">
                  <path d="M127,50 L126,50 C123.238576,50 121,47.7614237 121,45 C121,42.2385763 123.238576,40 126,40 L135,40 L135,56 L133,56 L133,42 L129,42 L129,56 L127,56 L127,50 Z M127,48 L127,42 L126,42 C124.343146,42 123,43.3431458 123,45 C123,46.6568542 124.343146,48 126,48 L127,48 Z" id="Pilcrow"/>
              </g>
          </g>
      </svg>
      <div class="description Box-root">
        <h3>Subscription to {{PRODUCT_NAME}} successful!</h3>
      </div>
    </div>
    <form action="/create-portal-session" method="POST">
      <input type="hidden" id="session-id" name="session_id" value="" />
      <button id="checkout-and-portal-button" type="submit">Manage your billing information</button>
    </form>
    <form action="/create-portal-session.php" method="POST">
      <input type="hidden" id="session-id" name="session_id" value="" />
      <button id="checkout-and-portal-button" type="submit">Manage your billing information</button>
    </form>
  </section>
</body>
<body>
  <section>
    <p>Picked the wrong subscription? Shop around then come back to pay!</p>
  </section>
</body>
    <div className="product">
      <Logo />
      <div className="description">
        <h3>{{PRODUCT_NAME}}</h3>
        <h5>{{FORMATTED_RECURRING_PRICE}}</h5>
      </div>
    </div>
    <form action="/create-checkout-session" method="POST">
      {/* Add a hidden field with the lookup_key of your Price */}
      <input type="hidden" name="lookup_key" value="{{PRICE_LOOKUP_KEY}}" />
      <button id="checkout-and-portal-button" type="submit">
        Checkout
      </button>
    </form>
    <form action="/create-checkout-session.php" method="POST">
      {/* Add a hidden field with the lookup_key of your Price */}
      <input type="hidden" name="lookup_key" value="{{PRICE_LOOKUP_KEY}}" />
      <button id="checkout-and-portal-button" type="submit">
        Checkout
      </button>
    </form>
    <section>
      <div className="product Box-root">
        <Logo />
        <div className="description Box-root">
          <h3>Subscription to {{PRODUCT_NAME}} successful!</h3>
        </div>
      </div>
      <form action="/create-portal-session" method="POST">
        <input
          type="hidden"
          id="session-id"
          name="session_id"
          value={sessionId}
        />
        <button id="checkout-and-portal-button" type="submit">
          Manage your billing information
        </button>
      </form>
      <form action="/create-portal-session.php" method="POST">
        <input
          type="hidden"
          id="session-id"
          name="session_id"
          value={sessionId}
        />
        <button id="checkout-and-portal-button" type="submit">
          Manage your billing information
        </button>
      </form>
    </section>
{
  "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": "^5.0.1",
    "stripe": "^8.202.0"
  },
  "devDependencies": {
    "concurrently": "4.1.2"
  },
  "homepage": "http://localhost:3000/checkout",
  "proxy": "http://127.0.0.1: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": "^3.7.0",
    "@stripe/stripe-js": "^7.3.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-scripts": "^5.0.1"
  },
  "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"
    ]
  }
}
// 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 API key embedded in code samples.
// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
const stripe = require('stripe')('<<YOUR_SECRET_KEY>>');
const YOUR_DOMAIN = "http://localhost:4242";
const YOUR_DOMAIN = "http://localhost:3000";
  const prices = await stripe.prices.list({
    lookup_keys: [req.body.lookup_key],
    expand: ['data.product'],
  });
  const session = await stripe.checkout.sessions.create({
    billing_address_collection: 'auto',
    line_items: [
      {
        price: prices.data[0].id,
        // For usage-based billing, don't pass quantity
        quantity: 1,

      },
    ],
    mode: 'subscription',
    success_url: `${YOUR_DOMAIN}/success.html?session_id={CHECKOUT_SESSION_ID}`,
    success_url: `${YOUR_DOMAIN}/?success=true&session_id={CHECKOUT_SESSION_ID}`,
    discounts: [{
      coupon: '{{COUPON_ID}}',
    }],
    customer: 'cus_123',
    customer_account: 'acct_123',
    subscription_data: {
      trial_period_days: 7,
      billing_cycle_anchor: 1672531200,
    },
    subscription_data: {
      billing_cycle_anchor: 1672531200,
    },
    automatic_tax: { enabled: true },
  });

  res.redirect(303, session.url);
  // This is the url to which the customer will be redirected when they're done
  // managing their billing with the portal.
  const returnUrl = YOUR_DOMAIN;

  const portalSession = await stripe.billingPortal.sessions.create({
    customer: checkoutSession.customer,
    return_url: returnUrl,
  });
  // This is the url to which the customer will be redirected when they're done
  // managing their billing with the portal.
  const returnUrl = YOUR_DOMAIN;

  const portalSession = await stripe.billingPortal.sessions.create({
    customer_account: checkoutSession.customer_account,
    return_url: returnUrl,
  });
  res.redirect(303, portalSession.url);
app.post(
  '/webhook',
  express.raw({ type: 'application/json' }),
  (request, response) => {
    let event = request.body;

    // To run this example, set an environment variable STRIPE_WEBHOOK_SECRET to
    // your endpoint's unique secret.
    //
    // If you are testing with the CLI, find the secret by running 'stripe listen'.
    // If you are using an endpoint defined with the API or dashboard, look in
    // your webhook settings at https://dashboard.stripe.com/webhooks.
    //
    // Don't include webhook secrets in code.
    const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET;

    // Only verify the event if you have an endpoint secret defined.
    // Otherwise use the basic event deserialized with JSON.parse
    if (endpointSecret) {
      // Get the signature sent by Stripe
      const signature = request.headers['stripe-signature'];
      try {
        event = stripe.webhooks.constructEvent(
          request.body,
          signature,
          endpointSecret
        );
      } catch (err) {
        console.log(`⚠️  Webhook signature verification failed.`, err.message);
        return response.sendStatus(400);
      }
    }
    let subscription;
    let status;
    // Handle the event
    switch (event.type) {
      case 'customer.subscription.trial_will_end':
        subscription = event.data.object;
        status = subscription.status;
        console.log(`Subscription status is ${status}.`);
        // Then define and call a method to handle the subscription trial ending.
        // handleSubscriptionTrialEnding(subscription);
        break;
      case 'customer.subscription.deleted':
        subscription = event.data.object;
        status = subscription.status;
        console.log(`Subscription status is ${status}.`);
        // Then define and call a method to handle the subscription deleted.
        // handleSubscriptionDeleted(subscriptionDeleted);
        break;
      case 'customer.subscription.created':
        subscription = event.data.object;
        status = subscription.status;
        console.log(`Subscription status is ${status}.`);
        // Then define and call a method to handle the subscription created.
        // handleSubscriptionCreated(subscription);
        break;
      case 'customer.subscription.updated':
        subscription = event.data.object;
        status = subscription.status;
        console.log(`Subscription status is ${status}.`);
        // Then define and call a method to handle the subscription update.
        // handleSubscriptionUpdated(subscription);
        break;
      case 'entitlements.active_entitlement_summary.updated':
        subscription = event.data.object;
        console.log(`Active entitlement summary updated for ${subscription}.`);
        // Then define and call a method to handle active entitlement summary updated
        // handleEntitlementUpdated(subscription);
        break;
      default:
        // Unexpected event type
        console.log(`Unhandled event type ${event.type}.`);
    }
    // Return a 200 response to acknowledge receipt of the event
    response.send();
  }
);
{
  "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": "^22.6.0"
  }
}
{
  "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": "^5.0.1",
    "stripe": "22.6.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 \"npm run start-client\" \"npm run 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 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 API key embedded in code samples.
\# Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
client = Stripe::StripeClient.new('<<YOUR_SECRET_KEY>>')
  prices = client.v1.prices.list(
    lookup_keys: [params['lookup_key']],
    expand: ['data.product']
  )
    session = client.v1.checkout.sessions.create({
      mode: 'subscription',
      line_items: [{
        quantity: 1,
        price: prices.data[0].id
      }],
      success_url: YOUR_DOMAIN + '/success.html?session_id={CHECKOUT_SESSION_ID}',
      success_url: YOUR_DOMAIN + '?success=true&session_id={CHECKOUT_SESSION_ID}',
      subscription_data: {
        trial_period_days: 7,
        billing_cycle_anchor: 1672531200
      },
      subscription_data: {
        billing_cycle_anchor: 1672531200
      },
      customer: 'cus_JyTTNqVDAoRYE1',
      customer_account: 'acct_123',
      discounts: [{
        coupon: 'gBY6sFUf'
      }],
      automatic_tax: {
        enabled: true
      },
    })
  redirect session.url, 303
  session = client.v1.billing_portal.sessions.create({

                                                    customer: checkout_session.customer,
                                                    return_url: return_url
                                                  })
  session = client.v1.billing_portal.sessions.create({

                                                    customer_account: checkout_session.customer_account,
                                                    return_url: return_url
                                                  })
  redirect session.url, 303
post '/webhook' do
  \# To run this example, set an environment variable STRIPE_WEBHOOK_SECRET to
  # your endpoint's unique secret.
  #
  # If you are testing with the CLI, find the secret by running 'stripe listen'.
  # If you are using an endpoint defined with the API or dashboard, look in
  # your webhook settings at https://dashboard.stripe.com/webhooks.
  #
  # Don't include webhook secrets in code.
  webhook_secret = ENV['STRIPE_WEBHOOK_SECRET']

  payload = request.body.read
  if webhook_secret
    # Retrieve the event by verifying the signature using the raw body and secret if webhook signing is configured.
    sig_header = request.env['HTTP_STRIPE_SIGNATURE']
    event = nil

    begin
      event = Stripe::Webhook.construct_event(
        payload, sig_header, webhook_secret
      )
    rescue JSON::ParserError => e
      # Invalid payload
      status 400
      return
    rescue Stripe::SignatureVerificationError => e
      # Invalid signature
      puts '⚠️  Webhook signature verification failed.'
      status 400
      return
    end
  else
    data = JSON.parse(payload, symbolize_names: true)
    event = Stripe::Event.construct_from(data)
  end
  # Get the type of webhook event sent - used to check the status of PaymentIntents.
  event_type = event['type']
  data = event['data']
  data_object = data['object']

  if event.type == 'customer.subscription.deleted'
    # handle subscription canceled automatically based
    # upon your subscription settings. Or if the user cancels it.
    # puts data_object
    puts "Subscription canceled: #{event.id}"
  end

  if event.type == 'customer.subscription.updated'
    # handle subscription updated
    # puts data_object
    puts "Subscription updated: #{event.id}"
  end

  if event.type == 'customer.subscription.created'
    # handle subscription created
    # puts data_object
    puts "Subscription created: #{event.id}"
  end

  if event.type == 'customer.subscription.trial_will_end'
    # handle subscription trial ending
    # puts data_object
    puts "Subscription trial will end: #{event.id}"
  end

  if event.type == 'entitlements.active_entitlement_summary.updated'
    # handle active entitlement summary updated
    # puts data_object
    puts "Active entitlement summary updated: #{event.id}"
  end

  content_type 'application/json'
  {
    status: 'success'
  }.to_json
end
import stripe
\# 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 API key embedded in code samples.
\# Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
client = stripe.StripeClient('<<YOUR_SECRET_KEY>>')
    try:
        prices = client.v1.prices.list(params={
            'lookup_keys': [request.form['lookup_key']],
            'expand': ['data.product'],
        })

        checkout_session = client.v1.checkout.sessions.create(params={
            'line_items': [
                {
                    'price': prices.data[0].id,
                    'quantity': 1,
                },
            ],
            'mode': 'subscription',
            'success_url': YOUR_DOMAIN +
            '/success.html?session_id={CHECKOUT_SESSION_ID}',
            'success_url': YOUR_DOMAIN +
            '?success=true&session_id={CHECKOUT_SESSION_ID}',
            'subscription_data': {
                'trial_period_days': 7,
                'billing_cycle_anchor': 1672531200,
            },
            'subscription_data': {
                'billing_cycle_anchor': 1672531200,
            },
            'discounts': [
                {
                    'coupon': '{{COUPON_ID}}'
                }
            ],
            'customer': 'cus_123',
            'customer_account': 'acct_123',
            'automatic_tax': {
              'enabled': True
            },
        })
        return redirect(checkout_session.url, code=303)
    portalSession = client.v1.billing_portal.sessions.create(params={
        'customer': checkout_session.customer,
        'return_url': return_url,
    })
    portalSession = client.v1.billing_portal.sessions.create(params={
        'customer_account': checkout_session.customer_account,
        'return_url': return_url,
    })
    return redirect(portalSession.url, code=303)
@app.route('/webhook', methods=['POST'])
def webhook_received():
    \# To run this example, set an environment variable STRIPE_WEBHOOK_SECRET to
    # your endpoint's unique secret.
    #
    # If you are testing with the CLI, find the secret by running 'stripe listen'.
    # If you are using an endpoint defined with the API or dashboard, look in
    # your webhook settings at https://dashboard.stripe.com/webhooks.
    #
    # Don't include webhook secrets in code.
    webhook_secret = os.environ.get('STRIPE_WEBHOOK_SECRET')

    request_data = json.loads(request.data)

    if webhook_secret:
        # Retrieve the event by verifying the signature using the raw body and secret if webhook signing is configured.
        signature = request.headers.get('stripe-signature')
        try:
            event = client.construct_event(
                payload=request.data, sig_header=signature, secret=webhook_secret)
            data = event['data']
        except Exception as e:
            return e
        # Get the type of webhook event sent - used to check the status of PaymentIntents.
        event_type = event['type']
    else:
        data = request_data['data']
        event_type = request_data['type']
    data_object = data['object']

    print('event ' + event_type)

    if event_type == 'checkout.session.completed':
        print('🔔 Payment succeeded!')
    elif event_type == 'customer.subscription.trial_will_end':
        print('Subscription trial will end')
    elif event_type == 'customer.subscription.created':
        print('Subscription created %s', event.id)
    elif event_type == 'customer.subscription.updated':
        print('Subscription created %s', event.id)
    elif event_type == 'customer.subscription.deleted':
        # handle subscription canceled automatically based
        # upon your subscription settings. Or if the user cancels it.
        print('Subscription canceled: %s', event.id)
    elif event_type == 'entitlements.active_entitlement_summary.updated':
        # handle active entitlement summary updated
        print('Active entitlement summary updated: %s', event.id)

    return jsonify({'status': 'success'})
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.6.0
toml==0.10.2
Werkzeug==3.1.5
  $session = $stripe->billingPortal->sessions->create([
    'customer' => $checkout_session->customer,
    'return_url' => $return_url,
  ]);
  $session = $stripe->billingPortal->sessions->create([
    'customer_account' => $checkout_session->customer_account,
    'return_url' => $return_url,
  ]);
  header("HTTP/1.1 303 See Other");
  header("Location: " . $session->url);

// To run this example, set an environment variable STRIPE_WEBHOOK_SECRET to
// your endpoint's unique secret.
//
// If you are testing with the CLI, find the secret by running 'stripe listen'.
// If you are using an endpoint defined with the API or dashboard, look in
// your webhook settings at https://dashboard.stripe.com/webhooks.
//
// Don't include webhook secrets in code.
$endpoint_secret = getenv('STRIPE_WEBHOOK_SECRET');

$payload = @file_get_contents('php://input');
$event = null;
try {
  $event = \Stripe\Event::constructFrom(
    json_decode($payload, true)
  );
} catch(\UnexpectedValueException $e) {
  // Invalid payload
  echo '⚠️  Webhook error while parsing basic request.';
  http_response_code(400);
  exit();
}
// Handle the event
switch ($event->type) {
  case 'customer.subscription.trial_will_end':
    $subscription = $event->data->object; // contains a \Stripe\Subscription
    // Then define and call a method to handle the trial ending.
    // handleTrialWillEnd($subscription);
    break;
  case 'customer.subscription.created':
    $subscription = $event->data->object; // contains a \Stripe\Subscription
    // Then define and call a method to handle the subscription being created.
    // handleSubscriptionCreated($subscription);
    break;
  case 'customer.subscription.deleted':
    $subscription = $event->data->object; // contains a \Stripe\Subscription
    // Then define and call a method to handle the subscription being deleted.
    // handleSubscriptionDeleted($subscription);
    break;
  case 'customer.subscription.updated':
    $subscription = $event->data->object; // contains a \Stripe\Subscription
    // Then define and call a method to handle the subscription being updated.
    // handleSubscriptionUpdated($subscription);
    break;
  case 'entitlements.active_entitlement_summary.updated':
    $subscription = $event->data->object; // contains a \Stripe\Subscription
    // Then define and call a method to handle active entitlement summary updated.
    // handleEntitlementUpdated($subscription);
    break;
  default:
    // Unexpected event type
    echo 'Received unknown event type';
}
// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
$stripeSecretKey = '<<YOUR_SECRET_KEY>>';
$stripe = new \Stripe\StripeClient($stripeSecretKey);
  $prices = $stripe->prices->all([
    // retrieve lookup_key from form data POST body
    'lookup_keys' => [$_POST['lookup_key']],
    'expand' => ['data.product']
  ]);
  $checkout_session = $stripe->checkout->sessions->create([
    'line_items' => [[
      'price' => $prices->data[0]->id,
      'quantity' => 1,
    ]],
    'mode' => 'subscription',
    'success_url' => $YOUR_DOMAIN . '/success.html?session_id={CHECKOUT_SESSION_ID}',
    'success_url' => $YOUR_DOMAIN . '?success=true&session_id={CHECKOUT_SESSION_ID}',
    'subscription_data' => [
      'trial_period_days' => 7,
      'billing_cycle_anchor' => 1672531200,
    ],
    'subscription_data' => [
      'billing_cycle_anchor' => 1672531200,
    ],
    'discounts' => [[
        'coupon' => '{{COUPON_ID}}',
    ]],
    'customer' => 'cus_123',
    'automatic_tax' => [
      'enabled' => true,
    ],
  ]);
  header("HTTP/1.1 303 See Other");
  header("Location: " . $checkout_session->url);
            // 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 API key embedded in code samples.
            // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
            services.AddSingleton(new StripeClient("<<YOUR_SECRET_KEY>>"));
            var priceOptions = new PriceListOptions
            {
                LookupKeys = new List<string> {
                    Request.Form["lookup_key"]
                }
            };
            StripeList<Price> prices = _client.V1.Prices.List(priceOptions);
            var options = new SessionCreateOptions
            {
                LineItems = new List<SessionLineItemOptions>
                {
                  new SessionLineItemOptions
                  {
                    Price = prices.Data[0].Id,
                    Quantity = 1,
                  },
                },
                Mode = "subscription",
                SuccessUrl = domain + "/success.html?session_id={CHECKOUT_SESSION_ID}",
                SuccessUrl = domain + "?success=true&session_id={CHECKOUT_SESSION_ID}",
                SubscriptionData = new SessionSubscriptionDataOptions
                {
                    TrialPeriodDays = 7,
                    BillingCycleAnchor = 1672531200,
                },
                SubscriptionData = new SessionSubscriptionDataOptions
                {
                    BillingCycleAnchor = 1672531200,
                },
                Customer = "cus_123",
      CustomerAccount: stripe.String("acct_123"),
                AutomaticTax = new SessionAutomaticTaxOptions { Enabled = true },
                CustomerAccount = "acct_123",
            };
            Session session = _client.V1.Checkout.Sessions.Create(options);
            Response.Headers.Add("Location", session.Url);
            return new StatusCodeResult(303);
            var options = new Stripe.BillingPortal.SessionCreateOptions
            {
                Customer = checkoutSession.CustomerId,
                ReturnUrl = returnUrl,
            };
            var session = _client.V1.BillingPortal.Sessions.Create(options);
            var options = new Stripe.BillingPortal.SessionCreateOptions
            {
                CustomerAccount = checkoutSession.CustomerAccount,
                ReturnUrl = returnUrl,
            };
            var session = _client.V1.BillingPortal.Sessions.Create(options);
            Response.Headers.Add("Location", session.Url);
            return new StatusCodeResult(303);
    [Route("webhook")]
    [ApiController]
    public class WebhookController : Controller
    {
        [HttpPost]
        public async Task<IActionResult> Index()
        {
            // To run this example, set an environment variable STRIPE_WEBHOOK_SECRET to
            // your endpoint's unique secret.
            //
            // If you are testing with the CLI, find the secret by running 'stripe listen'.
            // If you are using an endpoint defined with the API or dashboard, look in
            // your webhook settings at https://dashboard.stripe.com/webhooks.
            //
            // Don't include webhook secrets in code.
            var endpointSecret = Environment.GetEnvironmentVariable("STRIPE_WEBHOOK_SECRET");

            var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();

            try
            {
                var stripeEvent = EventUtility.ParseEvent(json);
                var signatureHeader = Request.Headers["Stripe-Signature"];
                stripeEvent = EventUtility.ConstructEvent(json,
                        signatureHeader, endpointSecret);
                // If on SDK version < 46, use class Events instead of EventTypes
                if (stripeEvent.Type == EventTypes.CustomerSubscriptionDeleted)
                {
                    var subscription = stripeEvent.Data.Object as Subscription;
                    Console.WriteLine("A subscription was canceled.", subscription.Id);
                    // Then define and call a method to handle the successful payment intent.
                    // handleSubscriptionCanceled(subscription);
                }
                else if (stripeEvent.Type == EventTypes.CustomerSubscriptionUpdated)
                {
                    var subscription = stripeEvent.Data.Object as Subscription;
                    Console.WriteLine("A subscription was updated.", subscription.Id);
                    // Then define and call a method to handle the successful payment intent.
                    // handleSubscriptionUpdated(subscription);
                }
                else if (stripeEvent.Type == EventTypes.CustomerSubscriptionCreated)
                {
                    var subscription = stripeEvent.Data.Object as Subscription;
                    Console.WriteLine("A subscription was created.", subscription.Id);
                    // Then define and call a method to handle the successful payment intent.
                    // handleSubscriptionUpdated(subscription);
                }
                else if (stripeEvent.Type == EventTypes.CustomerSubscriptionTrialWillEnd)
                {
                    var subscription = stripeEvent.Data.Object as Subscription;
                    Console.WriteLine("A subscription trial will end", subscription.Id);
                    // Then define and call a method to handle the successful payment intent.
                    // handleSubscriptionUpdated(subscription);
                }
                else if (stripeEvent.Type == EventTypes.ActiveEntitlementSummaryUpdated)
                {
                    var summary = stripeEvent.Data.Object as ActiveEntitlementSummary;
                    Console.WriteLine("Active entitlement summary updated for customer", summary.Customer);
                    // Then define and call a method to handle active entitlement summary updated.
                    // handleEntitlementUpdated($subscription);
                }
                else
                {
                    Console.WriteLine("Unhandled event type: {0}", stripeEvent.Type);
                }
                return Ok();
            }
            catch (StripeException e)
            {
                Console.WriteLine("Error: {0}", e.Message);
                return BadRequest();
            }
        }
    "github.com/stripe/stripe-go/v86"
    "github.com/stripe/stripe-go/v86/webhook"
    // 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 API key embedded in code samples.
    // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
    sc = stripe.NewClient("<<YOUR_SECRET_KEY>>")
    params := &stripe.PriceListParams{
      LookupKeys: stripe.StringSlice([]string{
        lookup_key,
      }),
    }
    var price *stripe.Price
    for p, err := range sc.V1Prices.List(context.TODO(), params).All(context.TODO()) {
      if err != nil {
        log.Printf("sc.V1Prices.List: %v", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
      }
      price = p
      break
    }
    if price == nil {
      log.Printf(">>>>>>>>>>>>>>>>>>>>>>>>>>> Add a price lookup key to checkout.html for the demo <<<<<<<<<<<<<<<<<<<<<<<<")
      return
    }
    checkoutParams := &stripe.CheckoutSessionCreateParams{
      Mode: stripe.String(stripe.CheckoutSessionModeSubscription),
      LineItems: []*stripe.CheckoutSessionCreateLineItemParams{
        &stripe.CheckoutSessionCreateLineItemParams{
          Price:    stripe.String(price.ID),
          Quantity: stripe.Int64(1),
        },
      },
      SubscriptionData: &stripe.CheckoutSessionCreateSubscriptionDataParams{
        TrialPeriodDays: stripe.Int64(7),
        BillingCycleAnchor: stripe.Int64(1672531200),
      },
      SubscriptionData: &stripe.CheckoutSessionCreateSubscriptionDataParams{
        BillingCycleAnchor: stripe.Int64(1672531200),
      },
      Discounts: []*stripe.CheckoutSessionCreateDiscountParams{
        &stripe.CheckoutSessionCreateDiscountParams{
          Coupon: stripe.String("gBY6sFUf"),
        },
      },
      SuccessURL: stripe.String(domain + "/success.html?session_id={CHECKOUT_SESSION_ID}"),
      SuccessURL: stripe.String(domain + "?success=true&session_id={CHECKOUT_SESSION_ID}"),
      Customer: stripe.String("cus_123"),
      CustomerAccount: stripe.String("acct_123"),
      AutomaticTax: &stripe.CheckoutSessionCreateAutomaticTaxParams{
        Enabled: stripe.Bool(true),
      },
    }

    s, err := sc.V1CheckoutSessions.Create(context.TODO(), checkoutParams)
    http.Redirect(w, r, s.URL, http.StatusSeeOther)
    // Authenticate your user.
    params := &stripe.BillingPortalSessionCreateParams{
      Customer:  stripe.String(s.Customer.ID),
      ReturnURL: stripe.String(domain),
    }
    ps, _ := sc.V1BillingPortalSessions.Create(context.TODO(), params)
    log.Printf("sc.V1BillingPortalSessions.Create: %v", ps.URL)
    // Authenticate your user.
    params := &stripe.BillingPortalSessionCreateParams{
      CustomerAccount: stripe.String(s.CustomerAccount),
      ReturnURL: stripe.String(domain),
    }
    ps, _ := sc.V1BillingPortalSessions.Create(context.TODO(), params)
    log.Printf("sc.V1BillingPortalSessions.Create: %v", ps.URL)
    http.Redirect(w, r, ps.URL, http.StatusSeeOther)
func handleWebhook(w http.ResponseWriter, req *http.Request) {
    const MaxBodyBytes = int64(65536)
    bodyReader := http.MaxBytesReader(w, req.Body, MaxBodyBytes)
    payload, err := ioutil.ReadAll(bodyReader)
    if err != nil {
      fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err)
      w.WriteHeader(http.StatusServiceUnavailable)
      return
    }

    // To run this example, set an environment variable STRIPE_WEBHOOK_SECRET to
    // your endpoint's unique secret.
    //
    // If you are testing with the CLI, find the secret by running 'stripe listen'.
    // If you are using an endpoint defined with the API or dashboard, look in
    // your webhook settings at https://dashboard.stripe.com/webhooks.
    //
    // Don't include webhook secrets in code.
    endpointSecret := os.Getenv("STRIPE_WEBHOOK_SECRET")

    signatureHeader := req.Header.Get("Stripe-Signature")
    event, err := sc.ConstructEvent(payload, signatureHeader, endpointSecret)
    if err != nil {
      fmt.Fprintf(os.Stderr, "⚠️  Webhook signature verification failed. %v\n", err)
      w.WriteHeader(http.StatusBadRequest) // Return a 400 error on a bad signature
      return
    }
    // Unmarshal the event data into an appropriate struct depending on its Type
    switch event.Type {
    case "customer.subscription.deleted":
      var subscription stripe.Subscription
      err := json.Unmarshal(event.Data.Raw, &subscription)
      if err != nil {
        fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err)
        w.WriteHeader(http.StatusBadRequest)
        return
      }
      log.Printf("Subscription deleted for %d.", subscription.ID)
      // Then define and call a func to handle the deleted subscription.
      // handleSubscriptionCanceled(subscription)
    case "customer.subscription.updated":
      var subscription stripe.Subscription
      err := json.Unmarshal(event.Data.Raw, &subscription)
      if err != nil {
        fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err)
        w.WriteHeader(http.StatusBadRequest)
        return
      }
      log.Printf("Subscription updated for %d.", subscription.ID)
      // Then define and call a func to handle the successful attachment of a PaymentMethod.
      // handleSubscriptionUpdated(subscription)
    case "customer.subscription.created":
      var subscription stripe.Subscription
      err := json.Unmarshal(event.Data.Raw, &subscription)
      if err != nil {
        fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err)
        w.WriteHeader(http.StatusBadRequest)
        return
      }
      log.Printf("Subscription created for %d.", subscription.ID)
      // Then define and call a func to handle the successful attachment of a PaymentMethod.
      // handleSubscriptionCreated(subscription)
    case "customer.subscription.trial_will_end":
      var subscription stripe.Subscription
      err := json.Unmarshal(event.Data.Raw, &subscription)
      if err != nil {
        fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err)
        w.WriteHeader(http.StatusBadRequest)
        return
      }
      log.Printf("Subscription trial will end for %d.", subscription.ID)
      // Then define and call a func to handle the successful attachment of a PaymentMethod.
      // handleSubscriptionTrialWillEnd(subscription)
    case "entitlements.active_entitlement_summary.updated":
      var subscription stripe.Subscription
      err := json.Unmarshal(event.Data.Raw, &subscription)
      if err != nil {
        fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err)
        w.WriteHeader(http.StatusBadRequest)
        return
      }
      log.Printf("Active entitlement summary updated for %d.", subscription.ID)
      // Then define and call a func to handle active entitlement summary updated.
      // handleEntitlementUpdated(subscription)
    default:
      fmt.Fprintf(os.Stderr, "Unhandled event type: %s\n", event.Type)
    }
    w.WriteHeader(http.StatusOK)
  }
require github.com/stripe/stripe-go/v86 v86.4.0
    // 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 API key embedded in code samples.
    // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
    StripeClient client = new StripeClient("<<YOUR_SECRET_KEY>>");
      PriceListParams priceParams = PriceListParams.builder().addLookupKey(request.queryParams("lookup_key")).build();
      StripeCollection<Price> prices = client.v1().prices().list(priceParams);
      SessionCreateParams params = SessionCreateParams.builder()
          .addLineItem(
              SessionCreateParams.LineItem.builder().setPrice(prices.getData().get(0).getId()).setQuantity(1L).build())
          .setMode(SessionCreateParams.Mode.SUBSCRIPTION)
          .setSuccessUrl(YOUR_DOMAIN + "/success.html?session_id={CHECKOUT_SESSION_ID}")
          .setSuccessUrl(YOUR_DOMAIN + "?success=true&session_id={CHECKOUT_SESSION_ID}")
          .setSubscriptionData(SessionCreateParams.SubscriptionData.builder().setTrialPeriodDays(7L).setBillingCycleAnchor(1672531200).build())
          .setSubscriptionData(SessionCreateParams.SubscriptionData.builder().setBillingCycleAnchor(1672531200).build())
          .addDiscount(SessionCreateParams.Discount.builder().setCoupon("{{COUPON_ID}}").build())
          .setCustomer("cus_JyTTNqVDAoRYE1")
          .setCustomerAccount("acct_123")
          .setAutomaticTax(
            SessionCreateParams.AutomaticTax.builder()
              .setEnabled(true)
              .build())
          .build();
      Session session = client.v1().checkout().sessions().create(params);
      response.redirect(session.getUrl(), 303);
      com.stripe.param.billingportal.SessionCreateParams params = new com.stripe.param.billingportal.SessionCreateParams.Builder()
          .setCustomer(checkoutSession.getCustomer())
          .setReturnUrl(YOUR_DOMAIN).build();

      com.stripe.model.billingportal.Session portalSession = client.v1().billingPortal().sessions().create(params);

      com.stripe.param.billingportal.SessionCreateParams params = new com.stripe.param.billingportal.SessionCreateParams.Builder()
          .setCustomerAccount(checkoutSession.getCustomerAccount())
          .setReturnUrl(YOUR_DOMAIN).build();

      com.stripe.model.billingportal.Session portalSession = client.v1().billingPortal().sessions().create(params);

      response.redirect(portalSession.getUrl(), 303);
      return "";
    post("/webhook", (request, response) -> {
      String payload = request.body();
      Event event = null;
      try {
        event = ApiResource.GSON.fromJson(payload, Event.class);
      } catch (JsonSyntaxException e) {
        // Invalid payload
        System.out.println("⚠️  Webhook error while parsing basic request.");
        response.status(400);
        return "";
      }
      String sigHeader = request.headers("Stripe-Signature");
      if (endpointSecret != null && sigHeader != null) {
        // Only verify the event if you have an endpoint secret defined.
        // Otherwise use the basic event deserialized with GSON.
        try {
          event = client.constructEvent(payload, sigHeader, endpointSecret);
        } catch (SignatureVerificationException e) {
          // Invalid signature
          System.out.println("⚠️  Webhook error while validating signature.");
          response.status(400);
          return "";
        }
      }
      // Deserialize the nested object inside the event
      EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer();
      StripeObject stripeObject = null;
      if (dataObjectDeserializer.getObject().isPresent()) {
        stripeObject = dataObjectDeserializer.getObject().get();
      } else {
        // Deserialization failed, probably due to an API version mismatch.
        // Refer to the Javadoc documentation on `EventDataObjectDeserializer` for
        // instructions on how to handle this case, or return an error here.
      }
      // Handle the event
      Subscription subscription = null;
      switch (event.getType()) {
        case "customer.subscription.deleted":
          subscription = (Subscription) stripeObject;
          // Then define and call a function to handle the event
          // customer.subscription.deleted
          // handleSubscriptionTrialEnding(subscription);
        case "customer.subscription.trial_will_end":
          subscription = (Subscription) stripeObject;
          // Then define and call a function to handle the event
          // customer.subscription.trial_will_end
          // handleSubscriptionDeleted(subscriptionDeleted);
        case "customer.subscription.created":
          subscription = (Subscription) stripeObject;
          // Then define and call a function to handle the event
          // customer.subscription.created
          // handleSubscriptionCreated(subscription);
        case "customer.subscription.updated":
          subscription = (Subscription) stripeObject;
          // Then define and call a function to handle the event
          // customer.subscription.updated
          // handleSubscriptionUpdated(subscription);
        case "entitlements.active_entitlement_summary.updated":
          subscription = (Subscription) stripeObject;
          // Then define and call a function to handle the event
          // entitlements.active_entitlement_summary.updated
          // handleEntitlementUpdated(subscription);
          // ... handle other event types
        default:
          System.out.println("Unhandled event type: " + event.getType());
      }
      response.status(200);
      return "";
    });
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)
## Próximos pasos

#### [Actualiza los precios de las suscripciones](https://docs.stripe.com/billing/subscriptions/change-price.md)

Actualiza las suscripciones para gestionar traspasos de los clientes a planes de precios superiores o inferiores.

#### [Aplicar prorrateos](https://docs.stripe.com/billing/subscriptions/prorations.md)

Aprende a ajustar la factura de un cliente para que refleje con precisión los cambios de precios de mitad de ciclo.

#### [Ofrecer ventas de productos adicionales](https://docs.stripe.com/payments/checkout/upsells.md)

Incentiva a los clientes con descuentos por comprometerse con intervalos de facturación más prolongados.
