Intégrer l’USDC au paiement en ligne
Un guide technique concret pour intégrer les paiements en USDC à votre tunnel de paiement : les modèles d’API, le choix du réseau, l’idempotence des webhooks et les défaillances que vous rencontrerez en production.
En bref
Une intégration de paiement en USDC suit un schéma familier : créer une intention de paiement sur votre serveur (montant, devise, préférences de réseau), recevoir de votre acquéreur une URL de page de paiement hébergée ou une configuration de widget, laisser l’acheteur payer depuis son portefeuille, puis traiter le webhook de confirmation de manière idempotente. Les décisions techniques les plus importantes sont le choix du réseau (Solana ou Base par défaut, pour des frais inférieurs au centime), l’idempotence des webhooks (identifiant de commande + hash de transaction), le parcours de remboursement (collecter l’adresse du portefeuille lors du paiement, exposer une API de remboursement) et une expérience soignée lors de la signature dans le portefeuille (liens profonds vers les portefeuilles mobiles, QR code en solution de repli sur ordinateur). Bien réalisé, un paiement en USDC aboutit en moins de 30 secondes de bout en bout et coûte au commerçant de 0.3% à 1% selon l’acquéreur.
La structure d’API standard
Les API d’acquisition en USDC suivent globalement le modèle d’intention de paiement popularisé par Stripe. Le périmètre minimal :
Le serveur crée l’intention de paiement
POST /v1/paymentsavec un corps contenantamount,currency(USD si le prix est exprimé en monnaie fiduciaire ; USDC s’il est exprimé en stablecoin),settlement_preference(USDC ou monnaie fiduciaire),networks(liste des réseaux autorisés),order_id(votre clé d’idempotence),success_url,cancel_urlet un objetmetadatapour votre propre rapprochement.L’acquéreur renvoie une URL de paiement ou une configuration de widget
Pour la page de paiement hébergée : une URL vers laquelle l’acheteur est redirigé. Pour le widget intégré : une configuration côté client (clé publiable, identifiant de l’intention) que le widget charge. Les deux parcours gèrent la détection du portefeuille, le choix du réseau et l’affichage de la cotation.
L’acheteur signe dans son portefeuille, le transfert on-chain est diffusé
Sur mobile : lien profond (deep link) vers MetaMask, Phantom, Trust, etc. Sur ordinateur : QR code WalletConnect ou fenêtre d’extension de navigateur. L’acheteur vérifie le montant et signe.
L’acquéreur attend les confirmations et déclenche le webhook
POST your_webhook_urlavec une charge utile contenantevent_type: “payment.succeeded”,order_id,amount,tx_hash,networket une signature que vous vérifiez avec le secret de webhook de l’acquéreur.Le serveur marque la commande comme payée de manière idempotente
Vérifiez la signature du webhook, recherchez
(order_id, tx_hash)dans votre base de données, marquez la commande comme payée si ce n’est pas déjà fait, puis lancez l’exécution de la commande.
Le choix du réseau
Le choix des réseaux acceptés est un arbitrage entre expérience utilisateur et coût :
- Solana : frais de réseau inférieurs au centime, confirmation en moins d’une seconde. Le meilleur choix par défaut pour un petit panier moyen.
- Base : quelques centimes de frais de réseau, confirmation en quelques secondes. Large prise en charge par les portefeuilles ; un bon choix par défaut pour un public nativement crypto.
- Polygon, Arbitrum : frais et vitesse comparables à ceux de Base. Les ajouter ne pose pas de problème, sans être strictement nécessaire.
- Mainnet Ethereum : $1–$8+ de frais de réseau selon le gas. Pénible pour les acheteurs sur les petites commandes. À accepter pour les paniers moyens élevés (au-delà de $500) ou en solution de repli.
- Tron : si vous ciblez les flux d’USDT en Asie et en Afrique, il vaut la peine d’envisager la prise en charge de l’USDT sur TRON en plus de l’USDC.
L’idempotence des webhooks
Les webhooks font l’objet de nouvelles tentatives. Votre gestionnaire doit être idempotent. Le schéma standard :
- Vérifiez la signature du webhook par HMAC-SHA256 avec le secret de votre acquéreur.
- Extrayez
(order_id, tx_hash)de la charge utile. - Recherchez cette paire dans votre table
processed_payments. - Si elle existe : renvoyez 200 OK sans rien faire d’autre.
- Si elle n’existe pas : insérez la ligne (avec une contrainte UNIQUE sur la paire), puis marquez la commande comme payée dans votre table principale des commandes, puis lancez l’exécution de la commande.
- Regroupez les opérations de l’étape 5 dans une seule transaction de base de données, afin qu’un plantage en cours de traitement n’entraîne pas une double exécution.
La plupart des webhooks d’acquisition incluent un identifiant de livraison : journalisez-le pour le débogage, mais ne l’utilisez pas comme clé d’idempotence. Les confirmations réseau et les nouvelles tentatives de l’acquéreur peuvent produire des événements payment.succeeded en double, avec des identifiants de livraison différents mais le même tx_hash ; votre dédoublonnage doit reposer sur l’identité on-chain, et non sur la livraison.
Le parcours de remboursement
Deux modèles dominent :
- Remboursement à l’expéditeur : l’acquéreur renvoie les USDC à l’adresse depuis laquelle l’acheteur a payé à l’origine. C’est l’expérience la plus simple ; elle fonctionne parce que l’enregistrement on-chain du paiement contient l’adresse source.
- Remboursement vers une adresse indiquée : l’acheteur indique une adresse de destination pour le remboursement (qui peut différer de l’adresse source s’il a payé depuis une plateforme d’échange ou un hot wallet). La plupart des acquéreurs le permettent via un
POST /v1/refundsavecdestination_address.
Le commerçant paie les frais de réseau du remboursement. Les remboursements totaux comme partiels sont pris en charge. Le remboursement lui-même prend le même temps de confirmation on-chain que le paiement initial.
Les défaillances en production
- L’acheteur abandonne après avoir signé. Le transfert on-chain est diffusé, mais il ferme l’onglet avant que le webhook ne soit déclenché. L’acquéreur détecte et confirme tout de même le paiement grâce à sa surveillance on-chain ; l’exécution de votre commande part du webhook, et non de la redirection.
- L’acheteur paie un montant erroné. La plupart des acquéreurs rejettent les montants qui ne correspondent pas au moment de la détection on-chain. Certains acceptent des correspondances approximatives (dans une marge de tolérance) et signalent l’écart dans le webhook.
- L’acheteur paie sur le mauvais réseau. S’il signe sur Ethereum alors que vous n’acceptez que Solana, le paiement échappe entièrement à la surveillance de votre acquéreur. La plupart des prestataires restituent les fonds via une procédure de récupération ; certains les perdent. Rendez le choix du réseau clair au moment du paiement.
- L’acheteur paie depuis une adresse de plateforme d’échange. Un remboursement à l’adresse source peut être rejeté ou arriver sur le mauvais compte. Collectez explicitement une adresse de destination pour les remboursements lors du paiement, pour tout produit susceptible d’être remboursé.
- Perte de parité d’un stablecoin (depeg). Rare, mais réelle. Si l’USDC perd sensiblement sa parité pendant le bref intervalle entre la cotation et le règlement on-chain, c’est le commerçant ou l’acquéreur qui absorbe la différence, selon le contrat.
Ajoutez le paiement en USDC avec DPT Acquiring
À partir de 0.3% par transaction. Règlement le jour même en USDC ou en monnaie fiduciaire. URL de page de paiement hébergée ou widget intégrable. Documentation du SDK et des webhooks sur merchant.dpt.xyz.