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

2
슬랙 통합 선택
슬랙 통합을 선택하고 슬랙 작업 공간 연결을 클릭합니다.

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

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 웹훅 구성에서 활성화되어 있는지 확인하세요.
- 슬랙 커넥터 구성에서 이벤트 유형이 선택되어 있는지 확인하세요.
- 이벤트를 수신하도록 엔드포인트가 올바르게 구성되어 있는지 확인하세요.