Encaissement des paiements par carte
Préparez votre application et votre back-end pour l'encaissement des paiements par carte à l'aide de Stripe Terminal.
Pour les lecteurs BBPOS WisePOS E et Stripe Reader S700, nous recommandons une intégration côté serveur, car elle utilise l’API Stripe au lieu d’un SDK Terminal pour collecter les paiements.
La définition d’un tunnel de paiement dans votre application est nécessaire pour encaisser des paiements avec Stripe Terminal. Utilisez le SDK Stripe Terminal pour créer et mettre à jour un PaymentIntent, un objet représentant une session de paiement individuelle.
Bien que les concepts fondamentaux d’une intégration pilotée par serveur soient similaires à ceux des intégrations basées sur des SDK, les étapes à suivre sont légèrement différentes :
- Créez un PaymentIntent. Vous pouvez décider de capturer vos paiements automatiquement ou manuellement.
- Traitez le paiement. L’autorisation sur la carte bancaire du client a lieu lorsque le lecteur traite le paiement.
- (facultatif) Capturez le PaymentIntent
Remarque
Cette forme d’intégration ne prend pas en charge les paiements par carte hors ligne.
Créer un PaymentIntent
La première étape de l’encaissement d’un paiement consiste à démarrer le tunnel de paiement. Lorsque le client commence son paiement, votre back-end doit créer un objet PaymentIntent qui représente une nouvelle session de paiement sur Stripe. Avec l’intégration pilotée par serveur, le PaymentIntent doit être créé côté serveur.
Dans un environnement de test, vous pouvez utiliser des montants tests pour simuler différents scénarios d’erreurs. En mode production, le montant du PaymentIntent s’affiche sur le lecteur pour le paiement.
Pour les paiements Terminal, le paramètre payment_
doit inclure l’option card_
.
Pour accepter les paiements Interac au Canada, vous devez également inclure interac_
dans payment_
. En savoir plus sur les considérations régionales pour le Canada.
Pour accepter les moyens de paiement autres que les cartes dans les pays pris en charge, vous devez également spécifier vos types préférés dans payment_
. En savoir plus sur les autres moyens de paiement.
Vous pouvez contrôler le tunnel de paiement de la manière suivante :
- Pour contrôler totalement le tunnel de paiement des transactions
card_
, définissez le paramètrepresent capture_
surmethod manual
. Cela vous permet d’ajouter une étape de rapprochement avant la finalisation du paiement. - Pour capturer et autoriser simultanément des paiements, définissez le paramètre
capture_
surmethod automatic
.
Traiter le paiement
Vous pouvez choisir de traiter un paiement immédiatement avec la carte présentée par votre client ou de vérifier d’abord les informations de carte. Nous vous recommandons le traitement immédiat pour la plupart des cas d’usage, car il s’agit d’une intégration plus simple avec moins d’appels à l’API et d’événements de webhook. Toutefois, si vous souhaitez insérer votre propre logique métier avant l’autorisation de la carte, vous pouvez utiliser le flux de collecte et de confirmation en deux étapes.
Si vous utilisez un lecteur de simulation, utilisez l’endpoint present_payment_method pour simuler la présentation ou l’insertion d’une carte bancaire dans le lecteur. Utilisez des cartes de test pour simuler différents scénarios de réussite ou d’échec.
Capturer le paiement
Si vous avez réglé capture_
sur manual
lors de la création du PaymentIntent à l’étape 1, le SDK renvoie à votre application un PaymentIntent autorisé, mais non capturé. En savoir plus sur la différence entre autorisation et capture. Lorsque votre application reçoit un PaymentIntent confirmé, veillez à ce qu’elle demande à votre back-end de capturer le PaymentIntent. Pour cela, créez dans votre back-end un endpoint qui accepte un ID de PaymentIntent et envoie une demande de capture à l’API Stripe.
Si l’appel de capture réussit, l’état du PaymentIntent passe à succeeded
.
Avertissement
Vous devez capturer les PaymentIntents
manuellement sous deux jours, faute de quoi l’autorisation expire et les fonds sont restitués au client.
Vérifier l’état du lecteur
Pour vérifier que le lecteur a terminé une action, votre application doit examiner l’état du lecteur avant d’initier une nouvelle action de lecteur. Dans la plupart des cas, vous constaterez que le paiement est approuvé et votre opérateur verra s’afficher l’expérience utilisateur permettant de finaliser la transaction, le cas échéant. Dans d’autres cas, vous pourrez avoir à gérer des erreurs, notamment des refus de paiement.
Utilisez l’une des méthodes suivantes pour vérifier l’état du lecteur :
Écouter les webhooks Recommandé
Pour une plus grande résilience, votre application doit de préférence écouter des webhooks de Stripe afin de recevoir en temps réel des notifications sur l’état du lecteur. Stripe envoie trois webhooks pour informer votre application de l’état d’action d’un lecteur :
État | Description |
---|---|
terminal. | Envoyé lorsqu’une action du lecteur aboutit, par exemple lorsqu’un paiement est autorisé avec succès. |
terminal. | Envoyé lorsqu’une action du lecteur échoue, par exemple lorsqu’une carte est refusée en raison de fonds insuffisants. |
terminal. Bêta | Envoyé lorsqu’une action du lecteur est mise à jour, par exemple lorsqu’un moyen de paiement est collecté (déclenché uniquement pour l’action collect_ ). |
Pour écouter ces webhooks, créez un endpoint de webhook. Il est préférable de configurer un endpoint dédié uniquement à ce type d’événements prioritaires, qui sont essentiels à la réussite du paiement.
Interroger l’API Stripe
En cas de problème de réception du webhook, vous pouvez interroger l’API Stripe en ajoutant à votre interface de point de vente un bouton check status
, que l’opérateur pourra utiliser si nécessaire.
Utiliser le PaymentIntent
Vous pouvez récupérer le PaymentIntent que vous avez transmis au lecteur pour traitement. Lorsque vous créez un PaymentIntent, son état initial est requires_
. Il passe ensuite à requires_
une fois le moyen de paiement collecté, puis à requires_
une fois le paiement correctement traité.
Utiliser l’objet Reader
Vous pouvez utiliser l’objet Reader, qui contient un attribut action indiquant la dernière action reçue par le lecteur, ainsi que son statut. Votre application peut récupérer un objet Reader pour savoir si l’état du lecteur a changé.
L’objet Reader est également renvoyé en réponse à l’étape de traitement du paiement. Lors du traitement d’un paiement, le type d’action
est process_
.
Le paramètre action.
passe à succeeded
lorsque le paiement réussit. Dans ce cas, vous pouvez finaliser la transaction. Les autres valeurs possibles du paramètre action.
sont failed
et in_
.
Gérer les erreurs
Votre application doit pouvoir gérer les erreurs courantes suivantes :
- Éviter les doublons de paiement
- Échecs de paiement
- Expiration du délai de paiement
- Annulation de paiement
- Lecteur occupé
- Expiration du délai imparti au lecteur
- Lecteur hors ligne
- Webhooks manquants
- Webhooks en retard
Éviter les doublons de paiement
L’objet PaymentIntent active les mouvements de fonds sur Stripe : utilisez un seul PaymentIntent pour représenter une transaction.
Réutilisez le même PaymentIntent même après le refus d’une carte (par exemple, pour fonds insuffisants), afin que votre client puisse réessayer avec une autre carte.
Si vous modifiez le PaymentIntent, vous devez appeler process_payment_intent pour mettre à jour les informations de paiement sur le lecteur.
Pour pouvoir être traité par Stripe, un PaymentIntent doit être à l’état requires_
. Un PaymentIntent autorisé, capturé ou annulé ne pourra pas être traité par un lecteur et génèrera une erreur intent_
:
{ "error": { "code": "intent_invalid_state", "doc_url": "https://docs.stripe.com/error-codes#intent-invalid-state", "message": "Payment intent must be in the requires_payment_method state to be processed by a reader.", "type": "invalid_request_error" } }
Échecs de paiement
Le motif d’échec le plus courant est l’échec d’autorisation de paiement (par exemple lorsque la banque du client refuse le paiement en raison de fonds insuffisants).
Lorsqu’une autorisation de paiement échoue, Stripe envoie un webhook terminal.
. Consultez les attributs action.failure_code et action.failure_message pour connaître le motif du refus de paiement :
{ "id": "tmr_xxx", "object": "terminal.reader", "action": { "failure_code": "card_declined", "failure_message": "Your card has insufficient funds.", "process_payment_intent": { "payment_intent": "pi_xxx" }, "status": "failed", "type": "process_payment_intent" }, ... }
En cas de carte refusée, demandez au client de fournir un autre moyen de paiement. Utilisez le même PaymentIntent dans une autre requête à l’endpoint de process_payment_intent. Si vous créez un nouveau PaymentIntent, vous devez annuler le PaymentIntent en échec pour éviter un paiement en double.
Pour les erreurs de lecture de carte (par exemple les erreurs de lecture de la puce), le lecteur invite automatiquement le client à réessayer, sans notification à votre application. En cas d’échecs répétés, vous pouvez inviter le client à utiliser un autre moyen de paiement en envoyant une autre requête process_payment_intent.
Délai de paiement expiré
Un lecteur dont la connexion Internet n’est pas fiable peut échouer à traiter un paiement lorsque l’autorisation de la carte prend plus longtemps que le délai autorisé par le réseau. Le lecteur affiche alors un écran de traitement pendant quelques secondes, suivi d’un écran d’échec, et vous recevez un webhook terminal.
avec le code d’échec (failure_
) connection_
:
{ "id": "tmr_xxx", "object": "terminal.reader", "action": { "failure_code": "connection_error", "failure_message": "Could not connect to Stripe.", "process_payment_intent": { "payment_intent": "pi_xxx" }, "status": "failed", "type": "process_payment_intent" }, ... }
Il est possible que la demande de confirmation de paiement ait été traitée par les systèmes back-end de Stripe, mais que le lecteur se soit déconnecté avant d’avoir reçu la réponse de Stripe. Lorsque vous recevez un webhook avec ce code d’échec, récupérez l’attribut status
du PaymentIntent pour vérifier si le paiement a été autorisé.
Assurez-vous que votre réseau répond à nos exigences en matière de réseau afin de limiter les délais d’attente.
Annulation de paiement
Annulation programmatique
Vous pourriez avoir besoin d’annuler un paiement en cours, par exemple si un client ajoute des articles à son achat alors que votre intégration a déjà initié l’encaissement du paiement au niveau du lecteur. Dans ce cas, utilisez l’endpoint cancel_action pour réinitialiser le lecteur :
Remarque
Vous ne pouvez pas annuler une action de lecteur lorsqu’un paiement est en cours d’autorisation. Si le client a déjà présenté sa carte sur le lecteur pour procéder au paiement, vous devez attendre que le traitement du paiement soit terminé. Les autorisations s’effectuent habituellement en quelques secondes. Si vous appelez cancel_action pendant une autorisation, cela générera une erreur de type terminal_
.
Annulation initiée par le client
Les utilisateurs peuvent définir la valeur de enable_
sur ces endpoints :
Lorsque cette valeur est définie sur « true », les utilisateurs de lecteurs intelligents voient apparaître un bouton d’annulation.

Encaissement des paiements avec possibilité d’annulation
Appuyer sur le bouton d’annulation annule la transaction active. Stripe envoie un webhook terminal.
avec un failure_code de customer_
.
{ "action": { "failure_code": "customer_canceled", "failure_message": "This action could not be completed due to an error on the card reader.", "process_payment_intent": { "payment_intent": "pi_xxx", "process_config": { "enable_customer_cancellation": true } }, "status": "failed", "type": "process_payment_intent" } }
Lecteur occupé
Un lecteur ne peut traiter qu’un seul paiement à la fois. Pendant le traitement d’un paiement, la tentative d’un nouveau paiement échoue avec une erreur terminal_
:
{ "error": { "code": "terminal_reader_busy", "doc_url": "https://docs.stripe.com/error-codes#terminal-reader-timeout", "message": "Reader is currently busy processing another request. Please reference the integration guide at https://stripe.com/docs/terminal/payments/collect-card-payment?terminal-sdk-platform=server-driven#handle-errors for details on how to handle this error.", "type": "invalid_request_error" } }
Les paiements qui n’ont pas commencé à être traités peuvent être remplacés par un nouveau paiement.
Un lecteur rejette également les requêtes API lorsqu’une mise à jour ou une modification des paramètres est en cours.
Expiration du délai imparti au lecteur
Il peut parfois arriver qu’un lecteur ne puisse pas répondre à temps à une requête API en raison d’un problème temporaire de réseau. Dans ce cas, vous recevez un code d’erreur terminal_
:
{ "error": { "code": "terminal_reader_timeout", "doc_url": "https://docs.stripe.com/error-codes#terminal-reader-timeout", "message": "There was a timeout when sending this command to the reader. Please reference the integration guide at https://stripe.com/docs/terminal/payments/collect-card-payment?terminal-sdk-platform=server-driven#handle-errors for details on how to handle this error.", "type": "invalid_request_error" } }
Dans ce cas, nous vous recommandons de réessayer la requête à l’API. Assurez-vous que votre réseau répond à nos exigences en matière de réseau afin de limiter les délais d’attente.
Il peut parfois arriver que le code d’erreur terminal_
soit envoyé à tort. Dans ce scénario, vous recevez une erreur terminal_
de l’API comme décrit ci-dessus, alors que le lecteur a bien reçu la commande. Ce type de faux négatif survient lorsque Stripe envoie un message au lecteur, mais ne reçoit pas d’accusé de réception du lecteur en raison de défaillances temporaires du réseau.
Lecteur hors ligne
Si la connection Internet d’un emplacement est perdue, la communication entre le lecteur et Stripe peut être interrompue. Dans ce cas, le lecteur ne peut pas répondre aux événements lancés par votre application de point de vente et votre infrastructure back-end.
Un lecteur qui ne répond pas régulièrement aux requêtes de l’API est très probablement hors tension (câble d’alimentation débranché ou batterie déchargée) ou non connecté à Internet.
Un lecteur est considéré comme hors ligne si Stripe n’a reçu aucun signal de ce lecteur au cours des 2 dernières minutes. Toute tentative d’appel de méthodes API sur un lecteur hors ligne génère un code d’erreur terminal_
:
{ "error": { "code": "terminal_reader_offline", "doc_url": "https://docs.stripe.com/error-codes#terminal-reader-offline", "message": "Reader is currently offline, please ensure the reader is powered on and connected to the internet before retrying your request. Reference the integration guide at https://stripe.com/docs/terminal/payments/collect-card-payment?terminal-sdk-platform=server-driven#handle-errors for details on how to handle this error.", "type": "invalid_request_error" } }
Reportez-vous à nos exigences en matière de réseau pour vous assurer qu’un lecteur est correctement connecté à Internet.
Webhooks manquants
Lorsqu’un lecteur se déconnecte en cours de paiement, il ne peut pas mettre à jour son état d’action dans l’API. Dans ce scénario, le lecteur affiche un écran d’erreur après présentation de la carte, mais l’objet Reader de l’API n’est pas mis à jour et ne reflète dont pas cet échec. Vous ne recevez pas non plus les webhooks d’action du lecteur. Dans ce cas, un lecteur peut présenter l’état d’action in_
. Le personnel de caisse doit alors intervenir en appelant l’endpoint cancel_action pour réinitialiser l’état du lecteur.
Webhooks en retard
En cas de panne généralisée de Stripe, il peut occasionnellement arriver que les webhooks d’action des lecteurs soient en retard. Dans ce cas, vous pouvez interroger l’état des objets Reader ou PaymentIntent pour connaître leur dernier état.
Événements de webhook
Webhook | Description |
---|---|
terminal. | Envoyé à la réussite d’une action asynchrone. Concerne les actions nécessitant la présentation d’une carte, par exemple process_ , confirm_ , process_ et refund_ . |
terminal. | Envoyé lors de l’échec d’une action asynchrone. Concerne les actions nécessitant une présentation de la carte, comme process_ , process_ ou refund_ . Aucun webhook n’est envoyé pour les actions set_ et cancel_ . Votre intégration doit gérer ces erreurs. |
terminal. | Envoyé à la mise à jour d’une action asynchrone. Concerne les action telles que collect_ . |