Esta documentación cubre características de nuestro próximo lanzamiento. Aunque la funcionalidad principal y el flujo de trabajo descritos aquí permanecerán sin cambios, puede que notes algunas mejoras antes del lanzamiento final, tales como:
- Actualizaciones y optimizaciones del iOS SDK
- Mejoras en la documentación (enlaces, terminología, diagramas)
- Actualizaciones de referencia de la API para los endpoints de inscripción
Con Pix Biometria 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.
El primer paso para habilitar la recolección de pagos biométricos es inscribir el dispositivo del usuario con su institución. Durante la inscripción, los datos clave sobre el dispositivo y las credenciales de clave pública del usuario se registran de manera segura con su institución, asegurando que los pagos futuros puedan ser confirmados usando solo la autenticación biométrica.
Una vez que la inscripción esté completa, puedes comenzar a solicitar pagos directamente desde el dispositivo del usuario.
En esta guía, te llevaremos a través de cada paso, desde la inscripción del dispositivo hasta iniciar con éxito una solicitud de pago en un dispositivo iOS.
Antes de continuar con esta guía, asegúrate de que:
Has generado tus Claves de la API de Pagos de Belvo.
Configuraste Webhooks para recibir actualizaciones sobre el estado de tus pagos e inscripciones.
Instalaste el SDK de iOS de Belvo:
Requisitos mínimos
- iOS: 15.0 o superior
- Swift: 5.0 o superior
Instrucciones:
Para integrar el SDK de Biometric PIX de Belvo en tu proyecto de Xcode usando Swift Package Manager:
- En Xcode, selecciona File → Add Packages....
- Ingresa la URL del repositorio del paquete:
https://github.com/belvo-finance-opensource/biometric-pix-ios-sdk. - Selecciona los requisitos de versión y haz clic en Add Package.
- Elige el producto BiometricPixSDK y haz clic en Add Package.
Agrega los derechos requeridos al archivo de derechos de tu aplicación:
<key>com.apple.developer.associated-domains</key> <array> <string>webcredentials:belvo.com</string> </array>Agrega la descripción del uso de la ubicación en tu archivo
Info.plist:<key>NSLocationWhenInUseUsageDescription</key> <string>Esta aplicación utiliza la ubicación para propósitos de seguridad y prevención de fraude.</string>Comparte tu Team ID y Bundle Identifier con Belvo en el siguiente formato
## Formato TEAM_ID.BUNDLE_ID ## Ejemplo ABCDEFGHIJ.com.yourcompany.appnameAdemás, para cada usuario que desees inscribir en el sistema de Pix Biometria, primero necesitarás crear un Cliente de Belvo.
La inscripción es el proceso de registrar el dispositivo de un usuario en su institución para permitir pagos biométricos para un comerciante determinado. Durante el proceso, utilizarás una combinación del SDK de iOS de Belvo Payments y la API para recuperar detalles clave sobre el dispositivo, así como los datos públicos biométricos.
- Listar Instituciones: Solicita al usuario que seleccione su institución financiera deseada para inscribirse, utilizando la API de Belvo para mostrar las opciones disponibles.
- Solicitar Permisos de Ubicación y Recopilar Señales de Riesgo: Solicita al usuario los permisos necesarios y recopila señales de riesgo, incluyendo el ID del dispositivo.
- Crear y Actualizar Inscripción: Envía las señales de riesgo recopiladas, junto con el ID del cliente, el ID de la institución y una URL de callback, al servidor de Belvo para crear la inscripción. Luego, redirige al usuario a la aplicación de su institución para su aprobación. Una vez que sean redirigidos de vuelta a tu URL de callback con detalles, envía estos a Belvo para actualizar el estado de la inscripción.
- Consultar Opciones de FIDO: Consulta continuamente la API de Belvo (
GET /enrollments/{id}/fido-registration-options/) para recuperar las opciones FIDO necesarias para el registro biométrico. ⚠️ Estrategia de Consulta: Recomendamos consultar nuestro servidor cada dos segundos durante un máximo de dos minutos. Si no se recibe respuesta dentro de este período, instruye al usuario para que lo intente de nuevo. - Solicitar Biométricos: Toma las opciones FIDO de la API de Belvo y utiliza el método
startRegistration(fidoOptions)del SDK de iOS de Belvo para solicitar al usuario su gesto biométrico. - Finalizar Inscripción: Envía los datos públicos biométricos a Belvo usando
POST /enrollments/{id}/confirm/. Después de eso, consultaGET /enrollments/{id}/hasta recibir una respuesta (estado de inscripción =SUCCEEDEDoFAILED).
En tu aplicación, solicita a tu usuario que seleccione la institución donde desea inscribir el dispositivo. Usa la solicitud de Listar todas las instituciones de pago para obtener una lista de todas las posibles instituciones. Una vez que el usuario seleccione la institución, guarda el id de la institución (requerido en el paso de Enviar Señales de Riesgo a Belvo (API)).
A continuación, en tu aplicación, necesitarás realizar las siguientes llamadas:
Este método requestPermission() crea y lanza una solicitud de permiso para permisos de ubicación y estado del teléfono.
import SwiftUI
import BiometricPixSDK
import Foundation
struct PermissionRequestExample: View {
@State private var permissionGranted: Bool? = nil
private let sdk = BiometricPixSDK()
private func requestPermission() {
sdk.requestPermission { granted in
DispatchQueue.main.async {
// Si es necesario, convertir granted a Bool
permissionGranted = granted as? Bool
// Si es necesario, manejar la UI
}
}
}
}Cuando el usuario concede su permiso, puedes entonces extraer las señales de riesgo del dispositivo usando collectRiskSignals(accountTenure).
El método collectRiskSignals(accountTenure) recopila datos completos de huellas digitales del dispositivo y señales de seguridad. Los datos recopilados incluyen ID del dispositivo, estado de seguridad, información de hardware y señales de comportamiento, que son cruciales para que la institución realice evaluaciones de riesgo y detección de fraude. El método devuelve un objeto RiskSignals que necesitas guardar y enviar a los servidores de Belvo en una llamada de API. Además, necesitas persistir el valor de deviceId que el objeto RiskSignals devuelve para que más tarde puedas asociarlo con el ID de Inscripción (más adelante, al listar Inscripciones, necesitas proporcionar el deviceID para recibir todas las Inscripciones).
En el argumento accountTenure, debes pasar la fecha en que el usuario fue creado como Cliente en la API de Belvo, en formato YYYY-MM-DD.
Esto se deriva del timestamp created_at del Cliente. Sin embargo, solo necesitas enviar los primeros 10 caracteres correspondientes al año, mes y día (YYYY-MM-DD). Una expresión regular útil para extraer esto del parámetro created_at podría ser: \d{4}-\d{2}-\d{2}.
import SwiftUI
import BiometricPixSDK
import Foundation
struct RiskSignalsView: View {
private let sdk = BiometricPixSDK()
private func collectRiskSignals() {
do {
// Recopilar señales de riesgo con la fecha de creación del usuario
signals = sdk.collectRiskSignals(
accountTenure: "YYYY-MM-DD"
)
} catch {
// Manejar errores que puedan ocurrir durante la recopilación de señales de riesgo.
// Los posibles errores incluyen:
// - Formato `accountTenure` inválido
// - Problemas de conectividad de red
// Considera registrar el error o mostrar un mensaje apropiado al usuario.
}
}
}Una vez que tengas las señales de riesgo y el ID del dispositivo, puedes enviar esta información a Belvo utilizando el método Create Enrollment.
POST /enrollments/// Cuerpo de la Solicitud
{
"type": "open_finance_biometric_pix",
"details": {
"customer": "{{created_customer_uuid}}",
"institution": "{{selected_institution_uuid}}",
"name": "Nombre para la inscripción",
"platform": "IOS",
"callback_url": "{{https://deeplink_to_your_application}}",
"risk_signals": {}
}
}| Parámetro | Tipo | Descripción |
|---|---|---|
type | string (enum) | El tipo de inscripción. Para Pix Biometria, esto debe establecerse en open_finance_biometric_pix. |
details | object | Detalles sobre la inscripción del dispositivo. |
details.customer | string (uuid) | El ID de Belvo para tu usuario. |
details.institution | string (uuid) | El ID de Belvo para la institución que tu usuario seleccionó para la inscripción. |
details.callback_url | string (uri) | El deeplink a donde tu usuario debe ser redirigido en tu aplicación después de que aprueben la inscripción en la aplicación de su institución. Debe ser compatible con HTTPS. |
details.name | string | Un nombre legible para la inscripción. |
details.platform | string | La plataforma a la que se refiere esta inscripción. Para dispositivos iOS, esto debe establecerse en IOS. |
details.risk_signals | object | El objeto RiskSignals (convertido a JSON) que recibiste después de usar el método collectRiskSignals. |
El callback_url que proporciones debe estar registrado en tus applinks. Para obtener detalles sobre cómo registrar tu URL de callback, consulta la documentación de Apple sobre applinks.
En la respuesta, recibirás un redirect_url que necesitas mostrar a tu usuario para que puedan ser redirigidos a su institución para confirmar su inscripción.
// 201 Created
{
"id": "82666cde-3f80-4350-b0f7-24cb8e9294c9",
"created_by": "56689ef8-4c92-44ae-b2c1-60505da4a7e1",
"created_at": "2024-11-26T11:20:57.389056Z",
"updated_at": "2024-11-26T11:20:57.389056Z",
"type": "open_finance_biometric_pix",
"status": "PENDING",
"details": {
"status": "AWAITING_ACCOUNT_HOLDER_VALIDATION",
"customer": "f78b14f3-5c1a-409a-966f-7b052b067cf0",
"institution": "188716fb-39ad-44a7-a992-6c278d2b24a4",
"platform": "IOS",
"name": "Primera Inscripción",
"callback_url": "deeplink-to-your-application",
"redirect_url": "https://www.user-banking-institituon.com/?enrollment_request=true...",
"risk_signals": "*****"
}
}Ahora necesitas redirigir a tu usuario a su institución usando el redirect_url para que puedan confirmar el proceso de inscripción. Durante el proceso, iniciarán sesión en su institución, revisarán la solicitud de inscripción y luego la autorizarán. Una vez que el usuario autorice la inscripción, la institución los redirigirá de vuelta al callback_url que proporcionaste.
https://redirect.clientApplication.com/
?state=<state>
&code=<code>
&id_token=<long_id_token>La institución pasará datos en los parámetros de consulta que debes enviar a Belvo usando la solicitud de Update Enrollment State API. Recomendamos transformar los parámetros de consulta en un objeto JSON y enviarlo directamente a Belvo.
Con el valor de la cadena de consulta guardado como un objeto JSON, puedes hacer la siguiente solicitud:
POST /enrollments/complete-redirection/{
"state": "{{state}}",
"code": "{{code}}",
"id_token": "{{id_token}}",
}En el caso de que haya sido un callback exitoso, en la respuesta de la solicitud el status de la inscripción seguirá configurado como PENDING.
// 200 OK
{
"id": "{{enrollment.id}}",
"type": "open_finance_biometric_pix",
"status": "PENDING",
"details": {
"callback_url": "https://merchant.com/enrollment-success/",
"customer": "{{customer.id}}",
"expires_at": "2022-10-31T00:00:00Z",
"institution": "uuid",
"name": "My Enrollment",
"payer_information": {
"bank_account": {
"institution_id": "{{institution.id}}",
"agency": "1234",
"number": "*****6789",
"account_type": "CHECKINGS"
}
},
"platform": "IOS",
"redirect_url": "https://example.com/redirect-enrollment/",
"risk_signals": "*******",
"status": "AWAITING_ACCOUNT_HOLDER_VALIDATION"
},
"external_id": null,
"metadata": {},
"status_reason_code": null,
"status_reason_message": null,
"created_by": "{{belvo_client.id}}",
"created_at": "{{timestamp}}",
"updated_at": "{{timestamp}}"
}La institución ahora procesará los datos de inscripción y proporcionará a Belvo las Opciones FIDO que se requieren para generar el desafío biométrico. Necesitarás consultar nuestra API para recuperar estos datos y luego solicitar datos biométricos de tu usuario.
Envía una solicitud cada dos segundos hasta que recibas una respuesta o pasen dos minutos sin respuesta. Si no recibes respuesta después de dos minutos, muestra una pantalla de “Intenta de nuevo” a tu usuario y reinicia el proceso. En segundo plano, la Inscripción cambiará a status = FAILED.
Después de recibir la respuesta exitosa de la solicitud Update Enrollment State, necesitas consultar el siguiente endpoint para recibir las opciones de registro FIDO necesarias para solicitar datos biométricos.
GET /enrollments/{enrollment_id}/fido-registration-options/Recibirás la siguiente respuesta 200 - OK de nuestra API. Asegúrate de guardar el objeto (fidoOptions) ya que es un parámetro requerido para el método startRegistration() del SDK.
// 200 OK
{
"rp": {
"id": "belvo.com",
"name": "Raidiam Mockbank - Pipeline NRJ"
},
"user": {
"id": "a5bd0ef9-f8ab-41a2-b968-489761a91de6",
"name": "Ralph Bragg",
"displayName": "Ralph Bragg"
},
"challenge": "R3dsT2REOE5oZ25JbVE",
"pubKeyCredParams": [
{
"alg": -257,
"type": "public-key"
},
{
"alg": -7,
"type": "public-key"
}
],
"extensions": {
"appid": "true"
}
}Con la carga útil recibida, necesitas usar el método startRegistration(fidoOptions). Este método inicia el registro de credenciales biométricas utilizando protocolos FIDO2. Procesa las opciones de registro FIDO (una cadena JSON) recibidas de tu servidor backend y lanza el flujo de autenticación biométrica nativa del dispositivo (por ejemplo, huella digital o escaneo facial).
import Foundation
import BiometricPixSDK
class FidoRegistrationViewModel : NSObject, ObservableObject {
private let sdk = BiometricPixSDK()
func startRegistration(fidoOptions: String) {
do {
sdk.startRegistration(
fidoResponseString: fidoOptions,
callback: self // Instancia de Callback
)
} catch {
// Manejar errores
}
}
}
// Implementación del callback para el registro
extension FidoRegistrationViewModel: FidoRegistrationCallback {
func onError(error: String) {
// Manejar errores de registro
}
func onSuccess(response attestationResponse: AttestationResponse) {
// Manejar registro exitoso
// El objeto attestationResponse contiene los datos necesarios para el siguiente paso.
let encodedId = attestationResponse.encodedId
let rawId = attestationResponse.rawId
let encodedAttestationObject = attestationResponse.encodedAttestationObject
let encodedClientDataJSON = attestationResponse.encodedClientDataJSON
// Persistir estos valores para enviarlos a tu backend.
}
}Al usar este modelo de vista en vistas de SwiftUI, decláralos como propiedades @ObservedObject para asegurar que no sean destruidos durante las re-renderizaciones de la vista. Esto es crítico para que los callbacks funcionen correctamente.
import SwiftUI
struct MyView: View {
@ObservedObject var registrationViewModel = FidoRegistrationViewModel()
// ...
}Necesitas almacenar los siguientes valores en variables ya que se utilizan para confirmar la Inscripción en el siguiente paso:
encodedIdrawIdencodedAttestationObjectencodedClientDataJSON
Para completar el proceso de Registro, necesitarás enviar los valores que recibiste al siguiente endpoint:
POST /payments/br/enrollments/{enrollment_id}/confirm/// Cuerpo de la Solicitud
{
"confirmation_data": {
"authenticatorAttachment": "platform",
"id": "{{encodedId}}",
"rawId": "{{rawId}}",
"type": "public-key",
"response": {
"attestationObject": "{{encodedAttestationObject}}",
"clientDataJSON": "{{encodedClientDataJSON}}"
}
}
}| Parámetro | Tipo | Descripción |
|---|---|---|
authenticatorAttachment | string | El tipo de autenticador. Debe establecerse en platform. |
id | string | El encodedId que recibiste del método startRegistration(). |
rawId | string | El rawId que recibiste del método startRegistration(). |
type | string | El tipo de credencial FIDO que se está generando. Debe establecerse en public-key. |
response.attestationObject | string | El encodedAttestationObject que recibiste del método startRegistration(). |
response.clientDataJSON | string | El encodedClientDataJSON que recibiste del método startRegistration(). |
Belvo responderá con un 204 - No Content y enviará la información a la institución para completar el proceso de registro.
Envía una solicitud cada dos segundos hasta que recibas una respuesta o pasen dos minutos sin respuesta. Si no recibes respuesta después de dos minutos, muestra una pantalla de “Intenta de nuevo” a tu usuario y reinicia el proceso. En segundo plano, el Registro pasará a status = FAILED.
Necesitarás consultar el siguiente endpoint hasta que recibas una respuesta de la API de Belvo. Una vez que recibas una respuesta, verifica el campo status.
GET /enrollments/{enrollment_id}/Si el status es SUCCEEDED, ¡perfecto! ¡El registro está listo y puedes comenzar a realizar pagos!
Una vez que el dispositivo de un usuario está registrado exitosamente, puedes iniciar solicitudes de pago utilizando sus credenciales biométricas almacenadas. Este proceso involucra:
- Seleccionar un Registro
- Crear una intención de pago
- Recopilar datos de autenticación biométrica
- Autorizar el pago
Utiliza el método de API Listar todas las inscripciones, con el parámetro de consulta requerido device_id, para solicitar todas las inscripciones que tu usuario ha realizado usando tu aplicación y su dispositivo actual. Muestra esta lista de inscripciones al usuario, permitiéndoles elegir qué inscripción usar para el pago. Guarda el id de esa inscripción (utilizado en el siguiente paso de Crear Intención de Pago).
GET /enrollments/?device_id={device_id}Una vez que tengas la Enrollment seleccionada por el usuario, puedes crear un Payment Intent:
POST /payments/br/payment-intents/{
"amount": 0.13,
"allowed_payment_method_types": [
"open_finance_biometric_pix"
],
"customer": "{{customer.id}}",
"description": "Test Payment Intent with Enrollment",
"statement_description": "Description to show on statement",
"payment_method_details": {
"open_finance_biometric_pix": {
"beneficiary_bank_account": "{{bank_account.id}}",
"enrollment": "{{enrollment.id}}"
}
},
"confirm": true
}| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
amount | número | si | El monto a pagar. |
allowed_payment_method_types | string | si | El tipo de método de pago. Debe establecerse en open_finance_biometric_pix. |
customer | string (uuid) | si | El id del usuario del cual estás solicitando pagos. |
description | string | si | Tu descripción para el pago. |
statement_description | string | si | La descripción que aparecerá en el estado de cuenta del usuario. |
payment_method_details.open_finance_biometric_pix.beneficiary_bank_account | string (uuid) | si | El id de la cuenta bancaria que recibirá los fondos. |
payment_method_details.open_finance_biometric_pix.enrollment | string (uuid) | si | El id de la Enrollment que el usuario seleccionó. |
confirm | booleano | si | Confirma que el pago está listo para ser procesado. Debe establecerse en true. |
En la respuesta, Belvo devolverá el payment_intent.id y el objeto fido_options que son necesarios para el siguiente paso de autenticación biométrica. Necesitas:
- Persistir el
payment_intent.iden tu backend. - Guardar el
fido_optionsen una variable para ser usado en el siguiente paso en el SDK de Belvo.
{
"id": "uuid",
"status": "PENDING",
"payment_method_information": {
"open_finance_biometric_pix": {
"provider": "belvo",
"consent_id": "urn:nubank:023230b9-1211-3420-bf6d-e7d56e87bdf1",
"fido_options": {
"rpId": "belvo.com",
"timeout": 300000,
"challenge": "oGW096Hvr8sVUIOf-10iqWI7ZfSx2GhoU359bBRK9h4",
"allowCredentials": [
{
"id": "AfD-uI4LUzJAuzyLBRrPncocLusMgZ8yHNuuUl-7NSFbBlqrW2rMF0D_Ao-orNqdX3YZVf8_wk1jj--HuNH1uKE",
"type": "public-key"
}
]
},
"end_to_end_id": "E432158152025061315009OzwiMmDSO7",
"external_payment_id": "bde3bb4d-5b48-4875-b69d-7f2beee4fb42",
"provider_request_id": "afc99a8b-e0c7-4a8b-85d7-193bd70e4cc0"
}
}
}Usando las fido_options recibidas del intento de pago, inicia el proceso de autenticación biométrica utilizando el método startSigning(fidoOptions) del SDK de Belvo para iOS. Después de que el usuario se autentique, también necesitarás llamar a collectRiskSignals(accountTenure) para recopilar información del dispositivo.
Los resultados de estos métodos contienen los valores que necesitarás enviar a tu backend para autorizar el pago.
import Foundation
import BiometricPixSDK
class FidoAuthenticationViewModel : NSObject, ObservableObject {
private let sdk = BiometricPixSDK()
func startSigning(fidoOptions: String) {
do {
// Nota: El método para iniciar la autenticación de pago es startSigning.
sdk.startSigning(
fidoResponseString: fidoOptions,// cadena json solicitada desde la API del backend
fallbackCredential: nil,//cadena de credenciales de respaldo si está disponible
callback: self// instancia de callback
)
} catch {
// Manejo de errores
}
}
private func collectRiskSignals() {
do {
// Recopilar señales de riesgo con la fecha de creación del usuario
let signals = sdk.collectRiskSignals(
accountTenure: "YYYY-MM-DD"
)
// Envía las señales a tu backend para ser usadas en el paso de autorización.
} catch {
// manejar error
}
}
}
// implementando callback para autenticación
extension FidoAuthenticationViewModel: FidoAuthenticationCallback {
func onError(error: String) {
// Manejar errores de autenticación
}
func onSuccess(response assertionResponse: AssertionResponse) {
// Manejar autenticación exitosa
// Extraer datos de assertionResponse y enviar a tu backend.
// Luego, llama a collectRiskSignals.
collectRiskSignals()
}
}Al usar este modelo de vista en vistas de SwiftUI, decláralos como propiedades @ObservedObject para asegurar que no sean destruidos durante las re-renderizaciones de la vista. Esto es crítico para que los callbacks funcionen correctamente.
import SwiftUI
struct MyView: View {
@ObservedObject var registrationViewModel = FidoRegistrationViewModel()
// ...
}Después de obtener la información requerida en el paso de Recolectar Datos Biométricos y Señales de Riesgo (SDK), ahora puedes autorizar el pago utilizando la API de Belvo.
POST /payment-intents/{payment_intent_id}/authorize/Belvo procesará la autorización. Necesitarás hacer sondeos a
GET /payment-intents/{id}/hasta que elstatusde la intención de pago se convierta enSUCCEEDED.Estrategia de Sondeo: Similar a la inscripción, recomendamos sondear el estado de la intención de pago (
GET /payment-intents/{payment_intent_id}/) cada dos segundos por hasta dos minutos hasta que el estado seaSUCCEEDED. Si el estado no cambia o ocurre un error, informa al usuario y sugiere reintentar.Una vez que el pago sea exitoso, muestra una pantalla de confirmación al Usuario Final.
// POST /payment-intents/{id}/authorize/ Ejemplo de Cuerpo de Solicitud
{
"risk_signals": {}, // El objeto de Señales de Riesgo recolectado
"assertion": {
"authenticatorAttachment": "platform",
"id": "{{encodedId}}",
"rawId": "{{rawId}}",
"response": {
"authenticatorData": "{{encodedAuthenticatorData}}",
"clientDataJSON": "{{encodedClientDataJSON}}",
"signature": "{{encodedSignature}}",
"userHandle": "{{userHandle}}"
},
"type": "public-key"
}
}La API de Belvo devolverá un 204 - Not Content. Después de esto, necesitas sondear el siguiente endpoint para obtener el estado final del pago:
GET /payment-intents/{payment_intent_id}/Envía una solicitud cada dos segundos hasta que recibas una respuesta o pasen dos minutos sin respuesta. Si no recibes respuesta después de dos minutos, muestra una pantalla de “Intenta de nuevo” a tu usuario y reinicia el proceso. En segundo plano, la Intención de Pago y el Cargo asociado pasarán a status = FAILED.