PHPAY-83: adicionar o gateway Cielo (API E-commerce 3.0) - #84
Merged
Merged
Conversation
Sexto gateway, e a primeira adquirente da biblioteca. Lidera o mercado por número de usuários (28%, ~30% no varejo). Declara duas das cinco capacidades: SupportsCharges /1/sales, captura, cancelamento SupportsSubscriptions recorrência via /1/RecurrentPayment É a forma mais estreita depois do Efí, e é a esperada para uma adquirente: não existe recurso de cliente — ele é um campo da venda. Webhooks são configurados no backoffice, e Pix é tipo de pagamento. A particularidade que mais mexeu no código é que a Cielo separa dois hosts por TIPO DE OPERAÇÃO, não por domínio: escritas vão para api.cieloecommerce, e consultas para apiquery.cieloecommerce. O PagBank também tem dois hosts, mas divididos por domínio, e lá cada recurso boota um client. Aqui o mesmo recurso precisa dos dois — create() num, find() no outro. Para isso, HasHttpClient::request() passa a aceitar um client opcional em vez de usar sempre $this->client. É uma mudança retrocompatível, e o trait da Cielo usa isso em queryGet(). Quem consome a biblioteca não vê diferença: o roteamento é interno. Outras decisões: - A recorrência não tem endpoint de criação. Ela nasce de uma venda com bloco RecurrentPayment e só então ganha um RecurrentPaymentId próprio. O recurso Subscription expressa isso em vez de fingir um create() direto. - Os endpoints de update da recorrência recebem um valor JSON puro no corpo (19900, "Monthly"), não um objeto. Daí o putValue() privado. - Valores em centavos inteiros, validados antes de qualquer chamada. - Header RequestId como chave de idempotência, gerado por chamada e fixável com setRequestId(). 179 testes no total. Os da Cielo cobrem o roteamento entre os dois hosts, a autenticação por MerchantId/MerchantKey, o corpo JSON puro dos updates de recorrência e a exigência de cartão na assinatura.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #83
Sexto gateway, e a primeira adquirente da biblioteca. A Cielo lidera o mercado por número de usuários (28%, ~30% no varejo).
Capacidades: 2 de 5
SupportsChargesPOST /1/sales, captura, cancelamentoSupportsSubscriptions/1/RecurrentPaymentSupportsCustomersSupportsWebhooksSupportsPixKeysÉ a forma mais estreita depois do Efí, e é a esperada para uma adquirente. Adquirente autoriza e captura transação; cadastro de cliente e cobrança recorrente rica são domínio de gateway.
A particularidade que mexeu no código
A Cielo separa dois hosts por tipo de operação, não por domínio:
apisandbox.cieloecommerce.cielo.com.brapiquerysandbox.cieloecommerce.cielo.com.brO PagBank também tem dois hosts, mas divididos por domínio (pedidos vs assinaturas) — lá cada recurso boota um client. Aqui o mesmo recurso precisa dos dois:
create()vai num,find()no outro.Por isso
HasHttpClient::request()passa a aceitar um client opcional em vez de usar sempre$this->client. Mudança retrocompatível — nenhum gateway existente foi tocado — e o trait da Cielo a usa emqueryGet(). Quem consome a biblioteca não vê diferença: o roteamento é interno.Há teste verificando que
find()não encosta no host de escrita.Outras decisões de modelagem
A recorrência não tem endpoint de criação. Ela nasce de uma venda carregando um bloco
RecurrentPayment, e só então ganha umRecurrentPaymentIdpróprio para ser gerenciada. O recursoSubscriptionexpressa isso em vez de fingir umcreate()direto:Os updates da recorrência recebem JSON puro, não objeto:
PUT .../Amountcom corpo19900,PUT .../Intervalcom corpo"Monthly". Daí oputValue()privado, e um teste que assevera o corpo exato.Valores em centavos inteiros, recusados na validação se vierem decimais.
Header
RequestIdcomo chave de idempotência, gerado por chamada e fixável comsetRequestId().Recursos
setOrderId,setCustomer,setPix,setBoleto,setCreditCard,setRequestId,create,find,findByOrderId,getStatus,getPixCode,capture,cancelsetCard,setInterval,setEndDate,create,find,deactivate,reactivate,updateAmount,updateInterval,updateEndDate,updateNextPaymentDateVerificação
179 testes (463 asserções), PHPStan nível 9 limpo, Pint limpo. Endpoints, hosts, autenticação e o modelo de recorrência foram conferidos na documentação oficial da Cielo.
O sandbox dela é self-service — o cadastro devolve
MerchantIdeMerchantKeysem exigir afiliação comercial, o que é incomum para adquirente e torna viável testar de verdade.