bacen / pix-api

API Pix: a API do Arranjo de Pagamentos Instantâneos Brasileiro, Pix, criado pelo Banco Central do Brasil.
https://bacen.github.io/pix-api
2.32k stars 262 forks source link

[Nova funcionalidade] Envio de Pix via API #254

Open franciscotfmc opened 3 years ago

franciscotfmc commented 3 years ago

Boa tarde, prezados.

Segue uma proposta de endpoint que possibilita o envio de Pix via API.

É uma funcionalidade importante para atender mais casos de uso (não previstos ainda na spec), dos quais cito 2 abaixo:

Trata-se de um serviço que nós já temos implementado, porém tivemos o cuidado de seguir o padrão da especificação do BC.

Tentamos pensar como seriam os inputs/outputs caso a especificação partisse da equipe do Banco Central. @ninrod temos ciência de que existe a possibilidade de termos que nos adequar futuramente caso algo diferente seja proposto.

Apesar disso, gostaríamos de deixar a contribuição abaixo, pois se mostrou bastante funcional para os nossos clientes.

POST /pix

Escopo: pix.send

Input

{
  "valor": "12.34",
  "pagador": {
    "chave": "pagador@gerencianet.com.br"
  },
  "favorecido": {
    "chave": "favorecido@gerencianet.com.br"
  }
}

OU

{
  "valor": "12.34",
  "pagador": {
    "chave": "pagador@gerencianet.com.br",
    "infoPagador": "Segue o pagamento da conta"
  },
  "favorecido": {
    "contaBanco": {
      "nome": "Nome Favorecido",
      "cpf": "00000000000",
      "codigoBanco": "09089356",
      "agencia": "1",
      "conta": "123453",
      "tipoConta": "cacc"
    }
  }
}

Output

HTTP Code: 201

{
  "e2eId": "E09089356202011251226APIff82f2e5",
  "valor": "12.34",
  "horario": {
    "solicitacao": "2020-11-25T12:26:42.905Z"
  },
  "status": {
    "type": "EM_PROCESSAMENTO"
  }
}

Exemplo do conteúdo do webhook para envio de Pix via API:

{
    "endToEndId": "E09089356202011251226APIff82f2e5",
    "valor": "12.34",
    "horario": "2020-11-26T11:06:52.000Z",
    "tipo": "SOLICITACAO",
    "status": "REALIZADO"
}
rubenskuhl commented 3 years ago
renatofrota commented 3 years ago
* Eu acho que o Input não deveria ter chave do pagador, pois a chave identifica apenas destinatário... o acesso já tem um client_id que é associado a uma conta ou alguma divisão mais granular (aplicação no caso da Gerencianet).

* Acho que deveria ser PUT e não POST

Acho que optaram por POST pois o request ficaria "pendurado" muito tempo antes de poder ser respondido com 201. Além disso, pode haver indisponibilidade eventual do próprio sistema Pix ou do PSP recebedor e deixar a requisição no PSP pagador (Gerencianet neste caso) para ser processada posteriormente, pode desonerar a aplicação que solicita o envio.

A aceitação de PUT poderia ser um adicional (assim como uma cobrança pode ser criada com PUT ou POST).

* Acho que deveria ser um outro escopo, para permitir que hajam permissões distintas. Isso é especialmente importante em coisas que tiram dinheiro ao invés de receber dinheiro. Sugiro /pay.

Não é necessário o endpoint ser diferente para que exija permissões distintas. A permissão é relativa ao verbo (POST / PUT, pra enviar Pix, GET para ler Pix recebidos (e enviados, talvez, como você também já citou em um item posterior?)).

* Senti falta de TxID para permitir conciliação do pagamento do outro lado.
* Senti falta de poder pagar um QR-Code estático ou dinâmico, ao invés de apenas transferência.
* Seria bom ter também GET. Esse GET poderia ser no /pix mesmo.
* Senti falta de webhook para saber o andamento do pagamento. Poderia ser uma chave "pay" no webhook para acompanhar isso.

São sugestões interessantes. Mas acho que a proposta era possibilitar o envio para os clientes que tem a necessidade de automação do repasse, acima de tudo. E em relação ao webhook, essa sugestão justifica o uso da chave na solicitação do envio 😉

Meus parabéns à GN.

rubenskuhl commented 3 years ago

Eu ainda acho mais interessante não ter chave no pagador e deixar alguma outra forma de identificar webhook dos pagamentos. Sobre TxID, QR-estático e QR-dinâmico, basta que o MVP não trave o oferecimento disso no futuro. (Mas o GET de pix enviado é questão de controle, e aí já necessária IMHO)

rubenskuhl commented 3 years ago

Retorno ser 200 ou 201 independe da ação. Neste caso, como imagino que seja retornado apenas o E2EID o apropriado seria 201 mesmo. E o retorno poderia ser assim que o E2EID fosse criado; se o envio foi bem-sucedido ou não, só consultando GET ou recebendo webhook para saber.

No campo favorecido, senti falta do CPF ou CNPJ, que o PSP poderia checar ao receber essa informação do PSP recebedor (mascarada ou não) e se não bater, não enviar.

renatofrota commented 3 years ago

Retorno ser 200 ou 201 independe da ação. Neste caso, como imagino que seja retornado apenas o E2EID o apropriado seria 201 mesmo. E o retorno poderia ser assim que o E2EID fosse criado; se o envio foi bem-sucedido ou não, só consultando GET ou recebendo webhook para saber.

Tem razão, se o E2EID é disponível antes da conclusão do envio, faria sentido ter apenas o PUT e receber 201. E aí, o endpoint deveria ser outro que não o /pix (que são transações concluídas). Com o verbo PUT e retorno 201 ele ficaria análogo ao /cob, servindo o /cob pra cobrar e este outro endpoint para pagar.

Considerando que o endpoint de cobrança tem seu nome baseado no Português (/cob => cobrança), eu sugeriria /pag (de pagamento) em vez de /pay.

No campo favorecido, senti falta do CPF ou CNPJ, que o PSP poderia checar ao receber essa informação do PSP recebedor (mascarada ou não) e se não bater, não enviar.

O recebedor já é especificado com a chave de recebimento então por que deveria haver esta verificação adicional de forma obrigatória? Como opção, entendo que faça sentido, dependendo do cenário. Mas se não preciso dessa informação ao enviar de forma manual, não vejo necessidade desse dado como exigência na API.

rubenskuhl commented 3 years ago

/pag harmoniza mais com /cob e /pix, de fato.

A transferência manual requer até mais parâmetros que CPF/CNPJ; requer banco, agência e conta. Agora, a por chave não requer, mas na jornada do pagador não automatizado, ela mostra o CPF/CNPJ e nome DICT do destino para que o pagador efetive ou não o Pix.

Então o que eu pensei seria mandatório para o PSP mas opcional para o pagador; se o pagador informar apenas chave, o PSP faz o pagamento independente do CPF/CNPJ associado à chave. Mas se o pagador informar chave e CPF/CNPJ, aí o PSP seria obrigado a verificar e realizar ou não a ação. Mas isso não precisa ser no momento do PUT em /pag, pode ser assíncrono.

renatofrota commented 3 years ago

A transferência manual requer até mais parâmetros que CPF/CNPJ; requer banco, agência e conta. Agora, a por chave não requer, mas na jornada do pagador não automatizado, ela mostra o CPF/CNPJ e nome DICT do destino para que o pagador efetive ou não o Pix.

Mostra. Mas não é um input do pagador. É para conferência.

Então o que eu pensei seria mandatório para o PSP mas opcional para o pagador; se o pagador informar apenas chave, o PSP faz o pagamento independente do CPF/CNPJ associado à chave. Mas se o pagador informar chave e CPF/CNPJ, aí o PSP seria obrigado a verificar e realizar ou não a ação. Mas isso não precisa ser no momento do PUT em /pag, pode ser assíncrono.

Nestes termos, concordo 101%!

ninrod commented 3 years ago

Tentamos pensar como seriam os inputs/outputs caso a especificação partisse da equipe do Banco Central. @ninrod temos ciência de que existe a possibilidade de termos que nos adequar futuramente caso algo diferente seja proposto.

@franciscotfmc , perfeito. Agradecemos pela contribuição. Essa funcionalidade está prevista na agenda evolutiva, mas é interessante poder desde já observar como o mercado implementaria.

franciscotfmc commented 3 years ago

Bom dia!

Acho que optaram por POST pois o request ficaria "pendurado" muito tempo antes de poder ser respondido com 201. Além disso, pode haver indisponibilidade eventual do próprio sistema Pix ou do PSP recebedor e deixar a requisição no PSP pagador (Gerencianet neste caso) para ser processada posteriormente, pode desonerar a aplicação que solicita o envio.

O objetivo de inputar pagador.chave é exatamente isso: saber onde enviar o webhook após a alteração do status. Optamos por esse caminho, em resumo, por 2 questões:

Acho que deveria ser PUT e não POST

Interessante mesmo ter uma versão PUT com algum atributo que garanta idempotência.

Acho que deveria ser um outro escopo, para permitir que hajam permissões distintas. Isso é especialmente importante em coisas que tiram dinheiro ao invés de receber dinheiro. Sugiro /pay.

Perfeita observação. Foi eu quem esqueceu de detalhar isso ao criar a issue. Editado. Criamos o um escopo específico: pix.send.

Senti falta de TxID para permitir conciliação do pagamento do outro lado. Senti falta de poder pagar um QR-Code estático ou dinâmico, ao invés de apenas transferência. Sobre TxID, QR-estático e QR-dinâmico, basta que o MVP não trave o oferecimento disso no futuro.

Importante esclarecer esse ponto. A sugestão aqui é realmente remeter a uma transferência Pix. O endpoint pode evoluir para que também atenda à necessidade de "pagar uma cobrança" via API. Neste caso eu entendo que o TxID seria o input necessário ao invés da chave:

{
  "valor": "12.34",
  "pagador": {
    "chave": "pagador@gerencianet.com.br"
  },
  "cob": {
    "txid": "00000000000000000000000000000001"
  }
}

Seria bom ter também GET. Esse GET poderia ser no /pix mesmo.

Vejo com bons olhos essa sugestão: aperfeiçoar o GET /pix/e2eid para que possa também consultar um pix enviado. Atualmente existe um filtro que restringe aos recebidos, seguindo a semântica da especificação.

Senti falta de webhook para saber o andamento do pagamento. Poderia ser uma chave "pay" no webhook para acompanhar isso.

Isso tem. Exemplo do conteúdo do webhook:

{
    "endToEndId": "E09089356202011251226APIff82f2e5",
    "valor": "12.34",
    "horario": "2020-11-26T11:06:52.000Z",
    "tipo": "SOLICITACAO",
    "status": "REALIZADO"
}

No campo favorecido, senti falta do CPF ou CNPJ, que o PSP poderia checar ao receber essa informação do PSP recebedor (mascarada ou não) e se não bater, não enviar.

Entendemos que o recebedor conhece a chave e, por isso, não vimos necessidade dessa informação neste momento.

Importante destacar que o endpoint permite inputar uma chave ou dados bancários, conforme exemplo abaixo (também adicionei no primeiro post para ficar mais completo):

{
  "valor": "99.99",
  "pagador": {
    "chave": "19974764017",
    "infoPagador": "Segue o pagamento da conta"
  },
  "favorecido": {
    "contaBanco": {
      "nome": "JOSE CARVALHO",
      "cpf": "10519952057",
      "codigoBanco": "09089356",
      "agencia": "1",
      "conta": "123453",
      "tipoConta": "cacc"
    }
  }
}
franciscotfmc commented 3 years ago

@renatofrota @rubenskuhl o retorno correto é 201 mesmo! :)

rubenskuhl commented 3 years ago

Bom dia!

Acho que optaram por POST pois o request ficaria "pendurado" muito tempo antes de poder ser respondido com 201. Além disso, pode haver indisponibilidade eventual do próprio sistema Pix ou do PSP recebedor e deixar a requisição no PSP pagador (Gerencianet neste caso) para ser processada posteriormente, pode desonerar a aplicação que solicita o envio.

O objetivo de inputar pagador.chave é exatamente isso: saber onde enviar o webhook após a alteração do status. Optamos por esse caminho, em resumo, por 2 questões:

  • Valida-se a chave do recebedor _(nunca é demais garantir que a chave inputada é da própria conta associada ao clientid);

Chave do pagador, no caso... ainda me parece estranho. Algo como "pag" ao invés da chave no webhook ainda me parece mais coerente.

Seria bom ter também GET. Esse GET poderia ser no /pix mesmo.

Vejo com bons olhos essa sugestão: aperfeiçoar o GET /pix/e2eid para que possa também consultar um pix enviado. Atualmente existe um filtro que restringe aos recebidos, seguindo a semântica da especificação.

Para não quebrar quem só espera pix recebido em /pix, poderia ter parametros incluirpagamentos=sim e apenaspagamentos=sim e só quem usar uma dessas formas vai ter acesso.

No campo favorecido, senti falta do CPF ou CNPJ, que o PSP poderia checar ao receber essa informação do PSP recebedor (mascarada ou não) e se não bater, não enviar.

Entendemos que o recebedor conhece a chave e, por isso, não vimos necessidade dessa informação neste momento.

O problema é que o pagador pode receber uma chave do recebedor e não tem acesso ao DICT para confirmar a titularidade da chave. Assim, se ele souber o CPF/CNPJ do recebedor esperado, especifica; senão, não.

Importante destacar que o endpoint permite inputar uma chave ou dados bancários, conforme exemplo abaixo (também adicionei no primeiro post para ficar mais completo):

Humm, isso é bom.

rubenskuhl commented 3 years ago

Mais alguns pensamentos:

sibelius commented 3 years ago

vamos ter uma api normalizado do Pix que permite pagar 1 BRCode EMV ?

rubenskuhl commented 3 years ago

vamos ter uma api normalizado do Pix que permite pagar 1 BRCode EMV ?

Nas conversas que tive sobre isso com um PSP, o que eu achei que faria mais sentido é uma API com 2 chamadas, para uma CX similar ao do mobile.

Na primeira, é passado o EMV mais um id de pagamento. O id é opcional para EMV de dinâmico mas mandatório para estático. O valor é passado num campo adicional mandatório, que caso o EMV seja de dinâmico sem alteração de valor, já é criticado.

A resposta disso é um E2EID provisório e o que o DICT mostra desse pagamento.

Já no 2o. passo, se passa o E2EID, o CPF/CNPJ do recebedor e o valor. O PSP faz a crítica (todos tem que bater) e aí completa a transação.

Exemplo: PreparaPagamentoEMV (EMV, id, valor) => Resposta E2EID, dados DICT ConfirmaPagamentoEMV (E2EID, cpf/cnpj, valor) => Resposta NOK ou EM_ANDAMENTO

O Webhook teria um novo método {webHookUrl}/pag onde a efetiva conclusão seria sinalizada. GET /pix com o E2EID também seria possível.

rafaelmaia8384 commented 2 years ago

Olá senhores, acredito que essa funcionalidade é urgente.

rubenskuhl commented 2 years ago

Olá senhores, acredito que essa funcionalidade é urgente.

A funcionalidade já é parte do SPI. Só não tem padronização de API, e a dúvida é se a padronização é mais urgente do que novos recursos como Pix débito automático, Pix garantido, Pix por aproximação e/ou off-line... eu acho que não.

Você pode ver no #480 uma lista com PSPs que já implementam envio de Pix via API.

rafaelmaia8384 commented 2 years ago

Olá senhores, acredito que essa funcionalidade é urgente.

A funcionalidade já é parte do SPI. Só não tem padronização de API, e a dúvida é se a padronização é mais urgente do que novos recursos como Pix débito automático, Pix garantido, Pix por aproximação e/ou off-line... eu acho que não.

Você pode ver no #480 uma lista com PSPs que já implementam envio de Pix via API.

Padrão, obrigado.