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

# Slack

> 将 Dodo Payments 与 Slack 集成，以实时接收有关您付款的通知。

## 介绍

Dodo Payments Slack 集成允许您直接在 Slack 工作区中接收有关您付款的实时通知。此集成使您能够随时了解付款状态，跟踪交易，并更有效地管理您的付款。

<Info>
  此集成使用我们的 Webhook 管理门户，将 Dodo Payments 的 Webhook 事件自动转换为兼容 Slack 的消息。无需额外编码——只需配置连接器，开始接收通知即可。
</Info>

## 开始使用

<Steps>
  <Step title="Open the Webhook Section">
    转到 Dodo Payments 仪表板中的<b>Webhook</b>部分。点击<b>+ 添加端点</b>按钮，然后打开 webhook 下拉菜单以显示其他集成。

    <Frame>
      <img src="https://mintcdn.com/dodopayments/slbAEdrLLwKHfaRf/images/integrations/slack/1.png?fit=max&auto=format&n=slbAEdrLLwKHfaRf&q=85&s=46218103ebf0646011873758c76b9bb6" alt="Dodo Payments 仪表板显示添加端点按钮和集成下拉菜单" style={{ maxHeight: '500px', width: 'auto' }} width="1782" height="1016" data-path="images/integrations/slack/1.png" />
    </Frame>
  </Step>

  <Step title="Select Slack Integration">
    选择<b>Slack</b>集成并点击<b>连接您的 Slack 工作区</b>。

    <Frame>
      <img src="https://mintcdn.com/dodopayments/slbAEdrLLwKHfaRf/images/integrations/slack/2.png?fit=max&auto=format&n=slbAEdrLLwKHfaRf&q=85&s=4bd696f82dbbab1bc099c6ccae5b9212" alt="Slack 集成卡片和连接按钮" style={{ maxHeight: '500px', width: 'auto' }} width="1670" height="226" data-path="images/integrations/slack/2.png" />
    </Frame>
  </Step>

  <Step title="Grant Slack Permissions">
    授予必要的权限给 Slack 应用程序的传入 Webhooks，以便它可以在您选择的频道中发布消息。

    <Frame>
      <img src="https://mintcdn.com/dodopayments/slbAEdrLLwKHfaRf/images/integrations/slack/3.png?fit=max&auto=format&n=slbAEdrLLwKHfaRf&q=85&s=00f04516a2720e377a29551ae42ad812" alt="Slack 传入 Webhooks 应用的 OAuth 权限屏幕" style={{ maxHeight: '500px', width: 'auto' }} width="1198" height="1536" data-path="images/integrations/slack/3.png" />
    </Frame>
  </Step>

  <Step title="Customize Transformation Code">
    添加或编辑转换代码，以根据您的用例自定义 Slack 通知。您可以使用预制模板或编写自己的逻辑。

    <Frame>
      <img src="https://mintcdn.com/dodopayments/slbAEdrLLwKHfaRf/images/integrations/slack/4.png?fit=max&auto=format&n=slbAEdrLLwKHfaRf&q=85&s=f3c7f2b7a9bb6d6ba1d1d6922ad42bc4" alt="Slack 集成的转换代码编辑器" style={{ maxHeight: '500px', width: 'auto' }} width="1686" height="1118" data-path="images/integrations/slack/4.png" />
    </Frame>
  </Step>

  <Step title="Test and Create">
    使用自定义或预制事件有效负载测试您的转换代码。当您满意后，点击<b>创建</b>以激活集成。

    <Frame>
      <img src="https://mintcdn.com/dodopayments/slbAEdrLLwKHfaRf/images/integrations/slack/5.png?fit=max&auto=format&n=slbAEdrLLwKHfaRf&q=85&s=7d22a91488a2038a177324fa627b7497" alt="测试转换和创建按钮" style={{ maxHeight: '500px', width: 'auto' }} width="1852" height="490" data-path="images/integrations/slack/5.png" />
    </Frame>
  </Step>

  <Step title="Integration Complete!">
    🎉 您已成功创建 Slack 集成！Dodo Payments 事件现在将实时发送到您选择的 Slack 频道。
  </Step>
</Steps>

## 转换代码示例

### 基本付款通知

此转换发送简单文本消息以处理付款事件：

```javascript payment_notifs.js icon="js" expandable theme={null}
function handler(webhook) {
  switch (webhook.eventType) {
    case "payment.succeeded":
      webhook.payload = {
        text: `✅ Payment Successful\nAmount: $${(webhook.payload.data.total_amount / 100).toFixed(2)}\nCustomer: ${webhook.payload.data.customer.email}\nPayment ID: ${webhook.payload.data.payment_id}`
      };
      break;
      
    case "payment.failed":
      webhook.payload = {
        text: `❌ Payment Failed\nAmount: $${(webhook.payload.data.total_amount / 100).toFixed(2)}\nCustomer: ${webhook.payload.data.customer.email}\nReason: ${webhook.payload.data.error_message || 'Unknown'}`
      };
      break;
      
    case "payment.processing":
      webhook.payload = {
        text: `⏳ Payment Processing\nAmount: $${(webhook.payload.data.total_amount / 100).toFixed(2)}\nCustomer: ${webhook.payload.data.customer.email}`
      };
      break;
  }

  return webhook;
}
```

### 丰富的订阅通知

此转换为订阅事件创建丰富的 Slack 消息和附件：

```javascript subscription_notifs.js icon="js" expandable theme={null}
function handler(webhook) {
  switch (webhook.eventType) {
    case "subscription.active":
      webhook.payload = {
        attachments: [{
          color: "good",
          title: "🎉 Subscription Activated",
          fields: [
            {
              title: "Customer",
              value: webhook.payload.data.customer.email,
              short: true
            },
            {
              title: "Product ID",
              value: webhook.payload.data.product_id,
              short: true
            },
            {
              title: "Amount",
              value: `$${(webhook.payload.data.recurring_pre_tax_amount / 100).toFixed(2)}/${webhook.payload.data.payment_frequency_interval}`,
              short: true
            },
            {
              title: "Next Billing",
              value: new Date(webhook.payload.data.next_billing_date).toLocaleDateString(),
              short: true
            }
          ],
          footer: "Dodo Payments",
          ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
        }]
      };
      break;
      
    case "subscription.cancelled":
      webhook.payload = {
        attachments: [{
          color: "warning",
          title: "⚠️ Subscription Cancelled",
          fields: [
            {
              title: "Customer",
              value: webhook.payload.data.customer.email,
              short: true
            },
            {
              title: "Product ID",
              value: webhook.payload.data.product_id,
              short: true
            },
            {
              title: "Cancellation Date",
              value: new Date(webhook.payload.data.cancelled_at).toLocaleDateString(),
              short: true
            },
            {
              title: "Cancel at Next Billing",
              value: webhook.payload.data.cancel_at_next_billing_date ? "Yes" : "No",
              short: true
            }
          ],
          footer: "Dodo Payments",
          ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
        }]
      };
      break;
      
    case "subscription.renewed":
      webhook.payload = {
        attachments: [{
          color: "good",
          title: "🔄 Subscription Renewed",
          fields: [
            {
              title: "Customer",
              value: webhook.payload.data.customer.email,
              short: true
            },
            {
              title: "Product ID",
              value: webhook.payload.data.product_id,
              short: true
            },
            {
              title: "Amount",
              value: `$${(webhook.payload.data.recurring_pre_tax_amount / 100).toFixed(2)}`,
              short: true
            },
            {
              title: "Next Billing",
              value: new Date(webhook.payload.data.next_billing_date).toLocaleDateString(),
              short: true
            }
          ],
          footer: "Dodo Payments",
          ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
        }]
      };
      break;
  }

  return webhook;
}
```

### 争议管理通知

此转换以适当的颜色和紧急程度处理争议事件：

```javascript dispute_notifs.js icon="js" expandable theme={null}
function handler(webhook) {
  switch (webhook.eventType) {
    case "dispute.opened":
      webhook.payload = {
        attachments: [{
          color: "danger",
          title: "🚨 New Dispute Opened",
          fields: [
            {
              title: "Payment ID",
              value: webhook.payload.data.payment_id,
              short: true
            },
            {
              title: "Amount",
              value: `$${(webhook.payload.data.amount / 100).toFixed(2)}`,
              short: true
            },
            {
              title: "Status",
              value: webhook.payload.data.dispute_status,
              short: true
            },
            {
              title: "Stage",
              value: webhook.payload.data.dispute_stage,
              short: true
            },
            {
              title: "Remarks",
              value: webhook.payload.data.remarks || "No remarks",
              short: false
            }
          ],
          footer: "Dodo Payments - Action Required",
          ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
        }]
      };
      break;
      
    case "dispute.won":
      webhook.payload = {
        attachments: [{
          color: "good",
          title: "✅ Dispute Won",
          fields: [
            {
              title: "Payment ID",
              value: webhook.payload.data.payment_id,
              short: true
            },
            {
              title: "Amount",
              value: `$${(webhook.payload.data.amount / 100).toFixed(2)}`,
              short: true
            },
            {
              title: "Status",
              value: webhook.payload.data.dispute_status,
              short: true
            },
            {
              title: "Resolution",
              value: "Dispute resolved in your favor",
              short: false
            }
          ],
          footer: "Dodo Payments",
          ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
        }]
      };
      break;
      
    case "dispute.lost":
      webhook.payload = {
        attachments: [{
          color: "danger",
          title: "❌ Dispute Lost",
          fields: [
            {
              title: "Payment ID",
              value: webhook.payload.data.payment_id,
              short: true
            },
            {
              title: "Amount",
              value: `$${(webhook.payload.data.amount / 100).toFixed(2)}`,
              short: true
            },
            {
              title: "Status",
              value: webhook.payload.data.dispute_status,
              short: true
            },
            {
              title: "Impact",
              value: "Funds will be debited from your account",
              short: false
            }
          ],
          footer: "Dodo Payments - Review Required",
          ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
        }]
      };
      break;
  }

  return webhook;
}
```

### 综合所有事件处理程序

此转换以一致的格式处理所有事件类型：

```javascript all_events_notifs.js icon="js" expandable  theme={null}
function handler(webhook) {
  const event = webhook.payload.data;
  const timestamp = new Date(webhook.payload.timestamp).toLocaleString();
  
  let color, emoji, title, fields = [];
  
  switch (webhook.eventType) {
    case "payment.succeeded":
      color = "good";
      emoji = "✅";
      title = "Payment Successful";
      fields = [
        { title: "Amount", value: `$${(event.total_amount / 100).toFixed(2)}`, short: true },
        { title: "Customer", value: event.customer.email, short: true },
        { title: "Payment ID", value: event.payment_id, short: true },
        { title: "Method", value: event.payment_method || "Unknown", short: true }
      ];
      break;
      
    case "payment.failed":
      color = "danger";
      emoji = "❌";
      title = "Payment Failed";
      fields = [
        { title: "Amount", value: `$${(event.total_amount / 100).toFixed(2)}`, short: true },
        { title: "Customer", value: event.customer.email, short: true },
        { title: "Reason", value: event.error_message || "Unknown", short: false }
      ];
      break;
      
    case "subscription.active":
      color = "good";
      emoji = "🎉";
      title = "Subscription Activated";
      fields = [
        { title: "Customer", value: event.customer.email, short: true },
        { title: "Product ID", value: event.product_id, short: true },
        { title: "Amount", value: `$${(event.recurring_pre_tax_amount / 100).toFixed(2)}/${event.payment_frequency_interval}`, short: true },
        { title: "Next Billing", value: new Date(event.next_billing_date).toLocaleDateString(), short: true }
      ];
      break;
      
    case "subscription.cancelled":
      color = "warning";
      emoji = "⚠️";
      title = "Subscription Cancelled";
      fields = [
        { title: "Customer", value: event.customer.email, short: true },
        { title: "Product ID", value: event.product_id, short: true },
        { title: "Cancellation Date", value: new Date(event.cancelled_at).toLocaleDateString(), short: true },
        { title: "Cancel at Next Billing", value: event.cancel_at_next_billing_date ? "Yes" : "No", short: true }
      ];
      break;
      
    case "refund.succeeded":
      color = "good";
      emoji = "💰";
      title = "Refund Processed";
      fields = [
        { title: "Amount", value: `$${(event.amount / 100).toFixed(2)}`, short: true },
        { title: "Refund ID", value: event.refund_id, short: true },
        { title: "Payment ID", value: event.payment_id, short: true },
        { title: "Reason", value: event.reason || "Not specified", short: true }
      ];
      break;
      
    case "dispute.opened":
      color = "danger";
      emoji = "🚨";
      title = "New Dispute Opened";
      fields = [
        { title: "Payment ID", value: event.payment_id, short: true },
        { title: "Amount", value: `$${(event.amount / 100).toFixed(2)}`, short: true },
        { title: "Status", value: event.dispute_status, short: true },
        { title: "Stage", value: event.dispute_stage, short: true },
        { title: "Remarks", value: event.remarks || "No remarks", short: false }
      ];
      break;
      
    case "license_key.created":
      color = "good";
      emoji = "🔑";
      title = "License Key Created";
      fields = [
        { title: "License ID", value: event.id, short: true },
        { title: "Product ID", value: event.product_id, short: true },
        { title: "License Key", value: event.key.substring(0, 8) + "...", short: true },
        { title: "Expires", value: event.expires_at ? new Date(event.expires_at).toLocaleDateString() : "Never", short: true }
      ];
      break;
      
    default:
      // Handle any other events with a generic format
      color = "warning";
      emoji = "ℹ️";
      title = webhook.eventType.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
      fields = [
        { title: "Event Type", value: webhook.eventType, short: true },
        { title: "Timestamp", value: timestamp, short: true }
      ];
  }
  
  webhook.payload = {
    attachments: [{
      color: color,
      title: `${emoji} ${title}`,
      fields: fields,
      footer: "Dodo Payments",
      ts: Math.floor(new Date(webhook.payload.timestamp).getTime() / 1000)
    }]
  };

  return webhook;
}
```

## 最佳实践

为了使 Slack 通知更有效：

* 使用附带颜色、字段和格式的丰富消息附件，以提高清晰度和可操作性。
* 始终包含关键数据，例如金额、客户邮箱和 ID，以便快速识别。
* 根据事件类型选择颜色：绿色 (`good`) 代表成功，红色 (`danger`) 代表争议或失败，黄色 (`warning`) 代表取消，蓝色 (`#36a64f`) 代表信息类事件。
* 添加时间戳，以帮助跟踪每个事件发生的时间。

<Warning>
  **处理敏感数据**：请注意不要在 Slack 消息中包含完整许可证密钥或个人数据等敏感信息。考虑截断或屏蔽敏感值。
</Warning>

## 故障排除

<AccordionGroup>
  <Accordion title="Notifications not appearing in Slack">
    * 验证 Slack Webhook URL 是否正确且处于激活状态
    * 检查转换代码是否是有效的 JavaScript
    * 确保所选事件类型正在触发
    * 验证您的 Slack 应用是否具有必要权限
  </Accordion>

  <Accordion title="Transformation errors">
    * 检查 Webhook 管理门户中的转换错误日志
    * 验证 Webhook 负载结构是否与您的转换代码匹配
    * 使用示例数据测试转换代码
    * 确保 Webhook 负载中包含所有必需字段
  </Accordion>

  <Accordion title="Missing event types">
    * 确认您希望接收的事件在 Dodo Payments Webhook 配置中已启用
    * 检查 Slack 连接器配置中是否选择了事件类型
    * 验证您的终端节点配置是否正确以接收事件
  </Accordion>
</AccordionGroup>
