> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# v1.97.6 (May 7, 2026)

> 权限功能上线，新增五个履行集成（Discord、GitHub、Telegram、Framer、Notion），客户门户中的订阅取消原因，可配置的印度电子授权最低金额，自适应货币费用包含设置，适用于 macOS/Windows/Linux 的 Dodo Payments 桌面应用，稳定币支付（USDC/USDP/USDG），导入现有许可证密钥，结账会话中要求电话号码，以及 bug 修复

## 新功能

### 1. **权限**

Dodo Payments 现已推出统一的 **权限**——单一层对每个履行集成实现自动交付。单一产品可以在每次成功购买或活跃订阅时交付多个权限。

<Frame>
  <img src="https://mintcdn.com/dodopayments/do-W-dMDGVB_xzr_/images/entitlements/list.png?fit=max&auto=format&n=do-W-dMDGVB_xzr_&q=85&s=12a326205f64d1e71485bce46114d296" alt="权限仪表板，左侧为权限列表，右侧为授予活动" style={{ maxHeight: '500px', width: 'auto' }} width="2000" height="1195" data-path="images/entitlements/list.png" />
</Frame>

**五个新的平台集成**

此前，Dodo Payments 会在购买时自动交付**许可证密钥**和**数字文件**。权限将这一范围扩展到五个额外的平台，因此付款客户可以在付款成功时立即获得社区、代码或内容的访问权限，无需手动履行：

| 集成           | 它交付什么                                   | 撤销行为           |
| ------------ | --------------------------------------- | -------------- |
| **Discord**  | 在客户完成 OAuth 后在您的 Discord 服务器中分配选定角色     | 取消/退款时移除角色     |
| **GitHub**   | 以您选择的权限级别将客户添加为私人存储库的协作成员               | 取消/退款时移除协作者    |
| **Telegram** | 通过您的 Telegram 机器人为私人聊天或频道发出一次性加入请求邀请链接  | 取消/退款时从聊天中移除客户 |
| **Framer**   | 解锁受访问代码限制的 Framer 模板重混链接                | 取消/退款时访问代码失效   |
| **Notion**   | 在客户通过 OAuth 授权后，将 Notion 模板页面复制到他们的工作空间 | 取消/退款时交付页面被归档  |

这加入了现有的**许可证密钥**（具有激活限制和到期的唯一密钥）和**数字文件**（电子书、模板、媒体的预签名下载 URL）集成，现都通过相同的授予生命周期管理。

**您开箱即用的功能**

| 功能                | 描述                                                                                                                                                                   |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **可重用模板**         | 一次定义权限（激活限制、文件包、Discord 角色、存储库权限等），并将其附加到任何产品                                                                                                                        |
| **自动授予**          | 在 `payment.succeeded` 和 `subscription.active` 上发出，跨续期和重新激活幂等                                                                                                         |
| **生命周期感知撤销**      | 在 `subscription.cancelled`、`subscription.on_hold`、`subscription.expired`、`refund.succeeded`、`subscription.plan_changed` 或手动 API/仪表板撤销时撤销——带有已填充的 `revocation_reason` |
| **OAuth + 平台直接流** | Discord、GitHub 和 Notion 订阅者同意的 OAuth；Telegram、Framer 和 Digital Files 的直接平台调用                                                                                         |
| **漂移检测**          | 检测到 Discord 角色、GitHub 协作成员或 Notion 页面与平台级别同步中断时撤销，带有 `revocation_reason: platform_external`                                                                          |
| **静态加密**          | 所有平台令牌（OAuth、bot、app 安装）都使用 AES-256-GCM 存储                                                                                                                           |

**Webhooks**

每个授予都会触发四个新的生命周期事件：

| 事件                            | 触发时机                                      |
| ----------------------------- | ----------------------------------------- |
| `entitlement_grant.created`   | 为客户创建新授予时                                 |
| `entitlement_grant.delivered` | 向客户提供访问时                                  |
| `entitlement_grant.failed`    | 无法完成交付时；检查 `error_code` 和 `error_message` |
| `entitlement_grant.revoked`   | 撤回访问时；检查 `revocation_reason`              |

<Tip>
  对于新的集成，监听 `entitlement_grant.delivered` 而不是 `payment.succeeded`。支付成功不意味着交付已完成，尤其对于基于 OAuth 的集成。
</Tip>

了解更多：[权限](/features/entitlements/introduction) | [权限授予 Webhooks](/developer-resources/webhooks/intents/entitlement-grant)

### 2. **客户门户中的订阅取消原因**

当客户从客户门户取消订阅时，他们现在需要在确认之前分享**取消原因**。捕获的原因将存储在订阅中为 `cancellation_feedback`，显示在 API 和 webhook 负载中，并在仪表板中可用，以便您可以一目了然地发现流失模式。

<Frame>
  <img src="https://mintcdn.com/dodopayments/RlXcM7JO-E_w40Np/images/customer-portal/cancellation-reasons.png?fit=max&auto=format&n=RlXcM7JO-E_w40Np&q=85&s=979394da2a9aa3907cbf9f4e225f9a4b" alt="客户门户取消模态框，带有'您为何取消？'下拉菜单，显示“太贵”、“缺乏功能”和“其他”等原因" style={{ maxHeight: '500px', width: 'auto' }} width="2880" height="1564" data-path="images/customer-portal/cancellation-reasons.png" />
</Frame>

**原因选项**

| 值                  | 面向客户的标签 |
| ------------------ | ------- |
| `too_expensive`    | 太贵      |
| `missing_features` | 缺乏功能    |
| `switched_service` | 转至另一服务  |
| `unused`           | 使用不够频繁  |
| `customer_service` | 客户服务差   |
| `low_quality`      | 质量差     |
| `too_complex`      | 过于复杂    |
| `other`            | 其他      |

**出现的位置**

* **订阅对象**：新的 `cancellation_feedback` 字段（上述值之一）和 `cancellation_comment`（可选自由文本），在客户取消时填充
* **`subscription.cancelled` webhook**：负载中包含这两个字段
* **API**：在程序化调度或执行取消时，把 `cancellation_feedback` 和 `cancellation_comment` 传递给 `PATCH /subscriptions/{id}`

```typescript theme={null}
// Reading the captured feedback
const subscription = await client.subscriptions.retrieve('sub_123');
console.log(subscription.cancellation_feedback); // e.g., "too_expensive"
console.log(subscription.cancellation_comment);  // e.g., "Switching to a competitor"
```

<Tip>
  将 `cancellation_feedback` 与 [Subscription Dunning](/features/recovery/subscription-dunning) 结合使用，以定制您的赢回电子邮件——例如，向 `too_expensive` 取消者发送折扣代码，并向 `missing_features` 取消者发送"缺少什么？"调查。
</Tip>

了解更多：[客户门户](/features/customer-portal#cancelling-a-subscription) | [订阅 Webhooks](/developer-resources/webhooks/intents/subscription)

### 3. **印度电子授权的可配置授权最低金额**

您现在可以配置印度卡定期订阅的 **授权底线**。此前，所有低于 ₹15,000 的印度卡订阅均采用固定的 ₹15,000 按需授权。现在，您可以在商户级别覆盖这一底线——每个结账会话或订阅也可根据需要设置。

与客户银行注册的授权金额为 `max(mandate_min_amount_inr_paise, billing_amount)`，因此该值在计费低于底线时，将作为客户可见的 **授权上限**。

```typescript theme={null}
// Per-subscription override
const subscription = await client.subscriptions.create({
  product_id: 'prod_inr_monthly',
  customer: { email: 'customer@example.in' },
  billing: { country: 'IN' /* ... */ },
  mandate_min_amount_inr_paise: 2_000_000 // ₹20,000 ceiling for this subscription
});

// Or via a checkout session
const session = await client.checkoutSessions.create({
  product_cart: [{ product_id: 'prod_inr_monthly', quantity: 1 }],
  mandate_min_amount_inr_paise: 2_000_000,
  return_url: 'https://yoursite.com/return'
});
```

**解决优先级**

1. 每次请求覆盖（结账会话、支付或订阅上的 `mandate_min_amount_inr_paise`）
2. 商户级设置在业务设置中
3. 系统默认值为 **₹15,000**（1,500,000 paise）

| 字段                             | 类型                | 范围     | 适用于                         |
| ------------------------------ | ----------------- | ------ | --------------------------- |
| `mandate_min_amount_inr_paise` | `integer`（INR 派塞） | `>= 1` | 非 Airwallex 连接器上的印度卡 INR 订阅 |

<Info>
  此设置仅影响为 INR 订阅的印度发行的卡（Visa，Mastercard，RuPay）注册的电子授权。UPI 订阅遵循其自己的自动支付流程，不受影响。
</Info>

了解更多：[印度支付方式](/features/payment-methods/india#mandate-types) | [订阅与 RBI 授权](/features/subscription#subscriptions-with-rbi-compliant-mandates)

### 4. **自适应货币费用包含业务设置**

自适应货币是一项允许您以客户当地货币收费的功能。默认情况下，**2-4% 的自适应货币费用**由客户承担，并在您的显示价格上附加。通过新的**费用包含**设置，您可以翻转这一点：让客户看到的显示价格不变，而您自行承担费用。

**在哪里配置**

转到 **设置 → 业务**，确保启用 **自适应定价**，然后在自适应货币部分中切换 **费用包含**。

**每次请求覆盖**

您还可以使用 `adaptive_currency_fees_inclusive` 布尔值，为单个结账、支付和按需订阅覆盖商户默认值：

```typescript theme={null}
const session = await client.checkoutSessions.create({
  product_cart: [{ product_id: 'prod_abc', quantity: 1 }],
  adaptive_currency_fees_inclusive: true, // override business default
  return_url: 'https://yoursite.com/return'
});
```

| 模式     | 客户看到           | 商家结算         |
| ------ | -------------- | ------------ |
| 独占（默认） | 本地价格 + 2-4% 费用 | 全基价          |
| 包含     | 本地价格（不变）       | 基价减去 2-4% 费用 |

<Info>
  INR → INR 交易始终作为包含处理，无论业务设置或每次请求覆盖如何。
</Info>

了解更多：[自适应货币](/features/adaptive-currency)

### 5. **Dodo Payments 桌面应用**

官方 **Dodo Payments 桌面应用**现已适用于 **macOS、Windows 和 Linux**。以快速的原生应用运行您的支付仪表板——无需浏览器标签。

| 平台                     | 下载                                                 |
| ---------------------- | -------------------------------------------------- |
| macOS (Apple Silicon)  | `Dodo.Payments_<version>_aarch64.dmg`              |
| macOS (Intel)          | `Dodo.Payments_<version>_x64.dmg`                  |
| Windows                | `Dodo.Payments_<version>_x64-setup.exe` (或 `.msi`) |
| Linux (Debian/Ubuntu)  | `Dodo.Payments_<version>_amd64.deb`                |
| Linux (Fedora/RHEL)    | `Dodo.Payments-<version>-1.x86_64.rpm`             |
| Linux (AppImage, 自动更新) | `Dodo.Payments_<version>_amd64.AppImage`           |

**包含什么**

* **小型原生二进制文件**——用 Tauri 构建在系统原生网页视图上，总共约 5 MB（无捆绑的 Chromium）
* **签名和公证**——macOS 构建通过 Apple Developer ID 签名并公证，因此没有 Gatekeeper 警告
* **自动更新**——每 4 小时检查一次并自动从 GitHub Releases 提供签名更新（适用于 macOS、Windows 和 Linux AppImage）
* **系统托盘 + 菜单栏**——在 macOS 上隐藏到托盘中，提供完整的文件/编辑/视图/帮助菜单及键盘快捷键（`⌘⇧H` 转到仪表板，`⌘L` 复制当前 URL，`⌘⌥I` 开发工具）
* **深度链接支持**——魔术链接认证链接直接在应用中打开
* **多窗口**——并排打开多个仪表板

<Tip>
  从 [桌面应用发布页面](https://github.com/dodopayments/dodo-desktop/releases/latest) 获取您平台的最新安装程序。该仓库是完全开源的。
</Tip>

### 6. **稳定币支付（USDC、USDP、USDG）**

全球接受 **稳定币支付**，以 USD 结算。客户可以从其喜爱的稳定币钱包中使用任何选择的网络进行支付；您无需承受加密货币波动风险、无需退款或客户方的银行基础设施，即可获得法定 USD。

**支持的货币和网络**

| 稳定币      | 网络                           |
| -------- | ---------------------------- |
| **USDC** | Ethereum、Solana、Polygon、Base |
| **USDP** | Ethereum、Solana              |
| **USDG** | Ethereum                     |

**覆盖范围**

| 细节    | 值           |
| ----- | ----------- |
| 计费货币  | USD         |
| 支持的国家 | 全球（印度除外）    |
| 订阅    | 不支持（仅一次性支付） |
| 最低金额  | \$0.50      |
| 结算    | USD         |

**配置**

在创建结账会话时传入 `crypto_currency` 到 `allowed_payment_method_types`：

```javascript theme={null}
const session = await client.checkoutSessions.create({
  product_cart: [{ product_id: 'prod_123', quantity: 1 }],
  allowed_payment_method_types: ['crypto_currency', 'credit', 'debit'],
  return_url: 'https://example.com/success'
});
```

客户会看到一个钱包地址和二维码，稳定币金额根据实时汇率计算；一旦区块链确认交易，您的 `payment.succeeded` webhook 会触发，客户会被重定向到您的成功页面。

<Info>
  稳定币支付设计为不可逆——无退款。我们建议总是提供 `credit` 和 `debit` 作为没有稳定币钱包的客户的备选方法。
</Info>

了解更多：[稳定币支付](/features/payment-methods/stablecoins)

### 7. **导入现有许可证密钥**

您现在可以使用 [Create License Key API](/api-reference/licenses/create-license-key) 将许可证密钥从其他系统导入 Dodo Payments。这使得从任何外部许可证密钥提供商的无中断迁移成为可能，因此您的现有客户可以继续在 Dodo Payments 上激活、验证和停用其密钥，而无需重新发行。

```typescript theme={null}
const licenseKey = await client.licenseKeys.create({
  customer_id: 'cus_abc123',
  product_id: 'prod_456',
  key: 'YOUR-EXISTING-LICENSE-KEY',
  activations_limit: 5,
  expires_at: '2026-12-31T23:59:59Z',
});
```

导入的密钥标记为 `source: "import"`（与支付时自动生成的密钥相比为 `source: "auto"`），因此在查询 `GET /license_keys` 时，您可以区别迁移的库存与自然发行的密钥。导入密钥上的 `payment_id` 为 `null`，因为它们与 Dodo Payments 交易无关。

<Warning>
  通过 API 创建或更新的许可证密钥不会触发给客户的电子邮件通知。如果您需要通知客户已导入的密钥，请在应用程序中单独处理。
</Warning>

<Tip>
  从 Polar.sh 或 Lemon Squeezy 迁移？[`dodo-migrate` CLI](/migrate-to-dodo) 可自动在单个命令中批量导入产品、客户、折扣和许可证密钥。
</Tip>

了解更多：[许可证密钥](/features/license-keys#import-existing-license-keys-via-api) | [Create License Key API](/api-reference/licenses/create-license-key)

### 8. **结账会话的 `require_phone_number`**

通过在创建结账会话时设置 `feature_flags.require_phone_number: true`，强制客户在结账时提供电话号码。电话号码会在结账表单中成为必填字段，如果客户留空，则表单验证将显示“需要电话号码”。

```typescript theme={null}
const session = await client.checkoutSessions.create({
  product_cart: [{ product_id: 'prod_abc', quantity: 1 }],
  feature_flags: {
    allow_phone_number_collection: true,
    require_phone_number: true
  },
  return_url: 'https://yoursite.com/return'
});
```

| 标志                              | 默认值     | 行为           |
| ------------------------------- | ------- | ------------ |
| `allow_phone_number_collection` | `true`  | 在结账时显示电话号码字段 |
| `require_phone_number`          | `false` | 使电话号码字段成为必填项 |

<Warning>
  `require_phone_number: true` 需要 `allow_phone_number_collection: true`。API 拒绝那些 `require_phone_number` 为 true 而电话收集被禁用的会话。
</Warning>

<Tip>
  适用于 B2B SaaS、受监管行业或任何需要验证联系渠道以支持、欺诈审核或合规的流程。
</Tip>

了解更多：[结账功能](/features/checkout) | [创建结账会话 API](/api-reference/checkout-sessions/create)

## Bug 修复和改进

* 整个平台的轻微 bug 修复和稳定性提升
