Pesquisa — CRMBonus: Visão Consolidada
Data: 2026-05-15
Contexto: Task #193232 — Análise do fluxo de integração CRMBonus
Sub-arquivos:
pesquisa-crm-bonus-documentacao-parceiro.md— API oficial CRM&Bonus (EcomV2)pesquisa-crm-bonus-analise-codigo.md— Análise de código: API Checkoutpesquisa-crm-bonus-docs-internos.md— Docs internos:docs/crm/+ Wiki ZZAPPSpesquisa-desconto-pix-crm-bonus.md— Desconto PIX + CrmBonus: fluxo atual e impacto do upsell
O que é o CRM&Bonus
O CRM&Bonus é um serviço de fidelidade de terceiros que gerencia bônus de clientes. No contexto do ZZLink/zzapp, clientes acumulam bônus em compras anteriores e podem utilizá-los como desconto em novas compras. A integração é assíncrona em relação ao cliente, mas linear e sequencial entre a API Checkout e a API CRM&Bonus.
As Três Operações
| Operação | Endpoint | Quando |
|---|---|---|
| Reserva | baixa_bonus | Criação do pedido (bonus_resgatado > 0) |
| Efetivação | finaliza_compra | Após captura bem-sucedida do pagamento |
| Cancelamento | cancelarBonusEcom | Estorno, cancelamento, falha de captura |
Fluxo Completo (conforme código real)
zzApp consulta CRM&Bonus diretamente
└── Envia dados de bônus no createByZzApp
└── CreatePaymentCommandHandler
└── cart.CrmBonus != null?
├── SIM, bonus_resgatado > 0 → baixa_bonus (reserva)
└── NÃO → nenhuma ação CRM
[Pagamento processado]
Captura bem-sucedida?
├── SIM → PosCaptureService
│ └── cart.CrmBonus != null && IdsBonus != null?
│ └── SIM → finaliza_compra (efetivação)
└── NÃO → Refund / Cancelamento
└── cancelarBonusEcom (libera bônus)
Callers por Operação
baixa_bonus (DebitCrmBonusAsync)
| Caller | Condição |
|---|---|
CreatePaymentCommandHandler | cart.CrmBonus != null + bonus_resgatado > 0 |
finaliza_compra (FinishCrmBonusAsync)
| Caller direto | Invocado por |
|---|---|
PosCaptureService | AntiFraudWebhookService, PagarMeCaptureService, OrderCommandHandler, WebhookBraspagService, PagarMeCreditCardService, PagarMePixService, FinishPaymentService |
cancelarBonusEcom (CancelCrmBonusAsync)
| Caller | used_bonus | Cenário |
|---|---|---|
OrderCommandHandler | true | Cancelamento manual do pedido (status Created/Pending) |
OrderCommandHandler | true | Falha na captura Braspag |
AntiFraudWebhookService | true | Falha na captura Braspag pós-aprovação antifraude |
PosRefundService.ExecutePosRefund | false | Estorno pós-captura confirmada (status Analysis/Paid) |
PosRefundService.ExecutePosRefundV2 | false | Estorno pós-captura confirmada (versão v2) |
Semântica de used_bonus
Atenção: a semântica é contraintuitiva. O parâmetro não indica se o bônus foi utilizado pelo cliente — indica qual operação precisa ser desfeita. Confirmado tanto pela documentação oficial do parceiro quanto pela análise do código real.
| Valor | Quando usar | finaliza_compra já foi chamado? | Impacto no CRM&Bonus |
|---|---|---|---|
true | Apenas baixa_bonus foi chamado (bônus ainda reservado) | ❌ Não | CRM libera a reserva |
false | finaliza_compra já foi chamado (bônus efetivado) | ✅ Sim | CRM reverte o consumo efetivado |
Ocorrências no código:
| Caller | used_bonus | Justificativa |
|---|---|---|
AntiFraudWebhookService (captura Braspag falhou) | true | Captura falhou → finaliza_compra nunca foi chamado |
OrderCommandHandler (cancelamento manual Created/Pending) | true | Status pré-captura → finaliza_compra nunca foi chamado |
OrderCommandHandler (falha na captura Braspag) | true | Captura falhou → finaliza_compra nunca foi chamado |
PosRefundService.ExecutePosRefund (estorno pós-captura) | false | Status Analysis/Paid → finaliza_compra já foi executado |
PosRefundService.ExecutePosRefundV2 (estorno pós-captura) | false | Estorno de venda confirmada → finaliza_compra já foi executado |
Armadilha no código:
PosRefundService.cscontém o comentário// INDICA SE O BONUS FOI USADOna variávelusedBonus = false. O comentário induz à leitura errada — naquele contexto o bônus foi efetivado. O valorfalseestá correto; o comentário não.
Autenticação na API CRM&Bonus
- Header
Authorization: valor fixo de configuração (Apis:CrmBonus:Authorization) - Header
Codempresa:Base64(tokenCrm)—tokenCrmlido da tabela de lojas viaIStorePaymentsRepository.GetTokenCrmByIdAsync(storeId) - Se
tokenCrmfornullpara a loja → objetocrmBonusdeve sernull→ integração não é executada
Validação de Resposta
Uma resposta do CRM&Bonus é considerada válida somente se:
HttpStatusCodeé 2xx, E- Body JSON contém
"status": true
Uma resposta HTTP 200 com "status": false é inválida.
Inconsistência Documentada
A documentação interna docs/crm/crm_analise.md descreve incorretamente o comportamento do AntiFraudWebhookService:
| Documentação anterior | Código real | |
|---|---|---|
AntiFraudWebhookService | used_bonus = false quando antifraude recusa | used_bonus = true apenas em falha de captura Braspag |
| PagarMe + antifraude reprovado | cancelamento direto via AntiFraudWebhookService | cancela via PagarMeRefundService → PosRefundService |
Pontos de Atenção
-
FinishCrmBonusAsyncnão lança exceção: CapturaHttpRequestExceptioninternamente e loga — uma falha na efetivação do bônus não interrompe o fluxo de captura. -
IdsBonuscomo condição extra no Finish: OPosCaptureServiceverifica!string.IsNullOrEmpty(cart.CrmBonus.IdsBonus)além do null check. UmCrmBonussemIdsBonusnão disparafinaliza_compra. -
paymentIdComplex: O identificador enviado ao CRM&Bonus não é o ID numérico do pedido — é um código composto gerado porICreateCodePaymentsForIntegrations.CreateCodePayment(orderId). -
Cancelamento manual status 81: Conforme Wiki ZZAPPS, o processo manual para pedidos com status 81 (ErrorAntifraud) não inclui o cancelamento de bônus CRM como etapa automática.
-
Job de expiração: Conforme Wiki ZZAPPS, o
JobExpiredOrderstambém disparacancelarBonusEcompara pedidos expirados — esse caller não aparece no código da API Checkout (provavelmente implementado em outro serviço/job).