# Accepter les paiements dans l’application Créez une intégration de paiement personnalisée dans votre application iOS, Android ou React Native à l'aide du composant Payment Element. Le composant Payment Element est un composant personnalisable qui affiche une liste de moyens de paiement que vous pouvez ajouter à n’importe quel écran de votre application. Lorsque les clients interagissent avec les moyens de paiement de la liste, le composant ouvre des feuilles de bas de page entrepreneur individuel pour collecter les informations de paiement. > #### Prise en charge de l’API Accounts v2 > > La Payment Sheet ne prend pas en charge les *comptes configurés par le client* (Account configurations represent role-based functionality that you can enable for accounts, such as merchant, customer, or recipient). Elle prend uniquement en charge les objets `Customer`. # Accepter un paiement > This is a Accepter un paiement for when platform is ios and type is payment. View the full page at https://docs.stripe.com/payments/mobile/accept-payment-embedded?platform=ios&type=payment. Un flux PaymentIntent vous permet de créer un débiter dans votre application. Dans cette intégration, vous affichez le Payment Element, créez un *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods) et confirmez un débiter dans votre application. ## Configurer Stripe [Côté serveur] [Côté client] ### Côté serveur Cette intégration exige que votre serveur dispose de endpoints qui communiquent avec l’API Stripe. Utilisez nos bibliothèques officielles pour accéder à l’API Stripe depuis votre serveur : #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ### Côté client Le [SDK iOS de Stripe](https://github.com/stripe/stripe-ios) est disponible en open source et [fait l’objet d’une documentation complète](https://stripe.dev/stripe-ios/index.html). Il est également compatible avec les applications prenant en charge iOS 13 et les versions ultérieures. #### Swift Package Manager Pour installer le SDK, veuillez suivre les étapes ci-dessous : 1. Dans Xcode, sélectionnez **File** > **Add Package Dependencies…** puis saisissez `https://github.com/stripe/stripe-ios-spm` en tant qu’URL du référentiel. 1. Sélectionnez le dernier numéro de version, visible sur notre [page des versions](https://github.com/stripe/stripe-ios/releases). 1. Ajoutez le produit **StripePaymentSheet** à la [cible de votre application](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app). #### CocoaPods 1. Si vous ne l’avez pas encore fait, installez la version la plus récente de [CocoaPods](https://guides.cocoapods.org/using/getting-started.html). 1. Si vous n’avez pas de fichier [Podfile](https://guides.cocoapods.org/syntax/podfile.html), exécutez la commande suivante pour en créer un : ```bash pod init ``` 1. Ajoutez cette ligne à votre `Podfile` : ```podfile pod 'StripePaymentSheet' ``` 1. Exécutez la commande suivante : ```bash pod install ``` 1. À partir de maintenant, n’oubliez pas d’utiliser le fichier .xcworkspace au lieu du fichier .xcodeproj pour ouvrir votre projet dans Xcode. 1. Pour mettre à jour ultérieurement le SDK vers la version la plus récente, il vous suffit d’exécuter : ```bash pod update StripePaymentSheet ``` #### Carthage 1. Si vous ne l’avez pas encore fait, installez la version la plus récente de [Carthage](https://github.com/Carthage/Carthage#installing-carthage). 1. Ajoutez cette ligne à votre `Cartfile` : ```cartfile github "stripe/stripe-ios" ``` 1. Suivez les [instructions d’installation de Carthage](https://github.com/Carthage/Carthage#if-youre-building-for-ios-tvos-or-watchos). Veillez à intégrer tous les cadres requis listés [ici](https://github.com/stripe/stripe-ios/tree/master/StripePaymentSheet/README.md#manual-linking). 1. Pour mettre à jour ultérieurement le SDK vers la version la plus récente, exécutez la commande suivante : ```bash carthage update stripe-ios --platform ios ``` #### Cadre manuel 1. Accédez à notre [page des versions GitHub](https://github.com/stripe/stripe-ios/releases/latest), puis téléchargez et décompressez **Stripe.xcframework.zip**. 1. Faites glisser **StripePaymentSheet.xcframework** vers la section **Embedded Binaries (Fichiers binaires incorporés)** des paramètres **General (Général)** de votre projet Xcode. Veillez à sélectionner **Copy items if needed (Copier les éléments si nécessaire)**. 1. Répétez l’étape 2 pour tous les cadres requis listés [ici](https://github.com/stripe/stripe-ios/tree/master/StripePaymentSheet/README.md#manual-linking). 1. À l’avenir, pour mettre à jour vers la version la plus récente de notre SDK, répétez les étapes 1 à 3. > Pour obtenir de plus amples informations sur la version la plus récente du SDK et ses versions antérieures, consultez la page des [versions](https://github.com/stripe/stripe-ios/releases) sur GitHub. Pour recevoir une notification lors de la publication d’une nouvelle version, [surveillez les versions](https://help.github.com/en/articles/watching-and-unwatching-releases-for-a-repository#watching-releases-for-a-repository) à partir du référentiel. Vous devez également définir votre [clé publique](https://dashboard.stripe.com/apikeys) pour que le SDK puisse effectuer des appels à l’API Stripe. Pour commencer, vous pouvez coder en dur la clé publique côté client pendant l’intégration, mais la récupérer sur votre serveur en mode production. ```swift // Set your publishable key: remember to change this to your live publishable key in production // See your keys here: https://dashboard.stripe.com/apikeys STPAPIClient.shared.publishableKey = "<>" ``` ## Activer des moyens de paiement Affichez vos [paramètres des moyens de paiement](https://dashboard.stripe.com/settings/payment_methods) et activez les moyens de paiement que vous souhaitez prendre en charge. Vous devez activer au moins un moyen de paiement pour créer un *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods). Par défaut, Stripe active les cartes bancaires et les autres moyens de paiement courants qui peuvent vous permettre d’atteindre davantage de clients. Nous vous recommandons toutefois d’activer d’autres moyens de paiement pertinents pour votre entreprise et vos clients. Consultez la page [Prise en charge des moyens de paiement](https://docs.stripe.com/payments/payment-methods/payment-method-support.md) pour en savoir plus sur la prise en charge des produits et des moyens de paiement, et notre [page des tarifs](https://stripe.com/pricing/local-payment-methods) pour prendre connaissance des frais que nous appliquons. ## Collecter les informations de paiement [Côté client] Le composant Embedded Mobile Payment Element est conçu pour être placé sur la page de paiement de votre application mobile native. L’élément affiche une liste de moyens de paiement que vous pouvez personnaliser pour l’adapter à l’apparence de votre application. Lorsque le client appuie sur la ligne **Carte bancaire**, un formulaire s’ouvre dans lequel il peut saisir les informations de son moyen de paiement. Par défaut, le bouton du formulaire indique **Continuer** et déclenche la fermeture du formulaire, ce qui permet à votre client de finaliser le paiement dans votre système de paiement. ![Payment Element](https://b.stripecdn.com/docs-statics-srv/assets/ios-embedded.b5867c116d537ffcb920dd80ebdfc741.png) Vous pouvez également configurer le bouton pour qu’il termine immédiatement le processus de paiement au lieu de continuer. Pour ce faire, effectuez [cette étape](https://docs.stripe.com/payments/mobile/accept-payment-embedded.md#embedded-let-customer-pay-immediately) après avoir suivi le guide. #### UIKit ### Initialiser le Payment Element Appelez `create` pour instancier EmbeddedPaymentElement avec un `EmbeddedPaymentElement.Configuration` et un [PaymentSheet.IntentConfiguration](https://github.com/stripe/stripe-ios/blob/master/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetIntentConfiguration.swift). L’objet Configuration contient des options de configuration générales pour EmbeddedPaymentElement qui ne changent pas entre les paiements, comme `returnURL`. L’objet `IntentConfiguration` contient des détails sur le paiement spécifique, comme le montant et la devise, ainsi qu’un rappel `confirmationTokenConfirmHandler`. Pour l’instant, laissez son implémentation vide. Une fois l’initialisation réussie, définissez les paramètres `presentingViewController` et `delegate`. ```swift import StripePaymentSheet class MyCheckoutVC: UIViewController { func createEmbeddedPaymentElement() async throws -> EmbeddedPaymentElement { let intentConfig = PaymentSheet.IntentConfiguration( mode: .payment(amount: 1099, currency: "USD") ) { [weak self] confirmationToken in return await self?.handleConfirmationToken(confirmationToken) } var configuration = EmbeddedPaymentElement.Configuration() configuration.returnURL = "your-app://stripe-redirect" // Use the return url you set up in the previous step let embeddedPaymentElement = try await EmbeddedPaymentElement.create(intentConfiguration: intentConfig, configuration: configuration) embeddedPaymentElement.presentingViewController = self embeddedPaymentElement.delegate = self return embeddedPaymentElement } func handleConfirmationToken(_ confirmationToken: STPConfirmationToken) async throws -> String { // You'll implement this in the "Confirm the payment" section below } } ``` ### Ajouter la vue Payment Element Une fois que le EmbeddedPaymentElement est initialisé avec succès, intégrez sa vue dans votre interface de paiement. > La vue doit être placée dans une vue défilable, comme UIScrollView, car elle n’a pas de taille fixe et peut changer de hauteur après son rendu initial. ```swift class MyCheckoutVC: UIViewController { // ... private(set) var embeddedPaymentElement: EmbeddedPaymentElement? private lazy var checkoutButton: UIButton = { let checkoutButton = UIButton(type: .system) checkoutButton.backgroundColor = .systemBlue checkoutButton.layer.cornerRadius = 5.0 checkoutButton.clipsToBounds = true checkoutButton.setTitle("Checkout", for: .normal) checkoutButton.setTitleColor(.white, for: .normal) checkoutButton.translatesAutoresizingMaskIntoConstraints = false checkoutButton.isEnabled = embeddedPaymentElement?.paymentOption != nil checkoutButton.addTarget(self, action: #selector(didTapConfirmButton), for: .touchUpInside) return checkoutButton }() // ... @objc func didTapConfirmButton() { // You'll implement this in the "Confirm the payment" section below } override func viewDidLoad() { super.viewDidLoad() Task { @MainActor in do { // Create a UIScrollView let scrollView = UIScrollView() scrollView.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(scrollView) // Create the Payment Element let embeddedPaymentElement = try await createEmbeddedPaymentElement() embeddedPaymentElement.delegate = self embeddedPaymentElement.presentingViewController = self self.embeddedPaymentElement = embeddedPaymentElement // Add its view to the scroll view scrollView.addSubview(embeddedPaymentElement.view) // Add your own checkout button to the scroll view scrollView.addSubview(checkoutButton) // Set up layout constraints embeddedPaymentElement.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), embeddedPaymentElement.view.topAnchor.constraint(equalTo: scrollView.topAnchor), embeddedPaymentElement.view.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor), embeddedPaymentElement.view.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor), checkoutButton.topAnchor.constraint(equalTo: embeddedPaymentElement.view.bottomAnchor, constant: 4.0), checkoutButton.leadingAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.leadingAnchor, constant: 4.0), checkoutButton.trailingAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.trailingAnchor, constant: -4.0), ]) } catch { // Handle view not being added to view } } } } ``` À ce stade, vous pouvez exécuter votre application et voir le composant Embedded Mobile Payment Element. ### Gérer les changements de hauteur La vue de l’élément EmbeddedPaymentElement peut augmenter ou diminuer en taille, ce qui peut avoir un impact sur la disposition de la vue. Gérez les changements de hauteur en implémentant la méthode déléguée `embeddedPaymentElementDidUpdateHeight`. La vue d’EmbeddedPaymentElement appelle cette méthode à l’intérieur d’un bloc d’animation qui met à jour sa hauteur. Votre implémentation doit appeler `setNeedsLayout()` et `layoutIfNeeded()` sur la vue de défilement qui contient la vue de l’EmbeddedPaymentElement pour permettre une animation fluide du changement de hauteur. ```swift extension MyCheckoutVC: EmbeddedPaymentElementDelegate { func embeddedPaymentElementDidUpdateHeight(embeddedPaymentElement: StripePaymentSheet.EmbeddedPaymentElement) { // Handle layout appropriately self.view.setNeedsLayout() self.view.layoutIfNeeded() } } ``` Nous vous recommandons de tester que votre vue réagit correctement aux changements de hauteur. Pour ce faire, appelez `testHeightChange()` sur EmbeddedPaymentElement afin de simuler l’affichage et le masquage d’un mandat dans le composant. Assurez-vous qu’après l’appel de `testHeightChange()`, votre vue de défilement s’ajuste correctement. ```swift class MyCheckoutVC: UIViewController { override func viewDidLoad() { // This is only for testing purposes: #if DEBUG Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { [weak self] _ in Task { @MainActor in self?.embeddedPaymentElement?.testHeightChange() } } #endif } } ``` ### (Facultatif) Afficher l’option de paiement sélectionnée Si vous avez besoin d’accéder aux détails de l’option de paiement sélectionnée par le client, comme une étiquette (par exemple, « ····4242 »), une image (par exemple, un logo VISA) ou des détails de facturation à afficher dans votre interface utilisateur, utilisez la propriété `paymentOption` de EmbeddedPaymentElement. Pour recevoir une notification à chaque modification de `paymentOption`, implémentez la méthode déléguée `embeddedPaymentElementDidUpdatePaymentOption`. ```swift extension MyCheckoutVC: EmbeddedPaymentElementDelegate { func embeddedPaymentElementDidUpdatePaymentOption(embeddedPaymentElement: EmbeddedPaymentElement) { print("The payment option changed: \(embeddedPaymentElement.paymentOption)") checkoutButton.isEnabled = embeddedPaymentElement.paymentOption != nil } } ``` ### (Facultatif) Mettre à jour les informations de paiement Lorsque le client effectue des actions qui modifient les informations de paiement (par exemple avec l’application d’un code de réduction), mettez à jour l’instance `EmbeddedPaymentElement` de manière à refléter les nouvelles valeurs en appelant la méthode `update`. Certains moyens de paiement, comme Apple Pay et Google Pay, affichent le montant dans l’interface utilisateur, alors assurez-vous qu’il est toujours exact et à jour. Une fois l’appel de modification terminé, mettez à jour votre interface utilisateur. L’appel de modification peut mettre à jour l’option de paiement sélectionnée par le client. ```swift extension MyCheckoutVC { func update() { Task { @MainActor in var updatedIntentConfig = oldIntentConfig // Update the amount to reflect the price after applying the discount code updatedIntentConfig.mode = PaymentSheet.IntentConfiguration.Mode.payment(amount: 999, currency: "USD") let result = await embeddedPaymentElement?.update(intentConfiguration: updatedIntentConfig) switch result { case .canceled, nil: // Do nothing; this happens when a subsequent `update` call cancels this one break case .failed(let error): // Display error to user in an alert, let users retry case .succeeded: // Update your UI in case the payment option changed } } } } ``` ### Confirmer le paiement Lorsque le client appuie sur le bouton de paiement, appelez `embeddedPaymentElement.confirm()` pour mener à bien le paiement. Veillez à désactiver l’interaction avec l’utilisateur lors de la confirmation. ```swift extension MyCheckoutVC { @objc func didTapConfirmButton() { Task { @MainActor in guard let embeddedPaymentElement else { return } self.view.isUserInteractionEnabled = false // Disable user interaction, show a spinner, and so on before calling confirm. let result = await embeddedPaymentElement.confirm() switch result { case .completed: // Payment completed - show a confirmation screen. case .failed(let error): self.view.isUserInteractionEnabled = true // Encountered an unrecoverable error. You can display the error to the user, log it, and so on. case .canceled: self.view.isUserInteractionEnabled = true // Customer canceled - you should probably do nothing. break } } } } ``` Ensuite, implémentez le rappel `confirmationTokenConfirmHandler` que vous avez passé précédemment à `PaymentSheet.IntentConfiguration` pour envoyer une requête à votre serveur. Votre serveur crée un PaymentIntent et renvoie sa clé secrète du client. Pour plus d’informations sur ce processus, consultez l’étape [Créer un PaymentIntent](https://docs.stripe.com/payments/mobile/accept-payment-embedded.md#submit-payment). Lorsque la requête est renvoyée, renvoyez la clé secrète du client contenue dans la réponse du serveur, ou générez une erreur. Le EmbeddedPaymentElement confirme le PaymentIntent en utilisant la clé secrète du client ou affiche le message d’erreur localisé dans son interface utilisateur (soit [errorDescription](https://developer.apple.com/documentation/foundation/localizederror/2946895-errordescription), soit [localizedDescription](https://developer.apple.com/documentation/foundation/nserror/1414418-localizeddescription)). Une fois la confirmation terminée, le EmbeddedPaymentElement n’est plus utilisable. Dirigez plutôt l’utilisateur vers un écran de reçu ou un écran similaire. ```swift extension MyCheckoutVC { func handleConfirmationToken(_ confirmationToken: STPConfirmationToken) async throws -> String { // Make a request to your own server. Pass `confirmationToken.stripeId` if using server-side confirmation, and return the client secret or throw an error. let myServerClientSecret = try await fetchIntentClientSecret(...) } } ``` #### SwiftUI ### Initialiser le Payment Element Appelez `load` pour charger l’EmbeddedPaymentElementViewModel avec un `EmbeddedPaymentElement.Configuration` et un [PaymentSheet.IntentConfiguration](https://github.com/stripe/stripe-ios/blob/master/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetIntentConfiguration.swift). L’objet Configuration contient des options de configuration générales pour EmbeddedPaymentElement qui ne changent pas entre les paiements, comme `returnURL`. L’objet `IntentConfiguration` contient des détails sur le paiement spécifique, comme le montant et la devise, ainsi qu’un rappel `confirmationTokenConfirmHandler`. Pour l’instant, laissez son implémentation vide. ```swift import SwiftUI import StripePaymentSheet struct MyEmbeddedCheckoutView: View { // Store an `EmbeddedPaymentElementViewModel` as a `@StateObject` @StateObject var embeddedViewModel = EmbeddedPaymentElementViewModel() var body: some View { ScrollView { // Empty scroll view for now } .task { do { if !embeddedViewModel.isLoaded { // Load the view model with your configuration try await loadEmbeddedViewModel() } } catch { // On load failure, implement retry logic (automatic retry or user-triggered through UI). } } } private func loadEmbeddedViewModel() async throws { let intentConfiguration = PaymentSheet.IntentConfiguration( mode: .payment(amount: 1099, currency: "USD") ) { confirmationToken in try await self.handleConfirmationToken(confirmationToken) } var configuration = EmbeddedPaymentElement.Configuration() configuration.returnURL = "your-app://stripe-redirect" // Use the return url you set up in the previous step try await embeddedViewModel.load(intentConfiguration: intentConfiguration, configuration: configuration) } func handleConfirmationToken(_ confirmationToken: STPConfirmationToken) async throws -> String { // You'll implement this in the "Confirm the payment" section below } } ``` ### Ajouter la vue Payment Element Une fois que EmbeddedPaymentElementViewModel est chargé avec succès, ajoutez EmbeddedPaymentElementView dans votre interface de paiement. > La vue doit être placée dans une vue défilable, comme ScrollView, car elle n’a pas de taille fixe et peut changer de hauteur après son rendu initial. ```swift struct MyEmbeddedCheckoutView: View { var body: some View { ScrollView { // isLoaded becomes true only after a successful call to `embeddedViewModel.load()` if embeddedViewModel.isLoaded { EmbeddedPaymentElementView(viewModel: embeddedViewModel) } } } } ``` À ce stade, vous pouvez exécuter votre application et voir le composant Embedded Mobile Payment Element. ### Gérer les changements de hauteur La EmbeddedPaymentElementView peut augmenter ou diminuer en taille, ce qui peut affecter la disposition de la vue. La EmbeddedPaymentElementView gère automatiquement ces changements lorsqu’elle se trouve à l’intérieur d’une ScrollView. Nous vous recommandons de tester que votre vue réagit correctement aux changements de hauteur. Pour ce faire, appelez `testHeightChange()` sur EmbeddedPaymentElementViewModel afin de simuler l’affichage et la disparition d’un mandat dans l’élément. Assurez-vous qu’après l’appel de `testHeightChange()`, votre ScrollView s’ajuste de manière fluide. ```swift struct MyEmbeddedCheckoutView: View { var body: some View { ScrollView { if embeddedViewModel.isLoaded { EmbeddedPaymentElementView(viewModel: embeddedViewModel) // For testing only #if DEBUG Button("Test height change") { embeddedViewModel.testHeightChange() } #endif } } } } ``` ### (Facultatif) Afficher l’option de paiement sélectionnée Si vous avez besoin d’accéder aux détails de l’option de paiement sélectionnée par le client, comme un libellé (par exemple, « ----4242 »), une image (par exemple, un logo VISA) ou des détails de facturation à afficher dans votre interface utilisateur, utilisez la propriété `paymentOption` du modèle EmbeddedPaymentElementViewModel. Lorsque le client sélectionne un moyen de paiement qui ouvre un formulaire, l’option de paiement est mise à jour après qu’il a cliqué sur **Continuer** dans le formulaire. ```swift struct MyEmbeddedCheckoutView: View { var body: some View { ScrollView { if embeddedViewModel.isLoaded { // ... // A real integration probably wouldn't show the selected payment option on the same screen as the embedded payment element. We display it as an example. if let paymentOption = embeddedViewModel.paymentOption { HStack { Image(uiImage: paymentOption.image) .resizable() .aspectRatio(contentMode: .fit) .frame(height: 30) Text(paymentOption.label) Spacer() } .padding() } } } } } ``` ### (Facultatif) Mettre à jour les informations de paiement Lorsque le client effectue des actions qui modifient les informations de paiement (par exemple, l’application d’un code de réduction), mettez à jour l’instance `EmbeddedPaymentElementViewModel` pour refléter les nouvelles valeurs en appelant la méthode `update`. Certains moyens de paiement, comme Apple Pay et Google Pay, affichent le montant dans l’interface utilisateur : assurez-vous qu’il est toujours exact et à jour. Une fois la mise à jour terminée, il est possible qu’elle ait modifié l’option de paiement sélectionnée par le client. ```swift extension MyEmbeddedCheckoutView { func update() { Task { @MainActor in var updatedIntentConfig = oldIntentConfig updatedIntentConfig.mode = PaymentSheet.IntentConfiguration.Mode.payment(amount: 999, currency: "USD") let result = await embeddedViewModel.update(intentConfiguration: updatedIntentConfig) switch result { case .canceled: // Do nothing; this happens when a subsequent `update` call cancels this one break case .failed(let error): // Display error to user in an alert, let users retry case .succeeded: // Update your UI in case the payment option changed } } } } ``` ### Confirmer le paiement Lorsque le client appuie sur le bouton de paiement, appelez `embeddedViewModel.confirm()` pour mener à bien le paiement. Veillez à désactiver l’interaction avec l’utilisateur lors de la confirmation. ```swift extension MyEmbeddedCheckoutView { func didTapConfirmButton() { Task { @MainActor in // Be sure to disable user interaction during confirm (not shown in this example) let result = await embeddedViewModel.confirm() switch result { case .completed: // Payment completed - show a confirmation screen. case .failed(let error): // Encountered an unrecoverable error. Re-enable user interaction, display the error to the user, log it, and so on. case .canceled: // Customer canceled - re-enable user interaction and let them try again. break } } } } ``` Ensuite, implémentez le rappel `confirmationTokenConfirmHandler` que vous avez passé précédemment à `PaymentSheet.IntentConfiguration` pour envoyer une requête à votre serveur. Votre serveur crée un PaymentIntent et renvoie sa clé secrète du client. Pour plus d’informations sur ce processus, consultez l’étape [Créer un PaymentIntent](https://docs.stripe.com/payments/mobile/accept-payment-embedded.md#submit-payment). Renvoyez la clé secrète du client de la réponse de votre serveur ou générez une erreur. Le EmbeddedPaymentElement confirme le PaymentIntent en utilisant la clé secrète du client ou affiche le message d’erreur localisé dans son interface utilisateur (soit [errorDescription](https://developer.apple.com/documentation/foundation/localizederror/2946895-errordescription), soit [localizedDescription](https://developer.apple.com/documentation/foundation/nserror/1414418-localizeddescription)). Une fois la confirmation terminée, le EmbeddedPaymentElement n’est plus utilisable. Dirigez plutôt l’utilisateur vers un écran de reçu ou un écran similaire. ```swift extension MyEmbeddedCheckoutView { func handleConfirmationToken(_ confirmationToken: STPConfirmationToken) async throws -> String { // Make a request to your own server. Pass confirmationToken.stripeId if using server-side confirmation. // Return the client secret or throw an error return try await MyAPIClient.shared.createIntent(confirmationTokenId: confirmationToken.stripeId) } } ``` ## Optional: Décocher l’option de paiement sélectionnée Si vous avez des options de paiement externes à l’EmbeddedPaymentElement, vous devrez peut-être décocher l’option de paiement sélectionnée. Pour ce faire, utilisez l’API `clearPaymentOption`. #### UIKit ```swift extension MyCheckoutVC: UIViewController { func deselectPaymentMethod() { embeddedPaymentElement?.clearPaymentOption() } } ``` #### SwiftUI ```swift @available(iOS 15.0, *) extension MyEmbeddedCheckoutView { func deselectPaymentMethod() { embeddedViewModel.clearPaymentOption() } } ``` ## Optional: Afficher vous-même le mandat Afin de garantir la conformité aux réglementations, l’Embedded Mobile Payment Element affiche les mandats et clauses de non-responsabilité par défaut. Ce texte doit être situé à proximité de votre bouton d’achat. Si nécessaire, désactivez leur affichage dans la vue et affichez-les vous-même. > Votre intégration doit afficher le texte du mandat pour être conforme. Assurez-vous que les URL dans le texte peuvent être ouvertes à l’aide d’un UITextView ou d’un élément similaire. #### UIKit ```swift var configuration = EmbeddedPaymentElement.Configuration(...) configuration.embeddedViewDisplaysMandateText = true ... let mandateTextView = UITextView() mandateTextView.attributedText = embeddedPaymentElement.paymentOption.mandateText ``` #### SwiftUI ```swift var configuration = EmbeddedPaymentElement.Configuration(...) configuration.embeddedViewDisplaysMandateText = true ... if let attributedText = embeddedViewModel.paymentOption?.mandateText { Text(AttributedString(attributedText)) } ``` ## Optional: Permettre au client de payer immédiatement dans le formulaire ![Embedded Payment Element](https://b.stripecdn.com/docs-statics-srv/assets/embedded-pay-immediate.057c691220d43158ac8000de10815ed9.png) Pour configurer le bouton dans la feuille de formulaire afin qu’il confirme immédiatement le paiement, définissez `formSheetAction` sur votre objet `EmbeddedPaymentElement.Configuration`. Le bloc de finalisation s’exécute avec le résultat du paiement après la fermeture du formulaire. L’interface utilisateur intégrée n’étant pas utilisable une fois le paiement effectué, il est préférable que votre implémentation redirige l’utilisateur vers un autre écran, par exemple un écran de reçu. ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.formSheetAction = .confirm(completion: { result in switch result { case .completed: // Payment completed. You can for example, show a confirmation screen. print("Completed") case .failed(let error): // Encountered an unrecoverable error. You can display the error to the user, log it, etc. print(error) case .canceled: // Customer canceled - you should probably do nothing. break } }) ``` ## Créer un PaymentIntent [Côté serveur] Sur votre serveur, créez a *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods) en indiquant un montant et une devise. Vous pouvez gérer les moyens de paiement depuis le [Dashboard](https://dashboard.stripe.com/settings/payment_methods). Stripe gère le l’affichage des moyens de paiement admissibles en fonction de facteurs tels que le montant de la transaction, la devise et le tunnel de paiement. Pour éviter que des clients malveillants ne choisissent eux-mêmes leurs tarifs, décidez toujours du montant à débiter côté serveur (un environnement sécurisé) plutôt que côté client. Si l’appel réussit, renvoyez la *clé secrète du client* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)) du PaymentIntent. Si l’appel échoue, [traitez l’erreur](https://docs.stripe.com/error-handling.md) et renvoyez un message d’erreur avec une courte explication à l’intention de votre client. > Vérifiez que toutes les propriétés de l’IntentConfiguration correspondent à votre PaymentIntent (par exemple, `setup_future_usage`, `amount` et `currency`). #### Ruby ```ruby require 'stripe' # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. client = Stripe::StripeClient.new('<>') post '/create-intent' do data = JSON.parse request.body.read params = { amount: 1099, currency: 'usd', automatic_payment_methods: {enabled: true}, } begin intent = client.v1.payment_intents.create(params) {client_secret: intent.client_secret}.to_json rescue Stripe::StripeError => e {error: e.error.message}.to_json end end ``` ## Configurer une URL de redirection [Côté client] Le client peut quitter votre application pour s’authentifier (par exemple, dans Safari ou dans son application bancaire). Pour lui permettre de revenir automatiquement sur votre application après s’être authentifié, [configurez un schéma d’URL personnalisé](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app) et configurez votre délégué d’application pour qu’il transmette l’URL au SDK. Stripe ne prend pas en charge les [liens universels](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content). #### SceneDelegate #### Swift ```swift // This method handles opening custom URL schemes (for example, "your-app://stripe-redirect") func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { guard let url = URLContexts.first?.url else { return } let stripeHandled = StripeAPI.handleURLCallback(with: url) if (!stripeHandled) { // This was not a Stripe url – handle the URL normally as you would } } ``` #### AppDelegate #### Swift ```swift // This method handles opening custom URL schemes (for example, "your-app://stripe-redirect") func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { let stripeHandled = StripeAPI.handleURLCallback(with: url) if (stripeHandled) { return true } else { // This was not a Stripe url – handle the URL normally as you would } return false } ``` #### SwiftUI #### Swift ```swift @main struct MyApp: App { var body: some Scene { WindowGroup { Text("Hello, world!").onOpenURL { incomingURL in let stripeHandled = StripeAPI.handleURLCallback(with: incomingURL) if (!stripeHandled) { // This was not a Stripe url – handle the URL normally as you would } } } } } ``` Paramétrez également l’[URL de retour](https://github.com/stripe/stripe-ios/blob/aa3234a7fafde98c9203b6ed77e0278c04310eb0/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L70) dans votre [EmbeddedPaymentElement.Configuration](https://github.com/stripe/stripe-ios/blob/aa3234a7fafde98c9203b6ed77e0278c04310eb0/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L12) sur l’URL de votre application. ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.returnURL = "your-app://stripe-redirect" ``` ## Gérer les événements post-paiement [Côté serveur] Stripe envoie un événement [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) à l’issue du paiement. Utilisez l’[outil de webhook du Dashboard](https://dashboard.stripe.com/webhooks) ou suivez le [guide consacré aux webhooks](https://docs.stripe.com/webhooks/quickstart.md) pour recevoir ces événements et exécuter des actions, comme envoyer une confirmation de commande par e-mail à votre client, enregistrer la vente dans une base de données ou lancer un flux de livraison. Plutôt que d’attendre un rappel de votre client, écoutez ces événements. Côté client, il arrive en effet que l’utilisateur ferme la fenêtre de son navigateur ou quitte l’application avant l’exécution du rappel. Certains clients malintentionnés peuvent d’autre part tenter de manipuler la réponse. En configurant votre intégration de manière à ce qu’elle écoute les événements asynchrones, vous pourrez accepter [plusieurs types de moyens de paiement](https://stripe.com/payments/payment-methods-guide) avec une seule et même intégration. En plus de l’événement `payment_intent.succeeded`, nous vous recommandons de gérer ces autres événements lorsque vous encaissez des paiements à l’aide de l’Element Payment : | Événement | Description | Action | | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.succeeded) | Envoyé lorsqu’un client effectue un paiement avec succès. | Envoyez au client une confirmation de commande et *traitez* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected) sa commande. | | [payment_intent.processing](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.processing) | Envoyé lorsqu’un client initie un paiement, mais qu’il ne l’a pas encore finalisé. Dans la plupart des cas, cet événement est envoyé lorsque le client initie un prélèvement bancaire. Il est suivi par un événement `payment_intent.succeeded` ou `payment_intent.payment_failed`. | Envoyez au client une confirmation de commande qui indique que son paiement est en attente. Pour des marchandises dématérialisées, vous pourrez traiter la commande sans attendre que le paiement soit effectué. | | [payment_intent.payment_failed](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.payment_failed) | Envoyé lorsqu’un client effectue une tentative de paiement qui se solde par un échec. | Si un paiement passe de l’état `processing` à `payment_failed`, proposez au client de retenter le paiement. | ## Tester l'intégration #### Cartes bancaires | Numéro de carte | Scénario | Méthode de test | | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 4242424242424242 | Le paiement par carte bancaire aboutit et ne nécessite pas d’authentification. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 4000002500003155 | Le paiement par carte bancaire requiert une *authentification* (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). | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 4000000000009995 | La carte est refusée avec un code de refus de type `insufficient_funds`. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 6205500000000000004 | La carte UnionPay a un numéro d’une longueur variable, allant de 13 à 19 chiffres. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | #### Virements avec redirection bancaire | Moyen de paiement | Scénario | Méthode de test | | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Bancontact, iDEAL | Votre client ne parvient pas à s’authentifier sur la page de redirection en utilisant un moyen de paiement avec redirection et à notification immédiate. | Choisissez un moyen de paiement avec redirection, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Faire échouer le paiement test** sur la page qui s’affiche. | | Pay by Bank | Le montant dû est réglé via un moyen de paiement avec redirection et à [notification différée](https://docs.stripe.com/payments/payment-methods.md#payment-notification). | Choisissez le moyen de paiement, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Finaliser le paiement test** sur la page qui s’affiche. | | Pay by Bank | Votre client ne parvient pas à s’authentifier sur la page de redirection en utilisant un moyen de paiement avec redirection et à notification différée. | Choisissez le moyen de paiement, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Faire échouer le paiement test** sur la page qui s’affiche. | | BLIK | Les paiements BLIK échouent de diverses manières : échecs immédiats (par exemple, code expiré ou non valide), erreurs différées (refus de la banque) ou expirations du délai (le client n’a pas répondu à temps). | Utiliser des modèles d’e-mail pour [simuler les différents échecs.](https://docs.stripe.com/payments/blik/accept-a-payment.md#simulate-failures) | #### Prélèvements bancaires | Moyen de paiement | Scénario | Méthode de test | | ---------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Prélèvement automatique SEPA | Le montant dû est réglé par prélèvement automatique SEPA. | Remplissez le formulaire à l’aide du numéro de compte `AT321904300235473204`. Le PaymentIntent confirmé passe d’abord à l’état processing, puis à l’état succeeded trois minutes plus tard. | | Prélèvement automatique SEPA | L’intention de paiement de votre client passe de l’état `processing` à l’état `requires_payment_method`. | Remplissez le formulaire à l’aide du numéro de compte `AT861904300235473202`. | Consultez la section consacrée aux [tests](https://docs.stripe.com/testing.md) pour obtenir des informations supplémentaires sur la manière de tester votre intégration. ## Activer la numérisation de carte Pour activer la numérisation des cartes pour iOS, définissez le paramètre `NSCameraUsageDescription` (**Confidentialité – Description de l’utilisation de l’appareil photo**) dans le fichier `Info.plist` de votre application et indiquez le motif d’accès à l’appareil photo (« pour numériser des cartes », par exemple). ## Optional: Activer les cartes sauvegardées [Côté serveur] [Côté client] `EmbeddedPaymentElement` peut permettre au client d’enregistrer sa carte bancaire et peut inclure les cartes bancaires enregistrées du client dans les moyens de paiement disponibles. Le client doit avoir un objet [Compte](https://docs.stripe.com/api/v2/core/accounts/create.md#v2_create_accounts-configuration-customer) configuré par le client ou un objet [Client](https://docs.stripe.com/api/customers/create.md) sur votre serveur. Pour activer une case à cocher qui permet au client denregistrer sa carte bancaire, créez une [CustomerSession](https://docs.stripe.com/api/customer_sessions.md), avec `payment_method_save` défini sur `enabled`. #### Comptes v2 ```javascript const stripe = require('stripe')('sk_test_your_secret_key'); app.post('/mobile-payment-element', async (req, res) => { // Use an existing Account ID if this is a returning customer. const customer_account = await stripe.v2.core.accounts.create(); const customerSession = await stripe.customerSessions.create({ customer_account: customer_account.id, components: { mobile_payment_element: { enabled: true, features: { payment_method_save: 'enabled', payment_method_redisplay: 'enabled', payment_method_remove: 'enabled' } }, }, }); res.json({ customerSessionClientSecret: customerSession.client_secret, customer_account: customer_account.id, }); }); ``` Ensuite, configurez EmbeddedPaymentElement avec l’ID du client et la clé secrète du client de la CustomerSession. #### UIKit ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet var configuration = EmbeddedPaymentElement.Configuration() configuration.customer = .init(id: customerAccountId, customerSessionClientSecret: customerSessionClientSecret) self.embeddedPaymentElement = try await EmbeddedPaymentElement.create(..., configuration: configuration) ``` #### SwiftUI ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet var configuration = EmbeddedPaymentElement.Configuration() configuration.customer = .init(id: customerAccountId, customerSessionClientSecret: customerSessionClientSecret) try await embeddedViewModel.load(..., configuration: configuration) ``` #### Clients v1 ```javascript const stripe = require('stripe')('sk_test_your_secret_key'); app.post('/mobile-payment-element', async (req, res) => { // Use an existing Customer ID if this is a returning customer. const customer = await stripe.customers.create(); const customerSession = await stripe.customerSessions.create({ customer: customer.id, components: { mobile_payment_element: { enabled: true, features: { payment_method_save: 'enabled', payment_method_redisplay: 'enabled', payment_method_remove: 'enabled' } }, }, }); res.json({ customerSessionClientSecret: customerSession.client_secret, customer: customer.id, }); }); ``` Ensuite, configurez EmbeddedPaymentElement avec l’ID du client et la clé secrète du client de la CustomerSession. #### UIKit ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet var configuration = EmbeddedPaymentElement.Configuration() configuration.customer = .init(id: customerId, customerSessionClientSecret: customerSessionClientSecret) self.embeddedPaymentElement = try await EmbeddedPaymentElement.create(..., configuration: configuration) ``` #### SwiftUI ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet var configuration = EmbeddedPaymentElement.Configuration() configuration.customer = .init(id: customerId, customerSessionClientSecret: customerSessionClientSecret) try await embeddedViewModel.load(..., configuration: configuration) ``` ## Optional: Autoriser les moyens de paiement à notification différée [Côté client] Les *moyens de paiement différés* (A payment method that can't immediately return payment status when a customer attempts a transaction (for example, ACH debits). Businesses commonly hold an order in a pending state until payment is successful with these payment methods) ne garantissent pas non plus que vous recevrez les fonds de votre client à la fin du paiement, à cause du délai de versement (par exemple, comptes bancaires aux États-Unis, prélèvements SEPA, iDEAL et Bancontact) ou parce qu’ils nécessitent une intervention du client (par exemple, OXXO, Konbini et Boleto). Par défaut, EmbeddedPaymentElement n’affiche pas les moyens de paiement différés. Pour vous inscrire, définissez `allowsDelayedPaymentMethods` sur true dans votre `EmbeddedPaymentElement.Configuration`. Cette étape ne suffit pas à activer des moyens de paiement spécifiques, elle permet simplement d’indiquer que votre application est capable de les gérer. Par exemple, bien qu’OXXO ne soit actuellement pas pris en charge par EmbeddedPaymentElement, s’il devient pris en charge et que vous avez installé la dernière version du SDK, votre application pourra afficher OXXO comme moyen de paiement sans modification supplémentaire de l’intégration. #### UIKit ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.allowsDelayedPaymentMethods = true self.embeddedPaymentElement = try await EmbeddedPaymentElement.create(..., configuration: configuration) ``` #### SwiftUI ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.allowsDelayedPaymentMethods = true try await embeddedViewModel.load(..., configuration: configuration) ``` Si le client utilise avec succès l’un de ces moyens de paiement différé dans EmbeddedPaymentElement, le résultat du paiement renvoyé est `.completed`. ## Optional: Activer Apple Pay > Si votre écran de paiement comporte un bouton **Apple Pay** dédié, suivez le [guide Apple Pay](https://docs.stripe.com/apple-pay.md#present-payment-sheet) et utilisez `ApplePayContext` pour encaisser le paiement à partir de votre bouton **Apple Pay**. Vous pouvez utiliser `EmbeddedPaymentElement` pour gérer d’autres types de moyens de paiement. ### Demander un ID de marchand Apple Pour obtenir un ID de marchand Apple, [demandez un nouvel identifiant](https://developer.apple.com/account/resources/identifiers/add/merchant) sur le site Web Apple Developer. Renseignez le formulaire en indiquant une description et un identifiant. La description n’est destinée qu’à votre propre information et vous pourrez la modifier ultérieurement au besoin. En ce qui concerne l’identifiant, Stripe vous recommande d’utiliser le nom de votre application (par exemple, `merchant.com.{{YOUR_APP_NAME}}`). ### Créer un certificat Apple Pay Créez un certificat permettant à votre application de chiffrer les données de paiement. Accédez aux [paramètres des certificats iOS](https://dashboard.stripe.com/settings/ios_certificates) dans le Dashboard, cliquez sur **Ajouter une nouvelle application** et suivez le guide. Téléchargez un fichier CSR (Certificate Signing Request) pour obtenir d’Apple un certificat sécurisé vous autorisant à utiliser Apple Pay. Un fichier CSR peut émettre exactement un certificat. Si vous changez d’ID de marchand Apple, vous devez accéder aux [paramètres des certificats iOS](https://dashboard.stripe.com/settings/ios_certificates) dans le Dashboard pour obtenir un nouveau fichier CSR et un nouveau certificat. ### Réaliser une intégration avec Xcode Ajoutez la fonctionnalité Apple Pay à votre application. Dans Xcode, ouvrez vos paramètres de projet, cliquez sur l’onglet **Signature et fonctionnalités**, puis ajoutez **Apple Pay**. Vous serez peut-être alors invité(e) à vous connecter à votre compte développeur. Sélectionnez l’ID du marchand créé plus tôt. Il est désormais possible d’utiliser Apple Pay sur votre application. ![](https://b.stripecdn.com/docs-statics-srv/assets/xcode.a701d4c1922d19985e9c614a6f105bf1.png) Activez la fonctionnalité Apple Pay dans Xcode ### Ajouter Apple Pay #### Paiement ponctuel Pour ajouter Apple Pay à EmbeddedPaymentElement, configurez [applePay](https://github.com/stripe/stripe-ios/blob/8be959abc141e360080efa88980afb325737a935/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L28) après avoir initialisé `EmbeddedPaymentElement.Configuration` avec votre ID de marchand Apple et le [code pays](https://dashboard.stripe.com/settings/account) de votre entreprise. #### iOS (Swift) ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.applePay = .init( merchantId: "merchant.com.your_app_name", merchantCountryCode: "US" ) ``` #### Paiements récurrents Pour ajouter Apple Pay à EmbeddedPaymentElement, configurez [applePay](https://github.com/stripe/stripe-ios/blob/8be959abc141e360080efa88980afb325737a935/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L28) après avoir initialisé `EmbeddedPaymentElement.Configuration` avec votre ID de marchand Apple et le [code pays](https://dashboard.stripe.com/settings/account) de votre entreprise. Conformément aux [directives d’Apple](https://developer.apple.com/design/human-interface-guidelines/apple-pay#Supporting-subscriptions) pour les paiements récurrents, vous devez également définir des attributs supplémentaires sur la `PKPaymentRequest`. Ajoutez un gestionnaire dans [ApplePayConfiguration.paymentRequestHandlers](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/applepayconfiguration/handlers/paymentrequesthandler) pour configurer les [PKPaymentRequest.paymentSummaryItems](https://developer.apple.com/documentation/passkit/pkpaymentrequest/1619231-paymentsummaryitems) avec le montant que vous avez l’intention de facturer (par exemple, 9,95 USD par mois). Vous pouvez également adopter des [tokens de marchand](https://developer.apple.com/apple-pay/merchant-tokens/) en définissant les propriétés `recurringPaymentRequest` ou `automaticReloadPaymentRequest` dans `PKPaymentRequest`. Pour en savoir plus sur l’utilisation des paiements récurrents avec Apple Pay, consultez la [documentation d’Apple sur PassKit](https://developer.apple.com/documentation/passkit/pkpaymentrequest). #### iOS (Swift) ```swift let customHandlers = EmbeddedPaymentElement.ApplePayConfiguration.Handlers( paymentRequestHandler: { request in // PKRecurringPaymentSummaryItem is available on iOS 15 or later if #available(iOS 15.0, *) { let billing = PKRecurringPaymentSummaryItem(label: "My Subscription", amount: NSDecimalNumber(string: "59.99")) // Payment starts today billing.startDate = Date() // Payment ends in one year billing.endDate = Date().addingTimeInterval(60 * 60 * 24 * 365) // Pay once a month. billing.intervalUnit = .month billing.intervalCount = 1 // recurringPaymentRequest is only available on iOS 16 or later if #available(iOS 16.0, *) { request.recurringPaymentRequest = PKRecurringPaymentRequest(paymentDescription: "Recurring", regularBilling: billing, managementURL: URL(string: "https://my-backend.example.com/customer-portal")!) request.recurringPaymentRequest?.billingAgreement = "You'll be billed $59.99 every month for the next 12 months. To cancel at any time, go to Account and click 'Cancel Membership.'" } request.paymentSummaryItems = [billing] request.currencyCode = "USD" } else { // On older iOS versions, set alternative summary items. request.paymentSummaryItems = [PKPaymentSummaryItem(label: "Monthly plan starting July 1, 2022", amount: NSDecimalNumber(string: "59.99"), type: .final)] } return request } ) var configuration = EmbeddedPaymentElement.Configuration() configuration.applePay = .init(merchantId: "merchant.com.your_app_name", merchantCountryCode: "US", customHandlers: customHandlers) ``` ### Suivi des commandes Pour ajouter des informations de [suivi de commande](https://developer.apple.com/design/human-interface-guidelines/technologies/wallet/designing-order-tracking) dans iOS 16 ou version ultérieure, configurez un [authorizationResultHandler](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/applepayconfiguration/handlers/authorizationresulthandler) dans votre `PaymentSheet.ApplePayConfiguration.Handlers`. Stripe effectue un appel vers votre implémentation une fois le paiement effectué, mais avant qu’iOS ne ferme la fiche Apple Pay. Dans votre déploiement `authorizationResultHandler`, récupérez les détails de la commande finalisée sur votre serveur. Ajoutez ces informations au [PKPaymentAuthorizationResult](https://developer.apple.com/documentation/passkit/pkpaymentauthorizationresult) spécifié, et renvoyez le résultat modifié. Pour en savoir plus sur le suivi des commandes, consultez la [documentation d’Apple sur les commandes Wallet](https://developer.apple.com/documentation/walletorders). #### iOS (Swift) ```swift let customHandlers = PaymentSheet.ApplePayConfiguration.Handlers( authorizationResultHandler: { result in do { // Fetch the order details from your service let myOrderDetails = try await MyAPIClient.shared.fetchOrderDetails(orderID: orderID) result.orderDetails = PKPaymentOrderDetails( orderTypeIdentifier: myOrderDetails.orderTypeIdentifier, // "com.myapp.order" orderIdentifier: myOrderDetails.orderIdentifier, // "ABC123-AAAA-1111" webServiceURL: myOrderDetails.webServiceURL, // "https://my-backend.example.com/apple-order-tracking-backend" authenticationToken: myOrderDetails.authenticationToken) // "abc123" // Return your modified PKPaymentAuthorizationResult return result } catch { return PKPaymentAuthorizationResult(status: .failure, errors: [error]) } } ) var configuration = EmbeddedPaymentElement.Configuration() configuration.applePay = .init(merchantId: "merchant.com.your_app_name", merchantCountryCode: "US", customHandlers: customHandlers) ``` ## Optional: Personnaliser l’élément Toute personnalisation est configurée au moyen de l’objet [EmbeddedPaymentElement.Configuration](https://github.com/stripe/stripe-ios/blob/8be959abc141e360080efa88980afb325737a935/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L12). ### Apparence Personnalisez les couleurs, les polices et plus encore afin de vous adapter à l’apparence de votre application à l’aide de l’[API Appearance](https://docs.stripe.com/elements/appearance-api/embedded-mobile.md?platform=ios). ### Recueillir les adresses des utilisateurs Recueillez les adresses de livraison ou de facturation de vos clients locaux et internationaux à l’aide du composant [Address Element](https://docs.stripe.com/elements/address-element.md?platform=ios). ### Nom d’affichage du marchand Précisez un nom d’entreprise pour le client en définissant [merchantDisplayName](https://github.com/stripe/stripe-ios/blob/8be959abc141e360080efa88980afb325737a935/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L66). Par défaut, il s’agit du nom de votre application. #### Swift ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.merchantDisplayName = "My app, Inc." ``` ### Mode sombre `EmbeddedPaymentElement` s’ajuste automatiquement en fonction des paramètres d’affichage du système de l’utilisateur (mode clair et sombre). Si votre application ne prend pas en charge le mode sombre, vous pouvez définir le [style](https://github.com/stripe/stripe-ios/blob/8be959abc141e360080efa88980afb325737a935/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L51) sur le mode `alwaysLight` ou `alwaysDark`. ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.style = .alwaysLight ``` ## Optional: Activer la collecte du CVC après confirmation Pour récupérer le CVC d’une carte bancaire enregistrée lors de la confirmation de PaymentIntent, votre intégration doit collecter les informations de paiement avant de créer un PaymentIntent. ### Mettre à jour la configuration de l’Intent `PaymentSheet.IntentConfiguration` accepte un paramètre facultatif qui contrôle le moment de récupérer le CVC pour une carte enregistrée. ```swift let intentConfig = PaymentSheet.IntentConfiguration( mode: .payment(amount: 1099, currency: "USD"), confirmHandler: { confirmationToken in // Handle ConfirmationToken...}, requireCVCRecollection: true) ``` ### Mettre à jour les paramètres de création de l’Intent Pour récupérer le CVC lors de la confirmation du paiement, ajoutez les paramètres `customerId` et `require_cvc_recollection` lors de la création du PaymentIntent. #### Ruby ```ruby require 'stripe' # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. client = Stripe::StripeClient.new('<>') post '/create-intent' do data = JSON.parse request.body.read params = { amount: 1099, currency: 'usd', automatic_payment_methods: {enabled: true},customer: customer.id, payment_method_options: { card: {require_cvc_recollection: true} } } begin intent = client.v1.payment_intents.create(params) {client_secret: intent.client_secret}.to_json rescue Stripe::StripeError => e {error: e.error.message}.to_json end end ``` # Collecter et enregistrer un moyen de paiement > This is a Collecter et enregistrer un moyen de paiement for when platform is ios and type is setup. View the full page at https://docs.stripe.com/payments/mobile/accept-payment-embedded?platform=ios&type=setup. Un flux SetupIntent vous permet d’enregistrer des moyens de paiement pour des paiements ultérieurs sans créer de débité. Dans cette intégration, vous affichez le Payment Element, créez un *SetupIntent* (The Setup Intents API lets you build dynamic flows for collecting payment method details for future payments. It tracks the lifecycle of a payment setup flow and can trigger additional authentication steps if required by law or by the payment method) et enregistrez le moyen de paiement dans votre application. ## Configurer Stripe [Côté serveur] [Côté client] ### Côté serveur Cette intégration exige que votre serveur dispose de endpoints qui communiquent avec l’API Stripe. Utilisez nos bibliothèques officielles pour accéder à l’API Stripe depuis votre serveur : #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ### Côté client Le [SDK iOS de Stripe](https://github.com/stripe/stripe-ios) est disponible en open source et [fait l’objet d’une documentation complète](https://stripe.dev/stripe-ios/index.html). Il est également compatible avec les applications prenant en charge iOS 13 et les versions ultérieures. #### Swift Package Manager Pour installer le SDK, veuillez suivre les étapes ci-dessous : 1. Dans Xcode, sélectionnez **File** > **Add Package Dependencies…** puis saisissez `https://github.com/stripe/stripe-ios-spm` en tant qu’URL du référentiel. 1. Sélectionnez le dernier numéro de version, visible sur notre [page des versions](https://github.com/stripe/stripe-ios/releases). 1. Ajoutez le produit **StripePaymentSheet** à la [cible de votre application](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app). #### CocoaPods 1. Si vous ne l’avez pas encore fait, installez la version la plus récente de [CocoaPods](https://guides.cocoapods.org/using/getting-started.html). 1. Si vous n’avez pas de fichier [Podfile](https://guides.cocoapods.org/syntax/podfile.html), exécutez la commande suivante pour en créer un : ```bash pod init ``` 1. Ajoutez cette ligne à votre `Podfile` : ```podfile pod 'StripePaymentSheet' ``` 1. Exécutez la commande suivante : ```bash pod install ``` 1. À partir de maintenant, n’oubliez pas d’utiliser le fichier .xcworkspace au lieu du fichier .xcodeproj pour ouvrir votre projet dans Xcode. 1. Pour mettre à jour ultérieurement le SDK vers la version la plus récente, il vous suffit d’exécuter : ```bash pod update StripePaymentSheet ``` #### Carthage 1. Si vous ne l’avez pas encore fait, installez la version la plus récente de [Carthage](https://github.com/Carthage/Carthage#installing-carthage). 1. Ajoutez cette ligne à votre `Cartfile` : ```cartfile github "stripe/stripe-ios" ``` 1. Suivez les [instructions d’installation de Carthage](https://github.com/Carthage/Carthage#if-youre-building-for-ios-tvos-or-watchos). Veillez à intégrer tous les cadres requis listés [ici](https://github.com/stripe/stripe-ios/tree/master/StripePaymentSheet/README.md#manual-linking). 1. Pour mettre à jour ultérieurement le SDK vers la version la plus récente, exécutez la commande suivante : ```bash carthage update stripe-ios --platform ios ``` #### Cadre manuel 1. Accédez à notre [page des versions GitHub](https://github.com/stripe/stripe-ios/releases/latest), puis téléchargez et décompressez **Stripe.xcframework.zip**. 1. Faites glisser **StripePaymentSheet.xcframework** vers la section **Embedded Binaries (Fichiers binaires incorporés)** des paramètres **General (Général)** de votre projet Xcode. Veillez à sélectionner **Copy items if needed (Copier les éléments si nécessaire)**. 1. Répétez l’étape 2 pour tous les cadres requis listés [ici](https://github.com/stripe/stripe-ios/tree/master/StripePaymentSheet/README.md#manual-linking). 1. À l’avenir, pour mettre à jour vers la version la plus récente de notre SDK, répétez les étapes 1 à 3. > Pour obtenir de plus amples informations sur la version la plus récente du SDK et ses versions antérieures, consultez la page des [versions](https://github.com/stripe/stripe-ios/releases) sur GitHub. Pour recevoir une notification lors de la publication d’une nouvelle version, [surveillez les versions](https://help.github.com/en/articles/watching-and-unwatching-releases-for-a-repository#watching-releases-for-a-repository) à partir du référentiel. Vous devez également définir votre [clé publique](https://dashboard.stripe.com/apikeys) pour que le SDK puisse effectuer des appels à l’API Stripe. Pour commencer, vous pouvez coder en dur la clé publique côté client pendant l’intégration, mais la récupérer sur votre serveur en mode production. ```swift // Set your publishable key: remember to change this to your live publishable key in production // See your keys here: https://dashboard.stripe.com/apikeys STPAPIClient.shared.publishableKey = "<>" ``` ## Activer des moyens de paiement Affichez vos [paramètres des moyens de paiement](https://dashboard.stripe.com/settings/payment_methods) et activez les moyens de paiement que vous souhaitez prendre en charge. Vous devez activer au moins un moyen de paiement pour créer un *SetupIntent* (The Setup Intents API lets you build dynamic flows for collecting payment method details for future payments. It tracks the lifecycle of a payment setup flow and can trigger additional authentication steps if required by law or by the payment method). Par défaut, Stripe active les cartes bancaires et les autres moyens de paiement courants qui peuvent vous permettre d’atteindre davantage de clients. Nous vous recommandons toutefois d’activer d’autres moyens de paiement pertinents pour votre entreprise et vos clients. Consultez la page [Prise en charge des moyens de paiement](https://docs.stripe.com/payments/payment-methods/payment-method-support.md) pour en savoir plus sur la prise en charge des produits et des moyens de paiement, et notre [page des tarifs](https://stripe.com/pricing/local-payment-methods) pour prendre connaissance des frais que nous appliquons. ## Créer un client [Côté serveur] Pour configurer un moyen de paiement pour des paiements futurs, vous devez l’associer à un objet représentant votre client. Lorsque votre client crée un compte ou effectue sa première transaction avec votre entreprise, créez un objet [Customer](https://docs.stripe.com/api/customers/create.md). ```curl curl -X POST https://api.stripe.com/v1/customers \ -u "<>:" ``` ## Collecter les informations de paiement [Côté client] Le composant Embedded Mobile Payment Element est conçu pour être placé sur la page de paiement de votre application mobile native. L’élément affiche une liste de moyens de paiement que vous pouvez personnaliser pour l’adapter à l’apparence de votre application. Lorsque le client appuie sur la ligne **Carte bancaire**, un formulaire s’ouvre dans lequel il peut saisir les informations de son moyen de paiement. Par défaut, le bouton du formulaire indique **Continuer** et déclenche la fermeture du formulaire, ce qui permet à votre client de terminer la configuration dans votre système de paiement. ![Payment Element](https://b.stripecdn.com/docs-statics-srv/assets/ios-embedded.b5867c116d537ffcb920dd80ebdfc741.png) Vous pouvez configurer le bouton pour qu’il termine immédiatement la configuration au lieu de continuer. Pour ce faire, effectuez [cette étape](https://docs.stripe.com/payments/mobile/accept-payment-embedded.md#embedded-let-customer-pay-immediately) après avoir suivi le guide. #### UIKit ### Initialiser le Payment Element Appelez `create` pour instancier EmbeddedPaymentElement avec un `EmbeddedPaymentElement.Configuration` et un [PaymentSheet.IntentConfiguration](https://github.com/stripe/stripe-ios/blob/master/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetIntentConfiguration.swift). L’objet Configuration contient des options de configuration générales pour EmbeddedPaymentElement qui ne changent pas entre les paiements, comme `returnURL`. L’objet `IntentConfiguration` contient des détails sur le paiement spécifique, comme le montant et la devise, ainsi qu’un rappel `confirmationTokenConfirmHandler`. Pour l’instant, laissez son implémentation vide. Une fois l’initialisation réussie, définissez les paramètres `presentingViewController` et `delegate`. ```swift import StripePaymentSheet class MyCheckoutVC: UIViewController { func createEmbeddedPaymentElement() async throws -> EmbeddedPaymentElement { let intentConfig = PaymentSheet.IntentConfiguration( mode: .setup(currency: "USD") ) { [weak self] confirmationToken in return await self?.handleConfirmationToken(confirmationToken) } var configuration = EmbeddedPaymentElement.Configuration() configuration.returnURL = "your-app://stripe-redirect" // Use the return url you set up in the previous step let embeddedPaymentElement = try await EmbeddedPaymentElement.create(intentConfiguration: intentConfig, configuration: configuration) embeddedPaymentElement.presentingViewController = self embeddedPaymentElement.delegate = self return embeddedPaymentElement } func handleConfirmationToken(_ confirmationToken: STPConfirmationToken) async throws -> String { // You'll implement this in the "Confirm the payment" section below } } ``` ### Ajouter la vue Payment Element Une fois que le EmbeddedPaymentElement est initialisé avec succès, intégrez sa vue dans votre interface de paiement. > La vue doit être placée dans une vue défilable, comme UIScrollView, car elle n’a pas de taille fixe et peut changer de hauteur après son rendu initial. ```swift class MyCheckoutVC: UIViewController { // ... private(set) var embeddedPaymentElement: EmbeddedPaymentElement? private lazy var checkoutButton: UIButton = { let checkoutButton = UIButton(type: .system) checkoutButton.backgroundColor = .systemBlue checkoutButton.layer.cornerRadius = 5.0 checkoutButton.clipsToBounds = true checkoutButton.setTitle("Checkout", for: .normal) checkoutButton.setTitleColor(.white, for: .normal) checkoutButton.translatesAutoresizingMaskIntoConstraints = false checkoutButton.isEnabled = embeddedPaymentElement?.paymentOption != nil checkoutButton.addTarget(self, action: #selector(didTapConfirmButton), for: .touchUpInside) return checkoutButton }() // ... @objc func didTapConfirmButton() { // You'll implement this in the "Confirm the payment" section below } override func viewDidLoad() { super.viewDidLoad() Task { @MainActor in do { // Create a UIScrollView let scrollView = UIScrollView() scrollView.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(scrollView) // Create the Payment Element let embeddedPaymentElement = try await createEmbeddedPaymentElement() embeddedPaymentElement.delegate = self embeddedPaymentElement.presentingViewController = self self.embeddedPaymentElement = embeddedPaymentElement // Add its view to the scroll view scrollView.addSubview(embeddedPaymentElement.view) // Add your own checkout button to the scroll view scrollView.addSubview(checkoutButton) // Set up layout constraints embeddedPaymentElement.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), embeddedPaymentElement.view.topAnchor.constraint(equalTo: scrollView.topAnchor), embeddedPaymentElement.view.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor), embeddedPaymentElement.view.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor), checkoutButton.topAnchor.constraint(equalTo: embeddedPaymentElement.view.bottomAnchor, constant: 4.0), checkoutButton.leadingAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.leadingAnchor, constant: 4.0), checkoutButton.trailingAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.trailingAnchor, constant: -4.0), ]) } catch { // Handle view not being added to view } } } } ``` À ce stade, vous pouvez exécuter votre application et voir le composant Embedded Mobile Payment Element. ### Gérer les changements de hauteur La vue de l’élément EmbeddedPaymentElement peut augmenter ou diminuer en taille, ce qui peut avoir un impact sur la disposition de la vue. Gérez les changements de hauteur en implémentant la méthode déléguée `embeddedPaymentElementDidUpdateHeight`. La vue d’EmbeddedPaymentElement appelle cette méthode à l’intérieur d’un bloc d’animation qui met à jour sa hauteur. Votre implémentation doit appeler `setNeedsLayout()` et `layoutIfNeeded()` sur la vue de défilement qui contient la vue de l’EmbeddedPaymentElement pour permettre une animation fluide du changement de hauteur. ```swift extension MyCheckoutVC: EmbeddedPaymentElementDelegate { func embeddedPaymentElementDidUpdateHeight(embeddedPaymentElement: StripePaymentSheet.EmbeddedPaymentElement) { // Handle layout appropriately self.view.setNeedsLayout() self.view.layoutIfNeeded() } } ``` Nous vous recommandons de tester que votre vue réagit correctement aux changements de hauteur. Pour ce faire, appelez `testHeightChange()` sur EmbeddedPaymentElement afin de simuler l’affichage et le masquage d’un mandat dans le composant. Assurez-vous qu’après l’appel de `testHeightChange()`, votre vue de défilement s’ajuste correctement. ```swift class MyCheckoutVC: UIViewController { override func viewDidLoad() { // This is only for testing purposes: #if DEBUG Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { [weak self] _ in Task { @MainActor in self?.embeddedPaymentElement?.testHeightChange() } } #endif } } ``` ### (Facultatif) Afficher l’option de paiement sélectionnée Si vous avez besoin d’accéder aux détails de l’option de paiement sélectionnée par le client, comme une étiquette (par exemple, « ····4242 »), une image (par exemple, un logo VISA) ou des détails de facturation à afficher dans votre interface utilisateur, utilisez la propriété `paymentOption` de EmbeddedPaymentElement. Pour recevoir une notification à chaque modification de `paymentOption`, implémentez la méthode déléguée `embeddedPaymentElementDidUpdatePaymentOption`. ```swift extension MyCheckoutVC: EmbeddedPaymentElementDelegate { func embeddedPaymentElementDidUpdatePaymentOption(embeddedPaymentElement: EmbeddedPaymentElement) { print("The payment option changed: \(embeddedPaymentElement.paymentOption)") checkoutButton.isEnabled = embeddedPaymentElement.paymentOption != nil } } ``` ### (Facultatif) Mettre à jour les informations de paiement Lorsque le client effectue des actions qui modifient les informations de paiement (par exemple avec l’application d’un code de réduction), mettez à jour l’instance `EmbeddedPaymentElement` de manière à refléter les nouvelles valeurs en appelant la méthode `update`. Certains moyens de paiement, comme Apple Pay et Google Pay, affichent le montant dans l’interface utilisateur, alors assurez-vous qu’il est toujours exact et à jour. Une fois l’appel de modification terminé, mettez à jour votre interface utilisateur. L’appel de modification peut mettre à jour l’option de paiement sélectionnée par le client. ```swift extension MyCheckoutVC { func update() { Task { @MainActor in var updatedIntentConfig = oldIntentConfig // Update the currency updatedIntentConfig.mode = PaymentSheet.IntentConfiguration.Mode.setup(currency: "USD") let result = await embeddedPaymentElement?.update(intentConfiguration: updatedIntentConfig) switch result { case .canceled, nil: // Do nothing; this happens when a subsequent `update` call cancels this one break case .failed(let error): // Display error to user in an alert, let users retry case .succeeded: // Update your UI in case the payment option changed } } } } ``` ### Confirmer la configuration Lorsque le client appuie sur le bouton de paiement, appelez `embeddedPaymentElement.confirm()` pour terminer la configuration. Veillez à désactiver l’interaction avec l’utilisateur lors de la confirmation. ```swift extension MyCheckoutVC { @objc func didTapConfirmButton() { Task { @MainActor in guard let embeddedPaymentElement else { return } self.view.isUserInteractionEnabled = false // Disable user interaction, show a spinner, and so on before calling confirm. let result = await embeddedPaymentElement.confirm() switch result { case .completed: // Setup completed - show a confirmation screen. case .failed(let error): self.view.isUserInteractionEnabled = true // Encountered an unrecoverable error. You can display the error to the user, log it, and so on. case .canceled: self.view.isUserInteractionEnabled = true // Customer canceled - you should probably do nothing. break } } } } ``` Ensuite, implémentez le rappel `confirmationTokenConfirmHandler` que vous avez passé précédemment à `PaymentSheet.IntentConfiguration` pour envoyer une requête à votre serveur. Votre serveur crée un SetupIntent et renvoie sa clé secrète du client. Pour plus d’informations sur ce processus, consultez l’étape [Créer un SetupIntent](https://docs.stripe.com/payments/mobile/accept-payment-embedded.md#submit-setup). Lorsque la requête est renvoyée, renvoyez la clé secrète du client contenue dans la réponse du serveur, ou générez une erreur. Le EmbeddedPaymentElement confirme le PaymentIntent en utilisant la clé secrète du client ou affiche le message d’erreur localisé dans son interface utilisateur (soit [errorDescription](https://developer.apple.com/documentation/foundation/localizederror/2946895-errordescription), soit [localizedDescription](https://developer.apple.com/documentation/foundation/nserror/1414418-localizeddescription)). Une fois la confirmation terminée, le EmbeddedPaymentElement n’est plus utilisable. Dirigez plutôt l’utilisateur vers un écran de reçu ou un écran similaire. ```swift extension MyCheckoutVC { func handleConfirmationToken(_ confirmationToken: STPConfirmationToken) async throws -> String { // Make a request to your own server. Pass `confirmationToken.stripeId` if using server-side confirmation, and return the client secret or throw an error. let myServerClientSecret = try await fetchIntentClientSecret(...) } } ``` #### SwiftUI ### Initialiser le Payment Element Appelez `load` pour charger l’EmbeddedPaymentElementViewModel avec un `EmbeddedPaymentElement.Configuration` et un [PaymentSheet.IntentConfiguration](https://github.com/stripe/stripe-ios/blob/master/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetIntentConfiguration.swift). L’objet Configuration contient des options de configuration générales pour EmbeddedPaymentElement qui ne changent pas entre les paiements, comme `returnURL`. L’objet `IntentConfiguration` contient des détails sur le paiement spécifique, comme le montant et la devise, ainsi qu’un rappel `confirmationTokenConfirmHandler`. Pour l’instant, laissez son implémentation vide. ```swift import SwiftUI import StripePaymentSheet struct MyEmbeddedCheckoutView: View { // Store an `EmbeddedPaymentElementViewModel` as a `@StateObject` @StateObject var embeddedViewModel = EmbeddedPaymentElementViewModel() var body: some View { ScrollView { // Empty scroll view for now } .task { do { if !embeddedViewModel.isLoaded { // Load the view model with your configuration try await loadEmbeddedViewModel() } } catch { // On load failure, implement retry logic (automatic retry or user-triggered through UI). } } } private func loadEmbeddedViewModel() async throws { let intentConfiguration = PaymentSheet.IntentConfiguration( mode: .setup(currency: "USD") ) { confirmationToken in try await self.handleConfirmationToken(confirmationToken) } var configuration = EmbeddedPaymentElement.Configuration() configuration.returnURL = "your-app://stripe-redirect" // Use the return url you set up in the previous step try await embeddedViewModel.load(intentConfiguration: intentConfiguration, configuration: configuration) } func handleConfirmationToken(_ confirmationToken: STPConfirmationToken) async throws -> String { // You'll implement this in the "Confirm the payment" section below } } ``` ### Ajouter la vue Payment Element Une fois que EmbeddedPaymentElementViewModel est chargé avec succès, ajoutez EmbeddedPaymentElementView dans votre interface de paiement. > La vue doit être placée dans une vue défilable, comme ScrollView, car elle n’a pas de taille fixe et peut changer de hauteur après son rendu initial. ```swift struct MyEmbeddedCheckoutView: View { var body: some View { ScrollView { // isLoaded becomes true only after a successful call to `embeddedViewModel.load()` if embeddedViewModel.isLoaded { EmbeddedPaymentElementView(viewModel: embeddedViewModel) } } } } ``` À ce stade, vous pouvez exécuter votre application et voir le composant Embedded Mobile Payment Element. ### Gérer les changements de hauteur La EmbeddedPaymentElementView peut augmenter ou diminuer en taille, ce qui peut affecter la disposition de la vue. La EmbeddedPaymentElementView gère automatiquement ces changements lorsqu’elle se trouve à l’intérieur d’une ScrollView. Nous vous recommandons de tester que votre vue réagit correctement aux changements de hauteur. Pour ce faire, appelez `testHeightChange()` sur EmbeddedPaymentElementViewModel afin de simuler l’affichage et la disparition d’un mandat dans l’élément. Assurez-vous qu’après l’appel de `testHeightChange()`, votre ScrollView s’ajuste de manière fluide. ```swift struct MyEmbeddedCheckoutView: View { var body: some View { ScrollView { if embeddedViewModel.isLoaded { EmbeddedPaymentElementView(viewModel: embeddedViewModel) // For testing only #if DEBUG Button("Test height change") { embeddedViewModel.testHeightChange() } #endif } } } } ``` ### (Facultatif) Afficher l’option de paiement sélectionnée Si vous avez besoin d’accéder aux détails de l’option de paiement sélectionnée par le client, comme un libellé (par exemple, « ----4242 »), une image (par exemple, un logo VISA) ou des détails de facturation à afficher dans votre interface utilisateur, utilisez la propriété `paymentOption` du modèle EmbeddedPaymentElementViewModel. Lorsque le client sélectionne un moyen de paiement qui ouvre un formulaire, l’option de paiement est mise à jour après qu’il a cliqué sur **Continuer** dans le formulaire. ```swift struct MyEmbeddedCheckoutView: View { var body: some View { ScrollView { if embeddedViewModel.isLoaded { // ... // A real integration probably wouldn't show the selected payment option on the same screen as the embedded payment element. We display it as an example. if let paymentOption = embeddedViewModel.paymentOption { HStack { Image(uiImage: paymentOption.image) .resizable() .aspectRatio(contentMode: .fit) .frame(height: 30) Text(paymentOption.label) Spacer() } .padding() } } } } } ``` ### (Facultatif) Mettre à jour les informations de paiement Lorsque le client effectue des actions qui modifient les informations de paiement (par exemple, l’application d’un code de réduction), mettez à jour l’instance `EmbeddedPaymentElementViewModel` pour refléter les nouvelles valeurs en appelant la méthode `update`. Certains moyens de paiement, comme Apple Pay et Google Pay, affichent le montant dans l’interface utilisateur : assurez-vous qu’il est toujours exact et à jour. Une fois la mise à jour terminée, il est possible qu’elle ait modifié l’option de paiement sélectionnée par le client. ```swift extension MyEmbeddedCheckoutView { func update() { Task { @MainActor in var updatedIntentConfig = oldIntentConfig updatedIntentConfig.mode = PaymentSheet.IntentConfiguration.Mode.setup(currency: "USD") let result = await embeddedViewModel.update(intentConfiguration: updatedIntentConfig) switch result { case .canceled: // Do nothing; this happens when a subsequent `update` call cancels this one break case .failed(let error): // Display error to user in an alert, let users retry case .succeeded: // Update your UI in case the payment option changed } } } } ``` ### Confirmer la configuration Lorsque le client appuie sur le bouton de paiement, appelez `embeddedViewModel.confirm()` pour terminer la configuration. Veillez à désactiver l’interaction avec l’utilisateur lors de la confirmation. ```swift extension MyEmbeddedCheckoutView { func didTapConfirmButton() { Task { @MainActor in // Be sure to disable user interaction during confirm (not shown in this example) let result = await embeddedViewModel.confirm() switch result { case .completed: // Setup completed - show a confirmation screen. case .failed(let error): // Encountered an unrecoverable error. Re-enable user interaction, display the error to the user, log it, and so on. case .canceled: // Customer canceled - re-enable user interaction and let them try again. break } } } } ``` Ensuite, implémentez le rappel `confirmationTokenConfirmHandler` que vous avez passé précédemment à `PaymentSheet.IntentConfiguration` pour envoyer une requête à votre serveur. Votre serveur crée un SetupIntent et renvoie sa clé secrète du client. Pour plus d’informations sur ce processus, consultez l’étape [Créer un SetupIntent](https://docs.stripe.com/payments/mobile/accept-payment-embedded.md#submit-setup). Renvoyez la clé secrète du client de la réponse de votre serveur ou générez une erreur. Le EmbeddedPaymentElement confirme le PaymentIntent en utilisant la clé secrète du client ou affiche le message d’erreur localisé dans son interface utilisateur (soit [errorDescription](https://developer.apple.com/documentation/foundation/localizederror/2946895-errordescription), soit [localizedDescription](https://developer.apple.com/documentation/foundation/nserror/1414418-localizeddescription)). Une fois la confirmation terminée, le EmbeddedPaymentElement n’est plus utilisable. Dirigez plutôt l’utilisateur vers un écran de reçu ou un écran similaire. ```swift extension MyEmbeddedCheckoutView { func handleConfirmationToken(_ confirmationToken: STPConfirmationToken) async throws -> String { // Make a request to your own server. Pass confirmationToken.stripeId if using server-side confirmation. // Return the client secret or throw an error return try await MyAPIClient.shared.createIntent(confirmationTokenId: confirmationToken.stripeId) } } ``` ## Optional: Décocher l’option de paiement sélectionnée Si vous avez des options de paiement externes à l’EmbeddedPaymentElement, vous devrez peut-être décocher l’option de paiement sélectionnée. Pour ce faire, utilisez l’API `clearPaymentOption`. #### UIKit ```swift extension MyCheckoutVC: UIViewController { func deselectPaymentMethod() { embeddedPaymentElement?.clearPaymentOption() } } ``` #### SwiftUI ```swift @available(iOS 15.0, *) extension MyEmbeddedCheckoutView { func deselectPaymentMethod() { embeddedViewModel.clearPaymentOption() } } ``` ## Optional: Afficher vous-même le mandat Afin de garantir la conformité aux réglementations, l’Embedded Mobile Payment Element affiche les mandats et clauses de non-responsabilité par défaut. Ce texte doit être situé à proximité de votre bouton d’achat. Si nécessaire, désactivez leur affichage dans la vue et affichez-les vous-même. > Votre intégration doit afficher le texte du mandat pour être conforme. Assurez-vous que les URL dans le texte peuvent être ouvertes à l’aide d’un UITextView ou d’un élément similaire. #### UIKit ```swift var configuration = EmbeddedPaymentElement.Configuration(...) configuration.embeddedViewDisplaysMandateText = true ... let mandateTextView = UITextView() mandateTextView.attributedText = embeddedPaymentElement.paymentOption.mandateText ``` #### SwiftUI ```swift var configuration = EmbeddedPaymentElement.Configuration(...) configuration.embeddedViewDisplaysMandateText = true ... if let attributedText = embeddedViewModel.paymentOption?.mandateText { Text(AttributedString(attributedText)) } ``` ## Optional: Laissez le client confirmer la configuration immédiatement dans la feuille Pour configurer le bouton dans la feuille de formulaire afin de confirmer immédiatement la configuration, configurez `formSheetAction` sur votre objet `EmbeddedPaymentElement.Configuration`. Le bloc de finalisation s’exécute avec le résultat de la configuration après la fermeture du formulaire. L’interface utilisateur intégrée n’étant pas utilisable une fois la configuration terminée, il est préférable que votre implémentation redirige l’utilisateur vers un autre écran, par exemple un écran de reçu. ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.formSheetAction = .confirm(completion: { result in switch result { case .completed: // Setup completed. You can for example, show a confirmation screen. print("Completed") case .failed(let error): // Encountered an unrecoverable error. You can display the error to the user, log it, etc. print(error) case .canceled: // Customer canceled - you should probably do nothing. break } }) ``` ## Créer un SetupIntent [Côté serveur] Sur votre serveur, créez un *SetupIntent* (The Setup Intents API lets you build dynamic flows for collecting payment method details for future payments. It tracks the lifecycle of a payment setup flow and can trigger additional authentication steps if required by law or by the payment method). Vous pouvez gérer les moyens de paiement à partir du [Dashboard](https://dashboard.stripe.com/settings/payment_methods). Stripe évalue les restrictions des moyens de paiement et d’autres paramètres pour déterminer la liste des moyens de paiement pris en charge. Si l’appel réussit, renvoyez la *clé secrète du client* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)) du SetupIntent. Si l’appel échoue, [traitez l’erreur](https://docs.stripe.com/error-handling.md) et renvoyez un message d’erreur avec une courte explication à l’intention de votre client. > Vérifiez que toutes les propriétés de l’IntentConfiguration correspondent à votre SetupIntent (par exemple, [usage](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-usage)). #### Ruby ```ruby require 'stripe' # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. client = Stripe::StripeClient.new('<>') post '/create-intent' do data = JSON.parse request.body.read params = { customer: ..., # The Customer ID you previously created automatic_payment_methods: {enabled: true}, } begin intent = client.v1.setup_intents.create(params) {client_secret: intent.client_secret}.to_json rescue Stripe::StripeError => e {error: e.error.message}.to_json end end ``` ## Configurer une URL de redirection [Côté client] Le client peut quitter votre application pour s’authentifier (par exemple, dans Safari ou dans son application bancaire). Pour lui permettre de revenir automatiquement sur votre application après s’être authentifié, [configurez un schéma d’URL personnalisé](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app) et configurez votre délégué d’application pour qu’il transmette l’URL au SDK. Stripe ne prend pas en charge les [liens universels](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content). #### SceneDelegate #### Swift ```swift // This method handles opening custom URL schemes (for example, "your-app://stripe-redirect") func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { guard let url = URLContexts.first?.url else { return } let stripeHandled = StripeAPI.handleURLCallback(with: url) if (!stripeHandled) { // This was not a Stripe url – handle the URL normally as you would } } ``` #### AppDelegate #### Swift ```swift // This method handles opening custom URL schemes (for example, "your-app://stripe-redirect") func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { let stripeHandled = StripeAPI.handleURLCallback(with: url) if (stripeHandled) { return true } else { // This was not a Stripe url – handle the URL normally as you would } return false } ``` #### SwiftUI #### Swift ```swift @main struct MyApp: App { var body: some Scene { WindowGroup { Text("Hello, world!").onOpenURL { incomingURL in let stripeHandled = StripeAPI.handleURLCallback(with: incomingURL) if (!stripeHandled) { // This was not a Stripe url – handle the URL normally as you would } } } } } ``` Paramétrez également l’[URL de retour](https://github.com/stripe/stripe-ios/blob/aa3234a7fafde98c9203b6ed77e0278c04310eb0/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L70) dans votre [EmbeddedPaymentElement.Configuration](https://github.com/stripe/stripe-ios/blob/aa3234a7fafde98c9203b6ed77e0278c04310eb0/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L12) sur l’URL de votre application. ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.returnURL = "your-app://stripe-redirect" ``` ## Débiter ultérieurement le moyen de paiement enregistré [Côté serveur] > `bancontact` et `ideal` sont les moyens de paiement ponctuel par défaut. Lorsque vous les configurez pour une utilisation future, ils génèrent un type de moyen de paiement réutilisable `sepa_debit`. Vous devez donc utiliser la requête `sepa_debit` pour les moyens de paiement enregistrés. > #### Conformité > > Lorsque vous enregistrez les informations de paiement d’un client, vous êtes responsable du respect de l’ensemble des lois, réglementations et règles du réseau en vigueur. Lorsque vous présentez au client final des moyens de paiement précédemment utilisés en vue d’effectuer ses prochains achats, assurez-vous de lister les moyens de paiement pour lesquels vous avez obtenu le consentement du client à l’enregistrement des informations de paiement aux fins des futurs achats. Le paramètre [allow_redisplay](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-allow_redisplay) vous permet de différencier les moyens de paiement associés au client qui peuvent ou non être présentés pour les achats futurs. Pour trouver un moyen de paiement à débiter, listez les moyens de paiement associés à votre client. Cet exemple liste des cartes bancaires, mais vous pouvez lister tout [type](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-type) pris en charge. > #### Utiliser l’API Accounts v2 pour représenter les clients > > L’API Accounts v2 est généralement disponible pour les utilisateurs de Connect et en aperçu public pour les autres utilisateurs de Stripe. Si vous avez accès à l’aperçu Accounts v2, vous devez [spécifier une version d’aperçu](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning) dans votre code. > > Pour demander l’accès à l’aperçu Accounts v2, > > Dans la plupart des cas d’usage, nous vous recommandons de [modéliser vos clients en tant qu’objets Account configurés par le client](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md), plutôt que d’utiliser des objets [Customer](https://docs.stripe.com/api/customers.md). #### Accounts v2 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d type=card ``` #### Customers v1 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d type=card ``` Lorsque vous êtes prêt à débiter votre client *hors session* (A payment is described as off-session if it occurs without the direct involvement of the customer, using previously-collected payment information), utilisez l’ID du `Customer` ou de l’`Account` configuré par le client ainsi que l’ID du `PaymentMethod` pour créer un `PaymentIntent` avec le montant et la devise du paiement. Définissez quelques autres paramètres pour effectuer le paiement hors session : - Définissez [off_session](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-off_session) sur true pour indiquer que le client n’est pas dans votre tunnel de paiement et ne peut pas répondre aux demandes d’authentification. Si, pendant votre tunnel de paiement, un partenaire (tel qu’un émetteur de cartes bancaires ou une banque) demande une authentification, Stripe sollicite des exemptions en utilisant les informations client issues d’une transaction précédente *pendant en session* (A payment is described as on-session if it occurs while the customer is actively in your checkout flow and able to authenticate the payment method). Si les conditions d’exemption ne sont pas remplies, le `PaymentIntent` peut générer une erreur. - Définissez [confirm](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-confirm) sur true pour déclencher la confirmation immédiatement lors de la création du `PaymentIntent`. - Définissez [payment_method](https://docs.stripe.com/api.md#create_payment_intent-payment_method) sur l’ID du `PaymentMethod`. - Selon la manière dont vous représentez les clients dans votre intégration, définissez soit [customer_account](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer_account) sur l’ID de l’objet `Account` configuré pour le client, soit [customer](https://docs.stripe.com/api.md#create_payment_intent-customer) sur l’ID de l’objet `Customer`. #### Accounts v2 ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=usd \ -d "automatic_payment_methods[enabled]=true" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d payment_method={{PAYMENT_METHOD_ID}} \ --data-urlencode "return_url=https://example.com/order/123/complete" \ -d off_session=true \ -d confirm=true ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=usd \ -d "automatic_payment_methods[enabled]=true" \ -d "customer={{CUSTOMER_ID}}" \ -d payment_method={{PAYMENT_METHOD_ID}} \ --data-urlencode "return_url=https://example.com/order/123/complete" \ -d off_session=true \ -d confirm=true ``` ## Tester l'intégration #### Cartes bancaires | Numéro de carte | Scénario | Méthode de test | | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 4242424242424242 | Le paiement par carte bancaire aboutit et ne nécessite pas d’authentification. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 4000002500003155 | Le paiement par carte bancaire requiert une *authentification* (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). | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 4000000000009995 | La carte est refusée avec un code de refus de type `insufficient_funds`. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 6205500000000000004 | La carte UnionPay a un numéro d’une longueur variable, allant de 13 à 19 chiffres. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | #### Virements avec redirection bancaire | Moyen de paiement | Scénario | Méthode de test | | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Bancontact, iDEAL | Votre client ne parvient pas à s’authentifier sur la page de redirection en utilisant un moyen de paiement avec redirection et à notification immédiate. | Choisissez un moyen de paiement avec redirection, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Faire échouer le paiement test** sur la page qui s’affiche. | | Pay by Bank | Le montant dû est réglé via un moyen de paiement avec redirection et à [notification différée](https://docs.stripe.com/payments/payment-methods.md#payment-notification). | Choisissez le moyen de paiement, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Finaliser le paiement test** sur la page qui s’affiche. | | Pay by Bank | Votre client ne parvient pas à s’authentifier sur la page de redirection en utilisant un moyen de paiement avec redirection et à notification différée. | Choisissez le moyen de paiement, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Faire échouer le paiement test** sur la page qui s’affiche. | | BLIK | Les paiements BLIK échouent de diverses manières : échecs immédiats (par exemple, code expiré ou non valide), erreurs différées (refus de la banque) ou expirations du délai (le client n’a pas répondu à temps). | Utiliser des modèles d’e-mail pour [simuler les différents échecs.](https://docs.stripe.com/payments/blik/accept-a-payment.md#simulate-failures) | #### Prélèvements bancaires | Moyen de paiement | Scénario | Méthode de test | | ---------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Prélèvement automatique SEPA | Le montant dû est réglé par prélèvement automatique SEPA. | Remplissez le formulaire à l’aide du numéro de compte `AT321904300235473204`. Le PaymentIntent confirmé passe d’abord à l’état processing, puis à l’état succeeded trois minutes plus tard. | | Prélèvement automatique SEPA | L’intention de paiement de votre client passe de l’état `processing` à l’état `requires_payment_method`. | Remplissez le formulaire à l’aide du numéro de compte `AT861904300235473202`. | Consultez la section consacrée aux [tests](https://docs.stripe.com/testing.md) pour obtenir des informations supplémentaires sur la manière de tester votre intégration. ## Activer la numérisation de carte Pour activer la numérisation des cartes pour iOS, définissez le paramètre `NSCameraUsageDescription` (**Confidentialité – Description de l’utilisation de l’appareil photo**) dans le fichier `Info.plist` de votre application et indiquez le motif d’accès à l’appareil photo (« pour numériser des cartes », par exemple). ## Optional: Activer les cartes sauvegardées [Côté serveur] [Côté client] `EmbeddedPaymentElement` peut permettre au client d’enregistrer sa carte bancaire et peut inclure les cartes bancaires enregistrées du client dans les moyens de paiement disponibles. Le client doit avoir un objet [Compte](https://docs.stripe.com/api/v2/core/accounts/create.md#v2_create_accounts-configuration-customer) configuré par le client ou un objet [Client](https://docs.stripe.com/api/customers/create.md) sur votre serveur. Pour activer une case à cocher qui permet au client denregistrer sa carte bancaire, créez une [CustomerSession](https://docs.stripe.com/api/customer_sessions.md), avec `payment_method_save` défini sur `enabled`. #### Comptes v2 ```javascript const stripe = require('stripe')('sk_test_your_secret_key'); app.post('/mobile-payment-element', async (req, res) => { // Use an existing Account ID if this is a returning customer. const customer_account = await stripe.v2.core.accounts.create(); const customerSession = await stripe.customerSessions.create({ customer_account: customer_account.id, components: { mobile_payment_element: { enabled: true, features: { payment_method_save: 'enabled', payment_method_redisplay: 'enabled', payment_method_remove: 'enabled' } }, }, }); res.json({ customerSessionClientSecret: customerSession.client_secret, customer_account: customer_account.id, }); }); ``` Ensuite, configurez EmbeddedPaymentElement avec l’ID du client et la clé secrète du client de la CustomerSession. #### UIKit ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet var configuration = EmbeddedPaymentElement.Configuration() configuration.customer = .init(id: customerAccountId, customerSessionClientSecret: customerSessionClientSecret) self.embeddedPaymentElement = try await EmbeddedPaymentElement.create(..., configuration: configuration) ``` #### SwiftUI ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet var configuration = EmbeddedPaymentElement.Configuration() configuration.customer = .init(id: customerAccountId, customerSessionClientSecret: customerSessionClientSecret) try await embeddedViewModel.load(..., configuration: configuration) ``` #### Clients v1 ```javascript const stripe = require('stripe')('sk_test_your_secret_key'); app.post('/mobile-payment-element', async (req, res) => { // Use an existing Customer ID if this is a returning customer. const customer = await stripe.customers.create(); const customerSession = await stripe.customerSessions.create({ customer: customer.id, components: { mobile_payment_element: { enabled: true, features: { payment_method_save: 'enabled', payment_method_redisplay: 'enabled', payment_method_remove: 'enabled' } }, }, }); res.json({ customerSessionClientSecret: customerSession.client_secret, customer: customer.id, }); }); ``` Ensuite, configurez EmbeddedPaymentElement avec l’ID du client et la clé secrète du client de la CustomerSession. #### UIKit ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet var configuration = EmbeddedPaymentElement.Configuration() configuration.customer = .init(id: customerId, customerSessionClientSecret: customerSessionClientSecret) self.embeddedPaymentElement = try await EmbeddedPaymentElement.create(..., configuration: configuration) ``` #### SwiftUI ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet var configuration = EmbeddedPaymentElement.Configuration() configuration.customer = .init(id: customerId, customerSessionClientSecret: customerSessionClientSecret) try await embeddedViewModel.load(..., configuration: configuration) ``` ## Optional: Autoriser les moyens de paiement à notification différée [Côté client] Les *moyens de paiement différés* (A payment method that can't immediately return payment status when a customer attempts a transaction (for example, ACH debits). Businesses commonly hold an order in a pending state until payment is successful with these payment methods) ne garantissent pas non plus que vous recevrez les fonds de votre client à la fin du paiement, à cause du délai de versement (par exemple, comptes bancaires aux États-Unis, prélèvements SEPA, iDEAL et Bancontact) ou parce qu’ils nécessitent une intervention du client (par exemple, OXXO, Konbini et Boleto). Par défaut, EmbeddedPaymentElement n’affiche pas les moyens de paiement différés. Pour vous inscrire, définissez `allowsDelayedPaymentMethods` sur true dans votre `EmbeddedPaymentElement.Configuration`. Cette étape ne suffit pas à activer des moyens de paiement spécifiques, elle permet simplement d’indiquer que votre application est capable de les gérer. Par exemple, bien qu’OXXO ne soit actuellement pas pris en charge par EmbeddedPaymentElement, s’il devient pris en charge et que vous avez installé la dernière version du SDK, votre application pourra afficher OXXO comme moyen de paiement sans modification supplémentaire de l’intégration. #### UIKit ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.allowsDelayedPaymentMethods = true self.embeddedPaymentElement = try await EmbeddedPaymentElement.create(..., configuration: configuration) ``` #### SwiftUI ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.allowsDelayedPaymentMethods = true try await embeddedViewModel.load(..., configuration: configuration) ``` Si le client utilise avec succès l’un de ces moyens de paiement différé dans EmbeddedPaymentElement, le résultat du paiement renvoyé est `.completed`. ## Optional: Activer Apple Pay > Si votre écran de paiement comporte un bouton **Apple Pay** dédié, suivez le [guide Apple Pay](https://docs.stripe.com/apple-pay.md#present-payment-sheet) et utilisez `ApplePayContext` pour encaisser le paiement à partir de votre bouton **Apple Pay**. Vous pouvez utiliser `EmbeddedPaymentElement` pour gérer d’autres types de moyens de paiement. ### Demander un ID de marchand Apple Pour obtenir un ID de marchand Apple, [demandez un nouvel identifiant](https://developer.apple.com/account/resources/identifiers/add/merchant) sur le site Web Apple Developer. Renseignez le formulaire en indiquant une description et un identifiant. La description n’est destinée qu’à votre propre information et vous pourrez la modifier ultérieurement au besoin. En ce qui concerne l’identifiant, Stripe vous recommande d’utiliser le nom de votre application (par exemple, `merchant.com.{{YOUR_APP_NAME}}`). ### Créer un certificat Apple Pay Créez un certificat permettant à votre application de chiffrer les données de paiement. Accédez aux [paramètres des certificats iOS](https://dashboard.stripe.com/settings/ios_certificates) dans le Dashboard, cliquez sur **Ajouter une nouvelle application** et suivez le guide. Téléchargez un fichier CSR (Certificate Signing Request) pour obtenir d’Apple un certificat sécurisé vous autorisant à utiliser Apple Pay. Un fichier CSR peut émettre exactement un certificat. Si vous changez d’ID de marchand Apple, vous devez accéder aux [paramètres des certificats iOS](https://dashboard.stripe.com/settings/ios_certificates) dans le Dashboard pour obtenir un nouveau fichier CSR et un nouveau certificat. ### Réaliser une intégration avec Xcode Ajoutez la fonctionnalité Apple Pay à votre application. Dans Xcode, ouvrez vos paramètres de projet, cliquez sur l’onglet **Signature et fonctionnalités**, puis ajoutez **Apple Pay**. Vous serez peut-être alors invité(e) à vous connecter à votre compte développeur. Sélectionnez l’ID du marchand créé plus tôt. Il est désormais possible d’utiliser Apple Pay sur votre application. ![](https://b.stripecdn.com/docs-statics-srv/assets/xcode.a701d4c1922d19985e9c614a6f105bf1.png) Activez la fonctionnalité Apple Pay dans Xcode ### Ajouter Apple Pay #### Paiement ponctuel Pour ajouter Apple Pay à EmbeddedPaymentElement, configurez [applePay](https://github.com/stripe/stripe-ios/blob/8be959abc141e360080efa88980afb325737a935/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L28) après avoir initialisé `EmbeddedPaymentElement.Configuration` avec votre ID de marchand Apple et le [code pays](https://dashboard.stripe.com/settings/account) de votre entreprise. #### iOS (Swift) ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.applePay = .init( merchantId: "merchant.com.your_app_name", merchantCountryCode: "US" ) ``` #### Paiements récurrents Pour ajouter Apple Pay à EmbeddedPaymentElement, configurez [applePay](https://github.com/stripe/stripe-ios/blob/8be959abc141e360080efa88980afb325737a935/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L28) après avoir initialisé `EmbeddedPaymentElement.Configuration` avec votre ID de marchand Apple et le [code pays](https://dashboard.stripe.com/settings/account) de votre entreprise. Conformément aux [directives d’Apple](https://developer.apple.com/design/human-interface-guidelines/apple-pay#Supporting-subscriptions) pour les paiements récurrents, vous devez également définir des attributs supplémentaires sur la `PKPaymentRequest`. Ajoutez un gestionnaire dans [ApplePayConfiguration.paymentRequestHandlers](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/applepayconfiguration/handlers/paymentrequesthandler) pour configurer les [PKPaymentRequest.paymentSummaryItems](https://developer.apple.com/documentation/passkit/pkpaymentrequest/1619231-paymentsummaryitems) avec le montant que vous avez l’intention de facturer (par exemple, 9,95 USD par mois). Vous pouvez également adopter des [tokens de marchand](https://developer.apple.com/apple-pay/merchant-tokens/) en définissant les propriétés `recurringPaymentRequest` ou `automaticReloadPaymentRequest` dans `PKPaymentRequest`. Pour en savoir plus sur l’utilisation des paiements récurrents avec Apple Pay, consultez la [documentation d’Apple sur PassKit](https://developer.apple.com/documentation/passkit/pkpaymentrequest). #### iOS (Swift) ```swift let customHandlers = EmbeddedPaymentElement.ApplePayConfiguration.Handlers( paymentRequestHandler: { request in // PKRecurringPaymentSummaryItem is available on iOS 15 or later if #available(iOS 15.0, *) { let billing = PKRecurringPaymentSummaryItem(label: "My Subscription", amount: NSDecimalNumber(string: "59.99")) // Payment starts today billing.startDate = Date() // Payment ends in one year billing.endDate = Date().addingTimeInterval(60 * 60 * 24 * 365) // Pay once a month. billing.intervalUnit = .month billing.intervalCount = 1 // recurringPaymentRequest is only available on iOS 16 or later if #available(iOS 16.0, *) { request.recurringPaymentRequest = PKRecurringPaymentRequest(paymentDescription: "Recurring", regularBilling: billing, managementURL: URL(string: "https://my-backend.example.com/customer-portal")!) request.recurringPaymentRequest?.billingAgreement = "You'll be billed $59.99 every month for the next 12 months. To cancel at any time, go to Account and click 'Cancel Membership.'" } request.paymentSummaryItems = [billing] request.currencyCode = "USD" } else { // On older iOS versions, set alternative summary items. request.paymentSummaryItems = [PKPaymentSummaryItem(label: "Monthly plan starting July 1, 2022", amount: NSDecimalNumber(string: "59.99"), type: .final)] } return request } ) var configuration = EmbeddedPaymentElement.Configuration() configuration.applePay = .init(merchantId: "merchant.com.your_app_name", merchantCountryCode: "US", customHandlers: customHandlers) ``` ### Suivi des commandes Pour ajouter des informations de [suivi de commande](https://developer.apple.com/design/human-interface-guidelines/technologies/wallet/designing-order-tracking) dans iOS 16 ou version ultérieure, configurez un [authorizationResultHandler](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/applepayconfiguration/handlers/authorizationresulthandler) dans votre `PaymentSheet.ApplePayConfiguration.Handlers`. Stripe effectue un appel vers votre implémentation une fois le paiement effectué, mais avant qu’iOS ne ferme la fiche Apple Pay. Dans votre déploiement `authorizationResultHandler`, récupérez les détails de la commande finalisée sur votre serveur. Ajoutez ces informations au [PKPaymentAuthorizationResult](https://developer.apple.com/documentation/passkit/pkpaymentauthorizationresult) spécifié, et renvoyez le résultat modifié. Pour en savoir plus sur le suivi des commandes, consultez la [documentation d’Apple sur les commandes Wallet](https://developer.apple.com/documentation/walletorders). #### iOS (Swift) ```swift let customHandlers = PaymentSheet.ApplePayConfiguration.Handlers( authorizationResultHandler: { result in do { // Fetch the order details from your service let myOrderDetails = try await MyAPIClient.shared.fetchOrderDetails(orderID: orderID) result.orderDetails = PKPaymentOrderDetails( orderTypeIdentifier: myOrderDetails.orderTypeIdentifier, // "com.myapp.order" orderIdentifier: myOrderDetails.orderIdentifier, // "ABC123-AAAA-1111" webServiceURL: myOrderDetails.webServiceURL, // "https://my-backend.example.com/apple-order-tracking-backend" authenticationToken: myOrderDetails.authenticationToken) // "abc123" // Return your modified PKPaymentAuthorizationResult return result } catch { return PKPaymentAuthorizationResult(status: .failure, errors: [error]) } } ) var configuration = EmbeddedPaymentElement.Configuration() configuration.applePay = .init(merchantId: "merchant.com.your_app_name", merchantCountryCode: "US", customHandlers: customHandlers) ``` ## Optional: Personnaliser l’élément Toute personnalisation est configurée au moyen de l’objet [EmbeddedPaymentElement.Configuration](https://github.com/stripe/stripe-ios/blob/8be959abc141e360080efa88980afb325737a935/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L12). ### Apparence Personnalisez les couleurs, les polices et plus encore afin de vous adapter à l’apparence de votre application à l’aide de l’[API Appearance](https://docs.stripe.com/elements/appearance-api/embedded-mobile.md?platform=ios). ### Recueillir les adresses des utilisateurs Recueillez les adresses de livraison ou de facturation de vos clients locaux et internationaux à l’aide du composant [Address Element](https://docs.stripe.com/elements/address-element.md?platform=ios). ### Nom d’affichage du marchand Précisez un nom d’entreprise pour le client en définissant [merchantDisplayName](https://github.com/stripe/stripe-ios/blob/8be959abc141e360080efa88980afb325737a935/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L66). Par défaut, il s’agit du nom de votre application. #### Swift ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.merchantDisplayName = "My app, Inc." ``` ### Mode sombre `EmbeddedPaymentElement` s’ajuste automatiquement en fonction des paramètres d’affichage du système de l’utilisateur (mode clair et sombre). Si votre application ne prend pas en charge le mode sombre, vous pouvez définir le [style](https://github.com/stripe/stripe-ios/blob/8be959abc141e360080efa88980afb325737a935/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L51) sur le mode `alwaysLight` ou `alwaysDark`. ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.style = .alwaysLight ``` # Accepter un paiement et enregistrer le moyen de paiement > This is a Accepter un paiement et enregistrer le moyen de paiement for when platform is ios and type is paymentsfu. View the full page at https://docs.stripe.com/payments/mobile/accept-payment-embedded?platform=ios&type=paymentsfu. Utilisez l’[API Payment Intents](https://docs.stripe.com/api/payment_intents.md) pour enregistrer des informations de paiement à partir d’un achat. Il existe plusieurs cas d’utilisation : - Débiter un client pour une commande en ligne et sauvegarder les détails pour des achats ultérieurs. - Initier le premier paiement d’une série de paiements récurrents. - Débiter un acompte et sauvegarder les détails pour facturer plus tard le montant total. > #### Transactions avec présentation de la carte > > Les transactions avec présentation de la carte, telles que les paiements via Stripe Terminal, utilisent un processus différent pour enregistrer le moyen de paiement. Pour en savoir plus, consultez [la documentation de Terminal](https://docs.stripe.com/terminal/features/saving-payment-details/save-after-payment.md). ## Conformité Vous êtes responsable du respect de l’ensemble des lois, réglementations et règles des réseaux applicables lorsque vous enregistrez les informations de paiement d’un client pour une utilisation ultérieure, par exemple lorsque vous affichez son moyen de paiement dans le tunnel de paiement pour un achat futur ou lorsque vous le débitez alors qu’il n’utilise pas activement votre site web ou votre application. Avant d’enregistrer ou de débiter le moyen de paiement d’un client, assurez-vous de : - Ajouter des conditions d’utilisation à votre site web ou à votre application indiquant comment vous prévoyez d’enregistrer les informations relatives aux moyens de paiement, par exemple : - Le consentement du client vous autorisant à initier un paiement ou une série de paiements en son nom pour des transactions spécifiées. - Le calendrier et la fréquence prévus des paiements (par exemple, si les paiements concernent des versements échelonnés, des paiements d’abonnement ou des recharges non programmées). - La façon dont vous déterminez le montant du paiement. - Votre politique d’annulation, si le moyen de paiement est utilisé dans le cadre d’un abonnement - Utiliser un moyen de paiement enregistré uniquement dans le but indiqué dans vos conditions. - Recueillez le consentement explicite du client pour cet usage spécifique. Par exemple, incluez une case à cocher « Enregistrer mon moyen de paiement pour une utilisation ultérieure ». - Conserver une trace écrite de l’acceptation de vos conditions par le client. ## Configurer Stripe [Côté serveur] [Côté client] ### Côté serveur Cette intégration exige que votre serveur dispose de endpoints qui communiquent avec l’API Stripe. Utilisez nos bibliothèques officielles pour accéder à l’API Stripe depuis votre serveur : #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ### Côté client Le [SDK iOS de Stripe](https://github.com/stripe/stripe-ios) est disponible en open source et [fait l’objet d’une documentation complète](https://stripe.dev/stripe-ios/index.html). Il est également compatible avec les applications prenant en charge iOS 13 et les versions ultérieures. #### Swift Package Manager Pour installer le SDK, veuillez suivre les étapes ci-dessous : 1. Dans Xcode, sélectionnez **File** > **Add Package Dependencies…** puis saisissez `https://github.com/stripe/stripe-ios-spm` en tant qu’URL du référentiel. 1. Sélectionnez le dernier numéro de version, visible sur notre [page des versions](https://github.com/stripe/stripe-ios/releases). 1. Ajoutez le produit **StripePaymentSheet** à la [cible de votre application](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app). #### CocoaPods 1. Si vous ne l’avez pas encore fait, installez la version la plus récente de [CocoaPods](https://guides.cocoapods.org/using/getting-started.html). 1. Si vous n’avez pas de fichier [Podfile](https://guides.cocoapods.org/syntax/podfile.html), exécutez la commande suivante pour en créer un : ```bash pod init ``` 1. Ajoutez cette ligne à votre `Podfile` : ```podfile pod 'StripePaymentSheet' ``` 1. Exécutez la commande suivante : ```bash pod install ``` 1. À partir de maintenant, n’oubliez pas d’utiliser le fichier .xcworkspace au lieu du fichier .xcodeproj pour ouvrir votre projet dans Xcode. 1. Pour mettre à jour ultérieurement le SDK vers la version la plus récente, il vous suffit d’exécuter : ```bash pod update StripePaymentSheet ``` #### Carthage 1. Si vous ne l’avez pas encore fait, installez la version la plus récente de [Carthage](https://github.com/Carthage/Carthage#installing-carthage). 1. Ajoutez cette ligne à votre `Cartfile` : ```cartfile github "stripe/stripe-ios" ``` 1. Suivez les [instructions d’installation de Carthage](https://github.com/Carthage/Carthage#if-youre-building-for-ios-tvos-or-watchos). Veillez à intégrer tous les cadres requis listés [ici](https://github.com/stripe/stripe-ios/tree/master/StripePaymentSheet/README.md#manual-linking). 1. Pour mettre à jour ultérieurement le SDK vers la version la plus récente, exécutez la commande suivante : ```bash carthage update stripe-ios --platform ios ``` #### Cadre manuel 1. Accédez à notre [page des versions GitHub](https://github.com/stripe/stripe-ios/releases/latest), puis téléchargez et décompressez **Stripe.xcframework.zip**. 1. Faites glisser **StripePaymentSheet.xcframework** vers la section **Embedded Binaries (Fichiers binaires incorporés)** des paramètres **General (Général)** de votre projet Xcode. Veillez à sélectionner **Copy items if needed (Copier les éléments si nécessaire)**. 1. Répétez l’étape 2 pour tous les cadres requis listés [ici](https://github.com/stripe/stripe-ios/tree/master/StripePaymentSheet/README.md#manual-linking). 1. À l’avenir, pour mettre à jour vers la version la plus récente de notre SDK, répétez les étapes 1 à 3. > Pour obtenir de plus amples informations sur la version la plus récente du SDK et ses versions antérieures, consultez la page des [versions](https://github.com/stripe/stripe-ios/releases) sur GitHub. Pour recevoir une notification lors de la publication d’une nouvelle version, [surveillez les versions](https://help.github.com/en/articles/watching-and-unwatching-releases-for-a-repository#watching-releases-for-a-repository) à partir du référentiel. Vous devez également définir votre [clé publique](https://dashboard.stripe.com/apikeys) pour que le SDK puisse effectuer des appels à l’API Stripe. Pour commencer, vous pouvez coder en dur la clé publique côté client pendant l’intégration, mais la récupérer sur votre serveur en mode production. ```swift // Set your publishable key: remember to change this to your live publishable key in production // See your keys here: https://dashboard.stripe.com/apikeys STPAPIClient.shared.publishableKey = "<>" ``` ## Activer des moyens de paiement Affichez vos [paramètres des moyens de paiement](https://dashboard.stripe.com/settings/payment_methods) et activez les moyens de paiement que vous souhaitez prendre en charge. Vous devez activer au moins un moyen de paiement pour créer un *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods). Par défaut, Stripe active les cartes bancaires et les autres moyens de paiement courants qui peuvent vous permettre d’atteindre davantage de clients. Nous vous recommandons toutefois d’activer d’autres moyens de paiement pertinents pour votre entreprise et vos clients. Consultez la page [Prise en charge des moyens de paiement](https://docs.stripe.com/payments/payment-methods/payment-method-support.md) pour en savoir plus sur la prise en charge des produits et des moyens de paiement, et notre [page des tarifs](https://stripe.com/pricing/local-payment-methods) pour prendre connaissance des frais que nous appliquons. ## Créer un client [Côté serveur] Pour configurer un moyen de paiement pour des paiements futurs, vous devez l’associer à un objet représentant votre client. Lorsque votre client crée un compte ou effectue sa première transaction avec votre entreprise, créez un objet [Customer](https://docs.stripe.com/api/customers/create.md). ```curl curl -X POST https://api.stripe.com/v1/customers \ -u "<>:" ``` ## Collecter les informations de paiement [Côté client] Le composant Embedded Mobile Payment Element est conçu pour être placé sur la page de paiement de votre application mobile native. L’élément affiche une liste de moyens de paiement que vous pouvez personnaliser pour l’adapter à l’apparence de votre application. Lorsque le client appuie sur la ligne **Carte bancaire**, un formulaire s’ouvre dans lequel il peut saisir les informations de son moyen de paiement. Par défaut, le bouton du formulaire indique **Continuer** et déclenche la fermeture du formulaire, ce qui permet à votre client de finaliser le paiement dans votre système de paiement. ![Payment Element](https://b.stripecdn.com/docs-statics-srv/assets/ios-embedded.b5867c116d537ffcb920dd80ebdfc741.png) Vous pouvez également configurer le bouton pour qu’il termine immédiatement le processus de paiement au lieu de continuer. Pour ce faire, effectuez [cette étape](https://docs.stripe.com/payments/mobile/accept-payment-embedded.md#embedded-let-customer-pay-immediately) après avoir suivi le guide. #### UIKit ### Initialiser le Payment Element Appelez `create` pour instancier EmbeddedPaymentElement avec un `EmbeddedPaymentElement.Configuration` et un [PaymentSheet.IntentConfiguration](https://github.com/stripe/stripe-ios/blob/master/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetIntentConfiguration.swift). L’objet Configuration contient des options de configuration générales pour EmbeddedPaymentElement qui ne changent pas entre les paiements, comme `returnURL`. L’objet `IntentConfiguration` contient des détails sur le paiement spécifique, comme le montant et la devise, ainsi qu’un rappel `confirmationTokenConfirmHandler`. Pour l’instant, laissez son implémentation vide. Une fois l’initialisation réussie, définissez les paramètres `presentingViewController` et `delegate`. > Pour enregistrer des moyens de paiement dans l’EmbeddedPaymentElement, configurez `setupFutureUsage`. Vous pouvez définir le paramètre [setupFutureUsage](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-setup_future_usage) de `IntentConfiguration` sur `onSession` ou `offSession`. Cette valeur est automatiquement appliquée à tous les moyens de paiement disponibles. ```swift import StripePaymentSheet class MyCheckoutVC: UIViewController { func createEmbeddedPaymentElement() async throws -> EmbeddedPaymentElement { let intentConfig = PaymentSheet.IntentConfiguration( mode: .payment(amount: 1099, currency: "USD", setupFutureUsage: .offSession) ) { [weak self] confirmationToken in return await self?.handleConfirmationToken(confirmationToken) } var configuration = EmbeddedPaymentElement.Configuration() configuration.returnURL = "your-app://stripe-redirect" // Use the return url you set up in the previous step let embeddedPaymentElement = try await EmbeddedPaymentElement.create(intentConfiguration: intentConfig, configuration: configuration) embeddedPaymentElement.presentingViewController = self embeddedPaymentElement.delegate = self return embeddedPaymentElement } func handleConfirmationToken(_ confirmationToken: STPConfirmationToken) async throws -> String { // You'll implement this in the "Confirm the payment" section below } } ``` ### Ajouter la vue Payment Element Une fois que le EmbeddedPaymentElement est initialisé avec succès, intégrez sa vue dans votre interface de paiement. > La vue doit être placée dans une vue défilable, comme UIScrollView, car elle n’a pas de taille fixe et peut changer de hauteur après son rendu initial. ```swift class MyCheckoutVC: UIViewController { // ... private(set) var embeddedPaymentElement: EmbeddedPaymentElement? private lazy var checkoutButton: UIButton = { let checkoutButton = UIButton(type: .system) checkoutButton.backgroundColor = .systemBlue checkoutButton.layer.cornerRadius = 5.0 checkoutButton.clipsToBounds = true checkoutButton.setTitle("Checkout", for: .normal) checkoutButton.setTitleColor(.white, for: .normal) checkoutButton.translatesAutoresizingMaskIntoConstraints = false checkoutButton.isEnabled = embeddedPaymentElement?.paymentOption != nil checkoutButton.addTarget(self, action: #selector(didTapConfirmButton), for: .touchUpInside) return checkoutButton }() // ... @objc func didTapConfirmButton() { // You'll implement this in the "Confirm the payment" section below } override func viewDidLoad() { super.viewDidLoad() Task { @MainActor in do { // Create a UIScrollView let scrollView = UIScrollView() scrollView.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(scrollView) // Create the Payment Element let embeddedPaymentElement = try await createEmbeddedPaymentElement() embeddedPaymentElement.delegate = self embeddedPaymentElement.presentingViewController = self self.embeddedPaymentElement = embeddedPaymentElement // Add its view to the scroll view scrollView.addSubview(embeddedPaymentElement.view) // Add your own checkout button to the scroll view scrollView.addSubview(checkoutButton) // Set up layout constraints embeddedPaymentElement.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), embeddedPaymentElement.view.topAnchor.constraint(equalTo: scrollView.topAnchor), embeddedPaymentElement.view.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor), embeddedPaymentElement.view.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor), checkoutButton.topAnchor.constraint(equalTo: embeddedPaymentElement.view.bottomAnchor, constant: 4.0), checkoutButton.leadingAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.leadingAnchor, constant: 4.0), checkoutButton.trailingAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.trailingAnchor, constant: -4.0), ]) } catch { // Handle view not being added to view } } } } ``` À ce stade, vous pouvez exécuter votre application et voir le composant Embedded Mobile Payment Element. ### Gérer les changements de hauteur La vue de l’élément EmbeddedPaymentElement peut augmenter ou diminuer en taille, ce qui peut avoir un impact sur la disposition de la vue. Gérez les changements de hauteur en implémentant la méthode déléguée `embeddedPaymentElementDidUpdateHeight`. La vue d’EmbeddedPaymentElement appelle cette méthode à l’intérieur d’un bloc d’animation qui met à jour sa hauteur. Votre implémentation doit appeler `setNeedsLayout()` et `layoutIfNeeded()` sur la vue de défilement qui contient la vue de l’EmbeddedPaymentElement pour permettre une animation fluide du changement de hauteur. ```swift extension MyCheckoutVC: EmbeddedPaymentElementDelegate { func embeddedPaymentElementDidUpdateHeight(embeddedPaymentElement: StripePaymentSheet.EmbeddedPaymentElement) { // Handle layout appropriately self.view.setNeedsLayout() self.view.layoutIfNeeded() } } ``` Nous vous recommandons de tester que votre vue réagit correctement aux changements de hauteur. Pour ce faire, appelez `testHeightChange()` sur EmbeddedPaymentElement afin de simuler l’affichage et le masquage d’un mandat dans le composant. Assurez-vous qu’après l’appel de `testHeightChange()`, votre vue de défilement s’ajuste correctement. ```swift class MyCheckoutVC: UIViewController { override func viewDidLoad() { // This is only for testing purposes: #if DEBUG Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { [weak self] _ in Task { @MainActor in self?.embeddedPaymentElement?.testHeightChange() } } #endif } } ``` ### (Facultatif) Afficher l’option de paiement sélectionnée Si vous avez besoin d’accéder aux détails de l’option de paiement sélectionnée par le client, comme une étiquette (par exemple, « ····4242 »), une image (par exemple, un logo VISA) ou des détails de facturation à afficher dans votre interface utilisateur, utilisez la propriété `paymentOption` de EmbeddedPaymentElement. Pour recevoir une notification à chaque modification de `paymentOption`, implémentez la méthode déléguée `embeddedPaymentElementDidUpdatePaymentOption`. ```swift extension MyCheckoutVC: EmbeddedPaymentElementDelegate { func embeddedPaymentElementDidUpdatePaymentOption(embeddedPaymentElement: EmbeddedPaymentElement) { print("The payment option changed: \(embeddedPaymentElement.paymentOption)") checkoutButton.isEnabled = embeddedPaymentElement.paymentOption != nil } } ``` ### (Facultatif) Mettre à jour les informations de paiement Lorsque le client effectue des actions qui modifient les informations de paiement (par exemple avec l’application d’un code de réduction), mettez à jour l’instance `EmbeddedPaymentElement` de manière à refléter les nouvelles valeurs en appelant la méthode `update`. Certains moyens de paiement, comme Apple Pay et Google Pay, affichent le montant dans l’interface utilisateur, alors assurez-vous qu’il est toujours exact et à jour. Une fois l’appel de modification terminé, mettez à jour votre interface utilisateur. L’appel de modification peut mettre à jour l’option de paiement sélectionnée par le client. ```swift extension MyCheckoutVC { func update() { Task { @MainActor in var updatedIntentConfig = oldIntentConfig // Update the amount to reflect the price after applying the discount code updatedIntentConfig.mode = PaymentSheet.IntentConfiguration.Mode.payment(amount: 999, currency: "USD", setupFutureUsage: .offSession) let result = await embeddedPaymentElement?.update(intentConfiguration: updatedIntentConfig) switch result { case .canceled, nil: // Do nothing; this happens when a subsequent `update` call cancels this one break case .failed(let error): // Display error to user in an alert, let users retry case .succeeded: // Update your UI in case the payment option changed } } } } ``` ### Confirmer le paiement Lorsque le client appuie sur le bouton de paiement, appelez `embeddedPaymentElement.confirm()` pour mener à bien le paiement. Veillez à désactiver l’interaction avec l’utilisateur lors de la confirmation. ```swift extension MyCheckoutVC { @objc func didTapConfirmButton() { Task { @MainActor in guard let embeddedPaymentElement else { return } self.view.isUserInteractionEnabled = false // Disable user interaction, show a spinner, and so on before calling confirm. let result = await embeddedPaymentElement.confirm() switch result { case .completed: // Payment completed - show a confirmation screen. case .failed(let error): self.view.isUserInteractionEnabled = true // Encountered an unrecoverable error. You can display the error to the user, log it, and so on. case .canceled: self.view.isUserInteractionEnabled = true // Customer canceled - you should probably do nothing. break } } } } ``` Ensuite, implémentez le rappel `confirmationTokenConfirmHandler` que vous avez passé précédemment à `PaymentSheet.IntentConfiguration` pour envoyer une requête à votre serveur. Votre serveur crée un PaymentIntent et renvoie sa clé secrète du client. Pour plus d’informations sur ce processus, consultez l’étape [Créer un PaymentIntent](https://docs.stripe.com/payments/mobile/accept-payment-embedded.md#submit-payment). Lorsque la requête est renvoyée, renvoyez la clé secrète du client contenue dans la réponse du serveur, ou générez une erreur. Le EmbeddedPaymentElement confirme le PaymentIntent en utilisant la clé secrète du client ou affiche le message d’erreur localisé dans son interface utilisateur (soit [errorDescription](https://developer.apple.com/documentation/foundation/localizederror/2946895-errordescription), soit [localizedDescription](https://developer.apple.com/documentation/foundation/nserror/1414418-localizeddescription)). Une fois la confirmation terminée, le EmbeddedPaymentElement n’est plus utilisable. Dirigez plutôt l’utilisateur vers un écran de reçu ou un écran similaire. ```swift extension MyCheckoutVC { func handleConfirmationToken(_ confirmationToken: STPConfirmationToken) async throws -> String { // Make a request to your own server. Pass `confirmationToken.stripeId` if using server-side confirmation, and return the client secret or throw an error. let myServerClientSecret = try await fetchIntentClientSecret(...) } } ``` #### SwiftUI ### Initialiser le Payment Element Appelez `load` pour charger l’EmbeddedPaymentElementViewModel avec un `EmbeddedPaymentElement.Configuration` et un [PaymentSheet.IntentConfiguration](https://github.com/stripe/stripe-ios/blob/master/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetIntentConfiguration.swift). L’objet Configuration contient des options de configuration générales pour EmbeddedPaymentElement qui ne changent pas entre les paiements, comme `returnURL`. L’objet `IntentConfiguration` contient des détails sur le paiement spécifique, comme le montant et la devise, ainsi qu’un rappel `confirmationTokenConfirmHandler`. Pour l’instant, laissez son implémentation vide. > Pour enregistrer des moyens de paiement dans le EmbeddedPaymentElement, configurez `setupFutureUsage`. Vous pouvez définir le paramètre [setupFutureUsage](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-setup_future_usage) sur `IntentConfiguration` à `onSession` ou `offSession`. Cette valeur s’applique automatiquement à tous les moyens de paiement disponibles. ```swift import SwiftUI import StripePaymentSheet struct MyEmbeddedCheckoutView: View { // Store an `EmbeddedPaymentElementViewModel` as a `@StateObject` @StateObject var embeddedViewModel = EmbeddedPaymentElementViewModel() var body: some View { ScrollView { // Empty scroll view for now } .task { do { if !embeddedViewModel.isLoaded { // Load the view model with your configuration try await loadEmbeddedViewModel() } } catch { // On load failure, implement retry logic (automatic retry or user-triggered through UI). } } } private func loadEmbeddedViewModel() async throws { let intentConfiguration = PaymentSheet.IntentConfiguration( mode: .payment(amount: 1099, currency: "USD", setupFutureUsage: .offSession) ) { confirmationToken in try await self.handleConfirmationToken(confirmationToken) } var configuration = EmbeddedPaymentElement.Configuration() configuration.returnURL = "your-app://stripe-redirect" // Use the return url you set up in the previous step try await embeddedViewModel.load(intentConfiguration: intentConfiguration, configuration: configuration) } func handleConfirmationToken(_ confirmationToken: STPConfirmationToken) async throws -> String { // You'll implement this in the "Confirm the payment" section below } } ``` ### Ajouter la vue Payment Element Une fois que EmbeddedPaymentElementViewModel est chargé avec succès, ajoutez EmbeddedPaymentElementView dans votre interface de paiement. > La vue doit être placée dans une vue défilable, comme ScrollView, car elle n’a pas de taille fixe et peut changer de hauteur après son rendu initial. ```swift struct MyEmbeddedCheckoutView: View { var body: some View { ScrollView { // isLoaded becomes true only after a successful call to `embeddedViewModel.load()` if embeddedViewModel.isLoaded { EmbeddedPaymentElementView(viewModel: embeddedViewModel) } } } } ``` À ce stade, vous pouvez exécuter votre application et voir le composant Embedded Mobile Payment Element. ### Gérer les changements de hauteur La EmbeddedPaymentElementView peut augmenter ou diminuer en taille, ce qui peut affecter la disposition de la vue. La EmbeddedPaymentElementView gère automatiquement ces changements lorsqu’elle se trouve à l’intérieur d’une ScrollView. Nous vous recommandons de tester que votre vue réagit correctement aux changements de hauteur. Pour ce faire, appelez `testHeightChange()` sur EmbeddedPaymentElementViewModel afin de simuler l’affichage et la disparition d’un mandat dans l’élément. Assurez-vous qu’après l’appel de `testHeightChange()`, votre ScrollView s’ajuste de manière fluide. ```swift struct MyEmbeddedCheckoutView: View { var body: some View { ScrollView { if embeddedViewModel.isLoaded { EmbeddedPaymentElementView(viewModel: embeddedViewModel) // For testing only #if DEBUG Button("Test height change") { embeddedViewModel.testHeightChange() } #endif } } } } ``` ### (Facultatif) Afficher l’option de paiement sélectionnée Si vous avez besoin d’accéder aux détails de l’option de paiement sélectionnée par le client, comme un libellé (par exemple, « ----4242 »), une image (par exemple, un logo VISA) ou des détails de facturation à afficher dans votre interface utilisateur, utilisez la propriété `paymentOption` du modèle EmbeddedPaymentElementViewModel. Lorsque le client sélectionne un moyen de paiement qui ouvre un formulaire, l’option de paiement est mise à jour après qu’il a cliqué sur **Continuer** dans le formulaire. ```swift struct MyEmbeddedCheckoutView: View { var body: some View { ScrollView { if embeddedViewModel.isLoaded { // ... // A real integration probably wouldn't show the selected payment option on the same screen as the embedded payment element. We display it as an example. if let paymentOption = embeddedViewModel.paymentOption { HStack { Image(uiImage: paymentOption.image) .resizable() .aspectRatio(contentMode: .fit) .frame(height: 30) Text(paymentOption.label) Spacer() } .padding() } } } } } ``` ### (Facultatif) Mettre à jour les informations de paiement Lorsque le client effectue des actions qui modifient les informations de paiement (par exemple, l’application d’un code de réduction), mettez à jour l’instance `EmbeddedPaymentElementViewModel` pour refléter les nouvelles valeurs en appelant la méthode `update`. Certains moyens de paiement, comme Apple Pay et Google Pay, affichent le montant dans l’interface utilisateur : assurez-vous qu’il est toujours exact et à jour. Une fois la mise à jour terminée, il est possible qu’elle ait modifié l’option de paiement sélectionnée par le client. ```swift extension MyEmbeddedCheckoutView { func update() { Task { @MainActor in var updatedIntentConfig = oldIntentConfig updatedIntentConfig.mode = PaymentSheet.IntentConfiguration.Mode.payment(amount: 999, currency: "USD", setupFutureUsage: .offSession) let result = await embeddedViewModel.update(intentConfiguration: updatedIntentConfig) switch result { case .canceled: // Do nothing; this happens when a subsequent `update` call cancels this one break case .failed(let error): // Display error to user in an alert, let users retry case .succeeded: // Update your UI in case the payment option changed } } } } ``` ### Confirmer le paiement Lorsque le client appuie sur le bouton de paiement, appelez `embeddedViewModel.confirm()` pour mener à bien le paiement. Veillez à désactiver l’interaction avec l’utilisateur lors de la confirmation. ```swift extension MyEmbeddedCheckoutView { func didTapConfirmButton() { Task { @MainActor in // Be sure to disable user interaction during confirm (not shown in this example) let result = await embeddedViewModel.confirm() switch result { case .completed: // Payment completed - show a confirmation screen. case .failed(let error): // Encountered an unrecoverable error. Re-enable user interaction, display the error to the user, log it, and so on. case .canceled: // Customer canceled - re-enable user interaction and let them try again. break } } } } ``` Ensuite, implémentez le rappel `confirmationTokenConfirmHandler` que vous avez passé précédemment à `PaymentSheet.IntentConfiguration` pour envoyer une requête à votre serveur. Votre serveur crée un PaymentIntent et renvoie sa clé secrète du client. Pour plus d’informations sur ce processus, consultez l’étape [Créer un PaymentIntent](https://docs.stripe.com/payments/mobile/accept-payment-embedded.md#submit-payment). Renvoyez la clé secrète du client de la réponse de votre serveur ou générez une erreur. Le EmbeddedPaymentElement confirme le PaymentIntent en utilisant la clé secrète du client ou affiche le message d’erreur localisé dans son interface utilisateur (soit [errorDescription](https://developer.apple.com/documentation/foundation/localizederror/2946895-errordescription), soit [localizedDescription](https://developer.apple.com/documentation/foundation/nserror/1414418-localizeddescription)). Une fois la confirmation terminée, le EmbeddedPaymentElement n’est plus utilisable. Dirigez plutôt l’utilisateur vers un écran de reçu ou un écran similaire. ```swift extension MyEmbeddedCheckoutView { func handleConfirmationToken(_ confirmationToken: STPConfirmationToken) async throws -> String { // Make a request to your own server. Pass confirmationToken.stripeId if using server-side confirmation. // Return the client secret or throw an error return try await MyAPIClient.shared.createIntent(confirmationTokenId: confirmationToken.stripeId) } } ``` ## Optional: Décocher l’option de paiement sélectionnée Si vous avez des options de paiement externes à l’EmbeddedPaymentElement, vous devrez peut-être décocher l’option de paiement sélectionnée. Pour ce faire, utilisez l’API `clearPaymentOption`. #### UIKit ```swift extension MyCheckoutVC: UIViewController { func deselectPaymentMethod() { embeddedPaymentElement?.clearPaymentOption() } } ``` #### SwiftUI ```swift @available(iOS 15.0, *) extension MyEmbeddedCheckoutView { func deselectPaymentMethod() { embeddedViewModel.clearPaymentOption() } } ``` ## Optional: Afficher vous-même le mandat Afin de garantir la conformité aux réglementations, l’Embedded Mobile Payment Element affiche les mandats et clauses de non-responsabilité par défaut. Ce texte doit être situé à proximité de votre bouton d’achat. Si nécessaire, désactivez leur affichage dans la vue et affichez-les vous-même. > Votre intégration doit afficher le texte du mandat pour être conforme. Assurez-vous que les URL dans le texte peuvent être ouvertes à l’aide d’un UITextView ou d’un élément similaire. #### UIKit ```swift var configuration = EmbeddedPaymentElement.Configuration(...) configuration.embeddedViewDisplaysMandateText = true ... let mandateTextView = UITextView() mandateTextView.attributedText = embeddedPaymentElement.paymentOption.mandateText ``` #### SwiftUI ```swift var configuration = EmbeddedPaymentElement.Configuration(...) configuration.embeddedViewDisplaysMandateText = true ... if let attributedText = embeddedViewModel.paymentOption?.mandateText { Text(AttributedString(attributedText)) } ``` ## Optional: Permettre au client de payer immédiatement dans le formulaire ![Embedded Payment Element](https://b.stripecdn.com/docs-statics-srv/assets/embedded-pay-immediate.057c691220d43158ac8000de10815ed9.png) Pour configurer le bouton dans la feuille de formulaire afin qu’il confirme immédiatement le paiement, définissez `formSheetAction` sur votre objet `EmbeddedPaymentElement.Configuration`. Le bloc de finalisation s’exécute avec le résultat du paiement après la fermeture du formulaire. L’interface utilisateur intégrée n’étant pas utilisable une fois le paiement effectué, il est préférable que votre implémentation redirige l’utilisateur vers un autre écran, par exemple un écran de reçu. ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.formSheetAction = .confirm(completion: { result in switch result { case .completed: // Payment completed. You can for example, show a confirmation screen. print("Completed") case .failed(let error): // Encountered an unrecoverable error. You can display the error to the user, log it, etc. print(error) case .canceled: // Customer canceled - you should probably do nothing. break } }) ``` ## Créer un PaymentIntent [Côté serveur] Sur votre serveur, créez a *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods) en indiquant un montant et une devise. Vous pouvez gérer les moyens de paiement depuis le [Dashboard](https://dashboard.stripe.com/settings/payment_methods). Stripe gère le l’affichage des moyens de paiement admissibles en fonction de facteurs tels que le montant de la transaction, la devise et le tunnel de paiement. Pour éviter que des clients malveillants ne choisissent eux-mêmes leurs tarifs, décidez toujours du montant à débiter côté serveur (un environnement sécurisé) plutôt que côté client. Si l’appel réussit, renvoyez la *clé secrète du client* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)) du PaymentIntent. Si l’appel échoue, [traitez l’erreur](https://docs.stripe.com/error-handling.md) et renvoyez un message d’erreur avec une courte explication à l’intention de votre client. > Vérifiez que toutes les propriétés de l’IntentConfiguration correspondent à votre PaymentIntent (par exemple, `setup_future_usage`, `amount` et `currency`). #### Ruby ```ruby require 'stripe' # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. client = Stripe::StripeClient.new('<>') post '/create-intent' do data = JSON.parse request.body.read params = { customer: ..., # The Customer ID you previously created amount: 1099, currency: 'usd', setup_future_usage: 'off_session', automatic_payment_methods: {enabled: true}, } begin intent = client.v1.payment_intents.create(params) {client_secret: intent.client_secret}.to_json rescue Stripe::StripeError => e {error: e.error.message}.to_json end end ``` ## Configurer une URL de redirection [Côté client] Le client peut quitter votre application pour s’authentifier (par exemple, dans Safari ou dans son application bancaire). Pour lui permettre de revenir automatiquement sur votre application après s’être authentifié, [configurez un schéma d’URL personnalisé](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app) et configurez votre délégué d’application pour qu’il transmette l’URL au SDK. Stripe ne prend pas en charge les [liens universels](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content). #### SceneDelegate #### Swift ```swift // This method handles opening custom URL schemes (for example, "your-app://stripe-redirect") func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { guard let url = URLContexts.first?.url else { return } let stripeHandled = StripeAPI.handleURLCallback(with: url) if (!stripeHandled) { // This was not a Stripe url – handle the URL normally as you would } } ``` #### AppDelegate #### Swift ```swift // This method handles opening custom URL schemes (for example, "your-app://stripe-redirect") func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { let stripeHandled = StripeAPI.handleURLCallback(with: url) if (stripeHandled) { return true } else { // This was not a Stripe url – handle the URL normally as you would } return false } ``` #### SwiftUI #### Swift ```swift @main struct MyApp: App { var body: some Scene { WindowGroup { Text("Hello, world!").onOpenURL { incomingURL in let stripeHandled = StripeAPI.handleURLCallback(with: incomingURL) if (!stripeHandled) { // This was not a Stripe url – handle the URL normally as you would } } } } } ``` Paramétrez également l’[URL de retour](https://github.com/stripe/stripe-ios/blob/aa3234a7fafde98c9203b6ed77e0278c04310eb0/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L70) dans votre [EmbeddedPaymentElement.Configuration](https://github.com/stripe/stripe-ios/blob/aa3234a7fafde98c9203b6ed77e0278c04310eb0/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L12) sur l’URL de votre application. ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.returnURL = "your-app://stripe-redirect" ``` ## Gérer les événements post-paiement [Côté serveur] Stripe envoie un événement [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) à l’issue du paiement. Utilisez l’[outil de webhook du Dashboard](https://dashboard.stripe.com/webhooks) ou suivez le [guide consacré aux webhooks](https://docs.stripe.com/webhooks/quickstart.md) pour recevoir ces événements et exécuter des actions, comme envoyer une confirmation de commande par e-mail à votre client, enregistrer la vente dans une base de données ou lancer un flux de livraison. Plutôt que d’attendre un rappel de votre client, écoutez ces événements. Côté client, il arrive en effet que l’utilisateur ferme la fenêtre de son navigateur ou quitte l’application avant l’exécution du rappel. Certains clients malintentionnés peuvent d’autre part tenter de manipuler la réponse. En configurant votre intégration de manière à ce qu’elle écoute les événements asynchrones, vous pourrez accepter [plusieurs types de moyens de paiement](https://stripe.com/payments/payment-methods-guide) avec une seule et même intégration. En plus de l’événement `payment_intent.succeeded`, nous vous recommandons de gérer ces autres événements lorsque vous encaissez des paiements à l’aide de l’Element Payment : | Événement | Description | Action | | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.succeeded) | Envoyé lorsqu’un client effectue un paiement avec succès. | Envoyez au client une confirmation de commande et *traitez* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected) sa commande. | | [payment_intent.processing](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.processing) | Envoyé lorsqu’un client initie un paiement, mais qu’il ne l’a pas encore finalisé. Dans la plupart des cas, cet événement est envoyé lorsque le client initie un prélèvement bancaire. Il est suivi par un événement `payment_intent.succeeded` ou `payment_intent.payment_failed`. | Envoyez au client une confirmation de commande qui indique que son paiement est en attente. Pour des marchandises dématérialisées, vous pourrez traiter la commande sans attendre que le paiement soit effectué. | | [payment_intent.payment_failed](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.payment_failed) | Envoyé lorsqu’un client effectue une tentative de paiement qui se solde par un échec. | Si un paiement passe de l’état `processing` à `payment_failed`, proposez au client de retenter le paiement. | ## Débiter ultérieurement le moyen de paiement enregistré [Côté serveur] > `bancontact` et `ideal` sont les moyens de paiement ponctuel par défaut. Lorsque vous les configurez pour une utilisation future, ils génèrent un type de moyen de paiement réutilisable `sepa_debit`. Vous devez donc utiliser la requête `sepa_debit` pour les moyens de paiement enregistrés. > #### Conformité > > Lorsque vous enregistrez les informations de paiement d’un client, vous êtes responsable du respect de l’ensemble des lois, réglementations et règles du réseau en vigueur. Lorsque vous présentez au client final des moyens de paiement précédemment utilisés en vue d’effectuer ses prochains achats, assurez-vous de lister les moyens de paiement pour lesquels vous avez obtenu le consentement du client à l’enregistrement des informations de paiement aux fins des futurs achats. Le paramètre [allow_redisplay](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-allow_redisplay) vous permet de différencier les moyens de paiement associés au client qui peuvent ou non être présentés pour les achats futurs. Pour trouver un moyen de paiement à débiter, listez les moyens de paiement associés à votre client. Cet exemple liste des cartes bancaires, mais vous pouvez lister tout [type](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-type) pris en charge. > #### Utiliser l’API Accounts v2 pour représenter les clients > > L’API Accounts v2 est généralement disponible pour les utilisateurs de Connect et en aperçu public pour les autres utilisateurs de Stripe. Si vous avez accès à l’aperçu Accounts v2, vous devez [spécifier une version d’aperçu](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning) dans votre code. > > Pour demander l’accès à l’aperçu Accounts v2, > > Dans la plupart des cas d’usage, nous vous recommandons de [modéliser vos clients en tant qu’objets Account configurés par le client](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md), plutôt que d’utiliser des objets [Customer](https://docs.stripe.com/api/customers.md). #### Accounts v2 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d type=card ``` #### Customers v1 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d type=card ``` Lorsque vous êtes prêt à débiter votre client *hors session* (A payment is described as off-session if it occurs without the direct involvement of the customer, using previously-collected payment information), utilisez l’ID du `Customer` ou de l’`Account` configuré par le client ainsi que l’ID du `PaymentMethod` pour créer un `PaymentIntent` avec le montant et la devise du paiement. Définissez quelques autres paramètres pour effectuer le paiement hors session : - Définissez [off_session](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-off_session) sur true pour indiquer que le client n’est pas dans votre tunnel de paiement et ne peut pas répondre aux demandes d’authentification. Si, pendant votre tunnel de paiement, un partenaire (tel qu’un émetteur de cartes bancaires ou une banque) demande une authentification, Stripe sollicite des exemptions en utilisant les informations client issues d’une transaction précédente *pendant en session* (A payment is described as on-session if it occurs while the customer is actively in your checkout flow and able to authenticate the payment method). Si les conditions d’exemption ne sont pas remplies, le `PaymentIntent` peut générer une erreur. - Définissez [confirm](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-confirm) sur true pour déclencher la confirmation immédiatement lors de la création du `PaymentIntent`. - Définissez [payment_method](https://docs.stripe.com/api.md#create_payment_intent-payment_method) sur l’ID du `PaymentMethod`. - Selon la manière dont vous représentez les clients dans votre intégration, définissez soit [customer_account](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer_account) sur l’ID de l’objet `Account` configuré pour le client, soit [customer](https://docs.stripe.com/api.md#create_payment_intent-customer) sur l’ID de l’objet `Customer`. #### Accounts v2 ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=usd \ -d "automatic_payment_methods[enabled]=true" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d payment_method={{PAYMENT_METHOD_ID}} \ --data-urlencode "return_url=https://example.com/order/123/complete" \ -d off_session=true \ -d confirm=true ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=usd \ -d "automatic_payment_methods[enabled]=true" \ -d "customer={{CUSTOMER_ID}}" \ -d payment_method={{PAYMENT_METHOD_ID}} \ --data-urlencode "return_url=https://example.com/order/123/complete" \ -d off_session=true \ -d confirm=true ``` ## Tester l'intégration #### Cartes bancaires | Numéro de carte | Scénario | Méthode de test | | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 4242424242424242 | Le paiement par carte bancaire aboutit et ne nécessite pas d’authentification. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 4000002500003155 | Le paiement par carte bancaire requiert une *authentification* (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). | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 4000000000009995 | La carte est refusée avec un code de refus de type `insufficient_funds`. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 6205500000000000004 | La carte UnionPay a un numéro d’une longueur variable, allant de 13 à 19 chiffres. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | #### Virements avec redirection bancaire | Moyen de paiement | Scénario | Méthode de test | | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Bancontact, iDEAL | Votre client ne parvient pas à s’authentifier sur la page de redirection en utilisant un moyen de paiement avec redirection et à notification immédiate. | Choisissez un moyen de paiement avec redirection, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Faire échouer le paiement test** sur la page qui s’affiche. | | Pay by Bank | Le montant dû est réglé via un moyen de paiement avec redirection et à [notification différée](https://docs.stripe.com/payments/payment-methods.md#payment-notification). | Choisissez le moyen de paiement, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Finaliser le paiement test** sur la page qui s’affiche. | | Pay by Bank | Votre client ne parvient pas à s’authentifier sur la page de redirection en utilisant un moyen de paiement avec redirection et à notification différée. | Choisissez le moyen de paiement, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Faire échouer le paiement test** sur la page qui s’affiche. | | BLIK | Les paiements BLIK échouent de diverses manières : échecs immédiats (par exemple, code expiré ou non valide), erreurs différées (refus de la banque) ou expirations du délai (le client n’a pas répondu à temps). | Utiliser des modèles d’e-mail pour [simuler les différents échecs.](https://docs.stripe.com/payments/blik/accept-a-payment.md#simulate-failures) | #### Prélèvements bancaires | Moyen de paiement | Scénario | Méthode de test | | ---------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Prélèvement automatique SEPA | Le montant dû est réglé par prélèvement automatique SEPA. | Remplissez le formulaire à l’aide du numéro de compte `AT321904300235473204`. Le PaymentIntent confirmé passe d’abord à l’état processing, puis à l’état succeeded trois minutes plus tard. | | Prélèvement automatique SEPA | L’intention de paiement de votre client passe de l’état `processing` à l’état `requires_payment_method`. | Remplissez le formulaire à l’aide du numéro de compte `AT861904300235473202`. | Consultez la section consacrée aux [tests](https://docs.stripe.com/testing.md) pour obtenir des informations supplémentaires sur la manière de tester votre intégration. ## Optional: Définissez SetupFutureUsage pour les moyens de paiement individuels (Preview) [Côté serveur] [Côté client] Pour plus de précision, définissez `setupFutureUsage` pour des moyens de paiement spécifiques avec [PaymentSheet.IntentConfiguration.Mode.PaymentMethodOptions](https://github.com/stripe/stripe-ios/blob/master/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentSheetIntentConfiguration.swift#L116). ```swift @_spi(PaymentMethodOptionsSetupFutureUsagePreview) import StripePaymentSheet class MyCheckoutVC: UIViewController { func createEmbeddedPaymentElement() async throws -> EmbeddedPaymentElement { let intentConfig = PaymentSheet.IntentConfiguration( mode: .payment( amount: 1099, currency: "USD",paymentMethodOptions: PaymentSheet.IntentConfiguration.Mode.PaymentMethodOptions( setupFutureUsageValues: [ .card: .offSession, .cashApp: .onSession ] ) ) ) { [weak self] confirmationToken in return try await self?.handleConfirmationToken(confirmationToken) } var configuration = EmbeddedPaymentElement.Configuration() configuration.returnURL = "your-app://stripe-redirect" // Use the return url you set up in the previous step let embeddedPaymentElement = try await EmbeddedPaymentElement.create(intentConfiguration: intentConfig, configuration: configuration) embeddedPaymentElement.presentingViewController = self embeddedPaymentElement.delegate = self return embeddedPaymentElement } } ``` En savoir plus sur [les valeurs](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-payment_method_options) `setupFutureUsage` prises en charge pour chaque moyen de paiement. Ensuite, assurez-vous que votre serveur ne définit pas `setup_future_usage` ou `payment_method_options[X][setup_future_usage]` sur la demande de PaymentIntent. Le SDK gère automatiquement la configuration en fonction de l’`IntentConfiguration`. #### Ruby ```ruby require 'stripe' # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. client = Stripe::StripeClient.new('<>') post '/create-intent' do data = JSON.parse request.body.read params = { amount: 1099, currency: 'usd', confirmation_token: data['confirmation_token'], # In the latest version of the API, specifying the `automatic_payment_methods` parameter is optional because Stripe enables its functionality by default. automatic_payment_methods: {enabled: true}, } begin intent = client.v1.payment_intents.create(params) {client_secret: intent.client_secret}.to_json rescue Stripe::StripeError => e {error: e.error.message}.to_json end end ``` ## Activer la numérisation de carte Pour activer la numérisation des cartes pour iOS, définissez le paramètre `NSCameraUsageDescription` (**Confidentialité – Description de l’utilisation de l’appareil photo**) dans le fichier `Info.plist` de votre application et indiquez le motif d’accès à l’appareil photo (« pour numériser des cartes », par exemple). ## Optional: Activer les cartes sauvegardées [Côté serveur] [Côté client] `EmbeddedPaymentElement` peut permettre au client d’enregistrer sa carte bancaire et peut inclure les cartes bancaires enregistrées du client dans les moyens de paiement disponibles. Le client doit avoir un objet [Compte](https://docs.stripe.com/api/v2/core/accounts/create.md#v2_create_accounts-configuration-customer) configuré par le client ou un objet [Client](https://docs.stripe.com/api/customers/create.md) sur votre serveur. Pour activer une case à cocher qui permet au client denregistrer sa carte bancaire, créez une [CustomerSession](https://docs.stripe.com/api/customer_sessions.md), avec `payment_method_save` défini sur `enabled`. #### Comptes v2 ```javascript const stripe = require('stripe')('sk_test_your_secret_key'); app.post('/mobile-payment-element', async (req, res) => { // Use an existing Account ID if this is a returning customer. const customer_account = await stripe.v2.core.accounts.create(); const customerSession = await stripe.customerSessions.create({ customer_account: customer_account.id, components: { mobile_payment_element: { enabled: true, features: { payment_method_save: 'enabled', payment_method_redisplay: 'enabled', payment_method_remove: 'enabled' } }, }, }); res.json({ customerSessionClientSecret: customerSession.client_secret, customer_account: customer_account.id, }); }); ``` Ensuite, configurez EmbeddedPaymentElement avec l’ID du client et la clé secrète du client de la CustomerSession. #### UIKit ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet var configuration = EmbeddedPaymentElement.Configuration() configuration.customer = .init(id: customerAccountId, customerSessionClientSecret: customerSessionClientSecret) self.embeddedPaymentElement = try await EmbeddedPaymentElement.create(..., configuration: configuration) ``` #### SwiftUI ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet var configuration = EmbeddedPaymentElement.Configuration() configuration.customer = .init(id: customerAccountId, customerSessionClientSecret: customerSessionClientSecret) try await embeddedViewModel.load(..., configuration: configuration) ``` #### Clients v1 ```javascript const stripe = require('stripe')('sk_test_your_secret_key'); app.post('/mobile-payment-element', async (req, res) => { // Use an existing Customer ID if this is a returning customer. const customer = await stripe.customers.create(); const customerSession = await stripe.customerSessions.create({ customer: customer.id, components: { mobile_payment_element: { enabled: true, features: { payment_method_save: 'enabled', payment_method_redisplay: 'enabled', payment_method_remove: 'enabled' } }, }, }); res.json({ customerSessionClientSecret: customerSession.client_secret, customer: customer.id, }); }); ``` Ensuite, configurez EmbeddedPaymentElement avec l’ID du client et la clé secrète du client de la CustomerSession. #### UIKit ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet var configuration = EmbeddedPaymentElement.Configuration() configuration.customer = .init(id: customerId, customerSessionClientSecret: customerSessionClientSecret) self.embeddedPaymentElement = try await EmbeddedPaymentElement.create(..., configuration: configuration) ``` #### SwiftUI ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet var configuration = EmbeddedPaymentElement.Configuration() configuration.customer = .init(id: customerId, customerSessionClientSecret: customerSessionClientSecret) try await embeddedViewModel.load(..., configuration: configuration) ``` ## Optional: Autoriser les moyens de paiement à notification différée [Côté client] Les *moyens de paiement différés* (A payment method that can't immediately return payment status when a customer attempts a transaction (for example, ACH debits). Businesses commonly hold an order in a pending state until payment is successful with these payment methods) ne garantissent pas non plus que vous recevrez les fonds de votre client à la fin du paiement, à cause du délai de versement (par exemple, comptes bancaires aux États-Unis, prélèvements SEPA, iDEAL et Bancontact) ou parce qu’ils nécessitent une intervention du client (par exemple, OXXO, Konbini et Boleto). Par défaut, EmbeddedPaymentElement n’affiche pas les moyens de paiement différés. Pour vous inscrire, définissez `allowsDelayedPaymentMethods` sur true dans votre `EmbeddedPaymentElement.Configuration`. Cette étape ne suffit pas à activer des moyens de paiement spécifiques, elle permet simplement d’indiquer que votre application est capable de les gérer. Par exemple, bien qu’OXXO ne soit actuellement pas pris en charge par EmbeddedPaymentElement, s’il devient pris en charge et que vous avez installé la dernière version du SDK, votre application pourra afficher OXXO comme moyen de paiement sans modification supplémentaire de l’intégration. #### UIKit ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.allowsDelayedPaymentMethods = true self.embeddedPaymentElement = try await EmbeddedPaymentElement.create(..., configuration: configuration) ``` #### SwiftUI ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.allowsDelayedPaymentMethods = true try await embeddedViewModel.load(..., configuration: configuration) ``` Si le client utilise avec succès l’un de ces moyens de paiement différé dans EmbeddedPaymentElement, le résultat du paiement renvoyé est `.completed`. ## Optional: Activer Apple Pay > Si votre écran de paiement comporte un bouton **Apple Pay** dédié, suivez le [guide Apple Pay](https://docs.stripe.com/apple-pay.md#present-payment-sheet) et utilisez `ApplePayContext` pour encaisser le paiement à partir de votre bouton **Apple Pay**. Vous pouvez utiliser `EmbeddedPaymentElement` pour gérer d’autres types de moyens de paiement. ### Demander un ID de marchand Apple Pour obtenir un ID de marchand Apple, [demandez un nouvel identifiant](https://developer.apple.com/account/resources/identifiers/add/merchant) sur le site Web Apple Developer. Renseignez le formulaire en indiquant une description et un identifiant. La description n’est destinée qu’à votre propre information et vous pourrez la modifier ultérieurement au besoin. En ce qui concerne l’identifiant, Stripe vous recommande d’utiliser le nom de votre application (par exemple, `merchant.com.{{YOUR_APP_NAME}}`). ### Créer un certificat Apple Pay Créez un certificat permettant à votre application de chiffrer les données de paiement. Accédez aux [paramètres des certificats iOS](https://dashboard.stripe.com/settings/ios_certificates) dans le Dashboard, cliquez sur **Ajouter une nouvelle application** et suivez le guide. Téléchargez un fichier CSR (Certificate Signing Request) pour obtenir d’Apple un certificat sécurisé vous autorisant à utiliser Apple Pay. Un fichier CSR peut émettre exactement un certificat. Si vous changez d’ID de marchand Apple, vous devez accéder aux [paramètres des certificats iOS](https://dashboard.stripe.com/settings/ios_certificates) dans le Dashboard pour obtenir un nouveau fichier CSR et un nouveau certificat. ### Réaliser une intégration avec Xcode Ajoutez la fonctionnalité Apple Pay à votre application. Dans Xcode, ouvrez vos paramètres de projet, cliquez sur l’onglet **Signature et fonctionnalités**, puis ajoutez **Apple Pay**. Vous serez peut-être alors invité(e) à vous connecter à votre compte développeur. Sélectionnez l’ID du marchand créé plus tôt. Il est désormais possible d’utiliser Apple Pay sur votre application. ![](https://b.stripecdn.com/docs-statics-srv/assets/xcode.a701d4c1922d19985e9c614a6f105bf1.png) Activez la fonctionnalité Apple Pay dans Xcode ### Ajouter Apple Pay #### Paiement ponctuel Pour ajouter Apple Pay à EmbeddedPaymentElement, configurez [applePay](https://github.com/stripe/stripe-ios/blob/8be959abc141e360080efa88980afb325737a935/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L28) après avoir initialisé `EmbeddedPaymentElement.Configuration` avec votre ID de marchand Apple et le [code pays](https://dashboard.stripe.com/settings/account) de votre entreprise. #### iOS (Swift) ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.applePay = .init( merchantId: "merchant.com.your_app_name", merchantCountryCode: "US" ) ``` #### Paiements récurrents Pour ajouter Apple Pay à EmbeddedPaymentElement, configurez [applePay](https://github.com/stripe/stripe-ios/blob/8be959abc141e360080efa88980afb325737a935/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L28) après avoir initialisé `EmbeddedPaymentElement.Configuration` avec votre ID de marchand Apple et le [code pays](https://dashboard.stripe.com/settings/account) de votre entreprise. Conformément aux [directives d’Apple](https://developer.apple.com/design/human-interface-guidelines/apple-pay#Supporting-subscriptions) pour les paiements récurrents, vous devez également définir des attributs supplémentaires sur la `PKPaymentRequest`. Ajoutez un gestionnaire dans [ApplePayConfiguration.paymentRequestHandlers](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/applepayconfiguration/handlers/paymentrequesthandler) pour configurer les [PKPaymentRequest.paymentSummaryItems](https://developer.apple.com/documentation/passkit/pkpaymentrequest/1619231-paymentsummaryitems) avec le montant que vous avez l’intention de facturer (par exemple, 9,95 USD par mois). Vous pouvez également adopter des [tokens de marchand](https://developer.apple.com/apple-pay/merchant-tokens/) en définissant les propriétés `recurringPaymentRequest` ou `automaticReloadPaymentRequest` dans `PKPaymentRequest`. Pour en savoir plus sur l’utilisation des paiements récurrents avec Apple Pay, consultez la [documentation d’Apple sur PassKit](https://developer.apple.com/documentation/passkit/pkpaymentrequest). #### iOS (Swift) ```swift let customHandlers = EmbeddedPaymentElement.ApplePayConfiguration.Handlers( paymentRequestHandler: { request in // PKRecurringPaymentSummaryItem is available on iOS 15 or later if #available(iOS 15.0, *) { let billing = PKRecurringPaymentSummaryItem(label: "My Subscription", amount: NSDecimalNumber(string: "59.99")) // Payment starts today billing.startDate = Date() // Payment ends in one year billing.endDate = Date().addingTimeInterval(60 * 60 * 24 * 365) // Pay once a month. billing.intervalUnit = .month billing.intervalCount = 1 // recurringPaymentRequest is only available on iOS 16 or later if #available(iOS 16.0, *) { request.recurringPaymentRequest = PKRecurringPaymentRequest(paymentDescription: "Recurring", regularBilling: billing, managementURL: URL(string: "https://my-backend.example.com/customer-portal")!) request.recurringPaymentRequest?.billingAgreement = "You'll be billed $59.99 every month for the next 12 months. To cancel at any time, go to Account and click 'Cancel Membership.'" } request.paymentSummaryItems = [billing] request.currencyCode = "USD" } else { // On older iOS versions, set alternative summary items. request.paymentSummaryItems = [PKPaymentSummaryItem(label: "Monthly plan starting July 1, 2022", amount: NSDecimalNumber(string: "59.99"), type: .final)] } return request } ) var configuration = EmbeddedPaymentElement.Configuration() configuration.applePay = .init(merchantId: "merchant.com.your_app_name", merchantCountryCode: "US", customHandlers: customHandlers) ``` ### Suivi des commandes Pour ajouter des informations de [suivi de commande](https://developer.apple.com/design/human-interface-guidelines/technologies/wallet/designing-order-tracking) dans iOS 16 ou version ultérieure, configurez un [authorizationResultHandler](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/applepayconfiguration/handlers/authorizationresulthandler) dans votre `PaymentSheet.ApplePayConfiguration.Handlers`. Stripe effectue un appel vers votre implémentation une fois le paiement effectué, mais avant qu’iOS ne ferme la fiche Apple Pay. Dans votre déploiement `authorizationResultHandler`, récupérez les détails de la commande finalisée sur votre serveur. Ajoutez ces informations au [PKPaymentAuthorizationResult](https://developer.apple.com/documentation/passkit/pkpaymentauthorizationresult) spécifié, et renvoyez le résultat modifié. Pour en savoir plus sur le suivi des commandes, consultez la [documentation d’Apple sur les commandes Wallet](https://developer.apple.com/documentation/walletorders). #### iOS (Swift) ```swift let customHandlers = PaymentSheet.ApplePayConfiguration.Handlers( authorizationResultHandler: { result in do { // Fetch the order details from your service let myOrderDetails = try await MyAPIClient.shared.fetchOrderDetails(orderID: orderID) result.orderDetails = PKPaymentOrderDetails( orderTypeIdentifier: myOrderDetails.orderTypeIdentifier, // "com.myapp.order" orderIdentifier: myOrderDetails.orderIdentifier, // "ABC123-AAAA-1111" webServiceURL: myOrderDetails.webServiceURL, // "https://my-backend.example.com/apple-order-tracking-backend" authenticationToken: myOrderDetails.authenticationToken) // "abc123" // Return your modified PKPaymentAuthorizationResult return result } catch { return PKPaymentAuthorizationResult(status: .failure, errors: [error]) } } ) var configuration = EmbeddedPaymentElement.Configuration() configuration.applePay = .init(merchantId: "merchant.com.your_app_name", merchantCountryCode: "US", customHandlers: customHandlers) ``` ## Optional: Personnaliser l’élément Toute personnalisation est configurée au moyen de l’objet [EmbeddedPaymentElement.Configuration](https://github.com/stripe/stripe-ios/blob/8be959abc141e360080efa88980afb325737a935/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L12). ### Apparence Personnalisez les couleurs, les polices et plus encore afin de vous adapter à l’apparence de votre application à l’aide de l’[API Appearance](https://docs.stripe.com/elements/appearance-api/embedded-mobile.md?platform=ios). ### Recueillir les adresses des utilisateurs Recueillez les adresses de livraison ou de facturation de vos clients locaux et internationaux à l’aide du composant [Address Element](https://docs.stripe.com/elements/address-element.md?platform=ios). ### Nom d’affichage du marchand Précisez un nom d’entreprise pour le client en définissant [merchantDisplayName](https://github.com/stripe/stripe-ios/blob/8be959abc141e360080efa88980afb325737a935/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L66). Par défaut, il s’agit du nom de votre application. #### Swift ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.merchantDisplayName = "My app, Inc." ``` ### Mode sombre `EmbeddedPaymentElement` s’ajuste automatiquement en fonction des paramètres d’affichage du système de l’utilisateur (mode clair et sombre). Si votre application ne prend pas en charge le mode sombre, vous pouvez définir le [style](https://github.com/stripe/stripe-ios/blob/8be959abc141e360080efa88980afb325737a935/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/Embedded/EmbeddedPaymentElementConfiguration.swift#L51) sur le mode `alwaysLight` ou `alwaysDark`. ```swift var configuration = EmbeddedPaymentElement.Configuration() configuration.style = .alwaysLight ``` ## Optional: Activer la collecte du CVC après confirmation Pour récupérer le CVC d’une carte bancaire enregistrée lors de la confirmation de PaymentIntent, votre intégration doit collecter les informations de paiement avant de créer un PaymentIntent. ### Mettre à jour la configuration de l’Intent `PaymentSheet.IntentConfiguration` accepte un paramètre facultatif qui contrôle le moment de récupérer le CVC pour une carte enregistrée. ```swift let intentConfig = PaymentSheet.IntentConfiguration( mode: .payment(amount: 1099, currency: "USD"), confirmHandler: { confirmationToken in // Handle ConfirmationToken...}, requireCVCRecollection: true) ``` ### Mettre à jour les paramètres de création de l’Intent Pour récupérer le CVC lors de la confirmation du paiement, ajoutez les paramètres `customerId` et `require_cvc_recollection` lors de la création du PaymentIntent. #### Ruby ```ruby require 'stripe' # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. client = Stripe::StripeClient.new('<>') post '/create-intent' do data = JSON.parse request.body.read params = { amount: 1099, currency: 'usd', automatic_payment_methods: {enabled: true},customer: customer.id, payment_method_options: { card: {require_cvc_recollection: true} } } begin intent = client.v1.payment_intents.create(params) {client_secret: intent.client_secret}.to_json rescue Stripe::StripeError => e {error: e.error.message}.to_json end end ``` # Accepter un paiement > This is a Accepter un paiement for when platform is android and type is payment. View the full page at https://docs.stripe.com/payments/mobile/accept-payment-embedded?platform=android&type=payment. Le Payment Element vous permet d’accepter plusieurs moyens de paiement à l’aide d’une seule intégration. Vous allez créer un tunnel de paiement personnalisé dans lequel vous afficherez le Payment Element, créerez le *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods) et confirmerez le paiement depuis votre application. ## Configurer Stripe [Côté serveur] [Côté client] Pour commencer, vous devez créer un compte Stripe. [Inscrivez-vous maintenant](https://dashboard.stripe.com/register). ### Côté serveur Cette intégration exige des endpoints sur votre serveur qui communiquent avec l’API Stripe. Utilisez nos bibliothèques officielles pour accéder à l’API Stripe depuis votre serveur : #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ### Côté client Le [SDK Stripe Android](https://github.com/stripe/stripe-android) est disponible en open source et [fait l’objet d’une documentation complète](https://stripe.dev/stripe-android/). Pour installer le SDK, ajoutez `stripe-android` au bloc `dependencies` de votre fichier [app/build.gradle](https://developer.android.com/studio/build/dependencies) : #### Kotlin ```kotlin plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id("org.jetbrains.kotlin.plugin.compose") } android { ... kotlinOptions { jvmTarget = "11" } buildFeatures { compose true } } dependencies { // ... // Stripe Android SDK implementation("com.stripe:stripe-android:23.8.0") // Include the financial connections SDK to support US bank account as a payment method implementation("com.stripe:financial-connections:23.8.0") } ``` > Pour obtenir de plus amples informations sur la version la plus récente du SDK et ses versions antérieures, consultez la page des [versions](https://github.com/stripe/stripe-android/releases) sur GitHub. Pour savoir quand une nouvelle version est disponible, [surveillez les versions du référentiel](https://docs.github.com/en/github/managing-subscriptions-and-notifications-on-github/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository). Vous devez également définir votre [clé publiable](https://dashboard.stripe.com/apikeys) afin que le SDK puisse effectuer des appels à l’API vers Stripe. Pour commencer rapidement, vous pouvez coder cela en dur côté client pendant l’intégration, mais récupérer la clé publiable sur votre serveur en mode production. ```kotlin // Set your publishable key: remember to change this to your live publishable key in production // See your keys here: https://dashboard.stripe.com/apikeys PaymentConfiguration.init(context, publishableKey = "<>") ``` ## Activer des moyens de paiement Affichez vos [paramètres des moyens de paiement](https://dashboard.stripe.com/settings/payment_methods) et activez les moyens de paiement que vous souhaitez prendre en charge. Vous devez activer au moins un moyen de paiement pour créer un *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods). Par défaut, Stripe active les cartes bancaires et les autres moyens de paiement courants qui peuvent vous permettre d’atteindre davantage de clients. Nous vous recommandons toutefois d’activer d’autres moyens de paiement pertinents pour votre entreprise et vos clients. Consultez la page [Prise en charge des moyens de paiement](https://docs.stripe.com/payments/payment-methods/payment-method-support.md) pour en savoir plus sur la prise en charge des produits et des moyens de paiement, et notre [page des tarifs](https://stripe.com/pricing/local-payment-methods) pour prendre connaissance des frais que nous appliquons. ## Collecter les informations de paiement [Côté client] L’Embedded Mobile Payment Element est conçu pour utilisation sur la page de paiement de votre application mobile native. L’élément affiche une liste de moyens de paiement, et vous pouvez le personnaliser pour l’adapter au visuel de votre application. Lorsque le client touche la ligne **Carte bancaire**, un formulaire s’ouvre, dans lequel il peut saisir les informations de son moyen de paiement. Le bouton dans le formulaire indique **Continuer** par défaut et entraîne la fermeture du formulaire lorsque lorsqu’il est utilisé, ce qui permet à votre client de terminer le paiement dans votre système de paiement. ![Payment Element intégré](https://b.stripecdn.com/docs-statics-srv/assets/android-embedded.1aefe2ca79ed073e350ec629a5af22d5.png) Vous avez également la possibilité de configurer le bouton pour qu’il termine immédiatement le processus de paiement au lieu de continuer. Pour ce faire, effectuez [cette étape](https://docs.stripe.com/payments/mobile/accept-payment-embedded.md#embedded-let-customer-pay-immediately) après avoir suivi le guide. ### Initialiser l’Embedded Payment Element #### Jetpack Compose Initialisez une instance de l’`EmbeddedPaymentElement` en utilisant la fonction `rememberEmbeddedPaymentElement` avec un `EmbeddedPaymentElement.Builder`. Transmettez un `CreateIntentWithConfirmationTokenCallback`. Vous pouvez laisser l’implémentation vide pour le moment, afin de préparer facilement l’intégration future des paiements. ```kotlin import com.stripe.android.paymentelement.EmbeddedPaymentElement import com.stripe.android.paymentelement.rememberEmbeddedPaymentElement @Composable fun CheckoutScreen() { val embeddedBuilder = remember { EmbeddedPaymentElement.Builder( createIntentCallback = { confirmationToken, -> TODO("You'll implement this in the "Confirm the payment" step") }, resultCallback = { result -> TODO("You'll implement this in the "Confirm the payment" step") }, ) } val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedBuilder) } ``` #### Vues (classique) Initialisez une instance de l’`EmbeddedPaymentElement` en utilisant la fonction `rememberEmbeddedPaymentElement` avec un `EmbeddedPaymentElement.Builder`. ```kotlin import com.stripe.android.paymentelement.EmbeddedPaymentElement import com.stripe.android.paymentelement.rememberEmbeddedPaymentElement @Composable fun CheckoutScreen() { val embeddedBuilder = remember { EmbeddedPaymentElement.Builder( createIntentCallback = { confirmationToken -> TODO("Completed in a later step.") }, resultCallback = { result -> TODO("Completed in a later step.") }, ) } val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedBuilder) } ``` Le Mobile Payment Element intégré est conçu pour l’interface Jetpack Compose et expose une méthode `@Composable Content`. Lors de l’utilisation de vues classiques, vous devez encapsuler le Payment Element intégré dans une `ComposeView`. ```xml ``` ```kotlin class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.checkout_screen_layout) val composeView = findViewById(R.id.compose_view) composeView.setContent { CheckoutScreen() } } } ``` ### Configurer l’Embedded Payment Element L’objet `Builder` contient les rappels nécessaires à l’instanciation de l’`EmbeddedPaymentElement`, y compris le `CreateIntentCallback`. Pour l’instant, laissez son implémentation vide. Après l’instanciation, appelez `configure` avec une `EmbeddedPaymentElement.Configuration` et une `PaymentSheet.IntentConfiguration`. L’objet `Configuration` contient les options générales pour `EmbeddedPaymentElement` qui ne changent pas entre les paiements. L’objet `IntentConfiguration` contient les détails du paiement spécifique, comme le montant et la devise. ```kotlin import com.stripe.android.paymentsheet.PaymentSheet @Composable fun CheckoutScreen() { val embeddedBuilder = .... val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedBuilder) LaunchedEffect(embeddedPaymentElement) { embeddedPaymentElement.configure( intentConfiguration = PaymentSheet.IntentConfiguration(mode = PaymentSheet.IntentConfiguration.Mode.Payment( amount = 1099, currency = "USD",),// Optional intent configuration options... ), configuration = EmbeddedPaymentElement.Configuration.Builder("Powdur").build() ) } } ``` ### Ajouter la vue Embedded Payment Element Une fois l’`EmbeddedPaymentElement` initialisé, placez son `@Composable Content` dans l’interface utilisateur de votre page de paiement. > Le contenu doit se trouver dans un conteneur déroulable, car sa hauteur peut changer après son affichage initial. ```kotlin @Composable fun CheckoutScreen() { val embeddedBuilder = .... val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedBuilder) ..... val scrollState = rememberScrollState() Column( modifier = Modifier .fillMaxSize() .verticalScroll(scrollState) .padding(16.dp) ) { embeddedPaymentElement.Content() } } ``` À ce stade, vous pouvez exécuter votre application et voir l’Embedded Mobile Payment Element. ### (Facultatif) Mettre à jour les informations de paiement Si un client modifie les détails du paiement (par exemple, en appliquant un code de réduction), mettez à jour l’instance `EmbeddedPaymentElement`. Lorsque vous appelez à nouveau la méthode `configure`, les nouvelles valeurs se synchronisent et s’affichent dans l’interface utilisateur. > Certains moyens de paiement, comme Google Pay, affichent le montant dans l’interface utilisateur. Si un client modifie le paiement et que vous ne mettez pas à jour l’élément `EmbeddedPaymentElement`, l’interface utilisateur affiche des valeurs incorrectes. Une fois l’appel à `configure` terminé, `@Composable Content` et `paymentOption` sont automatiquement mis à jour avec les nouvelles valeurs fournies lors de l’appel à `configure`. ```kotlin val intentConfiguration = PaymentSheet.IntentConfiguration( // Update the amount to reflect the price after applying the discount code mode = PaymentSheet.IntentConfiguration.Mode.Payment( amount = 999, currency = "USD", ), ) val configuration = EmbeddedPaymentElement.Configuration.Builder("Powdur") .build() LaunchedEffect(embeddedPaymentElement) { embeddedPaymentElement.configure( intentConfiguration = intentConfiguration, configuration = configuration, ) } ``` ### (Facultatif) Afficher l’option de paiement sélectionnée Vous pouvez afficher les détails de l’option de paiement (comme les 4 derniers chiffres, le logo de la carte ou les informations de facturation) en accédant à la propriété observable `Flow` de `paymentOption` dans le Payment Element intégré. Lorsqu’un client sélectionne un moyen de paiement qui ouvre un formulaire, l’option de paiement est mise à jour après qu’il ait appuyé sur **Continue** dans le formulaire. ```kotlin val selectedPaymentOption by embeddedPaymentElement.paymentOption.collectAsState() selectedPaymentOption?.let { paymentOption -> Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier .clickable( onClick = { }, ) .semantics { text = AnnotatedString(paymentOption.label) }, ) { Icon( painter = paymentOption.iconPainter, contentDescription = null, // decorative element modifier = Modifier.padding(horizontal = 4.dp), tint = Color.Unspecified, ) Text(text = paymentOption.label) } } ``` ### Confirmer le paiement Lorsque le client appuie sur le bouton de paiement, initiez le paiement en appelant `embeddedPaymentElement.confirm()`. Veillez à désactiver l’interaction avec l’utilisateur lors de la confirmation. Lorsqu’un formulaire est affiché, le `EmbeddedPaymentElement` appelle `confirm` lorsque l’utilisateur clique sur **Call to action**. Si le moyen de paiement sélectionné n’a aucun champ de formulaire, appelez `confirm` lorsque l’utilisateur clique sur **Call to action** sous le `@Composable Content`. ```kotlin Button( onClick = { embeddedPaymentElement.confirm() } ) { Text("Confirm payment") } ``` Ensuite, implémentez le rappel `createIntentCallback` que vous avez précédemment transmis à `EmbeddedPaymentElement.Builder` pour envoyer une requête à votre serveur. Votre serveur crée un `PaymentIntent` et renvoie la clé secrète du client, comme expliqué à la section [Créer un PaymentIntent](https://docs.stripe.com/payments/mobile/accept-payment-embedded.md#submit-payment). Lorsque vous recevez la requête, renvoyez le résultat de la création de l’Intent à l’aide de `CreateIntentResult` avec la clé secrète du client de la réponse de votre serveur ou une erreur. Le `EmbeddedPaymentElement` confirme le PaymentIntent en utilisant la clé secrète du client ou affiche le message d’erreur localisé dans son interface utilisateur. ```kotlin import com.stripe.android.paymentsheet.CreateIntentResult val embeddedBuilder = remember { val embeddedBuilder = EmbeddedPaymentElement.Builder( createIntentCallback = { confirmationToken ->// Make a request to your own server and receive a client secret or an error. val networkResult = ... if (networkResult.isSuccess) { CreateIntentResult.Success(networkResult.clientSecret) } else { CreateIntentResult.Failure(networkResult.exception) } }, resultCallback = { result ->when (result) { is EmbeddedPaymentElement.Result.Completed -> { // Payment completed - show a confirmation screen. } is EmbeddedPaymentElement.Result.Failed -> { // Encountered an unrecoverable error. You can display the error to the user, log it, and so on } is EmbeddedPaymentElement.Result.Canceled -> { // Customer canceled - you should probably do nothing. } } }, ) } ``` ## Optional: Décocher l’option de paiement sélectionnée Si vous avez des options de paiement externes à l’`EmbeddedPaymentElement`, vous devrez peut-être décocher l’option de paiement sélectionnée. Pour ce faire, utilisez l’API `clearPaymentOption`. ```kotlin @Composable fun CheckoutScreen() { val embeddedPaymentElementBuilder = .... val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedPaymentElementBuilder) .... Button( onClick = embeddedPaymentElement::clearPaymentOption ) { Text("Select external payment option") } } ``` ## Optional: Afficher vous-même le mandat Pour garantir la conformité réglementaire, l’Embedded Mobile Payment Element affiche les mandats et clauses de non-responsabilité par défaut. Ce texte doit être situé à proximité de votre bouton **Acheter**. Si vous désactivez l’affichage par défaut de ces éléments dans la vue, vous devez les afficher vous-même. > Pour être conforme, votre intégration doit afficher de manière appropriée le texte du mandat. Si vous l’affichez vous-même, assurez-vous que toutes les URL sont restituées correctement en incluant le texte dans un composable `Text`. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder("Merchant, Inc") .embeddedViewDisplaysMandateText(false) .build() .... val selectedPaymentOption by embeddedPaymentElement.paymentOption.collectAsState() selectedPaymentOption?.mandateText?.let { mandateText -> Text(mandateText) } ``` ## Optional: Permettre au client de payer immédiatement dans le formulaire ![Embedded Payment Element](https://b.stripecdn.com/docs-statics-srv/assets/embedded-pay-immediate.057c691220d43158ac8000de10815ed9.png) Pour configurer le bouton dans la feuille de formulaire afin qu’il confirme immédiatement le paiement, définissez `formSheetAction` sur votre objet `EmbeddedPaymentElement.Configuration`. Le bloc de finalisation s’exécute avec le résultat du paiement après la fermeture du formulaire. L’interface utilisateur intégrée n’étant pas utilisable une fois le paiement effectué, il est préférable que votre implémentation redirige l’utilisateur vers un autre écran, par exemple un écran de reçu. ```kotlin @Composable fun CheckoutScreen() { val embeddedBuilder = .... val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedBuilder) LaunchedEffect(embeddedPaymentElement) { embeddedPaymentElement.configure( intentConfiguration = ...., configuration = EmbeddedPaymentElement.Configuration.Builder("Powdur") .formSheetAction(EmbeddedPaymentElement.FormSheetAction.Confirm) .build() ) } } ``` ## Créer un PaymentIntent [Côté serveur] Sur votre serveur, créez a *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods) en indiquant un montant et une devise. Vous pouvez gérer les moyens de paiement depuis le [Dashboard](https://dashboard.stripe.com/settings/payment_methods). Stripe gère le l’affichage des moyens de paiement admissibles en fonction de facteurs tels que le montant de la transaction, la devise et le tunnel de paiement. Pour éviter que des clients malveillants ne choisissent eux-mêmes leurs tarifs, décidez toujours du montant à débiter côté serveur (un environnement sécurisé) plutôt que côté client. Si l’appel réussit, renvoyez la *clé secrète du client* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)) du PaymentIntent. Si l’appel échoue, [traitez l’erreur](https://docs.stripe.com/error-handling.md) et renvoyez un message d’erreur avec une courte explication à l’intention de votre client. > Vérifiez que toutes les propriétés de l’IntentConfiguration correspondent à votre PaymentIntent (par exemple, `setup_future_usage`, `amount` et `currency`). #### Ruby ```ruby require 'stripe' # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. client = Stripe::StripeClient.new('<>') post '/create-intent' do data = JSON.parse request.body.read params = { amount: 1099, currency: 'usd', automatic_payment_methods: {enabled: true}, } begin intent = client.v1.payment_intents.create(params) {client_secret: intent.client_secret}.to_json rescue Stripe::StripeError => e {error: e.error.message}.to_json end end ``` ## Gérer les événements post-paiement [Côté serveur] Stripe envoie un événement [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) à l’issue du paiement. Utilisez l’[outil de webhook du Dashboard](https://dashboard.stripe.com/webhooks) ou suivez le [guide consacré aux webhooks](https://docs.stripe.com/webhooks/quickstart.md) pour recevoir ces événements et exécuter des actions, comme envoyer une confirmation de commande par e-mail à votre client, enregistrer la vente dans une base de données ou lancer un flux de livraison. Plutôt que d’attendre un rappel de votre client, écoutez ces événements. Côté client, il arrive en effet que l’utilisateur ferme la fenêtre de son navigateur ou quitte l’application avant l’exécution du rappel. Certains clients malintentionnés peuvent d’autre part tenter de manipuler la réponse. En configurant votre intégration de manière à ce qu’elle écoute les événements asynchrones, vous pourrez accepter [plusieurs types de moyens de paiement](https://stripe.com/payments/payment-methods-guide) avec une seule et même intégration. En plus de l’événement `payment_intent.succeeded`, nous vous recommandons de gérer ces autres événements lorsque vous encaissez des paiements à l’aide de l’Element Payment : | Événement | Description | Action | | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.succeeded) | Envoyé lorsqu’un client effectue un paiement avec succès. | Envoyez au client une confirmation de commande et *traitez* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected) sa commande. | | [payment_intent.processing](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.processing) | Envoyé lorsqu’un client initie un paiement, mais qu’il ne l’a pas encore finalisé. Dans la plupart des cas, cet événement est envoyé lorsque le client initie un prélèvement bancaire. Il est suivi par un événement `payment_intent.succeeded` ou `payment_intent.payment_failed`. | Envoyez au client une confirmation de commande qui indique que son paiement est en attente. Pour des marchandises dématérialisées, vous pourrez traiter la commande sans attendre que le paiement soit effectué. | | [payment_intent.payment_failed](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.payment_failed) | Envoyé lorsqu’un client effectue une tentative de paiement qui se solde par un échec. | Si un paiement passe de l’état `processing` à `payment_failed`, proposez au client de retenter le paiement. | ## Tester l'intégration #### Cartes bancaires | Numéro de carte | Scénario | Méthode de test | | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 4242424242424242 | Le paiement par carte bancaire aboutit et ne nécessite pas d’authentification. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 4000002500003155 | Le paiement par carte bancaire requiert une *authentification* (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). | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 4000000000009995 | La carte est refusée avec un code de refus de type `insufficient_funds`. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 6205500000000000004 | La carte UnionPay a un numéro d’une longueur variable, allant de 13 à 19 chiffres. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | #### Virements avec redirection bancaire | Moyen de paiement | Scénario | Méthode de test | | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Bancontact, iDEAL | Votre client ne parvient pas à s’authentifier sur la page de redirection en utilisant un moyen de paiement avec redirection et à notification immédiate. | Choisissez un moyen de paiement avec redirection, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Faire échouer le paiement test** sur la page qui s’affiche. | | Pay by Bank | Le montant dû est réglé via un moyen de paiement avec redirection et à [notification différée](https://docs.stripe.com/payments/payment-methods.md#payment-notification). | Choisissez le moyen de paiement, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Finaliser le paiement test** sur la page qui s’affiche. | | Pay by Bank | Votre client ne parvient pas à s’authentifier sur la page de redirection en utilisant un moyen de paiement avec redirection et à notification différée. | Choisissez le moyen de paiement, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Faire échouer le paiement test** sur la page qui s’affiche. | | BLIK | Les paiements BLIK échouent de diverses manières : échecs immédiats (par exemple, code expiré ou non valide), erreurs différées (refus de la banque) ou expirations du délai (le client n’a pas répondu à temps). | Utiliser des modèles d’e-mail pour [simuler les différents échecs.](https://docs.stripe.com/payments/blik/accept-a-payment.md#simulate-failures) | #### Prélèvements bancaires | Moyen de paiement | Scénario | Méthode de test | | ---------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Prélèvement automatique SEPA | Le montant dû est réglé par prélèvement automatique SEPA. | Remplissez le formulaire à l’aide du numéro de compte `AT321904300235473204`. Le PaymentIntent confirmé passe d’abord à l’état processing, puis à l’état succeeded trois minutes plus tard. | | Prélèvement automatique SEPA | L’intention de paiement de votre client passe de l’état `processing` à l’état `requires_payment_method`. | Remplissez le formulaire à l’aide du numéro de compte `AT861904300235473202`. | Consultez la section consacrée aux [tests](https://docs.stripe.com/testing.md) pour obtenir des informations supplémentaires sur la manière de tester votre intégration. ## Optional: Activer les cartes sauvegardées [Côté serveur] [Côté client] `EmbeddedPaymentElement` peut permettre au client d’enregistrer sa carte bancaire et peut inclure les cartes bancaires enregistrées du client dans les moyens de paiement disponibles. Le client doit avoir un objet [Compte](https://docs.stripe.com/api/v2/core/accounts/create.md#v2_create_accounts-configuration-customer) configuré par le client ou un objet [Client](https://docs.stripe.com/api/customers/create.md) sur votre serveur. Pour activer une case à cocher qui permet au client d’enregistrer sa carte bancaire, créez une [CustomerSession](https://docs.stripe.com/api/customer_sessions.md), avec `payment_method_save` défini sur `enabled`. #### Comptes v2 ```javascript // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. const stripe = require("stripe")("<>"); const express = require('express'); const app = express(); app.set('trust proxy', true); app.use(express.json()); app.post('/payment-sheet', async (req, res) => { // Use an existing Account ID if this is a returning customer. const customer_account = await stripe.v2.core.accounts.create(); const customerSession = await stripe.customerSessions.create({ customer_account: customer_account.id, components: { mobile_payment_element: { enabled: true, features: { payment_method_save: 'enabled', payment_method_redisplay: 'enabled', payment_method_remove: 'enabled' } }, }, }); res.json({ customerSessionClientSecret: customerSession.client_secret, customer_account: customer_account.id, }); }); ``` Ensuite, configurez `EmbeddedPaymentElement` avec l’ID du client et la clé secrète du client `CustomerSession`. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Powdur") .customer( PaymentSheet.CustomerConfiguration.createWithCustomerSession( id = customerAccountId, clientSecret = customerSessionClientSecret, ) ) .build() embeddedPaymentElement.configure( intentConfiguration = // ... , configuration = configuration, ) ``` #### Clients v1 ```javascript // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. const stripe = require("stripe")("<>"); const express = require('express'); const app = express(); app.set('trust proxy', true); app.use(express.json()); app.post('/payment-sheet', async (req, res) => { // Use an existing Customer ID if this is a returning customer. const customer = await stripe.customers.create(); const customerSession = await stripe.customerSessions.create({ customer: customer.id, components: { mobile_payment_element: { enabled: true, features: { payment_method_save: 'enabled', payment_method_redisplay: 'enabled', payment_method_remove: 'enabled' } }, }, }); res.json({ customerSessionClientSecret: customerSession.client_secret, customer: customer.id, }); }); ``` Ensuite, configurez `EmbeddedPaymentElement` avec l’ID du client et la clé secrète du client `CustomerSession`. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Powdur") .customer( PaymentSheet.CustomerConfiguration.createWithCustomerSession( id = customerId, clientSecret = customerSessionClientSecret, ) ) .build() embeddedPaymentElement.configure( intentConfiguration = // ... , configuration = configuration, ) ``` ## Optional: Autoriser les moyens de paiement à notification différée [Côté client] Les *moyens de paiement différé* (A payment method that can't immediately return payment status when a customer attempts a transaction (for example, ACH debits). Businesses commonly hold an order in a pending state until payment is successful with these payment methods) ne vous garantissent pas de recevoir les fonds de votre client à l’issue du processus de paiement, soit parce qu’un certain délai est nécessaire (par exemple, les comptes bancaires États-Unis, les prélèvements SEPA, iDEAL, Bancontact et Sofort), soit parce que leur exécution nécessite une action de la part du client (par exemple, OXXO, Konbini et Boleto). Par défaut, l’`EmbeddedPaymentElement` n’affiche pas les moyens de paiement différé, même si vous les acceptez. Pour afficher les moyens de paiement différé que vous avez activés, définissez `allowsDelayedPaymentMethods` sur true dans votre `EmbeddedPaymentElement.Configuration`. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Powdur") .allowsDelayedPaymentMethods(true) .build() ``` Si le client utilise avec succès un moyen de paiement différé dans un `EmbeddedPaymentElement`, le résultat du paiement renvoyé est `EmbeddedPaymentElement.Result.Completed`. ## Optional: Activer Google Pay > Si votre écran de paiement comporte un bouton dédié **Google Pay**, suivez le [guide Google Pay](https://docs.stripe.com/google-pay.md?platform=android). Vous pouvez utiliser le Payment Element intégré pour gérer d’autres types de moyens de paiement. ### Configurer votre intégration Pour utiliser Google Pay, commencez par activer l’API Google Pay en ajoutant les informations suivantes au libellé `` de votre **AndroidManifest.xml** : ```xml ... ``` Pour en savoir plus, consultez cette page indiquant comment [configurer l’API Google Pay](https://developers.google.com/pay/api/android/guides/setup) pour Android. ### Ajouter Google Pay Pour ajouter Google Pay à votre intégration, transmettez un objet [PaymentSheet.GooglePayConfiguration](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-google-pay-configuration/index.html) avec votre environnement Google Pay (production ou test) et le [code pays de votre entreprise](https://dashboard.stripe.com/settings/account) lors de l’initialisation de l’`EmbeddedPaymentElement.Configuration`. ```kotlin val googlePayConfiguration = PaymentSheet.GooglePayConfiguration( environment = PaymentSheet.GooglePayConfiguration.Environment.Test, countryCode = "US", currencyCode = "USD" // Required for Setup Intents, optional for Payment Intents ) val configuration = EmbeddedPaymentElement.Configuration.Builder("Merchant, Inc.") .googlePay(googlePayConfiguration) .build() ``` ### Tester Google Pay Google vous permet d’effectuer des paiements de test via leur [suite de carte bancaire de test](https://developers.google.com/pay/api/android/guides/resources/test-card-suite). La suite de tests prend en charge l’utilisation de [cartes bancaires de test](https://docs.stripe.com/testing.md) de Stripe. Vous devez tester Google Pay à l’aide d’un appareil Android physique plutôt que d’un appareil simulé, dans un pays où Google Pay est pris en charge. Connectez-vous à un compte Google sur votre appareil de test avec une carte réelle enregistrée dans Google Wallet. ## Optional: Activer la numérisation de carte Pour activer la prise en charge de la numérisation des cartes bancaires, faites une [requête d’accès](https://developers.google.com/pay/api/android/guides/test-and-deploy/request-prod-access) à l’API Google Pay auprès de la [console Google Pay et Wallet](https://pay.google.com/business/console?utm_source=devsite&utm_medium=devsite&utm_campaign=devsite). - Si vous avez activé Google Pay, la fonctionnalité de numérisation de carte bancaire est automatiquement disponible dans notre interface utilisateur sur les appareils admissibles. Pour en savoir plus sur les appareils admissibles, consultez les [contraintes de l’API Google Pay](https://developers.google.com/pay/payment-card-recognition/debit-credit-card-recognition) - **Important :** la fonctionnalité de lecture de carte n’apparaît que dans les versions signées avec la même clé de signature enregistrée dans la [console Google Pay et Wallet](https://pay.google.com/business/console). Les versions de test ou de débogage utilisant différentes clés de signature (par exemple, les versions distribuées via Firebase App Tester) n’affichent pas l’option **Lire la carte**. Pour tester la lecture de carte dans les versions préliminaires, vous devez soit : - Signez vos versions de test avec votre clé de signature de production. - Ajoutez l’empreinte d’identification de votre clé de signature de test à la console Google Pay et Wallet Si votre application ne prend pas en charge Google Pay, vous pouvez utiliser le scanner de cartes Stripe. > Le scanner de carte Stripe est en version bêta publique. Pour activer la prise en charge de la numérisation de carte, ajoutez `stripecardscan` au bloc `dependencies` de votre fichier [app/build.gradle](https://developer.android.com/studio/build/dependencies) : #### Groovy ```groovy implementation 'com.stripe:stripecardscan:23.8.0' ``` ## Optional: Personnaliser le formulaire Toute personnalisation est configurée au moyen de l’objet `EmbeddedPaymentElement.Configuration`. ### Apparence Personnalisez les couleurs, les polices et plus encore afin de vous adapter à l’apparence de votre application à l’aide de l’[API Appearance](https://docs.stripe.com/elements/appearance-api/embedded-mobile.md?platform=android). ### Collecter les adresses des clients Recueillez les adresses de livraison et de facturation de vos clients à l’aide du composant [Address Element](https://docs.stripe.com/elements/address-element.md?platform=android). ### Personnaliser le nom d’entreprise à afficher Spécifiez un nom d’entreprise à afficher pour le client en définissant `merchantDisplayName`. Si vous ne spécifiez pas de nom, le nom de votre application s’affichera par défaut. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Merchant, Inc.") .build() ``` ### Spécifier les informations de facturation par défaut Pour définir des valeurs par défaut pour les informations de facturation collectées dans l’`EmbeddedPaymentElement`, configurez la propriété `defaultBillingDetails`. L’`EmbeddedPaymentElement` pré-remplit ses champs avec les valeurs que vous fournissez. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Merchant, Inc.") .defaultBillingDetails( PaymentSheet.BillingDetails( address = PaymentSheet.Address( country = "US", ), email = "foo@bar.com" ) ) .build() ``` ### Configurer la collecte des données de facturation Utiliser `BillingDetailsCollectionConfiguration` pour spécifier la manière dont vous souhaitez collecter les informations de facturation dans `EmbeddedPaymentElement`. Vous pouvez collecter le nom, l’adresse e-mail, le numéro de téléphone et l’adresse de votre client. Si vous souhaitez associer les informations de facturation par défaut à l’objet PaymentMethod même lorsque ces champs ne sont pas collectés dans l’interface utilisateur, définissez `billingDetailsCollectionConfiguration.attachDefaultsToPaymentMethod` sur `true`. ```kotlin import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration val billingDetails = PaymentSheet.BillingDetails( email = "foo@bar.com" ) val billingDetailsCollectionConfiguration = BillingDetailsCollectionConfiguration( attachDefaultsToPaymentMethod = true, name = BillingDetailsCollectionConfiguration.CollectionMode.Always, email = BillingDetailsCollectionConfiguration.CollectionMode.Never, address = BillingDetailsCollectionConfiguration.AddressCollectionMode.Full, ) val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Merchant, Inc.") .defaultBillingDetails(billingDetails) .billingDetailsCollectionConfiguration(billingDetailsCollectionConfiguration) .build() ``` > Consultez votre conseiller juridique au sujet des lois qui s’appliquent à la collecte d’informations. Ne collectez les numéros de téléphone que si vous en avez besoin pour la transaction. ## Optional: Activer la collecte du CVC à la confirmation Pour récupérer le CVC d’une carte bancaire enregistrée lors de la confirmation de PaymentIntent, votre intégration doit collecter les informations de paiement avant de créer un PaymentIntent. ### Mettre à jour la configuration de l’Intent `PaymentSheet.IntentConfiguration` accepte un paramètre facultatif qui contrôle le moment de récupérer le CVC pour une carte enregistrée. ```kotlin val intentConfig = PaymentSheet.IntentConfiguration( mode = PaymentSheet.IntentConfiguration.Mode.Payment( amount = 1099, currency = "usd", ),requireCvcRecollection = true, ) ``` ### Mettre à jour les paramètres de création de l’Intent Pour récupérer le CVC lors de la confirmation du paiement, ajoutez les paramètres `customerId` et `require_cvc_recollection` lors de la création du PaymentIntent. #### Ruby ```ruby require 'stripe' # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. client = Stripe::StripeClient.new('<>') post '/create-intent' do data = JSON.parse request.body.read params = { amount: 1099, currency: 'usd', automatic_payment_methods: {enabled: true},customer: customer.id, payment_method_options: { card: {require_cvc_recollection: true} }, } begin intent = client.v1.payment_intents.create(params) {client_secret: intent.client_secret}.to_json rescue Stripe::StripeError => e {error: e.error.message}.to_json end end ``` # Collecter et enregistrer un moyen de paiement > This is a Collecter et enregistrer un moyen de paiement for when platform is android and type is setup. View the full page at https://docs.stripe.com/payments/mobile/accept-payment-embedded?platform=android&type=setup. Un flux SetupIntent vous permet de collecter les informations du moyen de paiement et de les enregistrer pour de futurs paiements sans créer de débité. Dans cette intégration, vous créez un flux personnalisé où vous affichez le Payment Element, créez le *SetupIntent* (The Setup Intents API lets you build dynamic flows for collecting payment method details for future payments. It tracks the lifecycle of a payment setup flow and can trigger additional authentication steps if required by law or by the payment method) et confirmez l’enregistrement du moyen de paiement dans votre application. ## Configurer Stripe [Côté serveur] [Côté client] Pour commencer, vous devez créer un compte Stripe. [Inscrivez-vous maintenant](https://dashboard.stripe.com/register). ### Côté serveur Cette intégration exige des endpoints sur votre serveur qui communiquent avec l’API Stripe. Utilisez nos bibliothèques officielles pour accéder à l’API Stripe depuis votre serveur : #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ### Côté client Le [SDK Stripe Android](https://github.com/stripe/stripe-android) est disponible en open source et [fait l’objet d’une documentation complète](https://stripe.dev/stripe-android/). Pour installer le SDK, ajoutez `stripe-android` au bloc `dependencies` de votre fichier [app/build.gradle](https://developer.android.com/studio/build/dependencies) : #### Kotlin ```kotlin plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id("org.jetbrains.kotlin.plugin.compose") } android { ... kotlinOptions { jvmTarget = "11" } buildFeatures { compose true } } dependencies { // ... // Stripe Android SDK implementation("com.stripe:stripe-android:23.8.0") // Include the financial connections SDK to support US bank account as a payment method implementation("com.stripe:financial-connections:23.8.0") } ``` > Pour obtenir de plus amples informations sur la version la plus récente du SDK et ses versions antérieures, consultez la page des [versions](https://github.com/stripe/stripe-android/releases) sur GitHub. Pour savoir quand une nouvelle version est disponible, [surveillez les versions du référentiel](https://docs.github.com/en/github/managing-subscriptions-and-notifications-on-github/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository). Vous devez également définir votre [clé publiable](https://dashboard.stripe.com/apikeys) afin que le SDK puisse effectuer des appels à l’API vers Stripe. Pour commencer rapidement, vous pouvez coder cela en dur côté client pendant l’intégration, mais récupérer la clé publiable sur votre serveur en mode production. ```kotlin // Set your publishable key: remember to change this to your live publishable key in production // See your keys here: https://dashboard.stripe.com/apikeys PaymentConfiguration.init(context, publishableKey = "<>") ``` ## Activer des moyens de paiement Affichez vos [paramètres des moyens de paiement](https://dashboard.stripe.com/settings/payment_methods) et activez les moyens de paiement que vous souhaitez prendre en charge. Vous devez activer au moins un moyen de paiement pour créer un *SetupIntent* (The Setup Intents API lets you build dynamic flows for collecting payment method details for future payments. It tracks the lifecycle of a payment setup flow and can trigger additional authentication steps if required by law or by the payment method). Par défaut, Stripe active les cartes bancaires et les autres moyens de paiement courants qui peuvent vous permettre d’atteindre davantage de clients. Nous vous recommandons toutefois d’activer d’autres moyens de paiement pertinents pour votre entreprise et vos clients. Consultez la page [Prise en charge des moyens de paiement](https://docs.stripe.com/payments/payment-methods/payment-method-support.md) pour en savoir plus sur la prise en charge des produits et des moyens de paiement, et notre [page des tarifs](https://stripe.com/pricing/local-payment-methods) pour prendre connaissance des frais que nous appliquons. ## Créer un objet Customer [Côté serveur] Pour configurer un moyen de paiement pour des paiements futurs, vous devez l’associer à un objet représentant votre client. Lorsque votre client crée un compte ou effectue sa première transaction avec votre entreprise, créez soit un objet [Account](https://docs.stripe.com/api/v2/core/accounts/create.md) configuré pour le client avec l’API Accounts v2, soit un objet [Customer](https://docs.stripe.com/api/customers/create.md) avec l’API Customers. > #### Utiliser l’API Accounts v2 pour représenter les clients > > L’API Accounts v2 est généralement disponible pour les utilisateurs de Connect et en aperçu public pour les autres utilisateurs de Stripe. Si vous avez accès à l’aperçu Accounts v2, vous devez [spécifier une version d’aperçu](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning) dans votre code. > > Pour demander l’accès à l’aperçu Accounts v2, > > Dans la plupart des cas d’usage, nous vous recommandons de [modéliser vos clients en tant qu’objets Account configurés par le client](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md), plutôt que d’utiliser des objets [Customer](https://docs.stripe.com/api/customers.md). ```curl curl -X POST https://api.stripe.com/v1/customers \ -u "<>:" ``` ## Collecter les informations de paiement [Côté client] L’Embedded Mobile Payment Element est conçu pour utilisation sur la page de paiement de votre application mobile native. L’élément affiche une liste de moyens de paiement, et vous pouvez le personnaliser pour l’adapter au visuel de votre application. Lorsque le client touche la ligne **Carte bancaire**, un formulaire s’ouvre, dans lequel il peut saisir les informations de son moyen de paiement. Le bouton dans le formulaire indique **Continuer** par défaut et entraîne la fermeture du formulaire lorsque lorsqu’il est utilisé, ce qui permet à votre client de terminer la configuration dans votre système de paiement. ![Payment Element intégré](https://b.stripecdn.com/docs-statics-srv/assets/android-embedded.1aefe2ca79ed073e350ec629a5af22d5.png) Vous pouvez configurer le bouton pour qu’il termine immédiatement la configuration au lieu de continuer. Pour ce faire, effectuez [cette étape](https://docs.stripe.com/payments/mobile/accept-payment-embedded.md#embedded-let-customer-pay-immediately) après avoir suivi le guide. ### Initialiser l’Embedded Payment Element #### Jetpack Compose Initialisez une instance de l’`EmbeddedPaymentElement` en utilisant la fonction `rememberEmbeddedPaymentElement` avec un `EmbeddedPaymentElement.Builder`. Transmettez un `CreateIntentWithConfirmationTokenCallback`. Vous pouvez laisser l’implémentation vide pour le moment, afin de préparer facilement l’intégration future des paiements. ```kotlin import com.stripe.android.paymentelement.EmbeddedPaymentElement import com.stripe.android.paymentelement.rememberEmbeddedPaymentElement @Composable fun CheckoutScreen() { val embeddedBuilder = remember { EmbeddedPaymentElement.Builder( createIntentCallback = { confirmationToken, -> TODO("You'll implement this in the "Confirm the payment" step") }, resultCallback = { result -> TODO("You'll implement this in the "Confirm the payment" step") }, ) } val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedBuilder) } ``` #### Vues (classique) Initialisez une instance de l’`EmbeddedPaymentElement` en utilisant la fonction `rememberEmbeddedPaymentElement` avec un `EmbeddedPaymentElement.Builder`. ```kotlin import com.stripe.android.paymentelement.EmbeddedPaymentElement import com.stripe.android.paymentelement.rememberEmbeddedPaymentElement @Composable fun CheckoutScreen() { val embeddedBuilder = remember { EmbeddedPaymentElement.Builder( createIntentCallback = { confirmationToken -> TODO("Completed in a later step.") }, resultCallback = { result -> TODO("Completed in a later step.") }, ) } val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedBuilder) } ``` Le Mobile Payment Element intégré est conçu pour l’interface Jetpack Compose et expose une méthode `@Composable Content`. Lors de l’utilisation de vues classiques, vous devez encapsuler le Payment Element intégré dans une `ComposeView`. ```xml ``` ```kotlin class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.checkout_screen_layout) val composeView = findViewById(R.id.compose_view) composeView.setContent { CheckoutScreen() } } } ``` ### Configurer l’Embedded Payment Element L’objet `Builder` contient les rappels nécessaires à l’instanciation de l’`EmbeddedPaymentElement`, y compris le `CreateIntentCallback`. Pour l’instant, laissez son implémentation vide. Après l’instanciation, appelez `configure` avec une `EmbeddedPaymentElement.Configuration` et une `PaymentSheet.IntentConfiguration`. L’objet `Configuration` contient les options générales pour `EmbeddedPaymentElement` qui ne changent pas entre les paiements. L’objet `IntentConfiguration` contient les détails du paiement spécifique, comme le montant et la devise. ```kotlin import com.stripe.android.paymentsheet.PaymentSheet @Composable fun CheckoutScreen() { val embeddedBuilder = .... val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedBuilder) LaunchedEffect(embeddedPaymentElement) { embeddedPaymentElement.configure( intentConfiguration = PaymentSheet.IntentConfiguration(mode = PaymentSheet.IntentConfiguration.Mode.Setup( currency = "USD", ),// Optional intent configuration options... ), configuration = EmbeddedPaymentElement.Configuration.Builder("Powdur").build() ) } } ``` ### Ajouter la vue Embedded Payment Element Une fois l’`EmbeddedPaymentElement` initialisé, placez son `@Composable Content` dans l’interface utilisateur de votre page de paiement. > Le contenu doit se trouver dans un conteneur déroulable, car sa hauteur peut changer après son affichage initial. ```kotlin @Composable fun CheckoutScreen() { val embeddedBuilder = .... val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedBuilder) ..... val scrollState = rememberScrollState() Column( modifier = Modifier .fillMaxSize() .verticalScroll(scrollState) .padding(16.dp) ) { embeddedPaymentElement.Content() } } ``` À ce stade, vous pouvez exécuter votre application et voir l’Embedded Mobile Payment Element. ### (Facultatif) Mettre à jour les informations de paiement Si un client modifie les détails du paiement (par exemple, en appliquant un code de réduction), mettez à jour l’instance `EmbeddedPaymentElement`. Lorsque vous appelez à nouveau la méthode `configure`, les nouvelles valeurs se synchronisent et s’affichent dans l’interface utilisateur. > Certains moyens de paiement, comme Google Pay, affichent le montant dans l’interface utilisateur. Si un client modifie le paiement et que vous ne mettez pas à jour l’élément `EmbeddedPaymentElement`, l’interface utilisateur affiche des valeurs incorrectes. Une fois l’appel à `configure` terminé, `@Composable Content` et `paymentOption` sont automatiquement mis à jour avec les nouvelles valeurs fournies lors de l’appel à `configure`. ```kotlin val intentConfiguration = PaymentSheet.IntentConfiguration( // Change paymentMethodTypes to customize the payment methods you want to accept mode = PaymentSheet.IntentConfiguration.Mode.Setup( currency = "USD", ), paymentMethodTypes = listOf("card") ) val configuration = EmbeddedPaymentElement.Configuration.Builder("Powdur") .build() LaunchedEffect(embeddedPaymentElement) { embeddedPaymentElement.configure( intentConfiguration = intentConfiguration, configuration = configuration, ) } ``` ### (Facultatif) Afficher l’option de paiement sélectionnée Vous pouvez afficher les détails de l’option de paiement (comme les 4 derniers chiffres, le logo de la carte ou les informations de facturation) en accédant à la propriété observable `Flow` de `paymentOption` dans le Payment Element intégré. Lorsqu’un client sélectionne un moyen de paiement qui ouvre un formulaire, l’option de paiement est mise à jour après qu’il ait appuyé sur **Continue** dans le formulaire. ```kotlin val selectedPaymentOption by embeddedPaymentElement.paymentOption.collectAsState() selectedPaymentOption?.let { paymentOption -> Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier .clickable( onClick = { }, ) .semantics { text = AnnotatedString(paymentOption.label) }, ) { Icon( painter = paymentOption.iconPainter, contentDescription = null, // decorative element modifier = Modifier.padding(horizontal = 4.dp), tint = Color.Unspecified, ) Text(text = paymentOption.label) } } ``` ### Confirmer la configuration Lorsque le client appuie sur le bouton de paiement, confirmez le SetupIntent en appelant `embeddedPaymentElement.confirm()`. Veillez à désactiver l’interaction avec l’utilisateur lors de la confirmation. Lorsqu’un formulaire est affiché, le `EmbeddedPaymentElement` appelle `confirm` lorsque l’utilisateur clique sur **Call to action**. Si le moyen de paiement sélectionné n’a aucun champ de formulaire, appelez `confirm` lorsque l’utilisateur clique sur **Call to action** sous le `@Composable Content`. ```kotlin Button( onClick = { embeddedPaymentElement.confirm() } ) { Text("Confirm payment") } ``` Ensuite, implémentez le rappel `createIntentCallback` que vous avez passé précédemment à `EmbeddedPaymentElement.Builder` pour envoyer une requête à votre serveur. Votre serveur crée un SetupIntent et renvoie sa clé secrète du client, comme expliqué à l’étape [créer un SetupIntent](https://docs.stripe.com/payments/mobile/accept-payment-embedded.md#submit-setup). Lorsque vous recevez la requête, renvoyez le résultat de la création de l’Intent à l’aide de `CreateIntentResult` avec la clé secrète du client de la réponse de votre serveur ou une erreur. Le `EmbeddedPaymentElement` confirme le SetupIntent en utilisant la clé secrète du client ou affiche le message d’erreur localisé dans son interface utilisateur. ```kotlin import com.stripe.android.paymentsheet.CreateIntentResult val embeddedBuilder = remember { val embeddedBuilder = EmbeddedPaymentElement.Builder( createIntentCallback = { confirmationToken ->// Make a request to your own server and receive a client secret or an error. val networkResult = ... if (networkResult.isSuccess) { CreateIntentResult.Success(networkResult.clientSecret) } else { CreateIntentResult.Failure(networkResult.exception) } }, resultCallback = { result ->when (result) { is EmbeddedPaymentElement.Result.Completed -> { // Payment completed - show a confirmation screen. } is EmbeddedPaymentElement.Result.Failed -> { // Encountered an unrecoverable error. You can display the error to the user, log it, and so on } is EmbeddedPaymentElement.Result.Canceled -> { // Customer canceled - you should probably do nothing. } } }, ) } ``` ## Optional: Décocher l’option de paiement sélectionnée Si vous avez des options de paiement externes à l’`EmbeddedPaymentElement`, vous devrez peut-être décocher l’option de paiement sélectionnée. Pour ce faire, utilisez l’API `clearPaymentOption`. ```kotlin @Composable fun CheckoutScreen() { val embeddedPaymentElementBuilder = .... val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedPaymentElementBuilder) .... Button( onClick = embeddedPaymentElement::clearPaymentOption ) { Text("Select external payment option") } } ``` ## Optional: Afficher vous-même le mandat Pour garantir la conformité réglementaire, l’Embedded Mobile Payment Element affiche les mandats et clauses de non-responsabilité par défaut. Ce texte doit être situé à proximité de votre bouton **Acheter**. Si vous désactivez l’affichage par défaut de ces éléments dans la vue, vous devez les afficher vous-même. > Pour être conforme, votre intégration doit afficher de manière appropriée le texte du mandat. Si vous l’affichez vous-même, assurez-vous que toutes les URL sont restituées correctement en incluant le texte dans un composable `Text`. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder("Merchant, Inc") .embeddedViewDisplaysMandateText(false) .build() .... val selectedPaymentOption by embeddedPaymentElement.paymentOption.collectAsState() selectedPaymentOption?.mandateText?.let { mandateText -> Text(mandateText) } ``` ## Optional: Laissez le client confirmer la configuration immédiatement dans la feuille Pour configurer le bouton dans la feuille de formulaire afin de confirmer immédiatement la configuration, configurez `formSheetAction` sur votre objet `EmbeddedPaymentElement.Configuration`. Le bloc de finalisation s’exécute avec le résultat de la configuration après la fermeture du formulaire. L’interface utilisateur intégrée n’étant pas utilisable une fois la configuration terminée, il est préférable que votre implémentation redirige l’utilisateur vers un autre écran, par exemple un écran de reçu. ```kotlin @Composable fun CheckoutScreen() { val embeddedBuilder = .... val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedBuilder) LaunchedEffect(embeddedPaymentElement) { embeddedPaymentElement.configure( intentConfiguration = ...., configuration = EmbeddedPaymentElement.Configuration.Builder("Powdur") .formSheetAction(EmbeddedPaymentElement.FormSheetAction.Confirm) .build() ) } } ``` ## Créer un SetupIntent [Côté serveur] Sur votre serveur, créez un *SetupIntent* (The Setup Intents API lets you build dynamic flows for collecting payment method details for future payments. It tracks the lifecycle of a payment setup flow and can trigger additional authentication steps if required by law or by the payment method). Vous pouvez gérer les moyens de paiement à partir du [Dashboard](https://dashboard.stripe.com/settings/payment_methods). Stripe évalue les restrictions des moyens de paiement et d’autres paramètres pour déterminer la liste des moyens de paiement pris en charge. Si l’appel réussit, renvoyez la *clé secrète du client* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)) du SetupIntent. Si l’appel échoue, [traitez l’erreur](https://docs.stripe.com/error-handling.md) et renvoyez un message d’erreur avec une courte explication à l’intention de votre client. > Vérifiez que toutes les propriétés de l’IntentConfiguration correspondent à votre SetupIntent (par exemple, [usage](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-usage)). #### Ruby ```ruby require 'stripe' # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. client = Stripe::StripeClient.new('<>') post '/create-intent' do data = JSON.parse request.body.read params = { customer: ..., # The Customer ID you previously created automatic_payment_methods: {enabled: true}, } begin intent = client.v1.setup_intents.create(params) {client_secret: intent.client_secret}.to_json rescue Stripe::StripeError => e {error: e.error.message}.to_json end end ``` ## Débiter ultérieurement le moyen de paiement enregistré [Côté serveur] > `bancontact` et `ideal` sont les moyens de paiement ponctuel par défaut. Lorsque vous les configurez pour une utilisation future, ils génèrent un type de moyen de paiement réutilisable `sepa_debit`. Vous devez donc utiliser la requête `sepa_debit` pour les moyens de paiement enregistrés. > #### Conformité > > Lorsque vous enregistrez les informations de paiement d’un client, vous êtes responsable du respect de l’ensemble des lois, réglementations et règles du réseau en vigueur. Lorsque vous présentez au client final des moyens de paiement précédemment utilisés en vue d’effectuer ses prochains achats, assurez-vous de lister les moyens de paiement pour lesquels vous avez obtenu le consentement du client à l’enregistrement des informations de paiement aux fins des futurs achats. Le paramètre [allow_redisplay](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-allow_redisplay) vous permet de différencier les moyens de paiement associés au client qui peuvent ou non être présentés pour les achats futurs. Pour trouver un moyen de paiement à débiter, listez les moyens de paiement associés à votre client. Cet exemple liste des cartes bancaires, mais vous pouvez lister tout [type](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-type) pris en charge. > #### Utiliser l’API Accounts v2 pour représenter les clients > > L’API Accounts v2 est généralement disponible pour les utilisateurs de Connect et en aperçu public pour les autres utilisateurs de Stripe. Si vous avez accès à l’aperçu Accounts v2, vous devez [spécifier une version d’aperçu](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning) dans votre code. > > Pour demander l’accès à l’aperçu Accounts v2, > > Dans la plupart des cas d’usage, nous vous recommandons de [modéliser vos clients en tant qu’objets Account configurés par le client](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md), plutôt que d’utiliser des objets [Customer](https://docs.stripe.com/api/customers.md). #### Accounts v2 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d type=card ``` #### Customers v1 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d type=card ``` Lorsque vous êtes prêt à débiter votre client *hors session* (A payment is described as off-session if it occurs without the direct involvement of the customer, using previously-collected payment information), utilisez l’ID du `Customer` ou de l’`Account` configuré par le client ainsi que l’ID du `PaymentMethod` pour créer un `PaymentIntent` avec le montant et la devise du paiement. Définissez quelques autres paramètres pour effectuer le paiement hors session : - Définissez [off_session](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-off_session) sur true pour indiquer que le client n’est pas dans votre tunnel de paiement et ne peut pas répondre aux demandes d’authentification. Si, pendant votre tunnel de paiement, un partenaire (tel qu’un émetteur de cartes bancaires ou une banque) demande une authentification, Stripe sollicite des exemptions en utilisant les informations client issues d’une transaction précédente *pendant en session* (A payment is described as on-session if it occurs while the customer is actively in your checkout flow and able to authenticate the payment method). Si les conditions d’exemption ne sont pas remplies, le `PaymentIntent` peut générer une erreur. - Définissez [confirm](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-confirm) sur true pour déclencher la confirmation immédiatement lors de la création du `PaymentIntent`. - Définissez [payment_method](https://docs.stripe.com/api.md#create_payment_intent-payment_method) sur l’ID du `PaymentMethod`. - Selon la manière dont vous représentez les clients dans votre intégration, définissez soit [customer_account](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer_account) sur l’ID de l’objet `Account` configuré pour le client, soit [customer](https://docs.stripe.com/api.md#create_payment_intent-customer) sur l’ID de l’objet `Customer`. #### Accounts v2 ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=usd \ -d "automatic_payment_methods[enabled]=true" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d payment_method={{PAYMENT_METHOD_ID}} \ --data-urlencode "return_url=https://example.com/order/123/complete" \ -d off_session=true \ -d confirm=true ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=usd \ -d "automatic_payment_methods[enabled]=true" \ -d "customer={{CUSTOMER_ID}}" \ -d payment_method={{PAYMENT_METHOD_ID}} \ --data-urlencode "return_url=https://example.com/order/123/complete" \ -d off_session=true \ -d confirm=true ``` ## Tester l'intégration #### Cartes bancaires | Numéro de carte | Scénario | Méthode de test | | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 4242424242424242 | Le paiement par carte bancaire aboutit et ne nécessite pas d’authentification. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 4000002500003155 | Le paiement par carte bancaire requiert une *authentification* (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). | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 4000000000009995 | La carte est refusée avec un code de refus de type `insufficient_funds`. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 6205500000000000004 | La carte UnionPay a un numéro d’une longueur variable, allant de 13 à 19 chiffres. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | #### Virements avec redirection bancaire | Moyen de paiement | Scénario | Méthode de test | | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Bancontact, iDEAL | Votre client ne parvient pas à s’authentifier sur la page de redirection en utilisant un moyen de paiement avec redirection et à notification immédiate. | Choisissez un moyen de paiement avec redirection, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Faire échouer le paiement test** sur la page qui s’affiche. | | Pay by Bank | Le montant dû est réglé via un moyen de paiement avec redirection et à [notification différée](https://docs.stripe.com/payments/payment-methods.md#payment-notification). | Choisissez le moyen de paiement, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Finaliser le paiement test** sur la page qui s’affiche. | | Pay by Bank | Votre client ne parvient pas à s’authentifier sur la page de redirection en utilisant un moyen de paiement avec redirection et à notification différée. | Choisissez le moyen de paiement, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Faire échouer le paiement test** sur la page qui s’affiche. | | BLIK | Les paiements BLIK échouent de diverses manières : échecs immédiats (par exemple, code expiré ou non valide), erreurs différées (refus de la banque) ou expirations du délai (le client n’a pas répondu à temps). | Utiliser des modèles d’e-mail pour [simuler les différents échecs.](https://docs.stripe.com/payments/blik/accept-a-payment.md#simulate-failures) | #### Prélèvements bancaires | Moyen de paiement | Scénario | Méthode de test | | ---------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Prélèvement automatique SEPA | Le montant dû est réglé par prélèvement automatique SEPA. | Remplissez le formulaire à l’aide du numéro de compte `AT321904300235473204`. Le PaymentIntent confirmé passe d’abord à l’état processing, puis à l’état succeeded trois minutes plus tard. | | Prélèvement automatique SEPA | L’intention de paiement de votre client passe de l’état `processing` à l’état `requires_payment_method`. | Remplissez le formulaire à l’aide du numéro de compte `AT861904300235473202`. | Consultez la section consacrée aux [tests](https://docs.stripe.com/testing.md) pour obtenir des informations supplémentaires sur la manière de tester votre intégration. ## Optional: Activer les cartes sauvegardées [Côté serveur] [Côté client] `EmbeddedPaymentElement` peut permettre au client d’enregistrer sa carte bancaire et peut inclure les cartes bancaires enregistrées du client dans les moyens de paiement disponibles. Le client doit avoir un objet [Compte](https://docs.stripe.com/api/v2/core/accounts/create.md#v2_create_accounts-configuration-customer) configuré par le client ou un objet [Client](https://docs.stripe.com/api/customers/create.md) sur votre serveur. Pour activer une case à cocher qui permet au client d’enregistrer sa carte bancaire, créez une [CustomerSession](https://docs.stripe.com/api/customer_sessions.md), avec `payment_method_save` défini sur `enabled`. #### Comptes v2 ```javascript // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. const stripe = require("stripe")("<>"); const express = require('express'); const app = express(); app.set('trust proxy', true); app.use(express.json()); app.post('/payment-sheet', async (req, res) => { // Use an existing Account ID if this is a returning customer. const customer_account = await stripe.v2.core.accounts.create(); const customerSession = await stripe.customerSessions.create({ customer_account: customer_account.id, components: { mobile_payment_element: { enabled: true, features: { payment_method_save: 'enabled', payment_method_redisplay: 'enabled', payment_method_remove: 'enabled' } }, }, }); res.json({ customerSessionClientSecret: customerSession.client_secret, customer_account: customer_account.id, }); }); ``` Ensuite, configurez `EmbeddedPaymentElement` avec l’ID du client et la clé secrète du client `CustomerSession`. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Powdur") .customer( PaymentSheet.CustomerConfiguration.createWithCustomerSession( id = customerAccountId, clientSecret = customerSessionClientSecret, ) ) .build() embeddedPaymentElement.configure( intentConfiguration = // ... , configuration = configuration, ) ``` #### Clients v1 ```javascript // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. const stripe = require("stripe")("<>"); const express = require('express'); const app = express(); app.set('trust proxy', true); app.use(express.json()); app.post('/payment-sheet', async (req, res) => { // Use an existing Customer ID if this is a returning customer. const customer = await stripe.customers.create(); const customerSession = await stripe.customerSessions.create({ customer: customer.id, components: { mobile_payment_element: { enabled: true, features: { payment_method_save: 'enabled', payment_method_redisplay: 'enabled', payment_method_remove: 'enabled' } }, }, }); res.json({ customerSessionClientSecret: customerSession.client_secret, customer: customer.id, }); }); ``` Ensuite, configurez `EmbeddedPaymentElement` avec l’ID du client et la clé secrète du client `CustomerSession`. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Powdur") .customer( PaymentSheet.CustomerConfiguration.createWithCustomerSession( id = customerId, clientSecret = customerSessionClientSecret, ) ) .build() embeddedPaymentElement.configure( intentConfiguration = // ... , configuration = configuration, ) ``` ## Optional: Autoriser les moyens de paiement à notification différée [Côté client] Les *moyens de paiement différé* (A payment method that can't immediately return payment status when a customer attempts a transaction (for example, ACH debits). Businesses commonly hold an order in a pending state until payment is successful with these payment methods) ne vous garantissent pas de recevoir les fonds de votre client à l’issue du processus de paiement, soit parce qu’un certain délai est nécessaire (par exemple, les comptes bancaires États-Unis, les prélèvements SEPA, iDEAL, Bancontact et Sofort), soit parce que leur exécution nécessite une action de la part du client (par exemple, OXXO, Konbini et Boleto). Par défaut, l’`EmbeddedPaymentElement` n’affiche pas les moyens de paiement différé, même si vous les acceptez. Pour afficher les moyens de paiement différé que vous avez activés, définissez `allowsDelayedPaymentMethods` sur true dans votre `EmbeddedPaymentElement.Configuration`. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Powdur") .allowsDelayedPaymentMethods(true) .build() ``` Si le client utilise avec succès un moyen de paiement différé dans un `EmbeddedPaymentElement`, le résultat du paiement renvoyé est `EmbeddedPaymentElement.Result.Completed`. ## Optional: Activer Google Pay > Si votre écran de paiement comporte un bouton dédié **Google Pay**, suivez le [guide Google Pay](https://docs.stripe.com/google-pay.md?platform=android). Vous pouvez utiliser le Payment Element intégré pour gérer d’autres types de moyens de paiement. ### Configurer votre intégration Pour utiliser Google Pay, commencez par activer l’API Google Pay en ajoutant les informations suivantes au libellé `` de votre **AndroidManifest.xml** : ```xml ... ``` Pour en savoir plus, consultez cette page indiquant comment [configurer l’API Google Pay](https://developers.google.com/pay/api/android/guides/setup) pour Android. ### Ajouter Google Pay Pour ajouter Google Pay à votre intégration, transmettez un objet [PaymentSheet.GooglePayConfiguration](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-google-pay-configuration/index.html) avec votre environnement Google Pay (production ou test) et le [code pays de votre entreprise](https://dashboard.stripe.com/settings/account) lors de l’initialisation de l’`EmbeddedPaymentElement.Configuration`. ```kotlin val googlePayConfiguration = PaymentSheet.GooglePayConfiguration( environment = PaymentSheet.GooglePayConfiguration.Environment.Test, countryCode = "US", currencyCode = "USD" // Required for Setup Intents, optional for Payment Intents ) val configuration = EmbeddedPaymentElement.Configuration.Builder("Merchant, Inc.") .googlePay(googlePayConfiguration) .build() ``` ### Tester Google Pay Google vous permet d’effectuer des paiements de test via leur [suite de carte bancaire de test](https://developers.google.com/pay/api/android/guides/resources/test-card-suite). La suite de tests prend en charge l’utilisation de [cartes bancaires de test](https://docs.stripe.com/testing.md) de Stripe. Vous devez tester Google Pay à l’aide d’un appareil Android physique plutôt que d’un appareil simulé, dans un pays où Google Pay est pris en charge. Connectez-vous à un compte Google sur votre appareil de test avec une carte réelle enregistrée dans Google Wallet. ## Optional: Activer la numérisation de carte Pour activer la prise en charge de la numérisation des cartes bancaires, faites une [requête d’accès](https://developers.google.com/pay/api/android/guides/test-and-deploy/request-prod-access) à l’API Google Pay auprès de la [console Google Pay et Wallet](https://pay.google.com/business/console?utm_source=devsite&utm_medium=devsite&utm_campaign=devsite). - Si vous avez activé Google Pay, la fonctionnalité de numérisation de carte bancaire est automatiquement disponible dans notre interface utilisateur sur les appareils admissibles. Pour en savoir plus sur les appareils admissibles, consultez les [contraintes de l’API Google Pay](https://developers.google.com/pay/payment-card-recognition/debit-credit-card-recognition) - **Important :** la fonctionnalité de lecture de carte n’apparaît que dans les versions signées avec la même clé de signature enregistrée dans la [console Google Pay et Wallet](https://pay.google.com/business/console). Les versions de test ou de débogage utilisant différentes clés de signature (par exemple, les versions distribuées via Firebase App Tester) n’affichent pas l’option **Lire la carte**. Pour tester la lecture de carte dans les versions préliminaires, vous devez soit : - Signez vos versions de test avec votre clé de signature de production. - Ajoutez l’empreinte d’identification de votre clé de signature de test à la console Google Pay et Wallet Si votre application ne prend pas en charge Google Pay, vous pouvez utiliser le scanner de cartes Stripe. > Le scanner de carte Stripe est en version bêta publique. Pour activer la prise en charge de la numérisation de carte, ajoutez `stripecardscan` au bloc `dependencies` de votre fichier [app/build.gradle](https://developer.android.com/studio/build/dependencies) : #### Groovy ```groovy implementation 'com.stripe:stripecardscan:23.8.0' ``` ## Optional: Personnaliser le formulaire Toute personnalisation est configurée au moyen de l’objet `EmbeddedPaymentElement.Configuration`. ### Apparence Personnalisez les couleurs, les polices et plus encore afin de vous adapter à l’apparence de votre application à l’aide de l’[API Appearance](https://docs.stripe.com/elements/appearance-api/embedded-mobile.md?platform=android). ### Collecter les adresses des clients Recueillez les adresses de livraison et de facturation de vos clients à l’aide du composant [Address Element](https://docs.stripe.com/elements/address-element.md?platform=android). ### Personnaliser le nom d’entreprise à afficher Spécifiez un nom d’entreprise à afficher pour le client en définissant `merchantDisplayName`. Si vous ne spécifiez pas de nom, le nom de votre application s’affichera par défaut. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Merchant, Inc.") .build() ``` ### Spécifier les informations de facturation par défaut Pour définir des valeurs par défaut pour les informations de facturation collectées dans l’`EmbeddedPaymentElement`, configurez la propriété `defaultBillingDetails`. L’`EmbeddedPaymentElement` pré-remplit ses champs avec les valeurs que vous fournissez. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Merchant, Inc.") .defaultBillingDetails( PaymentSheet.BillingDetails( address = PaymentSheet.Address( country = "US", ), email = "foo@bar.com" ) ) .build() ``` ### Configurer la collecte des données de facturation Utiliser `BillingDetailsCollectionConfiguration` pour spécifier la manière dont vous souhaitez collecter les informations de facturation dans `EmbeddedPaymentElement`. Vous pouvez collecter le nom, l’adresse e-mail, le numéro de téléphone et l’adresse de votre client. Si vous souhaitez associer les informations de facturation par défaut à l’objet PaymentMethod même lorsque ces champs ne sont pas collectés dans l’interface utilisateur, définissez `billingDetailsCollectionConfiguration.attachDefaultsToPaymentMethod` sur `true`. ```kotlin import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration val billingDetails = PaymentSheet.BillingDetails( email = "foo@bar.com" ) val billingDetailsCollectionConfiguration = BillingDetailsCollectionConfiguration( attachDefaultsToPaymentMethod = true, name = BillingDetailsCollectionConfiguration.CollectionMode.Always, email = BillingDetailsCollectionConfiguration.CollectionMode.Never, address = BillingDetailsCollectionConfiguration.AddressCollectionMode.Full, ) val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Merchant, Inc.") .defaultBillingDetails(billingDetails) .billingDetailsCollectionConfiguration(billingDetailsCollectionConfiguration) .build() ``` > Consultez votre conseiller juridique au sujet des lois qui s’appliquent à la collecte d’informations. Ne collectez les numéros de téléphone que si vous en avez besoin pour la transaction. # Accepter un paiement et enregistrer le moyen de paiement > This is a Accepter un paiement et enregistrer le moyen de paiement for when platform is android and type is paymentsfu. View the full page at https://docs.stripe.com/payments/mobile/accept-payment-embedded?platform=android&type=paymentsfu. Utilisez l’[API Payment Intents](https://docs.stripe.com/api/payment_intents.md) pour enregistrer des informations de paiement à partir d’un achat. Il existe plusieurs cas d’utilisation : - Débiter un client pour une commande en ligne et sauvegarder les détails pour des achats ultérieurs. - Initier le premier paiement d’une série de paiements récurrents. - Débiter un acompte et sauvegarder les détails pour facturer plus tard le montant total. > #### Transactions avec présentation de la carte > > Les transactions avec présentation de la carte, telles que les paiements via Stripe Terminal, utilisent un processus différent pour enregistrer le moyen de paiement. Pour en savoir plus, consultez [la documentation de Terminal](https://docs.stripe.com/terminal/features/saving-payment-details/save-after-payment.md). ## Conformité Vous êtes responsable du respect de l’ensemble des lois, réglementations et règles des réseaux applicables lorsque vous enregistrez les informations de paiement d’un client pour une utilisation ultérieure, par exemple lorsque vous affichez son moyen de paiement dans le tunnel de paiement pour un achat futur ou lorsque vous le débitez alors qu’il n’utilise pas activement votre site web ou votre application. Avant d’enregistrer ou de débiter le moyen de paiement d’un client, assurez-vous de : - Ajouter des conditions d’utilisation à votre site web ou à votre application indiquant comment vous prévoyez d’enregistrer les informations relatives aux moyens de paiement, par exemple : - Le consentement du client vous autorisant à initier un paiement ou une série de paiements en son nom pour des transactions spécifiées. - Le calendrier et la fréquence prévus des paiements (par exemple, si les paiements concernent des versements échelonnés, des paiements d’abonnement ou des recharges non programmées). - La façon dont vous déterminez le montant du paiement. - Votre politique d’annulation, si le moyen de paiement est utilisé dans le cadre d’un abonnement - Utiliser un moyen de paiement enregistré uniquement dans le but indiqué dans vos conditions. - Recueillez le consentement explicite du client pour cet usage spécifique. Par exemple, incluez une case à cocher « Enregistrer mon moyen de paiement pour une utilisation ultérieure ». - Conserver une trace écrite de l’acceptation de vos conditions par le client. ## Configurer Stripe [Côté serveur] [Côté client] Pour commencer, vous devez créer un compte Stripe. [Inscrivez-vous maintenant](https://dashboard.stripe.com/register). ### Côté serveur Cette intégration exige des endpoints sur votre serveur qui communiquent avec l’API Stripe. Utilisez nos bibliothèques officielles pour accéder à l’API Stripe depuis votre serveur : #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ### Côté client Le [SDK Stripe Android](https://github.com/stripe/stripe-android) est disponible en open source et [fait l’objet d’une documentation complète](https://stripe.dev/stripe-android/). Pour installer le SDK, ajoutez `stripe-android` au bloc `dependencies` de votre fichier [app/build.gradle](https://developer.android.com/studio/build/dependencies) : #### Kotlin ```kotlin plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id("org.jetbrains.kotlin.plugin.compose") } android { ... kotlinOptions { jvmTarget = "11" } buildFeatures { compose true } } dependencies { // ... // Stripe Android SDK implementation("com.stripe:stripe-android:23.8.0") // Include the financial connections SDK to support US bank account as a payment method implementation("com.stripe:financial-connections:23.8.0") } ``` > Pour obtenir de plus amples informations sur la version la plus récente du SDK et ses versions antérieures, consultez la page des [versions](https://github.com/stripe/stripe-android/releases) sur GitHub. Pour savoir quand une nouvelle version est disponible, [surveillez les versions du référentiel](https://docs.github.com/en/github/managing-subscriptions-and-notifications-on-github/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository). Vous devez également définir votre [clé publiable](https://dashboard.stripe.com/apikeys) afin que le SDK puisse effectuer des appels à l’API vers Stripe. Pour commencer rapidement, vous pouvez coder cela en dur côté client pendant l’intégration, mais récupérer la clé publiable sur votre serveur en mode production. ```kotlin // Set your publishable key: remember to change this to your live publishable key in production // See your keys here: https://dashboard.stripe.com/apikeys PaymentConfiguration.init(context, publishableKey = "<>") ``` ## Activer des moyens de paiement Affichez vos [paramètres des moyens de paiement](https://dashboard.stripe.com/settings/payment_methods) et activez les moyens de paiement que vous souhaitez prendre en charge. Vous devez activer au moins un moyen de paiement pour créer un *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods). Par défaut, Stripe active les cartes bancaires et les autres moyens de paiement courants qui peuvent vous permettre d’atteindre davantage de clients. Nous vous recommandons toutefois d’activer d’autres moyens de paiement pertinents pour votre entreprise et vos clients. Consultez la page [Prise en charge des moyens de paiement](https://docs.stripe.com/payments/payment-methods/payment-method-support.md) pour en savoir plus sur la prise en charge des produits et des moyens de paiement, et notre [page des tarifs](https://stripe.com/pricing/local-payment-methods) pour prendre connaissance des frais que nous appliquons. ## Créer un objet Customer [Côté serveur] Pour configurer un moyen de paiement pour des paiements futurs, vous devez l’associer à un objet représentant votre client. Lorsque votre client crée un compte ou effectue sa première transaction avec votre entreprise, créez soit un objet [Account](https://docs.stripe.com/api/v2/core/accounts/create.md) configuré pour le client avec l’API Accounts v2, soit un objet [Customer](https://docs.stripe.com/api/customers/create.md) avec l’API Customers. > #### Utiliser l’API Accounts v2 pour représenter les clients > > L’API Accounts v2 est généralement disponible pour les utilisateurs de Connect et en aperçu public pour les autres utilisateurs de Stripe. Si vous avez accès à l’aperçu Accounts v2, vous devez [spécifier une version d’aperçu](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning) dans votre code. > > Pour demander l’accès à l’aperçu Accounts v2, > > Dans la plupart des cas d’usage, nous vous recommandons de [modéliser vos clients en tant qu’objets Account configurés par le client](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md), plutôt que d’utiliser des objets [Customer](https://docs.stripe.com/api/customers.md). ```curl curl -X POST https://api.stripe.com/v1/customers \ -u "<>:" ``` ## Collecter les informations de paiement [Côté client] L’Embedded Mobile Payment Element est conçu pour utilisation sur la page de paiement de votre application mobile native. L’élément affiche une liste de moyens de paiement, et vous pouvez le personnaliser pour l’adapter au visuel de votre application. Lorsque le client touche la ligne **Carte bancaire**, un formulaire s’ouvre, dans lequel il peut saisir les informations de son moyen de paiement. Le bouton dans le formulaire indique **Continuer** par défaut et entraîne la fermeture du formulaire lorsque lorsqu’il est utilisé, ce qui permet à votre client de terminer le paiement dans votre système de paiement. ![Payment Element intégré](https://b.stripecdn.com/docs-statics-srv/assets/android-embedded.1aefe2ca79ed073e350ec629a5af22d5.png) Vous avez également la possibilité de configurer le bouton pour qu’il termine immédiatement le processus de paiement au lieu de continuer. Pour ce faire, effectuez [cette étape](https://docs.stripe.com/payments/mobile/accept-payment-embedded.md#embedded-let-customer-pay-immediately) après avoir suivi le guide. ### Initialiser l’Embedded Payment Element #### Jetpack Compose Initialisez une instance de l’`EmbeddedPaymentElement` en utilisant la fonction `rememberEmbeddedPaymentElement` avec un `EmbeddedPaymentElement.Builder`. Transmettez un `CreateIntentWithConfirmationTokenCallback`. Vous pouvez laisser l’implémentation vide pour le moment, afin de préparer facilement l’intégration future des paiements. ```kotlin import com.stripe.android.paymentelement.EmbeddedPaymentElement import com.stripe.android.paymentelement.rememberEmbeddedPaymentElement @Composable fun CheckoutScreen() { val embeddedBuilder = remember { EmbeddedPaymentElement.Builder( createIntentCallback = { confirmationToken, -> TODO("You'll implement this in the "Confirm the payment" step") }, resultCallback = { result -> TODO("You'll implement this in the "Confirm the payment" step") }, ) } val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedBuilder) } ``` #### Vues (classique) Initialisez une instance de l’`EmbeddedPaymentElement` en utilisant la fonction `rememberEmbeddedPaymentElement` avec un `EmbeddedPaymentElement.Builder`. ```kotlin import com.stripe.android.paymentelement.EmbeddedPaymentElement import com.stripe.android.paymentelement.rememberEmbeddedPaymentElement @Composable fun CheckoutScreen() { val embeddedBuilder = remember { EmbeddedPaymentElement.Builder( createIntentCallback = { confirmationToken -> TODO("Completed in a later step.") }, resultCallback = { result -> TODO("Completed in a later step.") }, ) } val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedBuilder) } ``` Le Mobile Payment Element intégré est conçu pour l’interface Jetpack Compose et expose une méthode `@Composable Content`. Lors de l’utilisation de vues classiques, vous devez encapsuler le Payment Element intégré dans une `ComposeView`. ```xml ``` ```kotlin class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.checkout_screen_layout) val composeView = findViewById(R.id.compose_view) composeView.setContent { CheckoutScreen() } } } ``` ### Configurer l’Embedded Payment Element L’objet `Builder` contient les rappels nécessaires à l’instanciation de l’`EmbeddedPaymentElement`, y compris le `CreateIntentCallback`. Pour l’instant, laissez son implémentation vide. Après l’instanciation, appelez `configure` avec une `EmbeddedPaymentElement.Configuration` et une `PaymentSheet.IntentConfiguration`. L’objet `Configuration` contient les options générales pour `EmbeddedPaymentElement` qui ne changent pas entre les paiements. L’objet `IntentConfiguration` contient les détails du paiement spécifique, comme le montant et la devise. > Pour enregistrer les moyens de paiement dans `EmbeddedPaymentElement`, configurez `setupFutureUsage`. Vous pouvez définir le paramètre [setupFutureUsage](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-setup_future_usage) sur `IntentConfiguration` sur `onSession` ou `offSession`. Cette valeur est appliquée automatiquement à tous les moyens de paiement disponibles. ```kotlin import com.stripe.android.paymentsheet.PaymentSheet import com.stripe.android.paymentsheet.PaymentSheet.IntentConfiguration.SetupFutureUse @Composable fun CheckoutScreen() { val embeddedBuilder = .... val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedBuilder) LaunchedEffect(embeddedPaymentElement) { embeddedPaymentElement.configure( intentConfiguration = PaymentSheet.IntentConfiguration(mode = PaymentSheet.IntentConfiguration.Mode.Payment( amount = 1099, currency = "USD",setupFutureUse = SetupFutureUse.OffSession,),// Optional intent configuration options... ), configuration = EmbeddedPaymentElement.Configuration.Builder("Powdur").build() ) } } ``` ### Ajouter la vue Embedded Payment Element Une fois l’`EmbeddedPaymentElement` initialisé, placez son `@Composable Content` dans l’interface utilisateur de votre page de paiement. > Le contenu doit se trouver dans un conteneur déroulable, car sa hauteur peut changer après son affichage initial. ```kotlin @Composable fun CheckoutScreen() { val embeddedBuilder = .... val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedBuilder) ..... val scrollState = rememberScrollState() Column( modifier = Modifier .fillMaxSize() .verticalScroll(scrollState) .padding(16.dp) ) { embeddedPaymentElement.Content() } } ``` À ce stade, vous pouvez exécuter votre application et voir l’Embedded Mobile Payment Element. ### (Facultatif) Mettre à jour les informations de paiement Si un client modifie les détails du paiement (par exemple, en appliquant un code de réduction), mettez à jour l’instance `EmbeddedPaymentElement`. Lorsque vous appelez à nouveau la méthode `configure`, les nouvelles valeurs se synchronisent et s’affichent dans l’interface utilisateur. > Certains moyens de paiement, comme Google Pay, affichent le montant dans l’interface utilisateur. Si un client modifie le paiement et que vous ne mettez pas à jour l’élément `EmbeddedPaymentElement`, l’interface utilisateur affiche des valeurs incorrectes. Une fois l’appel à `configure` terminé, `@Composable Content` et `paymentOption` sont automatiquement mis à jour avec les nouvelles valeurs fournies lors de l’appel à `configure`. ```kotlin val intentConfiguration = PaymentSheet.IntentConfiguration( // Update the amount to reflect the price after applying the discount code mode = PaymentSheet.IntentConfiguration.Mode.Payment( amount = 999, currency = "USD", setupFutureUse = SetupFutureUse.OffSession, ), ) val configuration = EmbeddedPaymentElement.Configuration.Builder("Powdur") .build() LaunchedEffect(embeddedPaymentElement) { embeddedPaymentElement.configure( intentConfiguration = intentConfiguration, configuration = configuration, ) } ``` ### (Facultatif) Afficher l’option de paiement sélectionnée Vous pouvez afficher les détails de l’option de paiement (comme les 4 derniers chiffres, le logo de la carte ou les informations de facturation) en accédant à la propriété observable `Flow` de `paymentOption` dans le Payment Element intégré. Lorsqu’un client sélectionne un moyen de paiement qui ouvre un formulaire, l’option de paiement est mise à jour après qu’il ait appuyé sur **Continue** dans le formulaire. ```kotlin val selectedPaymentOption by embeddedPaymentElement.paymentOption.collectAsState() selectedPaymentOption?.let { paymentOption -> Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier .clickable( onClick = { }, ) .semantics { text = AnnotatedString(paymentOption.label) }, ) { Icon( painter = paymentOption.iconPainter, contentDescription = null, // decorative element modifier = Modifier.padding(horizontal = 4.dp), tint = Color.Unspecified, ) Text(text = paymentOption.label) } } ``` ### Confirmer le paiement Lorsque le client appuie sur le bouton de paiement, initiez le paiement en appelant `embeddedPaymentElement.confirm()`. Veillez à désactiver l’interaction avec l’utilisateur lors de la confirmation. Lorsqu’un formulaire est affiché, le `EmbeddedPaymentElement` appelle `confirm` lorsque l’utilisateur clique sur **Call to action**. Si le moyen de paiement sélectionné n’a aucun champ de formulaire, appelez `confirm` lorsque l’utilisateur clique sur **Call to action** sous le `@Composable Content`. ```kotlin Button( onClick = { embeddedPaymentElement.confirm() } ) { Text("Confirm payment") } ``` Ensuite, implémentez le rappel `createIntentCallback` que vous avez précédemment transmis à `EmbeddedPaymentElement.Builder` pour envoyer une requête à votre serveur. Votre serveur crée un `PaymentIntent` et renvoie la clé secrète du client, comme expliqué à la section [Créer un PaymentIntent](https://docs.stripe.com/payments/mobile/accept-payment-embedded.md#submit-payment). Lorsque vous recevez la requête, renvoyez le résultat de la création de l’Intent à l’aide de `CreateIntentResult` avec la clé secrète du client de la réponse de votre serveur ou une erreur. Le `EmbeddedPaymentElement` confirme le PaymentIntent en utilisant la clé secrète du client ou affiche le message d’erreur localisé dans son interface utilisateur. ```kotlin import com.stripe.android.paymentsheet.CreateIntentResult val embeddedBuilder = remember { val embeddedBuilder = EmbeddedPaymentElement.Builder( createIntentCallback = { confirmationToken ->// Make a request to your own server and receive a client secret or an error. val networkResult = ... if (networkResult.isSuccess) { CreateIntentResult.Success(networkResult.clientSecret) } else { CreateIntentResult.Failure(networkResult.exception) } }, resultCallback = { result ->when (result) { is EmbeddedPaymentElement.Result.Completed -> { // Payment completed - show a confirmation screen. } is EmbeddedPaymentElement.Result.Failed -> { // Encountered an unrecoverable error. You can display the error to the user, log it, and so on } is EmbeddedPaymentElement.Result.Canceled -> { // Customer canceled - you should probably do nothing. } } }, ) } ``` ## Optional: Décocher l’option de paiement sélectionnée Si vous avez des options de paiement externes à l’`EmbeddedPaymentElement`, vous devrez peut-être décocher l’option de paiement sélectionnée. Pour ce faire, utilisez l’API `clearPaymentOption`. ```kotlin @Composable fun CheckoutScreen() { val embeddedPaymentElementBuilder = .... val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedPaymentElementBuilder) .... Button( onClick = embeddedPaymentElement::clearPaymentOption ) { Text("Select external payment option") } } ``` ## Optional: Afficher vous-même le mandat Pour garantir la conformité réglementaire, l’Embedded Mobile Payment Element affiche les mandats et clauses de non-responsabilité par défaut. Ce texte doit être situé à proximité de votre bouton **Acheter**. Si vous désactivez l’affichage par défaut de ces éléments dans la vue, vous devez les afficher vous-même. > Pour être conforme, votre intégration doit afficher de manière appropriée le texte du mandat. Si vous l’affichez vous-même, assurez-vous que toutes les URL sont restituées correctement en incluant le texte dans un composable `Text`. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder("Merchant, Inc") .embeddedViewDisplaysMandateText(false) .build() .... val selectedPaymentOption by embeddedPaymentElement.paymentOption.collectAsState() selectedPaymentOption?.mandateText?.let { mandateText -> Text(mandateText) } ``` ## Optional: Permettre au client de payer immédiatement dans le formulaire ![Embedded Payment Element](https://b.stripecdn.com/docs-statics-srv/assets/embedded-pay-immediate.057c691220d43158ac8000de10815ed9.png) Pour configurer le bouton dans la feuille de formulaire afin qu’il confirme immédiatement le paiement, définissez `formSheetAction` sur votre objet `EmbeddedPaymentElement.Configuration`. Le bloc de finalisation s’exécute avec le résultat du paiement après la fermeture du formulaire. L’interface utilisateur intégrée n’étant pas utilisable une fois le paiement effectué, il est préférable que votre implémentation redirige l’utilisateur vers un autre écran, par exemple un écran de reçu. ```kotlin @Composable fun CheckoutScreen() { val embeddedBuilder = .... val embeddedPaymentElement = rememberEmbeddedPaymentElement(embeddedBuilder) LaunchedEffect(embeddedPaymentElement) { embeddedPaymentElement.configure( intentConfiguration = ...., configuration = EmbeddedPaymentElement.Configuration.Builder("Powdur") .formSheetAction(EmbeddedPaymentElement.FormSheetAction.Confirm) .build() ) } } ``` ## Créer un PaymentIntent [Côté serveur] Sur votre serveur, créez a *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods) en indiquant un montant et une devise. Vous pouvez gérer les moyens de paiement depuis le [Dashboard](https://dashboard.stripe.com/settings/payment_methods). Stripe gère le l’affichage des moyens de paiement admissibles en fonction de facteurs tels que le montant de la transaction, la devise et le tunnel de paiement. Pour éviter que des clients malveillants ne choisissent eux-mêmes leurs tarifs, décidez toujours du montant à débiter côté serveur (un environnement sécurisé) plutôt que côté client. Si l’appel réussit, renvoyez la *clé secrète du client* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)) du PaymentIntent. Si l’appel échoue, [traitez l’erreur](https://docs.stripe.com/error-handling.md) et renvoyez un message d’erreur avec une courte explication à l’intention de votre client. > Vérifiez que toutes les propriétés de l’IntentConfiguration correspondent à votre PaymentIntent (par exemple, `setup_future_usage`, `amount` et `currency`). #### Ruby ```ruby require 'stripe' # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. client = Stripe::StripeClient.new('<>') post '/create-intent' do data = JSON.parse request.body.read params = { customer: ..., # The Customer ID you previously created amount: 1099, currency: 'usd', setup_future_usage: 'off_session', automatic_payment_methods: {enabled: true}, } begin intent = client.v1.payment_intents.create(params) {client_secret: intent.client_secret}.to_json rescue Stripe::StripeError => e {error: e.error.message}.to_json end end ``` ## Gérer les événements post-paiement [Côté serveur] Stripe envoie un événement [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) à l’issue du paiement. Utilisez l’[outil de webhook du Dashboard](https://dashboard.stripe.com/webhooks) ou suivez le [guide consacré aux webhooks](https://docs.stripe.com/webhooks/quickstart.md) pour recevoir ces événements et exécuter des actions, comme envoyer une confirmation de commande par e-mail à votre client, enregistrer la vente dans une base de données ou lancer un flux de livraison. Plutôt que d’attendre un rappel de votre client, écoutez ces événements. Côté client, il arrive en effet que l’utilisateur ferme la fenêtre de son navigateur ou quitte l’application avant l’exécution du rappel. Certains clients malintentionnés peuvent d’autre part tenter de manipuler la réponse. En configurant votre intégration de manière à ce qu’elle écoute les événements asynchrones, vous pourrez accepter [plusieurs types de moyens de paiement](https://stripe.com/payments/payment-methods-guide) avec une seule et même intégration. En plus de l’événement `payment_intent.succeeded`, nous vous recommandons de gérer ces autres événements lorsque vous encaissez des paiements à l’aide de l’Element Payment : | Événement | Description | Action | | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.succeeded) | Envoyé lorsqu’un client effectue un paiement avec succès. | Envoyez au client une confirmation de commande et *traitez* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected) sa commande. | | [payment_intent.processing](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.processing) | Envoyé lorsqu’un client initie un paiement, mais qu’il ne l’a pas encore finalisé. Dans la plupart des cas, cet événement est envoyé lorsque le client initie un prélèvement bancaire. Il est suivi par un événement `payment_intent.succeeded` ou `payment_intent.payment_failed`. | Envoyez au client une confirmation de commande qui indique que son paiement est en attente. Pour des marchandises dématérialisées, vous pourrez traiter la commande sans attendre que le paiement soit effectué. | | [payment_intent.payment_failed](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.payment_failed) | Envoyé lorsqu’un client effectue une tentative de paiement qui se solde par un échec. | Si un paiement passe de l’état `processing` à `payment_failed`, proposez au client de retenter le paiement. | ## Tester l'intégration #### Cartes bancaires | Numéro de carte | Scénario | Méthode de test | | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 4242424242424242 | Le paiement par carte bancaire aboutit et ne nécessite pas d’authentification. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 4000002500003155 | Le paiement par carte bancaire requiert une *authentification* (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). | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 4000000000009995 | La carte est refusée avec un code de refus de type `insufficient_funds`. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | | 6205500000000000004 | La carte UnionPay a un numéro d’une longueur variable, allant de 13 à 19 chiffres. | Remplissez le formulaire de paiement par carte bancaire en saisissant le numéro de carte ainsi que la date d’expiration, le CVC et le code postal de votre choix. | #### Virements avec redirection bancaire | Moyen de paiement | Scénario | Méthode de test | | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Bancontact, iDEAL | Votre client ne parvient pas à s’authentifier sur la page de redirection en utilisant un moyen de paiement avec redirection et à notification immédiate. | Choisissez un moyen de paiement avec redirection, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Faire échouer le paiement test** sur la page qui s’affiche. | | Pay by Bank | Le montant dû est réglé via un moyen de paiement avec redirection et à [notification différée](https://docs.stripe.com/payments/payment-methods.md#payment-notification). | Choisissez le moyen de paiement, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Finaliser le paiement test** sur la page qui s’affiche. | | Pay by Bank | Votre client ne parvient pas à s’authentifier sur la page de redirection en utilisant un moyen de paiement avec redirection et à notification différée. | Choisissez le moyen de paiement, renseignez les informations demandées, puis confirmez le paiement. Enfin, cliquez sur **Faire échouer le paiement test** sur la page qui s’affiche. | | BLIK | Les paiements BLIK échouent de diverses manières : échecs immédiats (par exemple, code expiré ou non valide), erreurs différées (refus de la banque) ou expirations du délai (le client n’a pas répondu à temps). | Utiliser des modèles d’e-mail pour [simuler les différents échecs.](https://docs.stripe.com/payments/blik/accept-a-payment.md#simulate-failures) | #### Prélèvements bancaires | Moyen de paiement | Scénario | Méthode de test | | ---------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Prélèvement automatique SEPA | Le montant dû est réglé par prélèvement automatique SEPA. | Remplissez le formulaire à l’aide du numéro de compte `AT321904300235473204`. Le PaymentIntent confirmé passe d’abord à l’état processing, puis à l’état succeeded trois minutes plus tard. | | Prélèvement automatique SEPA | L’intention de paiement de votre client passe de l’état `processing` à l’état `requires_payment_method`. | Remplissez le formulaire à l’aide du numéro de compte `AT861904300235473202`. | Consultez la section consacrée aux [tests](https://docs.stripe.com/testing.md) pour obtenir des informations supplémentaires sur la manière de tester votre intégration. ## Optional: Définissez SetupFutureUsage pour les moyens de paiement individuels (Preview) [Côté serveur] [Côté client] Pour davantage de granularité, définissez `setupFutureUsage` pour des moyens de paiement spécifiques avec [PaymentSheet.IntentConfiguration.Mode.PaymentMethodOptions](https://github.com/stripe/stripe-android/blob/master/paymentsheet/src/main/java/com/stripe/android/paymentsheet/PaymentSheet.kt#L433). ```kotlin import com.stripe.android.model.PaymentMethod import com.stripe.android.paymentelement.PaymentMethodOptionsSetupFutureUsagePreview @OptIn(PaymentMethodOptionsSetupFutureUsagePreview::class) @Composable fun MyCheckoutScreen() { val embeddedPaymentElement = rememberEmbeddedPaymentElement( EmbeddedPaymentElement.Builder( createIntentCallback = { confirmationToken -> // Handle ConfirmationToken... } ) ) Column { embeddedPaymentElement.Content( intentConfiguration = PaymentSheet.IntentConfiguration( mode = PaymentSheet.IntentConfiguration.Mode.Payment( amount = 1099, currency = "usd",paymentMethodOptions = PaymentSheet.IntentConfiguration.Mode.PaymentMethodOptions( setupFutureUsageValues = mapOf( PaymentMethod.Type.Card to SetupFutureUse.OffSession, PaymentMethod.Type.CashAppPay to SetupFutureUse.OnSession ) ) ) ) ) } } ``` En savoir plus sur [les valeurs](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-payment_method_options) `setupFutureUsage` prises en charge pour chaque moyen de paiement. Ensuite, assurez-vous que votre serveur ne définit pas `setup_future_usage` ou `payment_method_options[X][setup_future_usage]` sur la demande de PaymentIntent. Le SDK gère automatiquement la configuration en fonction de l’`IntentConfiguration`. #### Ruby ```ruby require 'stripe' # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. client = Stripe::StripeClient.new('<>') post '/create-intent' do data = JSON.parse request.body.read params = { amount: 1099, currency: 'usd', confirmation_token: data['confirmation_token'], # In the latest version of the API, specifying the `automatic_payment_methods` parameter is optional because Stripe enables its functionality by default. automatic_payment_methods: {enabled: true}, } begin intent = client.v1.payment_intents.create(params) {client_secret: intent.client_secret}.to_json rescue Stripe::StripeError => e {error: e.error.message}.to_json end end ``` ## Optional: Activer les cartes sauvegardées [Côté serveur] [Côté client] `EmbeddedPaymentElement` peut permettre au client d’enregistrer sa carte bancaire et peut inclure les cartes bancaires enregistrées du client dans les moyens de paiement disponibles. Le client doit avoir un objet [Compte](https://docs.stripe.com/api/v2/core/accounts/create.md#v2_create_accounts-configuration-customer) configuré par le client ou un objet [Client](https://docs.stripe.com/api/customers/create.md) sur votre serveur. Pour activer une case à cocher qui permet au client d’enregistrer sa carte bancaire, créez une [CustomerSession](https://docs.stripe.com/api/customer_sessions.md), avec `payment_method_save` défini sur `enabled`. #### Comptes v2 ```javascript // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. const stripe = require("stripe")("<>"); const express = require('express'); const app = express(); app.set('trust proxy', true); app.use(express.json()); app.post('/payment-sheet', async (req, res) => { // Use an existing Account ID if this is a returning customer. const customer_account = await stripe.v2.core.accounts.create(); const customerSession = await stripe.customerSessions.create({ customer_account: customer_account.id, components: { mobile_payment_element: { enabled: true, features: { payment_method_save: 'enabled', payment_method_redisplay: 'enabled', payment_method_remove: 'enabled' } }, }, }); res.json({ customerSessionClientSecret: customerSession.client_secret, customer_account: customer_account.id, }); }); ``` Ensuite, configurez `EmbeddedPaymentElement` avec l’ID du client et la clé secrète du client `CustomerSession`. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Powdur") .customer( PaymentSheet.CustomerConfiguration.createWithCustomerSession( id = customerAccountId, clientSecret = customerSessionClientSecret, ) ) .build() embeddedPaymentElement.configure( intentConfiguration = // ... , configuration = configuration, ) ``` #### Clients v1 ```javascript // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. const stripe = require("stripe")("<>"); const express = require('express'); const app = express(); app.set('trust proxy', true); app.use(express.json()); app.post('/payment-sheet', async (req, res) => { // Use an existing Customer ID if this is a returning customer. const customer = await stripe.customers.create(); const customerSession = await stripe.customerSessions.create({ customer: customer.id, components: { mobile_payment_element: { enabled: true, features: { payment_method_save: 'enabled', payment_method_redisplay: 'enabled', payment_method_remove: 'enabled' } }, }, }); res.json({ customerSessionClientSecret: customerSession.client_secret, customer: customer.id, }); }); ``` Ensuite, configurez `EmbeddedPaymentElement` avec l’ID du client et la clé secrète du client `CustomerSession`. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Powdur") .customer( PaymentSheet.CustomerConfiguration.createWithCustomerSession( id = customerId, clientSecret = customerSessionClientSecret, ) ) .build() embeddedPaymentElement.configure( intentConfiguration = // ... , configuration = configuration, ) ``` ## Optional: Autoriser les moyens de paiement à notification différée [Côté client] Les *moyens de paiement différé* (A payment method that can't immediately return payment status when a customer attempts a transaction (for example, ACH debits). Businesses commonly hold an order in a pending state until payment is successful with these payment methods) ne vous garantissent pas de recevoir les fonds de votre client à l’issue du processus de paiement, soit parce qu’un certain délai est nécessaire (par exemple, les comptes bancaires États-Unis, les prélèvements SEPA, iDEAL, Bancontact et Sofort), soit parce que leur exécution nécessite une action de la part du client (par exemple, OXXO, Konbini et Boleto). Par défaut, l’`EmbeddedPaymentElement` n’affiche pas les moyens de paiement différé, même si vous les acceptez. Pour afficher les moyens de paiement différé que vous avez activés, définissez `allowsDelayedPaymentMethods` sur true dans votre `EmbeddedPaymentElement.Configuration`. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Powdur") .allowsDelayedPaymentMethods(true) .build() ``` Si le client utilise avec succès un moyen de paiement différé dans un `EmbeddedPaymentElement`, le résultat du paiement renvoyé est `EmbeddedPaymentElement.Result.Completed`. ## Optional: Activer Google Pay > Si votre écran de paiement comporte un bouton dédié **Google Pay**, suivez le [guide Google Pay](https://docs.stripe.com/google-pay.md?platform=android). Vous pouvez utiliser le Payment Element intégré pour gérer d’autres types de moyens de paiement. ### Configurer votre intégration Pour utiliser Google Pay, commencez par activer l’API Google Pay en ajoutant les informations suivantes au libellé `` de votre **AndroidManifest.xml** : ```xml ... ``` Pour en savoir plus, consultez cette page indiquant comment [configurer l’API Google Pay](https://developers.google.com/pay/api/android/guides/setup) pour Android. ### Ajouter Google Pay Pour ajouter Google Pay à votre intégration, transmettez un objet [PaymentSheet.GooglePayConfiguration](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-google-pay-configuration/index.html) avec votre environnement Google Pay (production ou test) et le [code pays de votre entreprise](https://dashboard.stripe.com/settings/account) lors de l’initialisation de l’`EmbeddedPaymentElement.Configuration`. ```kotlin val googlePayConfiguration = PaymentSheet.GooglePayConfiguration( environment = PaymentSheet.GooglePayConfiguration.Environment.Test, countryCode = "US", currencyCode = "USD" // Required for Setup Intents, optional for Payment Intents ) val configuration = EmbeddedPaymentElement.Configuration.Builder("Merchant, Inc.") .googlePay(googlePayConfiguration) .build() ``` ### Tester Google Pay Google vous permet d’effectuer des paiements de test via leur [suite de carte bancaire de test](https://developers.google.com/pay/api/android/guides/resources/test-card-suite). La suite de tests prend en charge l’utilisation de [cartes bancaires de test](https://docs.stripe.com/testing.md) de Stripe. Vous devez tester Google Pay à l’aide d’un appareil Android physique plutôt que d’un appareil simulé, dans un pays où Google Pay est pris en charge. Connectez-vous à un compte Google sur votre appareil de test avec une carte réelle enregistrée dans Google Wallet. ## Optional: Activer la numérisation de carte Pour activer la prise en charge de la numérisation des cartes bancaires, faites une [requête d’accès](https://developers.google.com/pay/api/android/guides/test-and-deploy/request-prod-access) à l’API Google Pay auprès de la [console Google Pay et Wallet](https://pay.google.com/business/console?utm_source=devsite&utm_medium=devsite&utm_campaign=devsite). - Si vous avez activé Google Pay, la fonctionnalité de numérisation de carte bancaire est automatiquement disponible dans notre interface utilisateur sur les appareils admissibles. Pour en savoir plus sur les appareils admissibles, consultez les [contraintes de l’API Google Pay](https://developers.google.com/pay/payment-card-recognition/debit-credit-card-recognition) - **Important :** la fonctionnalité de lecture de carte n’apparaît que dans les versions signées avec la même clé de signature enregistrée dans la [console Google Pay et Wallet](https://pay.google.com/business/console). Les versions de test ou de débogage utilisant différentes clés de signature (par exemple, les versions distribuées via Firebase App Tester) n’affichent pas l’option **Lire la carte**. Pour tester la lecture de carte dans les versions préliminaires, vous devez soit : - Signez vos versions de test avec votre clé de signature de production. - Ajoutez l’empreinte d’identification de votre clé de signature de test à la console Google Pay et Wallet Si votre application ne prend pas en charge Google Pay, vous pouvez utiliser le scanner de cartes Stripe. > Le scanner de carte Stripe est en version bêta publique. Pour activer la prise en charge de la numérisation de carte, ajoutez `stripecardscan` au bloc `dependencies` de votre fichier [app/build.gradle](https://developer.android.com/studio/build/dependencies) : #### Groovy ```groovy implementation 'com.stripe:stripecardscan:23.8.0' ``` ## Optional: Personnaliser le formulaire Toute personnalisation est configurée au moyen de l’objet `EmbeddedPaymentElement.Configuration`. ### Apparence Personnalisez les couleurs, les polices et plus encore afin de vous adapter à l’apparence de votre application à l’aide de l’[API Appearance](https://docs.stripe.com/elements/appearance-api/embedded-mobile.md?platform=android). ### Collecter les adresses des clients Recueillez les adresses de livraison et de facturation de vos clients à l’aide du composant [Address Element](https://docs.stripe.com/elements/address-element.md?platform=android). ### Personnaliser le nom d’entreprise à afficher Spécifiez un nom d’entreprise à afficher pour le client en définissant `merchantDisplayName`. Si vous ne spécifiez pas de nom, le nom de votre application s’affichera par défaut. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Merchant, Inc.") .build() ``` ### Spécifier les informations de facturation par défaut Pour définir des valeurs par défaut pour les informations de facturation collectées dans l’`EmbeddedPaymentElement`, configurez la propriété `defaultBillingDetails`. L’`EmbeddedPaymentElement` pré-remplit ses champs avec les valeurs que vous fournissez. ```kotlin val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Merchant, Inc.") .defaultBillingDetails( PaymentSheet.BillingDetails( address = PaymentSheet.Address( country = "US", ), email = "foo@bar.com" ) ) .build() ``` ### Configurer la collecte des données de facturation Utiliser `BillingDetailsCollectionConfiguration` pour spécifier la manière dont vous souhaitez collecter les informations de facturation dans `EmbeddedPaymentElement`. Vous pouvez collecter le nom, l’adresse e-mail, le numéro de téléphone et l’adresse de votre client. Si vous souhaitez associer les informations de facturation par défaut à l’objet PaymentMethod même lorsque ces champs ne sont pas collectés dans l’interface utilisateur, définissez `billingDetailsCollectionConfiguration.attachDefaultsToPaymentMethod` sur `true`. ```kotlin import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration val billingDetails = PaymentSheet.BillingDetails( email = "foo@bar.com" ) val billingDetailsCollectionConfiguration = BillingDetailsCollectionConfiguration( attachDefaultsToPaymentMethod = true, name = BillingDetailsCollectionConfiguration.CollectionMode.Always, email = BillingDetailsCollectionConfiguration.CollectionMode.Never, address = BillingDetailsCollectionConfiguration.AddressCollectionMode.Full, ) val configuration = EmbeddedPaymentElement.Configuration.Builder(merchantDisplayName = "Merchant, Inc.") .defaultBillingDetails(billingDetails) .billingDetailsCollectionConfiguration(billingDetailsCollectionConfiguration) .build() ``` > Consultez votre conseiller juridique au sujet des lois qui s’appliquent à la collecte d’informations. Ne collectez les numéros de téléphone que si vous en avez besoin pour la transaction. ## Optional: Activer la collecte du CVC à la confirmation Pour récupérer le CVC d’une carte bancaire enregistrée lors de la confirmation de PaymentIntent, votre intégration doit collecter les informations de paiement avant de créer un PaymentIntent. ### Mettre à jour la configuration de l’Intent `PaymentSheet.IntentConfiguration` accepte un paramètre facultatif qui contrôle le moment de récupérer le CVC pour une carte enregistrée. ```kotlin val intentConfig = PaymentSheet.IntentConfiguration( mode = PaymentSheet.IntentConfiguration.Mode.Payment( amount = 1099, currency = "usd", ),requireCvcRecollection = true, ) ``` ### Mettre à jour les paramètres de création de l’Intent Pour récupérer le CVC lors de la confirmation du paiement, ajoutez les paramètres `customerId` et `require_cvc_recollection` lors de la création du PaymentIntent. #### Ruby ```ruby require 'stripe' # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. client = Stripe::StripeClient.new('<>') post '/create-intent' do data = JSON.parse request.body.read params = { amount: 1099, currency: 'usd', automatic_payment_methods: {enabled: true},customer: customer.id, payment_method_options: { card: {require_cvc_recollection: true} }, } begin intent = client.v1.payment_intents.create(params) {client_secret: intent.client_secret}.to_json rescue Stripe::StripeError => e {error: e.error.message}.to_json end end ``` # Accepter un paiement > This is a Accepter un paiement for when platform is react-native and type is payment. View the full page at https://docs.stripe.com/payments/mobile/accept-payment-embedded?platform=react-native&type=payment. Le Payment Element vous permet d’accepter plusieurs moyens de paiement à l’aide d’une seule intégration. Vous allez créer un tunnel de paiement personnalisé dans lequel vous afficherez le Payment Element, créerez le *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods) et confirmerez le paiement depuis votre application. ## Configurer Stripe [Côté serveur] [Côté client] ### Côté serveur Cette intégration exige que votre serveur dispose de endpoints qui communiquent avec l’API Stripe. Utilisez nos bibliothèques officielles pour accéder à l’API Stripe depuis votre serveur : #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ### Côté client Le [SDK React Native](https://github.com/stripe/stripe-react-native) est disponible en open source et fait l’objet d’une documentation complète. En interne, il utilise des SDK [Android](https://github.com/stripe/stripe-android) et [iOS natifs](https://github.com/stripe/stripe-ios). Pour installer le SDK React Native de Stripe, exécutez l’une des commandes suivantes dans le répertoire de votre projet (selon le gestionnaire de paquets que vous utilisez) : #### yarn ```bash yarn add @stripe/stripe-react-native ``` #### npm ```bash npm install @stripe/stripe-react-native ``` Ensuite, installez les autres dépendances nécessaires : - Pour iOS, accédez au directeur **ios** et exécutez `pod install` pour vous assurer que vous installez également les dépendances natives requises. - Pour Android, il n’y a plus de dépendances à installer. > Nous vous recommandons de suivre le [guide officiel de TypeScript](https://reactnative.dev/docs/typescript#adding-typescript-to-an-existing-project) pour ajouter la prise en charge de TypeScript. ### Initialisation de Stripe Pour initialiser Stripe dans votre application React Native, wrappez votre écran de paiement avec le composant `StripeProvider` ou utilisez la méthode d’initialisation `initStripe`. Seule la [clé publiable](https://docs.stripe.com/keys.md#obtain-api-keys) de l’API dans `publishableKey` est nécessaire. L’exemple suivant montre comment initialiser Stripe à l’aide du composant `StripeProvider`. ```jsx import { useState, useEffect } from 'react'; import { StripeProvider } from '@stripe/stripe-react-native'; function App() { const [publishableKey, setPublishableKey] = useState(''); const fetchPublishableKey = async () => { const key = await fetchKey(); // fetch key from your server here setPublishableKey(key); }; useEffect(() => { fetchPublishableKey(); }, []); return ( {/* Your app code here */} ); } ``` > Utilisez vos [clés de test](https://docs.stripe.com/keys.md#obtain-api-keys) d’API lors de vos activités de test et de développement, et vos clés du [mode production](https://docs.stripe.com/keys.md#test-live-modes) pour la publication de votre application. ## Activer des moyens de paiement Affichez vos [paramètres des moyens de paiement](https://dashboard.stripe.com/settings/payment_methods) et activez les moyens de paiement que vous souhaitez prendre en charge. Vous devez activer au moins un moyen de paiement pour créer un *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods). Par défaut, Stripe active les cartes bancaires et les autres moyens de paiement courants qui peuvent vous permettre d’atteindre davantage de clients. Nous vous recommandons toutefois d’activer d’autres moyens de paiement pertinents pour votre entreprise et vos clients. Consultez la page [Prise en charge des moyens de paiement](https://docs.stripe.com/payments/payment-methods/payment-method-support.md) pour en savoir plus sur la prise en charge des produits et des moyens de paiement, et notre [page des tarifs](https://stripe.com/pricing/local-payment-methods) pour prendre connaissance des frais que nous appliquons. ## Recueillir les informations de paiement [Côté client] ### Initialiser le composant Embedded Payment Element Utilisez le hook `useEmbeddedPaymentElement` pour créer et afficher le Payment Element intégré dans votre application React Native. Ce hook nécessite deux objets de configuration : - `EmbeddedPaymentElementConfiguration` : paramètres généraux (par exemple, `returnURL`). - `IntentConfiguration` : informations spécifiques au paiement (par exemple, montant, devise et rappel `confirmationTokenConfirmHandler`). Le hook renvoie un objet avec le composant React `embeddedPaymentElementView` et d’autres méthodes d’assistance. Pour obtenir la liste complète des options et des valeurs renvoyées, consultez la [documentation sur le SDK React Native Stripe](https://stripe.dev/stripe-react-native/api-reference/interfaces/UseEmbeddedPaymentElementResult.html). > L’implémentation de `confirmationTokenConfirmHandler` est obligatoire, mais, pour cette étape, vous pouvez laisser la fonctionnalité vide et l’implémenter plus tard. ```jsx import { useState, useCallback, useEffect } from 'react'; import { useEmbeddedPaymentElement, IntentConfiguration, EmbeddedPaymentElementConfiguration, IntentCreationCallbackParams, } from '@stripe/stripe-react-native'; function MyCheckoutComponent() { const [intentConfig, setIntentConfig] = useState(null); const [elementConfig, setElementConfig] = useState(null); const initialize = useCallback(() => { const newIntentConfig: IntentConfiguration = { mode: { amount: 1099, currencyCode: 'USD', }, confirmationTokenConfirmHandler: async ( confirmationToken, callback: (params: IntentCreationCallbackParams) => void ) => { // You'll implement this in the "Confirm the payment" section below }, }; const newElementConfig: EmbeddedPaymentElementConfiguration = { merchantDisplayName: 'Your Business Name', returnURL: 'your-app://stripe-redirect', }; setIntentConfig(newIntentConfig); setElementConfig(newElementConfig); }, []); const { embeddedPaymentElementView, paymentOption, confirm, update, clearPaymentOption, loadingError, isLoaded, } = useEmbeddedPaymentElement( intentConfig!, elementConfig! ); useEffect(() => { initialize(); }, [initialize]); } ``` ### Ajouter la vue Embedded Payment Element Une fois le hook `useEmbeddedPaymentElement` initialisé, incluez `embeddedPaymentElementView` dans votre composant pour afficher le Payment Element intégré dans l’interface utilisateur de votre paiement. > Si `isLoaded` ne passe jamais à `true`, assurez-vous que `embeddedPaymentElementView` reste toujours dans l’arbre de rendu de votre composant. Sur Android, la vue native doit être montée pour que l’initialisation soit terminée. Contrôlez la visibilité via l’opacité plutôt que par un rendu conditionnel de la vue, comme montré dans l’exemple ci-dessous. ```jsx import { View, Text, ActivityIndicator } from 'react-native'; function MyCheckoutComponent() { // Other component code remains the same return ( {/* Handle loading errors through the loadingError property */} {loadingError && ( Failed to load payment form: {loadingError.message || String(loadingError)} )} {/* Keep the view in the render tree for Android, control visibility with opacity */} {embeddedPaymentElementView} {/* Show loading indicator while the view is loading */} {!loadingError && !isLoaded && ( )} ); } ``` Vous pouvez maintenant exécuter votre application et voir le Payment Element mobile intégré. ### (Facultatif) Afficher l’option de paiement sélectionnée Le hook `useEmbeddedPaymentElement` fournit une propriété `paymentOption` dans son objet de retour. Vous pouvez l’utiliser pour accéder à des informations sur l’option de paiement sélectionnée par le client, telles qu’une étiquette (par exemple, « ····4242 »), une image (par exemple, un logo VISA) ou des détails de facturation à afficher dans votre interface utilisateur. La propriété `paymentOption` est réactive, c’est-à-dire qu’elle se met automatiquement à jour lorsque l’option de paiement sélectionnée change. Vous n’avez pas besoin d’implémenter une méthode de délégation distincte. Au lieu de cela, vous pouvez utiliser cette propriété directement dans votre composant, et React le restitue chaque fois que `paymentOption` change. ```jsx import { View, Text, Image } from 'react-native'; function MyCheckoutComponent() { // Other component code remains the same return ( // Other component code remains the same // Display the currently selected payment option (label and image) {paymentOption?.image && ( )} Selected: {paymentOption?.label ?? 'None'} ); } ``` ### (Facultatif) Mettre à jour les informations de paiement Lorsque le client effectue des actions qui modifient les informations de paiement (par exemple, l’application d’un code de réduction), mettez à jour l’instance `EmbeddedPaymentElement` pour refléter les nouvelles valeurs en appelant la méthode de mise à jour. Certains moyens de paiement, comme Apple Pay et Google Pay, affichent le montant dans l’interface utilisateur. Vérifiez donc qu’il est toujours exact et à jour. Une fois l’appel de mise à jour terminé, mettez à jour votre interface utilisateur. L’appel de mise à jour peut modifier l’option de paiement sélectionnée par le client. > Utilisez toujours `await` lors de l’appel à l’API `update` pour garantir que les états de chargement s’exécutent dans le bon ordre. Sans `await`, l’indicateur de chargement peut disparaître avant la fin de la mise à jour. ```jsx import { useState, useCallback } from 'react'; import { View, Button, ActivityIndicator } from 'react-native'; function MyCheckoutComponent() { // Other component code remains the same const [isUpdating, setIsUpdating] = useState(false); const handleUpdate = useCallback(async () => { // Create a new IntentConfiguration object with updated values const updatedIntentConfig: IntentConfiguration = { ...intentConfig!, mode: { amount: 999, // Updated amount after applying discount code currencyCode: 'USD', }, }; setIsUpdating(true); try { await update(updatedIntentConfig); } catch (error) { // Handle any unexpected errors console.error('Unexpected error during update:', error); } finally { setIsUpdating(false); } }, [intentConfig, update]); // Example of how to use the handleUpdate function const applyDiscountCode = useCallback(async (discountCode: string) => { // Validate discount code with your server try { const response = await fetch('https://your-server.com/apply-discount', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ discountCode }), }); if (response.ok) { // Update the intent configuration with the new amount await handleUpdate(); } } catch (error) { console.error('Failed to apply discount:', error); } }, [handleUpdate]); return ( {/* Hide view and show loading indicator during update */} {embeddedPaymentElementView} {isUpdating && ( )}