# PaymentProvider

`PaymentProvider` 是 `@blocklet/payment-react` 库的基石。它作为一个上下文提供者，必须包裹您的应用程序或相关的支付组件。它负责获取必要的设置、管理应用程序状态，并向其所有子组件提供辅助函数和 API 客户端。

该库中几乎所有的组件和钩子都需要嵌套在 `PaymentProvider` 中才能正常工作。

## 工作原理

提供者在挂载时会初始化并从 Payment Kit 后端获取配置数据。这些数据连同用户会话和其他实用工具，通过 `usePaymentContext` 钩子提供给任何后代组件。这种模式确保您的支付组件始终能够访问必要的上下文，而无需进行属性钻取（prop drilling）。

<!-- DIAGRAM_IMAGE_START:architecture:16:9:1764919317 -->
![PaymentProvider](assets/diagram/payment-provider-diagram-0.zh.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 提供会话和 connectApi
export function useSessionContext() {
  const { session, connect } = useDidSessionContext();
  return { session, connectApi: connect };
}
```

一旦您的会话管理就位，请使用 `PaymentProvider` 包裹您的主应用程序组件。

```tsx App.tsx icon=logos:react
import { PaymentProvider } from '@blocklet/payment-react';
import { useSessionContext } from './SessionContext'; // 你的会话上下文钩子
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 | 类型 | 必需 | 描述 |
| --- | --- | --- | --- |
| `session` | `Session` | 是 | 来自您的身份验证上下文（例如，`@arcblock/did-connect-react`）的用户会话对象。 |
| `connect` | `Connect` | 是 | 来自您的身份验证上下文的 `connect` API 函数，用于 DID Connect 操作。 |
| `children` | `React.ReactNode` | 是 | 将有权访问支付上下文的子组件。 |
| `baseUrl` | `string` | 否 | Payment Kit blocklet 的基础 URL。仅在从不同源（跨源）集成支付组件时需要。 |
| `authToken` | `string` | 否 | 用于 API 请求的特定身份验证令牌。如果提供，它将取代基于会话的身份验证。 |


## 上下文值

`PaymentProvider` 内的组件可以使用 `usePaymentContext` 钩子访问以下值。

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

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

  return (
    <div>
      <p>Base Currency: {settings.baseCurrency?.name}</p>
      <p>Mode: {livemode ? 'Live' : 'Test'}</p>
      <button onClick={() => setLivemode(!livemode)}>Toggle Mode</button>
    </div>
  );
}
```

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

| 键 | 类型 | 描述 |
| --- | --- | --- |
| `session` | `object` | 经过身份验证的用户会话，包括用户详细信息。 |
| `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 令牌而不是默认的基于会话的身份验证（例如，用于服务器到服务器的通信或特定的访问授权），您可以传递 `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) 组件来创建支付流程。