CORTEX · doc

Payment Service

transação e cobrança

8 regras · v0.2.0 · rascunho · owner: plataforma · 18 KB · payment-service · sumário em JSON

CORTEX — payment-service (transação e cobrança)

Versão: 0.2.0 · Data: 2026-07-23 · Status: Rascunho · Owner: Plataforma Caminho canônico: cortex-docs/services/PAYMENT_SERVICE.md Documentos irmãos: cortex-docs/ECOSYSTEM.md (catálogo §4, comunicação §5) · cortex-docs/standards/UNISCALE_ENGINEERING_STANDARDS.md (evento §28, estado §29, tipos §22) · cortex-docs/services/CONNECTORS.md (padrão de connector)

Este documento promove a regras endereçáveis as decisões já assentadas do payment-service (descritas no ECOSYSTEM §4/§5). Não repete os padrões transversais — referencia UNISCALE. Rascunho pendente de revisão. As decisões em aberto estão listadas no fim (§Fronteiras a definir) e não devem ser inventadas pelo construtor — caem no FALLBACK do protocolo do repo.

O payment-service é dono da transação e da cobrança de finanças não-acadêmicas (a mensalidade acadêmica roda pelo gateway interno do jacad, fora daqui — ECOSYSTEM §6). Aplica o princípio do ecossistema: executor burro, regra no institutional (ECOSYSTEM §2). Tem banco próprio (UNISCALE §21); dinheiro é numeric(18,2), nunca float (UNISCALE §22).

Métodos no escopo desta versão: cartão e PIX. Boleto não está no escopo. O primeiro gateway é o Dom Pagamentos, atrás do dom-pagamentos-connector (§5).


1. Cobra sem saber o que vende (Obrigatório)

O payment-service recebe do ai-sales o valor e os campos a coletar já prontos e cobra sem saber o que é (em lógica de negócio). Não resolve preço, oferta, lote ou desconto — isso é do institutional/ai-sales (ECOSYSTEM §2, glossário §3: "Saber o que está vendendo" não é dele). Mesma filosofia do embedding-service (encapsula o gateway como aquele encapsula o modelo): o consumidor pede cobrança sem o serviço precisar entender a venda.

Isto vale inclusive na captura: o serviço não pergunta a ninguém se a venda ainda é válida e não consulta o institutional — ele obedece a ordem de quem é dono da regra (§7). Consultar seria voltar a saber o que vende, e criaria dependência de disponibilidade de outro serviço para o dinheiro entrar.

2. A confirmação real é o fato, não a resposta síncrona (Obrigatório)

O serviço opera síncrono (cartão) e assíncrono (PIX/webhook), mas a única verdade de que o dinheiro entrou é o fato payment.transaction.confirmed (UNISCALE §10, §28) — publicado na captura (§7), quando o gateway confirma. Nunca tratar a resposta síncrona otimista, nem a autorização, como confirmação: autorização é dinheiro reservado, não dinheiro recebido. É o fato da captura que destrava a matrícula no order-service — e a regra comercial "não matricula antes de pagar" depende disso.

O serviço publica também os fatos que outros precisam para reagir, e não só o de sucesso:

Fato Quando Quem depende
payment.transaction.authorized autorização aprovada, aguardando ordem de captura order-service — é o gatilho da validação dele (§7)
payment.transaction.confirmed captura confirmada — o dinheiro entrou order-service (matrícula), core, CRM
payment.transaction.failed recusa definitiva (cartão negado, captura recusada) ai-sales (retomar a conversa)
payment.transaction.expired janela venceu sem pagamento (PIX/link/autorização) ai-sales (fallback de PIX expirado — ECOSYSTEM §4)

Quem se interessa reage de forma desacoplada (ECOSYSTEM §5); o payment-service não sabe quem ouve e não chama consumidor direto. A nomenclatura exata segue uniscale.events.naming.

3. Checkout stateful e idempotente pela chave do chamador (Obrigatório)

O serviço hospeda o checkout (link stateful e idempotente) e o formulário pós-checkout. Reabrir o link, reenviar ou reprocessar webhook não pode gerar cobrança em duplicidade nem segunda confirmação — idempotência é pré-requisito, não opcional (coerente com UNISCALE §29.3: entrega at-least-once + consumer idempotente).

A idempotência tem duas chaves distintas, uma por fronteira:

  • Na criação da cobrança — chave do chamador. O ai-sales gera um identificador único do pagamento do lado dele e o envia na chamada, junto dos identificadores de correlação (lead_id, person_id, product_id). Se a chamada se perder (timeout, queda, resposta que não volta), o ai-sales reenvia com a mesma chave e o payment-service devolve a mesma cobrança em vez de criar outra — os dois lados conhecem a chave, então o ciclo se reconecta. Sem chave do chamador, uma resposta perdida deixaria uma cobrança órfã que o chamador não sabe que existe.
  • No webhook — chave do gateway. O gateway reentrega o mesmo evento (at-least-once). O serviço reconhece pelo identificador da transação/evento no gateway e não confirma duas vezes nem publica o fato duas vezes.

Regras de uso da chave do chamador:

  • Produtos distintos = chaves distintas. Duas compras legítimas do mesmo lead são duas cobranças — a chave é do pagamento, não da pessoa.
  • Mudou a negociação, muda a chave. Alteração que redefine a cobrança (ex.: troca de plano de pagamento para o mesmo curso) gera uma nova chave, e a cobrança anterior é cancelada (§4) — nunca reaproveitada.

Identificadores de correlação. lead_id e person_id acompanham a requisição para rastreio e vínculo, não para identificar a cobrança. Eles não servem como chave de idempotência: o mesmo lead pode comprar duas vezes legitimamente. A regra de propagação desses identificadores é transversal ao ecossistema, não deste serviço (ver Fronteiras).

4. Status único como árbitro da transação (Obrigatório)

A transação tem ciclo de vida governado por um campo status (vocabulário fechado), nunca flags booleanas que se contradizem (UNISCALE §29.4). A validação de sequência é do payment-service, no seu próprio banco, antes de publicar — ex.: "refund só após pagamento confirmado" (UNISCALE §28.6, que cita este serviço nominalmente). O core não valida transição nem segura evento por pré-condição: o serviço publica fatos já decididos.

O vocabulário é fechado:

Status Significado
pending cobrança criada, checkout aberto / PIX gerado — aguardando o pagador
processing enviado ao gateway, aguardando resultado
authorized cartão: valor reservado, aguardando ordem de captura (§7). Dinheiro não entrou
confirmed captura confirmada — o dinheiro entrou. Publica o fato (§2)
failed recusa definitiva (autorização negada ou captura recusada)
expired venceu sem conclusão: link/PIX não pago, ou autorização não capturada dentro do prazo do gateway
canceled cancelada antes de confirmar — por ordem do order-service (§7) ou por substituição da cobrança (§3)
refunded estornada após confirmada — estado existe, fluxo em versão futura (ver Fronteiras)

Transições permitidas:

  • Cartão: pending → processing → authorized → confirmed
  • PIX: pending → processing → confirmed (PIX não tem autorização/captura — é passo único)
  • Recusa: processing → failed · authorized → failed (captura recusada)
  • Vencimento: pending → expired · authorized → expired (a autorização tem prazo no gateway; se a ordem de captura não vier a tempo, ela vence e a cobrança recomeça)
  • Cancelamento: pending → canceled · authorized → canceled (cancelar implica desfazer a autorização no gateway, liberando o valor reservado)
  • Estorno: confirmed → refunded (versão futura)

5. Um payment-connector por gateway, fronteira nos dois sentidos (Obrigatório)

A mecânica de cada gateway fica atrás de um payment-connector por gateway (UNISCALE §7; regras de connector: cortex-docs/services/CONNECTORS.md). O gateway é substituível — o payment-service orquestra; o connector traduz (ECOSYSTEM §6). Trocar de gateway é trocar/reconfigurar o connector, sem mexer na orquestração nem no contrato com o ai-sales. O primeiro é o dom-pagamentos-connector.

O connector é a única fronteira com o gateway, nos dois sentidos:

  • Saída — toda requisição ao gateway (autorizar, capturar, cancelar) sai pelo connector, que traduz o contrato interno para a API do gateway.
  • Entrada — o webhook do gateway entra pelo connector, que traduz e repassa ao payment-service. O connector não decide nada e não guarda estado (CONNECTORS §1): quem interpreta, decide e persiste é o serviço.
  • Resposta ao gateway — o retorno que o gateway espera do webhook (ok/erro) volta pelo connector, refletindo o que o serviço decidiu.

O payment-service não fala com o gateway e o connector não é dono de transação. É essa separação que mantém o gateway substituível.

6. Dado de cartão nunca entra no CORTEX (Obrigatório)

A validação e a guarda do cartão são 100% do gateway. O front tokeniza o cartão com o SDK do gateway, e o que chega ao backend do CORTEX é apenas o token; a requisição de pagamento é feita pelo backend com o token, nunca com o dado do cartão.

Nenhum dado de cartão (PAN, CVV, validade, titular) trafega, é logado ou é persistido em qualquer ponto do CORTEX — nem em requisição, nem em log, nem em banco, nem em evento. Isto é invariante de segurança, não otimização: é o que mantém o dado de cartão fora do escopo do CORTEX. Implementação que faça o cartão passar pelo backend viola esta regra, mesmo que "só de passagem".

(A classificação PCI formal decorrente deste desenho é acordada com o gateway — a regra arquitetural, porém, é esta e não depende disso.)

7. Duas fases: autoriza, e captura por ordem do dono da regra (Obrigatório)

No cartão, autorização e captura são passos separados e existe decisão de negócio entre eles.

  1. O pagamento é autorizado no gateway → a transação vai a authorized (valor reservado, dinheiro não entrou) e o serviço publica o fato da autorização (§2).
  2. O order-service valida se a venda ainda pode ser executada — vaga ainda disponível, produto ainda existente, valores corretos. Essa checagem é necessária porque existe janela entre a proposta e o pagamento (o link pode viver por dezenas de horas), e nela a realidade muda.
  3. O order-service ordena ao payment-service: capturar ou cancelar.
    • Capturar → confirmed, publica payment.transaction.confirmed (§2), e é esse fato que destrava a matrícula.
    • Cancelar → canceled, desfazendo a autorização no gateway (o valor reservado é liberado) — a venda não fecha e a matrícula não ocorre.

O payment-service não faz essa validação e não a consulta. Ele não sabe o que torna uma venda válida — ele executa a ordem de quem sabe. É isso que preserva a §1 e evita que a entrada de dinheiro dependa da disponibilidade de outro serviço para decidir (a ordem chega quando chega; enquanto não chega, a transação fica em authorized até a autorização vencer — §4).

PIX não tem esta divisão: é passo único, confirmado direto pelo webhook.

8. Superfície exposta à internet: checkout e webhook (Obrigatório)

Só duas superfícies do fluxo de pagamento são acessíveis pela internet, e cada uma por um motivo:

  • A página de checkout (e o formulário pós-checkout), hospedada pelo payment-service — porque o pagador precisa abri-la.
  • O endpoint de webhook, no dom-pagamentos-connector — porque o gateway precisa chamá-lo (§5: o webhook entra pelo connector).

Todo o resto do payment-service é interno — não há API pública de transação. Superfície exposta é superfície atacável: ampliar essa lista é decisão de segurança, não conveniência de implementação.


Fronteiras a definir (não inventar)

Decisões ainda não tomadas — o construtor para e pergunta (FALLBACK), não chuta:

  • Refund / cancelamento / estorno de valor confirmado — fluxo adiado conscientemente para versão futura (ECOSYSTEM §7). Há o estado (refunded) e a regra de sequência (§4), não o desenho do fluxo. Chargeback também não está desenhado.
  • Falha de matrícula depois da captura — risco declarado e aceito. Se a matrícula falhar após o dinheiro capturado (jacad indisponível, vaga encerrada no instante), não há compensação automática nesta versão: o ai-sales é notificado para avisar o comprador e uma pessoa é notificada para atuar manualmente; o dinheiro permanece capturado até essa ação. O payment-service não notifica ninguém — ele publica fatos; quem notifica são os serviços que consomem. A validação pré-captura (§7) reduz a janela, não a elimina.
  • Forma do comando de captura/cancelamento (§7) — se o order-service ordena por chamada direta ou por fila é decisão de mecanismo, ainda em aberto. A regra fixa quem decide, não o transporte.
  • Prazo de validade da autorização (§4, authorized → expired) — depende do Dom Pagamentos; ler a API real, não presumir.
  • Contrato exato do que o ai-sales envia na criação da cobrança — além da chave de idempotência e dos identificadores de correlação, os campos são acordados com o ai-sales, que ainda não foi construído.
  • Schema do formulário pós-checkout e dos campos coletados — derivado caso a caso do que o ai-sales manda; não há schema fixo (coerente com "docs documentam o como, não o schema").
  • Propagação de lead_id / person_id é transversal. A decisão de que esses identificadores acompanham toda requisição do ecossistema não é regra deste serviço — pertence ao UNISCALE/ECOSYSTEM e ainda não está escrita lá. Aqui ela aparece só como consumo (§3).
  • Regra recíproca no order-service — como ele é quem valida e ordena a captura (§7), o doc dele precisa da regra-irmã: o que exatamente é validado, em que prazo, e o que faz quando a ordem falha. Enquanto não escrita lá, quem for implementar o lado do order-service para e pede a regra.

CHANGELOG

Versão Data Resumo
0.2.0 2026-07-23 Fecha as fronteiras que travavam o build e acrescenta três regras. Escopo fixado: cartão e PIX (boleto fora); primeiro gateway Dom Pagamentos (dom-pagamentos-connector). Regras novas: §6 dado de cartão nunca entra no CORTEX (front tokeniza via SDK do gateway; backend só usa token; nada de PAN/CVV em requisição, log, banco ou evento) — invariante de segurança que mantém o cartão fora do escopo; §7 duas fases — autorização reserva o valor e publica o fato, o order-service valida (vaga/produto/valores, porque a janela do link permite a realidade mudar) e ordena capturar ou cancelar, e o payment-service obedece sem consultar nada (preserva a §1 e evita dependência de disponibilidade); §8 superfície exposta à internet limitada a checkout (no serviço) e webhook (no connector). Regras alteradas: §2 passa a fixar que o fato de confirmação sai na captura, não na autorização, e lista os demais fatos publicados (authorized — gatilho do order-service, failed, expired — fallback de PIX expirado do ai-sales); §3 define as duas chaves de idempotência — a chave do chamador, gerada pelo ai-sales e reenviada em caso de perda (é ela que reconecta o ciclo e impede cobrança órfã), e a chave do gateway no webhook —, fixa que produtos distintos têm chaves distintas e que redefinir a negociação gera chave nova cancelando a anterior, e registra que lead_id/person_id são correlação, não idempotência; §4 ganha o vocabulário fechado de status (pending, processing, authorized, confirmed, failed, expired, canceled, refunded) com as transições permitidas, incluindo authorized → canceled (desfaz a autorização no gateway) e authorized → expired; §5 fixa que o connector é a fronteira nos dois sentidos (requisições saem por ele, webhook entra por ele, resposta ao gateway volta por ele) e nomeia o dom-pagamentos-connector. Fronteiras atualizadas: falha de matrícula pós-captura vira risco declarado e aceito (sem compensação automática; notificação ao comprador via ai-sales e a um humano para atuar); acrescenta forma do comando de captura, prazo da autorização no gateway, contrato do ai-sales, natureza transversal da propagação de lead_id/person_id e a regra recíproca no order-service. MINOR.
0.1.1 2026-06-17 Editorial (sem mudança de regra): serviço consumidor renomeado fulfillment → order-service na §2. PATCH.
0.1.0 2026-06-15 Rascunho inicial do payment-service. Promove a @rule endereçável as decisões já assentadas no ECOSYSTEM §4/§5: cobra sem saber o que vende (§1), confirmação só pelo fato payment.transaction.confirmed (§2), checkout stateful/idempotente (§3), status único com validação de sequência no próprio serviço (§4, UNISCALE §28.6/§29.4), um payment-connector por gateway substituível (§5). Lista as fronteiras em aberto (refund, chave de idempotência, schema do formulário, vocabulário de status) como NÃO-inventar. Regras no namespace ecosystem, área services.