Contrato de transporte
| Campo | Valor |
|---|---|
ce-source | plugin-br-bank-transfer |
| Tópico | lerian.streaming.plugin-br-bank-transfer |
ce-type | studio.lerian.plugin-br-bank-transfer.<event-key> |
| Versión del schema | Por evento, en el catálogo de abajo |
| Content type | application/json |
ce-subject | El id de la transferencia. payment_initiation.created lleva el id de la iniciación, y transfer_incoming.undeliverable lleva su jdIncomingMessageId |
ce-tenantid | Tu tenant, en el modo multi-tenant |
| Entrega | Por el outbox de PostgreSQL. El relay del outbox es el único publisher del broker |
| Manifiesto en runtime | GET /streaming/manifest |
STREAMING_ENABLED=true y las variables de streaming. Con el streaming desactivado, el plugin descarta los eventos. Si defines STREAMING_CLOUDEVENTS_SOURCE, su valor debe ser exactamente plugin-br-bank-transfer. En producción, el plugin sirve el manifiesto solo cuando la autenticación está activada.
Algunos eventos son de mejor esfuerzo: cuando su escritura en el outbox falla, el plugin mantiene el cambio que anuncian y no publica el evento. Si un evento esperado no llega, lee la transferencia con Get Transfer.
Catálogo de eventos
Iniciación y ciclo de vida de la transferencia
| Clave del evento | Schema | Se dispara cuando |
|---|---|---|
payment_initiation.created | 1.0.0 | Initiate Transfer creó una iniciación, antes de su confirmación. |
transfer.initiated | 1.0.0 | El plugin creó una transferencia TED OUT o TED entre cores a partir de una iniciación confirmada. |
transfer.processing_started | 1.0.0 | Una TED OUT entró en procesamiento (CREATED a PENDING a PROCESSING). |
transfer.completed | 1.2.0 | Una TED OUT, un P2P o una TED entre cores se completó. Para una TED OUT, el STR la liquidó, o un operador la liquidó manualmente. Para una TED entre cores, el otro core acreditó al destinatario. |
transfer.rejected | 1.1.0 | Una TED OUT o una TED entre cores se rechazó, y su retención se canceló. Para una TED OUT, JD la rechazó en el envío, o el STR rechazó la liquidación. Para una TED entre cores, el otro core rechazó el crédito, o JD Courier no alcanzó a ningún destinatario. |
Conciliación
| Clave del evento | Schema | Se dispara cuando |
|---|---|---|
transfer.reconciliation_required | 1.0.0 | Una TED OUT con resultado desconocido pasó a conciliación. |
transfer.reconciliation_resolved | 1.5.0 | El worker de conciliación o un operador resolvió una transferencia. |
transfer.reconciliation_exhausted | 1.1.0 | El worker de conciliación se detuvo después del número máximo de intentos y pasó la transferencia a revisión manual. |
transfer.reconciliation_failed | 1.0.0 | El worker de conciliación falló una TED OUT por un error determinista. |
transfer.reconciliation_manual_retry_requested | 1.0.0 | Un operador devolvió una TED OUT de la revisión manual a la cola de conciliación. |
transfer.scope_repaired | 1.0.0 | Un operador corrigió el ledger en el que está registrada una transferencia. No se movió dinero. |
Transferencias entrantes
| Clave del evento | Schema | Se dispara cuando |
|---|---|---|
transfer_incoming.completed | 1.0.0 | El plugin acreditó una TED IN o un crédito al cliente, o registró un crédito o una devolución entre cores del otro core (transferType CROSS_CORE_IN). |
transfer_incoming.chargeback | 1.1.0 | Una TED IN completada falló por un chargeback STR0010R2. Lo envía el worker de TED IN, y también un operador que cierra manualmente un chargeback estacionado. |
transfer_incoming.undeliverable | 1.0.0 | El plugin registró un crédito entrante que no pudo entregar. |
transfer_incoming.return_requested | 1.0.0 | La devolución de una TED IN entró en procesamiento: la retención está puesta, y el STR0010 está por enviarse. |
transfer_incoming.returned | 1.0.0 | El STR liquidó la devolución de una TED IN, y el crédito original se revirtió. |
transfer_incoming.return_rejected | 1.0.0 | La devolución de una TED IN se rechazó, y su retención se canceló. |
transfer_incoming.return_manual_review | 1.0.0 | La devolución de una TED IN espera a un operador. |
Devoluciones de TED OUT y de P2P
| Clave del evento | Schema | Se dispara cuando |
|---|---|---|
transfer_outgoing.devolution_notified | 1.1.0 | El plugin registró una devolución (STR0010R2) de una TED OUT en la transferencia original. |
transfer_internal.returned | 1.0.0 | La devolución de un P2P se completó, y el ledger revirtió la transacción original. |
transfer_internal.return_failed | 1.0.0 | El ledger rechazó la devolución de un P2P. No se movió nada, y el P2P puede devolverse otra vez. |
Deduplicación
Deduplica por(ce-source, ce-id) y mantén los consumidores idempotentes. Dos eventos también necesitan una clave de negocio:
transfer_incoming.chargeback: el worker de TED IN y un operador pueden anunciar cada uno el mismo chargeback, con dos ids. Deduplica portenantId,transferIdystatus.transfer.reconciliation_resolved: una resolución de operador puede llegar dos veces.convergedOntoExistingResolutionmarca la copia que encontró la resolución ya escrita. Deduplica portenantId,transferId,statusyreconciliationStatus, no por ese marcador.
Contratos de payload
Los montos son strings decimales, por ejemplo"1500.00". Los timestamps son strings RFC 3339 en UTC. Los campos marcados con ? son opcionales. tenantId queda vacío en el modo single-tenant.
// payment_initiation.created
interface PaymentInitiationCreated {
paymentInitiationId: string
tenantId: string
organizationId?: string
ledgerId: string
senderAccountId: string
recipientAccountId?: string
recipientIspb: string
amount: string
feeAmount: string
totalAmount: string
transferType: string
status: string
purpose?: string
expiresAt: string
createdAt: string
}
// transfer.initiated
interface TransferInitiated {
transferId: string
paymentInitiationId: string
tenantId: string
organizationId?: string
ledgerId: string
senderAccountId: string
recipientAccountId?: string
amount: string
feeAmount: string
totalAmount: string
transferType: string
status: string
confirmationNumber: string
controlNumber: string
midazTransactionId?: string
signingArtifactId?: string
createdAt: string
}
// transfer.processing_started
interface TransferProcessingStarted {
transferId: string
tenantId: string
transferType: string
status: string
controlNumber: string
statusPath: string
processingStartedAt: string
}
// transfer.completed
interface TransferCompleted {
transferId: string
initiationId: string
tenantId: string
organizationId?: string
ledgerId: string // on a P2P between ledgers, the payer's ledger
senderAccountId: string
recipientAccountId?: string
midazTransactionId: string
confirmationNumber: string
status: string
transferType: string // TED_OUT, P2P, or CROSS_CORE
amount: string
feeAmount: string
totalAmount: string
packageAppliedId?: string
completedAt: string
// TED OUT only
source?: "str0008r1" | "reconciliation" | "manual"
controlNumber?: string
clearingControlNumber?: string
messageSequence?: string
settledAt?: string
// P2P between ledgers only
recipientLedgerId?: string
ledgerGroupId?: string
}
// transfer.rejected
interface TransferRejected {
transferId: string
tenantId: string
transferType: string // TED_OUT or CROSS_CORE
status: string
failureCode: string // BTF-4005 on a cross-core TED
failureMessage: string
errorCategory: string
midazCancelled: boolean
midazTransactionId?: string
rejectedAt: string
// TED OUT only
source?: "dispatch" | "str0008r1" | "reconciliation"
rejectedBy?: "jd" | "bacen"
settlementRejectionCode?: string
controlNumber?: string
clearingControlNumber?: string
messageSequence?: string
}
// transfer.reconciliation_required
interface TransferReconciliationRequired {
transferId: string
tenantId: string
transferType: string
status: string
reconciliationStatus: string
controlNumber?: string
counterpartySystem: string
failureClass: string
failureCode: string
errorCategory: string
reason: string
reconciliationEnqueuedAt: string
}
// transfer.reconciliation_resolved
interface TransferReconciliationResolved {
transferId: string
tenantId: string
status: string
transferType: string
reconciliationStatus: string
resolution: string
reasonCategory: string
attempts: number
jdResponseCode?: string
controlNumber?: string
jdSequenceNumber?: string
clearingControlNumber?: string
// operator resolution only
actor?: string
operatorReason?: string
evidenceReference?: string
convergedOntoExistingResolution?: boolean
resolutionAuthorizedBy?: string
// resolution manual_repost only
previousCompensationTransactionId?: string
compensationTransactionId?: string
}
// transfer.reconciliation_exhausted
interface TransferReconciliationExhausted {
transferId: string
tenantId: string
status: string
transferType: string
reconciliationStatus: string
resolution: string
reasonCategory: string
attempts: number
maxAttempts: number
holdPreserved: boolean
jdResponseCode?: string
controlNumber?: string
jdSequenceNumber?: string
}
// transfer.reconciliation_failed
interface TransferReconciliationFailed {
transferId: string
tenantId: string
status: string
reconciliationStatus: string
resolution: string
reasonCategory: string
attempts: number
errorCategory: string
jdResponseCode?: string
controlNumber?: string
jdSequenceNumber?: string
}
// transfer.reconciliation_manual_retry_requested
interface TransferReconciliationManualRetryRequested {
transferId: string
tenantId: string
status: string
transferType: string
reconciliationStatus: string
operatorReason: string
previousAttempts: number
requestId?: string
requeuedAt: string
}
// transfer.scope_repaired
interface TransferScopeRepaired {
transferId: string
tenantId: string
ledgerId: string
status: string
transferType: string
actor: string
operatorReason: string
evidenceReference?: string
requestId?: string
repairedAt: string
}
// transfer_incoming.completed
interface TransferIncomingCompleted {
transferId: string
tenantId: string
status: string
transferType: string // TED_IN, TED_IN_STR0005 to TED_IN_STR0051, or CROSS_CORE_IN
amount: string
feeAmount: string
grossAmount: string
controlNumber: string // empty on CROSS_CORE_IN
messageSequence: string // empty on CROSS_CORE_IN
repairedBy: string
}
// transfer_incoming.chargeback
interface TransferIncomingChargeback {
transferId: string
tenantId: string
status: string
transferType: string
// absent when an operator closes the chargeback
chargebackCode?: string
messageSequence?: string
controlNumber?: string
}
// transfer_incoming.undeliverable
interface TransferIncomingUndeliverable {
undeliverableId: string
tenantId: string
jdIncomingMessageId: string
rejectionReason: string
rejectionCategory: string
controlNumber: string
messageSequence: string
grossAmount: string
senderISPB: string
}
// transfer_incoming.return_requested, returned, return_rejected, return_manual_review
interface TransferIncomingReturn {
transferId: string // the return, a TED_OUT
originalTransferId: string // the TED IN that it returns
tenantId: string
organizationId?: string
transferType: string
status: string
controlNumber: string
amount: string // the gross amount that leaves your institution
returnReasonCode: string
requestedVia: string
externalReference?: string
clearingControlNumber?: string
reversalTransactionId?: string
reconciliationReasonCode?: string
reconciliationReasonClass?: string
revertFailureClass?: string
failureCode?: string
rejectionCause?: "not_found" | "str_refused" | "jd_refused" | "local_verdict" | "operator"
occurredAt: string
}
// transfer_outgoing.devolution_notified
interface TransferOutgoingDevolutionNotified {
transferId: string
tenantId: string
codDevTransf: string
chargebackCode: string
senderISPB: string
recipientISPB: string
amount: string
controlNumber: string
transferStatus: string
transferType: string
feeRetained: boolean
feeRefunded: boolean
feeRefundedAmount?: string
via: string
}
// transfer_internal.returned, return_failed
interface TransferInternalReturn {
transferId: string // the return, a P2P
originalTransferId: string
tenantId: string
organizationId: string
ledgerId: string // the ledger of the debited account
recipientLedgerId?: string // between ledgers only: the ledger of the credited account
amount: string
reversalTransactionId?: string
requestedVia: string
revertFailureClass?: string
failureCode?: string
occurredAt: string
}

