Pular para conteúdo

Extensão de desconto

Visão geral

A extensão de desconto permite que as empresas indiquem que apoiam descontos códigos nas sessões de carrinho e checkout e especifica como os códigos de desconto são a ser compartilhado entre a plataforma e o negócio.

Principais recursos:

  • Envie um ou mais códigos de desconto
  • Receba descontos aplicados com títulos e valores legíveis por humanos
  • Códigos rejeitados comunicados via messages[] com códigos de erro detalhados
  • Descontos automáticos surgiram junto com descontos baseados em código

Dependências:

  • Capacidade de carrinho ou capacidade de checkout

Descoberta

As empresas anunciam suporte a descontos em seus perfis. A capacidade pode estender carrinho, checkout ou ambos:json { "ucp": { "version": "2026-07-14", "capabilities": { "br.dev.bcp.shopping.discount": [ { "version": "2026-07-14", "extends": ["br.dev.bcp.shopping.cart", "br.dev.bcp.shopping.checkout"], "spec": "https://bcp.dev.br/2026-07-14/specification/discount", "schema": "https://bcp.dev.br/2026-07-14/schemas/shopping/discount.json" } ] } } }As empresas PODEM anunciar suporte com desconto apenas para carrinho, somente finalização de compra ou ambos. As plataformas DEVEM verificar quais recursos são estendidos antes de enviar códigos de desconto.

Esquema

Quando esse recurso está ativo, o carrinho e/ou checkout são estendidos com um Objeto discounts.

Objeto de descontos

Discount codes input and applied discounts output.

Name Type Required Description
codes Array[string] No Discount codes to apply. Case-insensitive. Replaces previously submitted codes. Send empty array to clear.
applied Array[object] No Discounts successfully applied (code-based and automatic).

Desconto Aplicado

A discount that was successfully applied.

Name Type Required Description
code string No The discount code. Omitted for automatic discounts.
title string Yes Human-readable discount name (e.g., 'Summer Sale 20% Off').
amount integer Yes Total discount amount in ISO 4217 minor units.
automatic boolean No True if applied automatically by merchant rules (no code required).
method string No Allocation method. 'each' = applied independently per item. 'across' = split proportionally by value.
Enum: each, across
priority integer No Stacking order for discount calculation. Lower numbers applied first (1 = first).
provisional boolean No True if this discount requires additional verification.
eligibility string No The eligibility claim accepted by the Business for this discount. Corresponds to a value from context.eligibility. Omitted for code-based and non-eligibility automatic discounts.
allocations Array[object] No Breakdown of where this discount was allocated. Sum of allocation amounts equals total amount.

Alocação

Breakdown of how a discount amount was allocated to a specific target.

Name Type Required Description
path string Yes JSONPath to the allocation target (e.g., '$.line_items[0]', '$.totals.shipping').
amount integer Yes Amount allocated to this target in ISO 4217 minor units.

Detalhes de alocação

A matriz applied explica como os descontos foram calculados e distribuídos. O applied[].amount descreve a magnitude do desconto aplicado (sempre positivo); o valor da entrada totals[] correspondente representa seu valor assinado efeito no recebimento (negativo para descontos).

Método de alocação

O campo method indica como foi calculado o desconto:

Método Significado Exemplo
each Aplicado de forma independente por item elegível “10% de desconto em cada item” → 10% × preço do item
across Dividir proporcionalmente por valor "Desconto de $ 10 no pedido" → item de $ 6 a $ 60, item de $ 4 a $ 40

Ordem de empilhamento

Quando são aplicados descontos múltiplos, priority indica a ordem de cálculo. Números mais baixos são aplicados primeiro:text Cart: $100 Discount A (priority: 1): 20% off → $100 × 0.8 = $80 Discount B (priority: 2): $10 off → $80 - $10 = $70A ordem é importante porque os descontos percentuais são compostos de forma diferente dependendo quando eles são aplicados.

Matriz de Alocações

A matriz allocations divide onde cada dólar de desconto foi parar, usando JSONPath para identificar alvos:

Padrão de caminho Alvo
$.line_items[0] Item de primeira linha
$.line_items[1] Segunda linha
$.totals.shipping Custos de envio

Isso permite que as plataformas expliquem exatamente quanto cada desconto contribuiu para cada item de linha, mesmo quando vários descontos se acumulam.

Invariante: Soma de allocations[].amount é igual a applied_discount.amount.

Operações

Os códigos de desconto são enviados por meio do carrinho padrão ou da finalização da compra, criação/atualização operações. A mesma semântica se aplica a ambos os recursos.

Solicitar comportamento:

  • Semântica de substituição: o envio de discounts.codes substitui quaisquer códigos enviados anteriormente
  • Limpar códigos: Envie o array vazio "codes": [] para remover todos os códigos de desconto
  • Não diferencia maiúsculas de minúsculas: os códigos são correspondidos sem distinção entre maiúsculas e minúsculas por empresa

Comportamento de resposta:

  • discounts.applied contém todos os descontos ativos (baseados em código + automáticos)
  • Códigos rejeitados comunicados via messages[] (veja abaixo)
  • Valores de desconto refletidos em totals[] e line_items[].totals[]

Continuidade do carrinho até a finalização da compra: quando um carrinho é convertido em finalização da compra por meio do campo cart_id da capacidade do carrinho, as empresas DEVEM transferir qualquer desconto códigos que foram aplicados ao carrinho. Códigos que não são mais válidos na finalização da compra tempo (por exemplo, expirado, inelegível) DEVE ser comunicado via messages[] usando códigos de rejeição padrão.

Códigos rejeitados

Quando um código de desconto enviado não pode ser aplicado, as empresas comunicam isso através da matriz messages[]:json [ { "type": "warning", "code": "discount_code_expired", "path": "$.discounts.codes[0]", "content": "Code 'SUMMER20' expired on December 1st" } ]> Orientação de implementação: Operações que afetam os totais dos pedidos ou o

expectativa do usuário em relação ao total, DEVE usar type: "warning" para garantir eles são apresentados ao usuário em vez de manipulados silenciosamente pelas plataformas. Descontos rejeitados são um excelente exemplo: o usuário espera um desconto, mas não o faz recebê-lo, por isso devem ser informados.

Códigos de erro para descontos rejeitados:

Código Descrição
discount_code_expired O código expirou
discount_code_invalid Código não encontrado ou malformado
discount_code_already_applied O código já está aplicado
discount_code_combination_disallowed Não acumulável com outro desconto ativo
discount_code_user_not_logged_in O código requer usuário autenticado
discount_code_user_ineligible O usuário não atende aos critérios de elegibilidade

Descontos Automáticos

As empresas podem aplicar descontos automaticamente com base no conteúdo do carrinho, cliente segmento ou regras promocionais:

  • Aparecer em discounts.applied com automatic: true e sem campo code
  • Aplicado sem ação de plataforma
  • Não pode ser removido pela plataforma
  • Apresentado para transparência (a plataforma pode explicar ao usuário por que o desconto foi aplicado)

Reivindicações de elegibilidade

As reivindicações de elegibilidade são reivindicações do comprador sobre benefícios elegíveis (consulte Contexto), como associação de fidelidade, instrumento de pagamento vantagens e similares. Quando a extensão de desconto está ativa, as empresas que optar por aceitar reivindicações de elegibilidade DEVE revelar seu efeito nos preços como descontos provisórios na matriz applied. Plataformas DEVEM ser exibidas descontos provisórios ao comprador.

Comportamento de desconto

As plataformas enviam reclamações do comprador via context.eligibility no carrinho ou finalização da compra solicitações (consulte Contexto). Quando uma empresa reconhece um reivindicação e afetar o preço, ela DEVE apresentar uma declaração provisória correspondente desconto na matriz discounts.applied. Isto dá à Plataforma estruturada atribuição para exibir ao comprador.

Os descontos acionados por elegibilidade usam os seguintes campos:

Campo Valor Finalidade
automatic true Nenhum código necessário
provisional true Requer verificação na conclusão
eligibility "com.example.store_card" A reivindicação aceita
code (omitido) Não baseado em código

Os campos padrão priority, method e allocations aplicam-se ao empilhamento com outros descontos.

Verificação na finalização da compra

Os descontos de reivindicações aceitas, mas não verificadas, são provisional: true. Os descontos provisórios permanecem até que a reclamação seja verificada, rescindida ou substituído durante a sessão. Na conclusão da finalização da compra, todos os itens provisórios restantes reivindicações DEVEM ser resolvidas (consulte Verificação de elegibilidade na conclusão).

Exemplo: Desconto Provisório com Atribuição

Com base no exemplo do cartão da loja de Verificação de elegibilidade na conclusão, a extensão de desconto fornece atribuição estruturada. A Plataforma reivindica um benefício do cartão da loja; a empresa apresenta o desconto provisório com total detalhes de empilhamento e alocação:

=== "Solicitação"json { "context": { "eligibility": ["com.example.store_card"] }, "line_items": [ { "item": { "id": "prod_shirt" }, "quantity": 2 } ] }=== "Resposta"json { "ucp": { ... }, "id": "...", "currency": "...", "line_items": [ ... ], "discounts": { "applied": [ { "title": "Store Card 5% Off", "amount": 250, "automatic": true, "provisional": true, "eligibility": "com.example.store_card", "priority": 1, "method": "each", "allocations": [ {"path": "$.line_items[0]", "amount": 250} ] } ] }, "totals": [ {"type": "subtotal", "display_text": "Subtotal", "amount": 5000}, {"type": "items_discount", "display_text": "Discounts", "amount": -250}, {"type": "total", "display_text": "Total", "amount": 4750} ] }A plataforma agora pode renderizar: "Cartão da loja com 5% de desconto: -$2,50 (verificado em compra)" com total confiança na atribuição, valor e alocação.

Impacto em itens de linha e totais

Os descontos aplicados são refletidos nos campos principais do carrinho ou checkout usando dois tipos totais distintos:

Tipo total Quando usar
items_discount Descontos atribuídos a itens de linha ($.line_items[*])
discount Descontos no nível do pedido (frete, taxas, valor fixo do pedido)

Determinando o tipo: Se um desconto tiver allocations apontando para linha itens, contribui para items_discount. Descontos sem alocações, ou com alocações para frete/taxas, contribua para discount.

Tipo de desconto Onde refletido
Desconto em itens de linha line_items[].totals[type=items_discount]
Desconto no nível do pedido totals[type=discount]

Invariante: totals[type=items_discount].amount é igual sum(line_items[].totals[type=items_discount].amount).

A matriz discounts.applied mostra o que foi aplicado. O totals[] e line_items[].totals[] mostra onde e quanto.

Convenção de valor: Os valores de desconto em discounts.applied são positivos inteiros (o valor do desconto). As entradas de desconto em totals[] são negativo (o efeito no recibo) — o sinal é aplicado pelo esquema.

Exemplos

Carrinho com códigos de desconto

Códigos de desconto aplicados durante a exploração do carrinho. A resposta do carrinho inclui valores estimados de desconto, dando ao comprador visibilidade sobre a economia antes procedendo à finalização da compra.

=== "Solicitação"json { "line_items": [ { "item": { "id": "prod_1" }, "quantity": 2 } ], "discounts": { "codes": ["SUMMER20"] } }=== "Resposta"json { "ucp": { ... }, "id": "cart_abc123", "currency": "USD", "line_items": [ { "id": "li_1", "item": { "id": "prod_1", "title": "T-Shirt", "price": 2000 }, "quantity": 2, "totals": [ {"type": "subtotal", "amount": 4000}, {"type": "items_discount", "amount": -800}, {"type": "total", "amount": 3200} ] } ], "discounts": { "codes": ["SUMMER20"], "applied": [ { "code": "SUMMER20", "title": "Summer Sale 20% Off", "amount": 800, "method": "each", "allocations": [ {"path": "$.line_items[0]", "amount": 800} ] } ] }, "totals": [ {"type": "subtotal", "display_text": "Subtotal", "amount": 4000}, {"type": "items_discount", "display_text": "Item Discounts", "amount": -800}, {"type": "total", "display_text": "Estimated Total", "amount": 3200} ] }### Desconto no nível do pedido

Um desconto fixo aplicado ao total do pedido. Sem alocações – o desconto se aplica ao pedido como um todo e utiliza type: "discount" nos totais.

=== "Solicitação"json { "id": "...", "line_items": [ ... ], "discounts": { "codes": ["SAVE10"] } }=== "Resposta"json { "ucp": { ... }, "id": "...", "currency": "...", "line_items": [ ... ], "discounts": { "codes": ["SAVE10"], "applied": [ { "code": "SAVE10", "title": "$10 Off Your Order", "amount": 1000 } ] }, "totals": [ {"type": "subtotal", "display_text": "Subtotal", "amount": 5000}, {"type": "discount", "display_text": "Order Discount", "amount": -1000}, {"type": "total", "display_text": "Total", "amount": 4000} ] }### Descontos mistos (item + nível do pedido)

Este exemplo mostra os dois tipos de desconto: um desconto por item (20% de desconto) alocado para itens de linha e um desconto de frete automático no nível do pedido.

=== "Solicitação"json { "id": "...", "line_items": [ ... ], "discounts": { "codes": ["SUMMER20"] } }=== "Resposta"json { "ucp": { ... }, "id": "...", "currency": "...", "line_items": [ { "id": "li_1", "item": { "id": "prod_1", "title": "T-Shirt", "price": 2000 }, "quantity": 2, "totals": [ {"type": "subtotal", "amount": 4000}, {"type": "items_discount", "amount": -800}, {"type": "total", "amount": 3200} ] } ], "discounts": { "codes": ["SUMMER20"], "applied": [ { "code": "SUMMER20", "title": "Summer Sale 20% Off", "amount": 800, "allocations": [ {"path": "$.line_items[0]", "amount": 800} ] }, { "title": "Free shipping on orders over $30", "amount": 599, "automatic": true } ] }, "totals": [ {"type": "subtotal", "display_text": "Subtotal", "amount": 4000}, {"type": "items_discount", "display_text": "Item Discounts", "amount": -800}, {"type": "discount", "display_text": "Order Discounts", "amount": -599}, {"type": "fulfillment", "display_text": "Shipping", "amount": 0}, {"type": "total", "display_text": "Total", "amount": 2601} ] }### Código de desconto rejeitado

Quando não for possível aplicar um código de desconto, a rejeição é comunicada através do Matriz messages[]. O código ainda aparece em discounts.codes (ecoado de volta) mas não em discounts.applied.

=== "Solicitação"json { "id": "...", "line_items": [ ... ], "discounts": { "codes": ["SAVE10", "EXPIRED50"] } }=== "Resposta"json { "ucp": { ... }, "id": "...", "currency": "...", "line_items": [ ... ], "discounts": { "codes": ["SAVE10", "EXPIRED50"], "applied": [ { "code": "SAVE10", "title": "$10 Off Your Order", "amount": 1000 } ] }, "totals": [ {"type": "subtotal", "display_text": "Subtotal", "amount": 5000}, {"type": "discount", "display_text": "Order Discount", "amount": -1000}, {"type": "total", "display_text": "Total", "amount": 4000} ], "messages": [ { "type": "warning", "code": "discount_code_expired", "path": "$.discounts.codes[1]", "content": "Code 'EXPIRED50' expired on December 1st" } ] }### Descontos acumulados com alocações

Vários descontos aplicados com detalhamento total da alocação:

=== "Resposta"json { "ucp": { ... }, "id": "...", "currency": "...", "line_items": [ { "id": "li_1", "item": { "id": "prod_1", "title": "T-Shirt", "price": 6000 }, "quantity": 1, "totals": [ {"type": "subtotal", "amount": 6000}, {"type": "items_discount", "amount": -1500}, {"type": "total", "amount": 4500} ] }, { "id": "li_2", "item": { "id": "prod_2", "title": "Socks", "price": 4000 }, "quantity": 1, "totals": [ {"type": "subtotal", "amount": 4000}, {"type": "items_discount", "amount": -1000}, {"type": "total", "amount": 3000} ] } ], "discounts": { "codes": ["SUMMER20", "LOYALTY5"], "applied": [ { "code": "SUMMER20", "title": "Summer Sale 20% Off", "amount": 2000, "method": "each", "priority": 1, "allocations": [ {"path": "$.line_items[0]", "amount": 1200}, {"path": "$.line_items[1]", "amount": 800} ] }, { "code": "LOYALTY5", "title": "$5 Loyalty Reward", "amount": 500, "method": "across", "priority": 2, "allocations": [ {"path": "$.line_items[0]", "amount": 300}, {"path": "$.line_items[1]", "amount": 200} ] } ] }, "totals": [ {"type": "subtotal", "display_text": "Subtotal", "amount": 10000}, {"type": "items_discount", "display_text": "Item Discounts", "amount": -2500}, {"type": "total", "display_text": "Total", "amount": 7500} ] }Com esses dados, um agente pode explicar:

"Sua camiseta (US$ 60) ganhou US$ 12 de desconto na promoção de verão de 20%, mais US$ 3 do seu recompensa de fidelidade (dividida proporcionalmente). Economia total neste item: $ 15.