> ## Documentation Index
> Fetch the complete documentation index at: https://developers-partners.delivered.co.kr/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK 연동하기

> 글로벌체크아웃 JavaScript SDK는 브라우저 환경에서 글로벌체크아웃을 새 탭 또는 iframe으로 열 수 있는 메서드를 제공합니다. SDK 사용을 위한 준비와 메서드 사용법을 알아봅니다.

## 1. SDK 설치

SDK를 사용하기 위해 다음 스크립트를 HTML의 `<head>` 태그 내에 추가해주세요.

```html theme={null}
<head>
  <script src="https://sdk-checkout.delivered.co.kr/index.js"></script>
</head>
```

***

## 2. 메서드

글로벌체크아웃 SDK에서 제공하는 주요 메서드입니다.

### `orderInNewTab(products, isPriceDetailsSectionOpen)`

새로운 탭에서 글로벌체크아웃을 호출하는 메서드입니다. `products` 파라미터에 주문 정보를 전달하고, `isPriceDetailsSectionOpen`으로 가격 상세 섹션 펼침 여부를 설정할 수 있습니다.

```javascript theme={null}
orderInNewTab(products: CartProduct[], isPriceDetailsSectionOpen?: boolean): Promise<void>
```

* **파라미터**
  * `products` (타입: `CartProduct[]`): 주문 정보 배열입니다.(상세 타입은 아래 '3. 주문 상품 정보 연동' 참고)
  * `isPriceDetailsSectionOpen` (타입: `boolean`, 선택): 가격 상세 섹션 펼침 여부. 기본값은 `true`입니다.
* **리턴 타입**
  * `Promise<void>`: 주문 프로세스가 성공적으로 완료되면 resolve됩니다. 실패 시 에러가 reject됩니다.

#### Promise 사용

```javascript theme={null}
// products 데이터 구조는 '3. 주문 상품 정보 연동'의 예시를 참고하세요.
dkLibrary.orderInNewTab(products, false)
  .then(() => {
    console.log('주문 성공');
  })
  .catch((err) => {
    console.error('주문 실패:', err);
  })
  .finally(() => {
    console.log('주문 프로세스 완료');
  });
```

#### async/await 사용

```javascript theme={null}
// products 데이터 구조는 '3. 주문 상품 정보 연동'의 예시를 참고하세요.
try {
  await dkLibrary.orderInNewTab(products, true); // 가격 상세 섹션 노출
  console.log('주문 성공');
} catch (err) {
  console.error('주문 실패:', err);
}
```

***

### `orderInIframe(request, isPriceDetailsSectionOpen)`

iframe을 사용하여 글로벌체크아웃을 호출하는 메서드입니다. `request` 파라미터는 주문 정보와 부모 URL을 포함하며, `isPriceDetailsSectionOpen`으로 가격 상세 섹션 펼침 여부를 설정할 수 있습니다.

```javascript theme={null}
orderInIframe(request: IframeCartProductRequest, isPriceDetailsSectionOpen?: boolean): Promise<string>
```

* **파라미터**
  * `request` (타입: `IframeCartProductRequest`): 주문 정보와 부모 페이지 URL을 포함하는 객체입니다. (상세 타입은 아래 '3. 주문 상품 정보 연동' 참고)
  * `isPriceDetailsSectionOpen` (타입: `boolean`, 선택): 가격 상세 섹션 펼침 여부. 기본값은 `true`입니다.
* **리턴 타입**
  * `Promise<string>`: iframe 로드에 사용할 URL을 반환합니다. 실패 시 에러가 reject됩니다.

#### Promise 사용

```javascript theme={null}
// productsRequest 데이터 구조는 '3. 주문 상품 정보 연동'의 예시를 참고하세요.
dkLibrary.orderInIframe({
  products: productsRequest,
  parentUrl: 'https://example.com/iframe-page?url=',
}, false)
  .then((response) => {
    console.log('주문 성공');
    window.location.href = `https://example.com/iframe-page?url=${response}`;
  })
  .catch((err) => {
    console.error('주문 실패:', err);
  })
  .finally(() => {
    console.log('주문 프로세스 완료');
  });
```

<ResponseField name="parentUrl" type="string" required>
  iframe을 로드할 부모 페이지의 URL
</ResponseField>

#### async/await 사용

```javascript theme={null}
// productsRequest 데이터 구조는 '3. 주문 상품 정보 연동'의 예시를 참고하세요.
try {
  const response = await dkLibrary.orderInIframe({
    products: productsRequest,
    parentUrl: 'https://example.com/iframe-page?url=',
  }, true); // 가격 상세 섹션 숨김
  console.log('주문 성공');
  window.location.href = `https://example.com/iframe-page?url=${response}`;
} catch (err) {
  console.error('주문 실패:', err);
}
```

<ResponseField name="parentUrl" type="string" required>
  iframe을 로드할 부모 페이지의 URL
</ResponseField>

#### iframe을 노출할 페이지의 코드

```javascript theme={null}
const url = window.location.search.replace("?url=", "");
const eventListener = (e: MessageEvent<any>) => {

  const { type, payload } = e.data;

  if (type === "dk-global-order-go-to") {
    window.location.replace(payload);
  }
};

window.addEventListener("message", eventListener);
<iframe src={url} />
```

***

## 3. 주문 상품 정보 연동

### Parameter 상세 설명

<ResponseField name="IframeCartProductRequest" type="object" required>
  `orderInIframe` 메서드 요청 시 사용되는 데이터 구조

  <Expandable title="IframeCartProductRequest">
    <ResponseField name="products" type="CartProduct[]" required>
      장바구니에 담긴 상품 정보 배열
    </ResponseField>

    <ResponseField name="parentUrl" type="string" required>
      iframe을 로드할 부모 페이지의 URL
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="CartProduct" type="object" required>
  개별 장바구니 상품 정보 (`orderInNewTab`의 `products` 배열 요소, `IframeCartProductRequest`의 `products` 배열 요소)

  <Expandable title="CartProduct">
    <ResponseField name="productRequest" type="ProductRequest" required>
      상품 정보
    </ResponseField>

    <ResponseField name="selectedOptions" type="SelectedOptionGroup[]" required>
      선택된 옵션 그룹 정보 배열 (옵션이 없으면 빈 배열로 전달)
    </ResponseField>

    <ResponseField name="quantity" type="number" required>
      상품 수량 (1 이상의 정수)
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="ProductRequest" type="object" required>
  상품 정보

  <Expandable title="ProductRequest">
    <ResponseField name="sellerClientKey" type="string" required>
      판매자 클라이언트 키 (딜리버드 파트너스에서 제공한 판매자 고유값)
    </ResponseField>

    <ResponseField name="title" type="string" required>
      상품 제목
    </ResponseField>

    <ResponseField name="prices" type="PricesByCurrency" required>
      상품 판매가 (통화별 가격)
    </ResponseField>

    <ResponseField name="originalPrices" type="PricesByCurrency">
      할인 전 원래 가격 (통화별 가격). `discountRate` > 0 일 때 필수. 쇼핑몰의 상품 소비자가격과 동일해야 함.
    </ResponseField>

    <ResponseField name="discountRate" type="number" required>
      할인율 (0 이상)

      **주의:** `discountRate`가 0보다 크면 `originalPrices`는 필수값입니다. `discountRate`가 0이면 `originalPrices`는 선택값이며, 입력해도 적용되지 않습니다.
    </ResponseField>

    <ResponseField name="originUrl" type="string" required>
      상품이 게시된 원본 URL
    </ResponseField>

    <ResponseField name="images" type="string[]" required>
      상품 이미지 URL 배열 (최소 1개 이상)
    </ResponseField>

    <ResponseField name="options" type="OptionGroup[]" required>
      상품 옵션 그룹 배열 (옵션이 없으면 빈 배열로 전달)
    </ResponseField>

    <ResponseField name="quantityControl" type="QuantityControl" required>
      수량 제어 설정
    </ResponseField>

    <ResponseField name="sellerProductId" type="string">
      판매사가 관리하는 상품의 고유값
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="QuantityControl" type="object" required>
  수량 제어 설정

  <Expandable title="QuantityControl">
    <ResponseField name="allowQuantityChange" type="boolean" required>
      수량 변경 허용 여부. `true`인 경우 `minQuantity`, `maxQuantity` 필수
    </ResponseField>

    <ResponseField name="minQuantity" type="number">
      최소 수량 (`allowQuantityChange`가 `true`인 경우 필수)
    </ResponseField>

    <ResponseField name="maxQuantity" type="number">
      최대 수량 (`allowQuantityChange`가 `true`인 경우 필수)
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="OptionGroup" type="object" required>
  옵션 그룹 정보

  <Expandable title="OptionGroup">
    <ResponseField name="groupName" type="string" required>
      옵션 그룹명 (같은 상품 내에서 unique해야 함)
    </ResponseField>

    <ResponseField name="type" type="'text' | 'select' | 'image'" required>
      옵션 타입

      * `text`: 텍스트 입력
      * `select`: 선택형 옵션
      * `image`: 이미지 업로드
    </ResponseField>

    <ResponseField name="required" type="boolean" required>
      필수 옵션 여부. `true`인 경우 `selectedOptions`에 반드시 포함되어야 함
    </ResponseField>

    <ResponseField name="options" type="SelectTypeOption[]">
      선택형 옵션 목록 (`type`이 `select`인 경우 필수)
    </ResponseField>

    <ResponseField name="extraPrice" type="PricesByCurrency">
      추가 가격 (`type`이 `select`인 경우 무시됨)
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="SelectTypeOption" type="object" required>
  선택형 옵션 정보

  <Expandable title="SelectTypeOption">
    <ResponseField name="label" type="string" required>
      옵션 라벨 (같은 옵션 그룹 내에서 unique해야 함)
    </ResponseField>

    <ResponseField name="extraPrice" type="PricesByCurrency">
      해당 옵션의 추가 가격
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="SelectedOptionGroup" type="object" required>
  선택된 옵션 그룹 정보

  <Expandable title="SelectedOptionGroup">
    <ResponseField name="groupName" type="string" required>
      선택된 옵션 그룹명 (`ProductRequest`의 `options` 중 하나의 `groupName`과 일치해야 함)
    </ResponseField>

    <ResponseField name="value" type="string | string[]" required>
      선택된 값

      * `text`, `select` 타입: `string`
      * `image` 타입: `string[]` (png, jpg, jpeg 형식의 URL만 허용)
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="PricesByCurrency" type="object" required>
  통화별 가격 정보

  <Expandable title="PricesByCurrency">
    <ResponseField name="krw" type="number" required>
      원화(KRW) 가격.
    </ResponseField>

    <ResponseField name="usd" type="number">
      미국 달러(USD) 가격.
    </ResponseField>
  </Expandable>
</ResponseField>

### Example 1: 옵션이 없는 단일 상품 (KRW)

**상품 예시:**

* 단일 상품으로 별도의 옵션 없이 판매
* 고객이 수량만 선택 가능

```javascript theme={null}
const products = [
  {
    productRequest: {
      sellerClientKey: 'your_seller_client_key',
      title: '기본 면 티셔츠',
      prices: { krw: 19900 },
      discountRate: 0,
      originUrl: 'https://example.com/products/basic-tshirt',
      images: ['https://example.com/images/basic-tshirt.jpg'],
      options: [], // 옵션 없음
      quantityControl: {
        allowQuantityChange: true,
        minQuantity: 1,
        maxQuantity: 10
      }
    },
    selectedOptions: [], // 옵션 없음
    quantity: 2
  }
];
```

### Example 2: 선택형 옵션이 있는 상품 (KRW)

**상품 예시:**

* 색상 옵션: 화이트(추가금 없음), 블랙(+1,000원)
* 사이즈 옵션: S, M(추가금 없음), L(+500원)
* 할인가 적용: 정가 29,900원 → 할인가 19,900원 (33% 할인)
* 수량 변경 불가 (1개씩만 주문)

```javascript theme={null}
const products = [
  {
    productRequest: {
      sellerClientKey: 'your_seller_client_key',
      title: '프리미엄 오가닉 티셔츠',
      prices: { krw: 19900 },
      originalPrices: { krw: 29900 },
      discountRate: 33,
      originUrl: 'https://example.com/products/premium-tshirt',
      images: ['https://example.com/images/tshirt-front.jpg'],
      options: [
        {
          groupName: '색상',
          type: 'select',
          required: true,
          options: [
            { label: '화이트', extraPrice: { krw: 0 } },
            { label: '블랙', extraPrice: { krw: 1000 } }
          ]
        },
        {
          groupName: '사이즈',
          type: 'select',
          required: true,
          options: [
            { label: 'S', extraPrice: { krw: 0 } },
            { label: 'M', extraPrice: { krw: 0 } },
            { label: 'L', extraPrice: { krw: 500 } }
          ]
        }
      ],
      quantityControl: {
        allowQuantityChange: false
      }
    },
    selectedOptions: [
      { groupName: '색상', value: '화이트' },
      { groupName: '사이즈', value: 'M' }
    ],
    quantity: 1
  }
];
```

### Example 3: 커스터마이징 옵션이 있는 상품 (USD)

**상품 예시:**

* 기기 모델 옵션: iPhone 14(추가금 없음), iPhone 14 Pro(+\$1.99), Galaxy S23(추가금 없음), Galaxy S23 Ultra(+\$2.99)
* 케이스 소재 옵션: 실리콘(추가금 없음), 하드 플라스틱(+\$0.99), 가죽(+\$6.99)
* 커스텀 텍스트 옵션: 고객이 직접 입력하는 텍스트 각인 서비스 (+\$2.49)
* 이미지 업로드 옵션: 고객이 png/jpg/jpeg 파일을 업로드하여 인쇄 (+\$3.99)
* 수량 제한: 1\~5개까지 주문 가능

```javascript theme={null}
const products = [
  {
    productRequest: {
      sellerClientKey: 'your_seller_client_key',
      title: '커스텀 폰케이스',
      prices: { krw: 35000, usd: 29.99 },
      discountRate: 0,
      originUrl: 'https://example.com/products/custom-phone-case',
      images: ['https://example.com/images/phone-case-template.jpg'],
      options: [
        {
          groupName: '기기 모델',
          type: 'select',
          required: true,
          options: [
            { label: 'iPhone 14', extraPrice: { krw: 0, usd: 0 } },
            { label: 'iPhone 14 Pro', extraPrice: { krw: 2000, usd: 1.99 } },
            { label: 'Samsung Galaxy S23', extraPrice: { krw: 0, usd: 0 } },
            { label: 'Samsung Galaxy S23 Ultra', extraPrice: { krw: 3000, usd: 2.99 } }
          ]
        },
        {
          groupName: '케이스 소재',
          type: 'select',
          required: true,
          options: [
            { label: '실리콘 (소프트)', extraPrice: { krw: 0, usd: 0 } },
            { label: '하드 플라스틱', extraPrice: { krw: 1000, usd: 0.99 } },
            { label: '가죽 (프리미엄)', extraPrice: { krw: 8000, usd: 6.99 } }
          ]
        },
        {
          groupName: '커스텀 텍스트',
          type: 'text',
          required: false,
          extraPrice: { krw: 3000, usd: 2.49 }
        },
        {
          groupName: '이미지 업로드',
          type: 'image',
          required: false,
          extraPrice: { krw: 5000, usd: 3.99 }
        }
      ],
      quantityControl: {
        allowQuantityChange: true,
        minQuantity: 1,
        maxQuantity: 5
      }
    },
    selectedOptions: [
      { groupName: '기기 모델', value: 'iPhone 14 Pro' },
      { groupName: '케이스 소재', value: '가죽 (프리미엄)' },
      { groupName: '커스텀 텍스트', value: 'My Special Phone' },
      { 
        groupName: '이미지 업로드', 
        value: [
          'https://example.com/uploads/my-photo.jpg',
          'https://example.com/uploads/pattern-design.png'
        ] 
      }
    ],
    quantity: 2
  }
];
```

### Example 4: 장바구니 다중 상품 연동 (KRW)

**상품 예시:**

* 상품 1: 기본 티셔츠 (옵션 없음, 2개)
* 상품 2: 커스텀 머그컵 (색상 선택 + 텍스트 각인, 1개)

```javascript theme={null}
const products = [
  // 첫 번째 상품: 기본 티셔츠
  {
    productRequest: {
      sellerClientKey: 'your_seller_client_key',
      title: '기본 면 티셔츠',
      prices: { krw: 19900 },
      discountRate: 0,
      originUrl: 'https://example.com/products/basic-tshirt',
      images: ['https://example.com/images/basic-tshirt.jpg'],
      options: [], // 옵션 없음
      quantityControl: {
        allowQuantityChange: true,
        minQuantity: 1,
        maxQuantity: 10
      }
    },
    selectedOptions: [], // 옵션 없음
    quantity: 2
  },
  // 두 번째 상품: 커스텀 머그컵
  {
    productRequest: {
      sellerClientKey: 'your_seller_client_key',
      title: '커스텀 세라믹 머그컵',
      prices: { krw: 15000 },
      originalPrices: { krw: 18000 },
      discountRate: 17,
      originUrl: 'https://example.com/products/custom-mug',
      images: ['https://example.com/images/ceramic-mug.jpg'],
      options: [
        {
          groupName: '컵 색상',
          type: 'select',
          required: true,
          options: [
            { label: '화이트', extraPrice: { krw: 0 } },
            { label: '블랙', extraPrice: { krw: 1000 } },
            { label: '네이비', extraPrice: { krw: 1000 } }
          ]
        },
        {
          groupName: '개인화 텍스트',
          type: 'text',
          required: false,
          extraPrice: { krw: 3000 }
        }
      ],
      quantityControl: {
        allowQuantityChange: true,
        minQuantity: 1,
        maxQuantity: 5
      }
    },
    selectedOptions: [
      { groupName: '컵 색상', value: '블랙' },
      { groupName: '개인화 텍스트', value: 'My Coffee Cup' }
    ],
    quantity: 1
  }
];
```

***

## 4. 주의 사항

1. **클라이언트키 사용**
   * `sellerClientKey`는 딜리버드 파트너스에서 제공한 판매자 고유값입니다.
   * 모든 `ProductRequest` 객체에는 반드시 `sellerClientKey`가 포함되어야 합니다.

2. **옵션 그룹과 선택된 옵션의 관계**
   * `SelectedOptionGroup`의 `groupName`은 반드시 `ProductRequest`의 `options` 중 동일한 `groupName`이 존재해야 합니다.
   * `OptionGroup`에서 `required: true`인 옵션은 `selectedOptions`에 반드시 포함되어야 합니다.
   * `ProductRequest.options` 내부의 `groupName`은 같은 상품 내에서 unique해야 합니다.
   * `OptionGroup.options` 내부에서 `label`은 같은 옵션 그룹 내에서 unique해야 합니다.

3. **옵션 타입별 제약사항**
   * `type`이 `select`인 경우 `options` 필드가 필수입니다.
   * `type`이 `select`인 경우 `extraPrice`는 무시되고, 각 `SelectTypeOption`의 `extraPrice`가 적용됩니다.
   * `type`이 `image`인 경우 `value`는 `string[]` 타입이며, png, jpg, jpeg 형식의 완전한 URL만 허용됩니다.
   * `type`이 `text` 또는 `select`인 경우 `value`는 `string` 타입입니다.

4. **수량 제어 설정**
   * `allowQuantityChange`가 `true`인 경우 `minQuantity`, `maxQuantity` 값이 필수입니다.

5. **할인 가격 설정**
   * `discountRate`가 0보다 크다면, 할인 전 가격인 `originalPrices` 필드는 필수적으로 포함되어야 합니다.
   * `originalPrices`는 쇼핑몰의 상품 소비자가격과 동일해야 합니다.
   * `discountRate`가 0이라면, `originalPrices`는 선택 사항이며, 값을 전달해도 할인 계산에 사용되지 않습니다.

6. **통화 사용 설정**
   * `prices` 및 `originalPrices`, `extraPrice` 필드에는 `PricesByCurrency` 타입 객체를 사용합니다.
   * 기본 통화는 KRW입니다. KRW 가격(`krw`)은 항상 필수입니다.
   * 표시 통화가 USD인 쇼핑몰의 경우에도 주문 확인을 위해 `krw` 값이 필수로 포함되어야 합니다.
   * 쇼핑몰의 기본 화폐 단위를 USD로 사용하고 싶으신 경우, 딜리버드 파트너스 [문의하기](https://developers-partners.delivered.co.kr/contact-form)를 통해 별도 문의가 필요합니다.

7. **가격 상세 섹션 설정**
   * `isPriceDetailsSectionOpen` 파라미터로 체크아웃 페이지의 가격 상세 섹션 펼침 여부를 제어할 수 있습니다.
   * 기본값은 `true`(노출)이며, `false`로 설정하면 가격 상세 섹션이 접혀진 상태로 시작됩니다.
