# Créer une page d'abonnement préconfigurée avec Stripe Checkout

# Page d’abonnement préconfigurée avec Stripe Checkout

Commencez à utiliser notre exemple d’application pour exécuter une intégration d’abonnement complète et fonctionnelle à l’aide de [Stripe Billing](https://docs.stripe.com/billing.md) et [Stripe Checkout](https://docs.stripe.com/payments/checkout.md).

L’application test montre comment rediriger vos clients depuis votre site vers une page de paiement prédéfinie hébergée sur Stripe. Les API Stripe Billing permettent de créer et de gérer des abonnements, des factures et des paiements récurrents, tandis que Checkout fournit l’interface utilisateur préconfigurée, sécurisée et hébergée par Stripe pour collecter les informations du paiement.

Vous pouvez représenter les clients dans votre intégration soit sous forme d’objets [Accounts configuré par le client](https://docs.stripe.com/api/v2/core/accounts/create.md#v2_create_accounts-configuration-customer), soit sous forme d’objets [Customer](https://docs.stripe.com/api/customers/object.md). Pour en savoir plus sur les différences entre ces options, consultez la section [Utiliser des Accounts en tant que clients](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md).

Cliquez après chaque étape pour voir l’exemple de code correspondant. Au fur et à mesure des étapes, par exemple lorsque vous ajoutez des données de tarification, l’outil met à jour l’exemple de code.

Téléchargez et personnalisez l’application test localement pour tester votre intégration.

### Ajouter vos produits et tarifs

Créez ou sélectionnez *produits* (Products represent what your business sells—whether that's a good or a service) et *tarifs* (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) à utiliser dans cet exemple.

> Connectez-vous à votre compte Stripe pour configurer vos produits et tarifs.

### Ajouter des fonctionnalités à votre produit

Créez des fonctionnalités, comme un cadeau d’anniversaire annuel, et associez-les à votre abonnement pour [y donner droit](https://docs.stripe.com/billing/entitlements.md) aux nouveaux abonnés.

Écoutez les [événements de synthèse des droits actifs](https://docs.stripe.com/billing/entitlements.md#webhooks) pour votre [destination d’événements](https://docs.stripe.com/event-destinations.md), et utilisez l’[API de liste des droits actifs](https://docs.stripe.com/api/entitlements/active-entitlement/list.md) pour un client donné afin de fournir les droits de votre client.

### (Facultatif) Activer des moyens de paiement supplémentaires

Utilisez votre [Dashboard](https://dashboard.stripe.com/settings/payment_methods) pour activer les [moyens de paiement pris en charge](https://docs.stripe.com/payments/payment-methods/payment-method-support.md) que vous souhaitez accepter en plus des cartes. Checkout affiche dynamiquement les moyens de paiement activés par ordre de pertinence, en fonction de la localisation du client et d’autres caractéristiques.

### Ajouter une page d’aperçu des tarifs

Ajoutez à votre site une page qui affiche votre produit et permet à vos clients de s’y abonner. Lorsqu’il clique sur **Paiement**, le client est redirigé vers une page [Checkout](https://docs.stripe.com/payments/checkout.md) hébergée par Stripe, ce qui finalise la commande et empêche toute modification ultérieure.

Envisagez d’intégrer une [grille tarification](https://docs.stripe.com/payments/checkout/pricing-table.md) pour afficher dynamiquement vos informations tarification via le Dashboard. En cliquant sur une option tarification, votre client est redirigé vers la page de paiement.

### Ajouter un bouton de paiement

Le bouton de la page d’aperçu de votre commande redirige votre client vers la page de paiement hébergée par Stripe et utilise le `lookup_key` de votre produit pour récupérer le `price_id` sur le serveur.

### Ajouter une page de confirmation de paiement

Créez une page de confirmation de commande pour présenter le message de confirmation de commande ou les détails de la commande à votre client. Associez cette page à la `success_url` de la session Checkout, vers laquelle Stripe redirige le client une fois qu’il a terminé le paiement.

### Ajouter un bouton destiné au portail client

Ajoutez un bouton de redirection vers le portail client pour permettre aux clients de gérer leur abonnement. Lorsque les clients cliquent sur ce bouton, ils sont redirigés vers la page du portail client hébergée par Stripe.

### Rediriger vers la session du portail client

Envoyez une requête à l’endpoint de votre serveur afin de créer une redirection vers une nouvelle session du portail client. Cet exemple utilise le `session_id` de la [session Checkout](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-id) pour illustrer la récupération du `customer_id`. Dans un environnement de production, nous vous recommandons de sauvegarder cette valeur avec l’utilisateur authentifié dans votre base de données.

### Installer la bibliothèque Node de Stripe

Installez le package et importez-le dans votre code. Si vous partez de zéro et qu’il vous faut un fichier package.json, vous pouvez également télécharger les fichiers du projet à l’aide du lien de téléchargement dans l’éditeur de code.

#### npm

Installez la bibliothèque&nbsp;:

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

#### GitHub

Vous pouvez sinon télécharger le code source de la bibliothèque Node de Stripe directement [depuis GitHub](https://github.com/stripe/stripe-node).

### Installer la bibliothèque Ruby de Stripe

Installez le gem Ruby de Stripe et exigez-le dans votre code. Si vous partez de zéro et avez besoin d’un Gemfile, téléchargez les fichiers du projet à l’aide du lien dans l’éditeur de code.

#### Terminal

Installez le gem&nbsp;:

```bash
gem install stripe
```

#### Bundler

Ajoutez cette ligne à votre Gemfile&nbsp;:

```bash
gem 'stripe'
```

#### GitHub

Vous pouvez sinon télécharger le code source du gem Ruby de Stripe directement [depuis GitHub](https://github.com/stripe/stripe-ruby).

### Installer la bibliothèque Java

Ajoutez la dépendance à votre build et importez la bibliothèque. Ou bien, si vous partez de zéro et avez besoin d’un exemple de fichier pom.xml (pour Maven), téléchargez les fichiers du projet à l’aide du lien de téléchargement dans l’éditeur de code.

#### Maven

Ajoutez la dépendance suivante à votre POM et remplacez {VERSION} par le numéro de version que vous souhaitez utiliser.

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

#### Gradle

Ajoutez la dépendance à votre fichier build.gradle et remplacez {VERSION} par le numéro de version que vous souhaitez utiliser.

```bash
implementation "com.stripe:stripe-java:{VERSION}"
```

#### GitHub

Téléchargez le fichier JAR directement [depuis GitHub](https://github.com/stripe/stripe-java/releases/latest).

### Installer le package Python de Stripe

Installez le package Stripe et importez-le dans votre code. Si vous partez de zéro et qu’il vous faut un fichier requirements.txt, téléchargez les fichiers du projet à l’aide du lien de téléchargement dans l’éditeur de code.

#### pip

Installez le package via pip&nbsp;:

```bash
pip3 install stripe
```

#### GitHub

Téléchargez le code source de la bibliothèque stripe-python directement [depuis GitHub](https://github.com/stripe/stripe-python).

### Installer la bibliothèque PHP

Installez la bibliothèque avec composer et initialisez-la avec votre clé API secrète. Si vous partez de zéro et que vous avez besoin d’un fichier composer.json, vous pouvez également télécharger les fichiers à l’aide du lien de téléchargement dans l’éditeur de code.

#### Composer

Installez la bibliothèque&nbsp;:

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

#### GitHub

Vous pouvez sinon télécharger le code source de la bibliothèque php de Stripe directement [depuis GitHub](https://github.com/stripe/stripe-php).

### Configurer votre serveur

Ajoutez la dépendance à votre build et importez la bibliothèque. Si vous partez de zéro et avez besoin d’un fichier go.mod, téléchargez les fichiers du projet à l’aide du lien de téléchargement dans l’éditeur de code.

#### Go

Veillez à initialiser avec des modules Go&nbsp;:

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

#### GitHub

Vous pouvez sinon télécharger le code source de la bibliothèque Go de Stripe directement [depuis GitHub](https://github.com/stripe/stripe-go).

### Installer la bibliothèque Stripe.net

Installez le package avec .NET ou NuGet. Si vous partez de zéro, vous pouvez également télécharger les fichiers qui contiennent un fichier .csproj configuré.

#### .NET

Installez la bibliothèque&nbsp;:

```bash
dotnet add package Stripe.net
```

#### NuGet

Installez la bibliothèque&nbsp;:

```bash
Install-Package Stripe.net
```

#### GitHub

Vous pouvez sinon télécharger le code source de la bibliothèque .NET de Stripe directement [depuis GitHub](https://github.com/stripe/stripe-dotnet).

### Installer les bibliothèques Stripe

Installez les packages et importez-les dans votre code. Si vous partez de zéro et qu’il vous faut un fichier `package.json`, vous pouvez également télécharger les fichiers du projet à l’aide du lien de téléchargement dans l’éditeur de code.

Installez les bibliothèques&nbsp;:

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

### Créer une session Checkout

La [session Checkout](https://docs.stripe.com/api/checkout/sessions.md) détermine ce que votre client voit sur la page de paiement hébergée par Stripe, notamment les postes de factures, le montant et la devise de la commande, ainsi que les moyens de paiement acceptés.

### Obtenir le prix à partir de la clé de recherche

Transmettez la clé de recherche que vous avez définie pour votre produit dans l’endpoint [Price](https://docs.stripe.com/api/prices/list.md) afin d’appliquer son tarif à la commande.

### Définir les postes de facture

Conservez toujours sur votre serveur les informations sensibles relatives à l’inventaire de vos produits, notamment leur prix et leur disponibilité, pour éviter toute manipulation de la part du client. Transmettez l’ID du prix prédéfini récupéré ci-dessus.

### Définir le mode

Définissez le mode sur `subscription`. Checkout prend également en charge les modes [paiement](https://docs.stripe.com/checkout/quickstart.md) et [configuration](https://docs.stripe.com/payments/save-and-reuse.md) pour les paiements non récurrents.

### URL de confirmation de fourniture

Indiquez une URL accessible au public vers laquelle Stripe peut rediriger les clients après une opération réussie. Ajoutez le paramètre de requête `session_id` à la fin de votre URL afin de pouvoir récupérer le client ultérieurement et permettre à Stripe de générer le Dashboard hébergé du client.

### Rediriger depuis Checkout

Après avoir créé la session, redirigez votre client vers l’URL renvoyée dans la réponse (l’URL de réussite ou d’annulation).

### Créer une session de portail client

Lancez une [session de portail client](https://docs.stripe.com/api/customer_portal/sessions/create.md) sécurisée et hébergée par Stripe, qui permettra à vos clients de gérer leurs abonnements et leurs informations de facturation.

### Rediriger vers le portail client

Après avoir créé la session du portail, redirigez votre client vers l’URL renvoyée dans la réponse.

### Traiter l’abonnement

Créez un endpoint `/webhook` et obtenez votre clé secrète de webhook dans l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench pour écouter les événements liés à l’activité des abonnements. Après un paiement réussi et une redirection vers la page de confirmation, vérifiez que l’état de l’abonnement est `active` et accordez à votre client l’accès aux produits et fonctionnalités auxquels il s’est abonné.

### Exécuter le serveur

Définissez la variable d’environnement `STRIPE_WEBHOOK_SECRET` avec votre secret de signature du webhook. Vous trouverez ce secret dans l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench.

Démarrez votre serveur et accédez à <http://localhost:4242/>

```bash
npm start
```

### Exécuter le serveur

Définissez la variable d’environnement `STRIPE_WEBHOOK_SECRET` avec votre secret de signature du webhook. Vous trouverez ce secret dans l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench.

Démarrez votre serveur. Il ouvre automatiquement une fenêtre de navigateur à l’adresse <http://localhost:3000/checkout>

```bash
npm start
```

### Exécuter le serveur

Définissez la variable d’environnement `STRIPE_WEBHOOK_SECRET` avec votre secret de signature du webhook. Vous trouverez ce secret dans l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench.

Démarrez votre serveur et accédez à <http://localhost:4242/>

```bash
ruby server.rb
```

### Exécuter le serveur

Définissez la variable d’environnement `STRIPE_WEBHOOK_SECRET` avec votre secret de signature du webhook. Vous trouverez ce secret dans l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench.

Démarrez votre serveur. Il ouvre automatiquement une fenêtre de navigateur à l’adresse <http://localhost:3000/checkout>

```bash
ruby server.rb
```

### Exécuter le serveur

Définissez la variable d’environnement `STRIPE_WEBHOOK_SECRET` avec votre secret de signature du webhook. Vous trouverez ce secret dans l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench.

Démarrez votre serveur et accédez à <http://localhost:4242/>

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

### Exécuter le serveur

Définissez la variable d’environnement `STRIPE_WEBHOOK_SECRET` avec votre secret de signature du webhook. Vous trouverez ce secret dans l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench.

Démarrez votre serveur. Il ouvre automatiquement une fenêtre de navigateur à l’adresse <http://localhost:3000/checkout>

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

### Exécuter le serveur

Définissez la variable d’environnement `STRIPE_WEBHOOK_SECRET` avec votre secret de signature du webhook. Vous trouverez ce secret dans l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench.

Démarrez votre serveur et accédez à <http://localhost:4242/>

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

### Exécuter le serveur

Définissez la variable d’environnement `STRIPE_WEBHOOK_SECRET` avec votre secret de signature du webhook. Vous trouverez ce secret dans l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench.

Démarrez votre serveur. Il ouvre automatiquement une fenêtre de navigateur à l’adresse <http://localhost:3000/checkout>

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

### Exécuter le serveur

Définissez la variable d’environnement `STRIPE_WEBHOOK_SECRET` avec votre secret de signature du webhook. Vous trouverez ce secret dans l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench.

Démarrez votre serveur et accédez à <http://localhost:4242/>

```bash
dotnet run
```

### Exécuter le serveur

Définissez la variable d’environnement `STRIPE_WEBHOOK_SECRET` avec votre secret de signature du webhook. Vous trouverez ce secret dans l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench.

Démarrez votre serveur. Il ouvre automatiquement une fenêtre de navigateur à l’adresse <http://localhost:3000/checkout>

```bash
dotnet run
```

### Exécuter le serveur

Définissez la variable d’environnement `STRIPE_WEBHOOK_SECRET` avec votre secret de signature du webhook. Vous trouverez ce secret dans l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench.

Démarrez votre serveur et accédez à <http://localhost:4242/>

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

### Exécuter le serveur

Définissez la variable d’environnement `STRIPE_WEBHOOK_SECRET` avec votre secret de signature du webhook. Vous trouverez ce secret dans l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench.

Démarrez votre serveur. Il ouvre automatiquement une fenêtre de navigateur à l’adresse <http://localhost:3000/checkout>

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

### Exécuter le serveur

Définissez la variable d’environnement `STRIPE_WEBHOOK_SECRET` avec votre secret de signature du webhook. Vous trouverez ce secret dans l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench.

Démarrez votre serveur et accédez à <http://localhost:4242/>

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

### Exécuter le serveur

Définissez la variable d’environnement `STRIPE_WEBHOOK_SECRET` avec votre secret de signature du webhook. Vous trouverez ce secret dans l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench.

Démarrez votre serveur. Il ouvre automatiquement une fenêtre de navigateur à l’adresse <http://localhost:3000/checkout>

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

### Faire un essai

Cliquez sur le bouton de paiement. Sur la page de paiement hébergée par Stripe, utilisez l’une de ces cartes bancaires de test pour simuler un paiement.

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

## Ajouter des fonctionnalités de personnalisation

Si vous avez réussi à vous abonner à votre produit lors de votre test, votre intégration de paiement par abonnement est fonctionnelle. Utilisez les boutons ci-dessous pour voir comment personnaliser cet exemple à l’aide de fonctionnalités supplémentaires.

### Ajouter des périodes d’essai

Associez une période d’essai à une session Checkout.

### Ajouter une période d’essai

Utilisez `subscription_data` pour ajouter un nombre entier représentant le nombre de `trial_period_days` avant de débiter le client pour la première fois. La valeur doit être supérieure ou égale à `1`.

Si vous démarrez un essai gratuit sans moyen de paiement, définissez `les paramètres_d’essai[end_behavior][missing_payment_method]` sur `suspendre` ou `annuler` afin que l’abonnement ne se poursuive pas si l’essai se termine sans moyen de paiement. Transmettez ce paramètre dans `abonnement_données` lorsque vous créez une Checkout Session , ou la mettez à jour sur l’abonnement à un autre moment. Consultez la page [Utilisez des périodes d’essai](https://docs.stripe.com/billing/subscriptions/trials/free-trials.md#create-free-trials-without-payment) pour en savoir plus.

### Définir la date de début de cycle de facturation

Spécifiez une date de début du cycle de facturation lors de la création d’une session Checkout.

### Définir la date de début du cycle de facturation des abonnements

Utilisez `subscription_data` afin de définir un horodatage `billing_cycle_anchor` pour la prochaine date de facturation d’un abonnement. Pour en savoir plus, consultez la page [Définir la date de début de cycle de facturation dans Checkout](https://docs.stripe.com/payments/checkout/billing-cycle.md).

### Automatiser la perception des taxes

Calculez et percevez le montant de taxes approprié sur les transactions Stripe. En savoir plus sur [Stripe Tax](https://docs.stripe.com/tax.md) et la [manière de l’intégrer à Checkout](https://docs.stripe.com/tax/checkout.md). [Activez Stripe Tax](https://dashboard.stripe.com/tax) dans le Dashboard avant l’intégration.

### Ajouter le paramètre automatic_tax

Définissez le paramètre `automatic_tax` sur `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)
## Prochaines étapes

#### [Modifier le tarif des abonnements](https://docs.stripe.com/billing/subscriptions/change-price.md)

Modifiez les Abonnement pour gérer les clients qui passent à une offre tarifaire supérieure ou inférieure.

#### [Appliquer les calculs au prorata](https://docs.stripe.com/billing/subscriptions/prorations.md)

Découvrez comment ajuster la facture d’un client pour qu’elle reflète correctement les changements de tarif en milieu de cycle.

#### [Proposer des abonnements supérieurs](https://docs.stripe.com/payments/checkout/upsells.md)

Incitez les clients à prendre un abonnement sur une plus longue période en leur accordant des réductions.
