# Générer un reçu fiscal Cerfa en PDF depuis un template après un don Stripe

> Comment produire un reçu fiscal conforme au Cerfa 11580 en PDF, directement depuis un template de thème, après la confirmation d'un don Stripe.

- Auteur : WordPress Développement
- Publié le : 2024-10-18
- Mis à jour le : 2024-10-18
- Catégorie : Thèmes
- URL : https://www.wpmoderne.fr/themes/recu-fiscal-don-stripe-template/

## L’essentiel

- Génération du PDF déclenchée par un webhook Stripe confirmé
- Structure Cerfa 11580 respectée sans plugin dédié
- Archivage et renvoi du reçu limités à ce que gère le thème

« Le reçu, vous pouvez me le renvoyer par mail ? » Cette question, une association caritative l'a posée deux jours après un premier don en ligne encaissé via Stripe. Le site ne générait alors qu'une simple page de remerciement, sans trace exploitable pour la déclaration d'impôts du donateur. Il a fallu construire, depuis un template de thème, un vrai reçu fiscal au format Cerfa 11580, sans ajouter de plugin de dons supplémentaire à une pile déjà chargée.

Ce billet détaille la recette utilisée : un template dédié, une bibliothèque PDF légère, et un webhook Stripe comme déclencheur unique. Il ne traite ni de la déclaration fiscale de l'association ni de sa comptabilité complète — uniquement la production du document remis au donateur.

## Le problème : un don sans preuve exploitable

Le formulaire de don utilisait déjà Stripe Elements pour capturer la carte bancaire, avec une confirmation de paiement affichée sur une page de retour classique. Techniquement, le don était bien encaissé. Mais rien ne matérialisait ce don pour le donateur au format attendu par l'administration fiscale française : le Cerfa 11580 impose un formulaire précis, avec mentions obligatoires (identité de l'organisme, objet, montant, mode de versement, absence de contrepartie).

Renvoyer ces reçus à la main, un par un, n'était pas tenable au-delà de quelques dizaines de dons par mois. Il fallait un mécanisme automatique, déclenché au bon moment — c'est-à-dire seulement après confirmation réelle du paiement, jamais à la simple soumission du formulaire.

## Le webhook Stripe comme unique déclencheur

Le piège classique consiste à générer le reçu dès que l'utilisateur clique sur « Payer ». Or, entre ce clic et la confirmation réelle par Stripe, plusieurs choses peuvent échouer : carte refusée, 3D Secure abandonné, erreur réseau. Le seul moment fiable est la réception de l'événement `payment_intent.succeeded` sur le endpoint webhook.

```
add_action( 'rest_api_init', function () {
    register_rest_route( 'don/v1', '/stripe-webhook', array(
        'methods'  => 'POST',
        'callback' => 'don_traiter_webhook_stripe',
        'permission_callback' => '__return_true',
    ) );
} );

function don_traiter_webhook_stripe( WP_REST_Request $request ) {
    $payload   = $request->get_body();
    $signature = $request->get_header( 'stripe-signature' );

    try {
        $event = \Stripe\Webhook::constructEvent(
            $payload,
            $signature,
            getenv( 'STRIPE_WEBHOOK_SECRET' )
        );
    } catch ( \Exception $e ) {
        return new WP_REST_Response( array( 'error' => 'signature invalide' ), 400 );
    }

    if ( $event->type === 'payment_intent.succeeded' ) {
        $intent = $event->data->object;
        don_generer_recu_fiscal( $intent );
    }

    return new WP_REST_Response( array( 'ok' => true ), 200 );
}
```

La vérification de signature n'est pas optionnelle : sans elle, n'importe qui pourrait appeler ce endpoint et déclencher de faux reçus. Le secret de webhook doit être stocké en variable d'environnement, jamais en dur dans le thème.

### Récupérer l'identité du donateur

Stripe Elements ne collecte que ce qu'on lui demande. Pour un reçu fiscal complet, il faut au minimum le nom, l'adresse postale et le montant — ce dernier étant déjà disponible dans l'objet `payment_intent`. L'astuce : transmettre ces métadonnées à la création de l'intention de paiement, côté serveur, pour les récupérer intactes dans le webhook.

```
$intent = \Stripe\PaymentIntent::create( array(
    'amount'   => $montant_en_centimes,
    'currency' => 'eur',
    'metadata' => array(
        'donateur_nom'    => sanitize_text_field( $nom ),
        'donateur_adresse' => sanitize_textarea_field( $adresse ),
        'donateur_email'  => sanitize_email( $email ),
    ),
) );
```

> L'essentiel à retenir : Génération du PDF déclenchée par un webhook Stripe confirmé ; Structure Cerfa 11580 respectée sans plugin dédié ; Archivage et renvoi du reçu limités à ce que gère le thème

## Générer le PDF depuis un template de thème

Plutôt qu'un plugin PDF généraliste, la bibliothèque `dompdf/dompdf` installée via Composer suffit largement : elle convertit du HTML/CSS en PDF, ce qui permet de construire le reçu comme un template de thème classique, avec les balises WordPress habituelles.

```
function don_generer_recu_fiscal( $intent ) {
    $donateur = $intent->metadata;
    $montant  = number_format( $intent->amount / 100, 2, ',', ' ' );

    ob_start();
    include get_stylesheet_directory() . '/templates/recu-fiscal.php';
    $html = ob_get_clean();

    $dompdf = new Dompdf\Dompdf();
    $dompdf->loadHtml( $html );
    $dompdf->setPaper( 'A4' );
    $dompdf->render();

    $chemin = wp_upload_dir()['basedir'] . '/recus-fiscaux/' . $intent->id . '.pdf';
    file_put_contents( $chemin, $dompdf->output() );

    don_envoyer_recu_par_email( $donateur['donateur_email'], $chemin );
}
```

Le template `recu-fiscal.php` reprend la structure imposée par le Cerfa 11580 : dénomination de l'organisme, numéro et objet, identité du bénéficiaire, montant en chiffres et en lettres, mode de versement, mention de l'absence de contrepartie. Aucune de ces mentions n'est négociable — un reçu incomplet peut être refusé par l'administration fiscale du donateur.

### Numérotation et archivage

Chaque reçu doit porter un numéro unique et séquentiel. Une simple option WordPress incrémentée à chaque génération suffit pour un volume modeste :

- Lecture du compteur via `get_option( 'don_dernier_numero_recu', 0 )`
- Incrémentation et sauvegarde via `update_option()` avant génération du PDF
- Stockage du PDF dans un dossier protégé, hors de la racine publique accessible directement
- Enregistrement d'une ligne dans une table personnalisée reliant numéro de reçu, identifiant Stripe et date

Cette table dédiée, créée via `dbDelta()` à l'activation du thème, permet de retrouver un reçu à partir de l'identifiant de paiement Stripe en cas de réclamation, sans dépendre d'une recherche dans les emails envoyés.

## Ce que cette recette ne couvre pas

Il est important de border le périmètre. Cette mécanique produit un document individuel remis au donateur ; elle ne remplace ni la déclaration fiscale annuelle de l'association, ni sa comptabilité générale, ni le rapprochement bancaire des virements Stripe. Le trésorier de l'association garde la responsabilité de vérifier, en fin d'exercice, que la somme des reçus émis correspond bien aux montants effectivement reçus sur le compte bancaire.

> Un reçu fiscal automatisé retire de la charge administrative, mais ne retire pas la responsabilité de vérification humaine en fin d'année. Gardez toujours un export listant tous les reçus émis, consultable sans avoir à interroger la base Stripe.

## En résumé

Pour une association qui reçoit des dons ponctuels via Stripe, un template dédié couplé à un webhook signé et à Dompdf permet de produire un reçu fiscal conforme sans ajouter de plugin de dons complet. La clé du dispositif tient en trois points : ne déclencher la génération qu'après confirmation réelle du paiement, respecter scrupuleusement la structure du Cerfa 11580, et conserver une table de correspondance entre numéros de reçus et identifiants Stripe pour pouvoir répondre à toute demande a posteriori.
