# Tester un tunnel de don avec Stripe Checkout et remboursement partiel

> Un don en ligne remboursé à moitié doit rester cohérent sur le reçu fiscal et dans les statistiques. Voici comment couvrir ce scénario par les tests.

- Auteur : WordPress Développement
- Publié le : 2022-04-28
- Mis à jour le : 2022-04-28
- Catégorie : Tests
- URL : https://www.wpmoderne.fr/tests/tester-stripe-checkout-remboursement-partiel/

## L’essentiel

- Un remboursement partiel doit ajuster le montant affiché sans invalider le don entier
- Le webhook charge.refunded distingue le partiel du total via le montant remboursé
- Le test doit rejouer l'événement Stripe, pas simplement appeler une fonction interne

`charge.refunded` : un seul type d'événement Stripe couvre à la fois le remboursement total et le remboursement partiel d'un don, avec une seule différence détectable, le montant remboursé comparé au montant initial de la charge. C'est cette nuance, mal gérée initialement, qui a fait qu'un don remboursé à 30 % apparaissait comme intégralement annulé dans le tableau de bord d'une association cliente.

Le tunnel de don, construit sur Stripe Checkout, générait un reçu fiscal Cerfa dès la confirmation du paiement. Le jour où un donateur a demandé un remboursement partiel suite à une erreur de saisie du montant, le webhook a bien été reçu, mais le code traitait tout `charge.refunded` comme une annulation complète, supprimant le don de la liste des reçus valides au lieu d'en ajuster simplement le montant.

## Distinguer partiel et total dans la charge du webhook

L'objet `charge` transmis par Stripe contient deux champs déterminants : `amount`, le montant initial, et `amount_refunded`, le montant cumulé remboursé. Un remboursement est total seulement quand les deux sont strictement égaux.

```
function determiner_type_remboursement(array $charge): string
{
    if ($charge['amount_refunded'] === 0) {
        return 'aucun';
    }

    return $charge['amount_refunded'] === $charge['amount']
        ? 'total'
        : 'partiel';
}
```

## Le test qui rejoue l'événement Stripe

Plutôt que de tester la fonction isolément avec un tableau construit à la main, le test le plus fiable rejoue une charge utile réaliste, proche de ce que Stripe envoie réellement en webhook.

> L'essentiel à retenir : Un remboursement partiel doit ajuster le montant affiché sans invalider le don entier ; Le webhook charge.refunded distingue le partiel du total via le montant remboursé ; Le test doit rejouer l'événement Stripe, pas simplement appeler une fonction interne

```
class RemboursementDonTest extends WP_UnitTestCase
{
    public function test_un_remboursement_partiel_ajuste_le_montant_sans_annuler_le_don(): void
    {
        $don_id = self::factory()->post->create(['post_type' => 'don']);
        update_post_meta($don_id, '_stripe_charge_id', 'ch_test_123');
        update_post_meta($don_id, '_montant_centimes', 5000);

        $evenement = [
            'type' => 'charge.refunded',
            'data' => ['object' => [
                'id' => 'ch_test_123',
                'amount' => 5000,
                'amount_refunded' => 1500,
            ]],
        ];

        (new GestionnaireWebhookStripe())->traiter($evenement);

        $this->assertSame('rembourse_partiellement', get_post_meta($don_id, '_statut', true));
        $this->assertSame(3500, (int) get_post_meta($don_id, '_montant_net_centimes', true));
    }
}
```

### Vérifier l'impact sur le reçu fiscal

Le point le plus sensible pour un client associatif : le reçu Cerfa déjà émis ne doit jamais être modifié rétroactivement, pour des raisons de conformité documentaire, mais un nouveau don ne doit plus pouvoir être créé sur la base du montant initial non ajusté.

- Le reçu déjà généré reste inchangé, daté et archivé tel quel.
- Le tableau de bord de l'association affiche le montant net réellement conservé, distinct du montant du reçu émis.
- Un export comptable mensuel signale les dons partiellement remboursés dans une colonne dédiée plutôt que de les fondre dans le total.

## Couvrir le remboursement total séparément

Le remboursement total mérite son propre test, car le comportement attendu diffère réellement : le don doit alors passer à un statut `annule`, et une alerte doit prévenir l'équipe association pour vérifier si un reçu fiscal a déjà été transmis au donateur, cas qui nécessite une régularisation manuelle.

```
public function test_un_remboursement_total_annule_le_don(): void
{
    $evenement = [
        'type' => 'charge.refunded',
        'data' => ['object' => [
            'id' => 'ch_test_456',
            'amount' => 2000,
            'amount_refunded' => 2000,
        ]],
    ];

    (new GestionnaireWebhookStripe())->traiter($evenement);

    $this->assertSame('annule', get_post_meta($this->don_id, '_statut', true));
}
```

> Un webhook Stripe qui porte deux significations sous un seul type d'événement est un piège classique : le test doit explicitement couvrir la frontière entre les deux, pas seulement l'un des deux cas.

## En résumé

Un remboursement partiel Stripe n'est pas une simple variante mineure du remboursement total : il exige un traitement métier distinct, un statut différent, et une préservation stricte du reçu fiscal déjà émis. Rejouer l'événement webhook complet dans les tests, plutôt que de tester une fonction isolée, garantit que le code réagit correctement à ce que Stripe envoie réellement, pas à une simplification de confort.
