Integración
Integrar con la Anchor Platform para facilitar pagos transnacionales implica implementar lo siguiente, como mínimo:
GET /customer
&PUT /customer
puntos finales de la API KYC para solicitar y recopilar los datos KYC de los clientesGET /rate
punto final de la API RFQ para proporcionar tasas de FX entre los activos on-chain y off-chain admitidosGET /transactions
solicitudes para obtener actualizaciones sobre el estado de las transacciones de la Anchor Platform (documentación próximamente)JSON-RPC
solicitudes para actualizar los estados de las transacciones de la Anchor Platform
Lo siguiente también puede ser requerido dependiendo de tu caso de uso:
GET /fee
si tu negocio quiere proporcionar a los remitentes la opción de omitir el paso de creación de cotizacionesGET /unique_address
si tu negocio utiliza un servicio de custodia para activos on-chainDELETE /customer
si tu negocio quiere o está obligado a permitir que los remitentes soliciten la eliminación de los datos del cliente
Crear un Servidor Comercial
Primero, vamos a crear un servidor comercial y agregarlo a nuestro archivo de composición de Docker.
- YAML
version: "3.8"
services:
sep-server:
image: stellar/anchor-platform:2.11.0
command: --sep-server
env_file:
- ./dev.env
volumes:
- ./config:/home
ports:
- "8080:8080"
depends_on:
- db
platform-server:
image: stellar/anchor-platform:2.11.0
command: --platform-server
env_file:
- ./dev.env
volumes:
- ./config:/home
ports:
- "8085:8085"
depends_on:
- db
server:
build: .
ports:
- "8081:8081"
env_file:
- ./dev.env
db:
image: postgres:14
ports:
- "5432:5432"
env_file:
- ./dev.env
A continuación, crea un servidor web simple utilizando tu lenguaje de programación preferido y un Dockerfile
que inicie el servidor. docker compose up
debería iniciar correctamente los tres servicios. docker compose up
debería iniciar exitosamente los tres servicios.
Esta guía no proporciona una implementación de ejemplo de los endpoints, pero puedes encontrar más información sobre los esquemas de solicitud y respuesta en la Referencia de API de Anchor Platform, y las secciones a continuación ampliarán los conceptos importantes para entender al implementar los endpoints.
Puntos finales de Callback de Clientes
La Anchor Platform nunca almacena la PII de tus clientes, y en su lugar actúa como un servidor proxy entre las aplicaciones cliente y tu negocio, reenvíando solicitudes y respuestas a la otra parte. Actualmente, las solicitudes y respuestas son casi idénticas a las definidas en la especificación de API KYC SEP-12.
Identificar Clientes
Los clientes pueden ser identificados utilizando dos enfoques.
El primer enfoque utiliza una cuenta Stellar y un memo. Al usar la Anchor Platform para facilitar pagos transnacionales, la organización remitente utiliza su propia cuenta Stellar, la que se utilizó para autenticarse a través de SEP-10 Autenticación Stellar, al registrar clientes con tu negocio. Los memos se utilizan para distinguir a clientes únicos que provienen de la misma organización remitente.
El segundo enfoque utiliza identificadores de cliente generados por tu servicio. Por ejemplo, si una organización remitente está registrando a un cliente, tu negocio recibirá una solicitud PUT /customer
como la siguiente:
- JSON
{
"account": "GDJUOFZGW5WYBK4GIETCSSM6MTTIJ4SUMCQITPTLUWMQ6B4UIX2IEX47",
"memo": "780284017",
"type": "sep31-sender",
"first_name": "John",
"last_name": "Doe",
"email": "johndoe@example.com"
}
En este ejemplo, la clave pública GDJ...X47
identifica a la organización remitente, y el memo 780284017
identifica al cliente. Los memos suelen ser enteros de 64 bits, pero también pueden ser otros tipos de datos, por lo que deben guardarse como cadenas. En respuesta, tu negocio debe devolver un ID de cliente.
- JSON
{
"id": "fb5ddc93-1d5d-490d-ba5f-2c361cea41f7"
}
Tu servidor comercial puede usar cualquier identificador para clientes siempre que sea una cadena.
Después del registro de un cliente, la organización remitente puede usar cualquiera de los enfoques al verificar el estado del cliente. Por ejemplo, puedes recibir una solicitud GET /customer
como la siguiente:
- Ejemplo
/customer?account=GDJUOFZGW5WYBK4GIETCSSM6MTTIJ4SUMCQITPTLUWMQ6B4UIX2IEX47&memo=780284017&type=sep31-sender
O, la organización remitente podría usar el identificador que devolviste cuando originalmente registraron al cliente.
- Ejemplo
/customer?id=fb5ddc93-1d5d-490d-ba5f-2c361cea41f7&type=sep31-sender
Tu negocio deberá mantener un mapeo entre la cuenta y el memo utilizados para registrar originalmente al cliente y el ID que devolviste en la respuesta, así como los datos KYC proporcionados. En futuras iteraciones de la Anchor Platform, podríamos mantener este mapeo para tu negocio, para que solo tengas que trabajar con los ID que generas.
Tipos de Clientes
Tu negocio probablemente requiere diferentes conjuntos de información KYC dependiendo del tipo de cliente. Puedes definir las etiquetas para cada uno de estos tipos de clientes en tu archivo dev.assets.yaml
, y tus organizaciones remitentes deberán comprender qué etiqueta usar al registrar o consultar el estado de los clientes.
En las solicitudes PUT /customer
, debes usar el tipo enviado para evaluar si el remitente ha proporcionado todos los campos requeridos. En las solicitudes GET /customer
, debes usar el tipo para determinar el estado del cliente.
Prueba con la Billetera de Demostración
Puedes probar tu implementación con la Billetera de Demostración Stellar siguiendo los pasos a continuación.
- Selecciona "Generar keypair para nueva cuenta"
- Selecciona "Crear cuenta"
- Selecciona "Agregar Activo" e introduce el código del activo y el dominio principal de la Anchor Platform,
localhost:8080
- Selecciona "Agregar línea de confianza"
- Financia tu cuenta con un saldo del activo
- Selecciona "SEP-31 Enviar" en el menú desplegable
Deberías ver que la billetera de demostración encuentra las URLs de tu servicio, se autentica y verifica qué campos KYC necesita recopilar. Luego, debe mostrar un formulario para que ingreses los detalles KYC del remitente y del receptor.
Una vez que hayas ingresado la información solicitada, enviará esa información a la Anchor Platform, que la enviará a tu servidor comercial. Una vez que la billetera de demostración tenga los ID de los clientes que generaste, iniciará una transacción que debería fallar.
Punto Final de Callback de Tarifas
Una vez que la organización remitente haya registrado a los clientes involucrados en la transacción, necesitará solicitar una cotización, o tasa de FX, de tu negocio. La Anchor Platform solicita esta información a tu servidor comercial usando el GET /rate
endpoint.
Cotizaciones Firmes vs. Indicativas
Las solicitudes de cotizaciones tendrán un parámetro type
que es indicativa
o firme
. Si type=firm
, tu respuesta debe incluir el id
y el campo de fecha y hora expires_at
y reservar la liquidez necesaria para cumplir con esta cotización hasta que expire. Si type=indicative
, no devuelvas los campos id
o expires_at
porque la tasa proporcionada no se utilizará en una transacción.
Ten en cuenta que el cliente puede solicitar que la cotización expire después de una fecha y hora específicas utilizando el parámetro expires_after
. Tu negocio debe honrar esta solicitud devolviendo un valor expires_at
que esté en o después de la fecha y hora solicitadas o rechazar la solicitud con una respuesta de 400 Bad Request, que se reenviará al cliente.
Usando el ID del Cliente
Las solicitudes pueden incluir un parámetro client_id
que identifica a la organización remitente que solicita la tasa. Puedes usar este parámetro para adherirte a los términos comerciales acordados con esa organización remitente, como ofrecer tarifas con descuento. client_id
puede no estar presente para solicitudes indicativas, en cuyo caso tu precio de mercado debe ser devuelto. Actualmente, client_id
siempre será la clave pública Stellar que la organización remitente utilizó para autenticarse con la Anchor Platform.
Métodos de Entrega
Es común que las tarifas y comisiones de las empresas varíen dependiendo de los métodos de pago utilizados para enviar fondos al destinatario. Si tus métodos de entrega están configurados en tu archivo asset.yaml
, los clientes siempre proporcionarán el método de pago que quieren que tu negocio utilice para las solicitudes de cotización firmes.
Debido a que este punto final actualmente solo se utiliza para pagar remesas en activos off-chain, se utilizará buy_delivery_method
. Si este punto final se utiliza en otros flujos de transacción, como depósitos SEP-24, entonces sell_delivery_method
también puede ser pasado para negocios que soporten estos tipos de transacciones.
Actualizar las Actualizaciones de Estado de la Transacción
Para facilitar pagos transnacionales, necesitarás poder detectar cuándo una organización remitente ha enviado a tu negocio un pago on-chain y determinar qué transacción estaba destinado a cumplir.
La forma más fácil de hacerlo es ejecutar el Stellar Observer, que detectará estos pagos y actualizará el registro de transacción correspondiente con información sobre el pago. Tu negocio puede detectar estas actualizaciones sondeando el punto final de la API de la Plataforma GET /transactions
.
Ejecutando el Stellar Observer
El Stellar Observer monitorea el ledger Stellar para pagos realizados a tus cuentas y actualiza los registros de transacciones correspondientes con información de pago on-chain. Para ejecutar el observador, añade lo siguiente a tu archivo de composición de Docker.
- YAML
services:
...
observer:
image: stellar/anchor-platform:2.11.0
command: --stellar-observer
env_file:
- ./dev.env
volumes:
- ./config:/home
Sondeando Pagos Recibidos
El Stellar Observer realiza solicitudes JSON-RPC a la API de la Plataforma cada vez que detecta pagos recibidos para transacciones iniciadas por organizaciones remitentes, actualizando así la fecha y hora de transfer_received_at
de la transacción.
Tu negocio debe sondear periódicamente el punto final de la API de la Plataforma GET /transactions
para detectar estas actualizaciones. Puedes referirte al siguiente ejemplo:
- bash
curl http://localhost:8080/transactions?sep=31&order_by=transfer_received_at&order=desc
La respuesta incluirá una lista de transacciones de pagos transnacionales iniciadas por organizaciones remitentes. Esta lista estará ordenada de acuerdo con el momento en que se recibió un pago para esa transacción. Para cada transacción devuelta, tu negocio debe verificar si ya ha detectado el pago para esa transacción. Si lo ha hecho, has detectado todos los pagos realizados a tus cuentas.
Actualizar la Transacción a Través de JSON-RPC
El diagrama de flujo SEP-31 define la secuencia/reglas de la transición del estado de la transacción y un conjunto de métodos JSON-RPC que deben llamarse para cambiar ese estado. No puedes definir el estado que deseas establecer para una transacción específica en tus solicitudes. Cada método JSON-RPC define estructuras de datos que espera en la solicitud. Si la solicitud no contiene atributos requeridos, la Anchor Platform devolverá un error y no cambiará el estado de la transacción.
Los estados en verde son obligatorios y definen el flujo más corto.
Los estados en amarillo son opcionales y se pueden omitir.
Los estados en rojo significan que la transacción está en un estado de error o ha caducado.
Puedes crear una plantilla para realizar solicitudes JSON-RPC a la Anchor Platform.
Este capítulo también contiene información sobre el formato de solicitud/respuesta y códigos de error que podrían ser devueltos por la Anchor Platform.
Listo para Recibir Fondos
Las Transacciones SEP-31 deben estar inicialmente en el estado pending_sender
. El Anchor Receptor espera recibir el pago identificado por el stellar_memo incluido en la respuesta POST /transactions.
Una vez que tu negocio detecta que ha recibido un pago on-chain para una transacción específica, debe actualizar el estado de la transacción.
- JSON
// onchain-funds-received.json
[
{
"id": 1,
"jsonrpc": "2.0",
"method": "notify_onchain_funds_received",
"params": {
"transaction_id": "<transaction_id>",
"message": "Onchain funds received",
"stellar_transaction_id": "7...9",
"amount_in": {
"amount": 10
},
"amount_out": {
"amount": 9
},
"amount_fee": {
"amount": 1
}
}
}
]
Para procesar esto, necesitas ejecutar:
- bash
./call-json-rpc.sh onchain-funds-received.json
El estado de la transacción se cambiará a pending_receiver
.
Fondos Offchain Enviados
Para completar la transacción y cambiar su estado a completed
, necesitas hacer una solicitud JSON-RPC notify_offchain_funds_sent
.
- JSON
// offchain-funds-sent.json
[
{
"id": 1,
"jsonrpc": "2.0",
"method": "notify_offchain_funds_sent",
"params": {
"transaction_id": "<transaction_id>",
"message": "Offchain funds sent",
"funds_sent_at": "2023-07-04T12:34:56Z",
"external_transaction_id": "a...c"
}
}
]
Para ejecutar esto, necesitas hacer:
- bash
./call-json-rpc.sh offchain-funds-sent.json
Fondos Offchain Pendientes
Otra opción es mover el estado de la transacción a pending_external
. Este estado significa que el pago ha sido enviado a la red externa, pero aún no está confirmado.
- JSON
// offchain-funds-pending.json
[
{
"id": 1,
"jsonrpc": "2.0",
"method": "notify_offchain_funds_pending",
"params": {
"transaction_id": "<transaction_id>",
"message": "Offchain funds pending",
"external_transaction_id": "a...c"
}
}
]
Para ejecutar esto, necesitas hacer:
- bash
./call-json-rpc.sh offchain-funds-pending.json
Verificando la Información del Cliente
En algunos casos, el Anchor Receptor puede necesitar solicitar una información actualizada del Anchor Remitente. Por ejemplo, el banco le dice al Anchor Receptor que el nombre del Cliente Receptor proporcionado es incorrecto o falta un segundo nombre. Dado que esta información fue enviada a través de SEP-12, la transacción debe ir al estado pending_customer_info_update
hasta que el Anchor Remitente haga otra solicitud SEP-12 PUT /customer
para actualizar. El Anchor Remitente puede verificar qué campos necesitan actualizarse haciendo una solicitud SEP-12 GET /customer
que incluya los parámetros id o account y memo. El Anchor Receptor debe responder con un estado NEEDS_INFO
y last_name
incluido en los campos descritos.
Después de que el Anchor Remitente haga una solicitud SEP-12 PUT /customer
, llama al método JSON-RPC notify_customer_info_updated
nuevamente para actualizar el estado de la transacción. Además, llama a este método cada vez que cambie el estado SEP-12 de un cliente, como cuando se está validando la información del cliente y el estado cambia de NEEDS_INFO
a PROCESSING
. Esto asegura que cualquier cliente configurado con una URL de callback sea notificado sobre el último estado del cliente, permitiendo al cliente solicitar al usuario que actualice su información.
- JSON
// notify-customer-info-updated.json
[
{
"id": 1,
"jsonrpc": "2.0",
"method": "notify_customer_info_updated",
"params": {
"transaction_id": "<transaction_id>",
"message": "Customer info updated",
"customer_id": "45f8884d-d6e1-477f-a680-503179263359",
"customer_type": "sep31-receiver" // or sep31-sender
}
}
]
Para ejecutar esto, necesitas hacer:
- bash
./call-json-rpc.sh notify-customer-info-updated.json
Hacer un Reembolso Stellar
La integración con el servicio de custodia te permite realizar un reembolso a través del servicio de custodia, como Fireblocks.
- JSON
// do-stellar-refund.json
[
{
"id": 1,
"jsonrpc": "2.0",
"method": "do_stellar_refund",
"params": {
"transaction_id": "<transaction_id>",
"message": "Do stellar refund",
"refund": {
"amount": {
"amount": 9,
"asset": "stellar:USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5"
},
"amount_fee": {
"amount": 1,
"asset": "stellar:USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5"
}
}
}
}
]
Para ejecutar esto, necesitas hacer:
- bash
./call-json-rpc.sh do-stellar-refund.json
No puedes hacer múltiples reembolsos en el flujo SEP-31. Por esta razón, el total del monto reembolsado más la cantidad de la tarifa debería ser igual a amount_in
. De lo contrario, recibirás un error.
Reembolso Enviado
Hay posibilidad de enviar todos los fondos de vuelta al Anchor Remitente
(reembolso). Necesitas reembolsar la suma total (reembolso completo).
- JSON
// refund-sent.json
[
{
"id": 1,
"jsonrpc": "2.0",
"method": "notify_refund_sent",
"params": {
"transaction_id": "<transaction_id>",
"message": "Refund sent",
"refund": {
"id": "1c186184-09ee-486c-82a6-aa7a0ab1119c",
"amount": {
"amount": 10,
"asset": "iso4217:USD"
},
"amount_fee": {
"amount": 1,
"asset": "iso4217:USD"
}
}
}
}
]
Para ejecutar esto, necesitas hacer:
- bash
./call-json-rpc.sh refund-sent.json
No puedes hacer múltiples reembolsos en el flujo SEP-31. Por esta razón, el monto a reembolsar más la tarifa de monto debería ser igual a amount_in
. De lo contrario, recibirás un error.
Error de Transacción
Si encuentras un error irrecuperable al procesar la transacción, es necesario establecer el estado de la transacción en error
. Puedes usar el campo de mensaje para describir los detalles del error.
- JSON
// transaction-error.json
[
{
"id": 1,
"jsonrpc": "2.0",
"method": "notify_transaction_error",
"params": {
"transaction_id": "<transaction_id>",
"message": "Error occurred"
}
}
]
Para ejecutar esto, necesitas hacer:
- bash
./call-json-rpc.sh transaction-error.json
Si un usuario ha realizado una transferencia, deberías hacer una recuperación de la transacción, y luego puedes volver a procesar la transacción o iniciar un reembolso.
Transacción Caducada
Tu negocio puede querer caducar aquellas transacciones que han sido abandonadas por el usuario después de un tiempo. Es una buena práctica limpiar las transacciones inactivas en estado incompleto
. Para hacerlo, simplemente cambia el estado de la transacción a caducado
.
- JSON
// transaction-expired.json
[
{
"id": 1,
"jsonrpc": "2.0",
"method": "notify_transaction_expired",
"params": {
"transaction_id": "<transaction_id>",
"message": "Transaction expired"
}
}
]
Para procesar esto, necesitas ejecutar:
- bash
./call-json-rpc.sh transaction-expired.json
Este método JSON-RPC no se puede usar después de que el usuario ha realizado una transferencia.
Recuperación de Transacciones
El estado de la transacción puede cambiarse de error/expired
a pending-anchor
. Después de la recuperación, puedes reembolsar los activos recibidos o proceder con el procesamiento de la transacción. Para recuperar la transacción, es necesario hacer la siguiente solicitud JSON-RPC:
- JSON
// transaction-recovery.json
[
{
"id": 1,
"jsonrpc": "2.0",
"method": "notify_transaction_recovery",
"params": {
"transaction_id": "<transaction_id>",
"message": "Transaction recovered"
}
}
]
Para procesar esto, necesitas ejecutar:
- bash
./call-json-rpc.sh transaction-recovery.json
Endpoint de Callback de Tarifas
Tu negocio puede querer ofrecer a las organizaciones emisoras la opción de omitir el proceso de creación de cotizaciones, permitiendo a tu negocio usar una tarifa determinada en el momento en que los fondos se pagan al destinatario. En este caso, la Anchor Platform no hará una solicitud GET /rate
, pero aún deberás proporcionar la tarifa que tu negocio cobrará por estos tipos de transacciones utilizando el endpoint GET /fee
.
Configuración
Puedes habilitar estos tipos de transacciones actualizando la configuración de tu archivo assets.yaml
:
- YAML
assets:
- ...
sep31:
quotes_required: false
Endpoint de Callback de Dirección Única
Las empresas deben proporcionar un par de cuenta Stellar y memo únicos para cada transacción solicitada por las organizaciones emisoras para que la Anchor Platform pueda identificar y mapear el pago on-chain enviado para la transacción específica. La Anchor Platform puede generar estos pares de cuenta y memo por sí misma, pero la mayoría de las empresas utilizan un servicio de custodia para recibir pagos on-chain. En este caso, la empresa deberá solicitar al custodio que genere la cuenta Stellar y el memo. Esto se realiza utilizando el endpoint GET /unique_address
.
Configuración
Para configurar la Anchor Platform para realizar estas solicitudes, agrega lo siguiente a tu configuración:
- bash
# dev.env
SEP31_DEPOSIT_INFO_GENERATOR_TYPE=api
Este endpoint podría eliminarse durante futuras actualizaciones importantes de la versión de la Anchor Platform, cuando añada soporte para conectarse a servicios de custodia y generar estas direcciones automáticamente.