PHPAY-97: Asaas — assinaturas completas (listar, buscar, atualizar, remover, carnê e nota fiscal) - #98
Merged
Conversation
Alguns endpoints respondem PDF ou imagem, não JSON — o carnê de assinatura do Asaas é o primeiro. request() decodificava tudo como JSON e devolvia [] nesses casos. download() devolve o corpo cru, e os dois passam pelo mesmo send(), então a falha continua virando ApiException.
A especificação do Asaas marca cycle como obrigatório em POST /v3/subscriptions, mas o validador não o conferia: o payload sem ele passava e só falhava no gateway, como ApiException. Agora falha antes, como ValidationException, com os valores aceitos na mensagem. SubscriptionCycleEnum lista os sete ciclos.
O recurso Subscription só tinha create(). Agora cobre os 14 endpoints de assinatura da API do Asaas, conferidos na especificação OpenAPI oficial: - getAll(), find(), update() e destroy() - deactivate() e reactivate($id, $nextDueDate): a pausa que o Asaas recomenda no lugar de remover, porque destroy() leva junto as cobranças pendentes e vencidas. Reativar exige um novo vencimento, segundo a própria documentação - updateCreditCard(): troca o cartão sem cobrar, por token ou pelos dados do cartão, com o remoteIp do comprador - getPayments(): as cobranças já geradas - paymentBook(): o carnê, como os bytes do PDF - nota fiscal por cobrança: createInvoiceSettings(), getInvoiceSettings(), updateInvoiceSettings(), destroyInvoiceSettings() e getInvoices() E os setters que faltavam: setSubscription(), setAmount(Money|int|float), com número cru lido em reais como no resto do Asaas, e setCycle(SubscriptionCycleEnum). create(array) continua funcionando como sempre: o array sobrescreve o que os setters montaram. O parâmetro passou a ser opcional, então quem implementa SubscriptionInterface fora da biblioteca precisa acompanhar a assinatura nova.
- README: a seção de assinaturas do Asaas passa a cobrir consulta, ciclo de vida, carnê, troca de cartão e nota fiscal. O roadmap marca Assinaturas como pronto, e a nota de pendência sai - README: o Asaas deixa de ser "o único com as cinco capacidades", que era falso desde o Woovi - CLAUDE.md: as particularidades das assinaturas do Asaas e o download() no HasHttpClient. A pendência das assinaturas sai de O que ainda está em aberto - examples/asaas/subscriptions.php mostra as operações novas; o carnê gerado é ignorado pelo git
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 #97.
O que muda
As assinaturas do Asaas deixam de ser parciais (✍️) no roadmap. O recurso
Subscriptiontinha sócreate()e agora cobre os 14 endpoints de assinatura da API do Asaas, conferidos na especificação OpenAPI oficial:getAll()GET /v3/subscriptionsfind()GET /v3/subscriptions/{id}update()PUT /v3/subscriptions/{id}deactivate()/reactivate($id, $nextDueDate)PUT /v3/subscriptions/{id}comstatusdestroy()DELETE /v3/subscriptions/{id}updateCreditCard()PUT /v3/subscriptions/{id}/creditCardgetPayments()GET /v3/subscriptions/{id}/paymentspaymentBook()GET /v3/subscriptions/{id}/paymentBookcreate/get/update/destroyInvoiceSettings()/v3/subscriptions/{id}/invoiceSettingsgetInvoices()GET /v3/subscriptions/{id}/invoicesTambém entram os setters que faltavam:
setSubscription(),setAmount(Money|int|float)esetCycle(SubscriptionCycleEnum).Commits
feat(http):HasHttpClient::download(). O carnê responde PDF, e orequest()decodificava tudo como JSON, devolvendo[]. Os dois agora passam pelo mesmosend(), então a falha continua virandoApiException.fix(asaas):cyclepassa a ser obrigatório na criação, como na especificação do Asaas. O payload sem ele passava pela validação e só falhava no gateway.feat(asaas): os endpoints acima, com validação do troca-cartão (token, ou cartão e titular, sempre comremoteIp) e da nota fiscal (os sete impostos obrigatórios).doc(asaas): README, roadmap, CLAUDE.md eexamples/asaas/subscriptions.php.Decisões que merecem revisão
deactivate()ereactivate()existem porque o Asaas recomenda pausar em vez de remover. Odestroy()leva junto as cobranças pendentes e vencidas. Reativar exige um novonextDueDate, segundo a documentação do Asaas, por isso ele é parâmetro obrigatório.create(array $subscription)passou a ter o parâmetro opcional. Quem chama não percebe diferença, e o array continua sobrescrevendo o que os setters montaram. Só quebraria quem implementaSubscriptionInterfacefora da biblioteca, o mesmo caso doSupportsCustomersna v2.1.0.cycleobrigatório: quem criava assinatura sem ele recebiaApiExceptiondo Asaas e agora recebeValidationExceptionantes da chamada. A requisição já falhava, só falha mais cedo e com mensagem melhor.PUTnão listavalue, embora a própria página diga que dá para alterar o valor. Oupdate()repassa o array como está, sem normalizarMoney, e o PHPDoc manda consultar a documentação.Como testar
composer testroda 354 testes, 968 asserções, todos com HTTP mockado. Os 23 testes novos cobrem:ApiExceptionquando o carnê não existeNão foi exercitado contra o sandbox real.
Checklist
composer testpassa (Pint, Pest e PHPStan nível 9)