resend.emails.send를 SendGrid, Postmark, SES 또는 자체 SMTP 릴레이로 교체하십시오.- 대시보드에서 맞춤형 크레딧 할당량(이메일) 생성
- 구독 계획 및 일회성 충전 제품에 크레딧 첨부
- Resend를 통해 실제 이메일을 전송하고 원장 항목을 통해 전송당 크레딧 1개 차감
- 프런트엔드에서 실시간 크레딧 잔액 쿼리
- Dodo 웹훅을 정확하게 검증하고 고객에게 0이 되기 전에 경고하는
credit.balance_low처리
우리가 만들고 있는 것
MailKit의 가격 모델은 다음과 같습니다:- Dodo Payments 계정 (테스트 모드도 괜찮음)
- 무료 Resend 계정과 API 키
- Node.js 18+ 및 기본 TypeScript에 대한 이해
Step 1: Create Your Email Credit Entitlement
크레딧 할당량은 플랫폼이 판매하는 단위를 정의합니다: 이 경우 이메일 전송 하나.
The Credits tab under Products lists all your credit entitlements.
Open the Credits section
- Dodo Payments 대시보드에 로그인합니다.
- 왼쪽 사이드바에서 Products를 클릭합니다.
- Credits 탭을 선택합니다.
- Create Credit을 클릭합니다.
Configure the credit unit
Email CreditsCredit Type: Select Custom UnitUnit Name: emailPrecision: 0 (이메일은 항상 전체 단위입니다; 반 이메일을 보낼 수 없습니다)Credit Expiry: 30 days (각 주기의 할당량이 재설정됩니다)Leave the other defaults as-is
Save and copy the credit ID
cent_xxxxxxxxxxxx처럼 보입니다.Email Credits 할당이 준비되었습니다. 다음: 고객에게 크레딧을 제공하는 제품입니다.Step 2: Create the Plan and Top-Up Pack
두 가지 제품을 만듭니다: 반복되는 구독 계획과 일회성 결제 충전. 계획은 각 주기에 5,000개의 이메일을 제공합니다; 충전은 요구에 따라 5,000개를 추가합니다. 둘 다 동일한Email Credits 할당량을 연결합니다.
MailKit Plan ($19/month, 5,000 emails)
Create the subscription
- Products → Create Product로 이동
- 제품 세부 정보를 입력합니다:
MailKit PlanDescription: 5,000 transactional emails per month.- 제품 유형으로 Subscription을 선택
- 반복 가격 설정:
19.00Billing Cycle: MonthlyCurrency: USDAttach the email 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)를 복사합니다.충전 팩 ($9 one-time, 5,000 emails)
Create a one-time product
- Products → Create Product로 이동
- 제품 세부 정보를 입력합니다:
Email Top-Up PackDescription: Add 5,000 emails to your MailKit balance instantly.- 제품 유형으로 Single Payment을 선택
- 가격 설정:
9.00Currency: USDAttach the credit grant
- 크레딧 할당량:
Email Credits - 발행된 크레딧:
5000
Step 3: Set Up the Backend
이제 체크아웃, 전송, 잔액 쿼리, 웹훅을 처리하는 Express 서버를 구축합니다.Initialize the project
package.json에 개발 스크립트를 추가합니다:Configure environment variables
.env를 생성합니다:DODO_WEBHOOK_KEY는 엔드포인트를 생성한 후 4단계에서 채웁니다. Resend API 키는 resend.com/api-keys에서 가져옵니다.Build the server
server.ts를 생성합니다:Add a demo UI
public/index.html를 생성합니다:Step 4: Wire Up the Webhook Endpoint
credit.balance_low 이벤트는 고객이 다 쓰기 전에 알림을 제공할 수 있게 해줍니다. 없으면, 그들이 문제를 처음 인지하는 것은 이메일이 전송되지 않을 때입니다.
Expose your local server
https://1234abcd.ngrok-free.app).Register the endpoint in Dodo
- Developers → Webhooks → Add Endpoint로 이동
- URL:
https://1234abcd.ngrok-free.app/webhooks/dodo - Events:
credit.added,credit.balance_low,credit.rolled_over구독 - 저장한 다음, 서명 키를
.env에DODO_WEBHOOK_KEY로 복사합니다. - 서버를 다시 시작합니다.
Step 5: Test the Full Flow
Start the server
MailKit running on http://localhost:3000를 볼 수 있어야 합니다. 브라우저에서 엽니다.Subscribe a test customer
- 섹션 1에 테스트 이메일과 이름을 입력, Get checkout link 클릭
- 링크를 열고 테스트 카드로 체크아웃 완료
- 결제가 완료된 후, 대시보드의 Customers 아래에서
customer_id를 찾습니다.
Send a real email
- SECTION 3에
customer_id를 붙여 넣습니다. to를delivered@resend.dev로 설정하여 두십시오 (Resend의 모든 것을 허용하는 샌드박스 인박스)- Send를 클릭합니다.
Trigger the low-balance webhook
- Customers → [Customer] → Credits → Email Credits로 이동합니다.
- 잔액 조정 클릭 후
4000로 차감 - 데모를 통해 이메일 하나 더 전송
Buy a top-up pack
- 섹션 4에
customer_id를 붙여 넣습니다. - Buy 5,000 emails 클릭 후 테스트 체크아웃 완료
- 잔액을 새로 고치면 5,000씩 증가합니다.
credit.added 이벤트가 grant_source: one_time와 함께 발생합니다. 충전이 구독 크레딧 위에 쌓입니다; 두 풀은 FIFO(최소 비사용 만료 보조금 우선)로 소비됩니다.Test the hard stop
문제 해결
Webhook signature verification fails (401)
Webhook signature verification fails (401)
express.json()는 페이로드를 파싱하고 다시 직렬화하여 HMAC를 중단시킵니다. /webhooks/dodo가 app.use(express.json()) 줄 위에 등록되었는지, DODO_WEBHOOK_KEY가 엔드포인트 세부 페이지에 표시된 서명 키와 일치하는지 확인하십시오.Balance is 0, customer not found, or credits don't deduct
Balance is 0, customer not found, or credits don't deduct
- 고객이 체크아웃을 완료했는지 (크레딧은 성공적인 결제 후 발급되며 세션 생성 시 발급되지 않음)
CREDIT_ENTITLEMENT_ID가.env에서 제품에 연결된 크레딧과 일치하는지 (ID 불일치는 잘못된 크레딧에 조용히 기록됨)- 포함하고 있는
customer_id가 Dodo에서 온 것인지 (대시보드의customers테이블), 아니면 자체 데이터베이스에 있는 것인지 확인합니다.
Resend rejects the recipient
Resend rejects the recipient
onboarding@resend.dev은 Resend 계정의 이메일 또는 delivered@resend.dev로만 배달됩니다. 다른 사람에게 보내기 위해 도메인 확인하고 그 위에 from 주소를 사용하십시오.당신이 만든 것
One reusable credit unit
Email Credits는 한 번 정의하고 구독 계획과 충전 팩 모두에 첨부됩니다.Subscription with prepaid allowance
Top-up pack
Instant ledger debits
createLedgerEntry 호출. 계량기, 집계 지연 없음, Resend의 메시지 ID를 통한 재시도 시 멱등.