프로모션 코드 및 할인 구현

이 가이드는 Universal Commerce Protocol (UCP) 버전 2026-04-08에서 프로모션 코드 및 할인을 처리하기 위한 기술 API 참조 및 페이로드 스키마를 제공합니다.

엔드포인트를 빌드하기 전에 프로모션 코드 및 할인 개요에서 대략적인 개념, 수학적 불변성, 오류 처리 규칙을 검토했는지 확인하세요.

디스커버리

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

혼합 할인 (상품 + 주문 수준)

이 예에서는 두 가지 할인 유형을 보여줍니다. 광고 항목에 할당된 상품별 할인 (20% 할인)과 주문 수준의 자동 배송 할인입니다.

요청 예시:

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