R-001 — Desconto de membro exige validação do email no servidor

TLDR: o desconto só é aplicado quando o serviço de validação confirma que o email é de membro; qualquer outra resposta — inclusive falha — resulta em preço cheio.

Given / When / Then

Dado um checkout com discount_amount > 0 e discount_validation_url presente (discount_enabled?), Quando o comprador submete a compra com um email que o serviço de validação responde 200 + { "valid": true }, Então o discount_amount é abatido da base antes do cálculo dos juros de parcelamento, e o total descontado é o que vai para @payment.total e para o totalValue do gateway.

Dado o mesmo checkout, Quando a validação responde valid: false, não-200, dá timeout (5s) ou lança erro, Então o preço cheio é cobrado.

Dado um checkout sem discount_validation_url, Quando qualquer compra é feita, Então o serviço de validação não é instanciado e o total é exatamente o de um checkout sem desconto.

Tabela de decisão

discount_enabled? Resposta da validação Resultado
false (nenhuma chamada é feita) Preço cheio
true 200 + { "valid": true } Desconto abatido da base
true 200 + { "valid": false } Preço cheio
true Status não-200 Preço cheio
true Timeout (5s) Preço cheio
true Corpo não é JSON válido Preço cheio

Restrições

  • A validação é sempre refeita no servidor no momento da compra. O frontend nunca controla o total.
  • O fallback é seguro por construção: toda falha resulta em preço cheio, nunca em desconto indevido.
  • O token vai no header fixo X-DISCOUNT-ACCESS-TOKEN, lido de checkouts.discount_access_token — é por checkout, não global.
  • A regra vale apenas no fluxo v1 de compra (CheckoutService). O fluxo v2 (Payments::Creation::CreateFlow) não consulta o desconto.
  • Cross-sell (cross_sell_items) não recebe desconto.
  • A revalidação no submit abre uma janela: se a validação passa na digitação e falha na compra, o cliente vê preço com desconto e é cobrado preço cheio, sem aviso.

Teste vinculado

spec/services/checkout_service_spec.rb — “applies the discount to the payment total when the email is a valid member” spec/services/checkout_service_spec.rb — “sends the discounted total to the gateway when the email is a valid member” spec/services/checkout_service_spec.rb — “keeps the full total when the email is not a valid member” spec/services/checkout_service_spec.rb — “applies the discount to the checkout payment type total when the checkout uses payment types” spec/services/checkout_service_spec.rb — “does not instantiate the validation service and keeps the full total when the checkout has no discount url” spec/services/member_discount_validation_service_spec.rb — “returns false without calling the endpoint when the discount is not enabled” spec/services/member_discount_validation_service_spec.rb — “returns false when the request times out”

Referências