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

# Bộ chuyển đổi Fastify

> Tìm hiểu cách tích hợp Dodo Payments với dự án Fastify App Router của bạn bằng cách sử dụng Bộ chuyển đổi NextJS của chúng tôi. Bao gồm thanh toán, cổng khách hàng, webhook và thiết lập môi trường an toàn.

<CardGroup cols={2}>
  <Card title="Checkout Handler" icon="cart-shopping" href="#checkout-route-handler">
    Tích hợp trang thanh toán Dodo Payments vào ứng dụng Fastify của bạn.
  </Card>

  <Card title="Customer Portal" icon="user" href="#customer-portal-route-handler">
    Cho phép khách hàng quản lý đăng ký và thông tin.
  </Card>

  <Card title="Webhooks" icon="bell" href="#webhook-route-handler">
    Nhận và xử lý các sự kiện webhook của Dodo Payments.
  </Card>
</CardGroup>

## Cài đặt

<Steps>
  <Step title="Install the package">
    Chạy lệnh sau tại thư mục gốc dự án của bạn:

    ```bash theme={null}
    npm install @dodopayments/fastify
    ```
  </Step>

  <Step title="Set up environment variables">
    Tạo một <code>.env</code> file trong thư mục gốc dự án của bạn:

    ```env expandable theme={null}
    DODO_PAYMENTS_API_KEY=your-api-key
    DODO_PAYMENTS_RETURN_URL=https://yourapp.com/success
    DODO_PAYMENTS_WEBHOOK_KEY=your-webhook-secret
    DODO_PAYMENTS_ENVIRONMENT="test_mode" or "live_mode""
    ```

    <Warning>
      Không bao giờ đẩy tệp <code>.env</code> hoặc bí mật lên hệ thống quản lý phiên bản.
    </Warning>
  </Step>
</Steps>

## Ví dụ về Xử lý Đường dẫn

<Info>
  Tất cả ví dụ giả định bạn đang sử dụng Fastify App Router.
</Info>

<Tabs>
  <Tab title="Checkout Handler">
    <Info>
      Sử dụng trình xử lý này để tích hợp trang thanh toán Dodo Payments vào ứng dụng Fastify của bạn. Hỗ trợ các luồng thanh toán tĩnh (GET), động (POST) và phiên (POST).
    </Info>

    <CodeGroup>
      ```typescript Fastify Route Handler expandable theme={null}
        // route.ts
        import { Checkout } from '@dodopayments/fastify';
        import Fastify from 'fastify'

        const fastify = Fastify({})
        const checkoutGet = Checkout({
            bearerToken: process.env.DODO_PAYMENTS_API_KEY,
            environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
            returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
            type: 'static'
        });

        const checkoutPost = Checkout({
            bearerToken: process.env.DODO_PAYMENTS_API_KEY,
            environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
            returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
            type: 'dynamic'
        });

        const checkoutSession = Checkout({
            bearerToken: process.env.DODO_PAYMENTS_API_KEY,
            environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
            returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
            type: 'session'
        });

        fastify.get('/api/checkout', checkoutGet.getHandler);
        fastify.post('/api/checkout', checkoutPost.postHandler);
        fastify.post('/api/checkout-session', checkoutSession.postHandler);
      ```
    </CodeGroup>

    <CodeGroup>
      ```curl Static Checkout Curl example expandable theme={null}
      curl --request GET \
      --url 'https://example.com/api/checkout?productId=pdt_fqJhl7pxKWiLhwQR042rh' \
      --header 'User-Agent: insomnia/11.2.0' \
      --cookie mode=test
      ```
    </CodeGroup>

    <CodeGroup>
      ```curl Dynamic Checkout Curl example expandable theme={null}
      curl --request POST \
      --url https://example.com/api/checkout \
      --header 'Content-Type: application/json' \
      --header 'User-Agent: insomnia/11.2.0' \
      --cookie mode=test \
      --data '{
      "billing": {
        "city": "Texas",
        "country": "US",
        "state": "Texas",
        "street": "56, hhh",
        "zipcode": "560000"
      },
      "customer": {
        "email": "test@example.com",
        	"name": "test"
      },
      "metadata": {},
      "payment_link": true,
        "product_id": "pdt_QMDuvLkbVzCRWRQjLNcs",
        "quantity": 1,
        "billing_currency": "USD",
        "discount_codes": ["IKHZ23M9GQ"],
        "return_url": "https://example.com",
        "trial_period_days": 10
      }'
      ```
    </CodeGroup>

    <CodeGroup>
      ```curl Checkout Session Curl example expandable theme={null}
      curl --request POST \
      --url https://example.com/api/checkout-session \
      --header 'Content-Type: application/json' \
      --header 'User-Agent: insomnia/11.2.0' \
      --cookie mode=test \
      --data '{
      "product_cart": [
        {
          "product_id": "pdt_QMDuvLkbVzCRWRQjLNcs",
          "quantity": 1
        }
      ],
      "customer": {
        "email": "test@example.com",
        "name": "test"
      },
      "return_url": "https://example.com/success"
      }'
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Customer Portal Handler">
    <Info>
      Sử dụng trình xử lý này để cho phép khách hàng quản lý đăng ký và thông tin qua cổng khách hàng Dodo Payments.
    </Info>

    <CodeGroup>
      ```typescript Fastify Route Handler expandable theme={null}
      // route.ts
      import { CustomerPortal } from "@dodopayments/fastify";
      import Fastify from 'fastify'

      const fastify = Fastify({})
      const customerPortalHandler = CustomerPortal({
          bearerToken: process.env.DODO_PAYMENTS_API_KEY,
          environment: process.env.DODO_PAYMENTS_ENVIRONMENT
      });
      fastify.get('/api/customer-portal', customerPortalHandler);
      ```
    </CodeGroup>

    <CodeGroup>
      ```curl Customer Portal Curl example expandable theme={null}
      curl --request GET \
      --url 'https://example.com/api/customer-portal?customer_id=cus_9VuW4K7O3GHwasENg31m&send_email=true' \
      --header 'User-Agent: insomnia/11.2.0' \
      --cookie mode=test
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Webhook Handler">
    <Info>
      Sử dụng trình xử lý này để nhận và xử lý các sự kiện webhook của Dodo Payments một cách an toàn trong ứng dụng Fastify của bạn.
    </Info>

    <CodeGroup>
      ```typescript Fastify Route Handler expandable theme={null}
      // route.ts
      import Fastify from 'fastify'
      import { Webhooks } from '@dodopayments/fastify'

      const fastify = Fastify({})
      fastify.addContentTypeParser('application/json', { parseAs: 'string' }, function (req, body, done) {
          done(null, body)
      })

      fastify.post('/api/webhooks', Webhooks({
      webhookKey: process.env.DODO_PAYMENTS_WEBHOOK_KEY,
      onPayload: async (payload) => {
          // Handle Payload Here
          console.log(payload)
      }
      }));

      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Xử lý Đường dẫn Thanh toán

<Info>
  Dodo Payments hỗ trợ ba loại luồng thanh toán để tích hợp thanh toán vào trang web của bạn, bộ điều hợp này hỗ trợ tất cả các loại luồng đó.
</Info>

* **Liên kết Thanh toán Tĩnh:** URL có thể chia sẻ ngay lập tức để thu thập thanh toán nhanh chóng, không cần mã.
* **Liên kết Thanh toán Động:** Tạo liên kết thanh toán theo chương trình với các chi tiết tùy chỉnh bằng cách sử dụng API hoặc SDK.
* **Phiên Thanh toán:** Tạo trải nghiệm thanh toán an toàn, tùy chỉnh với giỏ hàng sản phẩm và thông tin khách hàng được cấu hình trước.

<AccordionGroup>
  <Accordion title="Static Checkout (GET)">
    ### Tham số truy vấn được hỗ trợ

    <ParamField query="productId" type="string" required>
      Mã định danh sản phẩm (ví dụ, <code>?productId=pdt\_nZuwz45WAs64n3l07zpQR</code>).
    </ParamField>

    <ParamField query="quantity" type="integer">
      Số lượng sản phẩm.
    </ParamField>

    <ParamField query="fullName" type="string">
      Họ và tên đầy đủ của khách hàng.
    </ParamField>

    <ParamField query="firstName" type="string">
      Tên đầu tiên của khách hàng.
    </ParamField>

    <ParamField query="lastName" type="string">
      Họ của khách hàng.
    </ParamField>

    <ParamField query="email" type="string">
      Địa chỉ email của khách hàng.
    </ParamField>

    <ParamField query="country" type="string">
      Quốc gia của khách hàng.
    </ParamField>

    <ParamField query="addressLine" type="string">
      Dòng địa chỉ của khách hàng.
    </ParamField>

    <ParamField query="city" type="string">
      Thành phố của khách hàng.
    </ParamField>

    <ParamField query="state" type="string">
      Tiểu bang/tỉnh của khách hàng.
    </ParamField>

    <ParamField query="zipCode" type="string">
      Mã zip/bưu điện của khách hàng.
    </ParamField>

    <ParamField query="disableFullName" type="boolean">
      Vô hiệu hóa trường họ và tên.
    </ParamField>

    <ParamField query="disableFirstName" type="boolean">
      Vô hiệu hóa trường tên.
    </ParamField>

    <ParamField query="disableLastName" type="boolean">
      Vô hiệu hóa trường họ.
    </ParamField>

    <ParamField query="disableEmail" type="boolean">
      Vô hiệu hóa trường email.
    </ParamField>

    <ParamField query="disableCountry" type="boolean">
      Vô hiệu hóa trường quốc gia.
    </ParamField>

    <ParamField query="disableAddressLine" type="boolean">
      Vô hiệu hóa trường dòng địa chỉ.
    </ParamField>

    <ParamField query="disableCity" type="boolean">
      Vô hiệu hóa trường thành phố.
    </ParamField>

    <ParamField query="disableState" type="boolean">
      Vô hiệu hóa trường tiểu bang.
    </ParamField>

    <ParamField query="disableZipCode" type="boolean">
      Vô hiệu hóa trường mã zip.
    </ParamField>

    <ParamField query="paymentCurrency" type="string">
      Chỉ định loại tiền thanh toán (ví dụ, <code>USD</code>).
    </ParamField>

    <ParamField query="showCurrencySelector" type="boolean">
      Hiển thị trình chọn tiền tệ.
    </ParamField>

    <ParamField query="paymentAmount" type="integer">
      Chỉ định số tiền thanh toán (ví dụ, <code>1000</code> cho \$10.00).
    </ParamField>

    <ParamField query="showDiscounts" type="boolean">
      Hiển thị các trường giảm giá.
    </ParamField>

    <ParamField query="metadata_*" type="string">
      Bất kỳ tham số truy vấn nào bắt đầu bằng <code>metadata\_</code> sẽ được truyền dưới dạng metadata.
    </ParamField>

    <Warning>
      Nếu <code>productId</code> bị thiếu, trình xử lý trả về phản hồi 400. Các tham số truy vấn không hợp lệ cũng dẫn đến phản hồi 400.
    </Warning>

    ### Định dạng Phản hồi

    Thanh toán tĩnh trả về phản hồi JSON với URL thanh toán:

    ```json theme={null}
    {
      "checkout_url": "https://checkout.dodopayments.com/..."
    }
    ```
  </Accordion>

  <Accordion title="Dynamic Checkout (POST)">
    * Gửi các tham số dưới dạng thân JSON trong một yêu cầu POST.
    * Hỗ trợ cả thanh toán một lần và định kỳ.
    * Để xem danh sách đầy đủ các trường thân POST được hỗ trợ, tham khảo:
      * [Request body for a One Time Payment Product](https://docs.dodopayments.com/api-reference/payments/post-payments)
      * [Request body for a Subscription Product](https://docs.dodopayments.com/api-reference/subscriptions/post-subscriptions)

    ### Định dạng Phản hồi

    Thanh toán động trả về phản hồi JSON với URL thanh toán:

    ```json theme={null}
    {
      "checkout_url": "https://checkout.dodopayments.com/..."
    }
    ```
  </Accordion>

  <Accordion title="Checkout Sessions (POST)">
    Phiên thanh toán cung cấp trải nghiệm thanh toán lưu trú an toàn hơn, xử lý toàn bộ luồng thanh toán cho cả mua một lần và đăng ký với khả năng tùy chỉnh đầy đủ.

    Tham khảo [Hướng dẫn Tích hợp Phiên Thanh toán](https://docs.dodopayments.com/developer-resources/checkout-session) để biết thêm chi tiết và danh sách đầy đủ các trường được hỗ trợ.

    ### Định dạng Phản hồi

    Các phiên thanh toán trả về phản hồi JSON với URL thanh toán:

    CODE\_PLACEHOLDER\_dd95c237f3ca327d\_End
  </Accordion>
</AccordionGroup>

## Xử lý Đường dẫn Cổng Khách Hàng

Bộ xử lý Đường dẫn Cổng Khách Hàng cho phép bạn tích hợp liền mạch cổng khách hàng Dodo Payments vào ứng dụng Fastify của bạn.

### Tham số truy vấn

<ParamField query="customer_id" type="string" required>
  ID khách hàng cho phiên cổng (ví dụ, <code>?customer\_id=cus\_123</code>).
</ParamField>

<ParamField query="send_email" type="boolean">
  Nếu đặt thành <code>true</code>, gửi email cho khách hàng với liên kết cổng.
</ParamField>

<Warning>
  Trả về 400 nếu <code>customer\_id</code> bị thiếu.
</Warning>

## Xử lý Đường dẫn Webhook

* **Phương thức:** Chỉ hỗ trợ yêu cầu POST. Các phương thức khác trả về 405.
* **Xác minh Chữ ký:** Xác minh chữ ký webhook bằng cách sử dụng <code>webhookKey</code>. Trả về 401 nếu xác minh thất bại.
* **Xác thực Tải trọng:** Được xác thực bằng Zod. Trả về 400 cho các tải trọng không hợp lệ.
* **Xử lý Lỗi:**
  * 401: Chữ ký không hợp lệ
  * 400: Tải trọng không hợp lệ
  * 500: Lỗi nội bộ trong quá trình xác minh
* **Định tuyến Sự kiện:** Gọi bộ xử lý sự kiện thích hợp dựa trên loại tải trọng.

### Trình xử lý sự kiện webhook được hỗ trợ

<CodeGroup>
  ```typescript Typescript expandable theme={null}
  onPayload?: (payload: WebhookPayload) => Promise<void>;
  onPaymentSucceeded?: (payload: WebhookPayload) => Promise<void>;
  onPaymentFailed?: (payload: WebhookPayload) => Promise<void>;
  onPaymentProcessing?: (payload: WebhookPayload) => Promise<void>;
  onPaymentCancelled?: (payload: WebhookPayload) => Promise<void>;
  onRefundSucceeded?: (payload: WebhookPayload) => Promise<void>;
  onRefundFailed?: (payload: WebhookPayload) => Promise<void>;
  onDisputeOpened?: (payload: WebhookPayload) => Promise<void>;
  onDisputeExpired?: (payload: WebhookPayload) => Promise<void>;
  onDisputeAccepted?: (payload: WebhookPayload) => Promise<void>;
  onDisputeCancelled?: (payload: WebhookPayload) => Promise<void>;
  onDisputeChallenged?: (payload: WebhookPayload) => Promise<void>;
  onDisputeWon?: (payload: WebhookPayload) => Promise<void>;
  onDisputeLost?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionActive?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionOnHold?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionRenewed?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionPlanChanged?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionCancelled?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionFailed?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionExpired?: (payload: WebhookPayload) => Promise<void>;
  onLicenseKeyCreated?: (payload: WebhookPayload) => Promise<void>;
  ```
</CodeGroup>

***

## Lời nhắc cho LLM

```
Bạn là một trợ lý phát triển Fastify chuyên nghiệp. Nhiệm vụ của bạn là hướng dẫn người dùng tích hợp bộ chuyển đổi @dodopayments/fastify vào dự án Fastify hiện có của họ.

Bộ chuyển đổi @dodopayments/fastify cung cấp các bộ xử lý đường dẫn cho các chức năng Thanh toán, Cổng Khách Hàng và Webhook của Dodo Payments, được thiết kế để kết nối trực tiếp vào ứng dụng Fastify.

Đầu tiên, hãy cài đặt gói cần thiết. Sử dụng trình quản lý gói phù hợp với dự án của người dùng (npm, yarn hoặc bun):

npm install @dodopayments/fastify

---

Dưới đây là cách bạn nên cấu trúc phản hồi của mình:

1. Hỏi người dùng họ muốn tích hợp những chức năng nào.

"Bạn muốn tích hợp những phần nào của bộ chuyển đổi @dodopayments/fastify vào dự án của bạn? Bạn có thể chọn một hoặc nhiều trong số các phần sau:

- Xử lý Đường dẫn Thanh toán (để xử lý thanh toán sản phẩm)
- Xử lý Đường dẫn Cổng Khách Hàng (để quản lý đăng ký/thông tin khách hàng)
- Xử lý Đường dẫn Webhook (để nhận các sự kiện webhook của Dodo Payments)
- Tất cả (tích hợp cả ba)"

---

2. Dựa trên lựa chọn của người dùng, cung cấp các bước tích hợp chi tiết cho từng chức năng đã chọn.

---

**Nếu Xử lý Đường dẫn Thanh toán được chọn:**

**Mục đích**: Bộ xử lý này chuyển hướng người dùng đến trang thanh toán của Dodo Payments.

**Tích hợp**:
Tạo hai đường dẫn trong ứng dụng Fastify của bạn — một cho thanh toán tĩnh (GET) và một cho thanh toán động (POST).

import { Checkout } from '@dodopayments/fastify';
import Fastify from 'fastify'

const fastify = Fastify({})
const checkoutGet = Checkout({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
    returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
    type: 'static'
});

const checkoutPost = Checkout({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
    returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
    type: 'dynamic'
});

const checkoutSession = Checkout({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
    returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
    type: 'session'
});

fastify.get('/api/checkout', checkoutGet.getHandler);
fastify.post('/api/checkout', checkoutPost.postHandler);
fastify.post('/api/checkout-session', checkoutSession.postHandler);

Tùy chọn Cấu hình:

    bearerToken: Khóa API Dodo Payments của bạn (khuyến nghị lưu trữ trong biến môi trường DODO_PAYMENTS_API_KEY).

    returnUrl (tùy chọn): URL để chuyển hướng người dùng sau khi thanh toán thành công.

    environment: "test_mode" hoặc "live_mode"

    type: "static" (GET), "dynamic" (POST), hoặc "session" (POST)

GET (thanh toán tĩnh) mong đợi các tham số truy vấn:

    productId (bắt buộc)

    quantity, các trường khách hàng (fullName, email, v.v.), và metadata (metadata_*) là tùy chọn.

    Trả về: {"checkout_url": "https://checkout.dodopayments.com/..."}

POST (thanh toán động) mong đợi một thân JSON với chi tiết thanh toán (một lần hoặc đăng ký). Trả về: {"checkout_url": "https://checkout.dodopayments.com/..."}. Tham khảo tài liệu để biết sơ đồ POST đầy đủ:

    Thanh toán một lần: https://docs.dodopayments.com/api-reference/payments/post-payments

    Đăng ký: https://docs.dodopayments.com/api-reference/subscriptions/post-subscriptions

POST (phiên thanh toán) - (Khuyến nghị) Một trải nghiệm thanh toán tùy chỉnh hơn. Trả về JSON với checkout_url: Các tham số được gửi dưới dạng thân JSON. Hỗ trợ cả thanh toán một lần và định kỳ. Trả về: {"checkout_url": "https://checkout.dodopayments.com/session/..."}. Để có danh sách đầy đủ các trường được hỗ trợ, hãy tham khảo:

    Hướng dẫn Tích hợp Phiên Thanh toán: https://docs.dodopayments.com/developer-resources/checkout-session

Nếu Xử lý Đường dẫn Cổng Khách Hàng được chọn:

Mục đích: Đường dẫn này cho phép khách hàng quản lý đăng ký của họ thông qua cổng Dodo Payments.

Tích hợp:

import { CustomerPortal } from "@dodopayments/fastify";
import Fastify from 'fastify'

const fastify = Fastify({})
const customerPortalHandler = CustomerPortal({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: process.env.DODO_PAYMENTS_ENVIRONMENT
});
fastify.get('/api/customer-portal', customerPortalHandler);

Tham số Truy vấn:

    customer_id (bắt buộc): ví dụ, ?customer_id=cus_123

    send_email (tùy chọn): nếu đúng, khách hàng sẽ nhận được email với liên kết cổng

Trả về 400 nếu customer_id bị thiếu.

Nếu Xử lý Đường dẫn Webhook được chọn:

Mục đích: Xử lý các sự kiện webhook đến từ Dodo Payments để kích hoạt các sự kiện trong ứng dụng của bạn.

Tích hợp:

import Fastify from 'fastify'
import { Webhooks } from '@dodopayments/fastify'

const fastify = Fastify({})
fastify.addContentTypeParser('application/json', { parseAs: 'string' }, function (req, body, done) {
    done(null, body)
})

fastify.post('/api/webhooks', Webhooks({
  webhookKey: process.env.DODO_PAYMENTS_WEBHOOK_KEY,
  onPayload: async (payload) => {
    // Xử lý Tải trọng Tại Đây
    console.log(payload)
  }
}));

Các Tính năng:

    Chỉ cho phép phương thức POST — các phương thức khác trả về 405

    Xác minh chữ ký được thực hiện bằng cách sử dụng webhookKey. Trả về 401 nếu không hợp lệ.

    Xác thực tải trọng dựa trên Zod. Trả về 400 nếu sơ đồ không hợp lệ.

    Tất cả các bộ xử lý đều là các hàm bất đồng bộ.

Các Bộ xử lý Sự kiện Webhook Hỗ trợ:

Bạn có thể truyền vào bất kỳ bộ xử lý nào sau đây:

    onPayload

    onPaymentSucceeded

    onPaymentFailed

    onPaymentProcessing

    onPaymentCancelled

    onRefundSucceeded

    onRefundFailed

    onDisputeOpened, onDisputeExpired, onDisputeAccepted, onDisputeCancelled, onDisputeChallenged, onDisputeWon, onDisputeLost

    onSubscriptionActive, onSubscriptionOnHold, onSubscriptionRenewed, onSubscriptionPaused, onSubscriptionPlanChanged, onSubscriptionCancelled, onSubscriptionFailed, onSubscriptionExpired

    onLicenseKeyCreated

Thiết lập Biến Môi Trường:

Hãy chắc chắn định nghĩa các biến môi trường này trong dự án của bạn:

DODO_PAYMENTS_API_KEY=your-api-key
DODO_PAYMENTS_RETURN_URL=https://yourapp.com/success
DODO_PAYMENTS_WEBHOOK_KEY=your-webhook-secret
DODO_PAYMENTS_ENVIRONMENT="test_mode" hoặc "live_mode""

Sử dụng chúng bên trong mã của bạn như:

process.env.DODO_PAYMENTS_API_KEY
process.env.DODO_PAYMENTS_WEBHOOK_KEY

Lưu ý Bảo mật: Không cam kết bí mật vào hệ thống kiểm soát phiên bản. Sử dụng tệp .env cục bộ và các trình quản lý bí mật trong môi trường triển khai (ví dụ: AWS, Vercel, Heroku, v.v.).

Sử dụng những cái này trong mã của bạn như sau:

process.env.DODO_PAYMENTS_API_KEY
process.env.DODO_PAYMENTS_WEBHOOK_KEY

Lưu ý Bảo mật: Không được đưa các thông tin bí mật vào kiểm soát phiên bản. Sử dụng tệp .env trên máy cục bộ và trình quản lý bí mật trong các môi trường triển khai (ví dụ: AWS, Vercel, Heroku, v.v.).
```
