> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 원하는 가격으로 동적 가격 책정 체크아웃

> 단일 제품을 사용하여 가변 가격으로 유연한 체크아웃 링크를 생성합니다. 고객이 가격을 선택할 수 있도록 원하는 가격 지불(Pay What You Want)을 활성화하거나 프로그래밍 방식으로 동적 금액을 설정합니다.

**동적 가격 책정**을 사용하면 여러 제품 항목을 생성하지 않고도 제품에 대해 가변 가격을 제공할 수 있습니다. 단일 제품에서 \*\*원하는 가격 지불(Pay What You Want, PWYW)\*\*을 활성화하면 최소 및 최대 가격 범위를 설정한 다음 체크아웃 세션 링크를 생성할 때 동적 금액을 전달할 수 있습니다.

이 접근 방식은 다음과 같은 경우에 이상적입니다:

* **가변 가격**을 관리할 필요 없이 여러 제품을 관리하지 않음
* 구매자가 금액을 선택하는 **고객 주도 가격 책정**
* API를 통해 동적으로 금액을 설정하는 **프로그래밍 방식 가격 제어**
* 디지털 제품, 기부 또는 실험적 출시를 위한 **유연한 가격 모델**

<Warning>
  Pay What You Want은 **Single Payment**(일회성 결제) 상품에서만 제공됩니다. 구독 상품에는 사용할 수 없습니다.
</Warning>

## 작동 방식

원하는 가격 지불이 활성화되면 다음을 수행할 수 있습니다:

1. **가격 범위 설정**: 최소 가격(필수)을 정의하고 선택적으로 최대 가격 설정
2. **동적 금액 전달**: 체크아웃 세션을 생성할 때 상품 카트에 `amount` 필드를 포함하세요
3. **고객이 선택하도록 허용**: 금액이 제공되지 않으면 고객이 자신의 가격을 입력할 수 있습니다(설정한 최소/최대 범위 내에서)

<Info>
  상품 카트에 `amount`을 전달하면 해당 금액이 결제에 사용됩니다. `amount` 필드를 생략하면 고객이 체크아웃 중에 자신만의 가격을 선택할 수 있습니다(설정한 최소/최대 범위 내에서).
</Info>

## 1단계: 원하는 가격 지불이 있는 제품 생성

먼저 Dodo Payments 대시보드에서 일회성 제품을 생성하고 원하는 가격 지불 가격 책정을 활성화합니다.

<Steps>
  <Step title="Create a new product">
    Dodo Payments 대시보드에서 **Products**로 이동한 다음 **Add Product**를 클릭하세요.
  </Step>

  <Step title="Configure product details">
    필수 상품 정보를 입력하세요:

    * **Product Name**: 상품에 표시될 이름
    * **Product Description**: 고객이 구매하는 항목에 대한 명확한 설명
    * **Product Image**: 이미지 업로드(PNG/JPG/WebP, 최대 3MB)
    * **Tax Category**: 적절한 세금 카테고리 선택
  </Step>

  <Step title="Set pricing type">
    **Pricing Type**을 **Single Payment**(일회성 결제)로 선택하세요.
  </Step>

  <Step title="Enable Pay What You Want">
    **Pricing** 섹션에서 **Pay What You Want** 토글을 활성화하세요.
  </Step>

  <Step title="Set minimum price">
    고객이 지불해야 할 **최소 가격**을 입력하세요. 이는 필수이며 수익 하한을 보장합니다.

    **예시**: 최소가 \$5.00이라면 `5.00`(또는 `500` 센트)를 입력하세요.
  </Step>

  <Step title="Set maximum price (optional)">
    선택적으로 고객이 지불할 수 있는 금액에 상한을 두기 위해 **최대 가격**을 설정하세요.
  </Step>

  <Step title="Set suggested price (optional)">
    선택적으로 고객에게 안내할 **추천 가격**을 입력하세요. 이는 기대치를 고정하는 데 도움이 되며 평균 주문 금액을 높일 수 있습니다.
  </Step>

  <Step title="Save the product">
    **Add Product**를 클릭하여 저장하세요. 체크아웃 세션에서 사용할 상품 ID(예: `pdt_123abc456def`)를 기록해 두세요.
  </Step>
</Steps>

<Tip>
  대시보드의 **Products** → **View Details** 또는 [List Products API](/api-reference/products/get-products)를 통해 상품 ID를 확인할 수 있습니다.
</Tip>

## 2단계: 동적 가격으로 체크아웃 세션 생성

제품이 Pay What You Want으로 구성되면 동적 금액을 사용하여 체크아웃 세션을 생성할 수 있습니다. 상품 카트의 `amount` 필드는 각 체크아웃 세션마다 가격을 프로그래밍 방식으로 설정할 수 있게 해줍니다.

### 금액 필드 이해하기

체크아웃 세션을 생성할 때 각 상품 카트 항목에 `amount` 필드를 포함할 수 있습니다:

* **`amount`가 제공된 경우**: 체크아웃은 이 정확한 금액을 사용합니다(최소/최대 범위 내여야 함)
* **`amount`가 생략된 경우**: 고객은 체크아웃 중에 자신의 가격을 입력할 수 있습니다(설정 범위 내에서)

<Warning>
  `amount` 필드는 Pay What You Want 상품에만 적용됩니다. 일반 상품에서는 이 필드를 무시합니다.
</Warning>

### 코드 예제

<CodeGroup>
  ```typescript TypeScript theme={null}
  import DodoPayments from 'dodopayments';

  // Initialize the Dodo Payments client
  const client = new DodoPayments({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
  });

  async function createDynamicPricingCheckout(
    productId: string,
    amountInCents: number,
    returnUrl: string
  ) {
    try {
      const session = await client.checkoutSessions.create({
        product_cart: [
          {
            product_id: productId,
            quantity: 1,
            // Dynamic amount in cents (e.g., 1500 = $15.00)
            amount: amountInCents
          }
        ],
        return_url: returnUrl,
        // Optional: Pre-fill customer information
        customer: {
          email: 'customer@example.com',
          name: 'John Doe'
        },
        // Optional: Add metadata for tracking
        metadata: {
          order_id: 'order_123',
          pricing_tier: 'custom'
        }
      });

      console.log('Checkout URL:', session.checkout_url);
      console.log('Session ID:', session.session_id);
      
      return session;
    } catch (error) {
      console.error('Failed to create checkout session:', error);
      throw error;
    }
  }

  // Example: Create checkout with $25.00 (2500 cents)
  const session = await createDynamicPricingCheckout(
    'prod_123abc456def',
    2500, // $25.00 in cents
    'https://yoursite.com/checkout/success'
  );

  // Example: Create checkout with $10.00 (1000 cents)
  const session2 = await createDynamicPricingCheckout(
    'prod_123abc456def',
    1000, // $10.00 in cents
    'https://yoursite.com/checkout/success'
  );
  ```

  ```python Python theme={null}
  import os
  from dodopayments import DodoPayments

  # Initialize the Dodo Payments client
  client = DodoPayments(
      bearer_token=os.environ.get("DODO_PAYMENTS_API_KEY"),
  )

  def create_dynamic_pricing_checkout(
      product_id: str,
      amount_in_cents: int,
      return_url: str
  ):
      """
      Create a checkout session with dynamic pricing.
      
      Args:
          product_id: The product ID with Pay What You Want enabled
          amount_in_cents: The amount in cents (e.g., 2500 for $25.00)
          return_url: URL to redirect after payment completion
      
      Returns:
          Session object with checkout_url and session_id
      """
      try:
          session = client.checkout_sessions.create(
              product_cart=[
                  {
                      "product_id": product_id,
                      "quantity": 1,
                      # Dynamic amount in cents (e.g., 1500 = $15.00)
                      "amount": amount_in_cents
                  }
              ],
              return_url=return_url,
              # Optional: Pre-fill customer information
              customer={
                  "email": "customer@example.com",
                  "name": "John Doe"
              },
              # Optional: Add metadata for tracking
              metadata={
                  "order_id": "order_123",
                  "pricing_tier": "custom"
              }
          )
          
          print(f"Checkout URL: {session.checkout_url}")
          print(f"Session ID: {session.session_id}")
          
          return session
      except Exception as error:
          print(f"Failed to create checkout session: {error}")
          raise error

  # Example: Create checkout with $25.00 (2500 cents)
  session = create_dynamic_pricing_checkout(
      "prod_123abc456def",
      2500,  # $25.00 in cents
      "https://yoursite.com/checkout/success"
  )

  # Example: Create checkout with $10.00 (1000 cents)
  session2 = create_dynamic_pricing_checkout(
      "prod_123abc456def",
      1000,  # $10.00 in cents
      "https://yoursite.com/checkout/success"
  )
  ```
</CodeGroup>

<Note>
  **금액 형식**: `amount` 필드는 해당 통화의 최저 단위로 입력해야 합니다. USD의 경우 센트를 사용합니다(예: \$25.00 = `2500`). 다른 통화라면 가장 작은 단위를 사용하세요(예: INR은 파이즈).
</Note>

## 3단계: 고객이 자신의 가격 선택하기

고객이 체크아웃 중에 자신의 가격을 선택하게 하려면 상품 카트에서 `amount` 필드를 생략하세요. 그러면 체크아웃 페이지에 고객이 최소 및 최대 범위 내에서 원하는 금액을 입력할 수 있는 필드가 표시됩니다.

<CodeGroup>
  ```typescript TypeScript theme={null}
  async function createCustomerChoiceCheckout(
    productId: string,
    returnUrl: string
  ) {
    try {
      const session = await client.checkoutSessions.create({
        product_cart: [
          {
            product_id: productId,
            quantity: 1
            // No amount field - customer will choose their price
          }
        ],
        return_url: returnUrl,
        customer: {
          email: 'customer@example.com',
          name: 'John Doe'
        }
      });

      return session;
    } catch (error) {
      console.error('Failed to create checkout session:', error);
      throw error;
    }
  }
  ```

  ```python Python theme={null}
  def create_customer_choice_checkout(
      product_id: str,
      return_url: str
  ):
      """
      Create a checkout session where customers choose their own price.
      """
      try:
          session = client.checkout_sessions.create(
              product_cart=[
                  {
                      "product_id": product_id,
                      "quantity": 1
                      # No amount field - customer will choose their price
                  }
              ],
              return_url=return_url,
              customer={
                  "email": "customer@example.com",
                  "name": "John Doe"
              }
          )
          
          return session
      except Exception as error:
          print(f"Failed to create checkout session: {error}")
          raise error
  ```
</CodeGroup>

## 일반 사용 사례

### 사용 사례 1: 사용자 유형에 따른 계층 가격 책정

동일한 제품을 사용하여 서로 다른 고객 세그먼트에 서로 다른 가격을 제공합니다:

```typescript theme={null}
// Student discount: $10.00
const studentSession = await createDynamicPricingCheckout(
  'prod_123abc456def',
  1000, // $10.00
  'https://yoursite.com/success'
);

// Regular price: $25.00
const regularSession = await createDynamicPricingCheckout(
  'prod_123abc456def',
  2500, // $25.00
  'https://yoursite.com/success'
);

// Premium price: $50.00
const premiumSession = await createDynamicPricingCheckout(
  'prod_123abc456def',
  5000, // $50.00
  'https://yoursite.com/success'
);
```

### 사용 사례 2: 수량에 따른 동적 가격 책정

구매한 수량에 따라 가격을 조정합니다:

```typescript theme={null}
async function createQuantityBasedCheckout(
  productId: string,
  quantity: number
) {
  // Base price: $20.00 per unit
  // Discount: 10% for 2+ items, 20% for 5+ items
  const basePrice = 2000; // $20.00 in cents
  let discount = 0;
  
  if (quantity >= 5) {
    discount = 0.20; // 20% off
  } else if (quantity >= 2) {
    discount = 0.10; // 10% off
  }
  
  const totalAmount = Math.round(basePrice * quantity * (1 - discount));
  
  const session = await client.checkoutSessions.create({
    product_cart: [
      {
        product_id: productId,
        quantity: quantity,
        amount: totalAmount
      }
    ],
    return_url: 'https://yoursite.com/success'
  });
  
  return session;
}
```

### 사용 사례 3: 시간 기반 또는 프로모션 가격 책정

특정 기간 동안 프로모션 가격을 적용합니다:

```typescript theme={null}
async function createPromotionalCheckout(productId: string) {
  const isPromoActive = checkIfPromotionActive(); // Your logic
  const regularPrice = 3000; // $30.00
  const promoPrice = 2000; // $20.00
  
  const amount = isPromoActive ? promoPrice : regularPrice;
  
  const session = await client.checkoutSessions.create({
    product_cart: [
      {
        product_id: productId,
        quantity: 1,
        amount: amount
      }
    ],
    return_url: 'https://yoursite.com/success',
    metadata: {
      pricing_type: isPromoActive ? 'promotional' : 'regular'
    }
  });
  
  return session;
}
```

## 모범 사례

<CardGroup cols={2}>
  <Card title="Set Reasonable Bounds" icon="sliders">
    비용을 충당하면서 접근 가능한 수준을 유지하도록 최소 가격을 선택하세요. 추천 가격을 사용하여 고객의 기대치를 안내하세요.
  </Card>

  <Card title="Validate Amounts" icon="shield-check">
    동적 금액이 상품의 최소/최대 범위를 벗어나지 않도록 항상 검증한 후 체크아웃 세션을 생성하세요.
  </Card>

  <Card title="Track Pricing Decisions" icon="chart-line">
    특정 금액을 선택한 이유를 추적하기 위해 메타데이터(e.g., `pricing_tier`, `discount_code`, `user_segment`)를 활용하세요.
  </Card>

  <Card title="Handle Edge Cases" icon="exclamation-triangle">
    금액이 최대값을 초과하거나 최소값 이하일 때 애플리케이션이 우아하게 처리하도록 하세요.
  </Card>
</CardGroup>

## 검증 및 오류 처리

항상 제품의 최소 및 최대 설정에 대해 금액을 검증하십시오:

<CodeGroup>
  ```typescript TypeScript theme={null}
  async function createValidatedCheckout(
    productId: string,
    amountInCents: number,
    minAmount: number,
    maxAmount: number | null
  ) {
    // Validate minimum
    if (amountInCents < minAmount) {
      throw new Error(
        `Amount ${amountInCents} is below minimum ${minAmount}`
      );
    }
    
    // Validate maximum (if set)
    if (maxAmount !== null && amountInCents > maxAmount) {
      throw new Error(
        `Amount ${amountInCents} exceeds maximum ${maxAmount}`
      );
    }
    
    // Create checkout session
    return await client.checkoutSessions.create({
      product_cart: [
        {
          product_id: productId,
          quantity: 1,
          amount: amountInCents
        }
      ],
      return_url: 'https://yoursite.com/success'
    });
  }
  ```

  ```python Python theme={null}
  def create_validated_checkout(
      product_id: str,
      amount_in_cents: int,
      min_amount: int,
      max_amount: int | None
  ):
      """
      Create a checkout session with amount validation.
      """
      # Validate minimum
      if amount_in_cents < min_amount:
          raise ValueError(
              f"Amount {amount_in_cents} is below minimum {min_amount}"
          )
      
      # Validate maximum (if set)
      if max_amount is not None and amount_in_cents > max_amount:
          raise ValueError(
              f"Amount {amount_in_cents} exceeds maximum {max_amount}"
          )
      
      # Create checkout session
      return client.checkout_sessions.create(
          product_cart=[
              {
                  "product_id": product_id,
                  "quantity": 1,
                  "amount": amount_in_cents
              }
          ],
          return_url="https://yoursite.com/success"
      )
  ```
</CodeGroup>

## API 참조

<CardGroup cols={2}>
  <Card title="Pay What You Want Feature" icon="dollar-sign" href="/features/pay-what-you-want">
    Pay What You Want 가격 모델과 그 기능에 대해 자세히 알아보세요.
  </Card>

  <Card title="Checkout Sessions Guide" icon="cart-shopping" href="/developer-resources/checkout-session">
    고급 체크아웃 세션 기능과 커스터마이징 옵션을 탐색하세요.
  </Card>
</CardGroup>

## 문제 해결

<AccordionGroup>
  <Accordion title="Amount is being ignored">
    `amount` 필드가 무시된다면 다음을 확인하세요:

    * 대시보드에서 해당 상품에 **Pay What You Want**이 활성화되어 있는지
    * 해당 상품이 구독이 아닌 **Single Payment**(일회성) 상품인지
    * 금액이 올바른 형식(예: USD는 센트)인지
  </Accordion>

  <Accordion title="Amount exceeds maximum or is below minimum">
    API는 금액이 상품의 가격 범위를 벗어나는 체크아웃 세션을 거부합니다. 체크아웃 세션을 생성하기 전에 금액을 항상 검증하거나 `amount` 필드를 생략하여 고객이 직접 가격을 선택하게 하세요.
  </Accordion>

  <Accordion title="Customer can't enter their own price">
    고객이 가격 입력 필드를 보지 못하는 경우 상품 카트에서 `amount` 필드를 생략했는지 확인하세요. `amount`가 제공되면 체크아웃은 해당 금액을 그대로 사용합니다.
  </Accordion>
</AccordionGroup>
