# Encaissement de paiements par carte en mode hors ligne Encaisser des paiements par carte lorsque vous rencontrez des problèmes de connectivité Internet. # iOS > This is a iOS for when terminal-card-present-integration is terminal and terminal-sdk-platform is ios and reader-type is bluetooth. View the full page at https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments?terminal-card-present-integration=terminal&terminal-sdk-platform=ios&reader-type=bluetooth. Le SDK Terminal permet à votre application de continuer à encaisser les paiements à l’aide d’un lecteur mobile sans connexion réseau. > En mode hors ligne, les informations de paiement sont collectées au moment de la vente et l’autorisation n’est tentée qu’après que la connectivité est rétablie et que le paiement est transmis. En tant qu’utilisateur, vous assumez tous les risques de refus et de falsification associés à une transaction hors ligne. Si votre lecteur falsifié ne peut pas transférer les paiements à Stripe, ou si l’émetteur refuse la transaction, il n’y a aucun moyen de récupérer les fonds et il est possible que vous ne receviez pas le paiement du client pour les biens ou services déjà fournis. > > Pour limiter les risques de refus de la part de l’émetteur, nous vous conseillons de : > > - Rétablir la connexion Internet le plus rapidement possible pour enregistrer les paiements sur Stripe. - Bloquer les transactions supérieures à un certain montant. - [Faire échouer tous les paiements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#managing-risk) quand le SDK a stocké un ensemble de transactions dont la somme dépasse un certain montant. ## Encaisser des paiements en mode hors ligne Les paiements hors ligne suivent les mêmes étapes que les paiements en ligne : création, collecte, traitement et capture du paiement. Votre appareil peut passer du mode en ligne au mode hors ligne à n’importe quelle étape du processus. 1. [Activer le mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) 1. [Se connecter à un lecteur en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#connect-while-offline) 1. [Gérer les événements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#handle-offline-events) 1. [Créer un Payment Intent en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#create-payment-intent) 1. [Collecter un moyen de paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#collect-payment-method) 1. [Confirmer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#confirm-payment) 1. [Attendre l’acheminement des paiements](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#wait-for-forward) 1. (Facultatif) [Capturer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#capture-payment) 1. (Facultatif) [Examiner les paiements encaissés hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#examine-offline) ## Activer le mode hors ligne Pour utiliser le mode hors ligne, votre application doit utiliser la version `3.3.0` ou une version ultérieure du SDK Terminal iOS. Utilisez un objet [Configuration](https://docs.stripe.com/api/terminal/configuration.md) ou [le Dashboard](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=dashboard#update-the-default-configuration-for-the-account) afin d’activer le mode hors ligne pour les appareils [pris en charge](https://docs.stripe.com/terminal/features/operate-offline/overview.md?reader-type=bluetooth#availability) dans votre `Location`. ```curl curl https://api.stripe.com/v1/terminal/configurations \ -u "<>:" \ -d "offline[enabled]=true" ``` Après avoir activé le mode hors ligne sur un objet `Configuration`, vous pouvez l’[affecter](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#create-a-configuration-for-an-individual-location) à un objet `Location`. Vous pouvez également activer le mode hors ligne par défaut pour tous les emplacements (`Locations`) en mettant à jour l’objet `Configuration` [par défaut](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#retrieve-the-account-default-configuration) de votre compte. La propagation des modifications apportées à l’API Configuration vers votre SDK et votre lecteur peut prendre quelques minutes. Pour qu’elles soient prises en compte, vous devez vous déconnecter puis vous reconnecter à votre lecteur. ## Se connecter à un lecteur en mode hors ligne Le SDK stocke localement les informations nécessaires sur `Location` après la connexion en ligne. Lors des connexions hors ligne suivantes, il utilise les informations de configuration stockées à partir de cet emplacement`Location`. Pour encaisser des paiements à l’aide d’un lecteur intelligent en mode hors ligne, vous devez avoir établi une connexion à un lecteur mobile du même type au même emplacement (`Location`) en étant en ligne au cours des 30 derniers jours et avoir mis à jour le logiciel de votre lecteur dans ce laps de temps. Si vous tentez de vous connecter à un lecteur hors ligne sans remplir ces conditions, la demande échoue avec une erreur. | Erreur | Résolution | | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Le SDK n’est pas connecté à Internet** | Assurez-vous que l’objet `Location` que vous utilisez est [configuré](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) pour le mode hors ligne. Sinon, connectez-vous en ligne à un lecteur, puis hors ligne à un lecteur du même type. | | **Le lecteur sélectionné nécessite une mise à jour logicielle avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Le logiciel du lecteur n’a pas été mis à jour depuis 30 jours ou plus. Connectez-vous au lecteur en ligne pour le mettre à jour. | | **Le lecteur sélectionné doit être appairé en ligne à cet endroit avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Vous essayez de vous connecter à un type de lecteur auquel votre PDV ne s’est pas encore connecté en ligne. Vous devez d’abord vous connecter en ligne à ce lecteur ou à tout autre lecteur du même type. Si vous voulez vous connecter hors ligne, vous pouvez également vous connecter à un type de lecteur auquel votre PDV s’est déjà connecté en ligne. | Si vous réinstallez l’application ou effectuez une opération qui vide la mémoire du disque pour le SDK (comme l’effacement du cache de votre application de point de vente dans les paramètres de l’appareil de point de vente), vous perdez tous les paiements que le SDK a stockés et qui n’ont pas encore été transmis. Assurez-vous qu’aucun paiement n’est stocké avant d’effectuer une action de suppression. ## Gérer les événements hors ligne [Côté client] - [OfflineDelegate (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Protocols/SCPOfflineDelegate.html) - [NetworkStatus (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Enums/SCPNetworkStatus.html) Pour permettre à votre application de recevoir des mises à jour sur l’état du réseau du SDK et des paiements transmis, implémentez le protocole `OfflineDelegate`et transmettez-le au SDK Terminal. Vous devez définir `OfflineDelegate` avant de collecter les paiements en mode hors ligne. #### Swift ```swift import StripeTerminal class CustomOfflineDelegate: OfflineDelegate { func terminal(_ terminal: Terminal, didChangeOfflineStatus offlineStatus: OfflineStatus) { // Check the value of `offlineStatus` and update your UI accordingly. For instance, // you can check the SDK's network status at `offlineStatus.sdk.networkStatus`. // // You can also check the SDK's current offline status using // `Terminal.shared.offlineStatus.sdk.networkStatus`. } func terminal(_ terminal: Terminal, didForwardPaymentIntent intent: PaymentIntent, error: Error?) { // The PaymentIntent was successfully forwarded, or an error occurred. // Reconcile any local state using the backend-generated `PaymentIntent.stripeId` // and the metadata you supplied when creating the PaymentIntent. // // Note that the `PaymentIntent.stripeId` may still be nil if creating the // PaymentIntent in the backend failed. } func terminal(_ terminal: Terminal, didReportForwardingError error: Error) { // A non-specific error occurred while forwarding a PaymentIntent. // Check the error message and your integration implementation to // troubleshoot. } } ``` #### Swift ```swift import UIKit import StripeTerminal @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { Terminal.initWithTokenProvider(APIClient.shared) Terminal.shared.offlineDelegate = CustomOfflineDelegate() // ... return true } // ... } ``` ## Créer un PaymentIntent en mode en ligne [Côté client] - [createPaymentIntent (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)createPaymentIntent:completion:) - [CreateConfiguration (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCreateConfiguration.html) - [OfflineDetails (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPOfflineDetails.html) Afin prendre en charge le fonctionnement hors ligne, utilisez l’attribut `createPaymentIntent` du SDK pour créer des objets PaymentIntent. Cela permet au SDK de créer des PaymentIntents en mode hors ligne et de les transmettre à Stripe une fois que vous avez rétabli la connexion. En mode hors ligne, les objets `PaymentIntent` ont un champ `stripeId` vide. Nous vous recommandons d’ajouter un identifiant personnalisé aux [metadata](https://docs.stripe.com/payments/payment-intents.md#storing-information-in-metadata) pour faciliter le rapprochement des objets `PaymentIntent`créés hors ligne dans votre base de données. Une fois que le `PaymentIntent` a été transmis à Stripe lors de l’[étape 7](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#wait-for-forward), utilisez votre identifiant personnalisé pour le rapprocher dans le rappel `OfflineDelegate.didForwardPaymentIntent`. #### Swift ```swift import UIKit import StripeTerminal class PaymentViewController: UIViewController { // Action for a "Checkout" button func checkoutAction() throws { // Populate the correct transaction amount from your application. let amount = UInt(10_00) // Build up parameters for creating a `PaymentIntent` let params = try PaymentIntentParametersBuilder( amount: amount, currency: "usd" ).setMetadata(["offlineId": UUID().uuidString]) .build() Terminal.shared.createPaymentIntent(params) { createResult, createError in if let error = createError { // Handle errors in your application. print("createPaymentIntent failed: \(error)") } else if let paymentIntent = createResult { print("createPaymentIntent succeeded")// If the `PaymentIntent` was created offline, its `stripeId` field will be nil. if let onlineCreatedId = paymentIntent.stripeId { print("created online"); } else { print("created offline") } } } } } ``` `Terminal.createPaymentIntent` accepte un paramètre `CreateConfiguration`. Par défaut, si vous êtes en mode hors ligne, le SDK Terminal enregistre tous les paiements hors ligne, puis les transmet au backend de Stripe lorsque la connexion est rétablie. Pour personnaliser ce comportement, vous pouvez transmettre un objet `CreateConfiguration` avec un attribut `offlineBehavior` défini sur `REQUIRE_ONLINE`, `PREFER_ONLINE` ou `FORCE_OFFLINE`. #### Gestion du risque La définition de `offlineBehavior` sur `REQUIRE_ONLINE` entraîne un échec de la transaction en cours si vous fonctionnez en mode hors ligne. Par exemple, vous pouvez refuser les transactions supérieures à un certain montant ou toutes les transactions hors ligne si le SDK a stocké un ensemble de transactions dont la somme dépasse un certain montant. Le SDK expose deux propriétés pour vous aider à gérer les risques : 1. `Terminal.offlineStatus.sdk.offlinePaymentsCount` 1. `Terminal.offlineStatus.sdk.offlinePaymentAmountsByCurrency` #### Gérer la latence en mode hors ligne Based on your network connectivity, the Terminal SDK automatically determines whether to collect payments online or offline. However, you might want to operate offline despite having an active network connection (for example, if you need to collect transactions quickly and your network connection is slow). You can pass a `CreateConfiguration` object with `offlineBehavior` set to `FORCE_OFFLINE` to collect the payment offline regardless of connectivity. Les paiements collectés hors ligne alors que le SDK Terminal dispose d’une connexion réseau active sont transmis en arrière-plan. #### Swift ```swift import UIKit import StripeTerminal class PaymentViewController: UIViewController { // Action for a "Checkout" button func checkoutAction() throws { // ...build up parameters and callback for creating a `PaymentIntent` // Your app might want to prevent offline payments for too large an amount. // Here, we block the payment if the amount is over 1000 usd. // Otherwise, we allow collecting offline if the network connection is unavailable.let offlineBehavior: SCPOfflineBehavior = { if amount > UInt(1_000_00) { return .requireOnline } else { return .preferOnline } }() let createConfiguration = try CreateConfigurationBuilder().setOfflineBehavior(offlineBehavior).build() Terminal.shared.createPaymentIntent(params, createConfig: createConfiguration) { createResult, createError in // handle success or failure } } } ``` ## Collecter un moyen de paiement [Côté client] - [didRequestReaderInput (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Protocols/SCPReaderDisplayDelegate.html#/c:objc\(pl\)SCPReaderDisplayDelegate\(im\)terminal:didRequestReaderInput:) - [CollectPaymentIntentConfiguration (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCollectPaymentIntentConfiguration.html) > La responsabilité du paiement vous incombe lorsque vous utilisez votre lecteur hors ligne. Les données de bande magnétique étant faciles à usurper, Stripe désactive cette option pour les paiements hors ligne. En outre, la présentation des cartes n’est pas prise en charge sur les marchés où l’*authentification forte du client* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase) est requise. La collecte des paiements en mode hors ligne est similaire [à la collecte des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#collect-payment). Utilisez la méthode `didRequestReaderInput` pour afficher les options de présentation de carte valides au client. > Les lecteurs ne prennent pas en charge l’[inspection des informations du moyen de paiement avant autorisation](https://docs.stripe.com/terminal/payments/collect-card-payment.md?terminal-sdk-platform=ios#collect-inspect-payment-method) en mode hors ligne. Bien que vous puissiez toujours utiliser le paramètre `initWithUpdate PaymentIntent` dans `CollectPaymentIntentConfiguration`, le champ `paymentMethod` de la PaymentIntent est absent si le SDK fonctionne hors ligne. #### Swift ```swift import UIKit import StripeTerminal class PaymentViewController: UIViewController { // Action for a "Checkout" button func checkoutAction() { Terminal.shared.collectPaymentMethod(paymentIntent) { collectResult, collectError in if let error = collectError { print("collectPaymentMethod failed: \(error)") } else if let paymentIntent = collectResult { print("collectPaymentMethod succeeded") // ... Confirm the payment } } } } ``` ## Confirmer le paiement [Côté client] La confirmation des paiements en mode hors ligne est similaire à la [confirmation des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#confirm-payment). La principale différence est que votre intégration doit gérer des types d’erreurs spécifiques au mode hors ligne, par exemple lorsque la transaction dépasse la limite maximum de 10 000 USD appliquée par Stripe pour les paiements hors ligne (ou un montant équivalent dans votre devise). Dans certains cas, le SDK peut créer en ligne un `PaymentIntent`, mais le confirmer hors ligne. Dans ce cas, le `PaymentIntent` peut avoir un `stripeId` non nul. S’il a été confirmé hors ligne, `offlineDetails` sera défini et renseigné. #### Swift ```swift import UIKit import StripeTerminal class PaymentViewController: UIViewController { // Action for a "Checkout" button func checkoutAction() { Terminal.shared.confirmPaymentIntent(paymentIntent) { confirmResult, confirmError in if let error = confirmError { // Handle offline-specific errors in your application (for example, // unsupported payment method). print("confirmPaymentIntent failed: \(error)") } else if let confirmedPaymentIntent= confirmResult {print("confirmPaymentIntent succeeded") if let offlineDetails = paymentIntent.offlineDetails { print("confirmed offline"); } else { print("confirmed online") } } } } } ``` #### Fourniture de reçus Vous pouvez avoir besoin d’informations concernant la carte utilisée pour un paiement en mode hors ligne. Par exemple, vous pouvez avoir besoin de générer un reçu pour les clients qui le demandent au moment de l’achat. Si le PaymentIntent est confirmé hors ligne, récupérez sa propriété [OfflineCardPresentDetails](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPOfflineCardPresentDetails.html) from the `paymentIntent.offlineDetails.offlineCardPresentDetails`. Ce hachage contient une propriété [ReceiptDetails](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPReceiptDetails.html) que vous pouvez utiliser pour générer un reçu ainsi que d’autres informations sur la carte bancaire, notamment sa marque et le nom de son titulaire. Les champs des reçus `account_type` et `authorization_response_code` ne sont pas disponibles sur les PaymentIntents traités en mode hors ligne. Les [reçus par e-mail préconfigurés](https://docs.stripe.com/terminal/features/receipts.md#prebuilt) sont uniquement envoyés lorsque la connexion est rétablie et que le paiement est capturé. ## Attendre l'acheminement des paiements [Côté client] Quand l’accès Internet est rétabli, le SDK commence automatiquement à transférer les paiements hors ligne stockés. Le SDK tente de transmettre les paiements même si l’état de son réseau est hors ligne. Cela signifie que votre fournisseur de tokens de connexion peut recevoir une demande de token de connexion, même lorsque l’appareil est hors ligne. Si vous éteignez votre appareil de POS trop tôt, vos paiements risquent de ne pas être transférés. Vous pouvez interroger `Terminal.offlineStatus.sdk.networkStatus` pour vous assurer que votre POS est en ligne et peut transférer des paiements, et `Terminal.offlineStatus.sdk.offlinePaymentsCount` pour connaître le nombre de paiements que le SDK Terminal doit transférer. ## Capturer le paiement Lorsque vous êtes hors ligne, vous pouvez créer des PaymentIntents avec l’attribut `captureMethod` défini sur `automatic`. Une fois que vous avez confirmé ces PaymentIntents, ils passent à l’état `Succeeded` au lieu de `RequiresCapture`. Stripe capture automatiquement les paiements une fois que vous les avez transmis. Si vous choisissez la capture manuelle, les paiements acheminés et autorisés doivent alors être capturés depuis votre back-end ou votre application. - Afin de capturer les paiements depuis votre back-end, utilisez des [webhooks](https://docs.stripe.com/webhooks.md) pour écouter les PaymentIntents à l’état `requires_capture`. - Pour capturer les paiements depuis votre application, attendez que celle-ci reçoive les appels à `OfflineDelegate.didForwardPayment` pour chaque PaymentIntent à mesure que le SDK les transmet. Un PaymentIntent est prêt à capturer si son état est `RequiresCapture` et si le paramètre `offlineDetails` est vide ou présente une valeur `requiresUpload` de `NO` . #### Swift ```swift Terminal.shared.confirmPaymentIntent(paymentIntent) { confirmResult, confirmError in if let error = confirmError { // Handle offline-specific errors in your application (for example, // unsupported payment method). print("confirmPaymentIntent failed: \(error)") } else if let confirmedPaymentIntent = confirmResult { if intent.status == .requiresCapture {if let offlineDetails = confirmedPaymentIntent.offlineDetails(), offlineDetails.requiresUpload { // Offline payment, wait for `didForwardPaymentIntent` (see snippet below) } else { // Online payment, can be captured now } } // else, handle other intent.status results here } } ``` Capturez un paiement hors ligne après qu’il ait été transmis par le SDK dans le `didForwardPaymentIntent` de votre OfflineDelegate : #### Swift ```swift import StripeTerminal class CustomOfflineDelegate: OfflineDelegate { // ... func terminal(_ terminal: Terminal, didForwardPaymentIntent intent: PaymentIntent, error: Error?) { if let error = error { // Handle the error appropriate for your application return } if intent.status == .requiresCapture { // The intent is ready to be captured. } else { // Handle the intent.status as appropriate. } } // ... } ``` ## Examiner les paiements collectés hors ligne Après autorisation, vous pouvez utiliser l’API [PaymentIntents](https://docs.stripe.com/payments/payment-intents.md) pour examiner les informations hors ligne d’un paiement. Accédez aux [informations relatives au moyen de paiement](https://docs.stripe.com/api/charges/object.md#charge_object-payment_method_details-card_present-offline) sur le dernier objet [Charge](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-latest_charge) d’un `PaymentIntent` pour déterminer s’il a été encaissé hors ligne. # Android > This is a Android for when terminal-card-present-integration is terminal and terminal-sdk-platform is android and reader-type is bluetooth. View the full page at https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments?terminal-card-present-integration=terminal&terminal-sdk-platform=android&reader-type=bluetooth. Le SDK Terminal permet à votre application de continuer à encaisser les paiements à l’aide d’un lecteur mobile sans connexion réseau. > En mode hors ligne, les informations de paiement sont collectées au moment de la vente et l’autorisation n’est tentée qu’après que la connectivité est rétablie et que le paiement est transmis. En tant qu’utilisateur, vous assumez tous les risques de refus et de falsification associés à une transaction hors ligne. Si votre lecteur falsifié ne peut pas transférer les paiements à Stripe, ou si l’émetteur refuse la transaction, il n’y a aucun moyen de récupérer les fonds et il est possible que vous ne receviez pas le paiement du client pour les biens ou services déjà fournis. > > Pour limiter les risques de refus de la part de l’émetteur, nous vous conseillons de : > > - Rétablir la connexion Internet le plus rapidement possible pour enregistrer les paiements sur Stripe. - Bloquer les transactions supérieures à un certain montant. - [Faire échouer tous les paiements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#managing-risk) quand le SDK a stocké un ensemble de transactions dont la somme dépasse un certain montant. ## Encaisser des paiements en mode hors ligne Les paiements hors ligne suivent les mêmes étapes que les paiements en ligne : création, collecte, traitement et capture du paiement. Votre appareil peut passer du mode en ligne au mode hors ligne à n’importe quelle étape du processus. 1. [Activer le mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) 1. [Se connecter à un lecteur en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#connect-while-offline) 1. [Gérer les événements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#handle-offline-events) 1. [Créer un Payment Intent en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#create-payment-intent) 1. [Collecter un moyen de paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#collect-payment-method) 1. [Confirmer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#confirm-payment) 1. [Attendre l’acheminement des paiements](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#wait-for-forward) 1. (Facultatif) [Capturer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#capture-payment) 1. (Facultatif) [Examiner les paiements encaissés hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#examine-offline) ## Activer le mode hors ligne Pour utiliser le mode hors ligne, votre application doit utiliser la version `3.2.0` ou une version ultérieure du SDK Terminal Android. Utilisez un objet [Configuration](https://docs.stripe.com/api/terminal/configuration.md) ou [le Dashboard](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=dashboard#update-the-default-configuration-for-the-account) afin d’activer le mode hors ligne pour les appareils [pris en charge](https://docs.stripe.com/terminal/features/operate-offline/overview.md?reader-type=bluetooth#availability) dans votre `Location`. ```curl curl https://api.stripe.com/v1/terminal/configurations \ -u "<>:" \ -d "offline[enabled]=true" ``` Après avoir activé le mode hors ligne sur un objet `Configuration`, vous pouvez l’[affecter](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#create-a-configuration-for-an-individual-location) à un objet `Location`. Vous pouvez également activer le mode hors ligne par défaut pour tous les emplacements (`Locations`) en mettant à jour l’objet `Configuration` [par défaut](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#retrieve-the-account-default-configuration) de votre compte. La propagation des modifications apportées à l’API Configuration vers votre SDK et votre lecteur peut prendre quelques minutes. Pour qu’elles soient prises en compte, vous devez vous déconnecter puis vous reconnecter à votre lecteur. ## Se connecter à un lecteur en mode hors ligne Le SDK stocke localement les informations nécessaires sur `Location` après la connexion en ligne. Lors des connexions hors ligne suivantes, il utilise les informations de configuration stockées à partir de cet emplacement`Location`. Pour encaisser des paiements à l’aide d’un lecteur intelligent en mode hors ligne, vous devez avoir établi une connexion à un lecteur mobile du même type au même emplacement (`Location`) en étant en ligne au cours des 30 derniers jours et avoir mis à jour le logiciel de votre lecteur dans ce laps de temps. Si vous tentez de vous connecter à un lecteur hors ligne sans remplir ces conditions, la demande échoue avec une erreur. | Erreur | Résolution | | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Le SDK n’est pas connecté à Internet** | Assurez-vous que l’objet `Location` que vous utilisez est [configuré](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) pour le mode hors ligne. Sinon, connectez-vous en ligne à un lecteur, puis hors ligne à un lecteur du même type. | | **Le lecteur sélectionné nécessite une mise à jour logicielle avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Le logiciel du lecteur n’a pas été mis à jour depuis 30 jours ou plus. Connectez-vous au lecteur en ligne pour le mettre à jour. | | **Le lecteur sélectionné doit être appairé en ligne à cet endroit avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Vous essayez de vous connecter à un type de lecteur auquel votre PDV ne s’est pas encore connecté en ligne. Vous devez d’abord vous connecter en ligne à ce lecteur ou à tout autre lecteur du même type. Si vous voulez vous connecter hors ligne, vous pouvez également vous connecter à un type de lecteur auquel votre PDV s’est déjà connecté en ligne. | Si vous réinstallez l’application ou effectuez une opération qui vide la mémoire du disque pour le SDK (comme l’effacement du cache de votre application de point de vente dans les paramètres de l’appareil de point de vente), vous perdez tous les paiements que le SDK a stockés et qui n’ont pas encore été transmis. Assurez-vous qu’aucun paiement n’est stocké avant d’effectuer une action de suppression. ## Gérer les événements hors ligne [Côté client] - [OfflineListener (Android)](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.callable/-offline-listener/index.html) - [NetworkStatus (Android)](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-network-status/index.html) Pour permettre à votre application de recevoir des mises à jour sur l’état du réseau du SDK et des paiements transmis, implémentez l’interface `OfflineListener` et transmettez-la au SDK Terminal. Vous devez définir `OfflineListener` avant de collecter les paiements en mode hors ligne. #### Kotlin ```kotlin class CustomOfflineListener : OfflineListener { override fun onOfflineStatusChange(offlineStatus: OfflineStatus) { // Check the value of `offlineStatus` and update your UI accordingly. For instance, // you can check the SDK's network status at `offlineStatus.sdk.networkStatus`. // // You can also check the SDK's current offline status using // `Terminal::offlineStatus`. } override fun onPaymentIntentForwarded(paymentIntent: PaymentIntent, e: TerminalException?) { // The PaymentIntent was successfully forwarded, or an error occurred. // Reconcile any local state using the backend-generated `PaymentIntent::id` // and the metadata you supplied when creating the PaymentIntent. // // Note that the `PaymentIntent::id` may still be null if creating the // PaymentIntent in the backend failed. } override fun onForwardingFailure(e: TerminalException) { // A non-specific error occurred while forwarding a PaymentIntent. // Check the error message and your integration implementation to // troubleshoot. } } ``` #### Kotlin ```kotlin Terminal.init( context = applicationContext, logLevel = LogLevel.VERBOSE, tokenProvider = CustomConnectionTokenProvider(), listener = CustomTerminalListener(), offlineListener = CustomOfflineListener(), ) ``` ## Créer un PaymentIntent en mode en ligne [Côté client] - [createPaymentIntent (Android)](https://stripe.dev/stripe-terminal-android/core/com.stripe.stripeterminal/-terminal/create-payment-intent.html) - [CreateConfiguration (Android)](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-create-configuration/index.html) - [OfflineDetails (Android)](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-offline-details/index.html) Afin prendre en charge le fonctionnement hors ligne, utilisez l’attribut `createPaymentIntent` du SDK pour créer des objets PaymentIntent. Cela permet au SDK de créer des PaymentIntents en mode hors ligne et de les transmettre à Stripe une fois que vous avez rétabli la connexion. En mode hors ligne, les objets `PaymentIntent` ont un champ `id` vide. Nous vous recommandons d’ajouter un identifiant personnalisé aux [metadata](https://docs.stripe.com/payments/payment-intents.md#storing-information-in-metadata) pour faciliter le rapprochement des objets `PaymentIntent`créés hors ligne dans votre base de données. Une fois que le `PaymentIntent` a été transmis à Stripe lors de l’[étape 7](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#wait-for-forward), utilisez votre identifiant personnalisé pour le rapprocher dans le rappel `OfflineListener::onPaymentIntentForwarded`. #### Kotlin ```kotlin private const val TAG = "PaymentActivity" class PaymentActivity : AppCompatActivity() { // Action for a "Checkout" button private fun onCheckout(cart: Cart) { // Build up parameters for creating a `PaymentIntent` val params = PaymentIntentParameters.Builder() .setAmount(cart.total) .setCurrency(cart.currency).setMetadata(mapOf("unique-id" to UUID.randomUUID().toString())) .build() val createPaymentCallback: PaymentIntentCallback = object : PaymentIntentCallback { override fun onSuccess(paymentIntent: PaymentIntent) { Log.d(TAG, "createPaymentIntent succeeded")// If the `PaymentIntent` was created offline, its `id` field will be null. if (paymentIntent.id != null) { Log.d(TAG, "created online") } else { Log.d(TAG, "created offline") } // ... Collect a PaymentMethod } override fun onFailure(e: TerminalException) { Log.e(TAG, "createPaymentIntent failed", e) // Handle errors in your application. } } Terminal.getInstance().createPaymentIntent(params, createPaymentCallback) } } ``` `Terminal.createPaymentIntent` accepte un paramètre `CreateConfiguration`. Par défaut, si vous êtes en mode hors ligne, le SDK Terminal enregistre tous les paiements hors ligne, puis les transmet au backend de Stripe lorsque la connexion est rétablie. Pour personnaliser ce comportement, vous pouvez transmettre un objet `CreateConfiguration` avec un attribut `offlineBehavior` défini sur `REQUIRE_ONLINE`, `PREFER_ONLINE` ou `FORCE_OFFLINE`. #### Gestion du risque La définition de `offlineBehavior` sur `REQUIRE_ONLINE` entraîne un échec de la transaction en cours si vous fonctionnez en mode hors ligne. Par exemple, vous pouvez refuser les transactions supérieures à un certain montant ou toutes les transactions hors ligne si le SDK a stocké un ensemble de transactions dont la somme dépasse un certain montant. Le SDK expose deux propriétés pour vous aider à gérer les risques : 1. `Terminal.offlineStatus.sdk.offlinePaymentsCount` 1. `Terminal.offlineStatus.sdk.offlinePaymentAmountsByCurrency` #### Gérer la latence en mode hors ligne Based on your network connectivity, the Terminal SDK automatically determines whether to collect payments online or offline. However, you might want to operate offline despite having an active network connection (for example, if you need to collect transactions quickly and your network connection is slow). You can pass a `CreateConfiguration` object with `offlineBehavior` set to `FORCE_OFFLINE` to collect the payment offline regardless of connectivity. Les paiements collectés hors ligne alors que le SDK Terminal dispose d’une connexion réseau active sont transmis en arrière-plan. #### Kotlin ```kotlin private const val TAG = "PaymentActivity" class PaymentActivity : AppCompatActivity() { // Action for a "Checkout" button private fun onCheckout(cart: Cart) { // ...build up parameters and callback for creating a `PaymentIntent` // Your app might want to prevent offline payments for too large an amount. // Here, we require a network connection if the payment if the amount is over 1000 usd. // Otherwise, we allow collecting offline if the network connection is unavailable.val offlineBehavior = if (cart.total > 1000000) { OfflineBehavior.REQUIRE_ONLINE } else { OfflineBehavior.PREFER_ONLINE } val createConfig = CreateConfiguration(offlineBehavior) Terminal.getInstance().createPaymentIntent(params, createPaymentCallback, createConfig) } } ``` ## Collecter un moyen de paiement [Côté client] - [onRequestReaderInput (Android)](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.callable/-reader-listener/on-request-reader-input.html) - [CollectPaymentIntentConfiguration (Android)](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-collect-payment-intent-configuration/index.html) > La responsabilité du paiement vous incombe lorsque vous utilisez votre lecteur hors ligne. Les données de bande magnétique étant faciles à usurper, Stripe désactive cette option pour les paiements hors ligne. En outre, la présentation des cartes n’est pas prise en charge sur les marchés où l’*authentification forte du client* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase) est requise. La collecte des paiements en mode hors ligne est similaire [à la collecte des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#collect-payment). Utilisez la méthode `onRequestReaderInput` pour afficher les options de présentation de carte valides au client. > Les lecteurs ne prennent pas en charge l’[inspection des informations du moyen de paiement avant autorisation](https://docs.stripe.com/terminal/payments/collect-card-payment.md?terminal-sdk-platform=android#collect-inspect-payment-method) en mode hors ligne. Bien que vous puissiez toujours définir le paramètre `updatePaymentIntent` dans `CollectPaymentIntentConfiguration`, le champ `paymentMethod` de la PaymentIntent est absent si le SDK fonctionne hors ligne. #### Kotlin ```kotlin private const val TAG = "PaymentActivity" class PaymentActivity : AppCompatActivity() { // Action for a "Checkout" button private fun onCheckout(cart: Cart) { val collectPaymentCallback: PaymentIntentCallback = object : PaymentIntentCallback { override fun onSuccess(paymentIntent: PaymentIntent) { Log.d(TAG, "collectPaymentMethod succeeded") // ... Confirm the payment } override fun onFailure(e: TerminalException) { Log.d(TAG, "collectPaymentMethod failed:", e) } } val collectConfig = CollectPaymentIntentConfiguration.Builder().build() Terminal.getInstance().collectPaymentMethod(paymentIntent, collectPaymentCallback, collectConfig) } } ``` ## Confirmer le paiement [Côté client] La confirmation des paiements en mode hors ligne est similaire à la [confirmation des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#confirm-payment). La principale différence est que votre intégration doit gérer des types d’erreurs spécifiques au mode hors ligne, par exemple lorsque la transaction dépasse la limite maximum de 10 000 USD appliquée par Stripe pour les paiements hors ligne (ou un montant équivalent dans votre devise). Dans certains cas, le SDK peut créer en ligne un `PaymentIntent`, mais le confirmer hors ligne. Dans ce cas, le `PaymentIntent` peut avoir un `id` non nul. S’il a été confirmé hors ligne, `offlineDetails` sera défini et renseigné. #### Kotlin ```kotlin private const val TAG = "PaymentActivity" class PaymentActivity : AppCompatActivity() { // Action for a "Checkout" button private fun onCheckout(cart: Cart) { val confirmPaymentIntentCallback: PaymentIntentCallback = object : PaymentIntentCallback { override fun onSuccess(paymentIntent: PaymentIntent) { Log.d(TAG, "confirmPaymentIntent succeeded")// If the `PaymentIntent` was confirmed offline, `paymentIntent.offlineDetails` will be defined if (paymentIntent.offlineDetails != null) { Log.d(TAG, "confirmed offline") } else { Log.d(TAG, "confirmed online") } } override fun onFailure(e: TerminalException) { // Handle offline-specific errors in your application (for example, // unsupported payment method). Log.e(TAG, "confirmPaymentIntent failed:", e) } } Terminal.getInstance().confirmPaymentIntent(paymentIntent, confirmPaymentIntentCallback) } } ``` #### Fourniture de reçus Vous pouvez avoir besoin d’informations concernant la carte utilisée pour un paiement en mode hors ligne. Par exemple, vous pouvez avoir besoin de générer un reçu pour les clients qui le demandent au moment de l’achat. Si le PaymentIntent est confirmé hors ligne, récupérez sa propriété [OfflineCardPresentDetails](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-offline-card-present-details/index.html) from the `paymentIntent.offlineDetails.offlineCardPresentDetails`. Ce hachage contient une propriété [ReceiptDetails](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-receipt-details/index.html) que vous pouvez utiliser pour générer un reçu ainsi que d’autres informations sur la carte bancaire, notamment sa marque et le nom de son titulaire. Les champs des reçus `account_type` et `authorization_response_code` ne sont pas disponibles sur les PaymentIntents traités en mode hors ligne. Les [reçus par e-mail préconfigurés](https://docs.stripe.com/terminal/features/receipts.md#prebuilt) sont uniquement envoyés lorsque la connexion est rétablie et que le paiement est capturé. ## Attendre l'acheminement des paiements [Côté client] Quand l’accès Internet est rétabli, le SDK commence automatiquement à transférer les paiements hors ligne stockés. Le SDK tente de transmettre les paiements même si l’état de son réseau est hors ligne. Cela signifie que votre fournisseur de tokens de connexion peut recevoir une demande de token de connexion, même lorsque l’appareil est hors ligne. Si vous éteignez votre appareil de POS trop tôt, vos paiements risquent de ne pas être transférés. Vous pouvez interroger `Terminal.offlineStatus.sdk.networkStatus` pour vous assurer que votre POS est en ligne et peut transférer des paiements, et `Terminal.offlineStatus.sdk.offlinePaymentsCount` pour connaître le nombre de paiements que le SDK Terminal doit transférer. ## Capturer le paiement Lorsque vous êtes hors ligne, vous pouvez créer des PaymentIntents avec l’attribut `captureMethod` défini sur `automatic`. Une fois que vous avez confirmé ces PaymentIntents, ils passent à l’état `SUCCEEDED` au lieu de `REQUIRES_CAPTURE` . Stripe capture automatiquement les paiements une fois que vous les avez transmis. Si vous choisissez la capture manuelle, les paiements acheminés et autorisés doivent alors être capturés depuis votre back-end ou votre application. - Afin de capturer les paiements depuis votre back-end, utilisez des [webhooks](https://docs.stripe.com/webhooks.md) pour écouter les PaymentIntents à l’état `requires_capture`. - Pour capturer les paiements depuis votre application, attendez que celle-ci reçoive les appels à `OfflineListener::onPaymentIntentForwarded` pour chaque PaymentIntent à mesure que le SDK les transmet. Un PaymentIntent est prêt à capturer si son état est `REQUIRES_CAPTURE` et si le paramètre `offlineDetails` est vide ou présente une valeur `requiresUpload` de `false` . #### Kotlin ```kotlin private const val TAG = "PaymentActivity" class PaymentActivity : AppCompatActivity() { // Action for a "Checkout" button private fun onCheckout(cart: Cart) { val callback: PaymentIntentCallback = object : PaymentIntentCallback { override fun onSuccess(paymentIntent: PaymentIntent) { Log.d(TAG, "confirmPaymentIntent succeeded") if (paymentIntent.status == PaymentIntentStatus.REQUIRES_CAPTURE) {val offlineDetails = paymentIntent.offlineDetails if (offlineDetails?.requiresUpload == true) { // Offline payment, wait for `onPaymentIntentForwarded` (see snippet below) } else { // Online payment, can be captured now } } else { // Handle other status results here } } override fun onFailure(e: TerminalException) { // Handle offline-specific errors in your application (for example, // unsupported payment method). Log.e(TAG, "confirmPaymentIntent failed:", e) } } Terminal.getInstance().confirmPaymentIntent(paymentIntent, callback) } } ``` Capturez un paiement hors ligne après qu’il ait été transmis par le SDK dans votre `OfflineListener::onPaymentIntentForwarded` : #### Kotlin ```kotlin class CustomOfflineListener : OfflineListener { // ... override fun onPaymentIntentForwarded(paymentIntent: PaymentIntent, e: TerminalException?) { if (e != null) { // Handle the error appropriate for your application } else if (paymentIntent.status == PaymentIntentStatus.REQUIRES_CAPTURE) { // The paymentIntent is ready to be captured } else { // Handle other status results here } } // ... } ``` ## Examiner les paiements collectés hors ligne Après autorisation, vous pouvez utiliser l’API [PaymentIntents](https://docs.stripe.com/payments/payment-intents.md) pour examiner les informations hors ligne d’un paiement. Accédez aux [informations relatives au moyen de paiement](https://docs.stripe.com/api/charges/object.md#charge_object-payment_method_details-card_present-offline) sur le dernier objet [Charge](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-latest_charge) d’un `PaymentIntent` pour déterminer s’il a été encaissé hors ligne. # React Native > This is a React Native for when terminal-card-present-integration is terminal and terminal-sdk-platform is react-native and reader-type is bluetooth. View the full page at https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments?terminal-card-present-integration=terminal&terminal-sdk-platform=react-native&reader-type=bluetooth. Le SDK Terminal permet à votre application de continuer à encaisser les paiements à l’aide d’un lecteur mobile sans connexion réseau. > En mode hors ligne, les informations de paiement sont collectées au moment de la vente et l’autorisation n’est tentée qu’après que la connectivité est rétablie et que le paiement est transmis. En tant qu’utilisateur, vous assumez tous les risques de refus et de falsification associés à une transaction hors ligne. Si votre lecteur falsifié ne peut pas transférer les paiements à Stripe, ou si l’émetteur refuse la transaction, il n’y a aucun moyen de récupérer les fonds et il est possible que vous ne receviez pas le paiement du client pour les biens ou services déjà fournis. > > Pour limiter les risques de refus de la part de l’émetteur, nous vous conseillons de : > > - Rétablir la connexion Internet le plus rapidement possible pour enregistrer les paiements sur Stripe. - Bloquer les transactions supérieures à un certain montant. - [Faire échouer tous les paiements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#managing-risk) quand le SDK a stocké un ensemble de transactions dont la somme dépasse un certain montant. ## Encaisser des paiements en mode hors ligne Les paiements hors ligne suivent les mêmes étapes que les paiements en ligne : création, collecte, traitement et capture du paiement. Votre appareil peut passer du mode en ligne au mode hors ligne à n’importe quelle étape du processus. 1. [Activer le mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) 1. [Se connecter à un lecteur en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#connect-while-offline) 1. [Gérer les événements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#handle-offline-events) 1. [Créer un Payment Intent en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#create-payment-intent) 1. [Collecter un moyen de paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#collect-payment-method) 1. [Confirmer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#confirm-payment) 1. [Attendre l’acheminement des paiements](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#wait-for-forward) 1. (Facultatif) [Capturer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#capture-payment) 1. (Facultatif) [Examiner les paiements encaissés hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#examine-offline) ## Activer le mode hors ligne Utilisez un objet [Configuration](https://docs.stripe.com/api/terminal/configuration.md) ou [le Dashboard](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=dashboard#update-the-default-configuration-for-the-account) afin d’activer le mode hors ligne pour les appareils [pris en charge](https://docs.stripe.com/terminal/features/operate-offline/overview.md?reader-type=bluetooth#availability) dans votre `Location`. ```curl curl https://api.stripe.com/v1/terminal/configurations \ -u "<>:" \ -d "offline[enabled]=true" ``` Après avoir activé le mode hors ligne sur un objet `Configuration`, vous pouvez l’[affecter](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#create-a-configuration-for-an-individual-location) à un objet `Location`. Vous pouvez également activer le mode hors ligne par défaut pour tous les emplacements (`Locations`) en mettant à jour l’objet `Configuration` [par défaut](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#retrieve-the-account-default-configuration) de votre compte. La propagation des modifications apportées à l’API Configuration vers votre SDK et votre lecteur peut prendre quelques minutes. Pour qu’elles soient prises en compte, vous devez vous déconnecter puis vous reconnecter à votre lecteur. ## Se connecter à un lecteur en mode hors ligne Le SDK stocke localement les informations nécessaires sur `Location` après la connexion en ligne. Lors des connexions hors ligne suivantes, il utilise les informations de configuration stockées à partir de cet emplacement`Location`. Pour encaisser des paiements à l’aide d’un lecteur intelligent en mode hors ligne, vous devez avoir établi une connexion à un lecteur mobile du même type au même emplacement (`Location`) en étant en ligne au cours des 30 derniers jours et avoir mis à jour le logiciel de votre lecteur dans ce laps de temps. Si vous tentez de vous connecter à un lecteur hors ligne sans remplir ces conditions, la demande échoue avec une erreur. | Erreur | Résolution | | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Le SDK n’est pas connecté à Internet** | Assurez-vous que l’objet `Location` que vous utilisez est [configuré](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) pour le mode hors ligne. Sinon, connectez-vous en ligne à un lecteur, puis hors ligne à un lecteur du même type. | | **Le lecteur sélectionné nécessite une mise à jour logicielle avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Le logiciel du lecteur n’a pas été mis à jour depuis 30 jours ou plus. Connectez-vous au lecteur en ligne pour le mettre à jour. | | **Le lecteur sélectionné doit être appairé en ligne à cet endroit avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Vous essayez de vous connecter à un type de lecteur auquel votre PDV ne s’est pas encore connecté en ligne. Vous devez d’abord vous connecter en ligne à ce lecteur ou à tout autre lecteur du même type. Si vous voulez vous connecter hors ligne, vous pouvez également vous connecter à un type de lecteur auquel votre PDV s’est déjà connecté en ligne. | Si vous réinstallez l’application ou effectuez une opération qui vide la mémoire du disque pour le SDK (comme l’effacement du cache de votre application de point de vente dans les paramètres de l’appareil de point de vente), vous perdez tous les paiements que le SDK a stockés et qui n’ont pas encore été transmis. Assurez-vous qu’aucun paiement n’est stocké avant d’effectuer une action de suppression. ## Gérer les événements hors ligne [Côté client] - [UserCallbacks (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#UserCallbacks) - [OfflineStatus (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#OfflineStatus) Pour permettre à votre application de recevoir des mises à jour sur l’état du réseau du SDK et des paiements transmis, implémentez les rappels hors ligne sur le hook `useStripeTerminal`. ```js const { connectReader, disconnectReader, connectedReader } = useStripeTerminal({ onDidChangeOfflineStatus(status: OfflineStatus) { // Check the value of `offlineStatus` and update your UI accordingly. // // You can also check the SDK's current offline status calling // `getOfflineStatus`. }, onDidForwardingFailure(error) { // A non-specific error occurred while forwarding a PaymentIntent. // Check the error message and your integration implementation to // troubleshoot. }, onDidForwardPaymentIntent(paymentIntent, error) { // The PaymentIntent was successfully forwarded, or an error occurred. // Reconcile any local state using the backend-generated `paymentIntent.id` // and the metadata you supplied when creating the PaymentIntent. // // Note that the `paymentIntent.id` may still be null if creating the // PaymentIntent in the backend failed. }, }); ``` ## Créer un PaymentIntent en mode en ligne [Côté client] - [createPaymentIntent (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#createPaymentIntent) - [CreatePaymentIntentParams (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#CreatePaymentIntentParams) - [OfflineStatus (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#OfflineStatus) - [OfflineStatusDetails (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#OfflineStatusDetails) Afin prendre en charge le fonctionnement hors ligne, utilisez l’attribut `createPaymentIntent` du SDK pour créer des objets PaymentIntent. Cela permet au SDK de créer des PaymentIntents en mode hors ligne et de les transmettre à Stripe une fois que vous avez rétabli la connexion. En mode hors ligne, les objets `PaymentIntent` ont un champ `id` vide. Nous vous recommandons d’ajouter un identifiant personnalisé aux [metadata](https://docs.stripe.com/payments/payment-intents.md#storing-information-in-metadata) pour faciliter le rapprochement des objets `PaymentIntent`créés hors ligne dans votre base de données. Une fois que le `PaymentIntent` a été transmis à Stripe lors de l’[étape 7](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#wait-for-forward), utilisez votre identifiant personnalisé pour le rapprocher dans le rappel `onDidForwardPaymentIntent`. ```js const _createPaymentIntent = async (cart) => { const {error, paymentIntent} = await createPaymentIntent({ amount: cart.total, currency: cart.currency,metadata: { "unique-id": UUID().uuidString } }); } ``` `Terminal.createPaymentIntent` accepte un paramètre `CreateConfiguration`. Par défaut, si vous êtes en mode hors ligne, le SDK Terminal enregistre tous les paiements hors ligne, puis les transmet au backend de Stripe lorsque la connexion est rétablie. Pour personnaliser ce comportement, vous pouvez transmettre un objet `CreateConfiguration` avec un attribut `offlineBehavior` défini sur `REQUIRE_ONLINE`, `PREFER_ONLINE` ou `FORCE_OFFLINE`. #### Gestion du risque La définition de `offlineBehavior` sur `REQUIRE_ONLINE` entraîne un échec de la transaction en cours si vous fonctionnez en mode hors ligne. Par exemple, vous pouvez refuser les transactions supérieures à un certain montant ou toutes les transactions hors ligne si le SDK a stocké un ensemble de transactions dont la somme dépasse un certain montant. Le SDK expose deux propriétés pour vous aider à gérer les risques : 1. `OfflineStatus.sdk.offlinePaymentsCount` 1. `OfflineStatus.sdk.offlinePaymentAmountsByCurrency` #### Gérer la latence en mode hors ligne Based on your network connectivity, the Terminal SDK automatically determines whether to collect payments online or offline. However, you might want to operate offline despite having an active network connection (for example, if you need to collect transactions quickly and your network connection is slow). You can set `offlineBehavior` to `force_offline` to collect the payment offline regardless of connectivity. Les paiements collectés hors ligne alors que le SDK Terminal dispose d’une connexion réseau active sont transmis en arrière-plan. ```js const _createPaymentIntent = async (cart) => { // Your app might want to prevent offline payments for too large an amount. // Here, we require a network connection if the payment if the amount is over 1000 usd. // Otherwise, we allow collecting offline if the network connection is unavailable.let offlineBehavior: if (cart.total > 1000000) { offlineBehavior = 'require_online' } else { offlineBehavior = 'prefer_online' } const {error, paymentIntent} = await createPaymentIntent({ amount: cart.total, currency: cart.currency,offlineBehavior, }); } ``` ## Collecter un moyen de paiement [Côté client] - [UserCallbacks (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#UserCallbacks) - [CollectPaymentMethodParams (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#CollectPaymentMethodParams) > La responsabilité du paiement vous incombe lorsque vous utilisez votre lecteur hors ligne. Les données de bande magnétique étant faciles à usurper, Stripe désactive cette option pour les paiements hors ligne. En outre, la présentation des cartes n’est pas prise en charge sur les marchés où l’*authentification forte du client* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase) est requise. La collecte des paiements en mode hors ligne est similaire [à la collecte des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#collect-payment). Utilisez la méthode pour afficher les options de présentation de carte valides au client. > La [vérification des informations relatives aux moyens de paiement avant l’autorisation](https://docs.stripe.com/terminal/payments/collect-card-payment.md?terminal-sdk-platform=react-native#collect-inspect-payment-method) n’est pas prise en charge en mode hors ligne. Bien que vous puissiez toujours définir le paramètre `updatePaymentIntent` dans `CollectConfiguration`, le champ `paymentMethod` du PaymentIntent est absent si le SDK fonctionne en mode hors ligne. ```js const _collectPaymentMethod_ = async () => { const { paymentIntent, error } = await collectPaymentMethod({ paymentIntent: paymentIntent }); if (error) { // Handle errors in your application. } // ... Confirm the payment } ``` ## Confirmer le paiement [Côté client] La confirmation des paiements en mode hors ligne est similaire à la [confirmation des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#confirm-payment). La principale différence est que votre intégration doit gérer des types d’erreurs spécifiques au mode hors ligne, par exemple lorsque la transaction dépasse la limite maximum de 10 000 USD appliquée par Stripe pour les paiements hors ligne (ou un montant équivalent dans votre devise). Dans certains cas, le SDK peut créer en ligne un `PaymentIntent`, mais le confirmer hors ligne. Dans ce cas, le `PaymentIntent` peut avoir un `id` non nul. S’il a été confirmé hors ligne, `offlineDetails` sera défini et renseigné. ```js const _confirmPaymentIntent = async () => { const { paymentIntent, error } = await confirmPaymentIntent({ paymentIntent: paymentIntent }); if (error) { // Handle offline-specific errors in your application (for example, // unsupported payment method). } if (paymentIntent.offlineDetails) { console.log('confirmed offline'); } else { console.log('confirmed online'); } } ``` #### Fourniture de reçus Vous pouvez avoir besoin d’informations concernant la carte utilisée pour un paiement en mode hors ligne. Par exemple, vous pouvez avoir besoin de générer un reçu pour les clients qui le demandent au moment de l’achat. Si le PaymentIntent est confirmé hors ligne, récupérez sa propriété [OfflineCardPresentDetails](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#OfflineCardPresentDetails) from the `paymentIntent.offlineDetails.offlineCardPresentDetails`. Ce hachage contient une propriété [ReceiptDetails](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#ReceiptDetails) que vous pouvez utiliser pour générer un reçu ainsi que d’autres informations sur la carte bancaire, notamment sa marque et le nom de son titulaire. Les champs des reçus `account_type` et `authorization_response_code` ne sont pas disponibles sur les PaymentIntents traités en mode hors ligne. Les [reçus par e-mail préconfigurés](https://docs.stripe.com/terminal/features/receipts.md#prebuilt) sont uniquement envoyés lorsque la connexion est rétablie et que le paiement est capturé. ## Attendre l'acheminement des paiements [Côté client] Quand l’accès Internet est rétabli, le SDK commence automatiquement à transférer les paiements hors ligne stockés. Le SDK tente de transmettre les paiements même si l’état de son réseau est hors ligne. Cela signifie que votre fournisseur de tokens de connexion peut recevoir une demande de token de connexion, même lorsque l’appareil est hors ligne. Si vous éteignez votre appareil de POS trop tôt, vos paiements risquent de ne pas être transférés. Vous pouvez interroger `OfflineStatus.sdk.networkStatus` pour vous assurer que votre POS est en ligne et peut transférer des paiements, et `OfflineStatus.sdk.offlinePaymentsCount` pour connaître le nombre de paiements que le SDK Terminal doit transférer. ## Capturer le paiement Lorsque vous êtes hors ligne, vous pouvez créer des PaymentIntents avec l’attribut `captureMethod` défini sur `automatic`. Une fois que vous avez confirmé ces PaymentIntents, ils passent à l’état `succeeded` au lieu de `requiresCapture` . Stripe capture automatiquement les paiements une fois que vous les avez transmis. Si vous choisissez la capture manuelle, les paiements acheminés et autorisés doivent alors être capturés depuis votre back-end ou votre application. - Afin de capturer les paiements depuis votre back-end, utilisez des [webhooks](https://docs.stripe.com/webhooks.md) pour écouter les PaymentIntents à l’état `requires_capture`. - Pour capturer les paiements depuis votre application, attendez que celle-ci reçoive les appels à `useStripeTerminal` hook’s `onDidForwardPaymentIntent` pour chaque PaymentIntent à mesure que le SDK les transmet. Un PaymentIntent est prêt à capturer si son état est `requiresCapture` et si le paramètre `OfflineDetails` est vide ou présente une valeur `requiresUpload` de `false` . ```js const _confirmPaymentIntent = async () => { const { paymentIntent, error } = await confirmPaymentIntent({ paymentIntent: paymentIntent }); if (error) { // Handle offline-specific errors in your application (for example, // unsupported payment method). } if (paymentIntent.status == 'requiresCapture') {const offlineDetails = paymentIntent.offlineDetails; if (offlineDetails.requiresUpload === true) { // Offline payment, wait for `onDidForwardPaymentIntent` (see snippet below) } else { // Online payment, can be captured now } } else { // handle other paymentIntent.status results here } } ``` Capturez un paiement hors ligne après qu’il ait été transmis par le SDK dans `onDidForwardPaymentIntent` : ```js const { connectReader, disconnectReader, connectedReader } = useStripeTerminal({ onDidForwardPaymentIntent(paymentIntent, error) { if (error) { // Handle the error appropriate for your application } else if (paymentIntent.status == 'requires_capture') { // The paymentIntent is ready to be captured } else { // Handle the paymentIntent.status as appropriate. } }, }); ``` ## Examiner les paiements collectés hors ligne Après autorisation, vous pouvez utiliser l’API [PaymentIntents](https://docs.stripe.com/payments/payment-intents.md) pour examiner les informations hors ligne d’un paiement. Accédez aux [informations relatives au moyen de paiement](https://docs.stripe.com/api/charges/object.md#charge_object-payment_method_details-card_present-offline) sur le dernier objet [Charge](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-latest_charge) d’un `PaymentIntent` pour déterminer s’il a été encaissé hors ligne. # iOS > This is a iOS for when terminal-card-present-integration is terminal and terminal-sdk-platform is ios and reader-type is internet. View the full page at https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments?terminal-card-present-integration=terminal&terminal-sdk-platform=ios&reader-type=internet. Le SDK Terminal permet à votre application de continuer à encaisser des paiements à l’aide d’un lecteur intelligent sans connexion Internet. Si vous utilisez un appareil de PDV distinct avec un lecteur Stripe intelligent, vous avez tout de même besoin d’un réseau local opérationnel pour autoriser votre appareil de PDV à communiquer avec le lecteur intelligent. Le fonctionnement hors ligne avec des lecteurs intelligents concerne les scénarios dans lesquels votre PDV et votre lecteur ne peuvent pas communiquer avec Stripe, par exemple en cas de panne du fournisseur d’accès à Internet. Si vous avez besoin de pouvoir fonctionner hors ligne sans réseau local, les [lecteurs mobiles](https://docs.stripe.com/terminal/mobile-readers.md) de Stripe Terminal peuvent vous être utiles. Vous pouvez également fonctionner hors ligne avec une intégration d’applications sur des appareils. Dans la mesure où votre application de PDV fonctionne directement sur le lecteur intelligent, vous n’avez pas besoin d’un réseau local pour encaisser des paiements. Toutefois, vous devez tout de même être sur un réseau local au premier démarrage de votre lecteur, même si ce réseau n’a pas accès à Internet. > En mode hors ligne, les informations de paiement sont collectées au moment de la vente et l’autorisation n’est tentée qu’après que la connectivité est rétablie et que le paiement est transmis. Lorsqu’il fonctionne hors ligne avec un lecteur connecté à Internet, le lecteur stocke les informations de paiement collectées. En tant qu’utilisateur, vous assumez tous les risques de refus et de falsification associés à une transaction hors ligne. Si votre lecteur falsifié ne peut pas transférer les paiements à Stripe, ou si l’émetteur refuse la transaction, il n’y a aucun moyen de récupérer les fonds et il est possible que vous ne receviez pas le paiement du client pour les biens ou services déjà fournis. > > Pour limiter les risques de refus de la part de l’émetteur, nous vous conseillons de : > > - Rétablir la connexion Internet le plus rapidement possible pour enregistrer les paiements sur Stripe. - Bloquer les transactions supérieures à un certain montant. - [Faire échouer tous les paiements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#managing-risk) quand le SDK a stocké un ensemble de transactions dont la somme dépasse un certain montant. ## Encaisser des paiements en mode hors ligne Les paiements hors ligne suivent les mêmes étapes que les paiements en ligne : création, collecte, traitement et capture du paiement. Votre appareil peut passer du mode en ligne au mode hors ligne à n’importe quelle étape du processus. 1. [Activer le mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) 1. [Se connecter à un lecteur en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#connect-while-offline) 1. [Gérer les événements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#handle-offline-events) 1. [Créer un Payment Intent en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#create-payment-intent) 1. [Collecter un moyen de paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#collect-payment-method) 1. [Confirmer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#confirm-payment) 1. [Attendre l’acheminement des paiements](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#wait-for-forward) 1. (Facultatif) [Capturer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#capture-payment) 1. (Facultatif) [Examiner les paiements encaissés hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#examine-offline) ## Activer le mode hors ligne Pour utiliser le mode hors ligne, votre application doit utiliser la version `3.3.0` ou une version ultérieure du SDK Terminal iOS. Utilisez un objet [Configuration](https://docs.stripe.com/api/terminal/configuration.md) ou [le Dashboard](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=dashboard#update-the-default-configuration-for-the-account) afin d’activer le mode hors ligne pour les appareils [pris en charge](https://docs.stripe.com/terminal/features/operate-offline/overview.md?reader-type=internet#availability) dans votre `Location`. ```curl curl https://api.stripe.com/v1/terminal/configurations \ -u "<>:" \ -d "offline[enabled]=true" ``` Après avoir activé le mode hors ligne sur un objet `Configuration`, vous pouvez l’[affecter](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#create-a-configuration-for-an-individual-location) à un objet `Location`. Vous pouvez également activer le mode hors ligne par défaut pour tous les emplacements (`Locations`) en mettant à jour l’objet `Configuration` [par défaut](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#retrieve-the-account-default-configuration) de votre compte. La propagation des modifications apportées à l’API Configuration vers votre SDK et votre lecteur peut prendre quelques minutes. Pour qu’elles soient prises en compte, vous devez vous déconnecter puis vous reconnecter à votre lecteur. ## Se connecter à un lecteur en mode hors ligne Le lecteur stocke localement les informations nécessaires sur `Location` après la connexion en ligne. Lors des connexions hors ligne suivantes, il utilise les informations de configuration stockées à partir de cet emplacement`Location`. Pour encaisser des paiements à l’aide d’un lecteur intelligent en mode hors ligne, vous devez avoir établi une connexion à un lecteur mobile du même type au même emplacement (`Location`) en étant en ligne au cours des 30 derniers jours sur le même réseau local. Le lecteur stocke les informations relatives à l’objet `Location` en local après s’être connecté en ligne, puis déduit les informations de configuration de cet emplacement `Location` lorsqu’il fonctionne hors ligne. Votre lecteur et votre appareil de point de vente doivent être sur le même réseau local que celui utilisé pour se connecter à Internet. Vous ne pouvez pas changer de réseau en mode hors ligne. Si vous tentez de vous connecter à un lecteur hors ligne sans remplir ces conditions, la demande échoue avec une erreur. | Erreur | Résolution | | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Le SDK n’est pas connecté à Internet** | Assurez-vous que l’objet `Location` que vous utilisez est [configuré](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) pour le mode hors ligne. Sinon, connectez-vous en ligne à un lecteur, puis hors ligne à un lecteur du même type. | | **Le lecteur sélectionné nécessite une mise à jour logicielle avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Le logiciel du lecteur n’a pas été mis à jour depuis 30 jours ou plus. Connectez-vous au lecteur en ligne pour le mettre à jour. | | **Le lecteur sélectionné doit être appairé en ligne à cet endroit avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Vous essayez de vous connecter à un type de lecteur auquel votre PDV ne s’est pas encore connecté en ligne. Vous devez d’abord vous connecter en ligne à ce lecteur ou à tout autre lecteur du même type. Si vous voulez vous connecter hors ligne, vous pouvez également vous connecter à un type de lecteur auquel votre PDV s’est déjà connecté en ligne. | ## Gérer les événements hors ligne [Côté client] - [OfflineDelegate (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Protocols/SCPOfflineDelegate.html) Pour permettre à votre application de recevoir des mises à jour sur l’état du réseau du SDK et des paiements transmis, implémentez le protocole `OfflineDelegate`et transmettez-le au SDK Terminal. Vous devez définir `OfflineDelegate` avant de collecter les paiements en mode hors ligne. #### Swift ```swift import StripeTerminal class CustomOfflineDelegate: OfflineDelegate { func terminal(_ terminal: Terminal, didChangeOfflineStatus offlineStatus: OfflineStatus) { // Check the value of `offlineStatus` and update your UI accordingly. For instance, // you can check the SDK's network status at `offlineStatus.sdk.networkStatus`. // // You can also check the SDK's current offline status using // `Terminal.shared.offlineStatus.sdk.networkStatus`. } func terminal(_ terminal: Terminal, didForwardPaymentIntent intent: PaymentIntent, error: Error?) { // The PaymentIntent was successfully forwarded, or an error occurred. // Reconcile any local state using the backend-generated `PaymentIntent.stripeId` // and the metadata you supplied when creating the PaymentIntent. // // Note that the `PaymentIntent.stripeId` may still be nil if creating the // PaymentIntent in the backend failed. } func terminal(_ terminal: Terminal, didReportForwardingError error: Error) { // A non-specific error occurred while forwarding a PaymentIntent. // Check the error message and your integration implementation to // troubleshoot. } } ``` #### Swift ```swift import UIKit import StripeTerminal @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { Terminal.initWithTokenProvider(APIClient.shared) Terminal.shared.offlineDelegate = CustomOfflineDelegate() // ... return true } // ... } ``` ## Créer un PaymentIntent en mode en ligne [Côté client] - [createPaymentIntent (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)createPaymentIntent:completion:) - [CreateConfiguration (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCreateConfiguration.html) - [OfflineDetails (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPOfflineDetails.html) Afin prendre en charge le fonctionnement hors ligne, utilisez l’attribut `createPaymentIntent` du SDK pour créer des objets PaymentIntent. Cela permet au SDK de créer des PaymentIntents en mode hors ligne et de les transmettre à Stripe une fois que vous avez rétabli la connexion. En mode hors ligne, les objets `PaymentIntent` ont un champ `stripeId` vide. Nous vous recommandons d’ajouter un identifiant personnalisé aux [metadata](https://docs.stripe.com/payments/payment-intents.md#storing-information-in-metadata) pour faciliter le rapprochement des objets `PaymentIntent`créés hors ligne dans votre base de données. Vous pouvez configurer un endpoint de [webhook](https://docs.stripe.com/webhooks.md) pour recevoir des événements `PaymentIntent` lorsque des paiements hors ligne sont transmis à Stripe, et utiliser votre identifiant pour les associer à un ID `PaymentIntent`. #### Swift ```swift import UIKit import StripeTerminal class PaymentViewController: UIViewController { // Action for a "Checkout" button func checkoutAction() throws { // Populate the correct transaction amount from your application. let amount = UInt(10_00) // Build up parameters for creating a `PaymentIntent` let params = try PaymentIntentParametersBuilder( amount: amount, currency: "usd" ).setMetadata(["offlineId": UUID().uuidString]) .build() Terminal.shared.createPaymentIntent(params) { createResult, createError in if let error = createError { // Handle errors in your application. print("createPaymentIntent failed: \(error)") } else if let paymentIntent = createResult { print("createPaymentIntent succeeded")// If the `PaymentIntent` was created offline, its `stripeId` field will be nil. if let onlineCreatedId = paymentIntent.stripeId { print("created online"); } else { print("created offline") } } } } } ``` `Terminal.createPaymentIntent` accepte un paramètre `CreateConfiguration`. Par défaut, si vous êtes en mode hors ligne, le SDK Terminal enregistre tous les paiements hors ligne, puis les transmet au backend de Stripe lorsque la connexion est rétablie. Pour personnaliser ce comportement, vous pouvez transmettre un objet `CreateConfiguration` avec un attribut `offlineBehavior` défini sur `REQUIRE_ONLINE`, `PREFER_ONLINE` ou `FORCE_OFFLINE`. #### Gestion du risque La définition de `offlineBehavior` sur `REQUIRE_ONLINE` entraîne un échec de la transaction en cours si vous fonctionnez en mode hors ligne. Par exemple, vous pouvez refuser les transactions supérieures à un certain montant ou toutes les transactions hors ligne si le lecteur a stocké un ensemble de transactions dont la somme dépasse un certain montant. Le SDK expose deux propriétés pour vous aider à gérer les risques : 1. `Terminal.offlineStatus.reader.offlinePaymentsCount` 1. `Terminal.offlineStatus.reader.offlinePaymentAmountsByCurrency` #### Gérer la latence en mode hors ligne Based on your network connectivity, the Terminal SDK automatically determines whether to collect payments online or offline. However, you might want to operate offline despite having an active network connection (for example, if you need to collect transactions quickly and your network connection is slow). You can pass a `CreateConfiguration` object with `offlineBehavior` set to `FORCE_OFFLINE` to collect the payment offline regardless of connectivity. Les paiements collectés hors ligne alors que le lecteur Terminal dispose d’une connexion réseau active sont transmis en arrière-plan. #### Swift ```swift import UIKit import StripeTerminal class PaymentViewController: UIViewController { // Action for a "Checkout" button func checkoutAction() throws { // ...build up parameters and callback for creating a `PaymentIntent` // Your app might want to prevent offline payments for too large an amount. // Here, we block the payment if the amount is over 1000 usd. // Otherwise, we allow collecting offline if the network connection is unavailable.let offlineBehavior: SCPOfflineBehavior = { if amount > UInt(1_000_00) { return .requireOnline } else { return .preferOnline } }() let createConfiguration = try CreateConfigurationBuilder().setOfflineBehavior(offlineBehavior).build() Terminal.shared.createPaymentIntent(params, createConfig: createConfiguration) { createResult, createError in // handle success or failure } } } ``` ## Collecter un moyen de paiement [Côté client] - [CollectPaymentIntentConfiguration (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCollectPaymentIntentConfiguration.html) > La responsabilité du paiement vous incombe lorsque vous utilisez votre lecteur hors ligne. Les données de bande magnétique étant faciles à usurper, Stripe désactive cette option pour les paiements hors ligne. En outre, la présentation des cartes n’est pas prise en charge sur les marchés où l’*authentification forte du client* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase) est requise. La collecte des paiements en mode hors ligne est similaire [à la collecte des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#collect-payment). Votre lecteur intelligent affiche automatiquement les options de paiement disponibles pour le client. > Les lecteurs ne prennent pas en charge l’[inspection des informations du moyen de paiement avant autorisation](https://docs.stripe.com/terminal/payments/collect-card-payment.md?terminal-sdk-platform=ios#collect-inspect-payment-method) en mode hors ligne. Bien que vous puissiez toujours utiliser le paramètre `initWithUpdate PaymentIntent` dans `CollectPaymentIntentConfiguration`, le champ `paymentMethod` de la PaymentIntent est absent si le SDK fonctionne hors ligne. #### Swift ```swift import UIKit import StripeTerminal class PaymentViewController: UIViewController { // Action for a "Checkout" button func checkoutAction() { Terminal.shared.collectPaymentMethod(paymentIntent) { collectResult, collectError in if let error = collectError { print("collectPaymentMethod failed: \(error)") } else if let paymentIntent = collectResult { print("collectPaymentMethod succeeded") // ... Confirm the payment } } } } ``` ## Confirmer le paiement [Côté client] La confirmation des paiements en mode hors ligne est similaire à la [confirmation des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#confirm-payment). La principale différence est que votre intégration doit gérer des types d’erreurs spécifiques au mode hors ligne, par exemple lorsque la transaction dépasse la limite maximum de 10 000 USD appliquée par Stripe pour les paiements hors ligne (ou un montant équivalent dans votre devise). Dans certains cas, le SDK peut créer en ligne un `PaymentIntent`, mais le confirmer hors ligne. Dans ce cas, le `PaymentIntent` peut avoir un `stripeId` non nul. S’il a été confirmé hors ligne, `offlineDetails` sera défini et renseigné. #### Swift ```swift import UIKit import StripeTerminal class PaymentViewController: UIViewController { // Action for a "Checkout" button func checkoutAction() { Terminal.shared.confirmPaymentIntent(paymentIntent) { confirmResult, confirmError in if let error = confirmError { // Handle offline-specific errors in your application (for example, // unsupported payment method). print("confirmPaymentIntent failed: \(error)") } else if let confirmedPaymentIntent= confirmResult {print("confirmPaymentIntent succeeded") if let offlineDetails = paymentIntent.offlineDetails { print("confirmed offline"); } else { print("confirmed online") } } } } } ``` #### Fourniture de reçus Vous pouvez avoir besoin d’informations concernant la carte utilisée pour un paiement en mode hors ligne. Par exemple, vous pouvez avoir besoin de générer un reçu pour les clients qui le demandent au moment de l’achat. Si le PaymentIntent est confirmé hors ligne, récupérez sa propriété [OfflineCardPresentDetails](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPOfflineCardPresentDetails.html) from the `paymentIntent.offlineDetails.offlineCardPresentDetails`. Ce hachage contient une propriété [ReceiptDetails](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPReceiptDetails.html) que vous pouvez utiliser pour générer un reçu ainsi que d’autres informations sur la carte bancaire, notamment sa marque et le nom de son titulaire. Les champs des reçus `account_type` et `authorization_response_code` ne sont pas disponibles sur les PaymentIntents traités en mode hors ligne. Les [reçus par e-mail préconfigurés](https://docs.stripe.com/terminal/features/receipts.md#prebuilt) sont uniquement envoyés lorsque la connexion est rétablie et que le paiement est capturé. ## Attendre l'acheminement des paiements [Côté client] Quand la connexion au réseau est rétablie, le lecteur commence automatiquement à transférer les paiements hors ligne stockés. Le lecteur tente de transmettre les paiements même si l’état de son réseau est hors ligne. Cela signifie que votre fournisseur de tokens de connexion peut recevoir une demande de token de connexion, même lorsque l’appareil est hors ligne. Si vous déconnectez ou éteignez votre lecteur intelligent trop tôt, vos paiements risquent de ne pas être transférés. Vous pouvez interroger `Terminal.offlineStatus.reader.networkStatus` pour vous assurer que votre lecteur est en ligne et qu’il peut transférer les paiements, et `Terminal.offlineStatus.reader.offlinePaymentsCount` pour connaître le nombre de paiements que le lecteur doit transférer. Si votre lecteur intelligent est endommagé ou ne peut plus accepter de paiements, vous pouvez généralement toujours transférer vos paiements stockés. Veillez à connecter le lecteur intelligent à votre PDV et à rétablir l’accès à Internet pour lui permettre de se reconnecter à Stripe. ## Capturer le paiement Lorsque vous êtes hors ligne, vous pouvez créer des PaymentIntents avec l’attribut `captureMethod` défini sur `automatic`. Une fois que vous avez confirmé ces PaymentIntents, ils passent à l’état `Succeeded` au lieu de `RequiresCapture`. Stripe capture automatiquement les paiements une fois que vous les avez transmis. Si vous choisissez la capture manuelle, les paiements acheminés et autorisés doivent alors être capturés depuis votre back-end ou votre application. - Afin de capturer les paiements depuis votre back-end, utilisez des [webhooks](https://docs.stripe.com/webhooks.md) pour écouter les PaymentIntents à l’état `requires_capture`. - Pour capturer les paiements depuis votre application, attendez que celle-ci reçoive les appels à `OfflineDelegate.didForwardPayment` pour chaque PaymentIntent à mesure que le lecteur les transmet. Un PaymentIntent est prêt à capturer si son état est `RequiresCapture` et si le paramètre `offlineDetails` est vide ou présente une valeur `requiresUpload` de `NO` . #### Swift ```swift Terminal.shared.confirmPaymentIntent(paymentIntent) { confirmResult, confirmError in if let error = confirmError { // Handle offline-specific errors in your application (for example, // unsupported payment method). print("confirmPaymentIntent failed: \(error)") } else if let confirmedPaymentIntent = confirmResult { if intent.status == .requiresCapture {if let offlineDetails = confirmedPaymentIntent.offlineDetails(), offlineDetails.requiresUpload { // Offline payment, wait for `didForwardPaymentIntent` (see snippet below) } else { // Online payment, can be captured now } } // else, handle other intent.status results here } } ``` Capturez un paiement hors ligne après qu’il ait été transmis par le lecteur dans le `didForwardPaymentIntent` de votre OfflineDelegate : #### Swift ```swift import StripeTerminal class CustomOfflineDelegate: OfflineDelegate { // ... func terminal(_ terminal: Terminal, didForwardPaymentIntent intent: PaymentIntent, error: Error?) { if let error = error { // Handle the error appropriate for your application return } if intent.status == .requiresCapture { // The intent is ready to be captured. } else { // Handle the intent.status as appropriate. } } // ... } ``` ## Examiner les paiements collectés hors ligne Après autorisation, vous pouvez utiliser l’API [PaymentIntents](https://docs.stripe.com/payments/payment-intents.md) pour examiner les informations hors ligne d’un paiement. Accédez aux [informations relatives au moyen de paiement](https://docs.stripe.com/api/charges/object.md#charge_object-payment_method_details-card_present-offline) sur le dernier objet [Charge](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-latest_charge) d’un `PaymentIntent` pour déterminer s’il a été encaissé hors ligne. # Android > This is a Android for when terminal-card-present-integration is terminal and terminal-sdk-platform is android and reader-type is internet. View the full page at https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments?terminal-card-present-integration=terminal&terminal-sdk-platform=android&reader-type=internet. Le SDK Terminal permet à votre application de continuer à encaisser des paiements à l’aide d’un lecteur intelligent sans connexion Internet. Si vous utilisez un appareil de PDV distinct avec un lecteur Stripe intelligent, vous avez tout de même besoin d’un réseau local opérationnel pour autoriser votre appareil de PDV à communiquer avec le lecteur intelligent. Le fonctionnement hors ligne avec des lecteurs intelligents concerne les scénarios dans lesquels votre PDV et votre lecteur ne peuvent pas communiquer avec Stripe, par exemple en cas de panne du fournisseur d’accès à Internet. Si vous avez besoin de pouvoir fonctionner hors ligne sans réseau local, les [lecteurs mobiles](https://docs.stripe.com/terminal/mobile-readers.md) de Stripe Terminal peuvent vous être utiles. Vous pouvez également fonctionner hors ligne avec une intégration d’applications sur des appareils. Dans la mesure où votre application de PDV fonctionne directement sur le lecteur intelligent, vous n’avez pas besoin d’un réseau local pour encaisser des paiements. Toutefois, vous devez tout de même être sur un réseau local au premier démarrage de votre lecteur, même si ce réseau n’a pas accès à Internet. > En mode hors ligne, les informations de paiement sont collectées au moment de la vente et l’autorisation n’est tentée qu’après que la connectivité est rétablie et que le paiement est transmis. Lorsqu’il fonctionne hors ligne avec un lecteur connecté à Internet, le lecteur stocke les informations de paiement collectées. En tant qu’utilisateur, vous assumez tous les risques de refus et de falsification associés à une transaction hors ligne. Si votre lecteur falsifié ne peut pas transférer les paiements à Stripe, ou si l’émetteur refuse la transaction, il n’y a aucun moyen de récupérer les fonds et il est possible que vous ne receviez pas le paiement du client pour les biens ou services déjà fournis. > > Pour limiter les risques de refus de la part de l’émetteur, nous vous conseillons de : > > - Rétablir la connexion Internet le plus rapidement possible pour enregistrer les paiements sur Stripe. - Bloquer les transactions supérieures à un certain montant. - [Faire échouer tous les paiements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#managing-risk) quand le SDK a stocké un ensemble de transactions dont la somme dépasse un certain montant. ## Encaisser des paiements en mode hors ligne Les paiements hors ligne suivent les mêmes étapes que les paiements en ligne : création, collecte, traitement et capture du paiement. Votre appareil peut passer du mode en ligne au mode hors ligne à n’importe quelle étape du processus. 1. [Activer le mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) 1. [Se connecter à un lecteur en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#connect-while-offline) 1. [Gérer les événements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#handle-offline-events) 1. [Créer un Payment Intent en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#create-payment-intent) 1. [Collecter un moyen de paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#collect-payment-method) 1. [Confirmer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#confirm-payment) 1. [Attendre l’acheminement des paiements](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#wait-for-forward) 1. (Facultatif) [Capturer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#capture-payment) 1. (Facultatif) [Examiner les paiements encaissés hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#examine-offline) ## Activer le mode hors ligne Pour utiliser le mode hors ligne, votre application doit utiliser la version `3.2.0` ou une version ultérieure du SDK Terminal Android. Utilisez un objet [Configuration](https://docs.stripe.com/api/terminal/configuration.md) ou [le Dashboard](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=dashboard#update-the-default-configuration-for-the-account) afin d’activer le mode hors ligne pour les appareils [pris en charge](https://docs.stripe.com/terminal/features/operate-offline/overview.md?reader-type=internet#availability) dans votre `Location`. ```curl curl https://api.stripe.com/v1/terminal/configurations \ -u "<>:" \ -d "offline[enabled]=true" ``` Après avoir activé le mode hors ligne sur un objet `Configuration`, vous pouvez l’[affecter](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#create-a-configuration-for-an-individual-location) à un objet `Location`. Vous pouvez également activer le mode hors ligne par défaut pour tous les emplacements (`Locations`) en mettant à jour l’objet `Configuration` [par défaut](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#retrieve-the-account-default-configuration) de votre compte. La propagation des modifications apportées à l’API Configuration vers votre SDK et votre lecteur peut prendre quelques minutes. Pour qu’elles soient prises en compte, vous devez vous déconnecter puis vous reconnecter à votre lecteur. ## Se connecter à un lecteur en mode hors ligne Le lecteur stocke localement les informations nécessaires sur `Location` après la connexion en ligne. Lors des connexions hors ligne suivantes, il utilise les informations de configuration stockées à partir de cet emplacement`Location`. Pour encaisser des paiements à l’aide d’un lecteur intelligent en mode hors ligne, vous devez avoir établi une connexion à un lecteur mobile du même type au même emplacement (`Location`) en étant en ligne au cours des 30 derniers jours sur le même réseau local. Le lecteur stocke les informations relatives à l’objet `Location` en local après s’être connecté en ligne, puis déduit les informations de configuration de cet emplacement `Location` lorsqu’il fonctionne hors ligne. Votre lecteur et votre appareil de point de vente doivent être sur le même réseau local que celui utilisé pour se connecter à Internet. Vous ne pouvez pas changer de réseau en mode hors ligne. Si vous tentez de vous connecter à un lecteur hors ligne sans remplir ces conditions, la demande échoue avec une erreur. | Erreur | Résolution | | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Le SDK n’est pas connecté à Internet** | Assurez-vous que l’objet `Location` que vous utilisez est [configuré](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) pour le mode hors ligne. Sinon, connectez-vous en ligne à un lecteur, puis hors ligne à un lecteur du même type. | | **Le lecteur sélectionné nécessite une mise à jour logicielle avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Le logiciel du lecteur n’a pas été mis à jour depuis 30 jours ou plus. Connectez-vous au lecteur en ligne pour le mettre à jour. | | **Le lecteur sélectionné doit être appairé en ligne à cet endroit avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Vous essayez de vous connecter à un type de lecteur auquel votre PDV ne s’est pas encore connecté en ligne. Vous devez d’abord vous connecter en ligne à ce lecteur ou à tout autre lecteur du même type. Si vous voulez vous connecter hors ligne, vous pouvez également vous connecter à un type de lecteur auquel votre PDV s’est déjà connecté en ligne. | ## Gérer les événements hors ligne [Côté client] - [OfflineListener (Android)](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.callable/-offline-listener/index.html) Pour permettre à votre application de recevoir des mises à jour sur l’état du réseau du SDK et des paiements transmis, implémentez l’interface `OfflineListener` et transmettez-la au SDK Terminal. Vous devez définir `OfflineListener` avant de collecter les paiements en mode hors ligne. #### Kotlin ```kotlin class CustomOfflineListener : OfflineListener { override fun onOfflineStatusChange(offlineStatus: OfflineStatus) { // Check the value of `offlineStatus` and update your UI accordingly. For instance, // you can check the SDK's network status at `offlineStatus.sdk.networkStatus`. // // You can also check the SDK's current offline status using // `Terminal::offlineStatus`. } override fun onPaymentIntentForwarded(paymentIntent: PaymentIntent, e: TerminalException?) { // The PaymentIntent was successfully forwarded, or an error occurred. // Reconcile any local state using the backend-generated `PaymentIntent::id` // and the metadata you supplied when creating the PaymentIntent. // // Note that the `PaymentIntent::id` may still be null if creating the // PaymentIntent in the backend failed. } override fun onForwardingFailure(e: TerminalException) { // A non-specific error occurred while forwarding a PaymentIntent. // Check the error message and your integration implementation to // troubleshoot. } } ``` #### Kotlin ```kotlin Terminal.init( context = applicationContext, logLevel = LogLevel.VERBOSE, tokenProvider = CustomConnectionTokenProvider(), listener = CustomTerminalListener(), offlineListener = CustomOfflineListener(), ) ``` ## Créer un PaymentIntent en mode en ligne [Côté client] - [createPaymentIntent (Android)](https://stripe.dev/stripe-terminal-android/core/com.stripe.stripeterminal/-terminal/create-payment-intent.html) - [CreateConfiguration (Android)](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-create-configuration/index.html) - [OfflineDetails (Android)](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-offline-details/index.html) Afin prendre en charge le fonctionnement hors ligne, utilisez l’attribut `createPaymentIntent` du SDK pour créer des objets PaymentIntent. Cela permet au SDK de créer des PaymentIntents en mode hors ligne et de les transmettre à Stripe une fois que vous avez rétabli la connexion. En mode hors ligne, les objets `PaymentIntent` ont un champ `id` vide. Nous vous recommandons d’ajouter un identifiant personnalisé aux [metadata](https://docs.stripe.com/payments/payment-intents.md#storing-information-in-metadata) pour faciliter le rapprochement des objets `PaymentIntent`créés hors ligne dans votre base de données. Vous pouvez configurer un endpoint de [webhook](https://docs.stripe.com/webhooks.md) pour recevoir des événements `PaymentIntent` lorsque des paiements hors ligne sont transmis à Stripe, et utiliser votre identifiant pour les associer à un ID `PaymentIntent`. #### Kotlin ```kotlin private const val TAG = "PaymentActivity" class PaymentActivity : AppCompatActivity() { // Action for a "Checkout" button private fun onCheckout(cart: Cart) { // Build up parameters for creating a `PaymentIntent` val params = PaymentIntentParameters.Builder() .setAmount(cart.total) .setCurrency(cart.currency).setMetadata(mapOf("unique-id" to UUID.randomUUID().toString())) .build() val createPaymentCallback: PaymentIntentCallback = object : PaymentIntentCallback { override fun onSuccess(paymentIntent: PaymentIntent) { Log.d(TAG, "createPaymentIntent succeeded")// If the `PaymentIntent` was created offline, its `id` field will be null. if (paymentIntent.id != null) { Log.d(TAG, "created online") } else { Log.d(TAG, "created offline") } // ... Collect a PaymentMethod } override fun onFailure(e: TerminalException) { Log.e(TAG, "createPaymentIntent failed", e) // Handle errors in your application. } } Terminal.getInstance().createPaymentIntent(params, createPaymentCallback) } } ``` `Terminal.createPaymentIntent` accepte un paramètre `CreateConfiguration`. Par défaut, si vous êtes en mode hors ligne, le SDK Terminal enregistre tous les paiements hors ligne, puis les transmet au backend de Stripe lorsque la connexion est rétablie. Pour personnaliser ce comportement, vous pouvez transmettre un objet `CreateConfiguration` avec un attribut `offlineBehavior` défini sur `REQUIRE_ONLINE`, `PREFER_ONLINE` ou `FORCE_OFFLINE`. #### Gestion du risque La définition de `offlineBehavior` sur `REQUIRE_ONLINE` entraîne un échec de la transaction en cours si vous fonctionnez en mode hors ligne. Par exemple, vous pouvez refuser les transactions supérieures à un certain montant ou toutes les transactions hors ligne si le lecteur a stocké un ensemble de transactions dont la somme dépasse un certain montant. Le SDK expose deux propriétés pour vous aider à gérer les risques : 1. `Terminal.offlineStatus.reader.offlinePaymentsCount` 1. `Terminal.offlineStatus.reader.offlinePaymentAmountsByCurrency` #### Gérer la latence en mode hors ligne Based on your network connectivity, the Terminal SDK automatically determines whether to collect payments online or offline. However, you might want to operate offline despite having an active network connection (for example, if you need to collect transactions quickly and your network connection is slow). You can pass a `CreateConfiguration` object with `offlineBehavior` set to `FORCE_OFFLINE` to collect the payment offline regardless of connectivity. Les paiements collectés hors ligne alors que le lecteur Terminal dispose d’une connexion réseau active sont transmis en arrière-plan. #### Kotlin ```kotlin private const val TAG = "PaymentActivity" class PaymentActivity : AppCompatActivity() { // Action for a "Checkout" button private fun onCheckout(cart: Cart) { // ...build up parameters and callback for creating a `PaymentIntent` // Your app might want to prevent offline payments for too large an amount. // Here, we require a network connection if the payment if the amount is over 1000 usd. // Otherwise, we allow collecting offline if the network connection is unavailable.val offlineBehavior = if (cart.total > 1000000) { OfflineBehavior.REQUIRE_ONLINE } else { OfflineBehavior.PREFER_ONLINE } val createConfig = CreateConfiguration(offlineBehavior) Terminal.getInstance().createPaymentIntent(params, createPaymentCallback, createConfig) } } ``` ## Collecter un moyen de paiement [Côté client] - [CollectPaymentIntentConfiguration (Android)](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-collect-payment-intent-configuration/index.html) > La responsabilité du paiement vous incombe lorsque vous utilisez votre lecteur hors ligne. Les données de bande magnétique étant faciles à usurper, Stripe désactive cette option pour les paiements hors ligne. En outre, la présentation des cartes n’est pas prise en charge sur les marchés où l’*authentification forte du client* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase) est requise. La collecte des paiements en mode hors ligne est similaire [à la collecte des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#collect-payment). Votre lecteur intelligent affiche automatiquement les options de paiement disponibles pour le client. > Les lecteurs ne prennent pas en charge l’[inspection des informations du moyen de paiement avant autorisation](https://docs.stripe.com/terminal/payments/collect-card-payment.md?terminal-sdk-platform=android#collect-inspect-payment-method) en mode hors ligne. Bien que vous puissiez toujours définir le paramètre `updatePaymentIntent` dans `CollectPaymentIntentConfiguration`, le champ `paymentMethod` de la PaymentIntent est absent si le SDK fonctionne hors ligne. #### Kotlin ```kotlin private const val TAG = "PaymentActivity" class PaymentActivity : AppCompatActivity() { // Action for a "Checkout" button private fun onCheckout(cart: Cart) { val collectPaymentCallback: PaymentIntentCallback = object : PaymentIntentCallback { override fun onSuccess(paymentIntent: PaymentIntent) { Log.d(TAG, "collectPaymentMethod succeeded") // ... Confirm the payment } override fun onFailure(e: TerminalException) { Log.d(TAG, "collectPaymentMethod failed:", e) } } val collectConfig = CollectPaymentIntentConfiguration.Builder().build() Terminal.getInstance().collectPaymentMethod(paymentIntent, collectPaymentCallback, collectConfig) } } ``` ## Confirmer le paiement [Côté client] La confirmation des paiements en mode hors ligne est similaire à la [confirmation des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#confirm-payment). La principale différence est que votre intégration doit gérer des types d’erreurs spécifiques au mode hors ligne, par exemple lorsque la transaction dépasse la limite maximum de 10 000 USD appliquée par Stripe pour les paiements hors ligne (ou un montant équivalent dans votre devise). Dans certains cas, le SDK peut créer en ligne un `PaymentIntent`, mais le confirmer hors ligne. Dans ce cas, le `PaymentIntent` peut avoir un `id` non nul. S’il a été confirmé hors ligne, `offlineDetails` sera défini et renseigné. #### Kotlin ```kotlin private const val TAG = "PaymentActivity" class PaymentActivity : AppCompatActivity() { // Action for a "Checkout" button private fun onCheckout(cart: Cart) { val confirmPaymentIntentCallback: PaymentIntentCallback = object : PaymentIntentCallback { override fun onSuccess(paymentIntent: PaymentIntent) { Log.d(TAG, "confirmPaymentIntent succeeded")// If the `PaymentIntent` was confirmed offline, `paymentIntent.offlineDetails` will be defined if (paymentIntent.offlineDetails != null) { Log.d(TAG, "confirmed offline") } else { Log.d(TAG, "confirmed online") } } override fun onFailure(e: TerminalException) { // Handle offline-specific errors in your application (for example, // unsupported payment method). Log.e(TAG, "confirmPaymentIntent failed:", e) } } Terminal.getInstance().confirmPaymentIntent(paymentIntent, confirmPaymentIntentCallback) } } ``` #### Fourniture de reçus Vous pouvez avoir besoin d’informations concernant la carte utilisée pour un paiement en mode hors ligne. Par exemple, vous pouvez avoir besoin de générer un reçu pour les clients qui le demandent au moment de l’achat. Si le PaymentIntent est confirmé hors ligne, récupérez sa propriété [OfflineCardPresentDetails](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-offline-card-present-details/index.html) from the `paymentIntent.offlineDetails.offlineCardPresentDetails`. Ce hachage contient une propriété [ReceiptDetails](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-receipt-details/index.html) que vous pouvez utiliser pour générer un reçu ainsi que d’autres informations sur la carte bancaire, notamment sa marque et le nom de son titulaire. Les champs des reçus `account_type` et `authorization_response_code` ne sont pas disponibles sur les PaymentIntents traités en mode hors ligne. Les [reçus par e-mail préconfigurés](https://docs.stripe.com/terminal/features/receipts.md#prebuilt) sont uniquement envoyés lorsque la connexion est rétablie et que le paiement est capturé. ## Attendre l'acheminement des paiements [Côté client] Quand la connexion au réseau est rétablie, le lecteur commence automatiquement à transférer les paiements hors ligne stockés. Le lecteur tente de transmettre les paiements même si l’état de son réseau est hors ligne. Cela signifie que votre fournisseur de tokens de connexion peut recevoir une demande de token de connexion, même lorsque l’appareil est hors ligne. Si vous déconnectez ou éteignez votre lecteur intelligent trop tôt, vos paiements risquent de ne pas être transférés. Vous pouvez interroger `Terminal.offlineStatus.reader.networkStatus` pour vous assurer que votre lecteur est en ligne et qu’il peut transférer les paiements, et `Terminal.offlineStatus.reader.offlinePaymentsCount` pour connaître le nombre de paiements que le lecteur doit transférer. Si votre lecteur intelligent est endommagé ou ne peut plus accepter de paiements, vous pouvez généralement toujours transférer vos paiements stockés. Veillez à connecter le lecteur intelligent à votre PDV et à rétablir l’accès à Internet pour lui permettre de se reconnecter à Stripe. ## Capturer le paiement Lorsque vous êtes hors ligne, vous pouvez créer des PaymentIntents avec l’attribut `captureMethod` défini sur `automatic`. Une fois que vous avez confirmé ces PaymentIntents, ils passent à l’état `SUCCEEDED` au lieu de `REQUIRES_CAPTURE` . Stripe capture automatiquement les paiements une fois que vous les avez transmis. Si vous choisissez la capture manuelle, les paiements acheminés et autorisés doivent alors être capturés depuis votre back-end ou votre application. - Afin de capturer les paiements depuis votre back-end, utilisez des [webhooks](https://docs.stripe.com/webhooks.md) pour écouter les PaymentIntents à l’état `requires_capture`. - Pour capturer les paiements depuis votre application, attendez que celle-ci reçoive les appels à `OfflineListener::onPaymentIntentForwarded` pour chaque PaymentIntent à mesure que le lecteur les transmet. Un PaymentIntent est prêt à capturer si son état est `REQUIRES_CAPTURE` et si le paramètre `offlineDetails` est vide ou présente une valeur `requiresUpload` de `false` . #### Kotlin ```kotlin private const val TAG = "PaymentActivity" class PaymentActivity : AppCompatActivity() { // Action for a "Checkout" button private fun onCheckout(cart: Cart) { val callback: PaymentIntentCallback = object : PaymentIntentCallback { override fun onSuccess(paymentIntent: PaymentIntent) { Log.d(TAG, "confirmPaymentIntent succeeded") if (paymentIntent.status == PaymentIntentStatus.REQUIRES_CAPTURE) {val offlineDetails = paymentIntent.offlineDetails if (offlineDetails?.requiresUpload == true) { // Offline payment, wait for `onPaymentIntentForwarded` (see snippet below) } else { // Online payment, can be captured now } } else { // Handle other status results here } } override fun onFailure(e: TerminalException) { // Handle offline-specific errors in your application (for example, // unsupported payment method). Log.e(TAG, "confirmPaymentIntent failed:", e) } } Terminal.getInstance().confirmPaymentIntent(paymentIntent, callback) } } ``` Capturez un paiement hors ligne après qu’il ait été transmis par le lecteur dans votre `OfflineListener::onPaymentIntentForwarded` : #### Kotlin ```kotlin class CustomOfflineListener : OfflineListener { // ... override fun onPaymentIntentForwarded(paymentIntent: PaymentIntent, e: TerminalException?) { if (e != null) { // Handle the error appropriate for your application } else if (paymentIntent.status == PaymentIntentStatus.REQUIRES_CAPTURE) { // The paymentIntent is ready to be captured } else { // Handle other status results here } } // ... } ``` ## Examiner les paiements collectés hors ligne Après autorisation, vous pouvez utiliser l’API [PaymentIntents](https://docs.stripe.com/payments/payment-intents.md) pour examiner les informations hors ligne d’un paiement. Accédez aux [informations relatives au moyen de paiement](https://docs.stripe.com/api/charges/object.md#charge_object-payment_method_details-card_present-offline) sur le dernier objet [Charge](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-latest_charge) d’un `PaymentIntent` pour déterminer s’il a été encaissé hors ligne. # React Native > This is a React Native for when terminal-card-present-integration is terminal and terminal-sdk-platform is react-native and reader-type is internet. View the full page at https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments?terminal-card-present-integration=terminal&terminal-sdk-platform=react-native&reader-type=internet. Le SDK Terminal permet à votre application de continuer à encaisser des paiements à l’aide d’un lecteur intelligent sans connexion Internet. Si vous utilisez un appareil de PDV distinct avec un lecteur Stripe intelligent, vous avez tout de même besoin d’un réseau local opérationnel pour autoriser votre appareil de PDV à communiquer avec le lecteur intelligent. Le fonctionnement hors ligne avec des lecteurs intelligents concerne les scénarios dans lesquels votre PDV et votre lecteur ne peuvent pas communiquer avec Stripe, par exemple en cas de panne du fournisseur d’accès à Internet. Si vous avez besoin de pouvoir fonctionner hors ligne sans réseau local, les [lecteurs mobiles](https://docs.stripe.com/terminal/mobile-readers.md) de Stripe Terminal peuvent vous être utiles. Vous pouvez également fonctionner hors ligne avec une intégration d’applications sur des appareils. Dans la mesure où votre application de PDV fonctionne directement sur le lecteur intelligent, vous n’avez pas besoin d’un réseau local pour encaisser des paiements. Toutefois, vous devez tout de même être sur un réseau local au premier démarrage de votre lecteur, même si ce réseau n’a pas accès à Internet. > En mode hors ligne, les informations de paiement sont collectées au moment de la vente et l’autorisation n’est tentée qu’après que la connectivité est rétablie et que le paiement est transmis. Lorsqu’il fonctionne hors ligne avec un lecteur connecté à Internet, le lecteur stocke les informations de paiement collectées. En tant qu’utilisateur, vous assumez tous les risques de refus et de falsification associés à une transaction hors ligne. Si votre lecteur falsifié ne peut pas transférer les paiements à Stripe, ou si l’émetteur refuse la transaction, il n’y a aucun moyen de récupérer les fonds et il est possible que vous ne receviez pas le paiement du client pour les biens ou services déjà fournis. > > Pour limiter les risques de refus de la part de l’émetteur, nous vous conseillons de : > > - Rétablir la connexion Internet le plus rapidement possible pour enregistrer les paiements sur Stripe. - Bloquer les transactions supérieures à un certain montant. - [Faire échouer tous les paiements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#managing-risk) quand le SDK a stocké un ensemble de transactions dont la somme dépasse un certain montant. ## Encaisser des paiements en mode hors ligne Les paiements hors ligne suivent les mêmes étapes que les paiements en ligne : création, collecte, traitement et capture du paiement. Votre appareil peut passer du mode en ligne au mode hors ligne à n’importe quelle étape du processus. 1. [Activer le mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) 1. [Se connecter à un lecteur en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#connect-while-offline) 1. [Gérer les événements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#handle-offline-events) 1. [Créer un Payment Intent en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#create-payment-intent) 1. [Collecter un moyen de paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#collect-payment-method) 1. [Confirmer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#confirm-payment) 1. [Attendre l’acheminement des paiements](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#wait-for-forward) 1. (Facultatif) [Capturer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#capture-payment) 1. (Facultatif) [Examiner les paiements encaissés hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#examine-offline) ## Activer le mode hors ligne Utilisez un objet [Configuration](https://docs.stripe.com/api/terminal/configuration.md) ou [le Dashboard](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=dashboard#update-the-default-configuration-for-the-account) afin d’activer le mode hors ligne pour les appareils [pris en charge](https://docs.stripe.com/terminal/features/operate-offline/overview.md?reader-type=internet#availability) dans votre `Location`. ```curl curl https://api.stripe.com/v1/terminal/configurations \ -u "<>:" \ -d "offline[enabled]=true" ``` Après avoir activé le mode hors ligne sur un objet `Configuration`, vous pouvez l’[affecter](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#create-a-configuration-for-an-individual-location) à un objet `Location`. Vous pouvez également activer le mode hors ligne par défaut pour tous les emplacements (`Locations`) en mettant à jour l’objet `Configuration` [par défaut](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#retrieve-the-account-default-configuration) de votre compte. La propagation des modifications apportées à l’API Configuration vers votre SDK et votre lecteur peut prendre quelques minutes. Pour qu’elles soient prises en compte, vous devez vous déconnecter puis vous reconnecter à votre lecteur. ## Se connecter à un lecteur en mode hors ligne Le lecteur stocke localement les informations nécessaires sur `Location` après la connexion en ligne. Lors des connexions hors ligne suivantes, il utilise les informations de configuration stockées à partir de cet emplacement`Location`. Pour encaisser des paiements à l’aide d’un lecteur intelligent en mode hors ligne, vous devez avoir établi une connexion à un lecteur mobile du même type au même emplacement (`Location`) en étant en ligne au cours des 30 derniers jours sur le même réseau local. Le lecteur stocke les informations relatives à l’objet `Location` en local après s’être connecté en ligne, puis déduit les informations de configuration de cet emplacement `Location` lorsqu’il fonctionne hors ligne. Votre lecteur et votre appareil de point de vente doivent être sur le même réseau local que celui utilisé pour se connecter à Internet. Vous ne pouvez pas changer de réseau en mode hors ligne. Si vous tentez de vous connecter à un lecteur hors ligne sans remplir ces conditions, la demande échoue avec une erreur. | Erreur | Résolution | | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Le SDK n’est pas connecté à Internet** | Assurez-vous que l’objet `Location` que vous utilisez est [configuré](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) pour le mode hors ligne. Sinon, connectez-vous en ligne à un lecteur, puis hors ligne à un lecteur du même type. | | **Le lecteur sélectionné nécessite une mise à jour logicielle avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Le logiciel du lecteur n’a pas été mis à jour depuis 30 jours ou plus. Connectez-vous au lecteur en ligne pour le mettre à jour. | | **Le lecteur sélectionné doit être appairé en ligne à cet endroit avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Vous essayez de vous connecter à un type de lecteur auquel votre PDV ne s’est pas encore connecté en ligne. Vous devez d’abord vous connecter en ligne à ce lecteur ou à tout autre lecteur du même type. Si vous voulez vous connecter hors ligne, vous pouvez également vous connecter à un type de lecteur auquel votre PDV s’est déjà connecté en ligne. | ## Gérer les événements hors ligne [Côté client] - [UserCallbacks (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#UserCallbacks) Pour permettre à votre application de recevoir des mises à jour sur l’état du réseau du SDK et des paiements transmis, implémentez les rappels hors ligne sur le hook `useStripeTerminal`. ```js const { connectReader, disconnectReader, connectedReader } = useStripeTerminal({ onDidChangeOfflineStatus(status: OfflineStatus) { // Check the value of `offlineStatus` and update your UI accordingly. // // You can also check the SDK's current offline status calling // `getOfflineStatus`. }, onDidForwardingFailure(error) { // A non-specific error occurred while forwarding a PaymentIntent. // Check the error message and your integration implementation to // troubleshoot. }, onDidForwardPaymentIntent(paymentIntent, error) { // The PaymentIntent was successfully forwarded, or an error occurred. // Reconcile any local state using the backend-generated `paymentIntent.id` // and the metadata you supplied when creating the PaymentIntent. // // Note that the `paymentIntent.id` may still be null if creating the // PaymentIntent in the backend failed. }, }); ``` ## Créer un PaymentIntent en mode en ligne [Côté client] - [createPaymentIntent (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#createPaymentIntent) - [CreatePaymentIntentParams (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#CreatePaymentIntentParams) - [OfflineStatus (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#OfflineStatus) - [OfflineStatusDetails (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#OfflineStatusDetails) Afin prendre en charge le fonctionnement hors ligne, utilisez l’attribut `createPaymentIntent` du SDK pour créer des objets PaymentIntent. Cela permet au SDK de créer des PaymentIntents en mode hors ligne et de les transmettre à Stripe une fois que vous avez rétabli la connexion. En mode hors ligne, les objets `PaymentIntent` ont un champ `id` vide. Nous vous recommandons d’ajouter un identifiant personnalisé aux [metadata](https://docs.stripe.com/payments/payment-intents.md#storing-information-in-metadata) pour faciliter le rapprochement des objets `PaymentIntent`créés hors ligne dans votre base de données. Vous pouvez configurer un endpoint de [webhook](https://docs.stripe.com/webhooks.md) pour recevoir des événements `PaymentIntent` lorsque des paiements hors ligne sont transmis à Stripe, et utiliser votre identifiant pour les associer à un ID `PaymentIntent`. ```js const _createPaymentIntent = async (cart) => { const {error, paymentIntent} = await createPaymentIntent({ amount: cart.total, currency: cart.currency,metadata: { "unique-id": UUID().uuidString } }); } ``` `Terminal.createPaymentIntent` accepte un paramètre `CreateConfiguration`. Par défaut, si vous êtes en mode hors ligne, le SDK Terminal enregistre tous les paiements hors ligne, puis les transmet au backend de Stripe lorsque la connexion est rétablie. Pour personnaliser ce comportement, vous pouvez transmettre un objet `CreateConfiguration` avec un attribut `offlineBehavior` défini sur `REQUIRE_ONLINE`, `PREFER_ONLINE` ou `FORCE_OFFLINE`. #### Gestion du risque La définition de `offlineBehavior` sur `REQUIRE_ONLINE` entraîne un échec de la transaction en cours si vous fonctionnez en mode hors ligne. Par exemple, vous pouvez refuser les transactions supérieures à un certain montant ou toutes les transactions hors ligne si le lecteur a stocké un ensemble de transactions dont la somme dépasse un certain montant. Le SDK expose deux propriétés pour vous aider à gérer les risques : 1. `OfflineStatus.reader.offlinePaymentsCount` 1. `OfflineStatus.reader.offlinePaymentAmountsByCurrency` #### Gérer la latence en mode hors ligne Based on your network connectivity, the Terminal SDK automatically determines whether to collect payments online or offline. However, you might want to operate offline despite having an active network connection (for example, if you need to collect transactions quickly and your network connection is slow). You can set `offlineBehavior` to `force_offline` to collect the payment offline regardless of connectivity. Les paiements collectés hors ligne alors que le lecteur Terminal dispose d’une connexion réseau active sont transmis en arrière-plan. ```js const _createPaymentIntent = async (cart) => { // Your app might want to prevent offline payments for too large an amount. // Here, we require a network connection if the payment if the amount is over 1000 usd. // Otherwise, we allow collecting offline if the network connection is unavailable.let offlineBehavior: if (cart.total > 1000000) { offlineBehavior = 'require_online' } else { offlineBehavior = 'prefer_online' } const {error, paymentIntent} = await createPaymentIntent({ amount: cart.total, currency: cart.currency,offlineBehavior, }); } ``` ## Collecter un moyen de paiement [Côté client] - [CollectPaymentMethodParams (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#CollectPaymentMethodParams) > La responsabilité du paiement vous incombe lorsque vous utilisez votre lecteur hors ligne. Les données de bande magnétique étant faciles à usurper, Stripe désactive cette option pour les paiements hors ligne. En outre, la présentation des cartes n’est pas prise en charge sur les marchés où l’*authentification forte du client* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase) est requise. La collecte des paiements en mode hors ligne est similaire [à la collecte des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#collect-payment). Votre lecteur intelligent affiche automatiquement les options de paiement disponibles pour le client. > La [vérification des informations relatives aux moyens de paiement avant l’autorisation](https://docs.stripe.com/terminal/payments/collect-card-payment.md?terminal-sdk-platform=react-native#collect-inspect-payment-method) n’est pas prise en charge en mode hors ligne. Bien que vous puissiez toujours définir le paramètre `updatePaymentIntent` dans `CollectConfiguration`, le champ `paymentMethod` du PaymentIntent est absent si le SDK fonctionne en mode hors ligne. ```js const _collectPaymentMethod_ = async () => { const { paymentIntent, error } = await collectPaymentMethod({ paymentIntent: paymentIntent }); if (error) { // Handle errors in your application. } // ... Confirm the payment } ``` ## Confirmer le paiement [Côté client] La confirmation des paiements en mode hors ligne est similaire à la [confirmation des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#confirm-payment). La principale différence est que votre intégration doit gérer des types d’erreurs spécifiques au mode hors ligne, par exemple lorsque la transaction dépasse la limite maximum de 10 000 USD appliquée par Stripe pour les paiements hors ligne (ou un montant équivalent dans votre devise). Dans certains cas, le SDK peut créer en ligne un `PaymentIntent`, mais le confirmer hors ligne. Dans ce cas, le `PaymentIntent` peut avoir un `id` non nul. S’il a été confirmé hors ligne, `offlineDetails` sera défini et renseigné. ```js const _confirmPaymentIntent = async () => { const { paymentIntent, error } = await confirmPaymentIntent({ paymentIntent: paymentIntent }); if (error) { // Handle offline-specific errors in your application (for example, // unsupported payment method). } if (paymentIntent.offlineDetails) { console.log('confirmed offline'); } else { console.log('confirmed online'); } } ``` #### Fourniture de reçus Vous pouvez avoir besoin d’informations concernant la carte utilisée pour un paiement en mode hors ligne. Par exemple, vous pouvez avoir besoin de générer un reçu pour les clients qui le demandent au moment de l’achat. Si le PaymentIntent est confirmé hors ligne, récupérez sa propriété [OfflineCardPresentDetails](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#OfflineCardPresentDetails) from the `paymentIntent.offlineDetails.offlineCardPresentDetails`. Ce hachage contient une propriété [ReceiptDetails](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#ReceiptDetails) que vous pouvez utiliser pour générer un reçu ainsi que d’autres informations sur la carte bancaire, notamment sa marque et le nom de son titulaire. Les champs des reçus `account_type` et `authorization_response_code` ne sont pas disponibles sur les PaymentIntents traités en mode hors ligne. Les [reçus par e-mail préconfigurés](https://docs.stripe.com/terminal/features/receipts.md#prebuilt) sont uniquement envoyés lorsque la connexion est rétablie et que le paiement est capturé. ## Attendre l'acheminement des paiements [Côté client] Quand la connexion au réseau est rétablie, le lecteur commence automatiquement à transférer les paiements hors ligne stockés. Le lecteur tente de transmettre les paiements même si l’état de son réseau est hors ligne. Cela signifie que votre fournisseur de tokens de connexion peut recevoir une demande de token de connexion, même lorsque l’appareil est hors ligne. Si vous déconnectez ou éteignez votre lecteur intelligent trop tôt, vos paiements risquent de ne pas être transférés. Vous pouvez interroger `OfflineStatus.reader.networkStatus` pour vous assurer que votre lecteur est en ligne et qu’il peut transférer les paiements, et `OfflineStatus.reader.offlinePaymentsCount` pour connaître le nombre de paiements que le lecteur doit transférer. Si votre lecteur intelligent est endommagé ou ne peut plus accepter de paiements, vous pouvez généralement toujours transférer vos paiements stockés. Veillez à connecter le lecteur intelligent à votre PDV et à rétablir l’accès à Internet pour lui permettre de se reconnecter à Stripe. ## Capturer le paiement Lorsque vous êtes hors ligne, vous pouvez créer des PaymentIntents avec l’attribut `captureMethod` défini sur `automatic`. Une fois que vous avez confirmé ces PaymentIntents, ils passent à l’état `succeeded` au lieu de `requiresCapture` . Stripe capture automatiquement les paiements une fois que vous les avez transmis. Si vous choisissez la capture manuelle, les paiements acheminés et autorisés doivent alors être capturés depuis votre back-end ou votre application. - Afin de capturer les paiements depuis votre back-end, utilisez des [webhooks](https://docs.stripe.com/webhooks.md) pour écouter les PaymentIntents à l’état `requires_capture`. - Pour capturer les paiements depuis votre application, attendez que celle-ci reçoive les appels à `useStripeTerminal` hook’s `onDidForwardPaymentIntent` pour chaque PaymentIntent à mesure que le lecteur les transmet. Un PaymentIntent est prêt à capturer si son état est `requiresCapture` et si le paramètre `OfflineDetails` est vide ou présente une valeur `requiresUpload` de `false` . ```js const _confirmPaymentIntent = async () => { const { paymentIntent, error } = await confirmPaymentIntent({ paymentIntent: paymentIntent }); if (error) { // Handle offline-specific errors in your application (for example, // unsupported payment method). } if (paymentIntent.status == 'requiresCapture') {const offlineDetails = paymentIntent.offlineDetails; if (offlineDetails.requiresUpload === true) { // Offline payment, wait for `onDidForwardPaymentIntent` (see snippet below) } else { // Online payment, can be captured now } } else { // handle other paymentIntent.status results here } } ``` Capturez un paiement hors ligne après qu’il ait été transmis par le lecteur dans `onDidForwardPaymentIntent` : ```js const { connectReader, disconnectReader, connectedReader } = useStripeTerminal({ onDidForwardPaymentIntent(paymentIntent, error) { if (error) { // Handle the error appropriate for your application } else if (paymentIntent.status == 'requires_capture') { // The paymentIntent is ready to be captured } else { // Handle the paymentIntent.status as appropriate. } }, }); ``` ## Examiner les paiements collectés hors ligne Après autorisation, vous pouvez utiliser l’API [PaymentIntents](https://docs.stripe.com/payments/payment-intents.md) pour examiner les informations hors ligne d’un paiement. Accédez aux [informations relatives au moyen de paiement](https://docs.stripe.com/api/charges/object.md#charge_object-payment_method_details-card_present-offline) sur le dernier objet [Charge](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-latest_charge) d’un `PaymentIntent` pour déterminer s’il a été encaissé hors ligne. # Java > This is a Java for when terminal-card-present-integration is terminal and terminal-sdk-platform is java and reader-type is internet. View the full page at https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments?terminal-card-present-integration=terminal&terminal-sdk-platform=java&reader-type=internet. Le SDK Terminal permet à votre application de continuer à encaisser des paiements à l’aide d’un lecteur intelligent sans connexion Internet. Si vous utilisez un appareil de PDV distinct avec un lecteur Stripe intelligent, vous avez tout de même besoin d’un réseau local opérationnel pour autoriser votre appareil de PDV à communiquer avec le lecteur intelligent. Le fonctionnement hors ligne avec des lecteurs intelligents concerne les scénarios dans lesquels votre PDV et votre lecteur ne peuvent pas communiquer avec Stripe, par exemple en cas de panne du fournisseur d’accès à Internet. Si vous avez besoin de pouvoir fonctionner hors ligne sans réseau local, les [lecteurs mobiles](https://docs.stripe.com/terminal/mobile-readers.md) de Stripe Terminal peuvent vous être utiles. Vous pouvez également fonctionner hors ligne avec une intégration d’applications sur des appareils. Dans la mesure où votre application de PDV fonctionne directement sur le lecteur intelligent, vous n’avez pas besoin d’un réseau local pour encaisser des paiements. Toutefois, vous devez tout de même être sur un réseau local au premier démarrage de votre lecteur, même si ce réseau n’a pas accès à Internet. > En mode hors ligne, les informations de paiement sont collectées au moment de la vente et l’autorisation n’est tentée qu’après que la connectivité est rétablie et que le paiement est transmis. Lorsqu’il fonctionne hors ligne avec un lecteur connecté à Internet, le lecteur stocke les informations de paiement collectées. En tant qu’utilisateur, vous assumez tous les risques de refus et de falsification associés à une transaction hors ligne. Si votre lecteur falsifié ne peut pas transférer les paiements à Stripe, ou si l’émetteur refuse la transaction, il n’y a aucun moyen de récupérer les fonds et il est possible que vous ne receviez pas le paiement du client pour les biens ou services déjà fournis. > > Pour limiter les risques de refus de la part de l’émetteur, nous vous conseillons de : > > - Rétablir la connexion Internet le plus rapidement possible pour enregistrer les paiements sur Stripe. - Bloquer les transactions supérieures à un certain montant. - [Faire échouer tous les paiements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#managing-risk) quand le SDK a stocké un ensemble de transactions dont la somme dépasse un certain montant. ## Encaisser des paiements en mode hors ligne Les paiements hors ligne suivent les mêmes étapes que les paiements en ligne : création, collecte, traitement et capture du paiement. Votre appareil peut passer du mode en ligne au mode hors ligne à n’importe quelle étape du processus. 1. [Activer le mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) 1. [Se connecter à un lecteur en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#connect-while-offline) 1. [Gérer les événements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#handle-offline-events) 1. [Créer un Payment Intent en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#create-payment-intent) 1. [Collecter un moyen de paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#collect-payment-method) 1. [Confirmer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#confirm-payment) 1. [Attendre l’acheminement des paiements](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#wait-for-forward) 1. (Facultatif) [Capturer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#capture-payment) 1. (Facultatif) [Examiner les paiements encaissés hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#examine-offline) ## Activer le mode hors ligne Utilisez un objet [Configuration](https://docs.stripe.com/api/terminal/configuration.md) ou [le Dashboard](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=dashboard#update-the-default-configuration-for-the-account) afin d’activer le mode hors ligne pour les appareils [pris en charge](https://docs.stripe.com/terminal/features/operate-offline/overview.md?reader-type=internet#availability) dans votre `Location`. ```curl curl https://api.stripe.com/v1/terminal/configurations \ -u "<>:" \ -d "offline[enabled]=true" ``` Après avoir activé le mode hors ligne sur un objet `Configuration`, vous pouvez l’[affecter](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#create-a-configuration-for-an-individual-location) à un objet `Location`. Vous pouvez également activer le mode hors ligne par défaut pour tous les emplacements (`Locations`) en mettant à jour l’objet `Configuration` [par défaut](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#retrieve-the-account-default-configuration) de votre compte. La propagation des modifications apportées à l’API Configuration vers votre SDK et votre lecteur peut prendre quelques minutes. Pour qu’elles soient prises en compte, vous devez vous déconnecter puis vous reconnecter à votre lecteur. ## Se connecter à un lecteur en mode hors ligne Le lecteur stocke localement les informations nécessaires sur `Location` après la connexion en ligne. Lors des connexions hors ligne suivantes, il utilise les informations de configuration stockées à partir de cet emplacement`Location`. Pour encaisser des paiements à l’aide d’un lecteur intelligent en mode hors ligne, vous devez avoir établi une connexion à un lecteur mobile du même type au même emplacement (`Location`) en étant en ligne au cours des 30 derniers jours sur le même réseau local. Le lecteur stocke les informations relatives à l’objet `Location` en local après s’être connecté en ligne, puis déduit les informations de configuration de cet emplacement `Location` lorsqu’il fonctionne hors ligne. Votre lecteur et votre appareil de point de vente doivent être sur le même réseau local que celui utilisé pour se connecter à Internet. Vous ne pouvez pas changer de réseau en mode hors ligne. Si vous tentez de vous connecter à un lecteur hors ligne sans remplir ces conditions, la demande échoue avec une erreur. | Erreur | Résolution | | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Le SDK n’est pas connecté à Internet** | Assurez-vous que l’objet `Location` que vous utilisez est [configuré](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) pour le mode hors ligne. Sinon, connectez-vous en ligne à un lecteur, puis hors ligne à un lecteur du même type. | | **Le lecteur sélectionné nécessite une mise à jour logicielle avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Le logiciel du lecteur n’a pas été mis à jour depuis 30 jours ou plus. Connectez-vous au lecteur en ligne pour le mettre à jour. | | **Le lecteur sélectionné doit être appairé en ligne à cet endroit avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Vous essayez de vous connecter à un type de lecteur auquel votre PDV ne s’est pas encore connecté en ligne. Vous devez d’abord vous connecter en ligne à ce lecteur ou à tout autre lecteur du même type. Si vous voulez vous connecter hors ligne, vous pouvez également vous connecter à un type de lecteur auquel votre PDV s’est déjà connecté en ligne. | ## Gérer les événements hors ligne [Côté client] - [OfflineListener (Java)](https://stripe.dev/stripe-terminal-java/external/com.stripe.stripeterminal.external.callable/-offline-listener/index.html) Pour permettre à votre application de recevoir des mises à jour sur l’état du réseau du SDK et des paiements transmis, implémentez l’interface `OfflineListener` et transmettez-la au SDK Terminal. Vous devez définir `OfflineListener` avant de collecter les paiements en mode hors ligne. ```java public class CustomOfflineListener implements OfflineListener { @Override public void onOfflineStatusChange(@NotNull OfflineStatus offlineStatus) { // Check the value of `offlineStatus` and update your UI accordingly. For instance, // you can check the SDK's network status at `offlineStatus.sdk.networkStatus`. // // You can also check the SDK's current offline status using // `Terminal::offlineStatus`. } @Override public void onPaymentIntentForwarded(@NotNull PaymentIntent paymentIntent, @Nullable TerminalException e) { // The PaymentIntent was successfully forwarded, or an error occurred. // Reconcile any local state using the backend-generated `PaymentIntent::getId` // and the metadata you supplied when creating the PaymentIntent. // // Note that the `PaymentIntent::getId` may still be null if creating the // PaymentIntent in the backend failed. } @Override public void onForwardingFailure(@NotNull TerminalException e) { // A non-specific error occurred while forwarding a PaymentIntent. // Check the error message and your integration implementation to // troubleshoot. } } ``` ```java Terminal.init( new CustomConnectionTokenProvider(), new CustomTerminalListener(), getApplicationInfo(), LogLevel.VERBOSE, new CustomOfflineListener() ); ``` ## Créer un PaymentIntent en mode en ligne [Côté client] - [createPaymentIntent (Java)](https://stripe.dev/stripe-terminal-java/core/com.stripe.stripeterminal/-terminal/create-payment-intent.html) - [CreateConfiguration (Java)](https://stripe.dev/stripe-terminal-java/external/com.stripe.stripeterminal.external.models/-create-configuration/index.html) - [OfflineDetails (Java)](https://stripe.dev/stripe-terminal-java/external/com.stripe.stripeterminal.external.models/-offline-details/index.html) Afin prendre en charge le fonctionnement hors ligne, utilisez l’attribut `createPaymentIntent` du SDK pour créer des objets PaymentIntent. Cela permet au SDK de créer des PaymentIntents en mode hors ligne et de les transmettre à Stripe une fois que vous avez rétabli la connexion. En mode hors ligne, les objets `PaymentIntent` ont un champ `id` vide. Nous vous recommandons d’ajouter un identifiant personnalisé aux [metadata](https://docs.stripe.com/payments/payment-intents.md#storing-information-in-metadata) pour faciliter le rapprochement des objets `PaymentIntent`créés hors ligne dans votre base de données. Vous pouvez configurer un endpoint de [webhook](https://docs.stripe.com/webhooks.md) pour recevoir des événements `PaymentIntent` lorsque des paiements hors ligne sont transmis à Stripe, et utiliser votre identifiant pour les associer à un ID `PaymentIntent`. ```java HashMap metadata = new HashMap<> (); metadata.put("unique-id", UUID.randomUUID().toString()); final PaymentIntentParameters params = new PaymentIntentParameters.Builder() .setAmount(cart.getTotal()) .setCurrency(cart.getCurrency()).setMetadata(metadata) .build(); final PaymentIntentCallback createPaymentCallback = new PaymentIntentCallback() { @Override public void onSuccess(@NotNull PaymentIntent paymentIntent) { System.out.println("createPaymentIntent succeeded");// If the `PaymentIntent` was created offline, its `id` field will be null. if (paymentIntent.getId() != null) { System.out.println("created online"); } else { System.out.println("created offline"); } // ... Collect a PaymentMethod } @Override public void onFailure(@NotNull TerminalException e) { // Handle errors in your application. } }; Terminal.getInstance().createPaymentIntent(params, null, createPaymentCallback); ``` `Terminal.createPaymentIntent` accepte un paramètre `CreateConfiguration`. Par défaut, si vous êtes en mode hors ligne, le SDK Terminal enregistre tous les paiements hors ligne, puis les transmet au backend de Stripe lorsque la connexion est rétablie. Pour personnaliser ce comportement, vous pouvez transmettre un objet `CreateConfiguration` avec un attribut `offlineBehavior` défini sur `REQUIRE_ONLINE`, `PREFER_ONLINE` ou `FORCE_OFFLINE`. #### Gestion du risque La définition de `offlineBehavior` sur `REQUIRE_ONLINE` entraîne un échec de la transaction en cours si vous fonctionnez en mode hors ligne. Par exemple, vous pouvez refuser les transactions supérieures à un certain montant ou toutes les transactions hors ligne si le lecteur a stocké un ensemble de transactions dont la somme dépasse un certain montant. Le SDK expose deux propriétés pour vous aider à gérer les risques : 1. `Terminal.offlineStatus.reader.offlinePaymentsCount` 1. `Terminal.offlineStatus.reader.offlinePaymentAmountsByCurrency` #### Gérer la latence en mode hors ligne Based on your network connectivity, the Terminal SDK automatically determines whether to collect payments online or offline. However, you might want to operate offline despite having an active network connection (for example, if you need to collect transactions quickly and your network connection is slow). You can pass a `CreateConfiguration` object with `offlineBehavior` set to `FORCE_OFFLINE` to collect the payment offline regardless of connectivity. Les paiements collectés hors ligne alors que le lecteur Terminal dispose d’une connexion réseau active sont transmis en arrière-plan. ```java // Your app might want to prevent offline payments for too large an amount. // Here, we block the payment if the amount is over 1000 usd. // Otherwise, we allow collecting offline if the network connection is unavailable. OfflineBehavior offlineBehavior = cart.getTotal() > 1000000 ? offlineBehavior = OfflineBehavior.REQUIRE_ONLINE : OfflineBehavior.PREFER_ONLINE; final CreateConfiguration createConfig = new CreateConfiguration(offlineBehavior); Terminal.getInstance().createPaymentIntent(params, createConfig, createPaymentCallback); ``` ## Collecter un moyen de paiement [Côté client] - [CollectPaymentIntentConfiguration (Java)](https://stripe.dev/stripe-terminal-java/external/com.stripe.stripeterminal.external.models/-collect-payment-intent-configuration/index.html) > La responsabilité du paiement vous incombe lorsque vous utilisez votre lecteur hors ligne. Les données de bande magnétique étant faciles à usurper, Stripe désactive cette option pour les paiements hors ligne. En outre, la présentation des cartes n’est pas prise en charge sur les marchés où l’*authentification forte du client* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase) est requise. La collecte des paiements en mode hors ligne est similaire [à la collecte des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#collect-payment). Votre lecteur intelligent affiche automatiquement les options de paiement disponibles pour le client. > Les lecteurs ne prennent pas en charge l’[inspection des informations du moyen de paiement avant autorisation](https://docs.stripe.com/terminal/payments/collect-card-payment.md?terminal-sdk-platform=java#collect-inspect-payment-method) en mode hors ligne. Bien que vous puissiez toujours utiliser `updatePaymentIntent` dans `CollectPaymentIntentConfiguration`, le champ `paymentMethod` de la PaymentIntent est absent lorsque le SDK fonctionne hors ligne. ```java final PaymentIntentCallback collectPaymentCallback = new PaymentIntentCallback() { @Override public void onSuccess(@NotNull PaymentIntent paymentIntent) { System.out.println("collectPaymentMethod succeeded"); // ... Confirm the payment } @Override public void onFailure(@NotNull TerminalException e) { e.printStackTrace(); } }; final CollectPaymentIntentConfiguration collectConfig = new CollectPaymentIntentConfiguration.Builder().build(); Terminal.getInstance().collectPaymentMethod(paymentIntent, collectConfig, collectPaymentCallback); ``` ## Confirmer le paiement [Côté client] La confirmation des paiements en mode hors ligne est similaire à la [confirmation des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#confirm-payment). La principale différence est que votre intégration doit gérer des types d’erreurs spécifiques au mode hors ligne, par exemple lorsque la transaction dépasse la limite maximum de 10 000 USD appliquée par Stripe pour les paiements hors ligne (ou un montant équivalent dans votre devise). Dans certains cas, le SDK peut créer en ligne un `PaymentIntent`, mais le confirmer hors ligne. Dans ce cas, le `PaymentIntent` peut avoir un `id` non nul. S’il a été confirmé hors ligne, `offlineDetails` sera défini et renseigné. ```java final PaymentIntentCallback confirmPaymentIntentCallback = new PaymentIntentCallback() { @Override public void onSuccess(@NotNull PaymentIntent paymentIntent) { System.out.println("confirmPaymentIntent succeeded"); // If the `PaymentIntent` was confirmed offline, `paymentIntent.getOfflineDetails()` will be definedif (paymentIntent.getOfflineDetails() != null) { System.out.println("confirmed offline"); } else { System.out.println("confirmed online"); } } @Override public void onFailure(@NotNull TerminalException e) { // Handle offline-specific errors in your application (for example, // unsupported payment method). e.printStackTrace(); } }; Terminal.getInstance().confirmPaymentIntent(paymentIntent, confirmPaymentIntentCallback); ``` #### Fourniture de reçus Vous pouvez avoir besoin d’informations concernant la carte utilisée pour un paiement en mode hors ligne. Par exemple, vous pouvez avoir besoin de générer un reçu pour les clients qui le demandent au moment de l’achat. Si le PaymentIntent est confirmé hors ligne, récupérez sa propriété [OfflineCardPresentDetails](https://stripe.dev/stripe-terminal-java/external/com.stripe.stripeterminal.external.models/-offline-card-present-details/index.html) from the `paymentIntent.offlineDetails.offlineCardPresentDetails`. Ce hachage contient une propriété [ReceiptDetails](https://stripe.dev/stripe-terminal-java/external/com.stripe.stripeterminal.external.models/-receipt-details/index.html) que vous pouvez utiliser pour générer un reçu ainsi que d’autres informations sur la carte bancaire, notamment sa marque et le nom de son titulaire. Les champs des reçus `account_type` et `authorization_response_code` ne sont pas disponibles sur les PaymentIntents traités en mode hors ligne. Les [reçus par e-mail préconfigurés](https://docs.stripe.com/terminal/features/receipts.md#prebuilt) sont uniquement envoyés lorsque la connexion est rétablie et que le paiement est capturé. ## Attendre l'acheminement des paiements [Côté client] Quand la connexion au réseau est rétablie, le lecteur commence automatiquement à transférer les paiements hors ligne stockés. Le lecteur tente de transmettre les paiements même si l’état de son réseau est hors ligne. Cela signifie que votre fournisseur de tokens de connexion peut recevoir une demande de token de connexion, même lorsque l’appareil est hors ligne. Si vous déconnectez ou éteignez votre lecteur intelligent trop tôt, vos paiements risquent de ne pas être transférés. Vous pouvez interroger `Terminal.offlineStatus.reader.networkStatus` pour vous assurer que votre lecteur est en ligne et qu’il peut transférer les paiements, et `Terminal.offlineStatus.reader.offlinePaymentsCount` pour connaître le nombre de paiements que le lecteur doit transférer. Si votre lecteur intelligent est endommagé ou ne peut plus accepter de paiements, vous pouvez généralement toujours transférer vos paiements stockés. Veillez à connecter le lecteur intelligent à votre PDV et à rétablir l’accès à Internet pour lui permettre de se reconnecter à Stripe. ## Capturer le paiement Lorsque vous êtes hors ligne, vous pouvez créer des PaymentIntents avec l’attribut `captureMethod` défini sur `automatic`. Une fois que vous avez confirmé ces PaymentIntents, ils passent à l’état `SUCCEEDED` au lieu de `REQUIRES_CAPTURE` . Stripe capture automatiquement les paiements une fois que vous les avez transmis. Si vous choisissez la capture manuelle, les paiements acheminés et autorisés doivent alors être capturés depuis votre back-end ou votre application. - Afin de capturer les paiements depuis votre back-end, utilisez des [webhooks](https://docs.stripe.com/webhooks.md) pour écouter les PaymentIntents à l’état `requires_capture`. - Pour capturer les paiements depuis votre application, attendez que celle-ci reçoive les appels à `OfflineListener.OnPaymentIntentForwarded` pour chaque PaymentIntent à mesure que le lecteur les transmet. Un PaymentIntent est prêt à capturer si son état est `REQUIRES_CAPTURE` et si le paramètre `offlineDetails` est vide ou présente une valeur `requiresUpload` de `false` . ```java final PaymentIntentCallback confirmPaymentIntentCallback = new PaymentIntentCallback() { @Override public void onSuccess(@NotNull PaymentIntent paymentIntent) { System.out.println("confirmPaymentIntent succeeded"); if (paymentIntent.getStatus() == PaymentIntentStatus.REQUIRES_CAPTURE) {OfflineDetails offlineDetails = paymentIntent.getOfflineDetails(); if (offlineDetails != null && offlineDetails.getRequiresUpload()) { // Offline payment, wait for `onPaymentIntentForwarded` (see snippet below) } else { // Online payment, can be captured now } } else { // Handle other status results here } } @Override public void onFailure(@NotNull TerminalException e) { // Handle offline-specific errors in your application (for example, // unsupported payment method). } }; Terminal.getInstance().confirmPaymentIntent(paymentIntent, confirmPaymentIntentCallback); ``` Capturez un paiement hors ligne après qu’il ait été transmis par le lecteur dans votre `OfflineListener::onPaymentIntentForwarded` : ```java public class CustomOfflineListener implements OfflineListener { // ... @Override public void onPaymentIntentForwarded(@NotNull PaymentIntent paymentIntent, @Nullable TerminalException e) { if (e != null) { // Handle the error appropriate for your application } else if (paymentIntent.getStatus() == PaymentIntentStatus.REQUIRES_CAPTURE) { // The paymentIntent is ready to be captured } else { // Handle other status results here } } // ... } ``` ## Examiner les paiements collectés hors ligne Après autorisation, vous pouvez utiliser l’API [PaymentIntents](https://docs.stripe.com/payments/payment-intents.md) pour examiner les informations hors ligne d’un paiement. Accédez aux [informations relatives au moyen de paiement](https://docs.stripe.com/api/charges/object.md#charge_object-payment_method_details-card_present-offline) sur le dernier objet [Charge](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-latest_charge) d’un `PaymentIntent` pour déterminer s’il a été encaissé hors ligne. # .NET > This is a .NET for when terminal-card-present-integration is terminal and terminal-sdk-platform is dotnet and reader-type is internet. View the full page at https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments?terminal-card-present-integration=terminal&terminal-sdk-platform=dotnet&reader-type=internet. Le SDK Terminal permet à votre application de continuer à encaisser des paiements à l’aide d’un lecteur intelligent sans connexion Internet. Si vous utilisez un appareil de PDV distinct avec un lecteur Stripe intelligent, vous avez tout de même besoin d’un réseau local opérationnel pour autoriser votre appareil de PDV à communiquer avec le lecteur intelligent. Le fonctionnement hors ligne avec des lecteurs intelligents concerne les scénarios dans lesquels votre PDV et votre lecteur ne peuvent pas communiquer avec Stripe, par exemple en cas de panne du fournisseur d’accès à Internet. Si vous avez besoin de pouvoir fonctionner hors ligne sans réseau local, les [lecteurs mobiles](https://docs.stripe.com/terminal/mobile-readers.md) de Stripe Terminal peuvent vous être utiles. Vous pouvez également fonctionner hors ligne avec une intégration d’applications sur des appareils. Dans la mesure où votre application de PDV fonctionne directement sur le lecteur intelligent, vous n’avez pas besoin d’un réseau local pour encaisser des paiements. Toutefois, vous devez tout de même être sur un réseau local au premier démarrage de votre lecteur, même si ce réseau n’a pas accès à Internet. > En mode hors ligne, les informations de paiement sont collectées au moment de la vente et l’autorisation n’est tentée qu’après que la connectivité est rétablie et que le paiement est transmis. Lorsqu’il fonctionne hors ligne avec un lecteur connecté à Internet, le lecteur stocke les informations de paiement collectées. En tant qu’utilisateur, vous assumez tous les risques de refus et de falsification associés à une transaction hors ligne. Si votre lecteur falsifié ne peut pas transférer les paiements à Stripe, ou si l’émetteur refuse la transaction, il n’y a aucun moyen de récupérer les fonds et il est possible que vous ne receviez pas le paiement du client pour les biens ou services déjà fournis. > > Pour limiter les risques de refus de la part de l’émetteur, nous vous conseillons de : > > - Rétablir la connexion Internet le plus rapidement possible pour enregistrer les paiements sur Stripe. - Bloquer les transactions supérieures à un certain montant. - [Faire échouer tous les paiements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#managing-risk) quand le SDK a stocké un ensemble de transactions dont la somme dépasse un certain montant. ## Encaisser des paiements en mode hors ligne Les paiements hors ligne suivent les mêmes étapes que les paiements en ligne : création, collecte, traitement et capture du paiement. Votre appareil peut passer du mode en ligne au mode hors ligne à n’importe quelle étape du processus. 1. [Activer le mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) 1. [Se connecter à un lecteur en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#connect-while-offline) 1. [Gérer les événements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#handle-offline-events) 1. [Créer un Payment Intent en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#create-payment-intent) 1. [Collecter un moyen de paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#collect-payment-method) 1. [Confirmer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#confirm-payment) 1. [Attendre l’acheminement des paiements](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#wait-for-forward) 1. (Facultatif) [Capturer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#capture-payment) 1. (Facultatif) [Examiner les paiements encaissés hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#examine-offline) ## Activer le mode hors ligne Utilisez un objet [Configuration](https://docs.stripe.com/api/terminal/configuration.md) ou [le Dashboard](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=dashboard#update-the-default-configuration-for-the-account) afin d’activer le mode hors ligne pour les appareils [pris en charge](https://docs.stripe.com/terminal/features/operate-offline/overview.md?reader-type=internet#availability) dans votre `Location`. ```curl curl https://api.stripe.com/v1/terminal/configurations \ -u "<>:" \ -d "offline[enabled]=true" ``` Après avoir activé le mode hors ligne sur un objet `Configuration`, vous pouvez l’[affecter](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#create-a-configuration-for-an-individual-location) à un objet `Location`. Vous pouvez également activer le mode hors ligne par défaut pour tous les emplacements (`Locations`) en mettant à jour l’objet `Configuration` [par défaut](https://docs.stripe.com/terminal/fleet/configurations-overview.md?dashboard-or-api=api#retrieve-the-account-default-configuration) de votre compte. La propagation des modifications apportées à l’API Configuration vers votre SDK et votre lecteur peut prendre quelques minutes. Pour qu’elles soient prises en compte, vous devez vous déconnecter puis vous reconnecter à votre lecteur. ## Se connecter à un lecteur en mode hors ligne Le lecteur stocke localement les informations nécessaires sur `Location` après la connexion en ligne. Lors des connexions hors ligne suivantes, il utilise les informations de configuration stockées à partir de cet emplacement`Location`. Pour encaisser des paiements à l’aide d’un lecteur intelligent en mode hors ligne, vous devez avoir établi une connexion à un lecteur mobile du même type au même emplacement (`Location`) en étant en ligne au cours des 30 derniers jours sur le même réseau local. Le lecteur stocke les informations relatives à l’objet `Location` en local après s’être connecté en ligne, puis déduit les informations de configuration de cet emplacement `Location` lorsqu’il fonctionne hors ligne. Votre lecteur et votre appareil de point de vente doivent être sur le même réseau local que celui utilisé pour se connecter à Internet. Vous ne pouvez pas changer de réseau en mode hors ligne. Si vous tentez de vous connecter à un lecteur hors ligne sans remplir ces conditions, la demande échoue avec une erreur. | Erreur | Résolution | | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Le SDK n’est pas connecté à Internet** | Assurez-vous que l’objet `Location` que vous utilisez est [configuré](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) pour le mode hors ligne. Sinon, connectez-vous en ligne à un lecteur, puis hors ligne à un lecteur du même type. | | **Le lecteur sélectionné nécessite une mise à jour logicielle avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Le logiciel du lecteur n’a pas été mis à jour depuis 30 jours ou plus. Connectez-vous au lecteur en ligne pour le mettre à jour. | | **Le lecteur sélectionné doit être appairé en ligne à cet endroit avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Vous essayez de vous connecter à un type de lecteur auquel votre PDV ne s’est pas encore connecté en ligne. Vous devez d’abord vous connecter en ligne à ce lecteur ou à tout autre lecteur du même type. Si vous voulez vous connecter hors ligne, vous pouvez également vous connecter à un type de lecteur auquel votre PDV s’est déjà connecté en ligne. | ## Gérer les événements hors ligne [Côté client] Pour permettre à votre application de recevoir des mises à jour sur l’état du réseau du SDK et des paiements transmis, implémentez l’interface `IOfflineListener` et transmettez-la au SDK Terminal. Vous devez définir `IOfflineListener` avant de collecter les paiements en mode hors ligne. ```csharp using TerminalSdk.Api; namespace StripeExampleApi; public class CustomOfflineListener : IOfflineListener { public void OnOfflineStatusChange(OfflineStatus offlineStatus) { // Check the value of `offlineStatus` and update your UI accordingly. For instance, // you can check the reader's network status at `offlineStatus.Reader.NetworkStatus`. // // You can also check the reader's current offline status using // `Terminal.OfflineStatus`. } public void OnPaymentIntentForwarded(PaymentIntent paymentIntent, TerminalException? e) { // The PaymentIntent was successfully forwarded, or an error occurred. // Reconcile any local state using the backend-generated `paymentIntent.Id` // and the metadata you supplied when creating the PaymentIntent. // // Note that the `PaymentIntent.Id` may still be null if creating the // PaymentIntent in the backend failed. } public void OnForwardingFailure(TerminalException e) { // A non-specific error occurred while forwarding a PaymentIntent. // Check the error message and your integration implementation to // troubleshoot. } } ``` ```csharp Terminal.InitTerminal( new CustomConnectionTokenProvider(), new CustomTerminalListener(), new CustomOfflineListener(), new ApplicationInformation.Builder() .SetName("Terminal Test Console") .SetVersion("0.0.0.1") .SetDataDirectory(new DirectoryInfo("C:\\TerminalSDK")) .Build() ); ``` ## Créer un PaymentIntent en mode en ligne [Côté client] Afin prendre en charge le fonctionnement hors ligne, utilisez l’attribut `CreatePaymentIntentAsync` du SDK pour créer des objets PaymentIntent. Cela permet au SDK de créer des PaymentIntents en mode hors ligne et de les transmettre à Stripe une fois que vous avez rétabli la connexion. En mode hors ligne, les objets `PaymentIntent` ont un champ `Id` vide. Nous vous recommandons d’ajouter un identifiant personnalisé aux [Metadata](https://docs.stripe.com/payments/payment-intents.md#storing-information-in-metadata) pour faciliter le rapprochement des objets `PaymentIntent`créés hors ligne dans votre base de données. Vous pouvez configurer un endpoint de [webhook](https://docs.stripe.com/webhooks.md) pour recevoir des événements `PaymentIntent` lorsque des paiements hors ligne sont transmis à Stripe, et utiliser votre identifiant pour les associer à un ID `PaymentIntent`. ```csharp // Build up parameters for creating a `PaymentIntent` var paymentIntentParameters = new PaymentIntentParameters.Builder() .SetAmount(cart.Total) .SetCurrency(cart.Currency).SetMetadata(new Dictionary() { { "unique-id", Guid.NewGuid().ToString() } }) .Build(); try { var paymentIntent = await Terminal.Instance.CreatePaymentIntentAsync(paymentIntentParameters, null); _logger.LogDebug("CreatePaymentIntentAsync succeeded");// If the `PaymentIntent` was created offline, its `Id` field will be null. if (paymentIntent.Id != null) { _logger.LogDebug("created online"); } else { _logger.LogDebug("created offline"); } // ... Collect a PaymentMethod } catch (TerminalException ex) { _logger.LogError(ex, "CreatePaymentIntentAsync failed"); // Handle errors in your application. } ``` `Terminal.CreatePaymentIntentAsync` accepte un paramètre `CreateConfiguration`. Par défaut, si vous êtes en mode hors ligne, le SDK Terminal enregistre tous les paiements hors ligne, puis les transmet au backend de Stripe lorsque la connexion est rétablie. Pour personnaliser ce comportement, vous pouvez transmettre un objet `CreateConfiguration` avec un attribut `OfflineBehavior` défini sur `RequireOnline`, `PreferOnline` ou `ForceOffline`. #### Gestion du risque La définition de `OfflineBehavior` sur `RequireOnline` entraîne un échec de la transaction en cours si vous fonctionnez en mode hors ligne. Par exemple, vous pouvez refuser les transactions supérieures à un certain montant ou toutes les transactions hors ligne si le lecteur a stocké un ensemble de transactions dont la somme dépasse un certain montant. Le SDK expose deux propriétés pour vous aider à gérer les risques : 1. `Terminal.OfflineStatus.Reader.OfflinePaymentsCount` 1. `Terminal.OfflineStatus.Reader.OfflinePaymentAmountsByCurrency` #### Gérer la latence en mode hors ligne Based on your network connectivity, the Terminal SDK automatically determines whether to collect payments online or offline. However, you might want to operate offline despite having an active network connection (for example, if you need to collect transactions quickly and your network connection is slow). You can pass a `CreateConfiguration` object with `OfflineBehavior` set to `ForceOffline` to collect the payment offline regardless of connectivity. Les paiements collectés hors ligne alors que le lecteur Terminal dispose d’une connexion réseau active sont transmis en arrière-plan. ```csharp // Your app might want to prevent offline payments for too large an amount. // Here, we require a network connection if the payment amount is over 1000 usd. // Otherwise, we allow collecting offline if the network connection is unavailable.var offlineBehavior = OfflineBehavior.PreferOnline; if (cart.total > 1000000) { offlineBehavior = OfflineBehavior.RequireOnline; } var createConfig = new CreateConfiguration.Builder() .SetOfflineBehavior(offlineBehavior) .Build(); var paymentIntent = await Terminal.Instance.CreatePaymentIntentAsync(paymentIntentParameters, createConfig); _logger.LogDebug("CreatePaymentIntentAsync succeeded"); // ...continue transaction ``` ## Collecter un moyen de paiement [Côté client] > La responsabilité du paiement vous incombe lorsque vous utilisez votre lecteur hors ligne. Les données de bande magnétique étant faciles à usurper, Stripe désactive cette option pour les paiements hors ligne. En outre, la présentation des cartes n’est pas prise en charge sur les marchés où l’*authentification forte du client* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase) est requise. La collecte des paiements en mode hors ligne est similaire [à la collecte des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#collect-payment). Votre lecteur intelligent affiche automatiquement les options de paiement disponibles pour le client. > La [vérification des informations relatives aux moyens de paiement avant l’autorisation](https://docs.stripe.com/terminal/payments/collect-card-payment.md?terminal-sdk-platform=dotnet#collect-inspect-payment-method) n’est pas prise en charge en mode hors ligne. Bien que vous puissiez toujours utiliser la méthode `SetUpdatePaymentIntent` dans `CollectConfiguration`, le champ `paymentMethod` du PaymentIntent est absent si le SDK fonctionne en mode hors ligne. ```csharp try { var collectConfig = new CollectConfiguration.Builder() .Build(); var collectedPaymentIntent = await Terminal.Instance.CollectPaymentMethodAsync(paymentIntent, collectConfig); _logger.LogDebug("CollectPaymentMethodAsync succeeded"); // ... Confirm the payment } catch (TerminalException ex) { // Handle errors in your application. } ``` ## Confirmer le paiement [Côté client] La confirmation des paiements en mode hors ligne est similaire à la [confirmation des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#confirm-payment). La principale différence est que votre intégration doit gérer des types d’erreurs spécifiques au mode hors ligne, par exemple lorsque la transaction dépasse la limite maximum de 10 000 USD appliquée par Stripe pour les paiements hors ligne (ou un montant équivalent dans votre devise). Dans certains cas, le SDK peut créer en ligne un `PaymentIntent`, mais le confirmer hors ligne. Dans ce cas, le `PaymentIntent` peut avoir un `Id` non nul. S’il a été confirmé hors ligne, `OfflineDetails` sera défini et renseigné. ```csharp try { var confirmedPaymentIntent = await Terminal.Instance.ConfirmPaymentIntentAsync(collectedPaymentIntent); } catch (TerminalException ex) { // Handle offline-specific errors in your application (for example, // unsupported payment method). } ``` #### Fourniture de reçus Vous pouvez avoir besoin d’informations concernant la carte utilisée pour un paiement en mode hors ligne. Par exemple, vous pouvez avoir besoin de générer un reçu pour les clients qui le demandent au moment de l’achat. Si le PaymentIntent est confirmé hors ligne, récupérez sa propriété OfflineCardPresentDetails from the `paymentIntent.OfflineDetails.OfflineCardPresentDetails` . Ce hachage contient une propriété ReceiptDetails que vous pouvez utiliser pour générer un reçu ainsi que d’autres informations sur la carte bancaire, notamment sa marque et le nom de son titulaire. Les champs des reçus `account_type` et `authorization_response_code` ne sont pas disponibles sur les PaymentIntents traités en mode hors ligne. Les [reçus par e-mail préconfigurés](https://docs.stripe.com/terminal/features/receipts.md#prebuilt) sont uniquement envoyés lorsque la connexion est rétablie et que le paiement est capturé. ## Attendre l'acheminement des paiements [Côté client] Quand la connexion au réseau est rétablie, le lecteur commence automatiquement à transférer les paiements hors ligne stockés. Le lecteur tente de transmettre les paiements même si l’état de son réseau est hors ligne. Cela signifie que votre fournisseur de tokens de connexion peut recevoir une demande de token de connexion, même lorsque l’appareil est hors ligne. Si vous déconnectez ou éteignez votre lecteur intelligent trop tôt, vos paiements risquent de ne pas être transférés. Vous pouvez interroger `Terminal.OfflineStatus.Reader.NetworkStatus` pour vous assurer que votre lecteur est en ligne et qu’il peut transférer les paiements, et `Terminal.OfflineStatus.Reader.OfflinePaymentsCount` pour connaître le nombre de paiements que le lecteur doit transférer. Si votre lecteur intelligent est endommagé ou ne peut plus accepter de paiements, vous pouvez généralement toujours transférer vos paiements stockés. Veillez à connecter le lecteur intelligent à votre PDV et à rétablir l’accès à Internet pour lui permettre de se reconnecter à Stripe. ## Capturer le paiement Lorsque vous êtes hors ligne, vous pouvez créer des PaymentIntents avec l’attribut `CaptureMethod` défini sur `Automatic` . Une fois que vous avez confirmé ces PaymentIntents, ils passent à l’état `Succeeded` au lieu de `RequiresCapture`. Stripe capture automatiquement les paiements une fois que vous les avez transmis. Si vous choisissez la capture manuelle, les paiements acheminés et autorisés doivent alors être capturés depuis votre back-end ou votre application. - Afin de capturer les paiements depuis votre back-end, utilisez des [webhooks](https://docs.stripe.com/webhooks.md) pour écouter les PaymentIntents à l’état `requires_capture`. - Pour capturer les paiements depuis votre application, attendez que celle-ci reçoive les appels à `OfflineListener.OnPaymentIntentForwarded` pour chaque PaymentIntent à mesure que le lecteur les transmet. Un PaymentIntent est prêt à capturer si son état est `RequiresCapture` et si le paramètre `OfflineDetails` est vide ou présente une valeur `RequiresUpload` de `false` . ```csharp try { var confirmedPaymentIntent = await Terminal.Instance.ConfirmPaymentIntentAsync(collectedPaymentIntent); _logger.LogDebug("ConfirmPaymentIntentAsync succeeded"); if (paymentIntent.status == PaymentIntentStatus.RequiresCapture) {var offlineDetails = paymentIntent.OfflineDetails; if (offlineDetails?.RequiresUpload == true) { // Offline payment, wait for `OnPaymentIntentForwarded` (see snippet below) } else { // Online payment, can be captured now } } else { // handle other paymentIntent.Status results here } } catch (TerminalException ex) { // Handle offline-specific errors in your application (for example, // unsupported payment method). _logger.LogError(ex, "ConfirmPaymentIntentAsync failed"); } ``` Capturez un paiement hors ligne après qu’il ait été transmis par le lecteur dans votre `IOfflineListener.OnPaymentIntentForwarded` : ```csharp using TerminalSdk.Api; namespace StripeExampleApi; public class CustomOfflineListener : IOfflineListener { public void OnPaymentIntentForwarded(PaymentIntent paymentIntent, TerminalException? e) { if (e != null) { // Handle the error appropriate for your application } else if (paymentIntent.Status == PaymentIntentStatus.RequiresCapture) { // The paymentIntent is ready to be captured } else { // Handle the paymentIntent.Status as appropriate. } } // ... } ``` ## Examiner les paiements collectés hors ligne Après autorisation, vous pouvez utiliser l’API [PaymentIntents](https://docs.stripe.com/payments/payment-intents.md) pour examiner les informations hors ligne d’un paiement. Accédez aux [informations relatives au moyen de paiement](https://docs.stripe.com/api/charges/object.md#charge_object-payment_method_details-card_present-offline) sur le dernier objet [Charge](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-latest_charge) d’un `PaymentIntent` pour déterminer s’il a été encaissé hors ligne. # iOS > This is a iOS for when terminal-card-present-integration is terminal and terminal-sdk-platform is ios and reader-type is simulated. View the full page at https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments?terminal-card-present-integration=terminal&terminal-sdk-platform=ios&reader-type=simulated. Le SDK Terminal permet à votre application de continuer à encaisser les paiements à l’aide d’un lecteur de simulation sans connexion réseau. > En mode hors ligne, les informations de paiement sont collectées au moment de la vente et l’autorisation n’est tentée qu’après que la connectivité est rétablie et que le paiement est transmis. En tant qu’utilisateur, vous assumez tous les risques de refus et de falsification associés à une transaction hors ligne. Si votre lecteur falsifié ne peut pas transférer les paiements à Stripe, ou si l’émetteur refuse la transaction, il n’y a aucun moyen de récupérer les fonds et il est possible que vous ne receviez pas le paiement du client pour les biens ou services déjà fournis. > > Pour limiter les risques de refus de la part de l’émetteur, nous vous conseillons de : > > - Rétablir la connexion Internet le plus rapidement possible pour enregistrer les paiements sur Stripe. - Bloquer les transactions supérieures à un certain montant. - [Faire échouer tous les paiements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#managing-risk) quand le SDK a stocké un ensemble de transactions dont la somme dépasse un certain montant. ## Encaisser des paiements en mode hors ligne Les paiements hors ligne suivent les mêmes étapes que les paiements en ligne : création, collecte, traitement et capture du paiement. Votre appareil peut passer du mode en ligne au mode hors ligne à n’importe quelle étape du processus. 1. [Activer le mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) 1. [Se connecter à un lecteur en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#connect-while-offline) 1. [Gérer les événements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#handle-offline-events) 1. [Créer un Payment Intent en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#create-payment-intent) 1. [Collecter un moyen de paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#collect-payment-method) 1. [Confirmer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#confirm-payment) 1. [Attendre l’acheminement des paiements](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#wait-for-forward) 1. (Facultatif) [Capturer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#capture-payment) 1. (Facultatif) [Examiner les paiements encaissés hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#examine-offline) ## Activer le mode hors ligne Pour utiliser le mode hors ligne, votre application doit utiliser la version `3.3.0` ou une version ultérieure du SDK Terminal iOS. Configurez le lecteur de simulation pour activer le mode hors ligne. #### Swift ``` let simulatorConfiguration = Terminal.shared.simulatorConfiguration simulatorConfiguration.offlineEnabled = true ``` ## Se connecter à un lecteur en mode hors ligne Le SDK stocke localement les informations nécessaires sur `Location` après la connexion en ligne. Lors des connexions hors ligne suivantes, il utilise les informations de configuration stockées à partir de cet emplacement`Location`. Pour encaisser des paiements à l’aide d’un lecteur intelligent en mode hors ligne, vous devez avoir établi une connexion à un lecteur mobile du même type au même emplacement (`Location`) en étant en ligne au cours des 30 derniers jours et avoir mis à jour le logiciel de votre lecteur dans ce laps de temps. Si vous tentez de vous connecter à un lecteur hors ligne sans remplir ces conditions, la demande échoue avec une erreur. | Erreur | Résolution | | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Le SDK n’est pas connecté à Internet** | Assurez-vous d’avoir activé le mode hors ligne sur l’objet `SimulatorConfiguration` pour votre lecteur de simulation. Sinon, connectez-vous en ligne à un lecteur, puis hors ligne à un lecteur du même type. | | **Le lecteur sélectionné nécessite une mise à jour logicielle avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Vous avez défini la valeur `SimulateReaderUpdate` de l’objet `SimulatorConfiguration` du SDK sur `SimulateReaderUpdateRequiredForOffline`. Utilisez une valeur différente pour autoriser la connexion hors ligne. | | **Le lecteur sélectionné doit être appairé en ligne à cet endroit avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Vous essayez de vous connecter à un type de lecteur auquel votre PDV ne s’est pas encore connecté en ligne. Vous devez d’abord vous connecter en ligne à ce lecteur ou à tout autre lecteur du même type. Si vous voulez vous connecter hors ligne, vous pouvez également vous connecter à un type de lecteur auquel votre PDV s’est déjà connecté en ligne. | ## Gérer les événements hors ligne [Côté client] - [OfflineDelegate (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Protocols/SCPOfflineDelegate.html) Pour permettre à votre application de recevoir des mises à jour sur l’état du réseau du SDK et des paiements transmis, implémentez le protocole `OfflineDelegate`et transmettez-le au SDK Terminal. Vous devez définir `OfflineDelegate` avant de collecter les paiements en mode hors ligne. #### Swift ```swift import StripeTerminal class CustomOfflineDelegate: OfflineDelegate { func terminal(_ terminal: Terminal, didChangeOfflineStatus offlineStatus: OfflineStatus) { // Check the value of `offlineStatus` and update your UI accordingly. For instance, // you can check the SDK's network status at `offlineStatus.sdk.networkStatus`. // // You can also check the SDK's current offline status using // `Terminal.shared.offlineStatus.sdk.networkStatus`. } func terminal(_ terminal: Terminal, didForwardPaymentIntent intent: PaymentIntent, error: Error?) { // The PaymentIntent was successfully forwarded, or an error occurred. // Reconcile any local state using the backend-generated `PaymentIntent.stripeId` // and the metadata you supplied when creating the PaymentIntent. // // Note that the `PaymentIntent.stripeId` may still be nil if creating the // PaymentIntent in the backend failed. } func terminal(_ terminal: Terminal, didReportForwardingError error: Error) { // A non-specific error occurred while forwarding a PaymentIntent. // Check the error message and your integration implementation to // troubleshoot. } } ``` #### Swift ```swift import UIKit import StripeTerminal @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { Terminal.initWithTokenProvider(APIClient.shared) Terminal.shared.offlineDelegate = CustomOfflineDelegate() // ... return true } // ... } ``` ## Créer un PaymentIntent en mode en ligne [Côté client] - [createPaymentIntent (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)createPaymentIntent:completion:) - [CreateConfiguration (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCreateConfiguration.html) - [OfflineDetails (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPOfflineDetails.html) Afin prendre en charge le fonctionnement hors ligne, utilisez l’attribut `createPaymentIntent` du SDK pour créer des objets PaymentIntent. Cela permet au SDK de créer des PaymentIntents en mode hors ligne et de les transmettre à Stripe une fois que vous avez rétabli la connexion. En mode hors ligne, les objets `PaymentIntent` ont un champ `stripeId` vide. Nous vous recommandons d’ajouter un identifiant personnalisé aux [metadata](https://docs.stripe.com/payments/payment-intents.md#storing-information-in-metadata) pour faciliter le rapprochement des objets `PaymentIntent`créés hors ligne dans votre base de données. Une fois que le `PaymentIntent` a été transmis à Stripe lors de l’[étape 7](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#wait-for-forward), utilisez votre identifiant personnalisé pour le rapprocher dans le rappel `OfflineDelegate.didForwardPaymentIntent`. #### Swift ```swift import UIKit import StripeTerminal class PaymentViewController: UIViewController { // Action for a "Checkout" button func checkoutAction() throws { // Populate the correct transaction amount from your application. let amount = UInt(10_00) // Build up parameters for creating a `PaymentIntent` let params = try PaymentIntentParametersBuilder( amount: amount, currency: "usd" ).setMetadata(["offlineId": UUID().uuidString]) .build() Terminal.shared.createPaymentIntent(params) { createResult, createError in if let error = createError { // Handle errors in your application. print("createPaymentIntent failed: \(error)") } else if let paymentIntent = createResult { print("createPaymentIntent succeeded")// If the `PaymentIntent` was created offline, its `stripeId` field will be nil. if let onlineCreatedId = paymentIntent.stripeId { print("created online"); } else { print("created offline") } } } } } ``` `Terminal.createPaymentIntent` accepte un paramètre `CreateConfiguration`. Par défaut, si vous êtes en mode hors ligne, le SDK Terminal enregistre tous les paiements hors ligne, puis les transmet au backend de Stripe lorsque la connexion est rétablie. Pour personnaliser ce comportement, vous pouvez transmettre un objet `CreateConfiguration` avec un attribut `offlineBehavior` défini sur `REQUIRE_ONLINE`, `PREFER_ONLINE` ou `FORCE_OFFLINE`. #### Gestion du risque La définition de `offlineBehavior` sur `REQUIRE_ONLINE` entraîne un échec de la transaction en cours si vous fonctionnez en mode hors ligne. Par exemple, vous pouvez refuser les transactions supérieures à un certain montant ou toutes les transactions hors ligne si le SDK a stocké un ensemble de transactions dont la somme dépasse un certain montant. Le SDK expose deux propriétés pour vous aider à gérer les risques : 1. `Terminal.offlineStatus.sdk.offlinePaymentsCount` 1. `Terminal.offlineStatus.sdk.offlinePaymentAmountsByCurrency` #### Gérer la latence en mode hors ligne Based on your network connectivity, the Terminal SDK automatically determines whether to collect payments online or offline. However, you might want to operate offline despite having an active network connection (for example, if you need to collect transactions quickly and your network connection is slow). You can pass a `CreateConfiguration` object with `offlineBehavior` set to `FORCE_OFFLINE` to collect the payment offline regardless of connectivity. Les paiements collectés hors ligne alors que le SDK Terminal dispose d’une connexion réseau active sont transmis en arrière-plan. #### Swift ```swift import UIKit import StripeTerminal class PaymentViewController: UIViewController { // Action for a "Checkout" button func checkoutAction() throws { // ...build up parameters and callback for creating a `PaymentIntent` // Your app might want to prevent offline payments for too large an amount. // Here, we block the payment if the amount is over 1000 usd. // Otherwise, we allow collecting offline if the network connection is unavailable.let offlineBehavior: SCPOfflineBehavior = { if amount > UInt(1_000_00) { return .requireOnline } else { return .preferOnline } }() let createConfiguration = try CreateConfigurationBuilder().setOfflineBehavior(offlineBehavior).build() Terminal.shared.createPaymentIntent(params, createConfig: createConfiguration) { createResult, createError in // handle success or failure } } } ``` ## Collecter un moyen de paiement [Côté client] - [CollectPaymentIntentConfiguration (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCollectPaymentIntentConfiguration.html) > La responsabilité du paiement vous incombe lorsque vous utilisez votre lecteur hors ligne. Les données de bande magnétique étant faciles à usurper, Stripe désactive cette option pour les paiements hors ligne. En outre, la présentation des cartes n’est pas prise en charge sur les marchés où l’*authentification forte du client* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase) est requise. La collecte des paiements en mode hors ligne est similaire [à la collecte des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#collect-payment). Utilisez la méthode `didRequestReaderInput` pour afficher les options de présentation de carte valides au client. > Les lecteurs ne prennent pas en charge l’[inspection des informations du moyen de paiement avant autorisation](https://docs.stripe.com/terminal/payments/collect-card-payment.md?terminal-sdk-platform=ios#collect-inspect-payment-method) en mode hors ligne. Bien que vous puissiez toujours utiliser le paramètre `initWithUpdate PaymentIntent` dans `CollectPaymentIntentConfiguration`, le champ `paymentMethod` de la PaymentIntent est absent si le SDK fonctionne hors ligne. #### Swift ```swift import UIKit import StripeTerminal class PaymentViewController: UIViewController { // Action for a "Checkout" button func checkoutAction() { Terminal.shared.collectPaymentMethod(paymentIntent) { collectResult, collectError in if let error = collectError { print("collectPaymentMethod failed: \(error)") } else if let paymentIntent = collectResult { print("collectPaymentMethod succeeded") // ... Confirm the payment } } } } ``` ## Confirmer le paiement [Côté client] La confirmation des paiements en mode hors ligne est similaire à la [confirmation des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#confirm-payment). La principale différence est que votre intégration doit gérer des types d’erreurs spécifiques au mode hors ligne, par exemple lorsque la transaction dépasse la limite maximum de 10 000 USD appliquée par Stripe pour les paiements hors ligne (ou un montant équivalent dans votre devise). Dans certains cas, le SDK peut créer en ligne un `PaymentIntent`, mais le confirmer hors ligne. Dans ce cas, le `PaymentIntent` peut avoir un `stripeId` non nul. S’il a été confirmé hors ligne, `offlineDetails` sera défini et renseigné. Il est possible de configurer le lecteur de simulation afin d’utiliser une carte bancaire de test pour simulation, ce qui vous permet de tester différents flux hors ligne lors de la confirmation. Par exemple, vous pouvez : - Utiliser le numéro de carte bancaire de test Interac de simulation pour tester les erreurs tout en confirmant un `PaymentIntent` hors ligne pour les moyens de paiement non pris en charge - Utiliser un numéro de carte bancaire de test qui [aboutit à un refus de paiement](https://docs.stripe.com/terminal/references/testing.md#test-cards-for-specific-error-cases) pour tester les échecs de transmission d’un `PaymentIntent` enregistré Pour obtenir la liste complète des options disponibles, la page consacrée au [test de Stripe Terminal](https://docs.stripe.com/terminal/references/testing.md). #### Swift ```swift import UIKit import StripeTerminal class PaymentViewController: UIViewController { // Action for a "Checkout" button func checkoutAction() { Terminal.shared.confirmPaymentIntent(paymentIntent) { confirmResult, confirmError in if let error = confirmError { // Handle offline-specific errors in your application (for example, // unsupported payment method). print("confirmPaymentIntent failed: \(error)") } else if let confirmedPaymentIntent= confirmResult {print("confirmPaymentIntent succeeded") if let offlineDetails = paymentIntent.offlineDetails { print("confirmed offline"); } else { print("confirmed online") } } } } } ``` #### Fourniture de reçus Vous pouvez avoir besoin d’informations concernant la carte utilisée pour un paiement en mode hors ligne. Par exemple, vous pouvez avoir besoin de générer un reçu pour les clients qui le demandent au moment de l’achat. Si le PaymentIntent est confirmé hors ligne, récupérez sa propriété [OfflineCardPresentDetails](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPOfflineCardPresentDetails.html) from the `paymentIntent.offlineDetails.offlineCardPresentDetails`. Ce hachage contient une propriété [ReceiptDetails](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPReceiptDetails.html) que vous pouvez utiliser pour générer un reçu ainsi que d’autres informations sur la carte bancaire, notamment sa marque et le nom de son titulaire. Les champs des reçus `account_type` et `authorization_response_code` ne sont pas disponibles sur les PaymentIntents traités en mode hors ligne. Les [reçus par e-mail préconfigurés](https://docs.stripe.com/terminal/features/receipts.md#prebuilt) sont uniquement envoyés lorsque la connexion est rétablie et que le paiement est capturé. ## Attendre l'acheminement des paiements [Côté client] Quand l’accès Internet est rétabli, le SDK commence automatiquement à transférer les paiements hors ligne stockés. Le SDK tente de transmettre les paiements même si l’état de son réseau est hors ligne. Cela signifie que votre fournisseur de tokens de connexion peut recevoir une demande de token de connexion, même lorsque l’appareil est hors ligne. Si vous éteignez votre appareil de POS trop tôt, vos paiements risquent de ne pas être transférés. Vous pouvez interroger `Terminal.offlineStatus.sdk.networkStatus` pour vous assurer que votre POS est en ligne et peut transférer des paiements, et `Terminal.offlineStatus.sdk.offlinePaymentsCount` pour connaître le nombre de paiements que le SDK Terminal doit transférer. ## Capturer le paiement Lorsque vous êtes hors ligne, vous pouvez créer des PaymentIntents avec l’attribut `captureMethod` défini sur `automatic`. Une fois que vous avez confirmé ces PaymentIntents, ils passent à l’état `Succeeded` au lieu de `RequiresCapture`. Stripe capture automatiquement les paiements une fois que vous les avez transmis. Si vous choisissez la capture manuelle, les paiements acheminés et autorisés doivent alors être capturés depuis votre back-end ou votre application. - Afin de capturer les paiements depuis votre back-end, utilisez des [webhooks](https://docs.stripe.com/webhooks.md) pour écouter les PaymentIntents à l’état `requires_capture`. - Pour capturer les paiements depuis votre application, attendez que celle-ci reçoive les appels à `OfflineDelegate.didForwardPayment` pour chaque PaymentIntent à mesure que le SDK les transmet. Un PaymentIntent est prêt à capturer si son état est `RequiresCapture` et si le paramètre `offlineDetails` est vide ou présente une valeur `requiresUpload` de `NO` . #### Swift ```swift Terminal.shared.confirmPaymentIntent(paymentIntent) { confirmResult, confirmError in if let error = confirmError { // Handle offline-specific errors in your application (for example, // unsupported payment method). print("confirmPaymentIntent failed: \(error)") } else if let confirmedPaymentIntent = confirmResult { if intent.status == .requiresCapture {if let offlineDetails = confirmedPaymentIntent.offlineDetails(), offlineDetails.requiresUpload { // Offline payment, wait for `didForwardPaymentIntent` (see snippet below) } else { // Online payment, can be captured now } } // else, handle other intent.status results here } } ``` Capturez un paiement hors ligne après qu’il ait été transmis par le SDK dans le `didForwardPaymentIntent` de votre OfflineDelegate : #### Swift ```swift import StripeTerminal class CustomOfflineDelegate: OfflineDelegate { // ... func terminal(_ terminal: Terminal, didForwardPaymentIntent intent: PaymentIntent, error: Error?) { if let error = error { // Handle the error appropriate for your application return } if intent.status == .requiresCapture { // The intent is ready to be captured. } else { // Handle the intent.status as appropriate. } } // ... } ``` ## Examiner les paiements collectés hors ligne Après autorisation, vous pouvez utiliser l’API [PaymentIntents](https://docs.stripe.com/payments/payment-intents.md) pour examiner les informations hors ligne d’un paiement. Accédez aux [informations relatives au moyen de paiement](https://docs.stripe.com/api/charges/object.md#charge_object-payment_method_details-card_present-offline) sur le dernier objet [Charge](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-latest_charge) d’un `PaymentIntent` pour déterminer s’il a été encaissé hors ligne. # Android > This is a Android for when terminal-card-present-integration is terminal and terminal-sdk-platform is android and reader-type is simulated. View the full page at https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments?terminal-card-present-integration=terminal&terminal-sdk-platform=android&reader-type=simulated. Le SDK Terminal permet à votre application de continuer à encaisser les paiements à l’aide d’un lecteur de simulation sans connexion réseau. > En mode hors ligne, les informations de paiement sont collectées au moment de la vente et l’autorisation n’est tentée qu’après que la connectivité est rétablie et que le paiement est transmis. En tant qu’utilisateur, vous assumez tous les risques de refus et de falsification associés à une transaction hors ligne. Si votre lecteur falsifié ne peut pas transférer les paiements à Stripe, ou si l’émetteur refuse la transaction, il n’y a aucun moyen de récupérer les fonds et il est possible que vous ne receviez pas le paiement du client pour les biens ou services déjà fournis. > > Pour limiter les risques de refus de la part de l’émetteur, nous vous conseillons de : > > - Rétablir la connexion Internet le plus rapidement possible pour enregistrer les paiements sur Stripe. - Bloquer les transactions supérieures à un certain montant. - [Faire échouer tous les paiements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#managing-risk) quand le SDK a stocké un ensemble de transactions dont la somme dépasse un certain montant. ## Encaisser des paiements en mode hors ligne Les paiements hors ligne suivent les mêmes étapes que les paiements en ligne : création, collecte, traitement et capture du paiement. Votre appareil peut passer du mode en ligne au mode hors ligne à n’importe quelle étape du processus. 1. [Activer le mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#enable-offline-mode) 1. [Se connecter à un lecteur en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#connect-while-offline) 1. [Gérer les événements hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#handle-offline-events) 1. [Créer un Payment Intent en mode hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#create-payment-intent) 1. [Collecter un moyen de paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#collect-payment-method) 1. [Confirmer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#confirm-payment) 1. [Attendre l’acheminement des paiements](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#wait-for-forward) 1. (Facultatif) [Capturer le paiement](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#capture-payment) 1. (Facultatif) [Examiner les paiements encaissés hors ligne](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#examine-offline) ## Activer le mode hors ligne Pour utiliser le mode hors ligne, votre application doit utiliser la version `3.2.0` ou une version ultérieure du SDK Terminal Android. Configurez le lecteur de simulation pour activer le mode hors ligne. #### Kotlin ``` val simulatorConfig = SimulatorConfiguration( offlineEnabled = true ); Terminal.getInstance().setSimulatorConfiguration(simulatorConfig); ``` ## Se connecter à un lecteur en mode hors ligne Le SDK stocke localement les informations nécessaires sur `Location` après la connexion en ligne. Lors des connexions hors ligne suivantes, il utilise les informations de configuration stockées à partir de cet emplacement`Location`. Pour encaisser des paiements à l’aide d’un lecteur intelligent en mode hors ligne, vous devez avoir établi une connexion à un lecteur mobile du même type au même emplacement (`Location`) en étant en ligne au cours des 30 derniers jours et avoir mis à jour le logiciel de votre lecteur dans ce laps de temps. Si vous tentez de vous connecter à un lecteur hors ligne sans remplir ces conditions, la demande échoue avec une erreur. | Erreur | Résolution | | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Le SDK n’est pas connecté à Internet** | Assurez-vous d’avoir activé le mode hors ligne sur l’objet `SimulatorConfiguration` pour votre lecteur de simulation. Sinon, connectez-vous en ligne à un lecteur, puis hors ligne à un lecteur du même type. | | **Le lecteur sélectionné nécessite une mise à jour logicielle avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Vous avez défini la valeur `SimulateReaderUpdate` de l’objet `SimulatorConfiguration` du SDK sur `REQUIRED_FOR_OFFLINE`. Utilisez une valeur différente pour autoriser la connexion hors ligne. | | **Le lecteur sélectionné doit être appairé en ligne à cet endroit avant de pouvoir être utilisé hors ligne pour collecter des paiements.** | Vous essayez de vous connecter à un type de lecteur auquel votre PDV ne s’est pas encore connecté en ligne. Vous devez d’abord vous connecter en ligne à ce lecteur ou à tout autre lecteur du même type. Si vous voulez vous connecter hors ligne, vous pouvez également vous connecter à un type de lecteur auquel votre PDV s’est déjà connecté en ligne. | ## Gérer les événements hors ligne [Côté client] - [OfflineListener (Android)](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.callable/-offline-listener/index.html) Pour permettre à votre application de recevoir des mises à jour sur l’état du réseau du SDK et des paiements transmis, implémentez l’interface `OfflineListener` et transmettez-la au SDK Terminal. Vous devez définir `OfflineListener` avant de collecter les paiements en mode hors ligne. #### Kotlin ```kotlin class CustomOfflineListener : OfflineListener { override fun onOfflineStatusChange(offlineStatus: OfflineStatus) { // Check the value of `offlineStatus` and update your UI accordingly. For instance, // you can check the SDK's network status at `offlineStatus.sdk.networkStatus`. // // You can also check the SDK's current offline status using // `Terminal::offlineStatus`. } override fun onPaymentIntentForwarded(paymentIntent: PaymentIntent, e: TerminalException?) { // The PaymentIntent was successfully forwarded, or an error occurred. // Reconcile any local state using the backend-generated `PaymentIntent::id` // and the metadata you supplied when creating the PaymentIntent. // // Note that the `PaymentIntent::id` may still be null if creating the // PaymentIntent in the backend failed. } override fun onForwardingFailure(e: TerminalException) { // A non-specific error occurred while forwarding a PaymentIntent. // Check the error message and your integration implementation to // troubleshoot. } } ``` #### Kotlin ```kotlin Terminal.init( context = applicationContext, logLevel = LogLevel.VERBOSE, tokenProvider = CustomConnectionTokenProvider(), listener = CustomTerminalListener(), offlineListener = CustomOfflineListener(), ) ``` ## Créer un PaymentIntent en mode en ligne [Côté client] - [createPaymentIntent (Android)](https://stripe.dev/stripe-terminal-android/core/com.stripe.stripeterminal/-terminal/create-payment-intent.html) - [CreateConfiguration (Android)](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-create-configuration/index.html) - [OfflineDetails (Android)](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-offline-details/index.html) Afin prendre en charge le fonctionnement hors ligne, utilisez l’attribut `createPaymentIntent` du SDK pour créer des objets PaymentIntent. Cela permet au SDK de créer des PaymentIntents en mode hors ligne et de les transmettre à Stripe une fois que vous avez rétabli la connexion. En mode hors ligne, les objets `PaymentIntent` ont un champ `id` vide. Nous vous recommandons d’ajouter un identifiant personnalisé aux [metadata](https://docs.stripe.com/payments/payment-intents.md#storing-information-in-metadata) pour faciliter le rapprochement des objets `PaymentIntent`créés hors ligne dans votre base de données. Une fois que le `PaymentIntent` a été transmis à Stripe lors de l’[étape 7](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md#wait-for-forward), utilisez votre identifiant personnalisé pour le rapprocher dans le rappel `OfflineListener::onPaymentIntentForwarded`. #### Kotlin ```kotlin private const val TAG = "PaymentActivity" class PaymentActivity : AppCompatActivity() { // Action for a "Checkout" button private fun onCheckout(cart: Cart) { // Build up parameters for creating a `PaymentIntent` val params = PaymentIntentParameters.Builder() .setAmount(cart.total) .setCurrency(cart.currency).setMetadata(mapOf("unique-id" to UUID.randomUUID().toString())) .build() val createPaymentCallback: PaymentIntentCallback = object : PaymentIntentCallback { override fun onSuccess(paymentIntent: PaymentIntent) { Log.d(TAG, "createPaymentIntent succeeded")// If the `PaymentIntent` was created offline, its `id` field will be null. if (paymentIntent.id != null) { Log.d(TAG, "created online") } else { Log.d(TAG, "created offline") } // ... Collect a PaymentMethod } override fun onFailure(e: TerminalException) { Log.e(TAG, "createPaymentIntent failed", e) // Handle errors in your application. } } Terminal.getInstance().createPaymentIntent(params, createPaymentCallback) } } ``` `Terminal.createPaymentIntent` accepte un paramètre `CreateConfiguration`. Par défaut, si vous êtes en mode hors ligne, le SDK Terminal enregistre tous les paiements hors ligne, puis les transmet au backend de Stripe lorsque la connexion est rétablie. Pour personnaliser ce comportement, vous pouvez transmettre un objet `CreateConfiguration` avec un attribut `offlineBehavior` défini sur `REQUIRE_ONLINE`, `PREFER_ONLINE` ou `FORCE_OFFLINE`. #### Gestion du risque La définition de `offlineBehavior` sur `REQUIRE_ONLINE` entraîne un échec de la transaction en cours si vous fonctionnez en mode hors ligne. Par exemple, vous pouvez refuser les transactions supérieures à un certain montant ou toutes les transactions hors ligne si le SDK a stocké un ensemble de transactions dont la somme dépasse un certain montant. Le SDK expose deux propriétés pour vous aider à gérer les risques : 1. `Terminal.offlineStatus.sdk.offlinePaymentsCount` 1. `Terminal.offlineStatus.sdk.offlinePaymentAmountsByCurrency` #### Gérer la latence en mode hors ligne Based on your network connectivity, the Terminal SDK automatically determines whether to collect payments online or offline. However, you might want to operate offline despite having an active network connection (for example, if you need to collect transactions quickly and your network connection is slow). You can pass a `CreateConfiguration` object with `offlineBehavior` set to `FORCE_OFFLINE` to collect the payment offline regardless of connectivity. Les paiements collectés hors ligne alors que le SDK Terminal dispose d’une connexion réseau active sont transmis en arrière-plan. #### Kotlin ```kotlin private const val TAG = "PaymentActivity" class PaymentActivity : AppCompatActivity() { // Action for a "Checkout" button private fun onCheckout(cart: Cart) { // ...build up parameters and callback for creating a `PaymentIntent` // Your app might want to prevent offline payments for too large an amount. // Here, we require a network connection if the payment if the amount is over 1000 usd. // Otherwise, we allow collecting offline if the network connection is unavailable.val offlineBehavior = if (cart.total > 1000000) { OfflineBehavior.REQUIRE_ONLINE } else { OfflineBehavior.PREFER_ONLINE } val createConfig = CreateConfiguration(offlineBehavior) Terminal.getInstance().createPaymentIntent(params, createPaymentCallback, createConfig) } } ``` ## Collecter un moyen de paiement [Côté client] - [CollectPaymentIntentConfiguration (Android)](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-collect-payment-intent-configuration/index.html) > La responsabilité du paiement vous incombe lorsque vous utilisez votre lecteur hors ligne. Les données de bande magnétique étant faciles à usurper, Stripe désactive cette option pour les paiements hors ligne. En outre, la présentation des cartes n’est pas prise en charge sur les marchés où l’*authentification forte du client* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase) est requise. La collecte des paiements en mode hors ligne est similaire [à la collecte des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#collect-payment). Utilisez la méthode `onRequestReaderInput` pour afficher les options de présentation de carte valides au client. > Les lecteurs ne prennent pas en charge l’[inspection des informations du moyen de paiement avant autorisation](https://docs.stripe.com/terminal/payments/collect-card-payment.md?terminal-sdk-platform=android#collect-inspect-payment-method) en mode hors ligne. Bien que vous puissiez toujours définir le paramètre `updatePaymentIntent` dans `CollectPaymentIntentConfiguration`, le champ `paymentMethod` de la PaymentIntent est absent si le SDK fonctionne hors ligne. #### Kotlin ```kotlin private const val TAG = "PaymentActivity" class PaymentActivity : AppCompatActivity() { // Action for a "Checkout" button private fun onCheckout(cart: Cart) { val collectPaymentCallback: PaymentIntentCallback = object : PaymentIntentCallback { override fun onSuccess(paymentIntent: PaymentIntent) { Log.d(TAG, "collectPaymentMethod succeeded") // ... Confirm the payment } override fun onFailure(e: TerminalException) { Log.d(TAG, "collectPaymentMethod failed:", e) } } val collectConfig = CollectPaymentIntentConfiguration.Builder().build() Terminal.getInstance().collectPaymentMethod(paymentIntent, collectPaymentCallback, collectConfig) } } ``` ## Confirmer le paiement [Côté client] La confirmation des paiements en mode hors ligne est similaire à la [confirmation des paiements en ligne](https://docs.stripe.com/terminal/payments/collect-card-payment.md#confirm-payment). La principale différence est que votre intégration doit gérer des types d’erreurs spécifiques au mode hors ligne, par exemple lorsque la transaction dépasse la limite maximum de 10 000 USD appliquée par Stripe pour les paiements hors ligne (ou un montant équivalent dans votre devise). Dans certains cas, le SDK peut créer en ligne un `PaymentIntent`, mais le confirmer hors ligne. Dans ce cas, le `PaymentIntent` peut avoir un `id` non nul. S’il a été confirmé hors ligne, `offlineDetails` sera défini et renseigné. Il est possible de configurer le lecteur de simulation afin d’utiliser une carte bancaire de test pour simulation, ce qui vous permet de tester différents flux hors ligne lors de la confirmation. Par exemple, vous pouvez : - Utiliser le numéro de carte bancaire de test Interac de simulation pour tester les erreurs tout en confirmant un `PaymentIntent` hors ligne pour les moyens de paiement non pris en charge - Utiliser un numéro de carte bancaire de test qui [aboutit à un refus de paiement](https://docs.stripe.com/terminal/references/testing.md#test-cards-for-specific-error-cases) pour tester les échecs de transmission d’un `PaymentIntent` enregistré Pour obtenir la liste complète des options disponibles, la page consacrée au [test de Stripe Terminal](https://docs.stripe.com/terminal/references/testing.md). #### Kotlin ```kotlin private const val TAG = "PaymentActivity" class PaymentActivity : AppCompatActivity() { // Action for a "Checkout" button private fun onCheckout(cart: Cart) { val confirmPaymentIntentCallback: PaymentIntentCallback = object : PaymentIntentCallback { override fun onSuccess(paymentIntent: PaymentIntent) { Log.d(TAG, "confirmPaymentIntent succeeded")// If the `PaymentIntent` was confirmed offline, `paymentIntent.offlineDetails` will be defined if (paymentIntent.offlineDetails != null) { Log.d(TAG, "confirmed offline") } else { Log.d(TAG, "confirmed online") } } override fun onFailure(e: TerminalException) { // Handle offline-specific errors in your application (for example, // unsupported payment method). Log.e(TAG, "confirmPaymentIntent failed:", e) } } Terminal.getInstance().confirmPaymentIntent(paymentIntent, confirmPaymentIntentCallback) } } ``` #### Fourniture de reçus Vous pouvez avoir besoin d’informations concernant la carte utilisée pour un paiement en mode hors ligne. Par exemple, vous pouvez avoir besoin de générer un reçu pour les clients qui le demandent au moment de l’achat. Si le PaymentIntent est confirmé hors ligne, récupérez sa propriété [OfflineCardPresentDetails](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-offline-card-present-details/index.html) from the `paymentIntent.offlineDetails.offlineCardPresentDetails`. Ce hachage contient une propriété [ReceiptDetails](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-receipt-details/index.html) que vous pouvez utiliser pour générer un reçu ainsi que d’autres informations sur la carte bancaire, notamment sa marque et le nom de son titulaire. Les champs des reçus `account_type` et `authorization_response_code` ne sont pas disponibles sur les PaymentIntents traités en mode hors ligne. Les [reçus par e-mail préconfigurés](https://docs.stripe.com/terminal/features/receipts.md#prebuilt) sont uniquement envoyés lorsque la connexion est rétablie et que le paiement est capturé. ## Attendre l'acheminement des paiements [Côté client] Quand l’accès Internet est rétabli, le SDK commence automatiquement à transférer les paiements hors ligne stockés. Le SDK tente de transmettre les paiements même si l’état de son réseau est hors ligne. Cela signifie que votre fournisseur de tokens de connexion peut recevoir une demande de token de connexion, même lorsque l’appareil est hors ligne. Si vous éteignez votre appareil de POS trop tôt, vos paiements risquent de ne pas être transférés. Vous pouvez interroger `Terminal.offlineStatus.sdk.networkStatus` pour vous assurer que votre POS est en ligne et peut transférer des paiements, et `Terminal.offlineStatus.sdk.offlinePaymentsCount` pour connaître le nombre de paiements que le SDK Terminal doit transférer. ## Capturer le paiement Lorsque vous êtes hors ligne, vous pouvez créer des PaymentIntents avec l’attribut `captureMethod` défini sur `automatic`. Une fois que vous avez confirmé ces PaymentIntents, ils passent à l’état `SUCCEEDED` au lieu de `REQUIRES_CAPTURE` . Stripe capture automatiquement les paiements une fois que vous les avez transmis. Si vous choisissez la capture manuelle, les paiements acheminés et autorisés doivent alors être capturés depuis votre back-end ou votre application. - Afin de capturer les paiements depuis votre back-end, utilisez des [webhooks](https://docs.stripe.com/webhooks.md) pour écouter les PaymentIntents à l’état `requires_capture`. - Pour capturer les paiements depuis votre application, attendez que celle-ci reçoive les appels à `OfflineListener::onPaymentIntentForwarded` pour chaque PaymentIntent à mesure que le SDK les transmet. Un PaymentIntent est prêt à capturer si son état est `REQUIRES_CAPTURE` et si le paramètre `offlineDetails` est vide ou présente une valeur `requiresUpload` de `false` . #### Kotlin ```kotlin private const val TAG = "PaymentActivity" class PaymentActivity : AppCompatActivity() { // Action for a "Checkout" button private fun onCheckout(cart: Cart) { val callback: PaymentIntentCallback = object : PaymentIntentCallback { override fun onSuccess(paymentIntent: PaymentIntent) { Log.d(TAG, "confirmPaymentIntent succeeded") if (paymentIntent.status == PaymentIntentStatus.REQUIRES_CAPTURE) {val offlineDetails = paymentIntent.offlineDetails if (offlineDetails?.requiresUpload == true) { // Offline payment, wait for `onPaymentIntentForwarded` (see snippet below) } else { // Online payment, can be captured now } } else { // Handle other status results here } } override fun onFailure(e: TerminalException) { // Handle offline-specific errors in your application (for example, // unsupported payment method). Log.e(TAG, "confirmPaymentIntent failed:", e) } } Terminal.getInstance().confirmPaymentIntent(paymentIntent, callback) } } ``` Capturez un paiement hors ligne après qu’il ait été transmis par le SDK dans votre `OfflineListener::onPaymentIntentForwarded` : #### Kotlin ```kotlin class CustomOfflineListener : OfflineListener { // ... override fun onPaymentIntentForwarded(paymentIntent: PaymentIntent, e: TerminalException?) { if (e != null) { // Handle the error appropriate for your application } else if (paymentIntent.status == PaymentIntentStatus.REQUIRES_CAPTURE) { // The paymentIntent is ready to be captured } else { // Handle other status results here } } // ... } ``` ## Examiner les paiements collectés hors ligne Après autorisation, vous pouvez utiliser l’API [PaymentIntents](https://docs.stripe.com/payments/payment-intents.md) pour examiner les informations hors ligne d’un paiement. Accédez aux [informations relatives au moyen de paiement](https://docs.stripe.com/api/charges/object.md#charge_object-payment_method_details-card_present-offline) sur le dernier objet [Charge](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-latest_charge) d’un `PaymentIntent` pour déterminer s’il a été encaissé hors ligne.