# 結帳模式

> 了解客戶端如何在內嵌面板與彈出式視窗之間作出選擇、為何受信任來源會影響選擇，以及在本機開發期間可以預期甚麼。

結帳會以兩種模式之一開啟。

**面板**是在頁面內呈現的內嵌面板。在桌面裝置上，它會從右方滑入，最大寬度為 `pane.width`；在流動裝置上，它會從底部向上滑入。訪客會留在你的網站，而當他們按 Escape 鍵或點擊變暗的區域時，面板便會關閉。

**彈出式視窗**是置中顯示在訪客螢幕上的獨立瀏覽器視窗。客戶端會偵測視窗是否已關閉，以便清除背景遮罩。

## 內嵌結帳需要受信任來源

面板模式會在你的網域上的 iframe 中呈現 Entase 結帳，因此只允許用於你已明確授權的網域。請將所有會開啟結帳的網域加入「設定」→「整合」中的**受信任來源** – 請參閱[整合與結帳自訂](/organizers/settings/integrations-and-checkout-customization.md)。

是否包含 `www.` 前綴很重要。如果你不確定網站使用哪種形式，請將兩者都加入。

如果你的網域不在清單中，結帳功能仍可運作 – 只會以彈出式視窗開啟。

## 如何解析 `'auto'`

使用預設的 `checkoutMode: 'auto'` 時，客戶端會依以下次序決定：

1. **非 HTTPS** → 彈出式視窗。內嵌結帳絕不會在不安全的頁面上使用。
2. **`localhost` 或 `127.0.0.1`** → 面板，並在主控台記錄警告。這是方便開發的安排，讓你可按內嵌版面進行開發；這並不表示你的正式環境網域是否獲准使用。
3. **其他情況** → 客戶端會詢問 Entase 此來源是否可使用內嵌結帳，並傳送 `pk` 以識別帳戶。如果回覆包括 pane，模式便會變為面板。

在收到該回覆前，模式會是**彈出式視窗**。這是最可能令你感到意外的行為：檢查是非同步的，因此在頁面載入後立即觸發的 `book()` 呼叫 – 在訪客有機會點擊任何內容之前 – 即使網域已完全正確設定，仍可能開啟彈出式視窗。實際上，真正的點擊總會在檢查完成很久後才發生。如果你會自動開啟結帳，請強制指定模式，而不要依賴偵測。

## 強制指定模式

明確設定 `checkoutMode`，即可完全略過偵測：

```js
const entase = new Entase({ pk: 'YOUR_PUBLISHABLE_KEY', checkoutMode: 'popup' });
```

或者，為單一預訂覆寫設定：

```js
entase.book('EVENT_ID', { checkoutMode: 'popup' });
```

在不是受信任來源的網域上強制使用 `'pane'` 並不會取得權限 – 面板會開啟，但其中的結帳無法與你的頁面通訊。請將 `'popup'` 用作有意識的選擇；如你希望在所有獲允許的地方使用內嵌結帳，則保留使用 `'auto'`。

無法識別的值會被忽略，並視為 `'auto'` 處理。

## 在執行期間讀取及更改模式

```js
entase.getCheckoutMode();        // 'pane' or 'popup' — never 'auto'
entase.setCheckoutMode('popup'); // applies to every later book() call
```

`getCheckoutMode()` 會傳回*已解析*的模式，因此它會報告實際會發生的情況。將模式重新設為 `'auto'` 會再次執行偵測。

## 彈出式視窗封鎖功能

瀏覽器只允許在使用者手勢期間呼叫 `window.open()`。請直接在點擊處理常式中呼叫 `book()` – 不要在 `await`、`fetch` 或 `setTimeout` 之後才呼叫；到那時手勢已失效，彈出式視窗便會被封鎖。

```js
// Blocked: the gesture is gone by the time book() runs.
button.addEventListener('click', async () => {
  const event = await fetch('/api/current-event').then(r => r.json());
  entase.book(event.id);
});

// Fine: resolve the id first, open on the click.
button.addEventListener('click', () => entase.book(button.dataset.eventId));
```

這只會影響彈出式視窗模式。面板模式會在頁面中建立元素，因此不受此限制。
