# Guardar datos de pago durante un pago dentro de la aplicación Guarda los datos de pago durante un pago en tu aplicación móvil. > #### Soporte de la API Accounts v2 > > Payment Sheet no ofrece soporte para *cuentas configuradas por el cliente*. Solo admite objetos `Customer`. # iOS > This is a iOS for when platform is ios and mobile-ui is payment-sheet. View the full page at https://docs.stripe.com/payments/mobile/save-during-payment?platform=ios&mobile-ui=payment-sheet. Usa la [API Payment Intents](https://docs.stripe.com/api/payment_intents.md) para guardar los datos de pago de una compra. Existen varios casos de uso: - Cóbrale al cliente un pedido de e-commerce y almacena los datos para compras futuras. - Inicia el primer pago de una serie de pagos recurrentes. - Cobra un depósito y almacena los datos para cobrar el importe total más tarde. > #### Transacciones con tarjeta presente > > Las transacciones con tarjeta presente, como los pagos a través de Stripe Terminal, utilizan un proceso diferente para guardar el método de pago. Para obtener más detalles, consulta [la documentación de Terminal](https://docs.stripe.com/terminal/features/saving-payment-details/save-after-payment.md). ## Cumplimiento de la normativa Eres responsable de cumplir con todas las leyes, normativas y reglas de red aplicables al guardar los datos de pago de un cliente para su uso futuro, como mostrarle su método de pago durante el proceso de pago de una compra futura o realizar un cargo cuando no esté utilizando activamente tu sitio web o tu aplicación. Antes de guardar o realizar un cargo en el método de pago de un cliente, asegúrate de: - Agrega Condiciones a tu sitio web o aplicación que indiquen cómo planeas guardar los datos del método de pago, por ejemplo, lo siguiente: - El acuerdo del cliente para que puedas iniciar un pago o una serie de pagos en su nombre para transacciones específicas. - El momento y la frecuencia previstos de los pagos (por ejemplo, si los cargos son por cuotas programadas, pagos de suscripciones o recargas no programadas). - Cómo determinas el importe de pago. - Tu política de cancelación, si el método de pago es para un servicio por suscripción. - Usa un método de pago guardado solo para los fines indicados en tus Condiciones. - Obtén el consentimiento explícito del cliente para este uso específico. Por ejemplo, incluye una casilla de verificación que indique «Guardar mi método de pago para usarlo en el futuro». - Mantén un registro del acuerdo escrito de tu cliente con tus Condiciones. ## Configura Stripe [Lado del servidor] [Lado del cliente] Primero, necesitas una cuenta de Stripe. [Regístrate ahora](https://dashboard.stripe.com/register). ### Lado del servidor Esta integración requiere puntos de conexión en tu servidor que se comuniquen con la API de Stripe. Usa nuestras bibliotecas oficiales para acceder a la esta API desde tu servidor: #### 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' ``` ### Lado del cliente El [SDK para iOS de Stripe](https://github.com/stripe/stripe-ios) es de código abierto, está [plenamente documentado](https://stripe.dev/stripe-ios/index.html) y es compatible con aplicaciones que admiten iOS 13 o posterior. #### Swift Package Manager Para instalar el SDK, sigue estos pasos: 1. En Xcode, selecciona **Archivo** > **Agregar dependencias de paquetes…** e introduce `https://github.com/stripe/stripe-ios-spm` como URL del repositorio. 1. Selecciona el número de versión más reciente en nuestra [página de versiones](https://github.com/stripe/stripe-ios/releases). 1. Agrega el producto **StripePaymentSheet** al [objetivo de tu aplicación](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app). #### CocoaPods 1. Si aún no lo has hecho, instala la última versión de [CocoaPods](https://guides.cocoapods.org/using/getting-started.html). 1. Si no tienes un [Podfile](https://guides.cocoapods.org/syntax/podfile.html), crea uno al ejecutar el siguiente comando: ```bash pod init ``` 1. Agrega esta línea a tu `Podfile`: ```podfile pod 'StripePaymentSheet' ``` 1. Ejecuta el siguiente comando: ```bash pod install ``` 1. De ahora en adelante, no olvides usar el archivo `.xcworkspace` en lugar del archivo `.xcodeproj` para abrir tu proyecto en Xcode. 1. En el futuro, para actualizar a la última versión del SDK, ejecuta lo siguiente: ```bash pod update StripePaymentSheet ``` #### Carthage 1. Si aún no lo has hecho, instala la última versión de [Carthage](https://github.com/Carthage/Carthage#installing-carthage). 1. Agrega esta línea a tu `Cartfile`: ```cartfile github "stripe/stripe-ios" ``` 1. Sigue las [instrucciones de instalación de Carthage](https://github.com/Carthage/Carthage#if-youre-building-for-ios-tvos-or-watchos). Asegúrate de incrustar todos los frameworks obligatorios enumerados [aquí](https://github.com/stripe/stripe-ios/tree/master/StripePaymentSheet/README.md#manual-linking). 1. En el futuro, para actualizar a la última versión del SDK, ejecuta el siguiente comando: ```bash carthage update stripe-ios --platform ios ``` #### Framework manual 1. Ve a nuestra [página de versiones de GitHub](https://github.com/stripe/stripe-ios/releases/latest) y descarga y descomprime **Stripe.xcframework.zip**. 1. Arrastra **StripePaymentSheet.xcframework** a la sección **Binarios incrustados** de la configuración **General** de tu proyecto en Xcode. Asegúrate de seleccionar **Copiar elementos si es necesario**. 1. Repite el paso 2 para todos los frameworks obligatorios enumerados [aquí](https://github.com/stripe/stripe-ios/tree/master/StripePaymentSheet/README.md#manual-linking). 1. En el futuro, para actualizar a la última versión de nuestro SDK, repite los pasos 1 a 3. > Para obtener más detalles sobre la última versión del SDK y las versiones anteriores, consulta la página [Versiones](https://github.com/stripe/stripe-ios/releases) en GitHub. Para recibir notificaciones cuando se publique una nueva versión, [mira las versiones](https://help.github.com/en/articles/watching-and-unwatching-releases-for-a-repository#watching-releases-for-a-repository) del repositorio. ## Habilita métodos de pago Los pagos con tarjeta están habilitados de forma predeterminada. Consulta la [configuración de tus métodos de pago](https://dashboard.stripe.com/settings/payment_methods) para habilitar más métodos de pago que quieras admitir. ## Agregar un punto de conexión [Lado del servidor] > #### Nota > > Para mostrar la PaymentSheet antes de crear un PaymentIntent, consulta [Recopila datos de pago antes de crear un Intent](https://docs.stripe.com/payments/accept-a-payment-deferred.md?type=payment). Esta integración usa tres objetos de la API de Stripe: 1. [PaymentIntent](https://docs.stripe.com/api/payment_intents.md): Stripe lo utiliza para representar tu intención de cobrarle a un cliente, haciendo el seguimiento de los intentos de cobro y de los cambios en el estado del pago a lo largo del proceso. 1. Una [Account configurada por el cliente](https://docs.stripe.com/api/v2/core/accounts/object.md#v2_account_object-applied_configurations) o un [Customer](https://docs.stripe.com/api/customers.md) Object: para configurar un método de pago para pagos futuros, debes asociarlo a un cliente. Crea un objeto que represente a tu cliente cuando cree una cuenta en tu negocio. Si tu cliente realiza un pago como invitado, puedes crear una `Account` o `Customer` Object antes del pago y asociarlo más adelante con tu propia representación interna de la cuenta del cliente. 1. [CustomerSession](https://docs.stripe.com/api/customer_sessions.md): la información del objeto que representa a tu cliente es sensible y no se puede recuperar directamente desde una app. Una `CustomerSession` le otorga al SDK acceso temporal con alcance limitado a la `Account` o `Customer` y proporciona opciones de configuración adicionales. Consulta la lista completa de [opciones de configuración](https://docs.stripe.com/api/customer_sessions/create.md#create_customer_session-components). Por motivos de seguridad, tu aplicación no puede crear estos objetos. En su lugar, agrega un punto de conexión en tu servidor que haga lo siguiente: 1. Recupera el objeto `Account` o `Customer`, o crea uno nuevo. 1. Crea una [CustomerSession](https://docs.stripe.com/api/customer_sessions.md) para el objeto `Account` o `Customer`. 1. Crea un `PaymentIntent` con el [importe](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-amount), la [moneda](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-currency), [setup_future_usage](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-setup_future_usage), y el [customer_account](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer_account) o el [customer](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer). 1. Devuelve el *client secret* (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)) del `PaymentIntent`, el `client_secret` de la `CustomerSession`, el ID del `Account` o `Customer` y tu [clave publicable](https://dashboard.stripe.com/apikeys) a tu app. > El Payment Element móvil solo admite `setup_future_usage` con tarjetas y cuentas bancarias de EE. UU. Los métodos de pago que se muestran a los clientes durante el proceso de compra también se incluyen en el PaymentIntent. Puedes permitir que Stripe extraiga los métodos de pago de tu configuración del Dashboard o puedes enumerarlos manualmente. Independientemente de la opción que elijas, debes saber que la moneda especificada en el PaymentIntent filtra los métodos de pago que se muestran al cliente. Por ejemplo, si especificas `eur` en el PaymentIntent y tienes habilitado OXXO en el Dashboard, OXXO no se mostrará al cliente porque OXXO no admite pagos en `eur`. A menos que tu integración requiera una opción basada en código para ofrecer métodos de pago, Stripe recomienda usar la opción automatizada. Esto se debe a que Stripe evalúa la moneda, las restricciones de los métodos de pago y otros parámetros para determinar la lista de métodos de pago admitidos. Se les da prioridad a los métodos de pago que aumentan la conversión y guardan mayor relación con la moneda y la ubicación del cliente. #### Gestionar los métodos de pago desde el Dashboard Puedes administrar los métodos de pago desde el [Dashboard](https://dashboard.stripe.com/settings/payment_methods). Stripe maneja la devolución de métodos de pago elegibles según factores como el monto de la transacción, la moneda y el flujo de pago. El PaymentIntent se crea según los métodos de pago que configuraste en el Dashboard. Si no quieres usar el Dashboard o si quieres especificar métodos de pago manualmente, puedes enumerarlos usando el atributo `payment_method_types`. #### curl ```bash # Create a Customer (use an existing Customer ID if this is a returning customer) curl https://api.stripe.com/v1/customers \ -u <>: \ -X "POST" \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" # Create an CustomerSession for the Customer curl https://api.stripe.com/v1/customer_sessions \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "components[mobile_payment_element][enabled]"=true \ -d "components[mobile_payment_element][features][payment_method_save]"=enabled \ -d "components[mobile_payment_element][features][payment_method_redisplay]"=enabled \ -d "components[mobile_payment_element][features][payment_method_remove]"=enabled # Create a PaymentIntent curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \ -d "setup_future_usage"="off_session" \ -d "automatic_payment_methods[enabled]"=true \ ``` #### Cómo enumerar métodos de pago manualmente #### curl ```bash # Create a Customer (use an existing Customer ID if this is a returning customer) curl https://api.stripe.com/v1/customers \ -u <>: \ -X "POST" \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" # Create an CustomerSession for the Customer curl https://api.stripe.com/v1/customer_sessions \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "components[mobile_payment_element][enabled]"=true \ -d "components[mobile_payment_element][features][payment_method_save]"=enabled \ -d "components[mobile_payment_element][features][payment_method_redisplay]"=enabled \ -d "components[mobile_payment_element][features][payment_method_remove]"=enabled # Create a PaymentIntent curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \ -d "setup_future_usage"="off_session" \ -d "payment_method_types[]"="card" \ ``` > Cada método de pago debe admitir la moneda especificada en el PaymentIntent, y tu empresa tiene que estar establecida en uno de los países que admite cada método de pago. Consulta la página de [opciones de integración de métodos de pago](https://docs.stripe.com/payments/payment-methods/integration-options.md) para obtener más información sobre qué admitimos. ## Recopila datos de pago [Lado del cliente] Para mostrar el Payment Element móvil en la pantalla de confirmación de compra: - Muestra los productos que compra el cliente junto con el importe total - Usa el [Address Element](https://docs.stripe.com/elements/address-element.md?platform=ios) para recopilar la información de envío necesaria del cliente - Agrega un botón de confirmación de compra para mostrar la interfaz de usuario (IU) de Stripe #### UIKit #### Accounts v2 En la pantalla de confirmación de compra de tu aplicación, obtén el secreto de cliente PaymentIntent, el secreto de cliente `CustomerSession`, el ID de la `cuenta`configurada por el cliente y la clave publicable del punto de conexión que creaste en el paso anterior. Usa `STPAPIClient.shared` para establecer tu clave publicable e iniciar la [PaymentSheet](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet.html). #### iOS (Swift) ```swift import UIKit@_spi(CustomerSessionBetaAccess) import StripePaymentSheet class CheckoutViewController: UIViewController { @IBOutlet weak var checkoutButton: UIButton! var paymentSheet: PaymentSheet? let backendCheckoutUrl = URL(string: "Your back-end endpoint/payment-sheet")! // Your back-end endpoint override func viewDidLoad() { super.viewDidLoad() checkoutButton.addTarget(self, action: #selector(didTapCheckoutButton), for: .touchUpInside) checkoutButton.isEnabled = false // MARK: Fetch the PaymentIntent client secret, CustomerSession client secret, customer-configured Account ID, and publishable key var request = URLRequest(url: backendCheckoutUrl) request.httpMethod = "POST" let task = URLSession.shared.dataTask(with: request, completionHandler: { [weak self] (data, response, error) in guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any], let customerAccountId = json["customerAccount"] as? String, let customerSessionClientSecret = json["customerSessionClientSecret"] as? String, let paymentIntentClientSecret = json["paymentIntent"] as? String, let publishableKey = json["publishableKey"] as? String, let self = self else { // Handle error return } STPAPIClient.shared.publishableKey = publishableKey// MARK: Create a PaymentSheet instance var configuration = PaymentSheet.Configuration() configuration.merchantDisplayName = "Example, Inc." configuration.customerAccount = .init(id: customerAccountId, customerSessionClientSecret: customerSessionClientSecret) // Set `allowsDelayedPaymentMethods` to true if your business handles // delayed notification payment methods like US bank accounts. configuration.allowsDelayedPaymentMethods = true self.paymentSheet = PaymentSheet(paymentIntentClientSecret:paymentIntentClientSecret, configuration: configuration) DispatchQueue.main.async { self.checkoutButton.isEnabled = true } }) task.resume() } } ``` #### Customers v1 En la pantalla de confirmación de compra de tu aplicación, obtén el secreto de cliente PaymentIntent, el secreto de cliente `CustomerSession`, el ID del `cliente` y la clave publicable del punto de conexión que creaste en el paso anterior. Usa `STPAPIClient.shared` para establecer tu clave publicable e iniciar la [PaymentSheet](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet.html). #### iOS (Swift) ```swift import UIKit@_spi(CustomerSessionBetaAccess) import StripePaymentSheet class CheckoutViewController: UIViewController { @IBOutlet weak var checkoutButton: UIButton! var paymentSheet: PaymentSheet? let backendCheckoutUrl = URL(string: "Your backend endpoint/payment-sheet")! // Your backend endpoint override func viewDidLoad() { super.viewDidLoad() checkoutButton.addTarget(self, action: #selector(didTapCheckoutButton), for: .touchUpInside) checkoutButton.isEnabled = false // MARK: Fetch the PaymentIntent client secret, CustomerSession client secret, Customer ID, and publishable key var request = URLRequest(url: backendCheckoutUrl) request.httpMethod = "POST" let task = URLSession.shared.dataTask(with: request, completionHandler: { [weak self] (data, response, error) in guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any], let customerId = json["customer"] as? String, let customerSessionClientSecret = json["customerSessionClientSecret"] as? String, let paymentIntentClientSecret = json["paymentIntent"] as? String, let publishableKey = json["publishableKey"] as? String, let self = self else { // Handle error return } STPAPIClient.shared.publishableKey = publishableKey// MARK: Create a PaymentSheet instance var configuration = PaymentSheet.Configuration() configuration.merchantDisplayName = "Example, Inc." configuration.customer = .init(id: customerId, customerSessionClientSecret: customerSessionClientSecret) // Set `allowsDelayedPaymentMethods` to true if your business handles // delayed notification payment methods like US bank accounts. configuration.allowsDelayedPaymentMethods = true self.paymentSheet = PaymentSheet(paymentIntentClientSecret:paymentIntentClientSecret, configuration: configuration) DispatchQueue.main.async { self.checkoutButton.isEnabled = true } }) task.resume() } } ``` Cuando el cliente toca el botón **Checkout**, llama a `present` para presentar la PaymentSheet. Después de que el cliente complete el pago, Stripe descarta la PaymentSheet y llama al bloque de finalización con [PaymentSheetResult](https://stripe.dev/stripe-ios/stripe-paymentsheet/Enums/PaymentSheetResult.html). #### iOS (Swift) ```swift @objc func didTapCheckoutButton() { // MARK: Start the checkout process paymentSheet?.present(from: self) { paymentResult in // MARK: Handle the payment result switch paymentResult { case .completed: print("Your order is confirmed") case .canceled: print("Canceled!") case .failed(let error): print("Payment failed: \(error)") } } } ``` #### SwiftUI #### Accounts v2 Crea un modelo `ObservableObject` para tu pantalla de confirmación de compra. Este modelo publica una [PaymentSheet](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet.html) y un [PaymentSheetResult](https://stripe.dev/stripe-ios/stripe-paymentsheet/Enums/PaymentSheetResult.html). ```swift import StripePaymentSheet import SwiftUI class CheckoutViewModel: ObservableObject { let backendCheckoutUrl = URL(string: "Your back-end endpoint/payment-sheet")! // Your back-end endpoint @Published var paymentSheet: PaymentSheet? @Published var paymentResult: PaymentSheetResult? } ``` Obtén el secreto de cliente PaymentIntent, el secreto de cliente `CustomerSession`, el ID de la `cuenta` configurada por el cliente y la clave publicable del punto de conexión que creaste en el paso anterior. Usa `STPAPIClient.shared` para establecer tu clave publicable e iniciar la [PaymentSheet](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet.html). ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet import SwiftUI class CheckoutViewModel: ObservableObject { let backendCheckoutUrl = URL(string: "Your back-end endpoint/payment-sheet")! // Your back-end endpoint @Published var paymentSheet: PaymentSheet? @Published var paymentResult: PaymentSheetResult? func preparePaymentSheet() { // MARK: Fetch thePaymentIntent and customer information from the back end var request = URLRequest(url: backendCheckoutUrl) request.httpMethod = "POST" let task = URLSession.shared.dataTask(with: request, completionHandler: { [weak self] (data, response, error) in guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any], let customerAccountId = json["customerAccount"] as? String, let customerSessionClientSecret = json["customerSessionClientSecret"] as? String, letpaymentIntentClientSecret = json["paymentIntent"] as? String, let publishableKey = json["publishableKey"] as? String, let self = self else { // Handle error return } STPAPIClient.shared.publishableKey = publishableKey// MARK: Create a PaymentSheet instance var configuration = PaymentSheet.Configuration() configuration.merchantDisplayName = "Example, Inc." configuration.customerAccount = .init(id: customerAccountId, customerSessionClientSecret: customerSessionClientSecret) // Set `allowsDelayedPaymentMethods` to true if your business handles // delayed notification payment methods like US bank accounts. configuration.allowsDelayedPaymentMethods = true DispatchQueue.main.async { self.paymentSheet = PaymentSheet(paymentIntentClientSecret:paymentIntentClientSecret, configuration: configuration) } }) task.resume() } } struct CheckoutView: View { @ObservedObject var model = CheckoutViewModel() var body: some View { VStack { if model.paymentSheet != nil { Text("Ready to pay.") } else { Text("Loading…") } }.onAppear { model.preparePaymentSheet() } } } ``` Agrega un [PaymentSheet.PaymentButton](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/PaymentButton.html) a tu `View`. Esto se comporta de manera similar a un `Button` de SwiftUI, que te permite personalizarlo agregando una `View`. Cuando tocas el botón, se muestra la PaymentSheet. Después de completar el pago, Stripe cierra la PaymentSheet y llama al controlador `onCompletion` con un objeto [PaymentSheetResult](https://stripe.dev/stripe-ios/stripe-paymentsheet/Enums/PaymentSheetResult.html). ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet import SwiftUI class CheckoutViewModel: ObservableObject { let backendCheckoutUrl = URL(string: "Your back-end endpoint/payment-sheet")! // Your back-end endpoint @Published var paymentSheet: PaymentSheet? @Published var paymentResult: PaymentSheetResult? func preparePaymentSheet() { // MARK: Fetch the PaymentIntent and customer information from the back end var request = URLRequest(url: backendCheckoutUrl) request.httpMethod = "POST" let task = URLSession.shared.dataTask(with: request, completionHandler: { [weak self] (data, response, error) in guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any], let customerAccountId = json["customerAccount"] as? String, let customerSessionClientSecret = json["customerSessionClientSecret"] as? String, let paymentIntentClientSecret = json["paymentIntent"] as? String, let publishableKey = json["publishableKey"] as? String, let self = self else { // Handle error return } STPAPIClient.shared.publishableKey = publishableKey // MARK: Create a PaymentSheet instance var configuration = PaymentSheet.Configuration() configuration.merchantDisplayName = "Example, Inc." configuration.customerAccount = .init(id: customerAccountId, customerSessionClientSecret: customerSessionClientSecret) // Set `allowsDelayedPaymentMethods` to true if your business can handle payment methods // that complete payment after a delay, like SEPA Debit and Sofort. configuration.allowsDelayedPaymentMethods = true DispatchQueue.main.async { self.paymentSheet = PaymentSheet(paymentIntentClientSecret: paymentIntentClientSecret, configuration: configuration) } }) task.resume() } func onPaymentCompletion(result: PaymentSheetResult) { self.paymentResult = result } } struct CheckoutView: View { @ObservedObject var model = CheckoutViewModel() var body: some View { VStack {if let paymentSheet = model.paymentSheet { PaymentSheet.PaymentButton( paymentSheet: paymentSheet, onCompletion: model.onPaymentCompletion ) { Text("Buy") } } else { Text("Loading…") }if let result = model.paymentResult { switch result { case .completed: Text("Payment complete") case .failed(let error): Text("Payment failed: \(error.localizedDescription)") case .canceled: Text("Payment canceled.") } } }.onAppear { model.preparePaymentSheet() } } } ``` #### Customers v1 Crea un modelo `ObservableObject` para tu pantalla de confirmación de compra. Este modelo publica una [PaymentSheet](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet.html) y un [PaymentSheetResult](https://stripe.dev/stripe-ios/stripe-paymentsheet/Enums/PaymentSheetResult.html). ```swift import StripePaymentSheet import SwiftUI class CheckoutViewModel: ObservableObject { let backendCheckoutUrl = URL(string: "Your back-end endpoint/payment-sheet")! // Your back-end endpoint @Published var paymentSheet: PaymentSheet? @Published var paymentResult: PaymentSheetResult? } ``` Obtén el secreto de cliente PaymentIntent, el secreto de cliente CustomerSession, el ID del `cliente` y la clave publicable del punto de conexión que creaste en el paso anterior. Usa `STPAPIClient.shared` para establecer tu clave publicable e iniciar la [PaymentSheet](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet.html). ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet import SwiftUI class CheckoutViewModel: ObservableObject { let backendCheckoutUrl = URL(string: "Your back-end endpoint/payment-sheet")! // Your back-end endpoint @Published var paymentSheet: PaymentSheet? @Published var paymentResult: PaymentSheetResult? func preparePaymentSheet() { // MARK: Fetch thePaymentIntent and Customer information from the back end var request = URLRequest(url: backendCheckoutUrl) request.httpMethod = "POST" let task = URLSession.shared.dataTask(with: request, completionHandler: { [weak self] (data, response, error) in guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any], let customerId = json["customer"] as? String, let customerSessionClientSecret = json["customerSessionClientSecret"] as? String, letpaymentIntentClientSecret = json["paymentIntent"] as? String, let publishableKey = json["publishableKey"] as? String, let self = self else { // Handle error return } STPAPIClient.shared.publishableKey = publishableKey// MARK: Create a PaymentSheet instance var configuration = PaymentSheet.Configuration() configuration.merchantDisplayName = "Example, Inc." configuration.customer = .init(id: customerId, customerSessionClientSecret: customerSessionClientSecret) // Set `allowsDelayedPaymentMethods` to true if your business handles // delayed notification payment methods like US bank accounts. configuration.allowsDelayedPaymentMethods = true DispatchQueue.main.async { self.paymentSheet = PaymentSheet(paymentIntentClientSecret:paymentIntentClientSecret, configuration: configuration) } }) task.resume() } } struct CheckoutView: View { @ObservedObject var model = CheckoutViewModel() var body: some View { VStack { if model.paymentSheet != nil { Text("Ready to pay.") } else { Text("Loading…") } }.onAppear { model.preparePaymentSheet() } } } ``` Agrega un [PaymentSheet.PaymentButton](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/PaymentButton.html) a tu `View`. Esto se comporta de manera similar a un `Button` de SwiftUI, que te permite personalizarlo agregando una `View`. Cuando tocas el botón, se muestra la PaymentSheet. Después de completar el pago, Stripe cierra la PaymentSheet y llama al controlador `onCompletion` con un objeto [PaymentSheetResult](https://stripe.dev/stripe-ios/stripe-paymentsheet/Enums/PaymentSheetResult.html). ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet import SwiftUI class CheckoutViewModel: ObservableObject { let backendCheckoutUrl = URL(string: "Your back-end endpoint/payment-sheet")! // Your back-end endpoint @Published var paymentSheet: PaymentSheet? @Published var paymentResult: PaymentSheetResult? func preparePaymentSheet() { // MARK: Fetch the PaymentIntent and Customer information from the back end var request = URLRequest(url: backendCheckoutUrl) request.httpMethod = "POST" let task = URLSession.shared.dataTask(with: request, completionHandler: { [weak self] (data, response, error) in guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any], let customerId = json["customer"] as? String, let customerSessionClientSecret = json["customerSessionClientSecret"] as? String, let paymentIntentClientSecret = json["paymentIntent"] as? String, let publishableKey = json["publishableKey"] as? String, let self = self else { // Handle error return } STPAPIClient.shared.publishableKey = publishableKey // MARK: Create a PaymentSheet instance var configuration = PaymentSheet.Configuration() configuration.merchantDisplayName = "Example, Inc." configuration.customer = .init(id: customerId, customerSessionClientSecret: customerSessionClientSecret) // Set `allowsDelayedPaymentMethods` to true if your business can handle payment methods // that complete payment after a delay, like SEPA Debit and Sofort. configuration.allowsDelayedPaymentMethods = true DispatchQueue.main.async { self.paymentSheet = PaymentSheet(paymentIntentClientSecret: paymentIntentClientSecret, configuration: configuration) } }) task.resume() } func onPaymentCompletion(result: PaymentSheetResult) { self.paymentResult = result } } struct CheckoutView: View { @ObservedObject var model = CheckoutViewModel() var body: some View { VStack {if let paymentSheet = model.paymentSheet { PaymentSheet.PaymentButton( paymentSheet: paymentSheet, onCompletion: model.onPaymentCompletion ) { Text("Buy") } } else { Text("Loading…") }if let result = model.paymentResult { switch result { case .completed: Text("Payment complete") case .failed(let error): Text("Payment failed: \(error.localizedDescription)") case .canceled: Text("Payment canceled.") } } }.onAppear { model.preparePaymentSheet() } } } ``` Si el `PaymentSheetResult` es `.completed`, infórmale al cliente (por ejemplo, mostrándole una pantalla de confirmación del pedido). Establecer `allowsDelayedPaymentMethods` en true permite aceptar métodos de pago de [notificación diferida](https://docs.stripe.com/payments/payment-methods.md#payment-notification) como cuentas bancarias en EE. UU. Para estos métodos de pago, el estado final del pago no se conoce cuando se completa el `PaymentSheet`, sino que se efectúa con éxito o falla más tarde. Si aceptas este tipo de métodos de pago, infórmale al cliente que su pedido está confirmado y solo finalízalo (por ejemplo, envía el producto) cuando el pago se realice correctamente. ## Configurar una URL de retorno [Lado del cliente] El cliente puede salir de tu aplicación para autenticarse (por ejemplo, en Safari o en su aplicación bancaria). Para permitirles que regresen automáticamente a tu aplicación después de autenticarse, [configura un esquema de URL personalizado](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app) y define el delegado de la aplicación para que envíe la URL al SDK. Stripe no admite [enlaces universales](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 } } } } } ``` Además, debes definir la [returnURL](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/Configuration.html#/s:6Stripe12PaymentSheetC13ConfigurationV9returnURLSSSgvp) del objeto [PaymentSheet.Configuration](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/Configuration.html) en la URL de tu aplicación. ```swift var configuration = PaymentSheet.Configuration() configuration.returnURL = "your-app://stripe-redirect" ``` ## Administrar eventos posteriores al pago [Lado del servidor] Stripe envía un evento [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) cuando se completa el pago. Usa la [herramienta de webhook del Dashboard](https://dashboard.stripe.com/webhooks) o sigue la [guía de webhooks](https://docs.stripe.com/webhooks/quickstart.md) para recibir estos eventos y ejecutar acciones como, por ejemplo, enviar un correo electrónico de confirmación del pedido a tu cliente, registrar la venta en una base de datos o iniciar un flujo de envío. Escucha estos eventos en lugar de esperar una devolución de llamada del cliente. De su lado, el cliente puede cerrar la ventana del navegador o salir de la aplicación antes de que se ejecute la devolución de llamada, y clientes malintencionados podrían manipular la respuesta. Si configuras tu integración para escuchar eventos asincrónicos, podrás aceptar [diferentes tipos de métodos de pago](https://stripe.com/payments/payment-methods-guide) con una sola integración. Además de administrar el evento `payment_intent.succeeded`, recomendamos administrar estos otros eventos si se cobran pagos con el Payment Element: | Evento | Descripción | Acción | | ------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.succeeded) | Se envía cuando un cliente completa correctamente un pago. | Envía al cliente una confirmación del pedido y *completa* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected) el pedido. | | [payment_intent.processing](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.processing) | Se envía cuando un cliente inicia con éxito un pago, pero éste aún no se completó. Este evento se envía normalmente cuando el cliente inicia un débito bancario. Le sigue un evento `payment_intent.succeeded` o `payment_intent.payment_failed` en el futuro. | Envía al cliente una confirmación del pedido que indique que el pago está pendiente. En caso de productos digitales, quizá te convenga completar el pedido antes de esperar que se complete el pago. | | [payment_intent.payment_failed](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.payment_failed) | Enviado cuando un cliente intenta un pago, pero el pago falla. | Si un pago pasa de `processing` a `payment_failed`, ofrécele al cliente otro intento de pago. | ## Cobrar al PaymentMethod guardado más tarde [Lado del servidor] > #### Cumplimiento de la normativa > > Al guardar los datos de pago de un cliente, eres responsable del cumplimiento de todas las leyes, normativas y reglas de red aplicables. Cuando entregues métodos de pago anteriores a tu cliente final para futuras compras, asegúrate de incluir los métodos de pago para los que obtuviste el consentimiento del cliente para guardar los datos del método de pago para este uso futuro específico. Para diferenciar entre los métodos de pago adjuntos a los clientes que pueden y no pueden presentarse a tu cliente final como un método de pago guardado para futuras compras, usa el parámetro [allow_redisplay](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-allow_redisplay). A fin de encontrar un método de pago para aceptar pagos, enumera los métodos de pago asociados a tu cliente. En este ejemplo, se enumeran las tarjetas, pero puedes enumerar cualquier [tipo](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-type) de tarjeta admitida. > #### Usa la API Accounts v2 para representar a los clientes > > La API Accounts v2 suele estar disponible para usuarios Connect y en versión preliminar pública para otros usuarios de Stripe. Si eres parte de la versión preliminar Accounts v2, debes especificar una [versión preliminar](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning) en tu código. > > Para solicitar el acceso a la versión preliminar Accounts v2, > > Para la mayoría de los casos de uso, te recomendamos que[modeles a tus clientes como objetos Account configurados por el cliente](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md) en lugar de usar objetos [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 ``` Cuando tengas todo listo para aceptar pagos *fuera de la sesión* (A payment is described as off-session if it occurs without the direct involvement of the customer, using previously-collected payment information) de tu cliente, usa el ID del `cliente` o `cuenta` configurados por el cliente y el ID del `PaymentMethod` para crear un `PayIntent` con el importe y las monedas del pago. Establece algunos otros parámetros con el fin de efectuar el pago fuera de la sesión: - Establece [off_session](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-off_session) en true para indicar que el cliente no se encuentra en su flujo de compra durante un intento de pago y no puede autenticar una solicitud realizada por un socio, como un emisor de tarjeta, un banco u otra entidad de pago. Si, durante tu flujo de compra, un socio solicita la autenticación, Stripe solicita exenciones usando la información del cliente de una transacción anterior *durante la sesión* (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 no se cumplen las condiciones para la exención, el `PaymentIntent` podría dar lugar a un error. - Establece [confirm](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-confirm) en true para activar la confirmación de inmediato cuando se crea el `PagoIntent`. - Establece [payment_method](https://docs.stripe.com/api.md#create_payment_intent-payment_method) en el ID del `PaymentMethod`. - Según cómo representes a los clientes en tu integración, establece [customer_account](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer_account) en el ID de la `cuenta` configurada por el cliente o [cliente](https://docs.stripe.com/api.md#create_payment_intent-customer) en el ID del `cliente`. #### 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 ``` ## Probar la integración #### Tarjetas | Método de pago | Escenario | Cómo hacer la prueba | | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | Tarjeta de crédito | La configuración de la tarjeta se realiza correctamente y no requiere *autenticación* (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). | Completa nuestro formulario de tarjeta de crédito con el número de tarjeta `4242 4242 4242 4242` y la fecha de vencimiento, el CVC o el código postal. | | Tarjeta de crédito | La tarjeta requiere autenticación para la configuración inicial, pero no en los pagos sucesivos. | Completa nuestro formulario de tarjeta de crédito con el número de tarjeta `4000 0025 0000 3155` y cualquier fecha de vencimiento, CVC y código postal. | | Tarjeta de crédito | La tarjeta requiere autenticación para la configuración inicial y también requiere autenticación para los pagos sucesivos. | Completa nuestro formulario de tarjeta de crédito con el número de tarjeta `4000 0027 6000 3184` y cualquier fecha de vencimiento, CVC y código postal. | | Tarjeta de crédito | La tarjeta es rechazada durante la configuración. | Completa nuestro formulario de tarjeta de crédito con el número de tarjeta `4000 0000 0000 9995` y la fecha de vencimiento, el CVC o el código postal. | ## Optional: Habilitar Apple Pay > Si tu pantalla de confirmación de compra tiene un **botón de Apple Pay** exclusivo, sigue la [Guía de Apple Pay](https://docs.stripe.com/apple-pay.md#present-payment-sheet) y utiliza `ApplePayContext` para cobrar el pago desde ese botón. Puedes usar `PaymentSheet` para gestionar otros tipos de métodos de pago. ### Inscribirse para obtener un ID de comerciante Apple Obtén un ID de comerciante Apple [solicitando un nuevo identificador](https://developer.apple.com/account/resources/identifiers/add/merchant) en el sitio web de desarrolladores de Apple. Completa el formulario con una descripción y el identificador. La descripción es para tus registros y se puede modificar en el futuro. Stripe recomienda usar el nombre de tu aplicación como identificador (por ejemplo, `merchant.com.{{YOUR_APP_NAME}}`). ### Crear un nuevo certificado de Apple Pay Crea un certificado para que tu aplicación cifre los datos de pago. Ve a [Configuración de certificados de iOS](https://dashboard.stripe.com/settings/ios_certificates) en el Dashboard, haz clic en **Agregar nueva aplicación** y sigue la guía. Descarga un archivo de solicitud de firma de certificado (CSR) para obtener un certificado seguro de Apple que te permita utilizar Apple Pay. Se debe usar un archivo CSR para emitir exactamente un certificado. Si cambias tu ID de comerciante de Apple, debes ir a la [Configuración de certificados de iOS](https://dashboard.stripe.com/settings/ios_certificates) en el Dashboard para obtener una nueva CSR y un nuevo certificado. ### Integrarse con Xcode Agrega la funcionalidad Apple Pay a tu aplicación. En Xcode, abre la configuración del proyecto, selecciona la pestaña **Firma y funcionalidades** y agrega la funcionalidad **Apple Pay**. En este paso, quizá se te solicite iniciar sesión en tu cuenta de desarrollador. Selecciona el ID de comerciante que creaste antes, y tu aplicación estará lista para aceptar Apple Pay. ![](https://b.stripecdn.com/docs-statics-srv/assets/xcode.a701d4c1922d19985e9c614a6f105bf1.png) Habilitar la funcionalidad Apple Pay en Xcode ### Agregar Apple Pay #### Pago único Para agregar Apple Pay a PaymentSheet, establece [applePay](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/Configuration.html#/s:6Stripe12PaymentSheetC13ConfigurationV8applePayAC05ApplefD0VSgvp) después de inicializar `PaymentSheet.Configuration` con tu ID de comerciante Apple y el [código de país de tu empresa](https://dashboard.stripe.com/settings/account). #### iOS (Swift) ```swift var configuration = PaymentSheet.Configuration() configuration.applePay = .init( merchantId: "merchant.com.your_app_name", merchantCountryCode: "US" ) ``` #### Pagos recurrentes Para agregar Apple Pay a PaymentSheet, establece [applePay](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/Configuration.html#/s:6Stripe12PaymentSheetC13ConfigurationV8applePayAC05ApplefD0VSgvp) después de inicializar `PaymentSheet.Configuration` con tu ID de comerciante Apple y el [código de país de tu empresa](https://dashboard.stripe.com/settings/account). Conforme a las [directrices de Apple](https://developer.apple.com/design/human-interface-guidelines/apple-pay#Supporting-subscriptions) para pagos recurrentes, también debes establecer otros atributos en `PKPaymentRequest`. Agrega un controlador en [ApplePayConfiguration.paymentRequestHandlers](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/applepayconfiguration/handlers/paymentrequesthandler) para configurar [PKPaymentRequest.paymentSummaryItems](https://developer.apple.com/documentation/passkit/pkpaymentrequest/1619231-paymentsummaryitems) con la cantidad que pretendes cobrar (por ejemplo, USD 9.95 al mes). También puedes adoptar [tokens de comerciante](https://developer.apple.com/apple-pay/merchant-tokens/) estableciendo las propiedades `recurringPaymentRequest` o `automaticReloadPaymentRequest` en la `PKPaymentRequest`. Para obtener más información sobre cómo usar los pagos recurrentes con Apple Pay, consulta la [Documentación de Apple sobre PassKit](https://developer.apple.com/documentation/passkit/pkpaymentrequest). #### iOS (Swift) ```swift let customHandlers = PaymentSheet.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 = PaymentSheet.Configuration() configuration.applePay = .init(merchantId: "merchant.com.your_app_name", merchantCountryCode: "US", customHandlers: customHandlers) ``` ### Seguimiento de pedidos Para agregar información de [seguimiento de pedidos](https://developer.apple.com/design/human-interface-guidelines/technologies/wallet/designing-order-tracking) en iOS 16 o posterior, configura un [authorizationResultHandler](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/applepayconfiguration/handlers/authorizationresulthandler) en tu `PaymentSheet.ApplePayConfiguration.Handlers`. Stripe llamará a tu implementación después de que se efectivice el pago, pero antes de que iOS descarte la hoja de Apple Pay. En tu implementación de `authorizationResultHandler`, obtén los datos del pedido de tu servidor para el pedido completado. Agrega los datos al [PKPaymentAuthorizationResult](https://developer.apple.com/documentation/passkit/pkpaymentauthorizationresult) proporcionado y devuelve el resultado modificado. Para obtener más información sobre el seguimiento de pedidos, consulta la [Documentación sobre los pedidos por billetera de Apple](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 = PaymentSheet.Configuration() configuration.applePay = .init(merchantId: "merchant.com.your_app_name", merchantCountryCode: "US", customHandlers: customHandlers) ``` ## Habilitar escaneo de tarjeta A fin de habilitar el soporte para escaneo de tarjetas para iOS, establece `NSCameraUsageDescription` (**Privacidad: descripción del uso de la cámara**) en el `Info.plist` de tu aplicación y especifica el motivo por el que se necesita acceder a la cámara (por ejemplo, «Para escanear tarjetas»). ## Optional: Personalizar la hoja Todo lo que se quiera personalizar se configura usando el objeto [PaymentSheet.Configuration](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/Configuration.html). ### Appearance Personaliza los colores y las fuentes, entre otros elementos, para que combinen con tu aplicación con la [API Appearance](https://docs.stripe.com/elements/appearance-api/mobile.md?platform=ios). ### Diseño del método de pago Configura el diseño de los métodos de pago en la hoja usando [paymentMethodLayout](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/configuration-swift.struct/paymentmethodlayout). Puedes mostrarlos horizontalmente, verticalmente o dejar que Stripe optimice el diseño de manera automática. ![](https://b.stripecdn.com/docs-statics-srv/assets/ios-mpe-payment-method-layouts.9d0513e2fcec5660378ba1824d952054.png) #### Swift ```swift var configuration = PaymentSheet.Configuration() configuration.paymentMethodLayout = .automatic ``` ### Recopilar las direcciones de los usuarios Recopila las direcciones de envío o facturación locales e internacionales de tus clientes usando el [Address Element](https://docs.stripe.com/elements/address-element.md?platform=ios). ### Nombre de pantalla para el comerciante Especifica un nombre de empresa que vea el cliente configurando [merchantDisplayName](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/Configuration.html#/s:18StripePaymentSheet0bC0C13ConfigurationV19merchantDisplayNameSSvp). De manera predeterminada, este es el nombre de tu aplicación. #### Swift ```swift var configuration = PaymentSheet.Configuration() configuration.merchantDisplayName = "My app, Inc." ``` ### Modo oscuro `PaymentSheet` se adapta automáticamente a la configuración de aspecto de todo el sistema del usuario (modo claro y modo oscuro). Si tu aplicación no admite el modo oscuro, puedes definir el [estilo](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/Configuration.html#/s:18StripePaymentSheet0bC0C13ConfigurationV5styleAC18UserInterfaceStyleOvp) en modo `alwaysLight` o `alwaysDark`. ```swift var configuration = PaymentSheet.Configuration() configuration.style = .alwaysLight ``` ### Datos de facturación predeterminados Para establecer los valores predeterminados para los datos de facturación recopilados en la hoja de pago, configura la propiedad `defaultBillingDetails`. Los campos de la `PaymentSheet` se rellenan automáticamente con los valores que proporcionas. ```swift var configuration = PaymentSheet.Configuration() configuration.defaultBillingDetails.address.country = "US" configuration.defaultBillingDetails.email = "foo@bar.com" ``` ### Recopilación de los datos de facturación Usa `billingDetailsCollectionConfiguration` para especificar cómo deseas recopilar los datos de facturación en la hoja de pago. Puedes recopilar el nombre, el correo electrónico, el número de teléfono y la dirección del cliente. Si solo quieres los datos de facturación requeridos por el método de pago, establece `billingDetailsCollectionConfiguration.attachDefaultsToPaymentMethod` en true. En ese caso, `PaymentSheet.Configuration.defaultBillingDetails` se establece como los [datos de facturación](https://docs.stripe.com/api/payment_methods/object.md?lang=node#payment_method_object-billing_details) del método de pago. Si quieres recopilar datos de facturación adicionales que no son necesariamente requeridos por el método de pago, establece `billingDetailsCollectionConfiguration.attachDefaultsToPaymentMethod` en false. En ese caso, los datos de facturación recopilados mediante la `PaymentSheet` se establecen como los datos de facturación del método de pago. ```swift var configuration = PaymentSheet.Configuration() configuration.defaultBillingDetails.email = "foo@bar.com" configuration.billingDetailsCollectionConfiguration.name = .always configuration.billingDetailsCollectionConfiguration.email = .never configuration.billingDetailsCollectionConfiguration.address = .full configuration.billingDetailsCollectionConfiguration.attachDefaultsToPaymentMethod = true ``` > Pregúntale a tu asesor legal sobre las leyes que se aplican a la recopilación de información. Solicita los números de teléfono solo si los necesitas para la transacción. ## Optional: Completa el pago en tu interfaz de usuario Puedes presentar la hoja de pago para recopilar solo los datos del método de pago y luego llamar al método `confirm` para completar el pago en la interfaz de usuario de tu aplicación. Esto resulta útil si tienes un botón de compra personalizado o solicitas pasos adicionales después de recopilar los datos del pago. ![](https://b.stripecdn.com/docs-statics-srv/assets/ios-multi-step.cd631ea4f1cd8cf3f39b6b9e1e92b6c5.png) Completa el pago en la interfaz de usuario de tu aplicación #### UIKit Los siguientes pasos te explican cómo completar el pago en la interfaz de usuario de tu aplicación. Consulta nuestro ejemplo de integración en [GitHub](https://github.com/stripe/stripe-ios/blob/master/Example/PaymentSheet%20Example/PaymentSheet%20Example/ExampleCustomCheckoutViewController.swift). 1. Primero, inicializa [PaymentSheet.FlowController](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/flowcontroller) en lugar de `PaymentSheet` y actualiza tu interfaz de usuario con su propiedad `paymentOption`. Esta propiedad contiene una imagen y una etiqueta que representan el método de pago predeterminado que el cliente seleccionó inicialmente. ```swift PaymentSheet.FlowController.create(paymentIntentClientSecret: paymentIntentClientSecret, configuration: configuration) { [weak self] result in switch result { case .failure(let error): print(error) case .success(let paymentSheetFlowController): self?.paymentSheetFlowController = paymentSheetFlowController // Update your UI using paymentSheetFlowController.paymentOption } } ``` 1. A continuación, llama a `presentPaymentOptions` para recopilar los datos del pago. Cuando se complete, actualiza nuevamente tu interfaz de usuario con la propiedad `paymentOption`. ```swift paymentSheetFlowController.presentPaymentOptions(from: self) { // Update your UI using paymentSheetFlowController.paymentOption } ``` 1. Por último, llama a `confirm`. ```swift paymentSheetFlowController.confirm(from: self) { paymentResult in // MARK: Handle the payment result switch paymentResult { case .completed: print("Payment complete!") case .canceled: print("Canceled!") case .failed(let error): print(error) } } ``` #### SwiftUI Los siguientes pasos te explican cómo completar el pago en la interfaz de usuario de tu aplicación. Consulta nuestro ejemplo de integración en [GitHub](https://github.com/stripe/stripe-ios/blob/master/Example/PaymentSheet%20Example/PaymentSheet%20Example/ExampleSwiftUICustomPaymentFlow.swift). 1. Primero, inicializa [PaymentSheet.FlowController](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/flowcontroller) en lugar de `PaymentSheet`. Su propiedad `paymentOption` contiene una imagen y una etiqueta que representan el método de pago que el cliente tiene seleccionado actualmente, que puedes usar en tu interfaz de usuario. ```swift PaymentSheet.FlowController.create(paymentIntentClientSecret: paymentIntentClientSecret, configuration: configuration) { [weak self] result in switch result { case .failure(let error): print(error) case .success(let paymentSheetFlowController): self?.paymentSheetFlowController = paymentSheetFlowController // Use the paymentSheetFlowController.paymentOption properties in your UI myPaymentMethodLabel = paymentSheetFlowController.paymentOption?.label ?? "Select a payment method" myPaymentMethodImage = paymentSheetFlowController.paymentOption?.image ?? UIImage(systemName: "square.and.pencil")! } } ``` 1. Usa [PaymentSheet.FlowController.PaymentOptionsButton](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/flowcontroller/paymentoptionsbutton) para integrar el botón que presenta la hoja para recopilar los datos de pago. Cuando `PaymentSheet.FlowController` llama al argumento `onSheetDismissed`, la `paymentOption` de la instancia `PaymentSheet.FlowController` refleja el método de pago seleccionado actualmente. ```swift PaymentSheet.FlowController.PaymentOptionsButton( paymentSheetFlowController: paymentSheetFlowController, onSheetDismissed: { myPaymentMethodLabel = paymentSheetFlowController.paymentOption?.label ?? "Select a payment method" myPaymentMethodImage = paymentSheetFlowController.paymentOption?.image ?? UIImage(systemName: "square.and.pencil")! }, content: { /* An example button */ HStack { Text(myPaymentMethodLabel) Image(uiImage: myPaymentMethodImage) } } ) ``` 1. Usa [PaymentSheet.FlowController.PaymentOptionsButton](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/flowcontroller/paymentoptionsbutton) para integrar el botón que confirma el pago. ```swift PaymentSheet.FlowController.ConfirmButton( paymentSheetFlowController: paymentSheetFlowController, onCompletion: { result in // MARK: Handle the payment result switch result { case .completed: print("Payment complete!") case .canceled: print("Canceled!") case .failed(let error): print(error) } }, content: { /* An example button */ Text("Pay") } ) ``` Establecer `allowsDelayedPaymentMethods` en true permite aceptar métodos de pago de [notificación diferida](https://docs.stripe.com/payments/payment-methods.md#payment-notification) como cuentas bancarias en EE. UU. Para estos métodos de pago, el estado final del pago no se conoce cuando se completa el `PaymentSheet`, sino que se efectúa con éxito o falla más tarde. Si aceptas este tipo de métodos de pago, infórmale al cliente que su pedido está confirmado y solo finalízalo (por ejemplo, envía el producto) cuando el pago se realice correctamente. # Android > This is a Android for when platform is android and mobile-ui is payment-sheet. View the full page at https://docs.stripe.com/payments/mobile/save-during-payment?platform=android&mobile-ui=payment-sheet. Usa la [API Payment Intents](https://docs.stripe.com/api/payment_intents.md) para guardar los datos de pago de una compra. Existen varios casos de uso: - Cóbrale al cliente un pedido de e-commerce y almacena los datos para compras futuras. - Inicia el primer pago de una serie de pagos recurrentes. - Cobra un depósito y almacena los datos para cobrar el importe total más tarde. > #### Transacciones con tarjeta presente > > Las transacciones con tarjeta presente, como los pagos a través de Stripe Terminal, utilizan un proceso diferente para guardar el método de pago. Para obtener más detalles, consulta [la documentación de Terminal](https://docs.stripe.com/terminal/features/saving-payment-details/save-after-payment.md). ## Cumplimiento de la normativa Eres responsable de cumplir con todas las leyes, normativas y reglas de red aplicables al guardar los datos de pago de un cliente para su uso futuro, como mostrarle su método de pago durante el proceso de pago de una compra futura o realizar un cargo cuando no esté utilizando activamente tu sitio web o tu aplicación. Antes de guardar o realizar un cargo en el método de pago de un cliente, asegúrate de: - Agrega Condiciones a tu sitio web o aplicación que indiquen cómo planeas guardar los datos del método de pago, por ejemplo, lo siguiente: - El acuerdo del cliente para que puedas iniciar un pago o una serie de pagos en su nombre para transacciones específicas. - El momento y la frecuencia previstos de los pagos (por ejemplo, si los cargos son por cuotas programadas, pagos de suscripciones o recargas no programadas). - Cómo determinas el importe de pago. - Tu política de cancelación, si el método de pago es para un servicio por suscripción. - Usa un método de pago guardado solo para los fines indicados en tus Condiciones. - Obtén el consentimiento explícito del cliente para este uso específico. Por ejemplo, incluye una casilla de verificación que indique «Guardar mi método de pago para usarlo en el futuro». - Mantén un registro del acuerdo escrito de tu cliente con tus Condiciones. ## Configura Stripe [Lado del servidor] [Lado del cliente] Primero, necesitas una cuenta de Stripe. [Regístrate ahora](https://dashboard.stripe.com/register). ### Lado del servidor Esta integración requiere puntos de conexión en tu servidor que se comuniquen con la API de Stripe. Usa las bibliotecas oficiales para acceder a la API de Stripe desde tu servidor: #### 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' ``` ### Lado del cliente El [SDK para Android de Stripe](https://github.com/stripe/stripe-android) es de código abierto y está [completamente documentado](https://stripe.dev/stripe-android/). Para instalar el SDK, agrega `stripe-android` al bloque `dependencies` de tu archivo [app/build.gradle](https://developer.android.com/studio/build/dependencies): #### Kotlin ```kotlin plugins { id("com.android.application") } android { ... } dependencies { // ... // Stripe Android SDK implementation("com.stripe:stripe-android:23.9.0") // Include the financial connections SDK to support US bank account as a payment method implementation("com.stripe:financial-connections:23.9.0") } ``` > Para conocer detalles de la última versión y de versiones anteriores del SDK, consulta la página [Versiones](https://github.com/stripe/stripe-android/releases) en GitHub. Para recibir una notificación cuando se publique una nueva versión, [mira las versiones del repositorio](https://docs.github.com/en/github/managing-subscriptions-and-notifications-on-github/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository). ## Habilita métodos de pago Los pagos con tarjeta están habilitados de forma predeterminada. Consulta la [configuración de tus métodos de pago](https://dashboard.stripe.com/settings/payment_methods) para habilitar más métodos de pago que quieras admitir. ## Agregar un punto de conexión [Lado del servidor] > #### Nota > > Para mostrar la PaymentSheet antes de crear un PaymentIntent, consulta [Recopila datos de pago antes de crear un Intent](https://docs.stripe.com/payments/accept-a-payment-deferred.md?type=payment). Esta integración usa tres objetos de la API de Stripe: 1. [PaymentIntent](https://docs.stripe.com/api/payment_intents.md): Stripe lo utiliza para representar tu intención de cobrarle a un cliente, haciendo el seguimiento de los intentos de cobro y de los cambios en el estado del pago a lo largo del proceso. 1. Una [Account configurada por el cliente](https://docs.stripe.com/api/v2/core/accounts/object.md#v2_account_object-applied_configurations) o un [Customer](https://docs.stripe.com/api/customers.md) Object: para configurar un método de pago para pagos futuros, debes asociarlo a un cliente. Crea un objeto que represente a tu cliente cuando cree una cuenta en tu negocio. Si tu cliente realiza un pago como invitado, puedes crear una `Account` o `Customer` Object antes del pago y asociarlo más adelante con tu propia representación interna de la cuenta del cliente. 1. [CustomerSession](https://docs.stripe.com/api/customer_sessions.md): la información del objeto que representa a tu cliente es sensible y no se puede recuperar directamente desde una app. Una `CustomerSession` le otorga al SDK acceso temporal con alcance limitado a la `Account` o `Customer` y proporciona opciones de configuración adicionales. Consulta la lista completa de [opciones de configuración](https://docs.stripe.com/api/customer_sessions/create.md#create_customer_session-components). Por motivos de seguridad, tu aplicación no puede crear estos objetos. En su lugar, agrega un punto de conexión en tu servidor que haga lo siguiente: 1. Recupera el objeto `Account` o `Customer`, o crea uno nuevo. 1. Crea una [CustomerSession](https://docs.stripe.com/api/customer_sessions.md) para el objeto `Account` o `Customer`. 1. Crea un `PaymentIntent` con el [importe](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-amount), la [moneda](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-currency), [setup_future_usage](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-setup_future_usage), y el [customer_account](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer_account) o el [customer](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer). 1. Devuelve el *client secret* (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)) del `PaymentIntent`, el `client_secret` de la `CustomerSession`, el ID del `Account` o `Customer` y tu [clave publicable](https://dashboard.stripe.com/apikeys) a tu app. > El Payment Element móvil solo admite `setup_future_usage` con tarjetas y cuentas bancarias de EE. UU. Los métodos de pago que se muestran a los clientes durante el proceso de compra también se incluyen en el PaymentIntent. Puedes permitir que Stripe extraiga los métodos de pago de tu configuración del Dashboard o puedes enumerarlos manualmente. Independientemente de la opción que elijas, debes saber que la moneda especificada en el PaymentIntent filtra los métodos de pago que se muestran al cliente. Por ejemplo, si especificas `eur` en el PaymentIntent y tienes habilitado OXXO en el Dashboard, OXXO no se mostrará al cliente porque OXXO no admite pagos en `eur`. A menos que tu integración requiera una opción basada en código para ofrecer métodos de pago, Stripe recomienda usar la opción automatizada. Esto se debe a que Stripe evalúa la moneda, las restricciones de los métodos de pago y otros parámetros para determinar la lista de métodos de pago admitidos. Se les da prioridad a los métodos de pago que aumentan la conversión y guardan mayor relación con la moneda y la ubicación del cliente. #### Gestionar los métodos de pago desde el Dashboard Puedes administrar los métodos de pago desde el [Dashboard](https://dashboard.stripe.com/settings/payment_methods). Stripe maneja la devolución de métodos de pago elegibles según factores como el monto de la transacción, la moneda y el flujo de pago. El PaymentIntent se crea según los métodos de pago que configuraste en el Dashboard. Si no quieres usar el Dashboard o si quieres especificar métodos de pago manualmente, puedes enumerarlos usando el atributo `payment_method_types`. #### curl ```bash # Create a Customer (use an existing Customer ID if this is a returning customer) curl https://api.stripe.com/v1/customers \ -u <>: \ -X "POST" \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" # Create an CustomerSession for the Customer curl https://api.stripe.com/v1/customer_sessions \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "components[mobile_payment_element][enabled]"=true \ -d "components[mobile_payment_element][features][payment_method_save]"=enabled \ -d "components[mobile_payment_element][features][payment_method_redisplay]"=enabled \ -d "components[mobile_payment_element][features][payment_method_remove]"=enabled # Create a PaymentIntent curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \ -d "setup_future_usage"="off_session" \ -d "automatic_payment_methods[enabled]"=true \ ``` #### Cómo enumerar métodos de pago manualmente #### curl ```bash # Create a Customer (use an existing Customer ID if this is a returning customer) curl https://api.stripe.com/v1/customers \ -u <>: \ -X "POST" \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" # Create an CustomerSession for the Customer curl https://api.stripe.com/v1/customer_sessions \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "components[mobile_payment_element][enabled]"=true \ -d "components[mobile_payment_element][features][payment_method_save]"=enabled \ -d "components[mobile_payment_element][features][payment_method_redisplay]"=enabled \ -d "components[mobile_payment_element][features][payment_method_remove]"=enabled # Create a PaymentIntent curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \ -d "setup_future_usage"="off_session" \ -d "payment_method_types[]"="card" \ ``` > Cada método de pago debe admitir la moneda especificada en el PaymentIntent, y tu empresa tiene que estar establecida en uno de los países que admite cada método de pago. Consulta la página de [opciones de integración de métodos de pago](https://docs.stripe.com/payments/payment-methods/integration-options.md) para obtener más información sobre qué admitimos. ## Recopila datos de pago [Lado del cliente] Antes de mostrar el Payment Element móvil, tu página de finalización de compra debe cumplir con los siguientes requisitos: - Mostrar los productos de la compra y el importe total - Recopilar cualquier dato de envío requerido usando el [Address Element](https://docs.stripe.com/elements/address-element.md?platform=android) - Incluye un botón de confirmación de compra para presentar la interfaz de usuario de Stripe #### Jetpack Compose [Inicializa](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-builder/index.html) una instancia de `PaymentSheet` dentro de `onCreate` de tu actividad de finalización de compra, especificando un método para administrar el resultado. ```kotlin import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import com.stripe.android.paymentsheet.PaymentSheet import com.stripe.android.paymentsheet.PaymentSheetResult @Composable fun App() { val paymentSheet = remember { PaymentSheet.Builder(::onPaymentSheetResult) }.build() } private fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) { // implemented in the next steps } ``` A continuación, alcanza el secreto de cliente del PaymentIntent, el secreto de cliente de la sesión de este, el ID del cliente y la clave publicable del punto de conexión que creaste en el paso anterior. Define tu clave publicable usando `PaymentConfiguration` y guarda las otras para usarlas cuando presentes la PaymentSheet. ```kotlin import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberimport androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext import com.stripe.android.PaymentConfiguration import com.stripe.android.paymentsheet.PaymentSheet import com.stripe.android.paymentsheet.PaymentSheetResult @Composable fun App() { val paymentSheet = remember { PaymentSheet.Builder(::onPaymentSheetResult) }.build()val context = LocalContext.current var customerConfig by remember { mutableStateOf(null) } varpaymentIntentClientSecret by remember { mutableStateOf(null) } LaunchedEffect(context) { // Make a request to your own server and retrieve payment configurations val networkResult = ... if (networkResult.isSuccess) {paymentIntentClientSecret = networkResult.paymentIntent customerConfig = PaymentSheet.CustomerConfiguration.createWithCustomerSession( id = networkResult.customer, clientSecret = networkResult.customerSessionClientSecret )PaymentConfiguration.init(context, networkResult.publishableKey)} } } private fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) { // implemented in the next steps } ``` Cuando el cliente toca tu botón de confirmación de compra, llama a [presentWithPaymentIntent](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/index.html#1814490530%2FFunctions%2F2002900378) para presentar la hoja de pago. Una vez que el cliente completa el pago, la hoja se cierra y se llama al [PaymentSheetResultCallback](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet-result-callback/index.html) con un [PaymentSheetResult](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet-result/index.html). ```kotlin import androidx.compose.material.Button import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext import com.stripe.android.PaymentConfiguration import com.stripe.android.paymentsheet.PaymentSheet import com.stripe.android.paymentsheet.PaymentSheetResult @Composable fun App() { val paymentSheet = remember { PaymentSheet.Builder(::onPaymentSheetResult) }.build() val context = LocalContext.current var customerConfig by remember { mutableStateOf(null) } var paymentIntentClientSecret by remember { mutableStateOf(null) } LaunchedEffect(context) { // Make a request to your own server and retrieve payment configurations val networkResult = ... if (networkResult.isSuccess) { paymentIntentClientSecret = networkResult.paymentIntent customerConfig = PaymentSheet.CustomerConfiguration.createWithCustomerSession( id = networkResult.customer, clientSecret = networkResult.customerSessionClientSecret ) PaymentConfiguration.init(context, networkResult.publishableKey) } }Button( onClick = { val currentConfig = customerConfig val currentClientSecret =paymentIntentClientSecret if (currentConfig != null && currentClientSecret != null) { presentPaymentSheet(paymentSheet, currentConfig, currentClientSecret) } } ) { Text("Checkout") } }private fun presentPaymentSheet( paymentSheet: PaymentSheet, customerConfig: PaymentSheet.CustomerConfiguration,paymentIntentClientSecret: String ) { paymentSheet.presentWithPaymentIntent(paymentIntentClientSecret, PaymentSheet.Configuration.Builder(merchantDisplayName = "My merchant name") .customer(customerConfig) // Set `allowsDelayedPaymentMethods` to true if your business handles // delayed notification payment methods like US bank accounts. .allowsDelayedPaymentMethods(true) .build() ) } private fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) {when(paymentSheetResult) { is PaymentSheetResult.Canceled -> { print("Canceled") } is PaymentSheetResult.Failed -> { print("Error: ${paymentSheetResult.error}") } is PaymentSheetResult.Completed -> { // Display for example, an order confirmation screen print("Completed") } } } ``` #### Vistas (clásicas) [Inicializa](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/index.html#-394860221%2FConstructors%2F2002900378) una instancia de `PaymentSheet` dentro de `onCreate` de tu actividad de finalización de compra y especifica un método para administrar el resultado. #### Kotlin ```kotlin import com.stripe.android.paymentsheet.PaymentSheet class CheckoutActivity : AppCompatActivity() { lateinit var paymentSheet: PaymentSheet override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) paymentSheet = PaymentSheet.Builder(::onPaymentSheetResult).build(this) } fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) { // implemented in the next steps } } ``` A continuación, alcanza el secreto de cliente del PaymentIntent, el secreto de cliente de la sesión de este, el ID del cliente y la clave publicable del punto de conexión que creaste en el paso anterior. Define tu clave publicable usando `PaymentConfiguration` y guarda las otras para usarlas cuando presentes la PaymentSheet. #### Kotlin ```kotlin import com.stripe.android.paymentsheet.PaymentSheet class CheckoutActivity : AppCompatActivity() { lateinit var paymentSheet: PaymentSheetlateinit var customerConfig: PaymentSheet.CustomerConfiguration lateinit varpaymentIntentClientSecret: String override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) paymentSheet = PaymentSheet.Builder(::onPaymentSheetResult).build(this)lifecycleScope.launch { // Make a request to your own server and retrieve payment configurations val networkResult = MyBackend.getPaymentConfig() if (networkResult.isSuccess) {paymentIntentClientSecret = networkResult.paymentIntent customerConfig = PaymentSheet.CustomerConfiguration.createWithCustomerSession( id = networkResult.customer, clientSecret = networkResult.customerSessionClientSecret )PaymentConfiguration.init(context, networkResult.publishableKey)} } } fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) { // implemented in the next steps } } ``` Cuando el cliente toca tu botón de confirmación de compra, llama a [presentWithPaymentIntent](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/index.html#1814490530%2FFunctions%2F2002900378) para presentar la hoja de pago. Una vez que el cliente completa el pago, la hoja se cierra y se llama al [PaymentSheetResultCallback](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet-result-callback/index.html) con un [PaymentSheetResult](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet-result/index.html). #### Kotlin ```kotlin // ... class CheckoutActivity : AppCompatActivity() { lateinit var paymentSheet: PaymentSheet lateinit var customerConfig: PaymentSheet.CustomerConfiguration lateinit var paymentIntentClientSecret: String // ...fun presentPaymentSheet() { paymentSheet.presentWithPaymentIntent(paymentIntentClientSecret, PaymentSheet.Configuration.Builder(merchantDisplayName = "My merchant name") .customer(customerConfig) // Set `allowsDelayedPaymentMethods` to true if your business handles // delayed notification payment methods like US bank accounts. .allowsDelayedPaymentMethods(true) .build() ) } fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) {when(paymentSheetResult) { is PaymentSheetResult.Canceled -> { print("Canceled") } is PaymentSheetResult.Failed -> { print("Error: ${paymentSheetResult.error}") } is PaymentSheetResult.Completed -> { // Display for example, an order confirmation screen print("Completed") } } } } ``` Establecer `allowsDelayedPaymentMethods` en true permite aceptar métodos de pago de [notificación diferida](https://docs.stripe.com/payments/payment-methods.md#payment-notification) como cuentas bancarias en EE. UU. Para estos métodos de pago, el estado final del pago no se conoce cuando se completa el `PaymentSheet`, sino que se efectúa con éxito o falla más tarde. Si aceptas este tipo de métodos de pago, infórmale al cliente que su pedido está confirmado y solo finalízalo (por ejemplo, envía el producto) cuando el pago se realice correctamente. ## Administrar eventos posteriores al pago [Lado del servidor] Stripe envía un evento [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) cuando se completa el pago. Usa la [herramienta de webhook del Dashboard](https://dashboard.stripe.com/webhooks) o sigue la [guía de webhooks](https://docs.stripe.com/webhooks/quickstart.md) para recibir estos eventos y ejecutar acciones como, por ejemplo, enviar un correo electrónico de confirmación del pedido a tu cliente, registrar la venta en una base de datos o iniciar un flujo de envío. Escucha estos eventos en lugar de esperar una devolución de llamada del cliente. De su lado, el cliente puede cerrar la ventana del navegador o salir de la aplicación antes de que se ejecute la devolución de llamada, y clientes malintencionados podrían manipular la respuesta. Si configuras tu integración para escuchar eventos asincrónicos, podrás aceptar [diferentes tipos de métodos de pago](https://stripe.com/payments/payment-methods-guide) con una sola integración. Además de administrar el evento `payment_intent.succeeded`, recomendamos administrar estos otros eventos si se cobran pagos con el Payment Element: | Evento | Descripción | Acción | | ------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.succeeded) | Se envía cuando un cliente completa correctamente un pago. | Envía al cliente una confirmación del pedido y *completa* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected) el pedido. | | [payment_intent.processing](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.processing) | Se envía cuando un cliente inicia con éxito un pago, pero éste aún no se completó. Este evento se envía normalmente cuando el cliente inicia un débito bancario. Le sigue un evento `payment_intent.succeeded` o `payment_intent.payment_failed` en el futuro. | Envía al cliente una confirmación del pedido que indique que el pago está pendiente. En caso de productos digitales, quizá te convenga completar el pedido antes de esperar que se complete el pago. | | [payment_intent.payment_failed](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.payment_failed) | Enviado cuando un cliente intenta un pago, pero el pago falla. | Si un pago pasa de `processing` a `payment_failed`, ofrécele al cliente otro intento de pago. | ## Cobrar al PaymentMethod guardado más tarde [Lado del servidor] > #### Cumplimiento de la normativa > > Al guardar los datos de pago de un cliente, eres responsable del cumplimiento de todas las leyes, normativas y reglas de red aplicables. Cuando entregues métodos de pago anteriores a tu cliente final para futuras compras, asegúrate de incluir los métodos de pago para los que obtuviste el consentimiento del cliente para guardar los datos del método de pago para este uso futuro específico. Para diferenciar entre los métodos de pago adjuntos a los clientes que pueden y no pueden presentarse a tu cliente final como un método de pago guardado para futuras compras, usa el parámetro [allow_redisplay](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-allow_redisplay). A fin de encontrar un método de pago para aceptar pagos, enumera los métodos de pago asociados a tu cliente. En este ejemplo, se enumeran las tarjetas, pero puedes enumerar cualquier [tipo](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-type) de tarjeta admitida. > #### Usa la API Accounts v2 para representar a los clientes > > La API Accounts v2 suele estar disponible para usuarios Connect y en versión preliminar pública para otros usuarios de Stripe. Si eres parte de la versión preliminar Accounts v2, debes especificar una [versión preliminar](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning) en tu código. > > Para solicitar el acceso a la versión preliminar Accounts v2, > > Para la mayoría de los casos de uso, te recomendamos que[modeles a tus clientes como objetos Account configurados por el cliente](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md) en lugar de usar objetos [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 ``` Cuando tengas todo listo para aceptar pagos *fuera de la sesión* (A payment is described as off-session if it occurs without the direct involvement of the customer, using previously-collected payment information) de tu cliente, usa el ID del `cliente` o `cuenta` configurados por el cliente y el ID del `PaymentMethod` para crear un `PayIntent` con el importe y las monedas del pago. Establece algunos otros parámetros con el fin de efectuar el pago fuera de la sesión: - Establece [off_session](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-off_session) en true para indicar que el cliente no se encuentra en su flujo de compra durante un intento de pago y no puede autenticar una solicitud realizada por un socio, como un emisor de tarjeta, un banco u otra entidad de pago. Si, durante tu flujo de compra, un socio solicita la autenticación, Stripe solicita exenciones usando la información del cliente de una transacción anterior *durante la sesión* (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 no se cumplen las condiciones para la exención, el `PaymentIntent` podría dar lugar a un error. - Establece [confirm](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-confirm) en true para activar la confirmación de inmediato cuando se crea el `PagoIntent`. - Establece [payment_method](https://docs.stripe.com/api.md#create_payment_intent-payment_method) en el ID del `PaymentMethod`. - Según cómo representes a los clientes en tu integración, establece [customer_account](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer_account) en el ID de la `cuenta` configurada por el cliente o [cliente](https://docs.stripe.com/api.md#create_payment_intent-customer) en el ID del `cliente`. #### 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 ``` ## Probar la integración #### Tarjetas | Método de pago | Escenario | Cómo hacer la prueba | | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | Tarjeta de crédito | La configuración de la tarjeta se realiza correctamente y no requiere *autenticación* (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). | Completa nuestro formulario de tarjeta de crédito con el número de tarjeta `4242 4242 4242 4242` y la fecha de vencimiento, el CVC o el código postal. | | Tarjeta de crédito | La tarjeta requiere autenticación para la configuración inicial, pero no en los pagos sucesivos. | Completa nuestro formulario de tarjeta de crédito con el número de tarjeta `4000 0025 0000 3155` y cualquier fecha de vencimiento, CVC y código postal. | | Tarjeta de crédito | La tarjeta requiere autenticación para la configuración inicial y también requiere autenticación para los pagos sucesivos. | Completa nuestro formulario de tarjeta de crédito con el número de tarjeta `4000 0027 6000 3184` y cualquier fecha de vencimiento, CVC y código postal. | | Tarjeta de crédito | La tarjeta es rechazada durante la configuración. | Completa nuestro formulario de tarjeta de crédito con el número de tarjeta `4000 0000 0000 9995` y la fecha de vencimiento, el CVC o el código postal. | ## Optional: Activar Google Pay ### Configura tu integración Para usar Google Pay, primero habilita la API de Google Pay agregando lo siguiente a la etiqueta `` de tu **AndroidManifest.xml**: ```xml ... ``` Para obtener más detalles, consulta cómo [configurar la API de Google Pay](https://developers.google.com/pay/api/android/guides/setup) para Android en Google Pay. ### Agregar Google Pay Para agregar Google Pay a tu integración, especifica un [PaymentSheet.GooglePayConfiguration](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-google-pay-configuration/index.html) con tu entorno de Google Pay (de producción o de prueba) y el [código de país de tu empresa](https://dashboard.stripe.com/settings/account) al inicializar [PaymentSheet.Configuration](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-configuration/index.html). #### Kotlin ```kotlin val googlePayConfiguration = PaymentSheet.GooglePayConfiguration( environment = PaymentSheet.GooglePayConfiguration.Environment.Test, countryCode = "US", currencyCode = "USD" // Required for Setup Intents, optional for Payment Intents ) val configuration = PaymentSheet.Configuration.Builder(merchantDisplayName = "My merchant name") .googlePay(googlePayConfiguration) .build() ``` ### Prueba Google Pay Google te permite realizar pagos de prueba a través de su tarjeta [Test card suite](https://developers.google.com/pay/api/android/guides/resources/test-card-suite). El conjunto de pruebas admite el uso de [tarjetas de prueba](https://docs.stripe.com/testing.md) de Stripe. Debes probar Google Pay usando un dispositivo Android físico en lugar de un dispositivo simulado, en un país donde se admite Google Pay. Inicia sesión en una cuenta Google en tu dispositivo de prueba con una tarjeta real guardada en Google Wallet. ## Optional: Personalizar la hoja Todo lo que se quiera personalizar se configura usando el objeto [PaymentSheet.Configuration](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-configuration/index.html). ### Appearance Personaliza los colores y las fuentes, entre otros elementos, para que combinen con tu aplicación usando la [API Appearance](https://docs.stripe.com/elements/appearance-api/mobile.md?platform=android). ### Diseño del método de pago Configura el diseño de los métodos de pago en la hoja con [paymentMethodLayout](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-configuration/-builder/index.html#2123253356%2FFunctions%2F2002900378). Puedes mostrarlos horizontalmente, verticalmente o dejar que Stripe optimice el diseño de manera automática. ![](https://b.stripecdn.com/docs-statics-srv/assets/android-mpe-payment-method-layouts.3bcfe828ceaad1a94e0572a22d91733f.png) #### Kotlin ```kotlin PaymentSheet.Configuration.Builder("Example, Inc.") .paymentMethodLayout(PaymentSheet.PaymentMethodLayout.Automatic) .build() ``` ### Recopilar las direcciones de los usuarios Recopila las direcciones de envío o facturación locales e internacionales de tus clientes usando el [Address Element](https://docs.stripe.com/elements/address-element.md?platform=android). ### Nombre con el que aparecerá la empresa Especifica el nombre que quieres que el cliente vea para tu empresa configurando [merchantDisplayName](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-configuration/index.html#-191101533%2FProperties%2F2002900378). De manera predeterminada, este es el nombre de tu aplicación. #### Kotlin ```kotlin PaymentSheet.Configuration.Builder( merchantDisplayName = "My app, Inc." ).build() ``` ### Modo oscuro De forma predeterminada, `PaymentSheet` se adapta automáticamente a la configuración de aspecto de todo el sistema del usuario (modo claro y modo oscuro). Puedes cambiarla definiendo modo claro o modo oscuro en tu aplicación: #### Kotlin ```kotlin // force dark AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) // force light AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) ``` ### Datos de facturación predeterminados Para establecer los valores predeterminados para los datos de facturación recopilados en la hoja de pago, configura la propiedad `defaultBillingDetails`. Los campos de la `PaymentSheet` se rellenan automáticamente con los valores que proporcionas. #### Kotlin ```kotlin val address = PaymentSheet.Address(country = "US") val billingDetails = PaymentSheet.BillingDetails( address = address, email = "foo@bar.com" ) val configuration = PaymentSheet.Configuration.Builder(merchantDisplayName = "Merchant, Inc.") .defaultBillingDetails(billingDetails) .build() ``` ### Configura la recopilación de datos de facturación Usa `BillingDetailsCollectionConfiguration` para especificar cómo deseas recopilar los datos de facturación en la PaymentSheet. Puedes recopilar el nombre, el correo electrónico, el número de teléfono y la dirección del cliente. Si quieres adjuntar datos de facturación predeterminados al objeto PaymentMethod aun cuando esos campos no se hayan recopilado en la interfaz de usuario, establece `billingDetailsCollectionConfiguration.attachDefaultsToPaymentMethod` en `true`. #### Kotlin ```kotlin 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 = PaymentSheet.Configuration.Builder(merchantDisplayName = "Merchant, Inc.") .defaultBillingDetails(billingDetails) .billingDetailsCollectionConfiguration(billingDetailsCollectionConfiguration) .build() ``` > Pregúntale a tu asesor legal sobre las leyes que se aplican a la recopilación de información. Solicita los números de teléfono solo si los necesitas para la transacción. ## Optional: Completa el pago en tu interfaz de usuario Puedes presentar una hoja de pago para recopilar solo los datos del método de pago y completar el pago en la interfaz de usuario de tu aplicación. Esto resulta útil si tienes un botón de compra personalizado o solicitas pasos adicionales después de recopilar los datos del pago. ![](https://b.stripecdn.com/docs-statics-srv/assets/android-multi-step.84d8a0a44b1baa596bda491322b6d9fd.png) > Una integración de ejemplo está [disponible en nuestro GitHub](https://github.com/stripe/stripe-android/blob/master/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/samples/ui/paymentsheet/custom_flow/CustomFlowActivity.kt). 1. Primero, inicializa [PaymentSheet.FlowController](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-flow-controller/index.html) en lugar de `PaymentSheet` usando uno de los métodos [Builder](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-flow-controller/-builder/index.html). #### Android (Kotlin) ```kotlin class CheckoutActivity : AppCompatActivity() { private lateinit var flowController: PaymentSheet.FlowController override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val flowController = PaymentSheet.FlowController.Builder( resultCallback = ::onPaymentSheetResult, paymentOptionResultCallback = ::onPaymentOption, ).build(this) } } ``` 1. A continuación, llama a `configureWithPaymentIntent` con las claves de objeto de Stripe recuperadas del backend y actualiza tu interfaz de usuario en la devolución de llamada usando [getPaymentOption()](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-flow-controller/index.html#-2091462043%2FFunctions%2F2002900378). Contiene una imagen y una etiqueta que representan el método de pago seleccionado actualmente por el cliente. #### Android (Kotlin) ```kotlin flowController.configureWithPaymentIntent( paymentIntentClientSecret = paymentIntentClientSecret, configuration = PaymentSheet.Configuration.Builder("Example, Inc.") .customer(PaymentSheet.CustomerConfiguration( id = customerId, ephemeralKeySecret = ephemeralKeySecret )) .build() ) { isReady, error -> if (isReady) { // Update your UI using `flowController.getPaymentOption()` } else { // handle FlowController configuration failure } } ``` 1. A continuación, llama a [presentPaymentOptions](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-flow-controller/index.html#449924733%2FFunctions%2F2002900378) para recopilar los datos del pago. Cuando el cliente termina, la hoja se cierra y llama al [paymentResultCallback](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-option-callback/index.html) especificado anteriormente en `create`. Implementa este método para actualizar tu interfaz de usuario con la `paymentOption` devuelta. #### Android (Kotlin) ```kotlin // ... flowController.presentPaymentOptions() // ... private fun onPaymentOption(paymentOptionResult: PaymentOptionResult) { val paymentOption = paymentOptionResult.paymentOption if (paymentOption != null) { paymentMethodButton.text = paymentOption.label paymentMethodButton.setCompoundDrawablesRelativeWithIntrinsicBounds( paymentOption.drawableResourceId, 0, 0, 0 ) } else { paymentMethodButton.text = "Select" paymentMethodButton.setCompoundDrawablesRelativeWithIntrinsicBounds( null, null, null, null ) } } ``` 1. Finalmente, llama a [confirm](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-flow-controller/index.html#-479056656%2FFunctions%2F2002900378) para completar el pago. Cuando el cliente termina, la hoja se cierra y llama al [paymentResultCallback](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet-result-callback/index.html#237248767%2FFunctions%2F2002900378) especificado anteriormente en `create`. #### Android (Kotlin) ```kotlin // ... flowController.confirmPayment() // ... private fun onPaymentSheetResult( paymentSheetResult: PaymentSheetResult ) { when (paymentSheetResult) { is PaymentSheetResult.Canceled -> { // Payment canceled } is PaymentSheetResult.Failed -> { // Payment Failed. See logcat for details or inspect paymentSheetResult.error } is PaymentSheetResult.Completed -> { // Payment Complete } } } ``` Establecer `allowsDelayedPaymentMethods` en true permite aceptar métodos de pago de [notificación diferida](https://docs.stripe.com/payments/payment-methods.md#payment-notification) como cuentas bancarias en EE. UU. Para estos métodos de pago, el estado final del pago no se conoce cuando se completa el `PaymentSheet`, sino que se efectúa con éxito o falla más tarde. Si aceptas este tipo de métodos de pago, infórmale al cliente que su pedido está confirmado y solo finalízalo (por ejemplo, envía el producto) cuando el pago se realice correctamente. # React Native > This is a React Native for when platform is react-native and mobile-ui is payment-sheet. View the full page at https://docs.stripe.com/payments/mobile/save-during-payment?platform=react-native&mobile-ui=payment-sheet. Usa la [API Payment Intents](https://docs.stripe.com/api/payment_intents.md) para guardar los datos de pago de una compra. Existen varios casos de uso: - Cóbrale al cliente un pedido de e-commerce y almacena los datos para compras futuras. - Inicia el primer pago de una serie de pagos recurrentes. - Cobra un depósito y almacena los datos para cobrar el importe total más tarde. > #### Transacciones con tarjeta presente > > Las transacciones con tarjeta presente, como los pagos a través de Stripe Terminal, utilizan un proceso diferente para guardar el método de pago. Para obtener más detalles, consulta [la documentación de Terminal](https://docs.stripe.com/terminal/features/saving-payment-details/save-after-payment.md). ## Cumplimiento de la normativa Eres responsable de cumplir con todas las leyes, normativas y reglas de red aplicables al guardar los datos de pago de un cliente para su uso futuro, como mostrarle su método de pago durante el proceso de pago de una compra futura o realizar un cargo cuando no esté utilizando activamente tu sitio web o tu aplicación. Antes de guardar o realizar un cargo en el método de pago de un cliente, asegúrate de: - Agrega Condiciones a tu sitio web o aplicación que indiquen cómo planeas guardar los datos del método de pago, por ejemplo, lo siguiente: - El acuerdo del cliente para que puedas iniciar un pago o una serie de pagos en su nombre para transacciones específicas. - El momento y la frecuencia previstos de los pagos (por ejemplo, si los cargos son por cuotas programadas, pagos de suscripciones o recargas no programadas). - Cómo determinas el importe de pago. - Tu política de cancelación, si el método de pago es para un servicio por suscripción. - Usa un método de pago guardado solo para los fines indicados en tus Condiciones. - Obtén el consentimiento explícito del cliente para este uso específico. Por ejemplo, incluye una casilla de verificación que indique «Guardar mi método de pago para usarlo en el futuro». - Mantén un registro del acuerdo escrito de tu cliente con tus Condiciones. ## Configura Stripe [Lado del servidor] [Lado del cliente] Primero, necesitas una cuenta de Stripe. [Regístrate ahora](https://dashboard.stripe.com/register). ### Lado del servidor Esta integración requiere puntos de conexión en tu servidor que se comuniquen con la API de Stripe. Usa las bibliotecas oficiales para acceder a la API de Stripe desde tu servidor: #### 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' ``` ### Lado del cliente El [SDK para React Native](https://github.com/stripe/stripe-react-native) es de código abierto y está plenamente documentado. Internamente, utiliza SDK para [iOS nativo](https://github.com/stripe/stripe-ios) y [Android](https://github.com/stripe/stripe-android). Para instalar el SDK para React Native de Stripe, ejecuta uno de los siguientes comandos en el directorio del proyecto (según el administrador de paquetes que utilices): #### hilado ```bash yarn add @stripe/stripe-react-native ``` #### npm ```bash npm install @stripe/stripe-react-native ``` A continuación, instala otras dependencias necesarias: - Para iOS, vaya al directorio **ios** y ejecute `pod install` para asegurarse de que también instala las dependencias nativas necesarias. - Para Android, no hay más dependencias para instalar. > Recomendamos seguir la [guía oficial de TypeScript](https://reactnative.dev/docs/typescript#adding-typescript-to-an-existing-project) para agregar soporte para TypeScript. ### Inicialización de Stripe Para inicializar Stripe en tu aplicación React Native, ajusta tu pantalla de pago con el componente `StripeProvider` o usa el método de inicialización `initStripe`. Solo se requiere la [clave publicable](https://docs.stripe.com/keys.md#obtain-api-keys) de la API en `publishableKey`. El siguiente ejemplo muestra cómo inicializar Stripe usando el componente `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 */} ); } ``` > Usa las [claves de prueba](https://docs.stripe.com/keys.md#obtain-api-keys) de la API durante las pruebas y el desarrollo, y tus claves para [modo activo](https://docs.stripe.com/keys.md#test-live-modes) cuando publiques tu aplicación. ## Habilita métodos de pago Los pagos con tarjeta están habilitados de forma predeterminada. Consulta la [configuración de tus métodos de pago](https://dashboard.stripe.com/settings/payment_methods) para habilitar más métodos de pago que quieras admitir. ## Agregar un punto de conexión [Lado del servidor] > #### Nota > > Para mostrar la PaymentSheet antes de crear un PaymentIntent, consulta [Recopila datos de pago antes de crear un Intent](https://docs.stripe.com/payments/accept-a-payment-deferred.md?type=payment). Esta integración usa tres objetos de la API de Stripe: 1. [PaymentIntent](https://docs.stripe.com/api/payment_intents.md): Stripe lo utiliza para representar tu intención de cobrarle a un cliente, haciendo el seguimiento de los intentos de cobro y de los cambios en el estado del pago a lo largo del proceso. 1. Una [Account configurada por el cliente](https://docs.stripe.com/api/v2/core/accounts/object.md#v2_account_object-applied_configurations) o un [Customer](https://docs.stripe.com/api/customers.md) Object: para configurar un método de pago para pagos futuros, debes asociarlo a un cliente. Crea un objeto que represente a tu cliente cuando cree una cuenta en tu negocio. Si tu cliente realiza un pago como invitado, puedes crear una `Account` o `Customer` Object antes del pago y asociarlo más adelante con tu propia representación interna de la cuenta del cliente. 1. [CustomerSession](https://docs.stripe.com/api/customer_sessions.md): la información del objeto que representa a tu cliente es sensible y no se puede recuperar directamente desde una app. Una `CustomerSession` le otorga al SDK acceso temporal con alcance limitado a la `Account` o `Customer` y proporciona opciones de configuración adicionales. Consulta la lista completa de [opciones de configuración](https://docs.stripe.com/api/customer_sessions/create.md#create_customer_session-components). Por motivos de seguridad, tu aplicación no puede crear estos objetos. En su lugar, agrega un punto de conexión en tu servidor que haga lo siguiente: 1. Recupera el objeto `Account` o `Customer`, o crea uno nuevo. 1. Crea una [CustomerSession](https://docs.stripe.com/api/customer_sessions.md) para el objeto `Account` o `Customer`. 1. Crea un `PaymentIntent` con el [importe](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-amount), la [moneda](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-currency), [setup_future_usage](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-setup_future_usage), y el [customer_account](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer_account) o el [customer](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer). 1. Devuelve el *client secret* (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)) del `PaymentIntent`, el `client_secret` de la `CustomerSession`, el ID del `Account` o `Customer` y tu [clave publicable](https://dashboard.stripe.com/apikeys) a tu app. > El Payment Element móvil solo admite `setup_future_usage` con tarjetas y cuentas bancarias de EE. UU. Los métodos de pago que se muestran a los clientes durante el proceso de compra también se incluyen en el PaymentIntent. Puedes permitir que Stripe extraiga los métodos de pago de tu configuración del Dashboard o puedes enumerarlos manualmente. Independientemente de la opción que elijas, debes saber que la moneda especificada en el PaymentIntent filtra los métodos de pago que se muestran al cliente. Por ejemplo, si especificas `eur` en el PaymentIntent y tienes habilitado OXXO en el Dashboard, OXXO no se mostrará al cliente porque OXXO no admite pagos en `eur`. A menos que tu integración requiera una opción basada en código para ofrecer métodos de pago, Stripe recomienda usar la opción automatizada. Esto se debe a que Stripe evalúa la moneda, las restricciones de los métodos de pago y otros parámetros para determinar la lista de métodos de pago admitidos. Se les da prioridad a los métodos de pago que aumentan la conversión y guardan mayor relación con la moneda y la ubicación del cliente. #### Gestionar los métodos de pago desde el Dashboard Puedes administrar los métodos de pago desde el [Dashboard](https://dashboard.stripe.com/settings/payment_methods). Stripe maneja la devolución de métodos de pago elegibles según factores como el monto de la transacción, la moneda y el flujo de pago. El PaymentIntent se crea según los métodos de pago que configuraste en el Dashboard. Si no quieres usar el Dashboard o si quieres especificar métodos de pago manualmente, puedes enumerarlos usando el atributo `payment_method_types`. #### curl ```bash # Create a Customer (use an existing Customer ID if this is a returning customer) curl https://api.stripe.com/v1/customers \ -u <>: \ -X "POST" \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" # Create an CustomerSession for the Customer curl https://api.stripe.com/v1/customer_sessions \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "components[mobile_payment_element][enabled]"=true \ -d "components[mobile_payment_element][features][payment_method_save]"=enabled \ -d "components[mobile_payment_element][features][payment_method_redisplay]"=enabled \ -d "components[mobile_payment_element][features][payment_method_remove]"=enabled # Create a PaymentIntent curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \ -d "setup_future_usage"="off_session" \ -d "automatic_payment_methods[enabled]"=true \ ``` #### Cómo enumerar métodos de pago manualmente #### curl ```bash # Create a Customer (use an existing Customer ID if this is a returning customer) curl https://api.stripe.com/v1/customers \ -u <>: \ -X "POST" \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" # Create an CustomerSession for the Customer curl https://api.stripe.com/v1/customer_sessions \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "components[mobile_payment_element][enabled]"=true \ -d "components[mobile_payment_element][features][payment_method_save]"=enabled \ -d "components[mobile_payment_element][features][payment_method_redisplay]"=enabled \ -d "components[mobile_payment_element][features][payment_method_remove]"=enabled # Create a PaymentIntent curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \ -d "setup_future_usage"="off_session" \ -d "payment_method_types[]"="card" \ ``` > Cada método de pago debe admitir la moneda especificada en el PaymentIntent, y tu empresa tiene que estar establecida en uno de los países que admite cada método de pago. Consulta la página de [opciones de integración de métodos de pago](https://docs.stripe.com/payments/payment-methods/integration-options.md) para obtener más información sobre qué admitimos. ## Recopila datos de pago [Lado del cliente] Antes de mostrar el Payment Element móvil, tu página de finalización de compra debe cumplir con los siguientes requisitos: - Mostrar los productos de la compra y el importe total - Recopilar la información de envío necesaria - Incluir un botón de pago para presentar la interfaz de usuario de Stripe En la finalización de compra de tu aplicación, haz una solicitud de red al punto de conexión de back-end que creaste en el paso anterior y llama a `initPaymentSheet` desde el hook `useStripe`. #### Accounts v2 ```javascript export default function CheckoutScreen() { const { initPaymentSheet, presentPaymentSheet } = useStripe(); const [loading, setLoading] = useState(false); const fetchPaymentSheetParams = async () => { const response = await fetch(`${API_URL}/payment-sheet`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, }); const { paymentIntent, ephemeralKey, customer_account } = await response.json(); return { paymentIntent, ephemeralKey, customer_account, }; }; const initializePaymentSheet = async () => { const { paymentIntent, ephemeralKey, customer_account, } = await fetchPaymentSheetParams(); const { error } = await initPaymentSheet({ merchantDisplayName: "Example, Inc.", customerAccountId: customer_account, customerEphemeralKeySecret: ephemeralKey, paymentIntentClientSecret: paymentIntent, // Set `allowsDelayedPaymentMethods` to true if your business accepts payment // methods that complete payment after a delay, like SEPA Debit and Sofort. allowsDelayedPaymentMethods: true, defaultBillingDetails: { name: 'Jane Doe', } }); if (!error) { setLoading(true); } }; const openPaymentSheet = async () => { // see below }; useEffect(() => { initializePaymentSheet(); }, []); return (