# Crear una plataforma de SaaS con Accounts v1 Crea cuentas conectadas con Accounts v1 y luego facilita los pagos directos a ellas en tu plataforma SaaS. > #### Integraciones de API Accounts v2 > > Esta guía solo se aplica a las plataformas Connect existentes que usan la API Accounts v1. Si eres un nuevo usuario Connect o si usas la API Accounts v2, consulta la [guía de plataformas SaaS v2](https://docs.stripe.com/connect/saas.md). En esta guía, se explica cómo habilitar a los usuarios para que acepten pagos, transfieran parte de sus ganancias tu saldo y transfieran el resto a las cuentas bancarias de tus usuarios. Para ilustrar estos conceptos, usaremos una plataforma de ejemplo que les permite a las empresas crear sus propias tiendas en línea. # Web > This is a Web for when platform is web. View the full page at https://docs.stripe.com/connect/end-to-end-saas-platform?platform=web. ## Prerrequisitos 1. [Registra tu plataforma](https://dashboard.stripe.com/connect). 1. [Verifica y agrega datos de la empresa en Dashboard](https://dashboard.stripe.com/account/onboarding). 1. [Completa el perfil de tu plataforma](https://dashboard.stripe.com/connect/settings/profile). 1. [Personaliza la configuración de tu marca](https://dashboard.stripe.com/settings/connect/stripe-dashboard/branding). Agrega el nombre, el ícono y el color de la marca de la empresa. ## Configura Stripe [Lado del servidor] Instala las bibliotecas oficiales de Stripe para acceder a la API desde tu aplicación: #### 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' ``` ## Crea una cuenta conectada Cuando un usuario (un vendedor o proveedor de servicios) crea una cuenta en tu plataforma, tienes que crear una [Cuenta](https://docs.stripe.com/api/accounts.md) de usuario (llamada *cuenta conectada*) para poder aceptar pagos y transferir fondos a su cuenta bancaria. Las cuentas conectadas representan a tu usuario en la API de Stripe y ayudan con la recopilación de los requisitos de onboarding para que Stripe pueda verificar la identidad del usuario. En el ejemplo de la plataforma para crear tiendas, la cuenta conectada representa a la empresa que configura su tienda en línea. ![Captura de pantalla del formulario del onboarding de Connect](https://b.stripecdn.com/docs-statics-srv/assets/Kavholm-Seamless-Standard.78b64d90c0bf87130c8b6ba1ef53df7f.png) ### Crear una cuenta conectada y completar la información automáticamente Usa la API `/v1/accounts` para [crear](https://docs.stripe.com/api/accounts/create.md) una cuenta conectada. Puedes crear la cuenta conectada utilizando los [parámetros predeterminados de la cuenta conectada](https://docs.stripe.com/connect/migrate-to-controller-properties.md) o especificando el tipo de cuenta. #### Con propiedades predeterminadas ```curl curl -X POST https://api.stripe.com/v1/accounts \ -u "<>:" ``` #### Con tipo de cuenta ```curl curl https://api.stripe.com/v1/accounts \ -u "<>:" \ -d type=standard ``` Si ya recopilaste información para tus cuentas conectadas, puedes completar automáticamente esa información en el objeto `Account`. Puedes completar previamente cualquier información de la cuenta, incluida la información personal y de la empresa, la información de la cuenta externa, etc. Después de crear la `cuenta`, crea una [persona](https://docs.stripe.com/api/persons/create.md) que represente a la persona responsable de abrir la cuenta, con `relationship.representative` establecido en verdadero y cualquier información de la cuenta que quieras completar previamente (por ejemplo, su nombre y apellido). ```curl curl https://api.stripe.com/v1/accounts/{{ACCOUNT_ID}}/persons \ -u "<>:" \ -d first_name=Jenny \ -d last_name=Rosen \ -d "relationship[representative]=true" ``` El onboarding de Connect no solicita la información que se completó automáticamente. Sin embargo, sí le pide al titular de la cuenta que confirme la información completada automáticamente antes de aceptar el [contrato de servicio de Connect](https://docs.stripe.com/connect/service-agreement-types.md). Cuando pruebes la integración, completa automáticamente la información de la cuenta con los [datos de prueba](https://docs.stripe.com/connect/testing.md). ### Crea un enlace de cuenta Puedes crear un enlace de cuenta llamando a la API [Account Links](https://docs.stripe.com/api/account_links.md) con los siguientes parámetros: - `account` - `refresh_url` - `return_url` - `type` = `account_onboarding` ```curl curl https://api.stripe.com/v1/account_links \ -u "<>:" \ -d "account={{CONNECTEDACCOUNT_ID}}" \ --data-urlencode "refresh_url=https://example.com/reauth" \ --data-urlencode "return_url=https://example.com/return" \ -d type=account_onboarding ``` ### Redirige al usuario a la URL del enlace de cuenta La respuesta a tu solicitud de [Account Links](https://docs.stripe.com/api/account_links.md) incluye un valor para la `url` de la clave. Redirige a este enlace para enviar al usuario al flujo. Los enlaces de cuenta son temporales y de un solo uso, ya que otorgan acceso a la información personal del usuario de la cuenta conectada. Autentica al usuario en tu aplicación antes de redirigirlo a esta URL. Si deseas completar previamente la información, debes hacerlo antes de generar el enlace de la cuenta. Después de crear el enlace de la cuenta, no podrás leer ni escribir información para la cuenta. > No envíes por correo electrónico, ni por mensaje de texto ni por ningún otro medio las URL del enlace de la cuenta fuera de la aplicación de la plataforma. En lugar de eso, envíalas al titular de la cuenta autenticado dentro de tu aplicación. ### Gestiona el caso de un usuario que vuelve a la plataforma El onboarding de Connect requiere que especifiques una `return_url` y una `refresh_url` para gestionar todos los casos en los que se redirige al usuario a tu plataforma. Es importante implementarlas correctamente para que el usuario tenga la mejor experiencia. > Puedes usar HTTP para tu `return_url` y `refresh_url` mientras estés en un entorno de pruebas (por ejemplo, testear con localhost), aunque en modo activo solo se acepta HTTPS. Debes actualizar las URL de prueba a URL HTTPS antes de pasar a modo activo. #### return_url Stripe redirige al usuario a esta URL cuando dicho usuario completa el flujo de onboarding de Connect. Esto no implica que se haya recopilado toda la información ni que no haya requisitos pendientes en la cuenta. Solo significa que se entró y se salió del flujo correctamente. No se especifica ningún estado a través de esta URL. Después de redirigir al usuario a tu `return_url`, verifica el estado del parámetro `details_submitted` en su cuenta por medio de uno de los siguientes métodos: - Escucha los webhooks `account.updated`. - Llamando a la API [Accounts](https://docs.stripe.com/api/accounts.md) e inspeccionando el objeto devuelto #### refresh_url Se redirige a tu usuario a la `refresh_url` en los siguientes casos: - Se venció el enlace (pasaron algunos minutos desde que se creó). - El usuario ya visitó el enlace (actualizó la página o se desplazó de página en el navegador). - Tu plataforma ya no puede acceder a la cuenta. - Se rechazó la cuenta. La `refresh_url` debería activar un método en tu servidor para volver a llamar a la API [Account Links](https://docs.stripe.com/api/account_links.md) con los mismos parámetros y redirigir al usuario al flujo de onboarding de Connect para crear una experiencia fluida. ### Gestiona los casos de usuarios que no hayan completado el onboarding Si se redirige al usuario a tu `return_url`, es posible que no haya completado el proceso de onboarding. Usa el punto de conexión `/v1/accounts` para recuperar la cuenta del usuario y verificar si hay `charges_enabled`. Si la cuenta no ha finalizado todo el proceso de onboarding, proporciona indicaciones de interfaz de usuario para que el usuario pueda continuarlo más tarde. Podrá completar la activación de su cuenta a través de un nuevo enlace de cuenta (generado por tu integración). Para ver si ha completado el proceso de onboarding, verifica el estado del parámetro `details_submitted` en su cuenta. ## Habilita métodos de pago Visualiza tu [configuración de métodos de pago](https://dashboard.stripe.com/settings/connect/payment_methods) y habilita los que quieras aceptar. Los pagos con tarjeta se habilitan de forma predeterminada, pero puedes habilitar y deshabilitar métodos de pago según sea necesario. Esta guía asume que tienes habilitados Bancontact, tarjetas de crédito, EPS, iDEAL, Przelewy24, débito directo SEPA y Sofort. Antes de que se abra el formulario de pago, 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. Los métodos de pago menos prioritarios se ocultan en un menú de contenido adicional. > El **componente integrado de configuración de métodos de pago** permite que las cuentas conectadas configuren los métodos de pago que ofrecen en el proceso de compra sin necesidad de acceder al Dashboard de Stripe. Obtén más información sobre el [componente integrado de configuración de métodos de pago](https://docs.stripe.com/connect/supported-embedded-components/payment-method-settings.md) y recibe una notificación cuando esté disponible. ## Acepta un pago Incorpora [Stripe Checkout](https://stripe.com/payments/checkout) como un formulario de pago directamente en tu sitio web o redirige a los usuarios a una página alojada por Stripe para aceptar pagos. Checkout admite múltiples métodos de pago y muestra automáticamente los más relevantes a tu cliente. También puedes usar el Payment Element, un componente prediseñado de la interfaz de usuario que está integrado como un iframe en tu formulario de pago, para aceptar múltiples métodos de pago con una sola integración del front-end. #### Página alojada por Stripe ### Crea una sesión de Checkout (Client-side) (Server-side) Una sesión de Checkout controla lo que tu cliente ve en el formulario de pago integrable, por ejemplo, las partidas, el importe y la moneda del pedido y los métodos de pago aceptados. Cuando se realizan cargos Direct, Checkout usa la configuración de la imagen de marca de la cuenta conectada. Para obtener más información, consulta la sección [Personalizar la imagen de marca](https://docs.stripe.com/connect/direct-charges.md?platform=web&ui=stripe-hosted#branding). A diferencia de los cargos a un Destino y de los cargos y envíos de fondos separados, los usuarios de las cuentas conectadas son responsables de gestionar las disputas asociadas con los cargos Direct. No es responsabilidad de la plataforma. En tu servidor, haz la siguiente llamada a la API de Stripe. Después de haber creado una sesión de Checkout, redirige a tu cliente a la [URL](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-url) recibida en la respuesta. ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \ -d mode=payment \ -d "line_items[0][price]={{PRICE_ID}}" \ -d "line_items[0][quantity]=1" \ -d "payment_intent_data[application_fee_amount]=123" \ --data-urlencode "success_url=https://example.com/success" ``` - `line_items`: este argumento representa los artículos que compra el cliente y que se mostrarán en la interfaz de usuario alojada. - `success_url`: este argumento redirige al usuario después de que completa el pago. - `Cuenta de Stripe`: este encabezado indica que aceptas [cargos Direct](https://docs.stripe.com/connect/direct-charges.md) para tu cuenta conectada. Con los cargos Direct, la cuenta conectada es responsable de las comisiones de Stripe, de los reembolsos y de los contracargos. La imagen de marca de la cuenta conectada se utiliza en el proceso de compra, lo que transmite al cliente la sensación de estar interactuando directamente con la empresa y no con tu plataforma. - (Opcional) `payment_intent_data[application_fee_amount]`: este argumento especifica el importe que tu plataforma tomará de la transacción. Después de que se procesa el pago en la cuenta conectada, se transfiere `application_fee_amount` a la plataforma y la comisión de Stripe se deduce del saldo de la cuenta conectada. ![Flujo de creación de cuenta](https://b.stripecdn.com/docs-statics-srv/assets/direct_charges.a2a8b68037ac95fe22140d6dde9740d3.svg) ### Gestiona eventos posteriores al pago (del lado del servidor) Stripe envía un evento [checkout.session.completed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.completed) cuando se completa el pago. [Utiliza un webhook para recibir estos eventos](https://docs.stripe.com/webhooks/quickstart.md) y ejecutar acciones, como enviar un correo electrónico de confirmación del pedido a tu cliente, registrar la venta en una base de datos o iniciar el flujo de tareas para un 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. Además, algunos métodos de pago tardan entre 2 y 14 días en confirmar el pago. Si configuras tu integración para escuchar eventos asincrónicos, podrás aceptar varios [métodos de pago](https://stripe.com/payments/payment-methods-guide) con una sola integración. Además de gestionar el evento `checkout.session.completed`, te recomendamos que gestiones otros dos eventos cuando cobres pagos con Checkout: | Evento | Descripción | Próximos pasos | | -------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | | [checkout.session.completed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.completed) | Mediante el envío del formulario de Checkout, el cliente ha autorizado correctamente el pago. | Espera hasta saber si el pago se efectuó correctamente o no. | | [checkout.session.async_payment_succeeded](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.async_payment_succeeded) | El pago del cliente se efectuó correctamente. | Completa el pedido de los productos o servicios comprados. | | [checkout.session.async_payment_failed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.async_payment_failed) | El pago se rechazó o falló por algún otro motivo. | Ponte en contacto con el cliente por correo electrónico y solicítale que haga un nuevo pedido. | Todos estos eventos incluyen el objeto [Checkout Session](https://docs.stripe.com/api/checkout/sessions.md). Después de que el pagose efectúa, el estado subyacente del *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods) cambia de `processing` a `succeeded`. #### Página integrada completa ### Crea una sesión de Checkout (Client-side) (Server-side) Una sesión de Checkout controla lo que tu cliente ve en la página de pago alojada en Stripe, como partidas, el importe y la moneda del pedido, y los métodos de pago aceptados. Cuando se realizan cargos Direct, Checkout utiliza la configuración de marca de la cuenta conectada. Para obtener más información, consulta la sección [Personalizar imagen de marca](https://docs.stripe.com/connect/direct-charges.md?platform=web&ui=stripe-hosted#branding). A diferencia de los cargos a un Destino y de los cargos y envíos de fondos separados, los usuarios de las cuentas conectadas son responsables de gestionar las disputas asociadas con los cargos Direct. No es responsabilidad de la plataforma. En tu servidor, haz la siguiente llamada a la API de Stripe. La respuesta de creación de la sesión de Checkout incluye un `client_secret` que usarás en el siguiente paso para montar Checkout. ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \ -d mode=payment \ -d "line_items[0][price]={{PRICE_ID}}" \ -d "line_items[0][quantity]=1" \ -d "payment_intent_data[application_fee_amount]=123" \ -d ui_mode=embedded_page \ --data-urlencode "return_url=https://example.com/checkout/return?session_id={CHECKOUT_SESSION_ID}" ``` - `line_items`: este argumento representa los artículos que compra el cliente y que aparecerán en la interfaz de usuario alojada. - `return_url`: este argumento redirige al usuario después de completar el intento de pago. - `Stripe-Account`: este encabezado indica un [cargo Direct](https://docs.stripe.com/connect/direct-charges.md) para la cuenta conectada. Con los cargos Direct, la cuenta conectada es responsable de las comisiones de Stripe, de los reembolsos y de los contracargos. La imagen de marca de la cuenta conectada se utiliza en Checkout, lo que le transmite al cliente la sensación de estar interactuando directamente con el comerciante a cargo del cobro y no con tu plataforma. - (Opcional) `payment_intent_data[application_fee_amount]`: este argumento especifica el importe que tu plataforma tomará de la transacción. Si estás usando la [herramienta de precios de la plataforma](https://docs.stripe.com/connect/platform-pricing-tools.md) de Stripe para gestionar los precios de las comisiones de la plataforma desde el [Dashboard](https://dashboard.stripe.com/test/settings/connect/platform_pricing/payments), no incluyas este argumento, ya que anulará toda lógica de precios establecida por la herramienta. Una vez procesado el pago en la cuenta conectada, se transfiere el `application_fee_amount` a la plataforma, y la comisión de Stripe se deduce del saldo de la cuenta conectada. Asegúrate de que la `return_url` corresponda a una página de tu sitio web que proporcione el estado del pago. Cuando Stripe redirija al cliente a la `return_url`, reemplazaremos la cadena `{CHECKOUT_SESSION_ID}` con la ID de la sesión de Checkout. Usa esto para recuperar la sesión de Checkout e inspeccionar el estado a fin de decidir qué mostrarles a los clientes. Cuando especifiques la `return_url`, también puedes adjuntar tus propios parámetros de consulta que se mantendrán durante el proceso de redireccionamiento. ![Flujo de creación de cuenta](https://b.stripecdn.com/docs-statics-srv/assets/direct_charges.a2a8b68037ac95fe22140d6dde9740d3.svg) ### Monta Checkout (del lado del cliente) #### HTML + JS Checkout está disponible como parte de [Stripe.js](https://docs.stripe.com/js.md). Incluye el script de Stripe.js en tu página agregándolo al encabezado de tu archivo HTML. A continuación, crea un nodo DOM vacío (contenedor) para usarlo en el montaje. ```html
``` Inicializa Stripe.js con la clave publicable de tu API. Crea una función `fetchClientSecret` asincrónica que haga una solicitud a tu servidor para crear la sesión de Checkout y recuperar el secreto de cliente. Pasa esta función a `options` al crear la instancia de Checkout: ```javascript // Initialize Stripe.js const stripe = Stripe('<>', { stripeAccount: '{{CONNECTED_ACCOUNT_ID}}', }); initialize(); // Fetch Checkout Session and retrieve the client secret async function initialize() { const fetchClientSecret = async () => { const response = await fetch("/create-checkout-session", { method: "POST", }); const { clientSecret } = await response.json(); return clientSecret; }; // Initialize Checkout const checkout = await stripe.createEmbeddedCheckoutPage({ fetchClientSecret, }); // Mount Checkout checkout.mount('#checkout'); } ``` #### React Instala Connect.js y las bibliotecas de React Connect.js desde el [registro público de npm](https://www.npmjs.com/package/@stripe/react-connect-js). ```bash npm install --save @stripe/connect-js @stripe/react-connect-js ``` Para utilizar el componente Embedded Checkout, crea un `EmbeddedCheckoutProvider`. Llama a `loadStripe` con tu clave de API publicable y pasa la `Promise` devuelta al proveedor. Crea una función `fetchClientSecret` asíncrona que haga una solicitud a tu servidor para que cree la sesión de Checkout y recupere el secreto de cliente. Pasa esta función al accesorio `options` aceptado por el proveedor. ```jsx import * as React from 'react'; import {loadStripe} from '@stripe/stripe-js'; import { EmbeddedCheckoutProvider, EmbeddedCheckout } from '@stripe/react-stripe-js'; // Make sure to call `loadStripe` outside of a component’s render to avoid // recreating the `Stripe` object on every render. const stripePromise = loadStripe('pk_test_123'); const App = ({fetchClientSecret}) => { const options = {fetchClientSecret}; return ( ) } ``` Checkout se muestra en un iframe que envía la información de pago a Stripe de manera segura mediante una conexión HTTPS. No coloques Checkout dentro de otro iframe porque, para algunos métodos de pago, se requiere el redireccionamiento a otra página a fin de confirmar el pago. ### Personaliza el aspecto Para personalizar Checkout y que coincida con el diseño de tu sitio, establece el color de fondo, el color del botón, el radio del borde y las fuentes en la [configuración de imagen de marca](https://dashboard.stripe.com/settings/branding) de tu cuenta. De forma predeterminada, Checkout procesa sin relleno o margen externos. Te recomendamos usar un elemento contenedor como un div para aplicar el margen deseado (por ejemplo, 16 px en todos los lados). ### Gestiona eventos posteriores al pago (del lado del servidor) Stripe envía un evento [checkout.session.completed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.completed) cuando se completa el pago. [Utiliza un webhook para recibir estos eventos](https://docs.stripe.com/webhooks/quickstart.md) y ejecutar acciones, como enviar un correo electrónico de confirmación del pedido a tu cliente, registrar la venta en una base de datos o iniciar el flujo de tareas para un 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. Además, algunos métodos de pago tardan entre 2 y 14 días en confirmar el pago. Si configuras tu integración para escuchar eventos asincrónicos, podrás aceptar varios [métodos de pago](https://stripe.com/payments/payment-methods-guide) con una sola integración. Además de gestionar el evento `checkout.session.completed`, te recomendamos que gestiones otros dos eventos cuando cobres pagos con Checkout: | Evento | Descripción | Próximos pasos | | -------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | | [checkout.session.completed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.completed) | Mediante el envío del formulario de Checkout, el cliente ha autorizado correctamente el pago. | Espera hasta saber si el pago se efectuó correctamente o no. | | [checkout.session.async_payment_succeeded](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.async_payment_succeeded) | El pago del cliente se efectuó correctamente. | Completa el pedido de los productos o servicios comprados. | | [checkout.session.async_payment_failed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.async_payment_failed) | El pago se rechazó o falló por algún otro motivo. | Ponte en contacto con el cliente por correo electrónico y solicítale que haga un nuevo pedido. | Todos estos eventos incluyen el objeto [Checkout Session](https://docs.stripe.com/api/checkout/sessions.md). Después de que el pagose efectúa, el estado subyacente del *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods) cambia de `processing` a `succeeded`. #### Flujo personalizado ### Crea un PaymentIntent (del lado del servidor) Stripe usa un objeto [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) para representar tu intención de cobrarle a un cliente y hace el seguimiento de los intentos de cobro y de los cambios en el estado del pago en todo el proceso. > Si quieres procesar el Payment Element antes de crearlo, consulta [Recopilar los datos de pago antes de crear un Intent](https://docs.stripe.com/payments/accept-a-payment-deferred.md?type=payment). ![Un diagrama resumen de todo el flujo de pago](https://b.stripecdn.com/docs-statics-srv/assets/accept-a-payment-payment-element.5cf6795a02f864923f9953611493d735.svg) Los métodos de pago que se les muestran a los clientes durante el proceso de finalización de compra también se incluyen en el PaymentIntent. Puedes permitir que Stripe extraiga automáticamente los métodos de pago de la configuración del Dashboard o puedes enumerarlos en forma manual. A menos que tu integración requiera una opción basada en código para ofrecer métodos de pago, no los enumeres manualmente. 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. Stripe les da prioridad a aquellos que aumentan la conversión y guardan mayor relación con la moneda y la ubicación del cliente. Los métodos de pago menos prioritarios se ocultan en un menú de contenido adicional. #### Gestiona los métodos de pago desde el Dashboard ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \ -d amount=1099 \ -d currency=eur \ -d "automatic_payment_methods[enabled]=true" \ -d application_fee_amount=123 ``` Al crear un PaymentIntent, debes especificar ciertos parámetros: - `amount` y `currency`: crea un PaymentIntent en tu servidor con un importe y una moneda. - (Opcional) `automatic_payment_methods`: en la última versión del API, no es necesario especificar este parámetro porque Stripe habilita la funcionalidad de forma predeterminada. Puedes gestionar los métodos de pago desde el [Dashboard](https://dashboard.stripe.com/settings/payment_methods). Stripe devuelve en forma automática los métodos de pago que cumplen con los requisitos en función de factores, como el importe de la transacción, la moneda y el flujo de pagos. - (Opcional) `payment_intent_data[application_fee_amount]`: este argumento especifica el importe que tu plataforma tomará de la transacción. Si estás usando la [herramienta de precios de la plataforma](https://docs.stripe.com/connect/platform-pricing-tools.md) de Stripe para gestionar los precios de las comisiones de la plataforma desde el [Dashboard](https://dashboard.stripe.com/test/settings/connect/platform_pricing/payments), no incluyas este argumento, ya que anulará toda lógica de precios establecida por la herramienta. Una vez procesado el pago en la cuenta conectada, se transfiere el `application_fee_amount` a la plataforma, y la comisión de Stripe se deduce del saldo de la cuenta conectada. #### Enumera manualmente los métodos de pago ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \ -d amount=1099 \ -d currency=eur \ -d "payment_method_types[]=bancontact" \ -d "payment_method_types[]=card" \ -d "payment_method_types[]=eps" \ -d "payment_method_types[]=ideal" \ -d "payment_method_types[]=p24" \ -d "payment_method_types[]=sepa_debit" \ -d "payment_method_types[]=sofort" \ -d application_fee_amount=123 ``` Al crear un PaymentIntent, debes especificar ciertos parámetros: - `amount`; crea un PaymentIntent en tu servidor con un importe específico. Determina siempre cuánto cobrar del lado del servidor, ya que se trata de un entorno de confianza. Este enfoque evita que clientes maliciosos puedan elegir sus propios precios. - `currency`: la moneda que incluyes en el PaymentIntent filtra los métodos de pago que se muestran al cliente, así que elígela en función de los métodos de pago que quieras ofrecer. Por ejemplo, si especificas `eur` y tienes habilitado OXXO en el Dashboard, OXXO no aparecerá ante el cliente porque no admite pagos en `eur`. Algunos métodos de pago admiten varias monedas y países. En el código de ejemplo de esta guía se usan Bancontact, tarjetas de crédito, EPS, iDEAL, Przelewy24, débito directo SEPA y Sofort. - `"payment_method_types[]"`: enumera manualmente todos los métodos de pago que quieres aceptar. - (Opcional) `payment_intent_data[application_fee_amount]`: este argumento especifica el importe que tu plataforma tomará de la transacción. Si estás usando la [herramienta de precios de la plataforma](https://docs.stripe.com/connect/platform-pricing-tools.md) de Stripe para gestionar los precios de las comisiones de la plataforma desde el [Dashboard](https://dashboard.stripe.com/test/settings/connect/platform_pricing/payments), no incluyas este argumento, ya que anulará toda lógica de precios establecida por la herramienta. Una vez procesado el pago en la cuenta conectada, se transfiere el `application_fee_amount` a la plataforma, y la comisión de Stripe se deduce del saldo de la cuenta conectada. > 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 las [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. ### Recuperar el secreto de cliente El PaymentIntent incluye un *secreto de cliente* (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)) que el lado del cliente usa para completar el proceso de pago de forma segura. Puedes usar diferentes métodos para pasar el secreto del cliente al lado del cliente. #### Aplicación de una sola página Recupera el secreto de cliente de un punto de conexión de tu servidor con la funcionalidad `fetch` del navegador. Este método es más conveniente si tu lado del cliente es una aplicación de una sola página, especialmente, si fue diseñada con un marco de front-end moderno como React. Crea el punto de conexión del servidor que se usa para el secreto de cliente: #### Ruby ```ruby get '/secret' do intent = # ... Create or retrieve the PaymentIntent {client_secret: intent.client_secret}.to_json end ``` Luego recupera el secreto de cliente con JavaScript del lado del cliente: ```javascript (async () => { const response = await fetch('/secret'); const {client_secret: clientSecret} = await response.json(); // Render the form using the clientSecret })(); ``` #### Renderización del lado del servidor Especifica el secreto de cliente desde tu servidor al cliente. Este enfoque funciona mejor si tu aplicación genera contenido estático en el servidor antes de enviarlo al navegador. Agrega [client_secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) en tu formulario de finalización de compra. En el código del lado de tu servidor, recupera el secreto de cliente de PaymentIntent: #### Ruby ```erb
``` ```ruby get '/checkout' do @intent = # ... Fetch or create the PaymentIntent erb :checkout end ``` ### Recopila los datos del pago (del lado del cliente) Recopila los datos de pago del lado del cliente con el Payment Element. El Payment Element es un componente de interfaz de usuario prediseñado que simplifica la recopilación de datos de pago para una amplia variedad de métodos de pago. El Payment Element contiene un iframe que envía la información de pago a Stripe de manera segura mediante una conexión HTTPS. No coloques el Payment Element dentro de otro iframe porque, para algunos métodos de pago, se requiere el redireccionamiento a otra página a fin de confirmar el pago. Para que la integración funcione, la dirección de la página de confirmación de compra debe empezar con `https://` en lugar de `http://`. Puedes probar tu integración sin usar HTTPS, pero recuerda [habilitarla](https://docs.stripe.com/security/guide.md#tls) cuando todo esté listo para aceptar pagos reales. #### Configura Stripe.js #### HTML + JS El Payment Element se encuentra disponible automáticamente como funcionalidad de Stripe.js. Para incluir el script Stripe.js en tu página de finalización de compra, agrégalo al `head` de tu archivo HTML. Carga siempre Stripe.js directamente desde js.stripe.com para cumplir con la normativa PCI. No incluyas el script en un paquete ni alojes una copia en tus sistemas. ```html Checkout ``` Crea una instancia de `Stripe` con el siguiente JavaScript en tu página de finalización de compra: ```javascript // Initialize Stripe.js with the same connected account ID used when creating // the PaymentIntent. const stripe = Stripe('<>', { stripeAccount: '{{CONNECTED_ACCOUNT_ID}}' }); ``` #### Agrega Stripe Elements y el Payment Element a tu página de pago El Payment Element necesita un lugar donde residir en tu página de pago. Crea un nodo DOM vacío (contenedor) con una ID única en tu formulario de pago. ```html
``` Cuando se haya cargado el formulario, crea una instancia de Payment Element y móntala en el nodo DOM del contenedor junto con el [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) del paso anterior. Especifica este valor como opción cuando crees la instancia [Elements](https://docs.stripe.com/js/elements_object/create). El secreto de cliente debe gestionarse con cuidado porque sirve para completar el cargo. No lo registres, no lo insertes en direcciones URL ni se lo muestres a nadie que no sea el cliente. ```javascript const options = { clientSecret: '{{CLIENT_SECRET}}', // Fully customizable with the Appearance API appearance: {/*...*/}, }; // Set up Stripe.js and Elements to use in checkout form using the client secret const elements = stripe.elements(options); // Create and mount the Payment Element const paymentElement = elements.create("payment"); paymentElement.mount("#payment-element"); ``` El Payment Element procesa un formulario dinámico que le permite a tu cliente elegir un método de pago. El formulario recopila automáticamente todos los datos de pago necesarios para el método de pago que el cliente seleccionó. Al configurar el objeto `Elements`, podrás [personalizar el aspecto del Payment Element](https://docs.stripe.com/elements/appearance-api.md) para que coincida con el diseño de tu sitio. #### Reaccionar Instala [React Stripe.js](https://www.npmjs.com/package/@stripe/react-stripe-js) y el [cargador Stripe.js](https://www.npmjs.com/package/@stripe/stripe-js) desde el registro público de npm: ```bash npm install --save @stripe/react-stripe-js @stripe/stripe-js ``` ### Agrega y configura el proveedor Elements en tu página de pago Para usar el componente Payment Element, envuelve el componente de tu página de confirmación de compra con un [proveedor Elements](https://docs.stripe.com/sdks/stripejs-react.md#elements-provider). Llama a `loadStripe` con tu clave publicable y especifica la `Promise` devuelta junto con el [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) del paso anterior como `options` al proveedor `Elements`. ```jsx import React from 'react'; import ReactDOM from 'react-dom'; import {Elements} from '@stripe/react-stripe-js'; import {loadStripe} from '@stripe/stripe-js'; import CheckoutForm from './CheckoutForm'; // Make sure to call `loadStripe` outside of a component’s render to avoid // recreating the `Stripe` object on every render. const stripePromise = loadStripe("<>", { stripeAccount: '{{CONNECTED_ACCOUNT_ID}}' }); function App() { const options = { // pass the client secret from the previous step clientSecret: '{{CLIENT_SECRET}}', // Fully customizable with the Appearance API appearance: {/*...*/}, }; return ( ); }; ReactDOM.render(, document.getElementById('root')); ``` #### Agrega el componente PaymentElement Usa el componente `PaymentElement` para crear tu formulario. ```jsx import React from 'react'; import {PaymentElement} from '@stripe/react-stripe-js'; const CheckoutForm = () => { return (
); }; export default CheckoutForm; ``` El Payment Element procesa un formulario dinámico que le permite a tu cliente elegir un tipo de método de pago. El formulario recopila automáticamente todos los datos de pago necesarios para el método de pago que el cliente seleccionó. Al configurar el proveedor `Elements`, podrás [personalizar el aspecto del Payment Element](https://docs.stripe.com/elements/appearance-api.md) para que coincida con el diseño de tu sitio. ### Envía el pago a Stripe (del lado del cliente) Usa [stripe.confirmPayment](https://docs.stripe.com/js/payment_intents/confirm_payment) para completar el pago con los datos del Payment Element. Proporciona una [return_url](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-return_url) a esta función para indicar a dónde Stripe debe redirigir al usuario después de completar el pago. Es posible que primero se redirija al usuario a un sitio intermedio, como una página de autorización del banco y, luego, a la`return_url`. Los pagos con tarjeta redirigen inmediatamente a la `return_url` cuando un pago se realiza correctamente. Si no quieres realizar el redireccionamiento de pagos con tarjeta una vez que se completan los pagos, puedes configurar el [redireccionamiento](https://docs.stripe.com/js/payment_intents/confirm_payment#confirm_payment_intent-options-redirect) en `if_required`. Esto solo redirigirá a los clientes que finalizan su compra con métodos de pago basados en redireccionamiento. #### HTML + JS ```javascript const form = document.getElementById('payment-form'); form.addEventListener('submit', async (event) => { event.preventDefault(); const {error} = await stripe.confirmPayment({ //`Elements` instance that was used to create the Payment Element elements, confirmParams: { return_url: 'https://example.com/order/123/complete', }, }); if (error) { // This point will only be reached if there is an immediate error when // confirming the payment. Show error to your customer (for example, payment // details incomplete) const messageContainer = document.querySelector('#error-message'); messageContainer.textContent = error.message; } else { // Your customer will be redirected to your `return_url`. For some payment // methods like iDEAL, your customer will be redirected to an intermediate // site first to authorize the payment, then redirected to the `return_url`. } }); ``` #### React Para llamar a [stripe.confirmPayment](https://docs.stripe.com/js/payment_intents/confirm_payment) desde el componente del formulario de pago, usa los hooks [useStripe](https://docs.stripe.com/sdks/stripejs-react.md#usestripe-hook) y [useElements](https://docs.stripe.com/sdks/stripejs-react.md#useelements-hook). Si prefieres componentes de clase tradicionales en lugar de hooks, puedes usar un [ElementsConsumer](https://docs.stripe.com/sdks/stripejs-react.md#elements-consumer). ```jsx import React, {useState} from 'react'; import {useStripe, useElements, PaymentElement} from '@stripe/react-stripe-js'; const CheckoutForm = () => { const stripe = useStripe(); const elements = useElements(); const [errorMessage, setErrorMessage] = useState(null); const handleSubmit = async (event) => { // We don't want to let default form submission happen here, // which would refresh the page. event.preventDefault(); if (!stripe || !elements) { // Stripe.js hasn't yet loaded. // Make sure to disable form submission until Stripe.js has loaded. return; } const {error} = await stripe.confirmPayment({ //`Elements` instance that was used to create the Payment Element elements, confirmParams: { return_url: 'https://example.com/order/123/complete', }, }); if (error) { // This point will only be reached if there is an immediate error when // confirming the payment. Show error to your customer (for example, payment // details incomplete) setErrorMessage(error.message); } else { // Your customer will be redirected to your `return_url`. For some payment // methods like iDEAL, your customer will be redirected to an intermediate // site first to authorize the payment, then redirected to the `return_url`. } }; return (
{/* Show error message to your customers */} {errorMessage &&
{errorMessage}
} ); }; export default CheckoutForm; ``` Asegúrate de que la `return_url` corresponda a una página de tu sitio web que proporcione el estado del pago. Cuando Stripe redirige al cliente a la `return_url`, proporcionamos los siguientes parámetros de consulta de URL: | Parámetro | Descripción | | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | | `payment_intent` | El identificador único del `PaymentIntent`. | | `payment_intent_client_secret` | El [secreto de cliente](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) del objeto `PaymentIntent`. | > Si tienes herramientas que rastrean la sesión del navegador del cliente, es posible que debas agregar el dominio `stripe.com` a la lista de exclusión de referentes. Los redireccionamientos hacen que algunas herramientas creen nuevas sesiones, lo que te impide realizar un seguimiento de la sesión completa. Usa uno de los parámetros de consulta para recuperar el PaymentIntent. Examina el [estado del PaymentIntent](https://docs.stripe.com/payments/paymentintents/lifecycle.md) para decidir qué mostrarás a tus clientes. También puedes adjuntar tus propios parámetros de consulta cuando proporciones la `return_url`, que se mantendrán durante el proceso de redireccionamiento. #### HTML + JS ```javascript // Initialize Stripe.js using your publishable key const stripe = Stripe('<>'); // Retrieve the "payment_intent_client_secret" query parameter appended to // your return_url by Stripe.js const clientSecret = new URLSearchParams(window.location.search).get( 'payment_intent_client_secret' ); // Retrieve the PaymentIntent stripe.retrievePaymentIntent(clientSecret).then(({paymentIntent}) => { const message = document.querySelector('#message') // Inspect the PaymentIntent `status` to indicate the status of the payment // to your customer. // // Some payment methods will [immediately succeed or fail][0] upon // confirmation, while others will first enter a `processing` state. // // [0]: https://stripe.com/docs/payments/payment-methods#payment-notification switch (paymentIntent.status) { case 'succeeded': message.innerText = 'Success! Payment received.'; break; case 'processing': message.innerText = "Payment processing. We'll update you when payment is received."; break; case 'requires_payment_method': message.innerText = 'Payment failed. Please try another payment method.'; // Redirect your user back to your payment page to attempt collecting // payment again break; default: message.innerText = 'Something went wrong.'; break; } }); ``` #### React ```jsx import React, {useState, useEffect} from 'react'; import {useStripe} from '@stripe/react-stripe-js'; const PaymentStatus = () => { const stripe = useStripe(); const [message, setMessage] = useState(null); useEffect(() => { if (!stripe) { return; } // Retrieve the "payment_intent_client_secret" query parameter appended to // your return_url by Stripe.js const clientSecret = new URLSearchParams(window.location.search).get( 'payment_intent_client_secret' ); // Retrieve the PaymentIntent stripe .retrievePaymentIntent(clientSecret) .then(({paymentIntent}) => { // Inspect the PaymentIntent `status` to indicate the status of the payment // to your customer. // // Some payment methods will [immediately succeed or fail][0] upon // confirmation, while others will first enter a `processing` state. // // [0]: https://stripe.com/docs/payments/payment-methods#payment-notification switch (paymentIntent.status) { case 'succeeded': setMessage('Success! Payment received.'); break; case 'processing': setMessage("Payment processing. We'll update you when payment is received."); break; case 'requires_payment_method': // Redirect your user back to your payment page to attempt collecting // payment again setMessage('Payment failed. Please try another payment method.'); break; default: setMessage('Something went wrong.'); break; } }); }, [stripe]); return message; }; export default PaymentStatus; ``` ### Gestiona eventos posteriores al pago (del 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. | ## Pruebas Para probar el flujo de creación de cuentas, [crea cuentas](https://docs.stripe.com/connect/testing.md#creating-accounts) y [usa OAuth](https://docs.stripe.com/connect/testing.md#using-oauth). Para probar la configuración de los **Métodos de pago** de las cuentas conectadas, inicia sesión en una de las cuentas de prueba y accede a la [configuración de los métodos de pago](https://dashboard.stripe.com/settings/payment_methods). Prueba el flujo de compra con las claves de prueba y una cuenta de prueba. Puedes usar las [tarjetas de prueba](https://docs.stripe.com/testing.md) para probar el flujo de pago y simular pagos con distintos resultados. # Hoja de pago > This is a Hoja de pago for when platform is ios and mobile-ui is payment-sheet. View the full page at https://docs.stripe.com/connect/end-to-end-saas-platform?platform=ios&mobile-ui=payment-sheet. ![](https://b.stripecdn.com/docs-statics-srv/assets/ios-overview.9e0d68d009dc005f73a6f5df69e00458.png) Integra la interfaz de usuario de pago prediseñada de Stripe a la confirmación de compra de tu aplicación iOS con la clase [PaymentSheet](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet.html). Consulta nuestro ejemplo de integración [en GitHub](https://github.com/stripe/stripe-ios/tree/master/Example/PaymentSheet%20Example). > #### Soporte de API Accounts v2 > > Payment Sheet no ofrece soporte para *cuentas configuradas por el cliente*. Solo admite objetos `Customer`. ## Prerrequisitos 1. [Registra tu plataforma](https://dashboard.stripe.com/connect). 1. [Verifica y agrega datos de la empresa en Dashboard](https://dashboard.stripe.com/account/onboarding). 1. [Completa el perfil de tu plataforma](https://dashboard.stripe.com/connect/settings/profile). 1. [Personaliza la configuración de tu marca](https://dashboard.stripe.com/settings/connect/stripe-dashboard/branding). Agrega el nombre, el ícono y el color de la marca de la empresa. ## Configurar Stripe [Lado del servidor] [Lado del cliente] Primero, necesitas una cuenta de Stripe. [Inscríbete ahora](https://dashboard.stripe.com/register). ### Lado del servidor Esta integración necesita 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 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. Configura el SDK con tu [clave publicable](https://dashboard.stripe.com/test/apikeys) de Stripe al iniciar la aplicación. Esto permite que tu aplicación haga solicitudes a la API de Stripe. #### Swift ```swift import UIKitimportStripePaymentSheet @main class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {StripeAPI.defaultPublishableKey = "<>" // do any other necessary launch configuration return true } } ``` > Usa las [claves de prueba](https://docs.stripe.com/keys.md#obtain-api-keys) 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. ## Crear una cuenta conectada Cuando un usuario (vendedor o proveedor de servicios) crea un cuenta en tu plataforma, crea una [Cuenta](https://docs.stripe.com/api/accounts.md) de usuario (llamada *cuenta conectada*) para que puedas aceptar pagos y transferir fondos a su cuenta bancaria. Las cuentas conectadas representan a tu usuario en la API de Stripe y ayudan con la recopilación de los requisitos de onboarding para que Stripe pueda verificar la identidad del usuario. En el ejemplo de la plataforma para crear tiendas, la cuenta conectada representa a la empresa que configura su tienda en línea. ![Flujo de creación de cuenta](https://b.stripecdn.com/docs-statics-srv/assets/standard-ios.10c6b24cef1d683d36f2264c726beb1d.png) ### Paso 2.1: Crea una cuenta conectada y completa automáticamente la información del (lado del servidor) Usa la API `/v1/accounts` para [crear](https://docs.stripe.com/api/accounts/create.md) una cuenta conectada. Puedes crear la cuenta conectada utilizando los [parámetros predeterminados de la cuenta conectada](https://docs.stripe.com/connect/migrate-to-controller-properties.md) o especificando el tipo de cuenta. #### Con propiedades predeterminadas ```curl curl -X POST https://api.stripe.com/v1/accounts \ -u "<>:" ``` #### Con tipo de cuenta ```curl curl https://api.stripe.com/v1/accounts \ -u "<>:" \ -d type=standard ``` Si ya recopilaste información para tus cuentas conectadas, puedes completar automáticamente esa información en el objeto `Account`. Puedes completar previamente cualquier información de la cuenta, incluida la información personal y de la empresa, la información de la cuenta externa, etc. Después de crear la `cuenta`, crea una [persona](https://docs.stripe.com/api/persons/create.md) que represente a la persona responsable de abrir la cuenta, con `relationship.representative` establecido en verdadero y cualquier información de la cuenta que quieras completar previamente (por ejemplo, su nombre y apellido). ```curl curl https://api.stripe.com/v1/accounts/{{ACCOUNT_ID}}/persons \ -u "<>:" \ -d first_name=Jenny \ -d last_name=Rosen \ -d "relationship[representative]=true" ``` El onboarding de Connect no solicita la información que se completó automáticamente. Sin embargo, sí le pide al titular de la cuenta que confirme la información completada automáticamente antes de aceptar el [contrato de servicio de Connect](https://docs.stripe.com/connect/service-agreement-types.md). Cuando pruebes la integración, completa automáticamente la información de la cuenta con los [datos de prueba](https://docs.stripe.com/connect/testing.md). ### Paso 2.2: Crear un enlace de cuenta (Server-side) Puedes crear un enlace de cuenta llamando a la API [Account Links](https://docs.stripe.com/api/account_links.md) con los siguientes parámetros: - `account` - `refresh_url` - `return_url` - `type` = `account_onboarding` ```curl curl https://api.stripe.com/v1/account_links \ -u "<>:" \ -d "account={{CONNECTEDACCOUNT_ID}}" \ --data-urlencode "refresh_url=https://example.com/reauth" \ --data-urlencode "return_url=https://example.com/return" \ -d type=account_onboarding ``` ### Paso 2.3: Redirigir a tu usuario a la URL del enlace de cuenta (Client-side) La respuesta a tu solicitud de [Account Links](https://docs.stripe.com/api/account_links.md) incluye un valor para la clave `url`. Redirige a este enlace para enviar al usuario al flujo. Los enlaces de cuenta son temporales y de un solo uso, ya que otorgan acceso a la información personal del usuario de la cuenta conectada. Autentica al usuario en tu aplicación antes de redirigirlo a esta URL. Si quieres completar previamente la información, debes hacerlo antes de generar el enlace de la cuenta. Después de crear el enlace para una cuenta Standard, no podrás leer ni escribir información para la cuenta. > No envíes por correo electrónico, ni por mensaje de texto ni por ningún otro medio las URL del enlace de la cuenta fuera de la aplicación de la plataforma. En lugar de eso, envíalas al titular de la cuenta autenticado dentro de tu aplicación. #### Swift ```swift import UIKit import SafariServices let BackendAPIBaseURL: String = "" // Set to the URL of your backend server class ConnectOnboardViewController: UIViewController { // ... override func viewDidLoad() { super.viewDidLoad() let connectWithStripeButton = UIButton(type: .system) connectWithStripeButton.setTitle("Connect with Stripe", for: .normal) connectWithStripeButton.addTarget(self, action: #selector(didSelectConnectWithStripe), for: .touchUpInside) view.addSubview(connectWithStripeButton) // ... } @objc func didSelectConnectWithStripe() { if let url = URL(string: BackendAPIBaseURL)?.appendingPathComponent("onboard-user") { var request = URLRequest(url: url) request.httpMethod = "POST" let task = URLSession.shared.dataTask(with: request) { (data, response, error) in guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any], let accountURLString = json["url"] as? String, let accountURL = URL(string: accountURLString) else { // handle error } let safariViewController = SFSafariViewController(url: accountURL) safariViewController.delegate = self DispatchQueue.main.async { self.present(safariViewController, animated: true, completion: nil) } } } } // ... } extension ConnectOnboardViewController: SFSafariViewControllerDelegate { func safariViewControllerDidFinish(_ controller: SFSafariViewController) { // the user may have closed the SFSafariViewController instance before a redirect // occurred. Sync with your backend to confirm the correct state } } ``` ### Paso 2.4: Gestionar el caso de un usuario que vuelve a la plataforma (Client-side) El onboarding de *Connect* (Connect is Stripe's solution for multi-party businesses, such as marketplace or software platforms, to route payments between sellers, customers, and other recipients) te exige especificar una `return_url` y una `refresh_url` para gestionar todos los casos en los que el usuario sea redirigido a tu plataforma. Es importante implementar estas direcciones correctamente para que tu usuario tenga la mejor experiencia. Puedes configurar un [enlace universal](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content) para que iOS pueda redirigir a los usuarios automáticamente a tu aplicación. #### return_url Stripe redirige al usuario a esta URL cuando dicho usuario completa el flujo de onboarding de Connect. Esto no implica que se haya recopilado toda la información ni que no haya requisitos pendientes en la cuenta. Solo significa que se entró y se salió del flujo correctamente. No se especifica ningún estado a través de esta URL. Después de redirigir al usuario a tu `return_url`, verifica el estado del parámetro `details_submitted` en su cuenta por medio de uno de los siguientes métodos: - Escuchando los *webhooks* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) `account.updated` - Llamando a la API [Accounts](https://docs.stripe.com/api/accounts.md) e inspeccionando el objeto devuelto #### refresh_url Tu usuario será redirigido a la `refresh_url` en estos casos: - Se venció el enlace (pasaron algunos minutos desde la creación del enlace) - El usuario ya visitó el enlace (actualizó la página o se desplazó de página en el navegador) - Tu plataforma ya no puede acceder a la cuenta - La cuenta ha sido rechazada La `refresh_url` debería activar un método en tu servidor para volver a llamar a la API [Account Links](https://docs.stripe.com/api/account_links.md) con los mismos parámetros y redirigir al usuario al flujo de onboarding de Connect para crear una experiencia fluida. ### Paso 2.5: Gestiona los casos de usuarios que no hayan completado el onboarding Es posible que un usuario redirigido a tu `return_url` no haya completado el proceso de onboarding. Usa el punto de conexión `/v1/accounts` para recuperar la cuenta del usuario y comprueba si hay `charges_enabled`. Si la cuenta no ha finalizado todo el proceso de onboarding, proporciona indicaciones de interfaz de usuario para que el usuario pueda continuarlo más tarde. Podrá completar la activación de su cuenta con un nuevo enlace de cuenta (generado por tu integración). Puedes verificar el estado del parámetro `details_submitted` en su cuenta para ver si se completó el proceso de onboarding. ## Habilitar métodos de pago Visualiza tu [configuración de métodos de pago](https://dashboard.stripe.com/settings/connect/payment_methods) y habilita los que quieras aceptar. Los pagos con tarjeta se habilitan de forma predeterminada, pero puedes habilitarlos y deshabilitarlos según sea necesario. ## 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. (Opcional) 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. (Opcional) [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). > Si nunca guardas tarjetas de tus clientes ni permites que vuelvan a usar tarjetas guardadas, puedes omitir el `Account` o `Customer` Object y el objeto `CustomerSession` en tu integración. 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), 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. 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 <>: \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \ -d "automatic_payment_methods[enabled]"=true \ -d application_fee_amount="123" \ ``` #### 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 <>: \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \ -d "payment_method_types[]"="bancontact" \ -d "payment_method_types[]"="card" \ -d "payment_method_types[]"="ideal" \ -d "payment_method_types[]"="klarna" \ -d "payment_method_types[]"="sepa_debit" \ -d application_fee_amount="123" \ ``` > 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. ## Integrar la hoja 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). Luego, establece `STPAPIClient.shared.stripeAccount` en el ID de cuenta conectada. #### 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 = publishableKeySTPAPIClient.shared.stripeAccount = ""{{CONNECTED_ACCOUNT_ID}}""// 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). Luego, establece `STPAPIClient.shared.stripeAccount` en el ID de cuenta conectada. #### 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 = publishableKeySTPAPIClient.shared.stripeAccount = ""{{CONNECTED_ACCOUNT_ID}}""// 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). Luego, establece `STPAPIClient.shared.stripeAccount` en el ID de cuenta conectada. ```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 = publishableKeySTPAPIClient.shared.stripeAccount = ""{{CONNECTED_ACCOUNT_ID}}""// 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 STPAPIClient.shared.stripeAccount = ""{{CONNECTED_ACCOUNT_ID}}"" // 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). Luego, establece `STPAPIClient.shared.stripeAccount` en el ID de cuenta conectada. ```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 = publishableKeySTPAPIClient.shared.stripeAccount = ""{{CONNECTED_ACCOUNT_ID}}""// 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 STPAPIClient.shared.stripeAccount = ""{{CONNECTED_ACCOUNT_ID}}"" // 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 } } } } } ``` ## Gestionar 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. | ## Probar la integración #### Tarjetas | Número de tarjeta | Escenario | Cómo hacer la prueba | | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | 4242424242424242 | El pago con tarjeta se efectúa correctamente y no requiere autenticación. | Completa el formulario de tarjeta de crédito con el número de tarjeta de crédito y la fecha de vencimiento, el CVC o el código postal. | | 4000002500003155 | El pago con tarjeta 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 el formulario de tarjeta de crédito con el número de tarjeta de crédito y la fecha de vencimiento, el CVC o el código postal. | | 4000000000009995 | La tarjeta es rechazada con un código de rechazo `insufficient_funds`. | Completa el formulario de tarjeta de crédito con el número de tarjeta de crédito y la fecha de vencimiento, el CVC o el código postal. | | 6205500000000000004 | La tarjeta UnionPay puede tener entre 13 y 19 dígitos. | Completa el formulario de tarjeta de crédito con el número de tarjeta de crédito y la fecha de vencimiento, el CVC o el código postal. | #### Redireccionamientos bancarios | Método de pago | Escenario | Cómo hacer la prueba | | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Bancontact, iDEAL | Tu cliente no pasa la autenticación en la página de redireccionamiento de un método de pago basado en redireccionamiento y con notificación inmediata. | Elige cualquier método de pago basado en redireccionamiento, completa los datos solicitados y confirma el pago. Luego, haz click en **Error en el pago de prueba** en la página de redireccionamiento. | | Pay by Bank | Tu cliente paga satisfactoriamente con un método de pago basado en redireccionamiento y con [notificación diferida](https://docs.stripe.com/payments/payment-methods.md#payment-notification). | Elige el método de pago, completa los datos solicitados y confirma el pago. Luego, haz click en **Completar el pago de prueba** en la página de redireccionamiento. | | Pay by Bank | Tu cliente no pasa la autenticación en la página de redireccionamiento de un método de pago basado en redireccionamiento y con notificación diferida. | Elige el método de pago, completa los datos solicitados y confirma el pago. Luego, haz click en **Error en el pago de prueba** en la página de redireccionamiento. | | BLIK | Los pagos BLIK generan errores de varias maneras: errores inmediatos (por ejemplo, el código venció o no es válido), errores demorados (el banco lo rechaza) o tiempos de espera (el cliente no respondió a tiempo). | Usa patrones de correo electrónico para [simular los diferentes errores.](https://docs.stripe.com/payments/blik/accept-a-payment.md#simulate-failures) | #### Débitos bancarios | Método de pago | Escenario | Cómo hacer la prueba | | ------------------- | --------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Débito directo SEPA | Tu cliente paga satisfactoriamente con débito directo SEPA. | Completa el formulario con el número de cuenta `AT321904300235473204`. El PaymentIntent confirmado pasa inicialmente al estado “en proceso” y, tres minutos más tarde, a “completado”. | | Débito directo SEPA | El estado del intento de pago de tu cliente pasa de `processing` a `requires_payment_method`. | Completa el formulario con el número de cuenta `AT861904300235473202`. | Consulta [Pruebas](https://docs.stripe.com/testing.md) para obtener información adicional para probar tu integración. ## 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 el botón de Apple Pay. 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 el escaneo de tarjetas 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") } ) ``` 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. ## Pruebas Para probar el flujo de creación de cuentas, [crea cuentas](https://docs.stripe.com/connect/testing.md#creating-accounts) y [usa OAuth](https://docs.stripe.com/connect/testing.md#using-oauth). Para probar la configuración de los **Métodos de pago** de las cuentas conectadas, inicia sesión en una de las cuentas de prueba y accede a la [configuración de los métodos de pago](https://dashboard.stripe.com/settings/payment_methods). Prueba tu flujo de compra con tus claves de prueba y una cuenta de prueba. Puedes usar nuestras [tarjetas de prueba](https://docs.stripe.com/testing.md) para probar tu flujo de pago y simular pagos con distintos resultados. # Solo Card Element > This is a Solo Card Element for when platform is ios and mobile-ui is card-element. View the full page at https://docs.stripe.com/connect/end-to-end-saas-platform?platform=ios&mobile-ui=card-element. Recopila la información de la tarjeta del cliente de manera segura con [STPPaymentCardTextField](https://stripe.dev/stripe-ios/stripe-payments-ui/Classes/STPPaymentCardTextField.html), un componente de interfaz de usuario listo para usar proporcionado por el SDK que recopila el número de tarjeta, la fecha de vencimiento, el CVC y el código postal. ![](https://d37ugbyn3rpeym.cloudfront.net/docs/mobile/ios/card-field.mp4) ## Prerrequisitos 1. [Registra tu plataforma](https://dashboard.stripe.com/connect). 1. [Verifica y agrega datos de la empresa en Dashboard](https://dashboard.stripe.com/account/onboarding). 1. [Completa el perfil de tu plataforma](https://dashboard.stripe.com/connect/settings/profile). 1. [Personaliza la configuración de tu marca](https://dashboard.stripe.com/settings/connect/stripe-dashboard/branding). Agrega el nombre, el ícono y el color de la marca de la empresa. ## Configurar Stripe [Lado del servidor] [Lado del cliente] Primero, necesitas una cuenta de Stripe. [Inscríbete ahora](https://dashboard.stripe.com/register). ### Lado del servidor Esta integración necesita 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 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 **StripePaymentsUI** 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 'StripePaymentsUI' ``` 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 StripePaymentsUI ``` #### 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/StripePaymentsUI/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 **StripePaymentsUI.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/StripePaymentsUI/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. Configura el SDK con tu [clave publicable](https://dashboard.stripe.com/test/apikeys) de Stripe al iniciar la aplicación. Esto permite que tu aplicación haga solicitudes a la API de Stripe. #### Swift ```swift import UIKitimportStripePaymentsUI @main class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {StripeAPI.defaultPublishableKey = "<>" // do any other necessary launch configuration return true } } ``` > Usa las [claves de prueba](https://docs.stripe.com/keys.md#obtain-api-keys) 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. ## Crear una cuenta conectada En esta guía se explica cómo usar código para crear una cuenta conectada. Si todavía no estás listo para la integración, puedes comenzar por crear una cuenta conectada [a través del Dashboard](https://docs.stripe.com/connect/dashboard/managing-individual-accounts.md). Cuando un usuario (vendedor o proveedor de servicios) crea un cuenta en tu plataforma, crea una [Cuenta](https://docs.stripe.com/api/accounts.md) de usuario (llamada *cuenta conectada*) para que puedas aceptar pagos y transferir fondos a su cuenta bancaria. Las cuentas conectadas representan a tu usuario en la API de Stripe y ayudan con la recopilación de los requisitos de onboarding para que Stripe pueda verificar la identidad del usuario. En el ejemplo de la plataforma para crear tiendas, la cuenta conectada representa a la empresa que configura su tienda en línea. ![](https://b.stripecdn.com/docs-statics-srv/assets/standard-ios.10c6b24cef1d683d36f2264c726beb1d.png) ### Paso 2.1: Crea una cuenta conectada y completa automáticamente la información del (lado del servidor) Usa la API `/v1/accounts` para [crear](https://docs.stripe.com/api/accounts/create.md) una cuenta conectada. Puedes crear la cuenta conectada utilizando los [parámetros predeterminados de la cuenta conectada](https://docs.stripe.com/connect/migrate-to-controller-properties.md) o especificando el tipo de cuenta. #### Con propiedades predeterminadas ```curl curl -X POST https://api.stripe.com/v1/accounts \ -u "<>:" ``` #### Con tipo de cuenta ```curl curl https://api.stripe.com/v1/accounts \ -u "<>:" \ -d type=standard ``` Si ya recopilaste información para tus cuentas conectadas, puedes completar automáticamente esa información en el objeto `Account`. Puedes completar previamente cualquier información de la cuenta, incluida la información personal y de la empresa, la información de la cuenta externa, etc. Después de crear la `cuenta`, crea una [persona](https://docs.stripe.com/api/persons/create.md) que represente a la persona responsable de abrir la cuenta, con `relationship.representative` establecido en verdadero y cualquier información de la cuenta que quieras completar previamente (por ejemplo, su nombre y apellido). ```curl curl https://api.stripe.com/v1/accounts/{{ACCOUNT_ID}}/persons \ -u "<>:" \ -d first_name=Jenny \ -d last_name=Rosen \ -d "relationship[representative]=true" ``` El onboarding de Connect no solicita la información que se completó automáticamente. Sin embargo, sí le pide al titular de la cuenta que confirme la información completada automáticamente antes de aceptar el [contrato de servicio de Connect](https://docs.stripe.com/connect/service-agreement-types.md). Cuando pruebes la integración, completa automáticamente la información de la cuenta con los [datos de prueba](https://docs.stripe.com/connect/testing.md). ### Paso 2.2: Crear un enlace de cuenta (Server-side) Puedes crear un enlace de cuenta llamando a la API [Account Links](https://docs.stripe.com/api/account_links.md) con los siguientes parámetros: - `account` - `refresh_url` - `return_url` - `type` = `account_onboarding` ```curl curl https://api.stripe.com/v1/account_links \ -u "<>:" \ -d "account={{CONNECTEDACCOUNT_ID}}" \ --data-urlencode "refresh_url=https://example.com/reauth" \ --data-urlencode "return_url=https://example.com/return" \ -d type=account_onboarding ``` ### Paso 2.3: Redirigir a tu usuario a la URL del enlace de cuenta (Client-side) La respuesta a tu solicitud de [enlaces de cuenta](https://docs.stripe.com/api/account_links.md) incluye un valor para la clave `url`. Redirige a este enlace para enviar al usuario al flujo. Las direcciones URL de la API [enlaces de cuenta](https://docs.stripe.com/api/account_links.md) son temporales y solo se pueden usar una vez porque otorgan acceso a los datos personales del titular de la cuenta. Autentica al usuario en tu solicitud antes de redirigirlo a esta URL. Si quieres completar automáticamente la información, debes hacerlo antes de generar el enlace de cuenta. Después de crear el enlace de cuenta para una cuenta Standard, no podrás leer ni escribir información para la cuenta. > No envíes por correo electrónico, ni por mensaje de texto ni por ningún otro medio las URL del enlace de la cuenta fuera de la aplicación de la plataforma. En lugar de eso, envíalas al titular de la cuenta autenticado dentro de tu aplicación. #### Swift ```swift import UIKit import SafariServices let BackendAPIBaseURL: String = "" // Set to the URL of your backend server class ConnectOnboardViewController: UIViewController { // ... override func viewDidLoad() { super.viewDidLoad() let connectWithStripeButton = UIButton(type: .system) connectWithStripeButton.setTitle("Connect with Stripe", for: .normal) connectWithStripeButton.addTarget(self, action: #selector(didSelectConnectWithStripe), for: .touchUpInside) view.addSubview(connectWithStripeButton) // ... } @objc func didSelectConnectWithStripe() { if let url = URL(string: BackendAPIBaseURL)?.appendingPathComponent("onboard-user") { var request = URLRequest(url: url) request.httpMethod = "POST" let task = URLSession.shared.dataTask(with: request) { (data, response, error) in guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any], let accountURLString = json["url"] as? String, let accountURL = URL(string: accountURLString) else { // handle error } let safariViewController = SFSafariViewController(url: accountURL) safariViewController.delegate = self DispatchQueue.main.async { self.present(safariViewController, animated: true, completion: nil) } } } } // ... } extension ConnectOnboardViewController: SFSafariViewControllerDelegate { func safariViewControllerDidFinish(_ controller: SFSafariViewController) { // the user may have closed the SFSafariViewController instance before a redirect // occurred. Sync with your backend to confirm the correct state } } ``` ### Paso 2.4: Gestionar el caso de un usuario que vuelve a la plataforma (Client-side) El onboarding de *Connect* (Connect is Stripe's solution for multi-party businesses, such as marketplace or software platforms, to route payments between sellers, customers, and other recipients) te exige especificar una `return_url` y una `refresh_url` para gestionar todos los casos en los que el usuario será redirigido a tu plataforma. Es importante implementar estas direcciones correctamente para que tu usuario tenga la mejor experiencia. Puedes configurar un [enlace universal](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content) para que iOS pueda redirigir a los usuarios automáticamente a tu aplicación. #### return_url Stripe genera el redireccionamiento a esta URL cuando el usuario completa el flujo de onboarding de Connect. Esto no implica que se haya recopilado toda la información o que no haya requisitos pendientes en la cuenta. Solo significa que se ingresó y se salió del flujo correctamente. No se especifica ningún estado a través de esta URL. Después de redirigir al usuario a tu `return_url`, verifica el estado del parámetro `details_submitted` en su cuenta por medio de uno de los siguientes métodos: - Escuchando los *webhooks* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) `account.updated` - Llamando a la API [Accounts](https://docs.stripe.com/api/accounts.md) e inspeccionando el objeto devuelto #### refresh_url Tu usuario será redirigido a la `refresh_url` en los siguientes casos: - Se venció el enlace (pasaron algunos minutos desde la creación del enlace) - Ya se visitó el enlace (el usuario actualizó la página o se desplazó de página en el navegador) - El enlace se compartió en una aplicación de terceros, como un cliente de mensajería que intenta acceder a la URL para obtener una vista previa. Muchos clientes visitan automáticamente enlaces, lo que hace que estos caduquen. - Tu plataforma ya no puede acceder a la cuenta - La cuenta ha sido rechazada La `refresh_url` debería activar un método en tu servidor para volver a llamar a la API [Account Links](https://docs.stripe.com/api/account_links.md) con los mismos parámetros y redirigir al usuario al flujo de onboarding de Connect para crear una experiencia fluida. ### Paso 2.5: Gestionar los casos de usuarios que no han completado el onboarding Es posible que un usuario redirigido a tu `return_url` no haya completado el proceso de onboarding. Usa el punto de conexión `/v1/accounts` para recuperar la cuenta del usuario y comprueba si hay `charges_enabled`. Si la cuenta no ha finalizado todo el proceso de onboarding, proporciona indicaciones de interfaz de usuario para que el usuario pueda continuarlo más tarde. Podrá completar la activación de su cuenta con un nuevo enlace de cuenta (generado por tu integración). Puedes verificar el estado del parámetro `details_submitted` en su cuenta para ver si se completó el proceso de onboarding. ## Aceptar un pago ### Paso 3.1: Crear la página de finalización de compra (Client-side) Recopila la información de la tarjeta del cliente de manera segura con [STPPaymentCardTextField](https://stripe.dev/stripe-ios/stripe-payments-ui/Classes/STPPaymentCardTextField.html), un componente de interfaz de usuario listo para usar proporcionado por el SDK que recopila el número de tarjeta, la fecha de vencimiento, el CVC y el código postal. ![](https://d37ugbyn3rpeym.cloudfront.net/docs/mobile/ios/card-field.mp4) Crea una instancia del componente de tarjeta y un botón **Pagar** con el siguiente código: #### Swift ```swift import UIKit import StripePaymentsUI class CheckoutViewController: UIViewController { lazy var cardTextField: STPPaymentCardTextField = { let cardTextField = STPPaymentCardTextField() return cardTextField }() lazy var payButton: UIButton = { let button = UIButton(type: .custom) button.layer.cornerRadius = 5 button.backgroundColor = .systemBlue button.titleLabel?.font = UIFont.systemFont(ofSize: 22) button.setTitle("Pay", for: .normal) button.addTarget(self, action: #selector(pay), for: .touchUpInside) return button }() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white let stackView = UIStackView(arrangedSubviews: [cardTextField, payButton]) stackView.axis = .vertical stackView.spacing = 20 stackView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(stackView) NSLayoutConstraint.activate([ stackView.leftAnchor.constraint(equalToSystemSpacingAfter: view.leftAnchor, multiplier: 2), view.rightAnchor.constraint(equalToSystemSpacingAfter: stackView.rightAnchor, multiplier: 2), stackView.topAnchor.constraint(equalToSystemSpacingBelow: view.topAnchor, multiplier: 2), ]) } @objc func pay() { // ... } } ``` Ejecuta tu aplicación y asegúrate de que en la página de finalización de compra, aparezca el componente de tarjeta y el botón de pago. ### Paso 3.2: Crear un PaymentIntent (Server-side) (Client-side) Stripe usa un objeto [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) para representar tu intención de cobrarle a un cliente y hace el seguimiento de los intentos de cobro y de los cambios en el estado del pago a lo largo del proceso. ### Lado del servidor Del lado del servidor, crea un punto de conexión que genere un PaymentIntent con un [importe](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-amount) y una [moneda](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-currency). Decide cuánto cobrar siempre del lado del servidor, un entorno de confianza, y no del lado del cliente. Esto impide que clientes maliciosos puedan elegir sus propios precios. #### curl ```bash curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -d amount=1000 \ -d currency="usd" \ -d "automatic_payment_methods[enabled]"=true \ -d application_fee_amount="123" \ -H "Stripe-Account: {{CONNECTED_STRIPE_ACCOUNT_ID}}" ``` En nuestro ejemplo de creador de tiendas, nuestro objetivo es crear un negocio en el que los clientes paguen directamente a las empresas. Para configurar este negocio, haz lo siguiente: - Indica que una compra de la empresa es un cargo Direct con el encabezado `Stripe-Account`. - Especifica qué parte de la compra de la empresa va a la plataforma con `application_fee_amount`. Cuando se hace una venta, Stripe transfiere el `application_fee_amount` de la cuenta conectada a la plataforma y deduce la comisión de Stripe de la parte de la cuenta conectada. A continuación, un ejemplo de este flujo de fondos: ![](https://b.stripecdn.com/docs-statics-srv/assets/direct_charges.a2a8b68037ac95fe22140d6dde9740d3.svg) En lugar de pasar el objeto PaymentIntent completo a tu aplicación, solo devuelve el *secreto de cliente* (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)). El secreto de cliente del PaymentIntent es una clave única que te permite confirmar el pago y actualizar los datos de la tarjeta del cliente sin manipular datos confidenciales, como el importe del pago. ### Lado del cliente Establece el ID de la cuenta conectada como argumento en la aplicación del cliente en las bibliotecas del lado del cliente. #### Swift ```swift import UIKit import StripePayments @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { StripeAPI.defaultPublishableKey = "<>" STPAPIClient.shared.stripeAccount = ""{{CONNECTED_ACCOUNT_ID}}"" return true } } ``` Del lado del cliente, solicita un PaymentIntent desde tu servidor y almacena el *secreto de cliente* (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)). #### Swift ```swift class CheckoutViewController: UIViewController { var paymentIntentClientSecret: String? // ...continued from previous step override func viewDidLoad() { // ...continued from previous step startCheckout() } func startCheckout() { // Request a PaymentIntent from your server and store its client secret // Click View full sample to see a complete implementation } } ``` ### Paso 3.3: Enviar el pago a Stripe (Client-side) Cuando el cliente toca el botón **Pagar**, *confirma* (Confirming a PaymentIntent indicates that the customer intends to pay with the current or provided payment method. Upon confirmation, the PaymentIntent attempts to initiate a payment) el `PaymentIntent` para completar el pago. Primero, ensambla un objeto [STPPaymentIntentParams](https://stripe.dev/stripe-ios/stripe-payments/Classes/STPPaymentIntentParams.html) con lo siguiente: 1. Los datos del método de pago del campo de texto de la tarjeta 1. El secreto de cliente del `PaymentIntent` de tu servidor En lugar de enviarle al cliente el objeto PaymentIntent completo, utiliza el *secreto de cliente* (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)). Esta clave es diferente de las claves de API utilizadas para autenticar las solicitudes de la API de Stripe. El secreto de cliente es una cadena que permite que la aplicación acceda a campos importantes del PaymentIntent (por ejemplo, `status`), pero que a su vez oculta los campos confidenciales (por ejemplo, `customer`). Administra el secreto de cliente con cuidado porque sirve para completar el cargo. No lo registres, no lo insertes en direcciones URL ni lo expongas a nadie excepto al cliente. A continuación, completa el pago mediante una llamada al método [STPPaymentHandler confirmPayment](https://stripe.dev/stripe-ios/stripe-payments/Classes/STPPaymentHandler.html#/c:@M@StripePayments@objc\(cs\)STPPaymentHandler\(im\)confirmPayment:withAuthenticationContext:completion:). #### Swift ```swift class CheckoutViewController: UIViewController { // ... @objc func pay() { guard let paymentIntentClientSecret = paymentIntentClientSecret else { return } // Collect card details let paymentIntentParams = STPPaymentIntentParams(clientSecret: paymentIntentClientSecret) paymentIntentParams.paymentMethodParams = cardTextField.paymentMethodParams // Submit the payment let paymentHandler = STPPaymentHandler.shared() paymentHandler.confirmPayment(paymentIntentParams, with: self) { (status, paymentIntent, error) in switch (status) { case .failed: self.displayAlert(title: "Payment failed", message: error?.localizedDescription ?? "") break case .canceled: self.displayAlert(title: "Payment canceled", message: error?.localizedDescription ?? "") break case .succeeded: self.displayAlert(title: "Payment succeeded", message: paymentIntent?.description ?? "", restartDemo: true) break @unknown default: fatalError() break } } } } extension CheckoutViewController: STPAuthenticationContext { func authenticationPresentingViewController() -> UIViewController { return self } } ``` Puedes [guardar los datos de la tarjeta de pago de un cliente](https://docs.stripe.com/payments/payment-intents.md#future-usage) en la confirmación del pago especificando `setupFutureUsage` y un `customer` en el `PaymentIntent`. También puedes especificar estos parámetros al crear el `PaymentIntent` en tu servidor. Si especificas el valor `setupFutureUsage` adecuado para tu aplicación, quizá el cliente deba completar otros pasos de autenticación, pero esto reduce la probabilidad de que los bancos rechacen futuros pagos. [Aprende cómo optimizar tarjetas para futuros pagos](https://docs.stripe.com/payments/payment-intents.md#future-usage) y determina el valor que usarás para tu aplicación. | Cómo intentas usar la tarjeta | Valor de enumeración `setup_future_usage` | | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | | Pagos *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) solamente | `on_session` | | 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) solamente | `off_session` | | Pagos durante la sesión y fuera de la sesión | `off_session` | Puedes usar una tarjeta configurada para pagos durante la sesión para efectuar pagos fuera de la sesión, pero existe una mayor probabilidad de que el banco rechace el pago fuera de la sesión y solicite la autenticación del titular de tarjeta. Si una normativa como la [autenticación reforzada de clientes](https://docs.stripe.com/strong-customer-authentication.md) requiere autenticación, `STPPaymentHandler` presenta controladores de vista con el [STPAuthenticationContext](https://stripe.dev/stripe-ios/stripe-payments/Protocols/STPAuthenticationContext.html) especificado y guía al cliente a lo largo del proceso. [Aprende a admitir la autenticación con 3D Secure en iOS](https://docs.stripe.com/payments/3d-secure.md?platform=ios). Si el pago se efectúa correctamente, se llama al controlador de finalización con el estado `.succeeded`. Si el pago falla, el estado es `.failed`. Puedes mostrar el error `error.localizedDescription` al usuario. También puedes comprobar el estado de un `PaymentIntent` en el [Dashboard](https://dashboard.stripe.com/test/payments) o inspeccionando la propiedad `status` en el objeto. ### Paso 3.4: Probar la integración (Client-side) ​​Dispones de varias tarjetas de prueba que puedes usar en un entorno de prueba para verificar que la integración esté lista. Úsalas con cualquier CVC y una fecha de vencimiento futura. | Número | Descripción | | ---------------- | -------------------------------------------------------------------------------------------------------------- | | 4242424242424242 | La transacción se realiza con éxito y se procesa el pago de inmediato. | | 4000002500003155 | Exige autenticación. Stripe activa un cuadro de diálogo que le solicita al cliente completar la autenticación. | | 4000000000009995 | Siempre da error con un código de rechazo `insufficient_funds`. | Para ver la lista completa de tarjetas de prueba, consulta nuestra guía sobre [pruebas](https://docs.stripe.com/testing.md). ### Paso 3.5: Completar el pedido (Server-side) Una vez efectuado el pago, debes gestionar todo lo necesario para *completar el pedido* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected). Por ejemplo, un creador de tiendas debe avisarle al negocio que envíe el artículo comprado al cliente. Configura un punto de conexión de *webhooks* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) [en el Dashboard](https://dashboard.stripe.com/account/webhooks) (para eventos *desde tus aplicaciones de Connect*). ![](https://b.stripecdn.com/docs-statics-srv/assets/connect_webhooks.4de92f78dcd94b36838010c85c8a051f.png) Crea un punto de conexión HTTP en tu servidor para controlar los pagos completados y así permitir que tus usuarios (las cuentas conectadas) puedan completar los pedidos. #### Ruby ```ruby # Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. client = Stripe::StripeClient.new('<>') # If you are testing your webhook locally with the Stripe CLI you # can find the endpoint's secret by running `stripe listen` # Otherwise, find your endpoint's secret in your webhook settings in # the Developer Dashboard endpoint_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks#verify-events for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, endpoint_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'payment_intent.succeeded' payment_intent = event['data']['object'] connected_account_id = event['account'] handle_successful_payment_intent(connected_account_id, payment_intent) end status 200 end def handle_successful_payment_intent(connected_account_id, payment_intent) # Fulfill the purchase puts 'Connected account ID: ' + connected_account_id puts payment_intent.to_s end ``` Obtén más información en nuestra [guía de gestión logística para pagos](https://docs.stripe.com/webhooks/handling-payment-events.md). ### Cómo probar webhooks a nivel local Usa la CLI de Stripe para hacer pruebas de webhooks localmente. 1. En primer lugar, [instala la CLI de Stripe](https://docs.stripe.com/stripe-cli/install.md) en tu máquina si aún no lo haz hecho. 1. Para iniciar sesión, ejecuta `stripe login` en la línea de comandos y sigue las instrucciones. 1. Por último, ejecuta `stripe listen --forward-connect-to localhost:{PORT}/webhook` en una ventana de la terminal para permitir que el host local reciba un evento simulado en tu cuenta conectada, y ejecuta `stripe trigger --stripe-account={{CONNECTED_STRIPE_ACCOUNT_ID}} payment_intent.succeeded` (o activa cualquier otro [evento aceptado](https://github.com/stripe/stripe-cli/wiki/trigger-command#supported-events)) en otra ventana. ## Probando Para probar el flujo de creación de cuentas, [crea cuentas](https://docs.stripe.com/connect/testing.md#creating-accounts) y [usa OAuth](https://docs.stripe.com/connect/testing.md#using-oauth). Para probar la configuración de los **Métodos de pago** de las cuentas conectadas, inicia sesión en una de las cuentas de prueba y accede a la [configuración de los métodos de pago](https://dashboard.stripe.com/settings/payment_methods). Prueba tu flujo de compra con tus claves de prueba y una cuenta de prueba. Puedes usar nuestras [tarjetas de prueba](https://docs.stripe.com/testing.md) para probar tu flujo de pago y simular pagos con distintos resultados. # Hoja de pago > This is a Hoja de pago for when platform is android and mobile-ui is payment-sheet. View the full page at https://docs.stripe.com/connect/end-to-end-saas-platform?platform=android&mobile-ui=payment-sheet. ![](https://b.stripecdn.com/docs-statics-srv/assets/android-overview.471eaf89a760f5b6a757fd96b6bb9b60.png) Integra la interfaz de usuario de pago prediseñada de Stripe a la confirmación de compra de tu aplicación Android con la clase [PaymentSheet](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/index.html). > #### Soporte de API Accounts v2 > > Payment Sheet no ofrece soporte para *cuentas configuradas por el cliente*. Solo admite objetos `Customer`. ## Prerrequisitos 1. [Registra tu plataforma](https://dashboard.stripe.com/connect). 1. [Verifica y agrega datos de la empresa en Dashboard](https://dashboard.stripe.com/account/onboarding). 1. [Completa el perfil de tu plataforma](https://dashboard.stripe.com/connect/settings/profile). 1. [Personaliza la configuración de tu marca](https://dashboard.stripe.com/settings/connect/stripe-dashboard/branding). Agrega el nombre, el ícono y el color de la marca de la empresa. ## Configurar Stripe [Lado del servidor] [Lado del cliente] Primero, necesitas una cuenta de Stripe. [Inscríbete ahora](https://dashboard.stripe.com/register). ### Lado del servidor Esta integración necesita 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.8.0") // Include the financial connections SDK to support US bank account as a payment method implementation("com.stripe:financial-connections:23.8.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). Configura el SDK con tu [clave publicable](https://dashboard.stripe.com/apikeys) de Stripe para que pueda hacer solicitudes a la API de Stripe, así como en tu subclase `Application`: #### Kotlin ```kotlin import com.stripe.android.PaymentConfiguration class MyApp : Application() { override fun onCreate() { super.onCreate() PaymentConfiguration.init( applicationContext, "<>" ) } } ``` > Usa las [claves de prueba](https://docs.stripe.com/keys.md#obtain-api-keys) 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. ## Crear una cuenta conectada Cuando un usuario (vendedor o proveedor de servicios) crea un cuenta en tu plataforma, crea una [Cuenta](https://docs.stripe.com/api/accounts.md) de usuario (llamada *cuenta conectada*) para que puedas aceptar pagos y transferir fondos a su cuenta bancaria. Las cuentas conectadas representan a tu usuario en la API de Stripe y ayudan con la recopilación de los requisitos de onboarding para que Stripe pueda verificar la identidad del usuario. En el ejemplo de la plataforma para crear tiendas, la cuenta conectada representa a la empresa que configura su tienda en línea. ![Flujo de creación de cuenta](https://b.stripecdn.com/docs-statics-srv/assets/standard-android.04900ae101e927a74a6f2b0afb53bf23.png) ### Paso 2.1: Crea una cuenta conectada y completa automáticamente la información del (lado del servidor) Usa la API `/v1/accounts` para [crear](https://docs.stripe.com/api/accounts/create.md) una cuenta conectada. Puedes crear la cuenta conectada utilizando los [parámetros predeterminados de la cuenta conectada](https://docs.stripe.com/connect/migrate-to-controller-properties.md) o especificando el tipo de cuenta. #### Con propiedades predeterminadas ```curl curl -X POST https://api.stripe.com/v1/accounts \ -u "<>:" ``` #### Con tipo de cuenta ```curl curl https://api.stripe.com/v1/accounts \ -u "<>:" \ -d type=standard ``` Si ya recopilaste información para tus cuentas conectadas, puedes completar automáticamente esa información en el objeto `Account`. Puedes completar previamente cualquier información de la cuenta, incluida la información personal y de la empresa, la información de la cuenta externa, etc. Después de crear la `cuenta`, crea una [persona](https://docs.stripe.com/api/persons/create.md) que represente a la persona responsable de abrir la cuenta, con `relationship.representative` establecido en verdadero y cualquier información de la cuenta que quieras completar previamente (por ejemplo, su nombre y apellido). ```curl curl https://api.stripe.com/v1/accounts/{{ACCOUNT_ID}}/persons \ -u "<>:" \ -d first_name=Jenny \ -d last_name=Rosen \ -d "relationship[representative]=true" ``` El onboarding de Connect no solicita la información que se completó automáticamente. Sin embargo, sí le pide al titular de la cuenta que confirme la información completada automáticamente antes de aceptar el [contrato de servicio de Connect](https://docs.stripe.com/connect/service-agreement-types.md). Cuando pruebes la integración, completa automáticamente la información de la cuenta con los [datos de prueba](https://docs.stripe.com/connect/testing.md). ### Paso 2.2: Crear un enlace de cuenta (Server-side) Puedes crear un enlace de cuenta llamando a la API [Account Links](https://docs.stripe.com/api/account_links.md) con los siguientes parámetros: - `account` - `refresh_url` - `return_url` - `type` = `account_onboarding` ```curl curl https://api.stripe.com/v1/account_links \ -u "<>:" \ -d "account={{CONNECTEDACCOUNT_ID}}" \ --data-urlencode "refresh_url=https://example.com/reauth" \ --data-urlencode "return_url=https://example.com/return" \ -d type=account_onboarding ``` ### Paso 2.3: Redirigir a tu usuario a la URL del enlace de cuenta (Client-side) La respuesta a tu solicitud de [Account Links](https://docs.stripe.com/api/account_links.md) incluye un valor para la clave `url`. Redirige a este enlace para enviar al usuario al flujo. Los enlaces de cuenta son temporales y de un solo uso, ya que otorgan acceso a los datos personales del usuario de la cuenta conectada. Autentica al usuario en tu aplicación antes de redirigirlo a esta URL. Si quieres completar previamente la información, debes hacerlo antes de generar el enlace de la cuenta. Después de crear el enlace para una cuenta Standard, no podrás leer ni escribir información para la cuenta. > No envíes por correo electrónico, ni por mensaje de texto ni por ningún otro medio las URL del enlace de la cuenta fuera de la aplicación de la plataforma. En lugar de eso, envíalas al titular de la cuenta autenticado dentro de tu aplicación. ```xml