# Stripe Billing dans un bloc dynamique : un abonnement associatif sans WooCommerce

> Tutoriel pour intégrer Stripe Billing dans un bloc dynamique dédié à la gestion d'un abonnement récurrent léger, sans installer WooCommerce pour un seul besoin.

- Auteur : Clément Hadrot
- Publié le : 2025-08-25
- Mis à jour le : 2025-08-25
- Catégorie : Blocs Gutenberg
- URL : https://wpmoderne.dev.wordpress-developpement.fr/blocs/stripe-billing-bloc-abonnement-associatif/

## L’essentiel

- Webhook Stripe traité par un endpoint REST WordPress dédié
- Statut d'abonnement stocké en post meta plutôt qu'en table personnalisée
- Bloc dynamique affichant le formulaire selon le statut de connexion

2025 aura vu de nombreuses associations chercher une alternative légère à WooCommerce pour un seul besoin précis : faire payer une cotisation annuelle récurrente sans gérer un catalogue de produits. Ce tutoriel construit ce cas précis, un bloc dynamique `cotisation/abonnement-stripe` qui gère un abonnement récurrent via Stripe Billing.

Il ne traite pas la gestion des plannings d'échéance complexes (changement de tarif en cours d'année, proratisation) ni le contrôle d'accès aux contenus réservés aux adhérents, qui relève d'un sujet distinct. L'objectif ici est strict : créer l'abonnement, encaisser le premier paiement, et suivre son renouvellement.

## Pourquoi éviter WooCommerce sur ce cas précis

WooCommerce excelle pour un catalogue de produits avec variantes, stock, expéditions. Une association qui vend une seule cotisation annuelle, sans variante ni stock, hérite avec WooCommerce d'une complexité disproportionnée : tables de commandes, statuts de commande, gestion de panier, autant de concepts inutiles pour un abonnement unique. Un bloc dynamique dédié, appuyé sur Stripe Billing directement, réduit la surface à ce qui sert réellement.

## Étape 1 — Créer le produit et le prix récurrent côté Stripe

Le produit et son prix récurrent se créent une fois, côté tableau de bord Stripe ou via l'API, en dehors de WordPress :

```
stripe products create --name="Cotisation annuelle"
stripe prices create \
  --unit-amount=3500 \
  --currency=eur \
  --recurring[interval]=year \
  --product=prod_XXXXXXXX
```

## Étape 2 — Le bloc dynamique et sa logique d'affichage

Le `render_callback` du bloc vérifie le statut d'abonnement de l'utilisateur connecté, stocké en post meta sur son profil, et affiche soit un bouton d'inscription, soit un état « déjà adhérent » :

```
function cotisation_render_bloc_abonnement( $attributes ) {
    if ( ! is_user_logged_in() ) {
        return '<p>Connectez-vous pour souscrire à la cotisation.</p>';
    }

    $statut = get_user_meta( get_current_user_id(), 'statut_abonnement_stripe', true );

    if ( 'actif' === $statut ) {
        return '<p>Votre cotisation est active. Merci !</p>';
    }

    return cotisation_generer_bouton_checkout();
}
```

> L'essentiel à retenir : Webhook Stripe traité par un endpoint REST WordPress dédié ; Statut d'abonnement stocké en post meta plutôt qu'en table personnalisée ; Bloc dynamique affichant le formulaire selon le statut de connexion

## Étape 3 — Créer la session Checkout en mode abonnement

Le bouton déclenche un appel REST vers un endpoint WordPress dédié, qui crée une session Stripe Checkout en mode `subscription` plutôt qu'en mode `payment` unique :

```
function cotisation_creer_session_checkout( WP_REST_Request $request ) {
    $session = \Stripe\Checkout\Session::create( array(
        'mode'       => 'subscription',
        'line_items' => array( array(
            'price'    => 'price_XXXXXXXX',
            'quantity' => 1,
        ) ),
        'client_reference_id' => get_current_user_id(),
        'success_url'         => home_url( '/merci-adhesion/' ),
        'cancel_url'          => home_url( '/adhesion/' ),
    ) );

    return rest_ensure_response( array( 'url' => $session->url ) );
}
```

## Étape 4 — Traiter le webhook invoice.paid

Un seul événement webhook suffit à couvrir ce cas d'usage : `invoice.paid`, déclenché à chaque paiement réussi, initial ou renouvelé. L'endpoint REST dédié met à jour le post meta du statut d'abonnement, après vérification de la signature Stripe :

```
function cotisation_webhook_stripe( WP_REST_Request $request ) {
    $evenement = \Stripe\Webhook::constructEvent(
        $request->get_body(),
        $request->get_header( 'stripe-signature' ),
        COTISATION_WEBHOOK_SECRET
    );

    if ( 'invoice.paid' === $evenement->type ) {
        $user_id = $evenement->data->object->subscription_details->metadata['user_id'] ?? null;
        if ( $user_id ) {
            update_user_meta( $user_id, 'statut_abonnement_stripe', 'actif' );
        }
    }

    return rest_ensure_response( array( 'reçu' => true ) );
}
```

## Le choix du post meta plutôt qu'une table dédiée

Une table personnalisée aurait pu sembler plus « propre », mais pour une seule donnée par utilisateur (le statut d'abonnement), elle ajoute une migration, une gestion de schéma et des requêtes SQL supplémentaires sans bénéfice réel sur ce volume. Le post meta sur l'utilisateur, via `update_user_meta()`, reste indexé correctement par WordPress et suffit largement tant que le nombre d'adhérents reste dans les milliers, pas les millions.

- Statut d'abonnement stocké en `user_meta`, pas en table personnalisée.
- Un seul événement webhook traité : `invoice.paid`, suffisant pour ce cas.
- Session Checkout en mode `subscription`, jamais en paiement unique reconduit manuellement.

> Avant d'ajouter une table SQL personnalisée, il vaut mieux se demander si le post meta ne suffit pas déjà — la réponse est oui bien plus souvent qu'on ne le pense.

## En résumé

Un abonnement récurrent associatif se construit correctement avec un bloc dynamique léger, une session Stripe Checkout en mode abonnement, et un seul webhook traité côté WordPress. WooCommerce reste pertinent dès qu'un catalogue de produits variés entre en jeu, mais devient un poids inutile pour ce cas d'usage unique et récurrent.
