實作促銷代碼和折扣

本指南提供技術 API 參考資料和酬載結構定義,說明如何處理通用商務通訊協定 (UCP) 2026-04-08 版的促銷代碼和折扣。

建立端點前,請務必先查看促銷代碼和折扣總覽,瞭解高階概念、數學不變量和錯誤處理規則。

探索

如要取得 Google 提供的折扣代碼,你必須在個人資料中宣傳折扣支援。在 2026-04-08 版中,平台會先檢查結帳功能是否已擴充,再提交折扣代碼。

{
  "ucp": {
    "version": "2026-04-08",
    "capabilities": {
      "dev.ucp.shopping.discount": [
        {
          "version": "2026-04-08",
          "extends": ["dev.ucp.shopping.checkout"],
          "spec": "https://ucp.dev/2026-04-08/specification/discount",
          "schema": "https://ucp.dev/2026-04-08/schemas/shopping/discount.json"
        }
      ]
    }
  }
}

對委刊項和總計的影響

系統會使用兩種不同的總計類型,在核心結帳欄位中顯示套用的折扣。如果折扣allocations指向委刊項,就會計入items_discount。未分配的折扣,或分配給運費或手續費的折扣,會計入 discount

折扣類型 總計類型 反映位置
委刊項折扣 items_discount line_items[].totals[type=items_discount]
訂單層級折扣 discount totals[type=discount]

版本規定:

2026-04-08 版本中,totals[]line_items[].totals[] 中的折扣項目必須使用負值,才能反映折扣對收據的扣減效果。discounts.appliedallocations 陣列中的金額一律為正整數。

自動套用促銷活動的 API 範例

以下範例說明如何自動套用折扣。要求酬載不含 discounts.codes 陣列,但回應會包含 "automatic": true,並省略 code 欄位。

自動套用的商品層級折扣

系統自動將 10% 的全站特價套用至特定委刊項。

要求範例:

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "title": "Sneakers", "price": 10000 },
      "quantity": 1
    }
  ]
}

回應範例:

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "title": "Sneakers", "price": 10000 },
      "quantity": 1,
      "totals": [
        {"type": "subtotal", "amount": 10000},
        {"type": "items_discount", "amount": -1000},
        {"type": "total", "amount": 9000}
      ]
    }
  ],
  "discounts": {
    "applied": [
      {
        "title": "10% Off Sitewide Sale",
        "amount": 1000,
        "automatic": true,
        "method": "each",
        "allocations": [
          {"path": "$.line_items[0]", "amount": 1000}
        ]
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 10000},
    {"type": "items_discount", "display_text": "Item Discounts", "amount": -1000},
    {"type": "total", "display_text": "Total", "amount": 9000}
  ]
}

自動套用的訂單層級折扣

套用至整筆訂單的促銷規則 (例如「訂單滿 $50 美元即享 $10 美元折扣」),但未指定委刊項分配。

要求範例:

{
  "line_items": [ ... ]
}

回應範例:

{
  "line_items": [ ... ],
  "discounts": {
    "applied": [
      {
        "title": "$10 Off Orders Over $50",
        "amount": 1000,
        "automatic": true
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 6000},
    {"type": "discount", "display_text": "Order Promo", "amount": -1000},
    {"type": "total", "display_text": "Total", "amount": 5000}
  ]
}

使用者套用促銷活動的 API 範例

以下範例說明使用者輸入宣傳代碼後觸發的折扣。要求酬載包含所要求的代碼,而回應會回傳這些代碼,同時分配套用的金額。

訂單層級折扣

訂單總額將扣除固定折扣金額。不需要分配,折扣會套用至整個訂單,並使用 type: "discount"

要求範例:

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SAVE10"]
  }
}

回應範例:

{
  "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}
  ]
}

混合折扣 (商品和訂單層級)

這個範例顯示兩種折扣類型:分配給委刊項的每項商品折扣 (8 折),以及訂單層級的自動運費折扣。

要求範例:

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SUMMER20"]
  }
}

回應範例:

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "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}
  ]
}

遭拒的折扣碼

如果代碼無效,系統會在 codes 中回顯該代碼,但會從 applied 中省略。拒絕要求時,系統會使用 messages[] 陣列中的 warning 傳達拒絕訊息。

要求範例:

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SAVE10", "EXPIRED50"]
  }
}

回應範例:

{
  "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"
    }
  ]
}

搭配配額使用的折扣

套用多項折扣,並提供完整分配明細。

要求範例:

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SUMMER20", "EXTRA5"]
  }
}

回應範例:

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "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": { "title": "Socks", "price": 4000 },
      "quantity": 1,
      "totals": [
        {"type": "subtotal", "amount": 4000},
        {"type": "items_discount", "amount": -1000},
        {"type": "total", "amount": 3000}
      ]
    }
  ],
  "discounts": {
    "codes": ["SUMMER20", "EXTRA5"],
    "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": "EXTRA5",
        "title": "Extra $5 Off",
        "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}
  ]
}