Múltiplos tipos de Payload
Muitas alterações aconteceram. Abaixo descrevemos por classes o que mudou, o que continuou e como isso afeta o seu antigo código:
Tratamento de Exceções
Antes, todos os erros no código retornavam um objeto simples Exception com uma mensagem sobre mais detalhes. Mas, agora, dividimos as principais exceções entre alguns tipos de objetos, são eles:
CannotParseKeyTypeException: Impossível determinar o tipo da chave Pix;EmvIdIsRequiredException: O campo EMV não foi preenchdo e é obrigatório;InvalidCobFieldException: Algum campo COB está inválido;InvalidEmvFieldException: Algum campo EMV está inválido;InvalidFieldException: Algum campo está inválido;InvalidPixCodeException: O código Pix recebido é inválido;InvalidPixKeyException: A chave Pix informada é incompatível com o tipo;InvalidPixKeyTypeException: O tipo de chave Pix informado é inválido.
As classes acima possuem métodos
get*()personalizados para você obter de forma mais precisa dos dados de erros equivalentes.
Se você já tratava exceções, nada muda! Exceto que, agora, tem mais controle para tratar determinados tipos de erros.
Classe Reader
- O método
extract()resultará em uma exceçãoInvalidPixCodeExceptionse o código Pix não foi um código Pix válido; - O método
export()criará umPayloadcompatível com o código Pix lido.
Classe Parser
- O método
getKeyType()resultará em uma excessãoCannotParseKeyTypeExceptionse não for possível determinar o tipo da chave Pix; - Os métodos
validateCpf()evalidateCnpj()agora são públicos e podem ser utilizados individualmente; - O método
getRandom()cria umastringaleatória contendo25caracteres entre[A-Za-z0-9]; - O método
validate()pode resultar em dois tipos de exceções:InvalidPixKeyTypeExceptionquando o tipo da chave é inválido;InvalidPixKeyExceptionquando a chave não é compatível com o tipo.
Classe Payload
- O valor padrão inicial do
tidsempre será***quando não preenchido; - O método
setPixKey()pode resultar em dois tipos de exceções:InvalidPixKeyTypeExceptionquando o tipo da chave é inválido;InvalidPixKeyExceptionquando a chave não é compatível com o tipo; - O método
setDescription()aceita até40caracteres; - O método
setTid()pode receber um valor vazio, quando acontecer, irá gerar um valor aleatório para o ID da transação com o métodoParser::getRandom(); - O método
getTid()foi adicionado; - O método
setAsReusable()foi descontinuado (veja mais detalhes abaixo); - Ao definir alguns campos, eles podem retornar a exceção
EmvIdIsRequiredExceptionse o campo não estiver preenchido ouInvalidEmvFieldExceptionse o campo estiver incorreto.
Descontinuação do setAsReusable()
O método setAsReusable() definia se um código Pix era único (dinâmico) ou reutilizável (estático). Ele continua valendo para criações manuais, entretanto, para organização do código, o Payload foi dividido em duas classes:
- Classe
StaticPayload: para códigos Pix estáticos; não muda nada, com excessão que sempre será um código reutilizável e ignora o métodosetAsReusable(); - Classe
DynamicPayload: para códigos Pix dinâmicos; altera o comportamento padrão doPayload, pois ignora os métodossetPixKey(),setDescription()esetAsReusable(). Os métodos ainda podem ser chamados, entretanto não alterarão valores noPayload. Além disso, acrescenta o métodosetPayloadUrl()com a URL do payload recebido pelo PSP (SPI). Cuidado ao utilizarsetTid()alguns SPIs aceitam, enquanto outros não.
A classe Dynamic Payload está diretamente associada a um QR Code dinâmico e só pode ser utilizada após criação da cobrança via alguma API Pix. A api será responsável por criar a cobrança no SPI e retornar o
location(uma URL que contem os dados do pix). Esselocationdeve ser adicionado emsetPayloadUrl().
Exemplo
// Montagem de um pix estático
$payload = (new StaticPayload())
->setMerchantName($merchantName)
->setMerchantCity($merchantCity)
->setPixKey($keyType, $keyValue)
->setDescription($description)
->setAmount($amount)
->setTid($tid);
// Montagem de um pix dinâmico
$payload = (new DynamicPayload())
->setMerchantName($merchantName)
->setMerchantCity($merchantCity)
->setAmount($amount)
->setPayloadUrl($url);
// Lendo um código pix e obtendo o payload
$payload = (new Reader($pixCode))->export();Classe CobPayload
O problema com as APIs do Pix é que, mesmo com o Banco Central lançando o padrão de comunicação para ser adotado, muitos SPI fazem as coisas do seu jeito. A única maneira de desenvolve uma biblioteca compatível com todas as principais APIs do mercado é tendo acesso a elas. Entendemos que isso está distante do propósito deste projeto. Afinal, cada API deveria ter sua própria biblioteca e então utilizar a nossa para montar os códigos Pix.
Mas, decidimos implementar a classe
CobPayloadque utiliza o padrão do Banco Central do Brasil. Cada API deveria ter umPayloadparecido para implementar os métodos. Fique a vontade para criar conforme a API que irá utilizar.
É utilizada para tratamento dos dados da API Pix e segue os padrões determinados em bacen/pix-api. Essa classe auxilia você criar um payload mais limpo, assim como receber os dados da API Pix de uma forma muito mais orgânica e organizada.
Além dos métodos para obter/setar dados do CobPayload, haverão dois métodos disponíveis sendo eles:
export(): exporta todos os dados da classeCobPayloadpara o array compatível com a API Pix;import(): importa todos os dados de resposta da API Pix para os objetos relacionados criando umCobPayloadorganizado.
O CobPayload e as classes deviradas disponíveis em Entities/Cob/* são bem flexíveis e fazem a importação/exportação de todos os dados disponíveis conforme os modelos padrões da API Pix, não há muito com o que se preocupar.
Em breve, vamos criar uma documentação detalhada sobre essas classes.
Exemplo
// Não implementamos ainda uma classe $api
$cobResponse = $api->getCob($tid);
// Cria o cob para normalizar os dados
$cob = (new CobPayload())->import($cobResponse);
// Nome do recebedor do Pix
$cob->getSender()->getName();
// Nome do devedor do Pix
$cob->getRecipient()->getName();
// Valor original do Pix
$cob->getAmount()->getOriginalAmount();
// Status da cobrança do Pix
$cob->getStatus();
// -> exemplos de dados
// Você também pode criar o seu cob e enviar via $api
$devedor = (new Entities\Cob\Person())->setDocument('12345678930');
$recebedor = (new Entities\Cob\Person())->setDocument('11222333000100');
$valor = (new Entities\Cob\Amount())->setOriginalAmount('1.00');
$calendario = (new Entities\Cob\Calendar())->setDueDate(DateTime::now()->add(new DateInterval('P10D')));
$cob = (new CobPayload())
->setSender($recebedor)
->setRecipient($devedor)
->setAmount($valor)
->setCalendar($calendario);
// Não implementamos ainda uma classe $api
// Envie o payload do cob
$cobResponse = $api->createCob($cob->export());
// Capture a resposta
$cob = (new CobPayload())->import($cobResponse);
// E, depois pode convertê-lo para um payload: