Ir al contenido
GitHub

Enviar remesas recurrentes con un monto de débito fijo

Un pago de remesa es una transferencia de dinero de una persona a otra, normalmente entre países o a larga distancia, que a menudo implica una conversión de monedas y tarifas. En esta guía, aprenderá cómo configurar un pago recurrente de un remitente en el que el remitente paga un monto fijo. El monto recibido por el destinatario puede variar en función de las fluctuaciones del tipo de cambio.

Este enfoque es útil en particular para situaciones de aplicaciones de remesas en estos casos:

  • El remitente y el destinatario efectúan operaciones, cada uno, en monedas distintas.
  • El remitente quiere enviar un monto fijo en su propia moneda de forma recurrente.
  • El remitente y el destinatario están seguros de que el monto entregado puede variar en función de las fluctuaciones del tipo de cambio.

Imagine que alguien en EE. UU. quiere enviar dinero a un familiar en México. Esta persona quiere enviar exactamente 200 dólares estadounidenses (USD) desde su cuenta, independientemente de cuánto reciba realmente su familiar después de que se aplique la conversión de moneda.

Para esta guía, asumirá el papel de un desarrollador que está creando una aplicación de remesas. Esta guía explica cómo configurar un pago recurrente en dólares estadounidenses, en el que el remitente paga exactamente USD 200 cada mes durante tres meses.

El monto entregado al destinatario puede variar cada mes según los cambios en el tipo de cambio. Para simplificar, esta guía parte de un tipo de cambio estático de USD 1 por cada MXN 20.

Detalles de la transacción de ejemplo:

  • El remitente paga: USD 200 cada mes (fijo)
  • Tipo de cambio: Un cambio estático de USD 1 por cada MXN 20
  • El destinatario recibe: $4.000 cada mes durante tres meses (el monto real puede variar)

Las tres partes que intervienen en este caso son las siguientes:

  • Desarrollador: usted, la persona que construye la aplicación de remesas.
  • Remitente: la persona que utiliza su aplicación para enviar dinero en USD.
  • Destinatario: la persona que recibe el dinero en MXN.

1. Obtener los datos de la dirección de billetera

Sección titulada «1. Obtener los datos de la dirección de billetera»

Cuando el remitente configura un pago recurrente a través de su aplicación, usted debe obtener la información de la dirección de billetera tanto del remitente como del destinatario.

Supongamos que el remitente guardó la dirección de su billetera en la configuración de su perfil en su aplicación. Asumamos también que el remitente ha ingresado la dirección de billetera del destinatario en el formulario de pago de su aplicación.

Llame a la GET Get Wallet Address API para cada dirección.

const senderWalletAddress = await client.walletAddress.get({
url: 'https://cloudninebank.example.com/sender'
})
const recipientWalletAddress = await client.walletAddress.get({
url: 'https://happylifebank.example.com/recipient'
})

Respuestas de ejemplo El siguiente ejemplo muestra una respuesta del proveedor de billetera del remitente.

{
"id": "https://cloudninebank.example.com/sender",
"assetCode": "USD",
"assetScale": 2,
"authServer": "https://auth.cloudninebank.example.com/",
"resourceServer": "https://cloudninebank.example.com/op"
}

El siguiente ejemplo muestra una respuesta del proveedor de billetera del destinatario.

{
"id": "https://happylifebank.example.com/recipient",
"assetCode": "MXN",
"assetScale": 2,
"authServer": "https://auth.happylifebank.example.com/",
"resourceServer": "https://happylifebank.example.com/op"
}

2. Solicitar una concesión de autorización para un pago entrante

Sección titulada «2. Solicitar una concesión de autorización para un pago entrante»

Utilice los datos del destinatario authServer recibidos en el paso 1 para llamar a la POST Grant Request API.

Esta llamada obtiene un token de acceso que permite a su aplicación solicitar la creación de un recurso de pago entrante en la cuenta de billetera del destinatario.

const recipientIncomingPaymentGrant = await client.grant.request(
{
url: recipientWalletAddress.authServer
},
{
access_token: {
access: [
{
type: 'incoming-payment',
actions: ['create'],
},
],
},
},
);

Ejemplo de respuesta El siguiente ejemplo muestra una respuesta del proveedor de billetera del destinatario.

{
"access_token": {
"value": "...", // access token value for incoming payment grant
"manage": "https://auth.happylifebank.example.com/token/{...}", // management uri for access token
"access": [
{
"type": "incoming-payment",
"actions": ["create"]
}
]
},
"continue": {
"access_token": {
"value": "..." // access token for continuing the request
},
"uri": "https://auth.happylifebank.example.com/continue/{...}" // continuation request uri
}
}

3. Solicitar la creación de un recurso de pago entrante

Sección titulada «3. Solicitar la creación de un recurso de pago entrante»

Use el token de acceso devuelto en la respuesta anterior para llamar a la POST Create Incoming Payment API.

Esta llamada solicita la creación de un recurso de pago entrante en la cuenta de billetera del destinatario.

const recipientIncomingPayment = await client.incomingPayment.create(
{
url: recipientWalletAddress.resourceServer,
accessToken: recipientIncomingPaymentGrant.access_token.value
},
{
walletAddress: recipientWalletAddress.id,
},
)

Ejemplo de respuesta El siguiente ejemplo muestra una respuesta del proveedor de billetera del destinatario.

{
"id": "https://happylifebank.example.com/incoming-payments/{...}",
"walletAddress": "https://happylifebank.example.com/recipient",
"receivedAmount": {
"value": "0",
"assetCode": "MXN",
"assetScale": 2
},
"completed": false,
"createdAt": "2025-10-03T23:24:55.52Z",
"methods": [
{
"type": "ilp",
"ilpAddress": "...",
"sharedSecret": "..."
}
]
}

4. Solicitar una concesión de autorización interactiva para un pago saliente

Sección titulada «4. Solicitar una concesión de autorización interactiva para un pago saliente»

Utilice la información del remitente authServer recibida en el paso 1 para llamar a la POST Grant Request API.

Esta llamada obtiene un token de acceso que permite a su aplicación solicitar la creación de recursos de pago saliente en la cuenta de billetera del remitente.

Como el remitente pagará un monto fijo de USD 200 al mes, la solicitud debe tener un objeto limits que contenga un debitAmount y un interval.

  • debitAmount - El monto máximo que se puede debitar al remitente por intervalo. Cuando comienza el siguiente intervalo, el valor se restablece.
  • interval - El intervalo de tiempo durante el cual la concesión es válida.

Los pagos salientes requieren una concesión de autorización interactiva, que el remitente aprueba una sola vez. Mientras la concesión de autorización (y su token de acceso) sean válidos y estén dentro de sus límites (interval + debitAmount), su aplicación puede crear pagos salientes sin volver a- aprobar cada intervalo. Puede encontrar más información en las páginas del flujo de Open Payments y proveedores de identidad.

const pendingSenderOutgoingPaymentGrant = await client.grant.request(
{
url: senderWalletAddress.authServer
},
{
access_token: {
access: [
{
identifier: senderWalletAddress.id,
type: 'outgoing-payment',
actions: ['create'],
limits: {
interval: 'R3/2025-10-03T23:25:00Z/P1M',
debitAmount: {
assetCode: 'USD',
assetScale: 2,
value: '20000', // $200.00 USD per interval
}
}
}
]
},
interact: {
start: ['redirect'],
finish: {
method: 'redirect',
uri: 'https://myapp.example.com/finish/{...}', // where to redirect your user after they've completed the interaction
nonce: NONCE
}
}
}
)

Ejemplo de respuesta El siguiente ejemplo muestra una respuesta del proveedor de billetera del remitente.

{
"interact": {
"redirect": "https://auth.interledger-test.dev/{...}", // uri to redirect your user to, to begin interaction
"finish": "..." // unique key to secure the callback
},
"continue": {
"access_token": {
"value": "..." // access token for continuing the outgoing payment grant request
},
"uri": "https://auth.interledger-test.dev/continue/{...}", // uri for continuing the outgoing payment grant request
"wait": 30
}
}

El intervalo que se emplea en esta guía es R3/2025-10-03T23:25:00Z/P1M. Recuerde que el remitente desea enviar USD 200 al mes durante tres meses. El intervalo se desglosa del siguiente modo:

  • R3/ es la cantidad de repeticiones:- tres.
  • 2025-10-03 es la fecha de inicio del intervalo repetido: - 3 de octubre de 2025.
  • T23:25:00Z/ es la hora de inicio del intervalo repetido: - 11:25 p. m. UTC.
  • P1M es el período entre cada intervalo: - un mes. Si se emplea con R3, se obtiene una concesión válida una vez por mes durante tres meses.

En total, esta concesión de autorización permitirá al remitente realizar pagos salientes desde:

  • las 11:25 p. m. UTC del 3 de octubre de 2025 hasta las 11:24 p. m. UTC del 3 de noviembre de 2025.
  • las 11:25 p. m. UTC del 3 de noviembre de 2025 hasta las 11:24 p. m. UTC del 3 de diciembre de 2025.
  • las 11:25 p. m. UTC del 3 de diciembre de 2025 hasta las 11:24 p. m. UTC del 3 de enero de 2026.

5. Comenzar la interacción con el remitente

Sección titulada «5. Comenzar la interacción con el remitente»

Una vez que el cliente recibe la respuesta del servidor de autorización, debe enviar al usuario al URI de interact.redirect de la respuesta. Esto da comienzo al flujo de interacción.

La respuesta también incluye un objeto de continue, que es fundamental para gestionar la interacción y obtener el consentimiento explícito del usuario para concesiones de autorizaciones de pagos salientes. El objeto de continue contiene un token de acceso y un URI que el cliente usará para finalizar la solicitud de concesión de autorización después de que el usuario haya completado su interacción con el proveedor de identidad (Identity provider, IdP). Esto asegura que el cliente pueda obtener de manera segura los permisos necesarios para proceder con el proceso de pago.

Respuesta de ejemplo
{
"interact": {
"redirect": "https://auth.interledger-test.dev/4CF492MLVMSW9MKMXKHQ",
"finish": "4105340a-05eb-4290-8739-f9e2b463bfa7"
},
"continue": {
"access_token": {
"value": "33OMUKMKSKU80UPRY5NM"
},
"uri": "https://auth.interledger-test.dev/continue/4CF492MLVMSW9MKMXKHQ",
"wait": 30
}
}

6. Finalizar la interacción con el remitente

Sección titulada «6. Finalizar la interacción con el remitente»

El usuario interactúa con el servidor de autorización a través de la interfaz del servidor y aprueba o rechaza la concesión de autorización.

Siempre que el usuario apruebe la concesión de autorización, el servidor de autorización realiza lo siguiente:

  • Envía al usuario al finish.uri anteriormente definido por su cliente. La manera en que el servidor envía al usuario al URI está fuera de alcance, pero las opciones comunes incluyen redireccionar al usuario desde una página web y lanzar el navegador del sistema con la URI específica.
  • Asegura la redirección al agregar un hash único, lo que le permite a su cliente validar la llamada de finish, y una referencia de interacción como parámetros de consulta al URI.

7. Solicitar una continuación de la concesión de autorización

Sección titulada «7. Solicitar una continuación de la concesión de autorización»

En nuestro ejemplo, suponemos que el IdP con el que interactuó su usuario (el remitente) cuenta con una interfaz de usuario. Cuando la interacción finaliza, el usuario regresa a su aplicación. Ahora su aplicación puede realizar una solicitud de continuación de la concesión de autorización de pago saliente.

En una situación hipotética donde una interfaz de usuario no se encuentra disponible, analice la posibilidad de implementar un mecanismo de sondeo para verificar que se haya completado la interacción.

Llame a la POST Grant Continuation Request API. Esta llamada obtiene un token de acceso que permite a su aplicación continuar con la solicitud de concesión de autorización de pago saliente.

Emita la solicitud al continue.uri proporcionado en la respuesta de concesión de autorización de pago saliente inicial.

Incluya la interact_ref devuelta en los parámetros de consulta del URI de redirección.

const senderOutgoingPaymentGrant = await client.grant.continue(
{
url: pendingSenderOutgoingPaymentGrant.continue.uri,
accessToken: pendingSenderOutgoingPaymentGrant.continue.access_token.value
},
{
interact_ref: interactRef
}
)

Ejemplo de respuesta El siguiente ejemplo muestra una respuesta del proveedor de billetera del remitente.

{
"access_token": {
"value": "...", // final access token required before creating outgoing payments
"manage": "https://auth.cloudninebank.example.com/token/{...}", // management uri for access token
"access": [
{
"type": "outgoing-payment",
"actions": ["create"],
"identifier": "https://cloudninebank.example.com/sender",
"limits": {
"interval": "R3/2025-10-03T23:25:00Z/P1M",
"debitAmount": {
"assetCode": "USD",
"assetScale": 2,
"value": "20000"
}
}
}
]
},
"continue": {
"access_token": {
"value": "..." // access token for continuing the request
},
"uri": "https://auth.cloudninebank.example.com/continue/{...}" // continuation request uri
}
}

8. Solicitar la creación de un recurso de pago saliente

Sección titulada «8. Solicitar la creación de un recurso de pago saliente»

Utilice el token de acceso devuelto en la continuación de la concesión de autorización de pago saliente (paso 7) para llamar a la POST Create Outgoing Payment API. Cree este pago haciendo referencia a la nueva URL incomingPayment y al debitAmount fijo.

const senderOutgoingPayment = await client.outgoingPayment.create(
{
url: senderWalletAddress.resourceServer,
accessToken: senderOutgoingPaymentGrant.access_token.value
},
{
walletAddress: senderWalletAddress.id,
incomingPayment: recipientIncomingPayment.id,
debitAmount: {
assetCode: 'USD',
assetScale: 2,
value: '20000'
},
}
)

Ejemplo de respuesta El siguiente ejemplo muestra una respuesta del proveedor de billetera del remitente.

{
"id": "https://cloudninebank.example.com/outgoing-payments/{...}", // url of the outgoing payment
"walletAddress": "https://cloudninebank.example.com/sender",
"receiver": "https://happylifebank.example.com/incoming-payments/{...}", // url of the incoming payment being paid
"debitAmount": {
"value": "20000", // The amount to debit from the sender's account
"assetCode": "USD",
"assetScale": 2
},
"receiveAmount": {
"value": "400000", // Recipient to receive $4,000 MXN (actual may vary by rate)
"assetCode": "MXN",
"assetScale": 2
},
"sentAmount": {
"value": "0",
"assetCode": "USD",
"assetScale": 2
},
"createdAt": "2025-10-03T23:27:45.41Z"
}

El primer pago ya está configurado. En el siguiente intervalo (dentro de un mes), repita los siguientes pasos para solicitar la creación de los siguientes:

  1. Un recurso de pago entrante (paso 3)
  2. Un recurso de pago saliente (paso 8)

Utilice el token de acceso asociado a la concesión de autorización de cada recurso en las solicitudes. No necesita solicitar nuevas concesiones de autorización porque las concesiones originales deberían seguir siendo válidas.