Transferência Pix a partir de uma chave

Pré requisitos para implementação:

  • Possuir uma chave api da Celcoin, para mais informações acessar esse link

  • Ter familiaridade com apis Rest usando o protocolo OAuth 2.0.

  • Ter o produto/solução contratada, caso queira usar a funcionalidade em ambiente produtivo, por favor entre em contato com a nossa equipe comercial através do e-mail [email protected]. Para dúvidas técnicas, basta entrar em contato com o suporte através do link.

Essa funcionalidade deve ser utilizada sempre que sua aplicação receber uma chave Pix de um usuário, desta forma o caso de uso poderia ser:

Como Fintech quero disponibilizar para os meus usuários a possibilidade de realizar transferências Pix para qualquer instituição financeira, uma vez que ele informa as chaves do recebedor(pessoa física ou jurídica), onde será retirado o saldo de sua conta e enviado para a conta do recebedor.

Consulta chave Pix no DICT

Para realizar uma transferência com uma chave Pix é necessário realizar uma consulta no DICT, através da API Retornar informações do DICT utilizando uma chave cadastrada no Pix, onde será retornado algumas informações que são obrigatórias ao realizar uma transferência, desta forma, sua aplicação deve disponibilizar para o usuário a possibilidade de informar para qual chave Pix ele deseja realizar a transferência. Essa chave pode ser um e-mail, CPF, CNPJ, telefone, ou uma chave aleatória.

O campo payerId é obrigatório devido a uma solicitação do banco central e deve ser preenchido com um CPF, ou CNPJ, sem os caracteres especiais, da sua instituição. Para testar essa consulta em sandbox recomendamos o uso da propriedade key populada com o valor [email protected], pois nosso ambiente está preparado para retornar essa consulta com esse e-mail.

Modelo de request :

curl --location --request POST 'https://sandbox.openfinance.celcoin.dev/pix/v1/dict/v2/key' \
--header 'accept: application/json' \
--header 'Content-Type: application/json-patch+json' \
--header 'Authorization: Bearer {access_token}' \
--header 'includeStatistics: true/false' \
--data-raw '{
  "payerId": "11223344556",
  "key": "[email protected]"
}'

Modelo de retorno:

{
    "key": "02194426140",
    "keyType": "CPF",
    "account": {
        "branch": 1,
        "accountNumber": "154660617",
        "accountType": "TRAN",
        "participant": "08561701",
        "openingDate": "2020-10-25T08:07:39.000Z"
    },
    "owner": {
        "type": "NATURAL_PERSON",
        "taxIdNumber": "02194426140",
        "name": "Fulano de Tal"
    },
    "endtoendid": "E13975893902312192056OacN253q7G9",
    "creationDate": "2020-10-26T12:35:48.926Z",
    "keyOwnershipDate": "2020-10-26T12:35:48.921Z",
    "statistics": {
        "keyStatistics": {
            "spi": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "settlements": {
                    "d90": 44,
                    "m12": 44,
                    "m60": 88
                }
            },
            "fraudMarkers": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "applicationFrauds": {
                    "d90": 76,
                    "m12": 13,
                    "m60": 4
                },
                "muleAccounts": {
                    "d90": 39,
                    "m12": 78,
                    "m60": 15
                },
                "scammerAccounts": {
                    "d90": 12,
                    "m12": 16,
                    "m60": 18
                },
                "otherFrauds": {
                    "d90": 6,
                    "m12": 55,
                    "m60": 75
                },
                "unknownFrauds": {
                    "d90": 16,
                    "m12": 98,
                    "m60": 7
                },
                "totalFraudTransactionAmount": {
                    "d90": 94,
                    "m12": 91,
                    "m60": 44
                },
                "distinctFraudReporters": {
                    "d90": 72,
                    "m12": 16,
                    "m60": 38
                }
            },
            "infractionReports": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "rejectedReports": {
                    "d90": 84,
                    "m12": 48,
                    "m60": 69
                },
                "openReports": 39,
                "openReportsDistinctReporters": 97
            },
            "entries": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "distinctAccounts": {
                    "d90": 48,
                    "m12": 30,
                    "m60": 19
                }
            }
        },
        "ownerStatistics": {
            "spi": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "settlements": {
                    "d90": 8,
                    "m12": 31,
                    "m60": 55
                }
            },
            "fraudMarkers": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "applicationFrauds": {
                    "d90": 13,
                    "m12": 84,
                    "m60": 99
                },
                "muleAccounts": {
                    "d90": 43,
                    "m12": 53,
                    "m60": 11
                },
                "scammerAccounts": {
                    "d90": 96,
                    "m12": 30,
                    "m60": 93
                },
                "otherFrauds": {
                    "d90": 19,
                    "m12": 75,
                    "m60": 91
                },
                "unknownFrauds": {
                    "d90": 84,
                    "m12": 1,
                    "m60": 83
                },
                "totalFraudTransactionAmount": {
                    "d90": 62,
                    "m12": 21,
                    "m60": 96
                },
                "distinctFraudReporters": {
                    "d90": 25,
                    "m12": 71,
                    "m60": 72
                }
            },
            "infractionReports": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "rejectedReports": {
                    "d90": 38,
                    "m12": 99,
                    "m60": 8
                },
                "openReports": 65,
                "openReportsDistinctReporters": 32
            },
            "entries": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "registeredAccounts": 62
            }
        }
    }
}{
    "key": "02194426140",
    "keyType": "CPF",
    "account": {
        "branch": 1,
        "accountNumber": "154660617",
        "accountType": "TRAN",
        "participant": "08561701",
        "openingDate": "2020-10-25T08:07:39.000Z"
    },
    "owner": {
        "type": "NATURAL_PERSON",
        "taxIdNumber": "02194426140",
        "name": "Bruno Jefferson Menezes"
    },
    "endtoendid": "E13935893202312122056OOcN253q7G9",
    "creationDate": "2020-10-26T12:35:48.926Z",
    "keyOwnershipDate": "2020-10-26T12:35:48.921Z",
    "statistics": {
        "keyStatistics": {
            "spi": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "settlements": {
                    "d90": 44,
                    "m12": 44,
                    "m60": 88
                }
            },
            "fraudMarkers": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "applicationFrauds": {
                    "d90": 76,
                    "m12": 13,
                    "m60": 4
                },
                "muleAccounts": {
                    "d90": 39,
                    "m12": 78,
                    "m60": 15
                },
                "scammerAccounts": {
                    "d90": 12,
                    "m12": 16,
                    "m60": 18
                },
                "otherFrauds": {
                    "d90": 6,
                    "m12": 55,
                    "m60": 75
                },
                "unknownFrauds": {
                    "d90": 16,
                    "m12": 98,
                    "m60": 7
                },
                "totalFraudTransactionAmount": {
                    "d90": 94,
                    "m12": 91,
                    "m60": 44
                },
                "distinctFraudReporters": {
                    "d90": 72,
                    "m12": 16,
                    "m60": 38
                }
            },
            "infractionReports": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "rejectedReports": {
                    "d90": 84,
                    "m12": 48,
                    "m60": 69
                },
                "openReports": 39,
                "openReportsDistinctReporters": 97
            },
            "entries": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "distinctAccounts": {
                    "d90": 48,
                    "m12": 30,
                    "m60": 19
                }
            }
        },
        "ownerStatistics": {
            "spi": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "settlements": {
                    "d90": 8,
                    "m12": 31,
                    "m60": 55
                }
            },
            "fraudMarkers": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "applicationFrauds": {
                    "d90": 13,
                    "m12": 84,
                    "m60": 99
                },
                "muleAccounts": {
                    "d90": 43,
                    "m12": 53,
                    "m60": 11
                },
                "scammerAccounts": {
                    "d90": 96,
                    "m12": 30,
                    "m60": 93
                },
                "otherFrauds": {
                    "d90": 19,
                    "m12": 75,
                    "m60": 91
                },
                "unknownFrauds": {
                    "d90": 84,
                    "m12": 1,
                    "m60": 83
                },
                "totalFraudTransactionAmount": {
                    "d90": 62,
                    "m12": 21,
                    "m60": 96
                },
                "distinctFraudReporters": {
                    "d90": 25,
                    "m12": 71,
                    "m60": 72
                }
            },
            "infractionReports": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "rejectedReports": {
                    "d90": 38,
                    "m12": 99,
                    "m60": 8
                },
                "openReports": 65,
                "openReportsDistinctReporters": 32
            },
            "entries": {
                "watermark": "2023-01-01T10:00:00.000Z",
                "registeredAccounts": 62
            }
        }
    }
}

Note que no retorno é apresentado no objeto account nas propriedades branch(agência), accountNumber(número da conta), accountType(tipo da conta), os dados bancários da chave que foi consultada, no caso de uma pessoa física, ou empresa que irá receber a transferência. A propriedade participant representa o código da instituição financeira participante no ISPB (Instituição de Sistema de Pagamentos Brasileiros), ou seja, para onde será enviado o dinheiro.

No objeto owner será apresentado informações sobre o dono da chave, como taxIdNumber(tipo do documento CPF, ou CNPJ), type(tipo de pessoa), sendo LEGAL_PERSON(pessoa jurídica) e NATURAL_PERSON (pessoa física) e name(o nome do dono).

Na sequência, é apresentada a propriedade endtoendid, que é um Identificador de ponta a ponta do Pix. Sempre que houver uma consulta ao DICT anterior ao envio de uma transação (pagamentos de QR Codes e transferências para chave), o endtoendid enviado na ordem de pagamento DEVE ser o mesmo recebido na resposta à consulta DICT.

Continuando, ainda serão retornados os parâmetros creationDate, keyOwnershipDate, responseTime e openClaimCreationDate, que são as datas e horários de criação, de vinculação da chave com a conta atual, da resposta da consulta e do início do processo de portabilidade (quando aplicável), respectivamente.

🚧

Sistema de Balde e Fichas

Esse endpoint adota um “sistema de baldes e fichas" em conformidade com o Manual Operacional do DICT (seção 13: “mecanismos de prevenção a ataques de leitura”).

O objetivo da política de baldes e fichas é garantir o uso adequado e equilibrado da API do DICT, evitando sobrecarga no sistema e protegendo a segurança e a privacidade das informações dos clientes bancários. É importante que os parceiros respeitem as limitações impostas pelo Banco Central para evitar a interrupção da operação ou o cancelamento do acesso à API.

Esse mecanismo é utilizado para controlar o número de consultas que podem ser feitas em um determinado intervalo de tempo e funcionará da seguinte maneira:

  • O parceiro possuirá um balde com 1000 fichas, que poderão ser usadas para consultar chaves Pix no DICT, com o objetivo de iniciar uma transação;
  • Cada busca com sucesso ao DICT consumirá 1 ficha.
  • Cada pagamento com sucesso (Pix cash-out) fará a reposição de 1 ficha.
  • Uma busca com erro (400 ou 404) consumirá, de forma definitiva, 20 fichas.
  • O balde de cada cliente terá uma taxa fixa de reposição de 5 fichas por minuto.

Quando todas as fichas de um balde são usadas, o cliente ficará temporariamente impedido de consultar o DICT e irá receber um erro do tipo 429 (HTTP). A partir daí, será necessário esperar até que o balde esteja novamente positivo para que as consultas sejam reiniciadas.
Desta forma, pedimos atenção ao número de consultas ao DICT que realizam, a fim de evitar qualquer tipo de transtorno.

Estatísticas da chave

O objeto statistics fornece dados estatísticos de usuários finais. As informações providas detalham o total de liquidações, fraudes reportadas e fraudes confirmadas do respectivo usuário consultado. Assim como nos dados estatísticos de chaves, esses totais são consolidados para os últimos 3 dias, 30 dias e 6 meses anteriores ao momento da consulta.

O campo lastUpdated informa data e hora da última atualização dos dados antifraude. Já em counters, está a lista de eventos referente aos dados antifraude, com os seguintes parâmetros:

  • type: tipo do contador:
    SETTLEMENTS - liquidações recebidas
    REPORTED_FRAUDS - fraudes reportadas para essa chave
    CONFIRMED_FRAUDS - fraudes que foram reportadas e confirmadas pelo PSP que detém a chave
    REJECTED - transações rejeitadas
  • by: agregador ("KEY", "OWNER", "ACCOUNT");
  • d3: valor dos ultimos 3 dias;
  • d30: valor dos ultimos 30 dias;
  • m6: valor dos últimos 6 meses (sem contar o mês atual)

Transferência dos valores

Após realizar a consulta da chave no DICT, deve ser realizada a transferência dos valores, para isso é necessário realizar uma chamada na API Iniciar pagamento Pix.

Modelo de request:

curl --location --request POST 'https://sandbox.openfinance.celcoin.dev/pix/v1/payment' \
--header 'accept: application/json' \
--header 'Content-Type: application/json-patch+json' \
--header 'Authorization: Bearer {access_token}' \
--data-raw '{
  "amount": 25.55,
  "clientCode": "14588549",
  "debitParty": {
    "account": "3794245",
    "branch": 30,
    "taxId": "13935893000109",
    "accountType": "CACC",
    "name": "IS2B - Integrated Solutions to Business S.A"
  },
  "creditParty": {
    "key": "[email protected]",
    "bank": "30306294",
    "account": "42161",
    "branch": 20,
    "taxId": "33188542046",
    "accountType": "CACC",
    "name": "Fulano de Tal"
  },
  "endToEndId": "E1393589320220720183401897103833",
  "initiationType": "DICT",
  "remittanceInformation": "Texto de mensagem",
  "paymentType": "IMMEDIATE",
  "urgency": "HIGH",
  "transactionType": "TRANSFER"
}'

Na propriedade amount, deve ser preenchido o valor a ser transferido, já na clientCode, deve ser utilizado um identificador único da sua aplicação, o qual deve ser armazenado e não pode ser repetido.

O objeto debitParty, deve ser preenchido com os dados da conta bolsão da Celcoin e o objeto creditParty, deve ser populado com os dados da conta que vai receber o valor, retornados na chamada Retorna as informações do DICT utilizando uma chave cadastrada no Pix, onde a propriedade participant é igual a bank, accountNumber igual a account, taxIdNumber igual a taxId.

A propriedade initiationType, deve ser populado com o valor DICT, para que a aplicação da Celcoin entenda que sua aplicação está executando uma transferência a partir de uma chave Pix.

A propriedade urgency, deve ser populada com o valor HIGH para ser executada na hora.

A propriedade transactionType, deve ser populada com valor TRANSFER, pois estamos executando uma transferência.

A propriedade paymentType, deve ser populada com IMMEDIATE para ser executada na hora.

A propriedade endToEndId, deve ser populada com o endToEndId recebido na Consulta DICT (/pix/v1/dict/v2/key).

Ao realizar a chamada de payments a Celcoin irá retirar o dinheiro da sua conta bolsão e vai executar a tentativa de transferência. Caso tudo ocorra como esperado, será enviado via webhook uma notificação, porém se por algum motivo ocorrer uma falha, sua aplicação também será notificada via webhook, mas nesse cenário a Celcoin devolve o saldo retirado da conta, para ser usado em possíveis transações futuras.

Modelo de retorno:

{
    "transactionId": 9153724,
    "code": "SUCCESS",
    "slip": "     COMPROVANTE TRANSFERENCIA PIX      \n            03/03/2022 10:16            \n           TERM 11 AGENTE 999           \n                CONTROLE                \n    E1393589320220303131601345285635    \n----------------------------------------\n                PAGADOR                 \n\n                Contrato                \n            AG:1 CC:100548925           \n        CPF/CNPJ:23694719000175         \n----------------------------------------\n               RECEBEDOR                \n\n        30306294 AG:20 CC:42161         \n          CPF/CNPJ:09958359006          \n     CHAVE:[email protected]      \n----------------------------------------\n   DATA DO PAGAMENTO 03/03/2022 10:16   \n\n            VALOR R$ 25,5500            \n----------------------------------------\n              AUTENTICACAO              \n4E.E9.6B.12.73.18.88.59.FA.9D.73.B1.04.86.92.8E\n",
    "slipAuth": "4E.E9.6B.12.73.18.88.59.FA.9D.73.B1.04.86.92.8E",
    "endToEndId": "E1393589320220303131601345285635"
}

Perceba que será retornado o id da transação Celcoin (transactionID) e o campo endtoEndId, recomendamos que seja armazenado esses campos em sua aplicação, pois a Celcoin irá enviar um gatilho em seu webhook, informando se a transação ocorreu com sucesso, ou não e através dele é possível fazer essas validações.

O campo code exibe se a requisição ocorreu com sucesso ou não conforme abaixo:

  • SUCCESS = Pagamento realizado com sucesso;
  • SUCCESSFUL_WITH_ERROR = Pagamento realizado com sucesso, porém tivemos algum erro interno na hora de gerar comprovante;
  • ALREADY_PAID = Pagamento já foi realizado anteriormente (mesmo clientCode ou endToEndId);
  • ALREADY_PAYD_WITH_ERROR = Pagamento já foi realizado anteriormente (mesmo clientCode ou endToEndId), porém aconteceu algum erro como geração de comprovante.

Nos casos de retornos "SUCCESS" e "SUCCESSFUL_WITH_ERROR", o webhook será disparado confirmando a transação ou o erro ocorrido.

A propriedade slip devolve o comprovante do pagamento e o endToEndId é o id da transação Pix no BACEN.

🚧

Recomendamos que essas informações sejam persistidas do lado da sua aplicação e apresentado, para o seu usuário confirmar se deseja realizar o pagamento.

Ele optando por realizar o pagamento, deve ser realizado os processos abaixo, caso contrário, basta encerrar a execução da transferência.

Recebendo status das transferências via webhooks

O webhook é uma forma de receber informações de maneira assíncrona, onde geralmente são disparados gatilhos, no formato JSON, quando um evento acontece. Após a Celcoin realizar a tentativa de transferência do valor para instituição bancária solicitada, ela irá disparar um gatilho (PAYMENT), no webhook de seu aplicativo, ou sistema, configurado pelo nosso time de suporte.

Para realizar a configuração de um webhook é necessário entrar em contato com a nossa equipe de suporte informando a url de seu webhook, senha e usuário, no formato BASIC, desta forma eles irão realizar o cadastro em nossa plataforma, para que seja possível o envio dos gatilhos.

Uma vez que a propriedade RequestBody.StatusCode.StatusId for igual a 2, seu usuário final pode ser notificado que a transferência ocorreu com sucesso, qualquer coisa diferente de 2, deve ser validado o retorno, tratado e apresentado ao usuário.

Criamos uma tabela que mostra quais são os possíveis retornos que podemos apresentar, para acessar basta clicar nesse link.

Para realizar testes em sandbox e receber o webhook de PAYMENTS com status igual 2 (sucesso), deve ser utilizado o payload informado no começo do artigo.

Caso você queira simular o pagamento com status rejeitado, basta alterar o payload alterando o objeto creditParty da seguinte forma:

"creditParty": {
        "bank": "30306294",
        "account": "10545584",
        "branch": 0,
        "taxId": "11122233344",
        "accountType": "CACC",
        "name": "Celcoin"
    }

Exemplo de aplicação

Criamos o protótipo de um aplicativo para exemplificar a utilização da API: