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

# Inngest

> Kích hoạt các chức năng serverless và công việc nền trong Inngest dựa trên các sự kiện thanh toán của Dodo.

## Giới thiệu

Thực thi các chức năng serverless và công việc nền tự động khi xảy ra các sự kiện thanh toán. Xử lý thanh toán, gửi thông báo, cập nhật cơ sở dữ liệu và chạy các quy trình phức tạp với nền tảng thực thi chức năng đáng tin cậy của Inngest.

<Info>
  Tích hợp này yêu cầu URL webhook Inngest của bạn từ cấu hình hàm.
</Info>

## Bắt đầu

<Steps>
  <Step title="Open the Webhook Section">
    Trong bảng điều khiển Dodo Payments, điều hướng đến <b>Webhooks → + Thêm Điểm cuối</b> và mở rộng menu thả xuống tích hợp.

    <Frame>
      <img src="https://mintcdn.com/dodopayments/slbAEdrLLwKHfaRf/images/integrations/inngest.png?fit=max&auto=format&n=slbAEdrLLwKHfaRf&q=85&s=b160678c00ceed38439160b4b253c8f3" alt="Thêm Điểm cuối và menu thả xuống tích hợp" style={{ maxHeight: '500px', width: 'auto' }} width="1646" height="944" data-path="images/integrations/inngest.png" />
    </Frame>
  </Step>

  <Step title="Select Inngest">
    Chọn thẻ tích hợp <b>Inngest</b>.
  </Step>

  <Step title="Create Inngest Function">
    Trong Inngest, tạo một hàm mới và sao chép URL webhook từ cấu hình hàm.
  </Step>

  <Step title="Paste Webhook URL">
    Dán URL webhook Inngest vào cấu hình điểm cuối.
  </Step>

  <Step title="Configure Transformation">
    Chỉnh sửa mã chuyển đổi để định dạng sự kiện phù hợp với hàm Inngest của bạn.
  </Step>

  <Step title="Test & Create">
    Kiểm tra với các payload mẫu và nhấp <b>Create</b> để kích hoạt tích hợp.
  </Step>

  <Step title="Done!">
    🎉 Các sự kiện thanh toán giờ sẽ tự động kích hoạt các hàm Inngest của bạn.
  </Step>
</Steps>

## Ví dụ Mã Biến đổi

### Payload Sự kiện Cơ bản

```javascript basic_event.js icon="js" expandable theme={null}
function handler(webhook) {
  if (webhook.eventType === "payment.succeeded") {
    const p = webhook.payload.data;
    webhook.payload = {
      name: "payment.succeeded",
      data: {
        payment_id: p.payment_id,
        amount: (p.total_amount / 100).toFixed(2),
        currency: p.currency || "USD",
        customer_email: p.customer.email,
        customer_name: p.customer.name,
        payment_method: p.payment_method || "unknown"
      },
      user: {
        email: p.customer.email
      },
      ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
    };
  }
  return webhook;
}
```

### Bộ xử lý Sự kiện Đăng ký

```javascript subscription_event.js icon="js" expandable theme={null}
function handler(webhook) {
  const s = webhook.payload.data;
  switch (webhook.eventType) {
    case "subscription.active":
      webhook.payload = {
        name: "subscription.started",
        data: {
          subscription_id: s.subscription_id,
          customer_email: s.customer.email,
          customer_name: s.customer.name,
          product_id: s.product_id,
          amount: (s.recurring_pre_tax_amount / 100).toFixed(2),
          frequency: s.payment_frequency_interval,
          next_billing: s.next_billing_date
        },
        user: {
          email: s.customer.email
        },
        ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
      };
      break;
    case "subscription.cancelled":
      webhook.payload = {
        name: "subscription.cancelled",
        data: {
          subscription_id: s.subscription_id,
          customer_email: s.customer.email,
          cancelled_at: s.cancelled_at,
          cancel_at_next_billing: s.cancel_at_next_billing_date
        },
        user: {
          email: s.customer.email
        },
        ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
      };
      break;
  }
  return webhook;
}
```

### Bộ xử lý Sự kiện Tranh chấp

```javascript dispute_event.js icon="js" expandable theme={null}
function handler(webhook) {
  if (webhook.eventType.startsWith("dispute.")) {
    const d = webhook.payload.data;
    webhook.payload = {
      name: webhook.eventType,
      data: {
        dispute_id: d.dispute_id,
        payment_id: d.payment_id,
        amount: (d.amount / 100).toFixed(2),
        status: d.dispute_status,
        stage: d.dispute_stage,
        remarks: d.remarks || "",
        urgent: webhook.eventType === "dispute.opened"
      },
      user: {
        email: d.customer?.email || "unknown"
      },
      ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
    };
  }
  return webhook;
}
```

## Các Trường hợp Sử dụng Inngest Thông thường

<AccordionGroup>
  <Accordion title="Payment Processing">
    * Gửi email xác nhận
    * Cập nhật hồ sơ khách hàng
    * Xử lý hoàn tiền
    * Tạo hóa đơn
    * Cập nhật tồn kho
  </Accordion>

  <Accordion title="Subscription Management">
    * Chào đón người đăng ký mới
    * Xử lý hủy đăng ký
    * Gửi nhắc nhở gia hạn
    * Cập nhật chu kỳ thanh toán
    * Xử lý thanh toán thất bại
  </Accordion>

  <Accordion title="Analytics & Reporting">
    * Cập nhật số liệu doanh thu
    * Theo dõi hành vi khách hàng
    * Tạo báo cáo
    * Đồng bộ dữ liệu lên các nền tảng analytics
    * Tính toán tỷ lệ churn
  </Accordion>
</AccordionGroup>

## Mẹo

* Sử dụng tên sự kiện mô tả để tổ chức chức năng tốt hơn
* Bao gồm ngữ cảnh người dùng cho việc thực thi chức năng
* Đặt dấu thời gian chính xác cho việc sắp xếp sự kiện
* Cấu trúc dữ liệu nhất quán giữa các sự kiện
* Sử dụng các tính năng thử lại và xử lý lỗi của Inngest

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

<AccordionGroup>
  <Accordion title="Functions not triggering">
    * Xác nhận URL webhook chính xác và đang hoạt động
    * Kiểm tra hàm Inngest đã được triển khai và đang hoạt động
    * Đảm bảo tên sự kiện khớp với trình kích hoạt hàm
    * Xem lại nhật ký hàm Inngest để tìm lỗi
  </Accordion>

  <Accordion title="Data not received correctly">
    * Kiểm tra cấu trúc payload phù hợp với mong đợi của Inngest
    * Xác minh tên sự kiện được định dạng đúng
    * Đảm bảo bao gồm tất cả trường bắt buộc
    * Thử nghiệm với công cụ kiểm tra webhook của Inngest
  </Accordion>
</AccordionGroup>
