# L’erreur « Invalid or duplicate order ID » sur une passerelle de paiement

> Une passerelle refuse un paiement en signalant un identifiant de commande déjà utilisé. Le vrai coupable se trouve dans la génération de référence, pas la passerelle.

- Auteur : WordPress Développement
- Publié le : 2021-06-24
- Mis à jour le : 2021-06-24
- Catégorie : E-commerce
- URL : https://www.wpmoderne.fr/ecommerce/invalid-duplicate-order-id-passerelle-paiement/

## L’essentiel

- Identifier la génération de référence de commande en cause
- Corriger l'unicité de l'identifiant transmis à la passerelle
- Distinguer numéro de commande et référence de transaction

« Invalid or duplicate order ID. » Ce message, renvoyé par la quasi-totalité des passerelles de paiement sérieuses (Stripe, PayPal, Ingenico, et bien d'autres), n'a rien d'un bug côté passerelle malgré les apparences. Il signale presque toujours qu'un identifiant déjà transmis lors d'une tentative précédente est réutilisé, ce que la passerelle refuse par sécurité pour éviter un double débit.

## Symptôme : un refus qui semble aléatoire

Le message n'apparaît pas sur toutes les commandes, ce qui complique le diagnostic : il touche surtout les commandes qui ont connu une première tentative de paiement échouée ou abandonnée, suivie d'une nouvelle tentative avec le même identifiant de commande WooCommerce. Sur un site à fort trafic, ce cas de figure reste statistiquement rare mais jamais nul, d'autant plus fréquent que le taux d'abandon en cours de paiement est élevé.

## Diagnostic : où se situe la réutilisation d'identifiant

La cause racine se trouve dans la manière dont l'intégration de la passerelle construit l'identifiant transmis lors de l'appel API. Beaucoup d'intégrations, y compris certaines maison développées rapidement, transmettent directement `$order->get_id()` comme référence de transaction sans y ajouter de composant variable :

```
// Ce qui provoque le problème : réutilisation du même ID
// à chaque nouvelle tentative de paiement sur la même commande
$reference_transaction = $order->get_id();

$reponse = $client_passerelle->creerPaiement([
    'order_id' => $reference_transaction,
    'amount' => $order->get_total(),
]);
```

Si le client abandonne une première tentative de paiement (fermeture d'onglet, retour arrière) puis relance le paiement depuis la même commande WooCommerce, le second appel API porte exactement le même `order_id` que le premier, aux yeux de la passerelle. Certaines passerelles tolèrent cette répétition, d'autres la rejettent explicitement pour prévenir un double débit accidentel.

> L'essentiel à retenir : Identifier la génération de référence de commande en cause ; Corriger l'unicité de l'identifiant transmis à la passerelle ; Distinguer numéro de commande et référence de transaction

## Correctif : distinguer numéro de commande et référence de transaction

La correction consiste à générer une référence de transaction unique à chaque tentative de paiement, tout en conservant le lien avec le numéro de commande WooCommerce pour la réconciliation comptable :

```
function generer_reference_transaction_unique(WC_Order $order): string
{
    $tentative = (int) $order->get_meta('_nombre_tentatives_paiement');
    $tentative++;
    $order->update_meta_data('_nombre_tentatives_paiement', $tentative);
    $order->save();

    return sprintf('%d-t%d', $order->get_id(), $tentative);
}
```

Cette référence composite (numéro de commande suivi d'un numéro de tentative) reste lisible pour un rapprochement comptable manuel tout en garantissant l'unicité attendue par la passerelle à chaque nouvel essai.

## Prévenir la récidive

- Ne jamais transmettre l'identifiant de commande brut comme référence de transaction unique si un client peut relancer un paiement plusieurs fois sur la même commande
- Journaliser chaque tentative avec sa référence exacte, utile pour retrouver l'historique en cas de réclamation client
- Tester explicitement le scénario d'abandon puis de reprise de paiement avant la mise en production d'une nouvelle passerelle

## Prévention à long terme

Ce type d'erreur reste invisible en phase de recette si les tests ne couvrent que le chemin nominal (un paiement réussi du premier coup). Ajouter systématiquement un scénario de test avec échec puis reprise de paiement, pour toute nouvelle intégration de passerelle, aurait révélé le problème avant la mise en production plutôt qu'après les premiers signalements clients.

## En résumé

« Invalid or duplicate order ID » pointe presque toujours vers une confusion entre numéro de commande WooCommerce et référence de transaction transmise à la passerelle. Générer une référence unique par tentative de paiement, tout en gardant le lien avec la commande d'origine, résout durablement ce type d'incident sans toucher à la configuration de la passerelle elle-même.
