---
# System prepended metadata

title: Distribuição de payins/payouts

---

# Distribuição de payins/payouts

## Contexto
### Motivação
Sempre que uma instituição falha temos que manualmente checar qual instituição está ativa e trocar automaticamente.
Precisamos automatizar esse processo para que todos possam **dormir em paz**.

### Objetivo
 - Detecção instânanea de erros nas instituições bancárias
 - Chaveamento de instituições de acordo com ordem de prioridade escolhida


## Proposta

### Novas aplicações: 
`transferocaas-banking-service`
`transferocaas-adapters-monitor-service`
`transferocaas-pix-bucket`

### Funcionalidades:
> - API para comunição síncrona com os adapters
    - Geração de QRCode
    - Consulta de saldo
    - Comprovantes
>- Background Services / Azure Functions
    - PixPaymentBucket
    - AdaptersHealthMonitor

### Discussões/Decisões Técnicas
### 1. Como compartilhar status dos adapters para todas as aplicações interessadas?
> **Opções:** 
> - **Usar cache compartilhado *(Azure Cache for Redis)***
    > **Solução**: 
    A cada mudança de status, será guardado o status na cache. Assim qualquer nó de qualquer aplicação interessada nesse status imediatamente terá a informação do status atual do adapter.
    > **PROS**
    - Todos os serviços sempre terão a mesma informação, de forma sincronizada.
    - Apenas um acesso Read-Only será necessário nos serviços.
    > **CONS**
    - Custo Adicional (R$ 200/mês aprox.)
    - 
> - **Publicar toda mudança de status em um tópico *(Topic/Azure ServiceBus)***
    > **Solução**: 
    A cada mudança de status, será publicado uma nova mensagem no tópico. Cada aplicação interessada terá uma subscription e deverá consumir e cachear esse status da melhor maneira.
    > **PROS**
    - Integração assíncrona entre os serviços/informação.
    - Sem custo adicional.
    > **CONS**
    - Para aplicação com multiplos nós, apenas um consumirá o tópico. Logo causará dessincronia de informação entre os nós de um mesmo serviço.
    - Implementação customizada para cada serviço interessado.
    - 
> - **HTTP Request para pegar o status atual de cada adapter**
    > **Solução**: 
    Sempre que uma aplicação se interessar no status atual do adapter, ela fará um request para o serviço de monitoramento e conseguirá essa informação de forma síncrona. E, a fim de dimuinuir o consumo, a aplicação cacheará o retorno do status do adapter.
    > **PROS**
    - Implementação simples (apenas um novo request)
    - Sem custo adicional.
    > **CONS**
    - Dessincronização de informação. Um adapter pode mudar de status e o serviço só ficar sabendo após sua cache interna expirar.
    - Alto consumo de recursos se não tiver cache.

> **Decisão:** Usar cache compartilhado *(Azure Cache for Redis)*

### Dependências
> - CosmosDB 
     - openbanking (somente Account)
     - caas-adapters-health **(new)**
     - pix-payment-bucket **(new)**
> - Azure Service Bus 
    - payment-bucket-queue **(new)**
    - caas-adapters-monitor-queue **(new)**
    - ~~caas-adapters-health **(new) (topic)**~~ 
> - Azure Redis for cache ([see](https://docs.microsoft.com/en-us/azure/azure-cache-for-redis/cache-dotnet-core-quickstart))
    - caas-adapters-status **(new)**
> - Banking Adapters (Genial, Stone, BS2, BIND, Frick)

### Aplicações impactadas
> - openbanking-api
> - payment-processor


# Fluxos
## 1. Banking Service API

### O que é?
> Nova API onde ficará centralizada toda a lógica realicionada a Banking, comum a todos os adapters de moedas FIAT.
> A idéia é tirar toda lógica relacionada à esses adapters de dentro da *openbanking-api* e centralizar nesse serviço

### Fluxo proposto
Todo o fluxo no openbanking-api que chama os adapters síncronamente (via HTTP Request) deverão passar por essa nova API. 

Os fluxos são:
- Criação de QR Code Dinâmico
- Consulta de Saldo
- Geração de comprovante
- Cadastro de novas contas para monitoramento

## 2. Adapters Health Monitoring

### O que é?
>Sistema de monitoramento que acompanha a *saúde* dos adapters bancários.
>A idéia é implementarmos um serviço que consuma os mensagens de todos os adapters, trate e repasse essa informação a todos os serviços afetados.

### Definições
A disponibilidade do adapter será avaliada em dois fluxos:
- **Deposit**: fluxo de pay-in (geração de QR Code)
- **Payment**: fluxo de pay-out (envio de pagamentos)

Que poderão ter os seguintes estados:
- <span style="color:gray">**Out**</span>: Adapter fora de operação *(configurado manualmente)*.
- <span style="color:red">**Suspended**</span>: Adapter com operação suspensa devido a falha.
- <span style="color:chocolate">**PartiallySuspended**</span>: Adapter funcionando porém pode apresentar falhas.
- <span style="color:green">**Healthy**</span>: Adapter funcionando.

onde:
- Os estados <span style="color:red">**Suspended**</span> e <span style="color:chocolate">**PartiallySuspended**</span> DEVEM POSSUIR um tempo de expiração.
- Ao expirar, será aplicado a seguintes lógica de *recovery*:
    - <span style="color:red">**Suspended**</span> **-->** <span style="color:chocolate">**PartiallySuspended**</span>, com o mesmo tempo expiração.
    - <span style="color:chocolate">**PartiallySuspended**</span> **-->** <span style="color:green">**Healthy**</span>, sem tempo de expiração


### Fluxo proposto
1. Todas as chamadas à API externas possuirão alertas configurados **(App Insights)**.
2. Para cada adapter, serão definidas as regras para que um alerta seja triggado e dispare um webhook para ***transferocaas-adapters-monitor-service***.
    Esse alerta poderá ser dos seguintes tipos:
    - Critical
    - High
    - Medium
3. Cada webhook recebido é mapeado para um modelo definido e publicado na fila ***caas-adapters-monitor-queue***.

4. O serviço ***transferocaas-adapters-monitor-service*** consumirá todas as mensagens dessa fila e salvará no Cosmos DB (nova collection).

5. Cada nova entrada no banco disparará uma função para mudar o status do adapter, com as seguintes regras:
    - Para mensagens **Critical** -> mudar para status **Suspended** por 30 min.
    - Para mensagens **High** -> mudar para status **Suspended** por 10 min.
    - Para mensagens **Medium** -> mudar para status **PartiallySuspended** por 10 min.

6. Persisitir o novo AdapterStatus no CosmosDB.
7. Persisitir o novo AdapterStatus no Redis Cache.
    ```
    key: Stone
    value: {
        "Deposit": "Suspended",
        "Payment": "Suspended"
    }
    expires_in: 12h
    ```
8. **A cada 5 minutos**, disparar um serviço será disparado para executar a lógica de *recovery*.

## 3. QR Code distributed creation
### O que é?
> No fluxo de criação de QR Code dinâmicos para pay-in, a aplicação poderá distribuir o payout nas seguintes condições:
> - Account configurada para distribuir pay-in em mais de uma instituição
> - Adapter configurado para receber pay-in não está ativo.

### Fluxo proposto

1. O documento de Account terá uma nova propriedade
    ```
    {
        //propriedade atual
        "AccountTypesPayIn": { 
            "{Blockchain}": {paymentGroupType}
        },

        //nova propriedade
        "PayInConfiguration": { 
            "{Blockchain}": [
                {
                    "Adapter": "{paymentGroupType}", //adapter configurado
                    "Priority": 1, //prioridade de uso
                    "Probability": 0.7 //prob. para distribuição ativa 
                },
                {
                    "Adapter": "{paymentGroupType}",
                    "Priority": 2,//prioridade de uso
                    "Probability": 0.3 //prob. para distribuição ativa 
                },
                {
                    "Adapter": "{paymentGroupType}",
                    "Priority": 3, //prioridade de uso - usada somente se os outros falharem
                    "Probability": 0.0 //prob. para distribuição ativa 
                }
            ]
        },
    }
    ```
2. Quando a API solicitar a criação de um novo QR Code, será escolhido aleatóriamente o adapter para ser criado (levando em conta a probabilidade configurada.)
3. Caso o adapter escolhido esteja indisponível ([ref](#2-Adapters-Health-Monitoring)) ou falhe na criação, o adapter de maior prioridade será usado para gerar.
4. Caso todos os adapters configurados estejam indisponíveis ou falhem, será retornado erro.
## 4. Payment Distribution
### O que é?
> No fluxo de criação de enviar pagamentos para os adapters, o payment-processor poderá distribuir o payout nas seguintes condições:
> - Account configurada para distribuir pagamentos em mais de uma instituição
> - Adapter configurado para receber pagamentos não está ativo.

### Fluxo proposto

1. O documento de Account terá uma nova propriedade
    ```
    {
        //propriedade atual
        "AccountTypesPayOut": { 
            "{Blockchain}": {paymentGroupType}
        },

        //nova propriedade
        "PayOutConfiguration": { 
            "{Blockchain}": [
                {
                    "Adapter": "{paymentGroupType}", //adapter configurado
                    "Priority": 1, //prioridade de uso
                    "Probability": 1.0 //prob. para distribuição ativa 
                },
                {
                    "Adapter": "{paymentGroupType}",
                    "Priority": 2,//prioridade de uso
                    "Probability": 0.0 //prob. para distribuição ativa 
                },
                {
                    "Adapter": "{paymentGroupType}",
                    "Priority": 3, //prioridade de uso - usada somente se os outros falharem
                    "Probability": 0.0 //prob. para distribuição ativa 
                }
            ]
        },
    }
    ```
2. Quando um pagamento for aprovado, será escolhido aleatóriamente o adapter para ele ser enviado (levando em conta a probabilidade configurada.)
3. Caso o adapter escolhido esteja indisponível ([ref](#2-Adapters-Health-Monitoring)) o pagamento será enviado para o próximo adapter de maior prioridade.
4. Caso todos os adapters configurados estejam indisponíveis, o payment não será processado e entrará num fluxo de espera até algum adapter esteja disponível.

## 5. Pix Payment Bucket (PPB)

#### O que é?
>O sistema PIX conta com uma política de proteção usando o conhecido algoritmo de [token bucket](https://en.wikipedia.org/wiki/Token_bucket).
>A idéia é implementarmos o mesmo algoritmo do nosso lado para que seja possível prever e atuar nos erros antes mesmo que ele aconteça.

#### Fluxo de pagamentos FIAT (já implementado)
>Todo pagamento Pix segue o seguinte fluxo dentro dos adapters:
>1. Payment recebido do CaaS via fila e cadastrado no DB com status **pending**.
>2. A API do banco é chamada para consultar a chave PIX informada no payment. Após isso temos três cenários possíveis:
    2.1. **Chave PIX não existe:**
    2.2. **Conta de destino não pertence ao taxId informado:** 
    2.3. **Conta de destina válida** 
>:::info
>:pushpin: Nos cenários 2.1 e 2.2, mudamos o status do payment diretamente para **processedWithError**.
>:::
>3. A API do banco é chamada novamente para iniciar o pagamento.
>4. Esperamos via webhook/polling a confirmação do pagamento.
>5. Depois de confirmado (erro ou sucesso), noticamos o CaaS.

#### Fluxo Proposto do PPB
>1. Toda instituição terá um balde com capacidade máxima (e inicial) de 2.000 fichas. 
>
>No cenário de hoje teremos:
> | Instituição       | Capacidade (Max)|
> | ----------------- |:---------- |
> | Stone JUST        | 2000       |
> | Stone 3RZ         | 2000       |
> | BS2 JUST          | 2000       |
> | BS2 3RZ           | 2000       |
> | Genial            | 2000       |
>2. Todo resultado de **consulta de chave pix** *(item 2 acima)* é notificado à fila ***payment-bucket-queue***.
>3. Todo pagamento **confirmado** *(item 5 acima)* é notificado à fila ***payment-bucket-queue***.
>4. O BackgroundService do PPB consome ativamente a fila ***payment-bucket-queue*** e cada mensagem afeta o número de fichas na seguinte forma:
    - **Consulta de chave Pix válida:** <span style="color:red">**-2 fichas**</span>
    - **Consulta de chave Pix inválida:** <span style="color:red">**-10 fichas**</span>
    - **Pagamento confirmado:** <span style="color:blue">**+2 fichas**</span>
>5. O balde também possuirá um incrementador recorrente de fichas com <span style="color:blue">**2 fichas/minuto**</span>.
>6. Cada balde terá os seguintes limites de operação configuráveis:
    - **Limite de atenção (Lo)** -> Ativa status de ***Atenção*** / Inativa status de ***Suspensão de operação***.
    - **Limite crítico (LoLo)** -> Ativa status de ***Suspensão de operação***.
E, toda vez que a quantidade de fichas no balde ultrapassar esses limites uma mensagem de status será disparado na fila ***caas-adapters-monitor-queue***.

