소개
Dodo Payments 슬랙 통합을 통해 슬랙 작업 공간에서 직접 결제에 대한 실시간 알림을 받을 수 있습니다. 이 통합을 통해 결제 상태를 업데이트하고, 거래를 추적하며, 결제를 보다 효율적으로 관리할 수 있습니다.이 통합은 웹훅 관리 포털을 사용하여 Dodo Payments 웹훅 이벤트를 자동으로 Slack 호환 메시지로 변환합니다. 추가 코딩은 필요하지 않습니다. 커넥터를 구성하고 알림을 받기만 하면 됩니다.
시작하기
Open the Webhook Section
Dodo Payments 대시보드에서 Webhook 섹션으로 이동하세요. + Add Endpoint 버튼을 클릭한 다음 통합을 표시하려면 웹훅 드롭다운을 열어주세요.

Customize Transformation Code
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;
}
풍부한 구독 알림
이 변환은 구독 이벤트에 대한 첨부 파일이 있는 풍부한 슬랙 메시지를 생성합니다: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 메시지에 포함하지 않도록 주의하세요. 민감한 값은 잘라내거나 마스킹하는 것을 고려하세요.
문제 해결
Notifications not appearing in Slack
Notifications not appearing in Slack
- Slack 웹훅 URL이 정확하고 활성 상태인지 확인하세요.
- 변환 코드가 유효한 JavaScript인지 확인하세요.
- 선택된 이벤트 유형이 트리거되고 있는지 확인하세요.
- Slack 앱에 필요한 권한이 있는지 확인하세요.
Transformation errors
Transformation errors
- 변환 오류 로그가 있는지 웹훅 관리 포털을 확인하세요.
- 웹훅 페이로드 구조가 변환 코드와 일치하는지 확인하세요.
- 샘플 데이터를 사용하여 변환 코드를 테스트하세요.
- 웹훅 페이로드에 모든 필수 필드가 있는지 확인하세요.
Missing event types
Missing event types
- 수신하려는 이벤트가 Dodo Payments 웹훅 구성에서 활성화되어 있는지 확인하세요.
- Slack 커넥터 구성에서 이벤트 유형이 선택되어 있는지 확인하세요.
- 엔드포인트가 이벤트 수신을 위해 올바르게 구성되어 있는지 확인하세요.


