메인 콘텐츠로 건너뛰기

소개

Dodo Payments 슬랙 통합을 통해 슬랙 작업 공간에서 직접 결제에 대한 실시간 알림을 받을 수 있습니다. 이 통합을 통해 결제 상태를 업데이트하고, 거래를 추적하며, 결제를 보다 효율적으로 관리할 수 있습니다.
이 통합은 웹훅 관리 포털을 사용하여 Dodo Payments 웹훅 이벤트를 슬랙 호환 메시지로 자동 변환합니다. 추가 코딩이 필요하지 않으며, 커넥터를 구성하고 알림을 받기 시작하면 됩니다.

시작하기

1

웹훅 섹션 열기

Dodo Payments 대시보드에서 웹훅 섹션으로 이동합니다. + 엔드포인트 추가 버튼을 클릭한 후, 웹훅 드롭다운을 열어 다른 통합을 확인합니다.
Dodo Payments 대시보드에서 엔드포인트 추가 버튼과 통합 드롭다운을 보여주는 이미지
2

슬랙 통합 선택

슬랙 통합을 선택하고 슬랙 작업 공간 연결을 클릭합니다.
슬랙 통합 카드와 연결 버튼
3

슬랙 권한 부여

선택한 채널에 메시지를 게시할 수 있도록 Incoming Webhooks 슬랙 앱에 필요한 권한을 부여합니다.
Incoming Webhooks 앱의 슬랙 OAuth 권한 화면
4

변환 코드 사용자 정의

사용 사례에 맞게 슬랙 알림을 사용자 정의하기 위해 변환 코드를 추가하거나 수정합니다. 미리 만들어진 템플릿을 사용하거나 자신의 로직을 작성할 수 있습니다.
슬랙 통합을 위한 변환 코드 편집기
5

테스트 및 생성

사용자 정의 또는 미리 만들어진 이벤트 페이로드로 변환 코드를 테스트합니다. 만족스러우면 생성을 클릭하여 통합을 활성화합니다.
변환 테스트 및 생성 버튼
6

통합 완료!

🎉 슬랙 통합을 성공적으로 생성했습니다! 이제 Dodo Payments 이벤트가 선택한 슬랙 채널로 실시간으로 전달됩니다.

변환 코드 예제

기본 결제 알림

이 변환은 결제 이벤트에 대한 간단한 텍스트 메시지를 보냅니다:
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;
}

풍부한 구독 알림

이 변환은 구독 이벤트에 대한 첨부 파일이 있는 풍부한 슬랙 메시지를 생성합니다:
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;
}

모범 사례

슬랙 알림을 효과적으로 만들기 위해:
  • 명확성과 실행 가능성을 위해 색상, 필드 및 형식이 있는 풍부한 메시지 첨부 파일을 사용하세요.
  • 빠른 식별을 위해 금액, 고객 이메일 및 ID와 같은 주요 데이터를 항상 포함하세요.
  • 이벤트 유형에 맞는 색상을 선택하세요: 성공을 위한 초록색 (good), 분쟁 또는 실패를 위한 빨간색 (danger), 취소를 위한 노란색 (warning), 정보 이벤트를 위한 파란색 (#36a64f).
  • 각 이벤트가 발생한 시간을 추적할 수 있도록 타임스탬프를 추가하세요.
민감한 데이터 처리: 슬랙 메시지에 전체 라이센스 키나 개인 데이터와 같은 민감한 정보를 포함하지 않도록 주의하세요. 민감한 값을 잘라내거나 마스킹하는 것을 고려하세요.

문제 해결

  • 슬랙 웹훅 URL이 올바르고 활성 상태인지 확인하세요.
  • 변환 코드가 유효한 JavaScript인지 확인하세요.
  • 선택한 이벤트 유형이 트리거되고 있는지 확인하세요.
  • 슬랙 앱에 필요한 권한이 있는지 확인하세요.
  • 변환 오류 로그를 위해 웹훅 관리 포털을 확인하세요.
  • 웹훅 페이로드 구조가 변환 코드와 일치하는지 확인하세요.
  • 샘플 데이터로 변환 코드를 테스트하세요.
  • 웹훅 페이로드에 모든 필수 필드가 포함되어 있는지 확인하세요.
  • 수신하려는 이벤트가 Dodo Payments 웹훅 구성에서 활성화되어 있는지 확인하세요.
  • 슬랙 커넥터 구성에서 이벤트 유형이 선택되어 있는지 확인하세요.
  • 이벤트를 수신하도록 엔드포인트가 올바르게 구성되어 있는지 확인하세요.