Skip to main content
Let Sentra write your integration code for you.
Use our AI assistant in VS Code, Cursor, or Windsurf to generate SDK/API code, webhook handlers, and more, just by describing what you want.
Try Sentra: AI-Powered Integration →
이 튜토리얼에서는 고객이 이메일 크레딧 풀에 대가를 미리 지불하는 트랜잭션 이메일 플랫폼 MailKit을 구축합니다. 이 계획은 매월 이메일 사용량을 허용하며, 고객이 크레딧이 부족할 경우 다음 주기를 기다리지 않고 충전 팩을 구매할 수 있습니다. 매 전송 시 크레딧 하나가 자동으로 차감됩니다.
이 튜토리얼에서는 이메일 공급자로 Resend를 사용합니다. 무료 등급(월 3,000 이메일)은 유료 계정 없이 전체 흐름을 구축하고 테스트하기에 충분합니다. 이 패턴은 모든 공급자와 함께 작동하며, resend.emails.send를 SendGrid, Postmark, SES 또는 자체 SMTP 릴레이로 교체하십시오.
이 튜토리얼이 끝나면 다음과 같은 내용을 알 수 있습니다:
  • 대시보드에서 맞춤형 크레딧 할당량(이메일) 생성
  • 구독 계획 및 일회성 충전 제품에 크레딧 첨부
  • Resend를 통해 실제 이메일을 전송하고 원장 항목을 통해 전송당 크레딧 1개 차감
  • 프런트엔드에서 실시간 크레딧 잔액 쿼리
  • Dodo 웹훅을 정확하게 검증하고 고객에게 0이 되기 전에 경고하는 credit.balance_low 처리

우리가 만들고 있는 것

MailKit의 가격 모델은 다음과 같습니다: 단위는 이메일 하나 = 크레딧 하나입니다. 고객은 토큰, 배치, 가중 단위에 대해 생각할 필요가 없습니다. 그들은 단지 “이번 달에 4,231개의 이메일이 남아 있습니다”라고 표시됩니다.
시작하기 전에 다음을 확인하십시오:
  • Dodo Payments 계정 (테스트 모드도 괜찮음)
  • 무료 Resend 계정과 API 키
  • Node.js 18+ 및 기본 TypeScript에 대한 이해

Step 1: Create Your Email Credit Entitlement

크레딧 할당량은 플랫폼이 판매하는 단위를 정의합니다: 이 경우 이메일 전송 하나.
Credits listing page

The Credits tab under Products lists all your credit entitlements.

1

Open the Credits section

  1. Dodo Payments 대시보드에 로그인합니다.
  2. 왼쪽 사이드바에서 Products를 클릭합니다.
  3. Credits 탭을 선택합니다.
  4. Create Credit을 클릭합니다.
2

Configure the credit unit

크레딧 세부 정보를 입력합니다:Credit Name: Email CreditsCredit Type: Select Custom UnitUnit Name: emailPrecision: 0 (이메일은 항상 전체 단위입니다; 반 이메일을 보낼 수 없습니다)Credit Expiry: 30 days (각 주기의 할당량이 재설정됩니다)
정밀도는 생성 후 변경할 수 없습니다. 이메일, 메시지 또는 세션과 같은 이산 단위의 경우 0가 적합합니다.
3

Leave the other defaults as-is

이 요리책에서는 롤오버 또는 초과 사용을 활성화하지 않습니다; 목표는 가능한 가장 간단한 CBB 흐름입니다. 나중에 크레딧 첨부에서 이를 다시 탐색할 수 있습니다.
4

Save and copy the credit ID

Create Credit을 클릭합니다. 크레딧을 열고 ID를 복사합니다. 백엔드 잔액 쿼리에 필요합니다. 이는 cent_xxxxxxxxxxxx처럼 보입니다.
당신의 Email Credits 할당이 준비되었습니다. 다음: 고객에게 크레딧을 제공하는 제품입니다.

Step 2: Create the Plan and Top-Up Pack

두 가지 제품을 만듭니다: 반복되는 구독 계획과 일회성 결제 충전. 계획은 각 주기에 5,000개의 이메일을 제공합니다; 충전은 요구에 따라 5,000개를 추가합니다. 둘 다 동일한 Email Credits 할당량을 연결합니다.
이 요리책에서는 사용량 기반 계량기가 아닌 직접 원장 항목으로 크레딧을 차감합니다. 원장 항목은 즉각적이며(잔액은 밀리초 단위로 업데이트됨), 추가 설정이 필요 없으며 한 사용자 액션이 정확히 하나의 크레딧인 경우 적합합니다. 인제스트된 사용 이벤트에서 자동 차감을 선호하는 경우(“토큰” 또는 “처리된 MB”와 같은 가중치 단위에 유용함), 계량기 기반 패턴은 크레딧 기반 과금 → 크레딧으로 사용량 과금을 참조하세요.

MailKit Plan ($19/month, 5,000 emails)

1

Create the subscription

  1. Products → Create Product로 이동
  2. 제품 세부 정보를 입력합니다:
Product Name: MailKit PlanDescription: 5,000 transactional emails per month.
  1. 제품 유형으로 Subscription을 선택
  2. 반복 가격 설정:
Recurring Price: 19.00Billing Cycle: MonthlyCurrency: USD
2

Attach the email credit entitlement

Entitlements → Credits → Attach로 스크롤하고 구성합니다:Credit Entitlement: Email CreditsCredits issued per billing cycle: 5000Low Balance Threshold: 20 (percent; 20% 이하로 떨어질 때 credit.balance_low 발생, 즉 1,000개의 이메일)Import Default Credit Settings: enabled (Step 1의 30일 만료 사용)제품에 추가를 클릭한 다음 저장합니다. 제품 ID(pdt_xxxxxxxxxxxx)를 복사합니다.
계획: $19/month → 각 주기에 5,000개의 이메일이 새로고침됩니다.

충전 팩 ($9 one-time, 5,000 emails)

1

Create a one-time product

  1. Products → Create Product로 이동
  2. 제품 세부 정보를 입력합니다:
Product Name: Email Top-Up PackDescription: Add 5,000 emails to your MailKit balance instantly.
  1. 제품 유형으로 Single Payment을 선택
  2. 가격 설정:
Price: 9.00Currency: USD
2

Attach the credit grant

Entitlements → Credits → Attach 에서:
  • 크레딧 할당량: Email Credits
  • 발행된 크레딧: 5000
일회성 제품은 자체 만료가 있는 크레딧을 제공합니다(구매 후 30일, Step 1에 따라). 충전은 구독 크레딧에 추가됩니다; 이를 대체하지 않습니다.
저장하고 제품 ID를 복사합니다.
충전 팩: $9 → +5,000개의 이메일, 즉시 사용 가능.

Step 3: Set Up the Backend

이제 체크아웃, 전송, 잔액 쿼리, 웹훅을 처리하는 Express 서버를 구축합니다.
1

Initialize the project

package.json에 개발 스크립트를 추가합니다:
tsx은 빌드 단계나 tsconfig.json 없이 TypeScript를 직접 실행합니다, 이는 튜토리얼에 적합합니다. 프로덕션에서는 tsconfig.jsonbuild 스크립트를 추가하십시오.
2

Configure environment variables

.env를 생성합니다:
.env
DODO_WEBHOOK_KEY는 엔드포인트를 생성한 후 4단계에서 채웁니다. Resend API 키는 resend.com/api-keys에서 가져옵니다.
.env.gitignore에 즉시 추가하십시오. API 키를 커밋하지 마십시오.
3

Build the server

프로젝트 루트에 server.ts를 생성합니다:
웹훅 본문은 원시여야 합니다. express.json()는 본문을 파싱하고 다시 직렬화하여 서명 검증을 중단시킵니다. /webhooks/dodoexpress.raw() 전에 정의합니다.
백엔드 준비 완료: 구독, 충전, 잔액, 전송, 및 웹훅 핸들러가 모두 연결되었습니다.
4

Add a demo UI

public/index.html를 생성합니다:

Step 4: Wire Up the Webhook Endpoint

credit.balance_low 이벤트는 고객이 다 쓰기 전에 알림을 제공할 수 있게 해줍니다. 없으면, 그들이 문제를 처음 인지하는 것은 이메일이 전송되지 않을 때입니다.
1

Expose your local server

웹훅은 공용 URL이 필요합니다. 개발 중에는 ngrok (또는 다른 터널)을 사용하십시오:
HTTPS 포워딩 URL을 복사합니다(예: https://1234abcd.ngrok-free.app).
2

Register the endpoint in Dodo

  1. Developers → Webhooks → Add Endpoint로 이동
  2. URL: https://1234abcd.ngrok-free.app/webhooks/dodo
  3. Events: credit.added, credit.balance_low, credit.rolled_over 구독
  4. 저장한 다음, 서명 키.envDODO_WEBHOOK_KEY로 복사합니다.
  5. 서버를 다시 시작합니다.

Step 5: Test the Full Flow

1

Start the server

MailKit running on http://localhost:3000를 볼 수 있어야 합니다. 브라우저에서 엽니다.
2

Subscribe a test customer

  1. 섹션 1에 테스트 이메일과 이름을 입력, Get checkout link 클릭
  2. 링크를 열고 테스트 카드로 체크아웃 완료
  3. 결제가 완료된 후, 대시보드의 Customers 아래에서 customer_id를 찾습니다.
고객은 이제 잔액에 5,000개의 이메일을 가지고 있어야 합니다. Customers → [Customer] → Credits를 확인하십시오.
3

Send a real email

  1. SECTION 3에 customer_id를 붙여 넣습니다.
  2. todelivered@resend.dev로 설정하여 두십시오 (Resend의 모든 것을 허용하는 샌드박스 인박스)
  3. Send를 클릭합니다.
Resend 메시지 ID가 반환됩니다. 2단계에서 잔액을 새로 고치면 수량이 즉시 4,999로 감소합니다. 각 원장 차감은 기록되는 즉시 실시간 잔액에 반영됩니다.
4

Trigger the low-balance webhook

임계값은 20%입니다 (5,000 이메일 할당량 중 1,000). 4,000개의 실제 이메일을 보내지 않고 이를 트리거하려면 대시보드에서 잔액을 수동으로 차감하십시오:
  1. Customers → [Customer] → Credits → Email Credits로 이동합니다.
  2. 잔액 조정 클릭 후 4000로 차감
  3. 데모를 통해 이메일 하나 더 전송
서버는 몇 초 안에 다음을 로그해야 합니다:
서버가 웹훅을 수신하고 검증했습니다. 프로덕션에서는 이것이 고객에게 이메일을 보내거나 앱 내부 배너를 표시하는 곳입니다.
5

Buy a top-up pack

  1. 섹션 4에 customer_id를 붙여 넣습니다.
  2. Buy 5,000 emails 클릭 후 테스트 체크아웃 완료
  3. 잔액을 새로 고치면 5,000씩 증가합니다.
credit.added 이벤트가 grant_source: one_time와 함께 발생합니다. 충전이 구독 크레딧 위에 쌓입니다; 두 풀은 FIFO(최소 비사용 만료 보조금 우선)로 소비됩니다.
6

Test the hard stop

잔액을 수동으로 0으로 차감한 다음 이메일 하나를 더 보내보십시오. 다음을 얻을 것입니다:
그 402는 애플리케이션 수준의 강제입니다. Dodo 잔액 API는 진실의 근원입니다; 클라이언트에 캐시하지 마십시오.

문제 해결

서명은 원시 HTTP 본문을 통해 계산됩니다. express.json()는 페이로드를 파싱하고 다시 직렬화하여 HMAC를 중단시킵니다. /webhooks/dodoapp.use(express.json()) 줄 위에 등록되었는지, DODO_WEBHOOK_KEY가 엔드포인트 세부 페이지에 표시된 서명 키와 일치하는지 확인하십시오.
세 가지를 이 순서로 확인하십시오:
  1. 고객이 체크아웃을 완료했는지 (크레딧은 성공적인 결제 후 발급되며 세션 생성 시 발급되지 않음)
  2. CREDIT_ENTITLEMENT_ID.env에서 제품에 연결된 크레딧과 일치하는지 (ID 불일치는 잘못된 크레딧에 조용히 기록됨)
  3. 포함하고 있는 customer_id가 Dodo에서 온 것인지 (대시보드의 customers 테이블), 아니면 자체 데이터베이스에 있는 것인지 확인합니다.
샌드박스 발신자 onboarding@resend.dev은 Resend 계정의 이메일 또는 delivered@resend.dev로만 배달됩니다. 다른 사람에게 보내기 위해 도메인 확인하고 그 위에 from 주소를 사용하십시오.

당신이 만든 것

One reusable credit unit

Email Credits는 한 번 정의하고 구독 계획과 충전 팩 모두에 첨부됩니다.

Subscription with prepaid allowance

$19/month는 주기당 5,000개의 이메일을 제공합니다. 고객은 그들이 무엇을 지불하는지 알고, 당신은 최악의 경우 비용을 알고 있습니다.

Top-up pack

5,000개의 이메일을 제공하는 일회성 제품입니다. 계획 변경 없이 구독 크레딧 위에 추가됩니다.

Instant ledger debits

각 전송 후 하나의 createLedgerEntry 호출. 계량기, 집계 지연 없음, Resend의 메시지 ID를 통한 재시도 시 멱등.

Credit-Based Billing Reference

롤오버, 초과 사용 모드, 원장 관리 및 전체 API 표면에 대한 전체 CBB 문서를 읽으십시오.
도움이 필요하신가요? Need help?
마지막 수정일 2026년 5월 13일