resend.emails.send。- 在您的仪表板中创建自定义信用权利(电子邮件)
- 将信用附加到订阅计划和一次性充值产品上
- 通过 Resend 发送真实电子邮件,并通过账本条目每发送一次扣减一个信用
- 从您的前端查询实时信用余额
- 正确验证 Dodo webhooks,并在客户接近零之前处理
credit.balance_low发出信号
我们正在构建的内容
以下是 MailKit 的定价模型:- 一个 Dodo Payments 账户(测试模式即可)
- 一个免费的 Resend 账户和 API 密钥
- Node.js 18+ 和基本的 TypeScript 知识
第 1 步:创建您的电子邮件信用权利
信用权利定义了您的平台出售的单位:在这种情况下为一次电子邮件发送。
The Credits tab under Products lists all your credit entitlements.
Open the Credits section
- 登录您的 Dodo Payments 仪表板
- 点击左侧边栏中的 产品
- 选择 信用 标签
- 点击 创建信用
Configure the credit unit
Email Credits信用类型: 选择 Custom Unit单位名称: email精度: 0(电子邮件始终为整单位;您无法发送半封邮件)信用过期: 30 days(每个周期的额度重置)Leave the other defaults as-is
Save and copy the credit ID
cent_xxxxxxxxxxxx。Email Credits 权利已准备好。接下来:授予客户信用的产品。第 2 步:创建计划和充值包
您将创建两个产品:一个定期的 订阅 计划和一个 一次性付款 充值。该计划授予每个周期 5,000 封电子邮件;充值可按需增加 5,000 封。两者都附加相同的Email Credits 权利。
MailKit 计划 ($19/月,5,000 封邮件)
Create the subscription
- 进入 产品 → 创建产品
- 填写产品详情:
MailKit Plan描述: 5,000 transactional emails per month.- 选择 订阅 作为产品类型
- 设置经常性价格:
19.00计费周期: Monthly货币: USDAttach the email credit entitlement
Email Credits每个计费周期发行的信用: 5000低余额阈值: 20(百分比;当余额低于周期额度的 20% 时触发 credit.balance_low,即 1,000 封邮件)导入默认信用设置: 启用(使用第 1 步的 30 天到期)点击 添加到产品,然后 保存 产品。复制产品 ID (pdt_xxxxxxxxxxxx)。充值包 ($9 一次性,5,000 封邮件)
Create a one-time product
- 进入 产品 → 创建产品
- 填写产品详情:
Email Top-Up Pack描述: Add 5,000 emails to your MailKit balance instantly.- 选择 一次性付款 作为产品类型
- 设置价格:
9.00货币: USDAttach the credit grant
- 信用权利:
Email Credits - 发放的信用:
5000
第 3 步:设置后端
现在构建处理结账、发送、余额查询和 webhooks 的 Express 服务器。Initialize the project
package.json:Configure environment variables
Build the server
server.ts:Add a demo UI
public/index.html:第 4 步:连接 Webhook 端点
credit.balance_low 事件是让您在客户用完之前提示他们的重要事件。没有它,他们第一次注意到问题是在发送邮件失败时。
Expose your local server
Register the endpoint in Dodo
- 进入 开发者 → Webhooks → 添加端点
- URL:
https://1234abcd.ngrok-free.app/webhooks/dodo - 事件: 订阅
credit.added,credit.balance_low和credit.rolled_over - 保存,然后将 签名密钥 复制到您的
.env作为DODO_WEBHOOK_KEY - 重启服务器
第 5 步:测试完整流程
Start the server
MailKit running on http://localhost:3000。在浏览器中打开它。Subscribe a test customer
- 在第 1 节中输入测试电子邮件和名称,点击 获取结账链接
- 打开链接,用测试卡完成结账
- 付款后,在仪表板下的 客户 中找到
customer_id
Send a real email
- 将
customer_id粘贴到第 3 节 - 保持
to设置为delivered@resend.dev(Resend 的沙盒邮箱,接受所有内容) - 点击 发送
Trigger the low-balance webhook
- 进入 客户 → [客户] → 信用 → 邮件信用
- 点击 调整余额 并扣减
4000 - 再通过演示发送一封邮件
Buy a top-up pack
- 将
customer_id粘贴到第 4 节 - 点击 购买 5,000 封邮件,完成测试结账
- 刷新余额,它会跳增 5,000
grant_source: one_time 触发 credit.added 事件。充值叠加在订阅信用之上;两个池按 FIFO 消耗(最早的未过期供给首先使用)。Test the hard stop
故障排除
Webhook signature verification fails (401)
Webhook signature verification fails (401)
express.json() 解析并重新序列化有效负载,这会打破 HMAC。确保 /webhooks/dodo 使用 express.raw({ type: 'application/json' }) 在 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 在重试时具备幂等性。