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

> 使用无代码支付链接、叠加式结账或内嵌式结账，将 Dodo Payments 与 GoHighLevel (GHL) 集成，并通过 webhooks 自动化履约。

## 简介

[GoHighLevel](https://www.gohighlevel.com/) (GHL) 是一个一体化 CRM 和 marketing 平台，涵盖漏斗、网站、email/SMS 以及自动化（"Workflows"）。GHL 未将 Dodo Payments 列为内置 processor，因此你可以根据希望结账体验嵌入的程度以及可编写代码的能力，通过以下三种方式之一连接两者。

无论采用哪种方式，履约处理方式都相同。Dodo 会将 [webhook events](/developer-resources/webhooks) 发送到 GHL 的 **Inbound Webhook Workflow**，用于为联系人添加标签、授予访问权限并发送确认通知。

## 选择适合你的方式

| 方式                      | 所需代码           | 结账体验                  | 适用场景                |
| ----------------------- | -------------- | --------------------- | ------------------- |
| **A. Payment Links**    | 无（无代码）         | 客户会被重定向到 Dodo 托管的结账页面 | 大多数 GHL 用户，最快上线     |
| **B. Overlay Checkout** | 自定义代码加 backend | 在 GHL 页面上方打开 modal    | 希望在页面内完成结账且不离开漏斗的团队 |
| **C. Inline Checkout**  | 自定义代码加 backend | 结账表单嵌入页面内部            | 完全嵌入式、品牌化的 UX       |

<Info>
  如果你刚开始接触，请从 **方式 A（Payment Links）** 开始。它无需代码，适用于所有 GHL 用户，只需几分钟即可完成。方式 B 和 C 需要 backend 来创建 [checkout sessions](/api-reference/checkout-sessions/create)，适合熟悉代码的团队。
</Info>

## 前置条件

* 一个至少创建了一个 **product** 的 Dodo Payments 账户。
* 一个拥有漏斗、网站或 workflow 的 GoHighLevel 账户。
* 在 Dodo dashboard 中拥有 **Settings → Webhooks** 的访问权限（以及用于获取 API key 的 **Settings → Developer** 访问权限）。
* 对于方式 B 和 C：一个用于创建 checkout sessions 的小型 **backend 或 serverless endpoint**。

<Note>
  GHL 要求拥有一个 **connected domain** 才能*发布*漏斗。在构建期间，请使用漏斗的 **Preview** 进行测试。请注意，自定义 JavaScript（方式 B 和 C）通常只会在**真实域名上的已发布页面**运行，而不会在 Preview 中运行。
</Note>

## 使用 webhooks 处理履约（所有方式）

这是自动化层。只需设置一次，无论选择哪种结账方式都可以正常工作。

<Steps>
  <Step title="Create the workflow">
    在 GHL 的 **sub-account** 中，从左侧菜单打开 **Automation**（此时会进入 **Workflows** 标签页）。点击 **Create workflow**，然后选择 **Start from Scratch**。
  </Step>

  <Step title="Add the Inbound Webhook trigger">
    在 builder 中，点击 **Add new trigger**。在 **Add trigger** 面板中搜索 **webhook**，然后选择 **Inbound webhook**（位于 **Triggers → Events** 下）。复制它生成的 **Webhook URL**。
  </Step>

  <Step title="Register the webhook in Dodo">
    在 Dodo dashboard 中，前往 **Settings → Webhooks**，添加新的 endpoint，然后粘贴 GHL Inbound Webhook URL。完成一次测试购买，让 GHL 捕获示例 payload，以便你映射字段（customer email、product、amount、status）。
  </Step>

  <Step title="Add fulfillment actions">
    返回 GHL workflow，根据 event 添加操作，例如 **find/create contact by email**、**add a tag**、**grant course/membership access** 以及 **send a confirmation email**。然后 **Publish** workflow。
  </Step>
</Steps>

<Warning>
  支付在 Dodo 上处理，因此不会出现在 GHL 的 Payments 标签页中。使用上述 webhook workflow 将支付记录同步到 GHL，并将 **webhook 视为授予访问权限的事实来源**，而不是浏览器重定向，因为客户可能会在返回之前关闭标签页。
</Warning>

## 方式 A：Payment Links（无代码）

将 Dodo payment link 添加到任意 GHL button、漏斗 CTA、order-page button、email 或 SMS 中。

<Steps>
  <Step title="Create a product and copy its payment link">
    在 Dodo dashboard 中，前往 **Products → Add Product**，设置 **name** 和 **price**，选择 **one-time** 或 **subscription**，然后点击 **Save**。打开该 product 并复制其 **Payment Link**（格式：`https://checkout.dodopayments.com/buy/{product_id}`）。
  </Step>

  <Step title="Add the link to your GHL button">
    编辑你的漏斗或网站页面，选择 **Buy / Checkout button**，将其操作设置为 **Open URL / Website**，然后粘贴你的 Dodo payment link。
  </Step>

  <Step title="Set a success page (optional)">
    在 Dodo 中将 product 的 **return URL** 设置为 GHL thank-you page，让客户付款后返回漏斗。
  </Step>
</Steps>

<Tip>
  你可以使用 [payment-link query parameters](/features/checkout) 预填并锁定客户信息，或添加 tracking。这对于将漏斗或 offer ID 作为 metadata 传递很有用，你可以通过 webhook 读取这些 metadata。
</Tip>

## 方式 B：Overlay Checkout（自定义代码）

通过 CDN 使用 [Checkout SDK](/developer-resources/overlay-checkout)，在 GHL 页面上以 **modal overlay** 的形式打开 Dodo checkout。需要一个 backend 来创建 [checkout session](/api-reference/checkout-sessions/create)，并返回其 `checkoutUrl`。

<Steps>
  <Step title="Create a backend endpoint that calls the Checkout Sessions API">
    此步骤**不可省略**。SDK 需要一个有效的 `checkoutUrl`，而创建它需要你的 **secret API key**。GHL 只托管静态页面，无法替你执行此 server-side 调用；你也绝不能直接从浏览器调用 [Create Checkout Session API](/api-reference/checkout-sessions/create)，因为这样会将 secret key 暴露在页面源代码中。因此，overlay 和 inline checkout **无法仅依靠 GHL 工作**：你需要一个由你控制的 backend 来创建 session，并仅返回 URL。

    任何小型 backend 都可以：serverless function（Cloudflare Workers、Vercel Functions、AWS Lambda、Supabase Edge Functions 等），或者你已有服务器上的 endpoint。无论使用哪种平台，逻辑都相同：接收请求，使用 secret key 调用 Dodo API，返回 `checkout_url`。

    示例 handler 逻辑（根据你选择的平台进行调整）：

    ```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 };
    }
    ```

    将 Dodo API key 作为 secret 存储在你部署所使用的平台上（绝不要将其提交到代码仓库），允许来自 GHL domain 的请求（CORS），并将 endpoint 部署在你控制的 domain 下，例如 `https://api.example.com/create-checkout`。迁移到 live mode 后，切换为 `https://live.dodopayments.com/checkouts`。
  </Step>

  <Step title="Add a Custom Code element in the GHL page builder">
    在 GHL page builder 中打开漏斗步骤或网站页面，然后：

    1. 点击 builder 左上角的 **+** 图标，打开 **Quick Add**。
    2. 从左侧 category list 中选择 **Elements**。
    3. 找到 **Custom Code**（也显示为 HTML），并将其拖到页面上。
    4. 将下面的代码粘贴到该元素的 code editor 中，然后保存。

    ```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 通常只会在**已发布页面**（connected domain）上运行，不一定会在 Preview 中运行。发布后点击 **Pay Now**，确认 overlay 是否打开。
  </Step>
</Steps>

## 方式 C：Inline（嵌入式）Checkout

使用同一个 SDK 和 mount container，将 checkout form **嵌入 GHL 页面内部**（无重定向、无 popup）。与方式 B 一样，它需要一个 backend 来创建 session。

<Steps>
  <Step title="Create a backend endpoint that calls the Checkout Sessions API">
    它与 overlay 的要求相同，同样**不可省略**：创建 session 需要你的 secret API key，因此必须在 server-side 执行。GHL 无法独立完成此操作。复用上方 **Overlay Checkout** 部分中说明的同一个 backend endpoint（任意由你控制的小型 serverless function 或服务器），该 endpoint 调用 [Create Checkout Session API](/api-reference/checkout-sessions/create) 并返回 `{ checkoutUrl }`。
  </Step>

  <Step title="Add a container and SDK via Custom Code">
    在 GHL page builder 中：

    1. 点击 builder 左上角的 **+** 图标，打开 **Quick Add**。
    2. 从左侧 category list 中选择 **Elements**。
    3. 找到 **Custom Code**（也显示为 HTML），并将其拖到你希望显示 checkout form 的位置。
    4. 将下面的代码粘贴到该元素的 code editor 中，然后保存。

    ```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)">
    要在 inline checkout 中使用 Apple Pay，请[验证你的 domain](/features/payment-methods/digital-wallets#apple-pay)。托管 association file，并在 dashboard 中注册该 domain。
  </Step>
</Steps>

<Warning>
  Inline 是 GHL 中参与度最高的选项。它需要自定义代码、backend、真实 domain 上的已发布页面，以及（对于 Apple Pay）domain verification。如果你不需要完全嵌入式的表单，请优先选择方式 A 或 B。
</Warning>

## 需要处理的 Events

| Dodo event                                        | 触发时机               | 建议的 GHL action                       |
| ------------------------------------------------- | ------------------ | ------------------------------------ |
| `payment.succeeded`                               | Payment 被 capture  | 将联系人标记为已付款，授予访问权限，发送确认通知             |
| `subscription.active`                             | Subscription 被激活   | 授予 membership，启动 onboarding workflow |
| `subscription.renewed`                            | 收取 renewal payment | 延长下一周期的访问权限                          |
| `subscription.on_hold`                            | Renewal 失败         | 触发 dunning 或 reminder workflow       |
| `subscription.cancelled` / `subscription.expired` | Subscription 结束    | 移除访问权限，添加 churned 标签                 |

每个 webhook 都包含 **customer email**。使用 GHL 的 **find/create contact by email** action，将支付关联到正确的联系人。完整列表请参阅 [Webhook Event Guide](/developer-resources/webhooks/intents/webhook-events-guide)。

## 测试与上线

<Steps>
  <Step title="Test in test mode">
    让 Dodo 保持在 **Test Mode**，使用测试卡 `4242 4242 4242 4242`（任意未来日期的有效期和任意 CVC），完成一次购买，并确认 GHL workflow 已触发且应用了标签或访问权限。
  </Step>

  <Step title="Go live">
    将 Dodo 切换到 **Live Mode**，并更新 live-mode webhook endpoint。其他需要更改的内容取决于你采用的方式：

    * **Payment Links (A)：** 换用 product 的 **live** payment link。
    * **Overlay checkout (B)：** 让 backend 使用 `https://live.dodopayments.com/checkouts` 和你的 **live** API key，并在 `Initialize` 调用中，将 SDK 的 `mode` 设置为 `"live"`。
    * **Inline checkout (C)：** 与 overlay 相同，因为它使用相同的 backend endpoint 和 SDK initialization。

    然后执行一次真实的端到端购买，以确认一切正常。
  </Step>
</Steps>

## 提示

<Tip>
  将**webhook 视为授予访问权限的事实来源**。根据 `payment.succeeded` / `subscription.active` 执行操作，而不是根据浏览器重定向执行。
</Tip>

<Tip>
  使用 `webhook-signature` header 验证 webhook 的真实性（[Standard Webhooks](/developer-resources/webhooks)），确保只有真实的 Dodo events 才会在 GHL 中触发履约。
</Tip>

## 故障排除

<AccordionGroup>
  <Accordion title="Payment succeeded but nothing happened in GHL">
    检查 Dodo webhook endpoint 是否指向正确的 GHL Inbound Webhook URL，workflow 是否已**发布**，以及 trigger 是否已捕获示例 payload，从而建立字段映射。
  </Accordion>

  <Accordion title="Overlay or inline button does nothing">
    Custom JS 通常只会在\*\*已发布页面（真实 domain）\*\*上运行，而不会在 Preview 中运行。确认页面已发布、SDK `<script>` 已加载，并且 `checkoutUrl` 是 backend 返回的有效 session URL。
  </Accordion>

  <Accordion title="Contact not created or not matched">
    确保 workflow 使用 **find/create contact by email**，并且 email 字段已从 webhook payload 中完成映射。
  </Accordion>

  <Accordion title="Payment isn't showing in GHL's Payments tab">
    这是预期行为。支付在 Dodo 上处理，因此请使用 webhook workflow 将其同步到 GHL。
  </Accordion>
</AccordionGroup>
