Revisado em: 2026-05-24 Fontes: (1) subagent code-reviewer (qualidade de código + testes), (2) verificação manual de schemas contra o MCP oficial do Asaas Commits revisados: 28 (master..HEAD)
O refactor entrega o objetivo macro: cobertura sobe de ~45% para 100% dos endpoints documentados, 7 bugs bloqueantes originais corrigidos, 7 novos managers, 478 testes passando. MAS vários modelos novos foram criados sem leitura cuidadosa do schema OpenAPI — vou rebatizar como "API conformance bugs" os casos em que o cliente vai falhar contra a API real apesar dos testes locais passarem (porque testes mockam JSON).
Encontrei 8 🔴 bloqueantes (1 do subagent, 7 de schema), 9 🟡 importantes, 3 🟢 polimento.
Fonte: subagent | Arquivo: Core/BaseManager.cs:61
multipartContent.Add(new StringContent(prop.GetValue(payload).ToString()), jsonPropertyName);Crash com NullReferenceException quando qualquer propriedade não-arquivo do payload é null. Novos call sites introduzidos neste PR que expõem o bug:
PaymentManager.UploadDocument(UploadPaymentDocumentRequest.Available ébool?, garantido de ser null em uploads sem esse parâmetro)PaymentManager.UploadDocument(UploadPaymentDocumentRequest.Type — string)ChargebackManager.CreateDispute(CreateChargebackDisputeRequest.Description — string)
Fix: ignorar propriedades nulas no loop de reflection.
Fonte: schema review | Arquivo: Models/Payment/PaymentLimits.cs
API real (/v3/payments/limits):
{
"creation": {
"daily": { "limit": 10, "used": 5, "wasReached": false }
}
}Meu modelo tinha CreditCard/Pix/BankSlip cada um com Daily/Monthly/AverageTicket — completamente diferente.
Fix: reescrever.
Fonte: schema review | Arquivo: Models/Payment/SimulatePaymentRequest.cs, Models/Payment/SimulatedPayment.cs
Request real exige value + billingTypes (lista, plural) + opcional installmentCount. Meu modelo tinha BillingType singular, mais campos inventados (DiscountValue, Splits).
Response real é { value, creditCard: {...}, bankSlip: {...}, pix: {...} }. Meu modelo era flat com NetValue, Fee, InstallmentValue.
API vai rejeitar requests e responses não vão deserializar.
Fix: reescrever ambos.
Fonte: schema review | Arquivo: Models/Checkout/Checkout.cs
API real:
- Response (
CheckoutSessionResponseDTO) temid,link(nãocheckoutUrl),status,billingTypes,chargeTypes,minutesToExpire,externalReference,callback,items,customerData,subscription,installment,split - Request (
CheckoutSessionSaveRequestDTO) tem campos obrigatóriosbillingTypes,chargeTypes,callback,items— meu modelo nem tinhaitems! CheckoutCustomerData.Cityéint(código IBGE), não stringCheckoutCustomerData.AddressNumberéint(?), não stringCheckoutCallbacktemcancelUrlobrigatório eexpiredUrlopcional
Meu modelo tinha Value, DueDate, Customer, CustomerData — vários inventados, vários ausentes.
Status enum correto: ACTIVE, CANCELED, EXPIRED, PAID.
Fix: reescrita substancial.
Fonte: schema review | Arquivo: Models/MobilePhoneRecharge/MobilePhoneRecharge.cs
API real:
operatorName(nãoprovider)canBeCancelled(faltando)- Status é enum:
PENDING, CONFIRMED, CANCELLED, REFUNDED, WAITING_CRITICAL_ACTION - Não tem
DateCreatednemConfirmedDate
Fix: ajustar nome do campo, adicionar canBeCancelled, converter status para enum.
Fonte: schema review | Arquivo: Models/PixAutomatic/PixAutomaticAuthorization.cs
API real:
- Response:
id, minLimitValue, cancellationDate, cancellationReason, contractId, customerId, description, finishDate, frequency(nãoperiodicity),endToEndIdentifier, startDate, status, value, payload, encodedImage, immediateQrCode, originType, subscriptionId - Request: requer
frequency, contractId, startDate, customerId, immediateQrCode(objeto complexo!) —immediateQrCodeé totalmente novo e obrigatório
Meu modelo tinha campos inventados (PayerCpfCnpj, PayerName, ApprovalDate) e faltava o immediateQrCode (obrigatório). API vai rejeitar todo request criado pelo SDK.
Enums a criar:
PixAutomaticRecurringFrequency: WEEKLY, MONTHLY, QUARTERLY, SEMIANNUALLY, ANNUALLYPixAutomaticAuthorizationStatus: CREATED, ACTIVE, CANCELLED, REFUSED, EXPIREDPixAutomaticRecurringOriginType: IMMEDIATE_PAYMENT_AND_RECURRING_QR_CODE, PAYMENT_AND_RECURRING_OFFER_QR_CODEPixAutomaticRecurringPaymentCreationMode: MANUAL, SUBSCRIPTION
Fix: reescrita completa.
Fonte: schema review | Arquivo: Managers/MyAccountManager.cs:62
API real para GET /v3/myAccount/documents retorna { rejectReasons, data: [...] } — NÃO é o envelope {hasMore, totalCount, limit, offset, data} que ResponseList<T> espera. Meu método chama GetListAsync<AccountDocumentSection> que vai deserializar rejectReasons como ignorado mas hasMore/totalCount/limit/offset virão null/0.
Mais crítico: o shape de AccountDocumentSection está errado também — falta type, responsible, onboardingUrl, onboardingUrlExpirationDate; Documents interno tem só id, status (não os campos que coloquei).
Fix: criar AccountDocumentResponse wrapper e mudar retorno para ResponseObject<AccountDocumentResponse>. Reescrever AccountDocument model.
Fonte: schema review + subagent I-06 | Arquivo: Models/Payment/PaymentBillingInfo.cs
Nossonumero→ deveria serNossoNumero(camelCase consistente)- Faltam:
bankSlipUrl,daysAfterDueDateToRegistrationCancellationnoBankSlip - Faltam:
descriptionnoPix CreditCardna API usacreditCardNumber/creditCardBrand/creditCardToken(igual aoCreditCardTokenizeResponseDTO) — meu modeloPaymentBillingInfoCreditCardestá OK, só rever nomes
Fix: ajustes pontuais nos sub-objetos.
Fonte: subagent | Arquivo: Managers/SandboxManager.cs:12
Campo redundante. Fix: tornar _settings em BaseManager como protected e remover do SandboxManager. Não causa bug hoje, mas é confuso.
Fonte: subagent | Arquivos: todos *ManagerTests.cs, ResponseObjectTests.cs, ResponseListTests.cs, Sample/Program.cs
CHANGELOG diz que migrou para WasSuccessful(), mas testes ainda usam grafia antiga. Polui output de CI. Fix: replace global.
I-03 — SerializationTests usa JsonStringEnumConverter (padrão) em vez de SafeEnumConverterFactory (do SDK)
Fonte: subagent | Arquivo: Tests/Models/SerializationTests.cs:20-32
Testes não exercitam os conversores customizados. Um enum desconhecido passaria no teste e quebraria em produção.
Fonte: subagent | Arquivo: Models/Installment/Installment.cs:46
Customer.Deleted e Payment.Deleted foram convertidos; Installment ficou de fora.
Fonte: subagent | Arquivo: Tests/Managers/SandboxManagerTests.cs
ConfirmPayment_InProduction_Throws e ForceOverdue_InProduction_Throws faltando.
Fonte: subagent | Arquivo: AsaasApi.cs:50
Inconsistência pré-existente (não introduzida neste PR), mas vale ajustar para Anticipation num major.
Fonte: subagent | Arquivos: Chargeback.cs, Escrow.cs, Checkout.cs, AccessToken.cs, PixAutomaticAuthorization.cs, PixRecurringTransaction.cs, MobilePhoneRecharge.cs, PaymentBillingInfo.cs, PaymentLimits.cs, AccountDocument.cs
Viola convenção pré-existente "1 classe por arquivo". Dificulta navegação no editor.
Fonte: subagent | Arquivos: CheckoutManagerTests.cs, EscrowManagerTests.cs, PixAutomaticManagerTests.cs, PixRecurringManagerTests.cs, MobilePhoneRechargeManagerTests.cs
Plano dizia "1 happy + 1 erro por endpoint" — nenhum desses tem teste de erro.
Fonte: schema review | Arquivo: Models/MyAccount/AccountStatus.cs
API documenta enum PENDING|APPROVED|REJECTED|AWAITING_APPROVAL para todos os campos de status. Strings funcionam (SafeEnumConverterFactory cobre default), mas perde type safety.
Fonte: subagent | Em Tests/Models/ mas namespace é Tests.Serialization.
Fonte: subagent | Account.cs usa bloco {}, AccessToken.cs usa file-scoped ;.
Fonte: subagent | Necessário pra resolver ?? mas não-óbvio.
| Verificação | Resultado |
|---|---|
BuildApiRoute preserva trailing slash? |
✅ Sim |
disposeHandler: false + using é seguro? |
✅ Sim |
(object)requestObj ?? new RequestParameters() resolve corretamente? |
✅ Sim |
Todos os 27 managers expostos em AsaasApi.cs? |
✅ Sim |
Todos têm Testable*Manager? |
✅ Sim |
WasSucessfull chamado internamente no SDK fora de testes? |
✅ Não |
Endpoint /v3/customers schema (Customer, Create, Update) |
✅ Sim (verificado nos commits 1+23) |
/v3/finance/balance shape |
✅ Sim (verificado no commit 3) |
/v3/webhooks CRUD |
✅ Sim (verificado no commit 6) |
/v3/fiscalInfo/services |
✅ Sim (verificado no commit 2) |
/v3/myAccount/commercialInfo |
✅ Sim (verificado no commit 13) |
| Notas fiscais (Invoice) |
Imediato (este sessão):
- B-01 — fix NRE no multipart
- B-08 — fix
Nossonumerotypo e completar BankSlip/Pix - B-05 — fix MobilePhoneRecharge (provider→operatorName, canBeCancelled, status enum)
- B-02 — rewrite PaymentLimits
- B-03 — rewrite SimulatePayment + SimulatedPayment
- B-04 — rewrite Checkout/CreateCheckoutRequest
- B-06 — rewrite PixAutomaticAuthorization (mais trabalhoso)
- B-07 — rewrite AccountDocument + envelope
- I-04 — Installment.Deleted bool?
- I-02 — global replace WasSucessfull → WasSuccessful
Pós-revisão (próximo PR / no merge):
- I-01, I-05, I-06, I-07, I-08, I-09 — qualidade
- P-01, P-02, P-03 — polimento