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

# GoHighLevel

> Tích hợp Dodo Payments với GoHighLevel (GHL) bằng payment links không cần code, overlay checkout hoặc inline checkout, đồng thời tự động hóa việc hoàn tất đơn hàng bằng webhooks.

## Giới thiệu

[GoHighLevel](https://www.gohighlevel.com/) (GHL) là nền tảng CRM và marketing tất cả trong một, hỗ trợ funnels, website, email/SMS và tự động hóa ("Workflows"). GHL không liệt kê Dodo Payments là processor tích hợp sẵn, vì vậy bạn kết nối hai nền tảng này theo một trong ba cách, tùy thuộc vào mức độ tích hợp checkout và khả năng viết code của bạn.

Trong mọi phương án, việc hoàn tất đơn hàng được xử lý theo cùng một cách. Dodo gửi [các sự kiện webhook](/developer-resources/webhooks) đến **Inbound Webhook Workflow** của GHL để gắn tag cho contact, cấp quyền truy cập và gửi email xác nhận.

## Chọn phương án

| Phương án               | Code cần thiết            | Trải nghiệm checkout                                   | Phù hợp nhất với                                                |
| ----------------------- | ------------------------- | ------------------------------------------------------ | --------------------------------------------------------------- |
| **A. Payment Links**    | Không (no-code)           | Khách hàng được chuyển hướng đến checkout do Dodo host | Hầu hết người dùng GHL, triển khai nhanh nhất                   |
| **B. Overlay Checkout** | Code tùy chỉnh và backend | Một modal mở trên trang GHL                            | Các nhóm muốn checkout ngay trên trang mà không rời khỏi funnel |
| **C. Inline Checkout**  | Code tùy chỉnh và backend | Form checkout được nhúng bên trong trang               | UX được nhúng hoàn toàn và mang thương hiệu                     |

<Info>
  Mới bắt đầu? Hãy bắt đầu với **Phương án A (Payment Links)**. Phương án này không cần code, hoạt động với mọi người dùng GHL và chỉ mất vài phút. Phương án B và C cần backend để tạo [checkout sessions](/api-reference/checkout-sessions/create), phù hợp với các nhóm có kinh nghiệm viết code.
</Info>

## Điều kiện tiên quyết

* Tài khoản Dodo Payments có ít nhất một **product** đã được tạo.
* Tài khoản GoHighLevel có funnel, website hoặc workflow.
* Quyền truy cập **Settings → Webhooks** (và **Settings → Developer** để lấy API key) trong dashboard Dodo.
* Với Phương án B và C: một **backend hoặc serverless endpoint** nhỏ để tạo checkout sessions.

<Note>
  GHL yêu cầu **connected domain** để *publish* funnel. Trong quá trình xây dựng, hãy sử dụng **Preview** của funnel để kiểm thử. Lưu ý rằng JavaScript tùy chỉnh (Phương án B và C) thường chỉ chạy trên **published page trên domain thực**, không chạy trong Preview.
</Note>

## Hoàn tất đơn hàng bằng webhooks (tất cả phương án)

Đây là lớp tự động hóa. Thiết lập một lần và hoạt động bất kể bạn chọn phương án checkout nào.

<Steps>
  <Step title="Create the workflow">
    Trong **sub-account** GHL, mở **Automation** ở menu bên trái (màn hình sẽ mở tab **Workflows**). Nhấp **Create workflow**, sau đó chọn **Start from Scratch**.
  </Step>

  <Step title="Add the Inbound Webhook trigger">
    Trong builder, nhấp **Add new trigger**. Trong bảng **Add trigger**, tìm kiếm **webhook** và chọn **Inbound webhook** (nằm trong **Triggers → Events**). Sao chép **Webhook URL** được tạo.
  </Step>

  <Step title="Register the webhook in Dodo">
    Trong dashboard Dodo, đi đến **Settings → Webhooks**, thêm endpoint mới và dán GHL Inbound Webhook URL. Thực hiện một giao dịch thử để GHL thu thập payload mẫu, từ đó bạn có thể ánh xạ các field (email khách hàng, product, amount, status).
  </Step>

  <Step title="Add fulfillment actions">
    Quay lại workflow GHL, thêm các action dựa trên sự kiện, chẳng hạn như **find/create contact by email**, **add a tag**, **grant course/membership access** và **send a confirmation email**. Sau đó **Publish** workflow.
  </Step>
</Steps>

<Warning>
  Thanh toán được xử lý trên Dodo, vì vậy chúng sẽ **không xuất hiện trong tab Payments của GHL**. Đối soát chúng vào GHL bằng webhook workflow ở trên và xem **webhook là nguồn dữ liệu chính xác** để cấp quyền truy cập, không phải browser redirect, vì khách hàng có thể đóng tab trước khi quay lại.
</Warning>

## Phương án A: Payment Links (no-code)

Gắn Dodo payment link vào bất kỳ nút GHL, funnel CTA, nút trên trang order, email hoặc SMS nào.

<Steps>
  <Step title="Create a product and copy its payment link">
    Trong dashboard Dodo, đi đến **Products → Add Product**, đặt **name** và **price**, chọn **one-time** hoặc **subscription**, rồi nhấp **Save**. Mở product và sao chép **Payment Link** (định dạng: `https://checkout.dodopayments.com/buy/{product_id}`).
  </Step>

  <Step title="Add the link to your GHL button">
    Chỉnh sửa funnel hoặc trang website, chọn **Buy / Checkout button**, đặt action thành **Open URL / Website** và dán payment link của Dodo.
  </Step>

  <Step title="Set a success page (optional)">
    Đặt **return URL** của product trong Dodo thành trang cảm ơn của GHL để khách hàng quay lại funnel sau khi thanh toán.
  </Step>
</Steps>

<Tip>
  Bạn có thể điền sẵn và khóa thông tin khách hàng hoặc thêm tracking bằng [payment-link query parameters](/features/checkout). Tính năng này hữu ích khi truyền funnel hoặc offer ID dưới dạng metadata mà bạn có thể đọc lại từ webhook.
</Tip>

## Phương án B: Overlay Checkout (code tùy chỉnh)

Mở Dodo checkout dưới dạng **modal overlay** trên trang GHL bằng [Checkout SDK](/developer-resources/overlay-checkout) qua CDN. Cần backend để tạo [checkout session](/api-reference/checkout-sessions/create) và trả về `checkoutUrl`.

<Steps>
  <Step title="Create a backend endpoint that calls the Checkout Sessions API">
    Bước này **bắt buộc**. SDK cần một `checkoutUrl` đang hoạt động, và để tạo một session cần **secret API key**. GHL chỉ host các trang tĩnh, không thể thực hiện lời gọi server-side này thay bạn; đồng thời bạn không được gọi [Create Checkout Session API](/api-reference/checkout-sessions/create) trực tiếp từ browser, vì điều đó sẽ làm lộ secret key trong source của trang. Do đó, overlay checkout và inline checkout **không thể hoạt động chỉ với GHL**: bạn cần một backend do mình kiểm soát để tạo session và chỉ trả về URL.

    Bất kỳ backend nhỏ nào cũng được: một serverless function (Cloudflare Workers, Vercel Functions, AWS Lambda, Supabase Edge Functions và các nền tảng tương tự) hoặc endpoint trên server bạn đang vận hành. Logic ở mọi nơi đều giống nhau: nhận request, gọi API Dodo bằng secret key và trả về `checkout_url`.

    Logic handler mẫu (điều chỉnh theo nền tảng bạn chọn):

    ```js theme={null}
    async function createCheckout(env) {
      const res = await fetch("https://test.dodopayments.com/checkouts", {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${env.DODO_API_KEY}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          product_cart: [{ product_id: "pdt_your_product_id", quantity: 1 }],
        }),
      });

      const data = await res.json();
      return { checkoutUrl: data.checkout_url };
    }
    ```

    Lưu API key Dodo dưới dạng secret trên nền tảng bạn triển khai (không bao giờ commit vào code), cho phép request từ domain GHL (CORS) và định tuyến endpoint dưới một domain do bạn kiểm soát, ví dụ `https://api.example.com/create-checkout`. Chuyển sang `https://live.dodopayments.com/checkouts` khi chuyển sang live mode.
  </Step>

  <Step title="Add a Custom Code element in the GHL page builder">
    Mở funnel step hoặc trang website trong GHL page builder, sau đó:

    1. Nhấp biểu tượng **+** ở góc trên bên trái builder để mở **Quick Add**.
    2. Chọn **Elements** từ danh sách category bên trái.
    3. Tìm **Custom Code** (cũng hiển thị là HTML) và kéo vào trang.
    4. Dán code bên dưới vào code editor của element, sau đó lưu lại.

    ```html theme={null}
    <!-- Load the Dodo Checkout SDK -->
    <script src="https://cdn.jsdelivr.net/npm/dodopayments-checkout@latest/dist/index.js"></script>
    <script>
      DodoPaymentsCheckout.DodoPayments.Initialize({
        mode: "test", // change to "live" in production
        displayType: "overlay",
        onEvent: (event) => console.log("Checkout event:", event),
      });

      async function openDodoCheckout() {
        // calls the backend endpoint from the previous step, creating a fresh session per click
        const res = await fetch("https://api.example.com/create-checkout", { method: "POST" });
        const { checkoutUrl } = await res.json();

        DodoPaymentsCheckout.DodoPayments.Checkout.open({ checkoutUrl });
      }
    </script>

    <button onclick="openDodoCheckout()">Pay Now</button>
    ```
  </Step>

  <Step title="Publish and test on your domain">
    Custom JS chạy trên trang **published** (connected domain), nhưng không phải lúc nào cũng chạy trong Preview. Publish trang, sau đó nhấp **Pay Now** để xác nhận overlay mở thành công.
  </Step>
</Steps>

## Phương án C: Inline (embedded) Checkout

Nhúng form checkout **bên trong** trang GHL (không redirect, không popup) bằng cùng SDK với một mount container. Giống Phương án B, phương án này cần backend để tạo session.

<Steps>
  <Step title="Create a backend endpoint that calls the Checkout Sessions API">
    Yêu cầu giống overlay và cũng **bắt buộc**: việc tạo session cần secret API key, vì vậy phải được thực hiện server-side. GHL không thể tự thực hiện việc này. Tái sử dụng backend endpoint được mô tả trong phần **Overlay Checkout** ở trên (bất kỳ serverless function hoặc server nhỏ nào do bạn kiểm soát) để gọi [Create Checkout Session API](/api-reference/checkout-sessions/create) và trả về `{ checkoutUrl }`.
  </Step>

  <Step title="Add a container and SDK via Custom Code">
    Trong GHL page builder:

    1. Nhấp biểu tượng **+** ở góc trên bên trái builder để mở **Quick Add**.
    2. Chọn **Elements** từ danh sách category bên trái.
    3. Tìm **Custom Code** (cũng hiển thị là HTML) và kéo vào vị trí trên trang nơi bạn muốn form checkout xuất hiện.
    4. Dán code bên dưới vào code editor của element, sau đó lưu lại.

    ```html theme={null}
    <script src="https://cdn.jsdelivr.net/npm/dodopayments-checkout@latest/dist/index.js"></script>

    <div id="dodo-inline-checkout"></div>

    <script>
      DodoPaymentsCheckout.DodoPayments.Initialize({
        mode: "test",
        displayType: "inline",
        onEvent: (event) => console.log("Checkout event:", event),
      });

      async function mountDodoCheckout() {
        // calls the backend endpoint from the previous step
        const res = await fetch("https://api.example.com/create-checkout", { method: "POST" });
        const { checkoutUrl } = await res.json();

        DodoPaymentsCheckout.DodoPayments.Checkout.open({
          checkoutUrl,
          elementId: "dodo-inline-checkout",
        });
      }

      mountDodoCheckout();
    </script>
    ```
  </Step>

  <Step title="Verify your domain for wallets (Apple Pay)">
    Để sử dụng Apple Pay trên inline checkout, hãy [xác minh domain của bạn](/features/payment-methods/digital-wallets#apple-pay). Host association file và đăng ký domain trong dashboard.
  </Step>
</Steps>

<Warning>
  Inline là lựa chọn phức tạp nhất trong GHL. Phương án này cần code tùy chỉnh, backend, published page trên domain thực và (đối với Apple Pay) xác minh domain. Nếu không cần form được nhúng hoàn toàn, hãy ưu tiên Phương án A hoặc B.
</Warning>

## Các sự kiện cần xử lý

| Dodo event                                        | Thời điểm kích hoạt         | GHL action đề xuất                                                 |
| ------------------------------------------------- | --------------------------- | ------------------------------------------------------------------ |
| `payment.succeeded`                               | Payment được capture        | Gắn tag contact là đã thanh toán, cấp quyền truy cập, gửi xác nhận |
| `subscription.active`                             | Subscription được kích hoạt | Cấp quyền membership, bắt đầu onboarding workflow                  |
| `subscription.renewed`                            | Đã nhận payment gia hạn     | Gia hạn quyền truy cập cho chu kỳ tiếp theo                        |
| `subscription.on_hold`                            | Gia hạn không thành công    | Kích hoạt workflow nhắc thanh toán hoặc dunning                    |
| `subscription.cancelled` / `subscription.expired` | Subscription kết thúc       | Xóa quyền truy cập, gắn tag churned                                |

Mọi webhook đều bao gồm **customer email**. Sử dụng action **find/create contact by email** của GHL để liên kết payment với đúng contact. Để xem danh sách đầy đủ, hãy tham khảo [Webhook Event Guide](/developer-resources/webhooks/intents/webhook-events-guide).

## Kiểm thử và đưa vào vận hành

<Steps>
  <Step title="Test in test mode">
    Giữ Dodo ở **Test Mode**, sử dụng test card `4242 4242 4242 4242` (bất kỳ ngày hết hạn trong tương lai và CVC nào), hoàn tất một giao dịch và xác nhận GHL workflow được kích hoạt cũng như áp dụng tag hoặc quyền truy cập.
  </Step>

  <Step title="Go live">
    Chuyển Dodo sang **Live Mode** và cập nhật webhook endpoint của live mode. Những thay đổi khác phụ thuộc vào phương án bạn chọn:

    * **Payment Links (A):** thay bằng payment link **live** của product.
    * **Overlay checkout (B):** trỏ backend đến `https://live.dodopayments.com/checkouts` bằng **live** API key và đặt `mode` của SDK thành `"live"` trong lời gọi `Initialize`.
    * **Inline checkout (C):** giống overlay vì sử dụng cùng backend endpoint và SDK initialization.

    Sau đó thực hiện một giao dịch thực tế end-to-end để xác nhận.
  </Step>
</Steps>

## Mẹo

<Tip>
  Hãy xem **webhook là nguồn dữ liệu chính xác** để cấp quyền truy cập. Xử lý `payment.succeeded` / `subscription.active`, không xử lý browser redirect.
</Tip>

<Tip>
  Xác minh tính xác thực của webhook bằng header `webhook-signature` ([Standard Webhooks](/developer-resources/webhooks)), để chỉ các sự kiện Dodo hợp lệ mới kích hoạt việc hoàn tất đơn hàng trong GHL.
</Tip>

## Khắc phục sự cố

<AccordionGroup>
  <Accordion title="Payment succeeded but nothing happened in GHL">
    Kiểm tra Dodo webhook endpoint có trỏ đến GHL Inbound Webhook URL chính xác hay không, workflow đã được **published** chưa và trigger đã thu thập payload mẫu để tạo field mapping hay chưa.
  </Accordion>

  <Accordion title="Overlay or inline button does nothing">
    Custom JS thường chỉ chạy trên **published page (real domain)**, không chạy trong Preview. Xác nhận trang đã được publish, SDK `<script>` đã được load và `checkoutUrl` là session URL hợp lệ từ backend của bạn.
  </Accordion>

  <Accordion title="Contact not created or not matched">
    Đảm bảo workflow sử dụng **find/create contact by email** và field email được ánh xạ từ webhook payload.
  </Accordion>

  <Accordion title="Payment isn't showing in GHL's Payments tab">
    Điều này là bình thường. Thanh toán được xử lý trên Dodo, vì vậy hãy đối soát chúng vào GHL bằng webhook workflow.
  </Accordion>
</AccordionGroup>
