> ## 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.

# React Native

> Hướng dẫn hoàn chỉnh để tích hợp Dodo Payments SDK vào ứng dụng React Native của bạn để xử lý thanh toán an toàn

# Tích hợp SDK React Native

Dodo Payments React Native SDK cho phép bạn xây dựng trải nghiệm thanh toán an toàn trong các ứng dụng Android và iOS gốc của bạn. SDK của chúng tôi cung cấp các thành phần và màn hình UI có thể tùy chỉnh để thu thập thông tin thanh toán.

* 📦 Cài đặt SDK của chúng tôi từ [NPM](https://www.npmjs.com/package/dodopayments-react-native-sdk)
* 📚 Xem [kho demo](https://github.com/dodopayments/dodopayments-react-native-demo) của chúng tôi để có ví dụ triển khai hoàn chỉnh
* 🎥 Xem [video demo](https://youtu.be/eicctkqK04Y) của chúng tôi để thấy Dodo Payments SDK hoạt động

<Frame>
  <iframe className="w-full aspect-video rounded-md" src="https://www.youtube.com/embed/eicctkqK04Y" title="React Native SDK Demo | Dodo Payments" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen />
</Frame>

## Tính năng

<CardGroup cols={1}>
  <Card title="Simplified Security" icon="shield-check">
    Thu thập dữ liệu thanh toán nhạy cảm một cách bảo mật trong khi vẫn tuân thủ PCI
  </Card>

  <Card title="Multiple Payment Methods" icon="credit-card">
    Chấp nhận nhiều [phương thức thanh toán](/features/payment-methods) để mở rộng phạm vi toàn cầu
  </Card>

  <Card title="Native UI" icon="mobile">
    Màn hình và thành phần gốc cho Android và iOS
  </Card>
</CardGroup>

<Note>
  Hiện tại, Apple Pay, Google Pay, Cash App và UPI chưa được hỗ trợ trong React Native SDK. Chúng tôi đang tích cực làm việc để bổ sung hỗ trợ cho các phương thức thanh toán này trong các bản phát hành tương lai.
</Note>

## Cài đặt

<Steps>
  <Step title="Install the SDK">
    Cài đặt Dodo Payments SDK bằng trình quản lý gói bạn ưa thích:

    <Tabs>
      <Tab title="npm">
        ```bash theme={null}
        npm install dodopayments-react-native-sdk
        ```
      </Tab>

      <Tab title="yarn">
        ```bash theme={null}
        yarn add dodopayments-react-native-sdk
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Platform-specific setup">
    <Tabs>
      <Tab title="iOS">
        Chạy pod install trong thư mục iOS của bạn:

        ```bash theme={null}
        cd ios && pod install && npm run ios
        ```
      </Tab>

      <Tab title="Android">
        Chạy lệnh sau:

        ```bash theme={null}
        npm run android
        ```
      </Tab>
    </Tabs>
  </Step>
</Steps>

## Cài đặt phía khách hàng

<Steps>
  <Step title="Get Publishable Key">
    Lấy khóa publishable từ bảng điều khiển Dodo Payments. (Riêng biệt cho cả chế độ thử nghiệm và trực tiếp)
    [https://app.dodopayments.com/developer/others](https://app.dodopayments.com/developer/others)
  </Step>

  <Step title="Setup Payment Provider">
    Bao bọc ứng dụng của bạn bằng `DodoPaymentProvider`:

    ```tsx App.tsx theme={null}
    import React from 'react';
    import { DodoPaymentProvider } from 'dodopayments-react-native-sdk';
    import PaymentScreen from './PaymentScreen';

    function App() {
      return (
        <DodoPaymentProvider publishableKey="YOUR_PUBLISHABLE_KEY">
          <PaymentScreen />
        </DodoPaymentProvider>
      );
    }

    export default App;
    ```

    <Note>
      Bạn cần tạo các khóa API từ bảng điều khiển Dodo Payments. Xem [hướng dẫn tạo khóa API](/api-reference/introduction#api-key-generation) để biết hướng dẫn chi tiết.
    </Note>
  </Step>

  <Step title="Create payment utility function">
    Tạo một hàm tiện ích để lấy tham số thanh toán từ API backend của bạn:

    ```tsx utils/fetchPaymentParams.ts theme={null}
    const API_URL = 'YOUR_BACKEND_URL'; // Replace with your server URL

    const fetchPaymentParams = async () => {
      const response = await fetch(`${API_URL}/create-payment`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
      });
      
      if (!response.ok) {
        throw new Error('Failed to fetch payment parameters');
      }
      
      return await response.json();
    };

    export default fetchPaymentParams;
    ```

    <Note>
      Hàm này giả định bạn có một endpoint API backend tạo payment intent và trả về client secret. Đảm bảo backend của bạn được cấu hình đúng để xử lý việc tạo thanh toán. Xem [Hướng dẫn tích hợp API](/developer-resources/integration-guide) để biết ví dụ thiết lập backend.
    </Note>
  </Step>

  <Step title="Implement the payment screen">
    Tạo màn hình thanh toán của bạn bằng hook `useCheckout`. Đây là một triển khai hoàn chỉnh:

    ```tsx PaymentScreen.tsx theme={null}
    import React from 'react';
    import { View, Text, useColorScheme } from 'react-native';
    import { useCheckout, type sessionParams } from 'dodopayments-react-native-sdk';
    import fetchPaymentParams from './utils/fetchPaymentParams';

    const PaymentScreen = () => {
      const { initPaymentSession, presentPaymentSheet } = useCheckout();
      const [error, setError] = React.useState('');
      const [message, setMessage] = React.useState('');
      const [loading, setLoading] = React.useState(false);
      const [showSuccessScreen, setShowSuccessScreen] = React.useState(false);
      const isDarkMode = useColorScheme() === 'dark';

      const processPayment = async () => {
        setLoading(true);
        setMessage('');
        setError('');

        try {
          // 1. Get payment parameters from your backend
          const key = await fetchPaymentParams();
          
          // 2. Initialize payment session
          const paymentSheetParamsResult = await initPaymentSession({
            clientSecret: key.clientSecret,
          });
          
          // 3. Configure and present payment sheet
          const params: sessionParams = {
            ...(paymentSheetParamsResult as sessionParams),
            configuration: {
              appearance: {
                themes: isDarkMode ? 'dark' : 'light',
                primaryButton: {
                  colors: {
                    light: {
                      background: 'green',
                      componentBorder: 'green',
                      placeholderText: 'yellow',
                    },
                    dark: {
                      background: 'green',
                      componentBorder: 'green',
                      placeholderText: 'yellow',
                    },
                  },
                  shapes: {
                    borderRadius: 30,
                    borderWidth: 3,
                  },
                },
              },
              mode: 'test', // DEFAULTS TO TEST MODE
            },
          };

          const paymentSheetResponse = await presentPaymentSheet(params);

          // 4. Handle payment result
          switch (paymentSheetResponse?.status) {
            case 'cancelled':
              setError('Payment cancelled by user.');
              break;
            case 'succeeded':
              setMessage('');
              setShowSuccessScreen(true);
              break;
            case 'failed':
              setError('Payment failed : \n' + paymentSheetResponse?.message);
              break;
            default:
              setError(paymentSheetResponse?.message);
              setMessage('');
          }
        } catch (err) {
          setError('Failed to process payment');
        } finally {
          setLoading(false);
        }
      };

      return (
        <View>
          <Button 
            onPress={processPayment}
            disabled={loading}
            title={loading ? 'Processing...' : 'Pay Now'}
          />
          {error && <Text style={{ color: 'red' }}>{error}</Text>}
          {message && <Text style={{ color: 'green' }}>{message}</Text>}
          {showSuccessScreen && (
            <PaymentSuccessScreen
              amount={total}
              onContinue={() => setShowSuccessScreen(false)}
            />
          )}
        </View>
      );
    };

    export default PaymentScreen;
    ```

    <Note>
      Để xem ví dụ hoàn chỉnh với phong cách, xử lý lỗi và tùy chọn tùy chỉnh, hãy tham khảo các kho demo của chúng tôi:

      * [Demo tích hợp cơ bản](https://github.com/dodopayments/dodopayments-react-native-demo)
    </Note>
  </Step>
</Steps>

## Tùy chọn cấu hình

### Tham số phiên

<ParamField path="clientSecret" type="string" required>
  Client secret từ payment intent của bạn, lấy từ API One time payment hoặc subscription.
</ParamField>

<ParamField path="mode" type="string" required>
  Chế độ của phiên thanh toán (thử nghiệm hoặc trực tiếp).
</ParamField>

<ParamField path="configuration.appearance" type="object">
  Các tùy chọn tùy chỉnh cho giao diện payment sheet
</ParamField>

<ParamField path="configuration.appearance.themes" type="string">
  Chế độ giao diện: `'light'` hoặc `'dark'`
</ParamField>

### Tùy chỉnh giao diện

Bạn có thể tùy chỉnh React Native Unified Checkout để phù hợp với thiết kế ứng dụng bằng cách chỉnh sửa màu sắc, phông chữ và nhiều thứ khác thông qua tham số appearance khi gọi `initPaymentSession()`.

#### Tùy chỉnh màu sắc

Mỗi danh mục màu xác định màu của một hoặc nhiều thành phần trong giao diện người dùng. Ví dụ, `primary` xác định màu của nút Pay.

| Danh mục màu          | Sử dụng                                                    |
| --------------------- | ---------------------------------------------------------- |
| `primary`             | Màu chính cho nút Pay và các mục được chọn                 |
| `background`          | Màu nền của trang thanh toán                               |
| `componentBackground` | Màu nền cho các trường nhập, tab và thành phần khác        |
| `componentBorder`     | Màu viền ngoài cho các trường nhập, tab và thành phần khác |
| `componentDivider`    | Màu viền trong (viền chia sẻ) cho các thành phần           |
| `primaryText`         | Màu chữ tiêu đề                                            |
| `secondaryText`       | Màu chữ nhãn cho các trường nhập                           |
| `componentText`       | Màu chữ nhập liệu (ví dụ: số thẻ, mã zip)                  |
| `placeholderText`     | Màu chữ giữ chỗ cho các trường nhập                        |
| `icon`                | Màu cho biểu tượng (ví dụ: nút đóng)                       |
| `error`               | Màu cho thông báo lỗi và hành động hủy bỏ                  |

Ví dụ cấu hình với hỗ trợ chế độ sáng và tối:

```tsx theme={null}
const appearance = {
  colors: {
    light: {
      primary: '#F8F8F2',
      background: '#ffffff',
      componentBackground: '#E6DB74',
      componentBorder: '#FD971F',
      componentDivider: '#FD971F',
      primaryText: '#F8F8F2',
      secondaryText: '#75715E',
      componentText: '#AE81FF',
      placeholderText: '#E69F66',
      icon: '#F92672',
      error: '#FF0000',
    },
    dark: {
      primary: '#00ff0099',
      background: '#ff0000',
      componentBackground: '#ff0080',
      componentBorder: '#62ff08',
      componentDivider: '#d6de00',
      primaryText: '#5181fc',
      secondaryText: '#ff7b00',
      componentText: '#00ffff',
      placeholderText: '#00ffff',
      icon: '#f0f0f0',
      error: '#0f0f0f',
    },
  },
};
```

#### Tùy chỉnh hình dạng

Bạn có thể tùy chỉnh bán kính viền, độ rộng viền và bóng được sử dụng trong toàn bộ giao diện thanh toán:

```tsx theme={null}
const appearance = {
  shapes: {
    borderRadius: 10, // Border radius for input fields, tabs, and components
    borderWidth: 1,   // Border width for components
  },
};
```

#### Tùy chỉnh cụ thể cho thành phần

Bạn có thể tùy chỉnh các thành phần UI cụ thể như nút chính (nút Thanh toán). Các cài đặt này có ưu tiên hơn các cài đặt giao diện toàn cầu:

```tsx theme={null}
const appearance = {
  primaryButton: {
    colors: {
      background: '#000000',
      text: '#ffffff',
      border: '#ff00ff',
    },
    shapes: {
      borderRadius: 10,
      borderWidth: 1.5,
    },
  },
};
```

Để áp dụng các tùy chỉnh này, hãy bao gồm chúng trong cấu hình phiên thanh toán của bạn:

```tsx theme={null}
const params: sessionParams = {
  ...paymentSheetParams,
  configuration: {
    appearance: {
      themes: isDarkMode ? 'dark' : 'light',
      ...appearance, // Include your custom appearance settings
    },
  },
};
```

## Xử lý lỗi

Xử lý các trạng thái thanh toán khác nhau trong hàm thanh toán của bạn:

```tsx theme={null}
const handlePaymentResult = (paymentSheetResponse) => {
  switch (paymentSheetResponse?.status) {
    case 'cancelled':
      // User cancelled the payment
      console.log('Payment cancelled by user');
      break;
    case 'succeeded':
      // Payment completed successfully
      console.log('Payment succeeded');
      // Navigate to success screen or update UI
      break;
    case 'failed':
      // Payment failed
      console.log('Payment failed:', paymentSheetResponse?.message);
      // Show error message to user
      break;
    default:
      console.log('Unknown payment status:', paymentSheetResponse?.status);
  }
};
```

<AccordionGroup>
  <Accordion title="Common Error Scenarios">
    * **Sự cố kết nối mạng**: Đảm bảo kết nối internet ổn định
    * **Client secret không hợp lệ**: Xác minh backend đang tạo payment intent hợp lệ
    * **Thiếu các phụ thuộc đồng cấp**: Cài đặt tất cả phụ thuộc cần thiết
    * **Cấu hình riêng theo nền tảng**: Hoàn thành các bước cài đặt iOS và Android
    * **Lỗi API**: Kiểm tra [Tham chiếu mã lỗi](/api-reference/error-codes) để xử lý lỗi chi tiết
  </Accordion>

  <Accordion title="Debugging Tips">
    * Bật ghi nhật ký gỡ lỗi trong quá trình phát triển
    * Kiểm tra các yêu cầu mạng đến backend của bạn
    * Xác minh khóa API được cấu hình đúng cách
    * Kiểm tra trên cả nền tảng iOS và Android
    * Xem lại [Câu hỏi thường gặp về kỹ thuật](/miscellaneous/faq) để biết các vấn đề thường gặp
    * Sử dụng [Chế độ thử nghiệm và Chế độ trực tiếp](/miscellaneous/test-mode-vs-live-mode) một cách phù hợp
  </Accordion>
</AccordionGroup>

### Phương thức thanh toán thử nghiệm

<Tip>
  Sử dụng số thẻ thử nghiệm trong quá trình phát triển để xác minh tích hợp mà không xử lý thanh toán thật. Tìm hiểu thêm về [quy trình kiểm thử](/miscellaneous/testing-process) và các môi trường thử nghiệm hiện có.
</Tip>
