# PaymentProvider

`PaymentProvider` 是 `@blocklet/payment-react` 函式庫的基石。它作為一個上下文提供者，必須包裝您的應用程式或相關的支付元件。它負責取得必要的設定、管理應用程式狀態，並為其所有子元件提供輔助函式和 API 客戶端。

此函式庫中幾乎每個元件和掛鉤都需要嵌套在 `PaymentProvider` 內才能正常運作。

## 運作方式

該提供者在掛載時會初始化並從 Payment Kit 後端取得設定資料。這些資料，連同使用者的 session 和其他工具，會透過 `usePaymentContext` 掛鉤提供給任何後代元件。這種模式確保您的支付元件始終能夠存取必要的上下文，而無需透過屬性傳遞。

<!-- DIAGRAM_IMAGE_START:architecture:16:9:1764919317 -->
![PaymentProvider](assets/diagram/payment-provider-diagram-0.zh-TW.jpg)
<!-- DIAGRAM_IMAGE_END -->

## 設定與使用

若要使用 `PaymentProvider`，您需要從應用程式的驗證上下文中為其提供 `session` 和 `connect` 物件。在整個文件中，我們將使用一個自訂掛鉤 `useSessionContext` 來代表您應用程式的驗證邏輯。以下是此類掛鉤的典型實作：

```typescript SessionContext.tsx icon=logos:react
import React, { createContext, useContext } from 'react';
import { SessionProvider, useSessionContext as useDidSessionContext } from '@arcblock/did-connect-react';

// 您可以建立自己的上下文或使用現有的上下文
const AppContext = createContext({});

export function AppProvider({ children }) {
  return (
    <SessionProvider>
      <AppContext.Provider value={{}}>
        {children}
      </AppContext.Provider>
    </SessionProvider>
  );
}

// 這個自訂掛鉤為 PaymentProvider 提供 session 和 connectApi
export function useSessionContext() {
  const { session, connect } = useDidSessionContext();
  return { session, connectApi: connect };
}
```

一旦您的 session 管理就緒，就用 `PaymentProvider` 包裝您的主應用程式元件。

```tsx App.tsx icon=logos:react
import { PaymentProvider } from '@blocklet/payment-react';
import { useSessionContext } from './SessionContext'; // 您的 session 上下文掛鉤
import MyPaymentPage from './MyPaymentPage';

function App() {
  const { session, connectApi } = useSessionContext();

  return (
    <PaymentProvider session={session} connect={connectApi}>
      <MyPaymentPage />
    </PaymentProvider>
  );
}

export default App;
```

## Props

`PaymentProvider` 元件接受以下 props：

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `session` | `Session` | 是 | 來自您的驗證上下文的使用者 session 物件 (例如 `@arcblock/did-connect-react`)。 |
| `connect` | `Connect` | 是 | 來自您的驗證上下文的 `connect` API 函式，用於 DID Connect 操作。 |
| `children` | `React.ReactNode` | 是 | 將有權存取支付上下文的子元件。 |
| `baseUrl` | `string` | 否 | Payment Kit blocklet 的基礎 URL。僅在從不同來源 (跨來源) 整合支付元件時才需要。 |
| `authToken` | `string` | 否 | 用於 API 請求的特定驗證令牌。如果提供，它將取代基於 session 的驗證。 |


## 上下文值

`PaymentProvider` 內的元件可以使用 `usePaymentContext` 掛鉤存取以下值。

```typescript MyComponent.tsx icon=logos:react
import { usePaymentContext } from '@blocklet/payment-react';

function MyComponent() {
  const { settings, livemode, setLivemode } = usePaymentContext();

  return (
    <div>
      <p>基礎貨幣： {settings.baseCurrency?.name}</p>
      <p>模式： {livemode ? '正式' : '測試'}</p>
      <button onClick={() => setLivemode(!livemode)}>切換模式</button>
    </div>
  );
}
```

以下是可用上下文值的完整列表：

| Key | Type | Description |
| --- | --- | --- |
| `session` | `object` | 經過驗證的使用者 session，包含使用者詳細資訊。 |
| `connect` | `function` | 用於啟動 DID Wallet 互動的 `connect` 函式。 |
| `livemode` | `boolean` | 表示上下文是處於正式 (`true`) 模式還是測試 (`false`) 模式。 |
| `setLivemode` | `(livemode: boolean) => void` | 一個在正式和測試模式之間切換的函式。這將觸發重新取得設定。 |
| `settings` | `Settings` | 一個包含從後端取得的 `paymentMethods` 和 `baseCurrency` 設定的物件。 |
| `refresh` | `(forceRefresh?: boolean) => void` | 一個手動觸發重新取得設定資料的函式。 |
| `getCurrency` | `(id: string) => TPaymentCurrency` | 一個輔助函式，可透過 ID 取得特定貨幣的詳細資訊。 |
| `getMethod` | `(id: string) => TPaymentMethodExpanded` | 一個輔助函式，可透過 ID 取得特定支付方式的詳細資訊。 |
| `api` | `AxiosInstance` | 一個預先設定的 Axios 實例，用於向 Payment Kit 後端發出經過驗證的 API 呼叫。 |
| `prefix` | `string` | blocklet 的 URL 前綴。 |
| `payable` | `boolean` | 一個可用於控制支付操作可用性的狀態。 |
| `setPayable` | `(status: boolean) => void` | 一個更新 `payable` 狀態的函式。 |


## 進階情境

### 跨來源整合

如果您的應用程式和 Payment Kit blocklet 託管在不同的網域上，您必須使用 `baseUrl` prop。這讓 `PaymentProvider` 能夠正確地定位並與 Payment Kit API 通訊。

```tsx CrossOriginApp.tsx icon=logos:react
import { PaymentProvider } from '@blocklet/payment-react';
import { useSessionContext } from './SessionContext';

function CrossOriginApp() {
  const { session, connectApi } = useSessionContext();

  return (
    <PaymentProvider 
      session={session} 
      connect={connectApi}
      baseUrl="https://payment-kit.another-domain.com"
    >
      {/* 您的支付元件 */}
    </PaymentProvider>
  );
}
```

### 自訂驗證令牌

在您需要使用特定的 API 令牌而不是預設的基於 session 的驗證的情境下 (例如，用於伺服器對伺服器通訊或特定的存取授權)，您可以傳遞 `authToken` prop。

```tsx TokenAuthApp.tsx icon=logos:react
import { PaymentProvider } from '@blocklet/payment-react';
import { useSessionContext } from './SessionContext';

function TokenAuthApp() {
  const { session, connectApi } = useSessionContext();
  const myCustomAuthToken = 'sk_xxxxxx'; // 您的秘密令牌

  return (
    <PaymentProvider 
      session={session} 
      connect={connectApi}
      authToken={myCustomAuthToken}
    >
      {/* 元件將使用提供的 authToken 進行 API 呼叫 */}
    </PaymentProvider>
  );
}
```

---

設定好 `PaymentProvider` 後，您現在可以開始將支付元件整合到您的應用程式中。一個好的下一步是探索如何使用 [CheckoutForm](./components-checkout-checkout-form.md) 元件來建立支付流程。