« 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 ),
),
) );

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.