メインコンテンツへスキップ

はじめに

Dodo PaymentsのSlack統合を使用すると、Slackワークスペース内で直接支払いに関するリアルタイム通知を受け取ることができます。この統合により、支払いの状況を把握し、取引を追跡し、支払いをより効率的に管理できます。
この統合は、Dodo PaymentsのWebhook管理ポータルを使用して、Dodo PaymentsのWebhookイベントをSlack互換のメッセージに自動的に変換します。追加のコーディングは不要で、コネクタを設定するだけで通知を受け取ることができます。

始め方

1

Webhookセクションを開く

Dodo PaymentsダッシュボードのWebhookセクションに移動します。+ エンドポイントを追加ボタンをクリックし、Webhookドロップダウンを開いて他の統合を表示します。
Dodo PaymentsダッシュボードのAdd Endpointボタンと統合ドロップダウンを表示
2

Slack統合を選択

Slack統合を選択し、Slackワークスペースを接続をクリックします。
Slack統合カードと接続ボタン
3

Slackの権限を付与

Incoming Webhooks Slackアプリに必要な権限を付与し、選択したチャンネルにメッセージを投稿できるようにします。
Incoming WebhooksアプリのSlack OAuth権限画面
4

変換コードをカスタマイズ

変換コードを追加または編集して、使用ケースに合わせてSlack通知をカスタマイズします。事前に作成されたテンプレートを使用するか、自分のロジックを書くことができます。
Slack統合の変換コードエディタ
5

テストと作成

カスタムまたは事前に作成されたイベントペイロードで変換コードをテストします。満足したら、作成をクリックして統合を有効にします。
テスト変換と作成ボタン
6

統合完了!

🎉 Slack統合を正常に作成しました!あなたのDodo Paymentsイベントは、選択したSlackチャンネルにリアルタイムで配信されます。

変換コードの例

基本的な支払い通知

この変換は、支払いイベントのためのシンプルなテキストメッセージを送信します:
payment_notifs.js
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メッセージを作成します:
subscription_notifs.js
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;
}

紛争管理通知

この変換は、適切な色と緊急度で紛争イベントを処理します:
dispute_notifs.js
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;
}

包括的な全イベントハンドラー

この変換は、一貫したフォーマットで全てのイベントタイプを処理します:
all_events_notifs.js
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)。
  • 各イベントが発生した時刻を追跡するために、タイムスタンプを追加してください。
機密データの取り扱い:Slackメッセージに完全なライセンスキーや個人データなどの機密情報を含めないように注意してください。機密値を切り詰めたりマスクしたりすることを検討してください。

トラブルシューティング

  • SlackのWebhook URLが正しくアクティブであることを確認してください
  • 変換コードが有効なJavaScriptであることを確認してください
  • 選択したイベントタイプがトリガーされていることを確認してください
  • Slackアプリに必要な権限があることを確認してください
  • 変換エラーログのためにWebhook管理ポータルを確認してください
  • Webhookペイロードの構造が変換コードと一致していることを確認してください
  • サンプルデータで変換コードをテストしてください
  • Webhookペイロードにすべての必須フィールドが含まれていることを確認してください
  • 受信したいイベントがDodo PaymentsのWebhook設定で有効になっていることを確認してください
  • Slackコネクタ設定でイベントタイプが選択されていることを確認してください
  • エンドポイントがイベントを受信するように正しく設定されていることを確認してください