# Guía de Integración de Biometric Pix Con el Biometric Pix de Belvo, la recolección de pagos de los usuarios se vuelve sencilla, eliminando la necesidad de que los usuarios naveguen a su institución financiera para aprobar cada solicitud de pago individual. En esta guía, te llevaremos a través de cada paso, desde el registro del dispositivo hasta la iniciación exitosa de una solicitud de pago. Requisitos previos Por favor, asegúrate de haber completado todos los pasos en nuestro artículo dedicado a los requisitos previos antes de continuar con esta guía. ¡Soportamos el Modo Oscuro! 🤩 Nuestro hosted widget de Biometric Pix no solo soporta el Modo Oscuro, sino también personalización adicional de colores. Para más detalles, consulta nuestro artículo dedicado a Branding y Personalización (Biometric Pix Widget) (*Próximamente*). ## Flujo General En el diagrama a continuación, puedes ver el flujo general de inscripción y pago: 1. Tu usuario selecciona pagar con Biometric Pix. 2. Generas un token de acceso (con los detalles requeridos para la inscripción y el pago) y lo añades a la URL del widget. 3. Rediriges a tu usuario a la URL del widget. 4. Tu usuario pasa por el proceso de inscripción y pago dentro del widget. 1. Recibirás eventos de webhook detallando el estado de la inscripción, pago y cargo. 5. Tu usuario es redirigido de vuelta a tu aplicación. 6. Recibes un webhook de transacción confirmando que el pago fue procesado. ¡Y eso es todo! ¡El proceso completo de inscripción y pago solo requiere **una** llamada POST a la API de Belvo! El resto es manejado por el Biometric Pix Widget. ## Generar un `access_token` Recomendamos siempre enviar la información de inscripción y pago Para facilitar tu flujo de trabajo, recomendamos que siempre envíes los objetos `enrollment` y `payment_intent`. Esto permitirá que el widget maneje todo el flujo por ti (nuevas inscripciones, inscripciones existentes y pagos). El token de acceso solo es válido por 30 minutos. Para generar un token de acceso para el widget Biometric Pix que realizará tanto la inscripción del dispositivo como el pago, necesitarás hacer una llamada POST a `/api/payments/br/token` con el siguiente payload: ```json { "use_cases": ["ENROLLMENT", "PAYMENT_INTENT"], "widget": { "enrollment": { "type": "open_finance_biometric_pix", "external_id": "recommended_uuid", "details": { "name": "optional_name_for_enrollment", "customer": { "identifier": "user_CPF", "name": "Gustavo Veloso", "external_id": "recommended_uuid" } } }, "payment_intent": { "amount": "amount_as_string", "external_id": "recommended_uuid", "description": "internal_description", "statement_description": "description_to_display", "allowed_payment_method_types": ["open_finance_biometric_pix"], "payment_method_details": { "open_finance_biometric_pix": { "beneficiary_bank_account": "registered_bank_account_belvo_id" } } }, "callback_urls": { "success": "url_to_redirect_user_after_success", "exit": "url_to_redirect_user_after_exit_or_error" }, "top_tier_institutions": [ "nubank_retail", "picpay_retail", "mercadopago_retail", "itau_retail"], "branding": {}, // Consulta nuestro artículo dedicado a la marca y personalización "theme": [] // Consulta nuestro artículo dedicado a la marca y personalización } } ``` ### `use_cases` ```json Parámetro de Casos de Uso { "use_cases": ["ENROLLMENT", "PAYMENT_INTENT"], // [!code highlight] "widget": { } } ``` En el parámetro use_cases, necesitas proporcionar el propósito del widget. Puedes elegir lo siguiente: - `ENROLLMENT`: Usa esta opción si deseas inscribir el dispositivo de tu usuario en la red de Biometric Pix o listar las inscripciones previas de tus usuarios. - `PAYMENT_INTENT`: Usa esta opción si deseas crear un pago para tu usuario utilizando Biometric Pix. Si pasas ambos casos de uso (recomendado), el widget primero inscribirá al usuario y luego guiará a tu usuario a través de la solicitud de pago también. ### `enrollment` El objeto de enrollment contiene información clave que se requiere para inscribir el dispositivo del usuario con su institución. ```json Enrollment Object { "use_cases": ["ENROLLMENT", "PAYMENT_INTENT"], "widget": { "enrollment": { "type": "open_finance_biometric_pix", "external_id": "recommended_uuid", "details": { "name": "optional_name_for_enrollment", "customer": { "identifier": "user_CPF", "name": "Gustavo Veloso", "external_id": "recommended_uuid" } } }, } } ``` | Parámetro | Requerido | Descripción | | --- | --- | --- | | `type` | si | El tipo de enrollment. Para los pagos Biometric Pix de 🇧🇷 Brasil, esto debe establecerse en `open_finance_biometric_pix`. | | `external_id` | altamente recomendado | Un identificador único adicional para el recurso con fines internos. Recomendamos usar este campo para almacenar su propio identificador único para cada recurso (cliente, cuenta bancaria, intención de pago o enrollment). Esto puede ser útil para rastrear el recurso en su sistema y para fines de depuración. | | `details.name` | opcional | Use el parámetro name para proporcionar un nombre opcional, legible por humanos, para el enrollment. | | `details.customer` | si | En el objeto customer, necesita proporcionar:- El CPF de su usuario en el parámetro `identifier` (requerido). - El `name` de su usuario (opcional, pero altamente recomendado). - Un `external_id` único adicional con fines internos, útil para rastrear el recurso en su sistema y para fines de depuración (opcional, pero altamente recomendado). | ### `payment_intent` El objeto `payment_intent` contiene toda la información requerida para realizar el pago. ```json Payment Intent Object { "use_cases": ["ENROLLMENT", "PAYMENT_INTENT"], "widget": { "enrollment": { "type": "open_finance_biometric_pix", "external_id": "recommended_uuid", "details": { "name": "optional_name_for_enrollment", "customer": { "identifier": "user_CPF", "name": "Gustavo Veloso", "external_id": "recommended_uuid" } } }, "payment_intent": { "amount": "amount_as_string", "external_id": "recommended_uuid", "description": "internal_description", "statement_description": "description_to_display", "allowed_payment_method_types": ["open_finance_biometric_pix"], "payment_method_details": { "open_finance_biometric_pix": { "beneficiary_bank_account": "registered_bank_account_belvo_id" } } }, } } ``` | Parámetro | Requerido | Descripción | | --- | --- | --- | | `amount` | si | En el parámetro `amount`, necesitas proporcionar el monto del pago como una cadena. | | `external_id` | altamente recomendado | Un identificador único adicional para el recurso con fines internos. Recomendamos usar este campo para almacenar tu propio identificador único para cada recurso (cliente, cuenta bancaria, intención de pago o inscripción). Esto puede ser útil para rastrear el recurso en tu sistema y para propósitos de depuración. | | `description` | si | En el parámetro `description`, necesitas proporcionar una descripción del pago para tus propósitos internos. | | `statement_description` | altamente recomendado | En el parámetro opcional `statement_description`, necesitas proporcionar una descripción que aparecerá en el estado de cuenta del cliente (altamente recomendado). Si no utilizas el parámetro `statement_description`, el valor de `description` se usará como la descripción del estado de cuenta. | | `allowed_payment_method_types` | si | El parámetro `allowed_payment_method_types` indica qué método de pago debe usarse. Para pagos Biometric Pix en Brasil, esto debe establecerse en `["open_finance_biometric_pix"]`. | | `payment_method_details` | si | En el objeto `payment_method_details`, proporcionas información adicional requerida para procesar un pago en la red de Open Finance. Específicamente, proporcionarás la `beneficiary_bank_account` en el objeto `open_finance_biometric_pix`.- En el parámetro requerido `beneficiary_bank_account`, necesitas proporcionar el ID de la cuenta bancaria que recibirá los fondos del pago. | ### `callback_urls` En el objeto `callback_urls` (requerido), debes agregar enlaces a donde tu usuario debe ser redirigido. En caso de un error durante la inscripción o el pago, el usuario será redirigido a la URL de `exit`. Si la inscripción o el pago son exitosos, el usuario será redirigido a la URL de `success`. ```json Callback URLs Object { "use_cases": ["ENROLLMENT", "PAYMENT_INTENT"], "widget": { "enrollment": { "type": "open_finance_biometric_pix", "external_id": "recommended_uuid", "details": { "name": "optional_name_for_enrollment", "customer": { "identifier": "user_CPF", "name": "Gustavo Veloso", "external_id": "recommended_uuid" } } }, "payment_intent": { "amount": "amount_as_string", "external_id": "recommended_uuid", "description": "internal_description", "statement_description": "description_to_display", "allowed_payment_method_types": ["open_finance_biometric_pix"], "payment_method_details": { "open_finance_biometric_pix": { "beneficiary_bank_account": "registered_bank_account_belvo_id" } } }, "callback_urls": { "success": "url_to_redirect_user_after_success", "exit": "url_to_redirect_user_after_exit_or_error" }, "top_tier_institutions": [ "nubank_retail", "picpay_retail", "mercadopago_retail", "itau_retail"], "branding": { "color_scheme": "LIGHT", "company_name": "ACME" }, "theme": [] // See our dedicated branding and customization article } } ``` | Parámetro | Requerido | Descripción | | --- | --- | --- | | `success` | si | La URL a la que tu usuario es redirigido cuando completa exitosamente la inscripción o el pago. | | `exit` | si | La URL a la que tu usuario es redirigido cuando sale del proceso del widget o encuentra un error. La `exit_url` se utiliza en los siguientes casos específicos: **Salidas iniciadas por el usuario:** - El usuario cierra o sale manualmente del widget antes de completar el proceso de inscripción o pago **Condiciones de error:** - Un error `token_not_valid` es devuelto por la API de Belvo (token de acceso expirado o inválido) - El widget se abre en un dispositivo que no soporta la tecnología WebAuthn Cuando se redirige a la URL de salida debido a un error, se adjuntarán parámetros de consulta para proporcionar detalles del error. A continuación se muestra un ejemplo de un error `token_not_valid`: ``` Example Error Callback Structure https:///?error=token_not_valid&error_description=Authorization+header+is+missing+or+invalid. ``` | Error de Token No Válido en el Widget En el caso de un error de token no válido, tu usuario verá el siguiente mensaje en el widget (en portugués): "Sessão expirada: Sua sessão expirou, para realizar a conexão de conta você precisará iniciar novamente o processo." ### `top_tier_institutions` ```json Top Tier Institutions Parameter { "use_cases": ["ENROLLMENT", "PAYMENT_INTENT"], "widget": { // Otros parámetros... "top_tier_institutions": [ "nubank_retail", "picpay_retail", "mercadopago_retail", "itau_retail"] } } ``` En el parámetro `top_tier_institutions`, puedes proporcionar una lista de instituciones que se mostrarán inicialmente en el widget (los usuarios aún podrán buscar otras instituciones). Puedes seleccionar entre 1 a 5 instituciones de la lista disponible. Las instituciones se mostrarán en el orden en que las proporciones en el array. Si no pasas este parámetro, el widget mostrará todas las instituciones disponibles. Para una lista de instituciones disponibles, por favor consulta el parámetro top_tier_institutions en nuestra Referencia de API. ### `branding` y `theme` ```json Parámetros de Branding y Tema { "use_cases": ["ENROLLMENT", "PAYMENT_INTENT"], "widget": { "enrollment": { "type": "open_finance_biometric_pix", "external_id": "recommended_uuid", "details": { "name": "optional_name_for_enrollment", "customer": { "identifier": "user_CPF", "name": "Gustavo Veloso", "external_id": "recommended_uuid" } } }, "payment_intent": { "amount": "amount_as_string", "external_id": "recommended_uuid", "description": "internal_description", "statement_description": "description_to_display", "allowed_payment_method_types": ["open_finance_biometric_pix"], "payment_method_details": { "open_finance_biometric_pix": { "beneficiary_bank_account": "registered_bank_account_belvo_id" } } }, "callback_urls": { "success": "url_to_redirect_user_after_success", "exit": "url_to_redirect_user_after_exit_or_error" }, "top_tier_institutions": [ "nubank_retail", "picpay_retail", "mercadopago_retail", "itau_retail"], "branding": { "color_scheme": "LIGHT", "company_name": "ACME" }, // Consulta nuestro artículo dedicado a branding y personalización "theme": [] // Consulta nuestro artículo dedicado a branding y personalización } } ``` #### `branding` En el objeto `branding`, puedes agregar personalización adicional al widget para que coincida con las necesidades de tu marca o aplicación. | Parámetro | Requerido | Descripción | | --- | --- | --- | | `color_scheme` | si | En el parámetro `color_scheme` defines si el widget debe estar en modo `LIGHT` (predeterminado) o `DARK`. Si deseas personalizar aún más los colores para estos modos, consulta el parámetro `theme`. | | `company_name` | si | El nombre de tu empresa. | #### `theme` Opcionalmente, puedes agregar los colores de tu marca al widget utilizando el parámetro `theme`. Para obtener más información sobre dónde aparecerán estos colores en el widget, consulta la guía de marca de Biometric Pix dedicada. Nuestra API devolverá el siguiente payload: ```json { "refresh": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MjMzNDY1MDY5MiwiaWF0IjoxNzEyNTcwNjkyLCJqdGkiOiIxMDAxMTg4NDU4Y2M0ZTlhOThmMDA4MmU3MDU3YzBmNyIsInVzZXJfaWQiOiI2ZTliZTg4NC00NzgxLTQxNDMtYjY3My1hY2EwMjQ3NWVlOGMiLCJvcmdhbml6YXRpb25fbmFtZSI6IkRvbWluaWsgQ2hvbGV3c2tpJ3MgdGVhbSIsIm9yZ2FuaXphdGlvbl9pZCI6IjZlOWJlODg0LTQ3ODEtNDE0My1iNjczLWFjYTAyNDc1ZWU4YyIsInNjb3BlcyI6WyJyZWFkX2luc3RpdHV0aW9ucyIsIndyaXRlX2xpbmtzIl0sImVudmlyb25tZW50Ijoic2FuZGJveCIsImFwaV91cmwiOiJzYW5kYm94LmJlbHZvLmNvbSIsImNyZWRlbnRpYWxzX3N0b3JhZ2UiOiIzMGQiLCJzdGFsZV9pbiI6IjM2NWQiLCJmZXRjaF9yZXNvdXJjZXMiOlsiQUNDT1VOVFMiLCJUUkFOU0FDVElPTlMiLCJPV05FUlMiXSwiaXNzIjoic2FuZGJveC5iZWx2by5jb20ifQ.X43VAc6c37U0JbiYgSd_r4SESjvGOuMgOpK5_DbuMHF7seATr7atO1QiUGwxdwBlEHo9ECST_9QKiHjv7G2czg", "access": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzEyNTcxODkyLCJpYXQiOjE3MTI1NzA2OTIsImp0aSI6ImFiNjRmYjkyZmY1ZjQ0MTU4N2IwM2Y2MDJhMzhhMjNhIiwidXNlcl9pZCI6IjZlOWJlODg0LTQ3ODEtNDE0My1iNjczLWFjYTAyNDc1ZWU4YyIsIm9yZ2FuaXphdGlvbl9uYW1lIjoiRG9taW5payBDaG9sZXdza2kncyB0ZWFtIiwib3JnYW5pemF0aW9uX2lkIjoiNmU5YmU4ODQtNDc4MS00MTQzLWI2NzMtYWNhMDI0NzVlZThjIiwic2NvcGVzIjpbInJlYWRfaW5zdGl0dXRpb25zIiwid3JpdGVfbGlua3MiXSwiZW52aXJvbm1lbnQiOiJzYW5kYm94IiwiYXBpX3VybCI6InNhbmRib3guYmVsdm8uY29tIiwiY3JlZGVudGlhbHNfc3RvcmFnZSI6IjMwZCIsInN0YWxlX2luIjoiMzY1ZCIsImZldGNoX3Jlc291cmNlcyI6WyJBQ0NPVU5UUyIsIlRSQU5TQUNUSU9OUyIsIk9XTkVSUyJdLCJpc3MiOiJzYW5kYm94LmJlbHZvLmNvbSJ9.2Irt1KCEKo6V17Y-N3zWeX3AchEvCrUWa_AlWoZ2gIIBhHvghHGkXtupOOrXKVqW9kTCOBE77-1riyyblUo4fw" } ``` ## Añadir token a la URL del widget Una vez que recibas el token de acceso, solo necesitas añadir el valor del parámetro `access` a la siguiente URL: ```curl Biometric Pix URL https://pix-biometria.pay.belvo.com/?access_token={access_token} ## Ejemplo https://pix-biometria.pay.belvo.com/?access_token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MjMzNDY1MDY5MiwiaWF0IjoxNzEyNTcwNjkyLCJqdGkiOiIxMDAxMTg4NDU4Y2M0ZTlhOThmMDA4MmU3MDU3YzBmNyIsInVzZXJfaWQiOiI2ZTliZTg4NC00NzgxLTQxNDMtYjY3My1hY2EwMjQ3NWVlOGMiLCJvcmdhbml6YXRpb25fbmFtZSI6IkRvbWluaWsgQ2hvbGV3c2tpJ3MgdGVhbSIsIm9yZ2FuaXphdGlvbl9pZCI6IjZlOWJlODg0LTQ3ODEtNDE0My1iNjczLWFjYTAyNDc1ZWU4YyIsInNjb3BlcyI6WyJyZWFkX2luc3RpdHV0aW9ucyIsIndyaXRlX2xpbmtzIl0sImVudmlyb25tZW50Ijoic2FuZGJveCIsImFwaV91cmwiOiJzYW5kYm94LmJlbHZvLmNvbSIsImNyZWRlbnRpYWxzX3N0b3JhZ2UiOiIzMGQiLCJzdGFsZV9pbiI6IjM2NWQiLCJmZXRjaF9yZXNvdXJjZXMiOlsiQUNDT1VOVFMiLCJUUkFOU0FDVElPTlMiLCJPV05FUlMiXSwiaXNzIjoic2FuZGJveC5iZWx2by5jb20ifQ.X43VAc6c37U0JbiYgSd_r4SESjvGOuMgOpK5_DbuMHF7seATr7atO1QiUGwxdwBlEHo9ECST_9QKiHjv7G2czg ``` ## Redirigir al usuario a la URL En tu aplicación, redirige a tu usuario a la URL que formaste en el paso anterior. Esto cargará el widget y tu usuario será guiado a través del proceso de registro y pago. ## Flujos de inscripción del widget A continuación, puedes ver el proceso que tu usuario seguirá en el widget para completar el proceso de inscripción. ### Notificaciones de webhook Durante el flujo de inscripción, recibirás las siguientes notificaciones de webhook: | Código de Webhook | Tipo (Recurso) | Descripción | Disparador | | --- | --- | --- | --- | | `OBJECT_CREATED` | CUSTOMERS | En el caso de que el CPF que enviaste para tu usuario no haya sido registrado aún para tu cuenta en nuestro sistema, crearemos el cliente y te notificaremos vía webhook y te proporcionaremos el `customer.id`. Recomendamos que almacenes este ID con el usuario asociado en tu base de datos. | El usuario ha seleccionado su institución y es redirigido a ella. | | `OBJECT_CREATED` | ENROLLMENTS | Una vez que comenzamos el proceso de inscripción y lo creamos en nuestro sistema, te notificamos vía webhook y te proporcionamos el `enrollment.id`. Recomendamos que almacenes este ID con el usuario asociado en tu base de datos. **Nota 1**: Para asociar la inscripción con tu usuario, por favor revisa el `details.metadata.{provided_key}` para el identificador único que proporcionaste para la sesión del widget. **Nota 2**: Un usuario puede tener múltiples inscripciones (para cada institución y para cada dispositivo). En otras palabras, hay una relación de 1:N entre el cliente y el número de inscripciones asociadas con el cliente. | El usuario ha seleccionado su institución y es redirigido a ella. | | `STATUS_UPDATE` | ENROLLMENTS | Cuando el usuario es redirigido desde su institución de vuelta al widget, recibirás una notificación de `STATUS_UPDATE`, indicando si el proceso de inscripción fue exitoso o no. Puedes recibir uno de los siguientes eventos de webhook: `SUCCEEDED` `FAILED` Para más detalles, consulta nuestra sección dedicada a Webhooks de Inscripciones. | El usuario es redirigido de vuelta al widget. | ## Flujo de Pago del Widget A continuación, puedes ver el proceso que tu usuario seguirá en el widget para completar el proceso de inscripción. ### Notificaciones de webhook Durante el flujo de pago, recibirás las siguientes notificaciones de webhook: | Código de Webhook | Tipo (Recurso) | Descripción | Disparador | | --- | --- | --- | --- | | `OBJECT_CREATED` | PAYMENT_INTENTS | Una vez que comenzamos el proceso de pago y lo creamos en nuestro sistema, te notificamos a través de webhook y proporcionamos el `payment_intent.id`. **Nota**: Para asociar la intención de pago con tu usuario (o inscripción), por favor revisa el `details.metadata.{provided_key}` para el identificador único que proporcionaste para la sesión del widget. | El usuario ha seleccionado qué inscripción usar y ha hecho clic en continuar. | | `OBJECT_CREATED` | CHARGES | Una vez que comenzamos el proceso de pago y lo creamos en nuestro sistema, te notificamos a través de webhook y proporcionamos el `charge.id`. | El usuario ha seleccionado qué inscripción usar y ha hecho clic en continuar. | | `STATUS_UPDATE` | PAYMENT_INTENTS | Durante el proceso del widget y de pago recibirás los siguientes webhooks `STATUS_UPDATE` para la intención de pago: `REQUIRES_ACTION` `PROCESSING` `SUCCEEDED` `FAILED` | Recibirás los eventos `REQUIRES_ACTION` y `PROCESSING` al mismo tiempo que `OBJECT_CREATED`. Los dos últimos los recibirás cuando el pago se complete con éxito o falle. | | `STATUS_UPDATE` | CHARGES | Durante el proceso del widget y de pago recibirás los siguientes webhooks `STATUS_UPDATE` para el cargo: `SUCCEEDED` `FAILED` | Cuando el pago se complete con éxito o falle. | | `OBJECT_CREATED` | TRANSACTIONS | Una vez que la intención de pago y el cargo asociado se hayan procesado con éxito, Belvo creará una Transacción. | La transacción fue procesada con éxito por la institución. | ## Realizar pagos subsecuentes Para realizar pagos subsecuentes para el usuario, puedes usar el mismo payload `access_token` como en Paso 1 - Generar un access_token. Nuestro widget detectará automáticamente si tu usuario tiene alguna inscripción existente y, de ser así, iniciará inmediatamente el widget en el Flujo de Pago del Widget.