关于 localized-pricing
面向使用 DodoPayments 的开发者,介绍固定本地价格、结账时汇率转换和购买力平价定价。内容涵盖价格配置、地区与货币解析、方案变更及税务影响。
主要功能
- 01按国家或货币设置固定价格
- 02结账时按实时汇率转换
- 03配置国家级购买力平价比例
- 04管理本地价格的增删改查
- 05说明价格回退、方案变更与税务
适用场景
- 01为不同国家设置可预测的价格
- 02为结账提供客户本地货币
- 03为不同市场启用购买力平价折扣
- 04处理订阅换计划时的本地价格
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dodopayments/ skills --skill localized-pricing安装后在 Claude Code 中输入/localized-pricing确认已加载。
详细介绍
本地化定价、自适应货币与 PPP
本技能介绍了在多个国家和货币中定价的三种不同机制。开发者经常会混淆它们。本技能将为它们厘清区别,展示各自的实现方式,并说明它们与套餐变更、按比例计费和税费之间的交互。
何时使用本技能
- 你需要为特定国家或货币设置固定价格。
- 你想在结账时提供实时外汇换算。
- 你正在考虑为新兴市场提供购买力平价折扣。
- 你不确定应该使用本地化定价还是自适应货币。
- 你需要处理账单国家和货币的解析、回退行为,或使用本地化价格时的套餐变更。
核心概念
三种机制,三种用途
| 机制 | 功能 | 由谁控制 | 价格何时变化 |
|---|---|---|---|
| 本地化定价 | 开发者按国家/货币设置固定价格 | 你(通过 API) | 仅在你更新价格时 |
| 自适应货币 | 在结账时按实时汇率换算 | Dodo(实时汇率) | 每笔交易都会根据当前汇率变化 |
| 购买力平价(PPP) | 按国家收取基础价格的一定百分比 | 你(在仪表板中为整个业务设置国家百分比,按产品选择启用) | 仅在你更改百分比时 |
主要区别: 本地化价格是静态的。自适应货币是动态的。PPP 是按国家设定的百分比,会先应用于基础价格,再由自适应货币进行换算。
本地化定价
为特定国家和货币设置固定价格。创建后,本地化价格不会变化,除非你主动更新。它不会跟踪汇率。
如果你希望掌控价格并为不同地区提供可预测的定价,请使用本地化定价。
自适应货币
在结账时启用实时外汇换算。客户会看到本地货币,Dodo 会使用当前汇率换算基础价格。
如果你希望客户能够使用任意货币结账,而无需逐一手动设置价格,请使用自适应货币。
PPP(购买力平价)
PPP 是原生功能(文档)。Dodo 会为每个国家保存一个适用于整个业务的百分比(30 到 100,仅能在仪表板中管理),客户根据其账单国家支付标价的相应比例。每个产品通过 price.purchasing_power_parity: true 选择启用(默认值为 false)。
PPP 需要自适应货币:请先在 Settings → Business 中启用,否则产品的启用操作会被拒绝。若存在匹配的本地化价格,则始终优先使用该价格;折扣码则会应用于 PPP 折后价格。
await client.products.create({
name: 'Starter Plan',
tax_category: 'saas',
price: {
type: 'one_time_price',
currency: 'USD',
price: 2000, // $20.00; a customer in India at 30% pays $6.00
discount: 0,
purchasing_power_parity: true,
},
});
产品定价模式
每个产品都有一个 pricing_mode,用于决定如何解析价格:
by_country:Dodo 根据客户的账单国家查找本地化价格。by_currency:Dodo 根据客户的账单货币查找本地化价格。
通过 client.products.update(...) 为每个产品设置一次模式。同一产品不能混用不同模式。
import DodoPayments from 'dodopayments';
const client = new DodoPayments({
bearerToken: process.env.DODO_PAYMENTS_API_KEY,
environment: 'test_mode',
});
// Set pricing mode to by_country
await client.products.update('pdt_premium_plan', {
pricing_mode: 'by_country',
});
// Or by_currency
await client.products.update('pdt_premium_plan', {
pricing_mode: 'by_currency',
});
本地化价格的 CRUD 操作
本地化价格嵌套在产品下。所有金额均以货币的最小单位表示(USD 的分为美分,INR 的卢比为派士)。
创建本地化价格
// ₹999.00 for customers in India
const localizedPrice = await client.products.localizedPrices.create('pdt_premium_plan', {
currency: 'INR',
country_code: 'IN',
amount: 99900, // 999.00 in paise
});
列出产品的本地化价格
const prices = await client.products.localizedPrices.list('pdt_premium_plan');
console.log(prices);
获取特定本地化价格
const price = await client.products.localizedPrices.retrieve('lp_abc123', {
product_id: 'pdt_premium_plan',
});
console.log(price.amount, price.currency, price.country_code);
更新本地化价格
await client.products.localizedPrices.update('lp_abc123', {
product_id: 'pdt_premium_plan',
amount: 109900, // Update to ₹1099.00
});
归档本地化价格
await client.products.localizedPrices.archive('lp_abc123', {
product_id: 'pdt_premium_plan',
});
归档的价格会软删除。它们不再适用于新的结账,但仍会保留在历史记录中。
结账时的自适应货币
在控制面板的 Settings → Business 中启用自适应货币(文档)。然后,Dodo 会按实时汇率转换产品的基础价格。在结账会话中传入 billing_currency 和 billing_address.country,只会固定收费货币;如果省略这两个参数,自适应货币会根据客户的 IP 地址选择货币和国家/地区。
// Server route (e.g. POST /api/checkout): create the session and return its URL
export async function POST() {
const session = await client.checkoutSessions.create({
product_cart: [
{
product_id: 'pdt_premium_plan',
quantity: 1,
},
],
billing_currency: 'AED', // Pin the charge currency (requires Adaptive Currency)
billing_address: { country: 'AE' },
return_url: 'https://example.com/return',
});
return Response.json({ checkout_url: session.checkout_url });
}
切勿在浏览器代码中调用 SDK 或暴露 API 密钥。浏览器只会接收 URL 并重定向:
// Browser
const res = await fetch('/api/checkout', { method: 'POST' });
const { checkout_url } = (await res.json()) as { checkout_url: string };
window.location.href = checkout_url;
**费用:**默认情况下,自适应货币会在显示价格的基础上收取阶梯式转换费用(低于 $500 为 4%,$500 至 $1,500 为 3%,高于 $1,500 为 2%)。在 Settings → Business 中启用 Fees Inclusive,即可从结算款中扣除这笔费用。如果本地化价格匹配,交易始终按费用含入价格处理。
**魅力定价:**启用自适应货币后,魅力定价可以将转换后的价格取整为 49.99 等整洁的尾数。此功能需要启用自适应货币。
创建订阅和更改方案时也可以使用自适应货币。请查看 API 参考,确认你所用特定端点是否支持 billing_currency。
账单国家/地区和货币的解析
Dodo 按以下顺序解析客户的账单国家/地区和货币:
- 传入结账请求的
billing_address.country或billing_currency。 - 客户保存的地址(如果客户已存在于 Dodo 中)。
- IP 地理位置(如果可用)。
- 回退到产品的基础价格和货币。
如果解析出的国家/地区或货币没有对应的本地化价格,Dodo 会回退到基础价格。此回退会自动进行,不会报错。
与方案更改和按比例计费的交互
客户更改方案时,新方案的本地化价格会沿用原订阅的账单国家/地区或货币。
按比例计费会使用新方案的本地化价格(如果客户所在国家/地区或使用的货币有对应价格)。
await client.subscriptions.changePlan('sub_abc123', {
product_id: 'pdt_enterprise_plan',
quantity: 1,
proration_billing_mode: 'prorated_immediately',
});
按比例计费的金额会使用新方案的本地化价格。
本地化定价的税务行为
税费根据本地化价格计算,而不是基础价格。例如,如果你为印度设置了 ₹999.00 的本地化价格,税费就按该金额计算。
含税定价的处理方式相同:本地化价格会被视为含税总价。
常见错误
错误 1:认为本地化价格会随汇率自动更新
本地化价格是固定的。如果你今天设置了 INR 999.00,该价格会保持不变,直到你手动更新。它不会跟踪 USD/INR 汇率。
如果你需要实时外汇转换,请改用自适应货币。
错误 2:混淆 by_country 和 by_currency
by_country:Dodo 将客户的账单国家/地区与本地化价格的country_code匹配。by_currency:Dodo 将客户的账单货币与本地化价格的currency匹配。
在印度使用 USD 卡的客户会匹配 by_currency: USD,但不会匹配 by_country: IN(除非你也为印度设置了 USD 价格)。
错误 3:忘记设置回退价格
如果你设置了 pricing_mode: by_country,但没有为客户所在国家/地区创建本地化价格,Dodo 会回退到基础价格:如果客户使用的货币已是你的基础货币,就直接收费;如果启用了自适应货币,则会通过自适应货币进行转换(文档)。如果未启用自适应货币,就会按基础货币收取基础价格,这通常不是你想要的结果。
启用此模式前,请务必为目标市场创建本地化价格。
错误 4:混用本地化定价和自适应货币
你可以在同一款产品上同时使用这两者,但它们的用途不同。本地化定价用于固定的地区专属价格,自适应货币用于实时汇率换算。
如果你为印度设置了本地化价格,同时启用了自适应货币,那么印度客户将优先看到本地化价格。
错误 5:为购买力平价引入第三方工具
购买力平价是原生功能:为产品启用 price.purchasing_power_parity: true,并在控制面板中设置各国百分比(必须启用自适应货币)。ParityDeals 等第三方工具仅在你想要使用其网站横幅时作为替代方案;其优惠码会作为普通的 discount_codes 在结账时传递。
错误 6:未在生产环境中处理缺失的本地化价格
务必测试回退行为。如果客户所在的国家或使用的货币没有本地化价格,他们会看到基础价格。请判断这是否可以接受,或者是否需要阻止不支持地区的客户结账。