关于 gplay-ppp-pricing
gplay-ppp-pricing 是用于 Google Play 商品的按购买力平价制定区域价格的技能,面向管理应用内商品和订阅定价的开发者。它涵盖旧版与新版商品 API,并强调获取现有区域配置后合并更新,避免移除地区数据。
主要功能
- 01按区域购买力系数计算价格
- 02支持应用内商品与一次性商品
- 03支持订阅价格调整
- 04合并保留现有区域配置
- 05说明区域版本及更新掩码要求
适用场景
- 01为不同国家设置本地化商品价格
- 02调整现有订阅的区域定价
- 03创建带区域价格的一次性商品
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ tamtom/ gplay-cli-skills --skill gplay-ppp-pricing安装后在 Claude Code 中输入/gplay-ppp-pricing确认已加载。
详细介绍
PPP 定价(按地区定价)
使用此技能,根据购买力平价或自定义定价策略,为不同国家设置不同价格。
前提条件
- 确保已设置凭据(
gplay auth login --service-account或GPLAY_SERVICE_ACCOUNT环境变量)。 - 使用
GPLAY_PACKAGE,或显式传入--package。 - 确定基础地区(通常为 US)和基础价格。
重要:必需的标志
更新会修改定价的订阅或一次性商品时,必须提供:
--regions-version:Google Play API 更新地区定价时必需。请使用最新版本。如果不知道当前版本,请发送任意值(例如"2022/02")——API 错误会告知最新版本(例如latest value is ExternalRegionLaunchVersionId{versionId=2025/03})。然后使用正确版本重试。--update-mask "basePlans":更新订阅时必需。若未提供,API 将返回:"update_mask must contain at least one path."- 对于一次性商品,请使用
--update-mask "purchaseOptions"。
重要:保留所有现有地区(先获取再合并)
Google Play API 会拒绝删除现有地区配置的更新。 如果某个订阅已配置 173 个地区,而你只发送 30 个 PPP 地区,API 将返回:"Regional configs were removed from the base plan: BM, BO, CI..."
始终遵循先获取再合并的模式:
- 获取当前商品,以取得所有现有地区配置
- 仅将 PPP 目标地区替换为计算出的价格
- 发送完整的合并列表(所有原有地区 + PPP 覆盖项)
此规则也适用于:
otherRegionsConfig(订阅)——如果之前已在某个基本方案中设置,更新 JSON 中必须包含此项。newRegionsConfig(一次性商品购买选项)——如果之前已设置(包含usdPrice、eurPrice和availability),则必须包含此项。省略会导致:"Cannot remove currency for new regions once it has been added: EUR."
重要:货币代码应以 Google Play 为准,不要凭假设填写
不要对货币与地区的映射进行硬编码。 货币代码会因 --regions-version 的值而变化(例如,在采用欧元后,旧版本中的保加利亚 BG 使用 BGN,而新版本中使用 EUR)。
始终使用获取到的现有地区配置中的货币代码。 对于价格被覆盖的 PPP 目标地区,请使用下方乘数表中的货币。对于所有其他地区,请原样保留 Google Play 返回的现有货币。
PPP 乘数表
将这些乘数应用于基础 USD 价格。所有结果均四舍五入为以 .99 结尾(例如,$4.73 → $4.99,₹249.37 → ₹249.99)。
第 1 档 — 全价(1.0x–1.1x)
| 地区 | 代码 | 乘数 | 货币 |
|---|---|---|---|
| 美国 | US | 1.0x | USD |
| 英国 | GB | 1.0x | GBP |
| 德国 | DE | 1.0x | EUR |
| 澳大利亚 | AU | 1.0x | AUD |
| 瑞士 | CH | 1.1x | CHF |
| 加拿大 | CA | 1.0x | CAD |
| 荷兰 | NL | 1.0x | EUR |
| 瑞典 | SE | 1.0x | SEK |
| 挪威 | NO | 1.05x | NOK |
| 丹麦 | DK | 1.0x | DKK |
第 2 档 — 中等(0.6x–0.8x)
| 地区 | 代码 | 乘数 | 货币 |
|---|---|---|---|
| 法国 | FR | 0.8x | EUR |
| 西班牙 | ES | 0.7x | EUR |
| 意大利 | IT | 0.7x | EUR |
| 日本 | JP | 0.8x | JPY |
| 韩国 | KR | 0.7x | KRW |
| 波兰 | PL | 0.6x | PLN |
| 葡萄牙 | PT | 0.7x | EUR |
| 捷克共和国 | CZ | 0.6x | CZK |
| 希腊 | GR | 0.65x | EUR |
| 智利 | CL | 0.6x | CLP |
| 沙特阿拉伯 | SA | 0.8x | SAR |
| 阿联酋 | AE | 0.8x | AED |
第 3 档 — 低(0.3x–0.5x)
| 地区 | 代码 | 乘数 | 货币 |
|---|---|---|---|
| 印度 | IN | 0.3x | INR |
| 巴西 | BR | 0.5x | BRL |
| 墨西哥 | MX | 0.45x | MXN |
| 印度尼西亚 | ID | 0.3x | IDR |
| 土耳其 | TR | 0.35x | TRY |
| 越南 | VN | 0.3x | VND |
| 菲律宾 | PH | 0.35x | PHP |
| 埃及 | EG | 0.3x | EGP |
| 哥伦比亚 | CO | 0.4x | COP |
| 阿根廷 | AR | 0.3x | ARS |
| 尼日利亚 | NG | 0.3x | NGN |
| 巴基斯坦 | PK | 0.25x | PKR |
| 泰国 | TH | 0.4x | THB |
| 马来西亚 | MY | 0.45x | MYR |
| 南非 | ZA | 0.4x | ZAR |
| 乌克兰 | UA | 0.3x | UAH |
工作流:设置基于 PPP 的 IAP 定价(旧版 inappproducts API)
将此工作流用于通过 gplay iap 创建的旧版托管商品。此类商品使用 priceMicros/currency 格式。
1. 列出应用内商品
gplay iap list --package "PACKAGE"
2. 获取当前商品详情
gplay iap get --package "PACKAGE" --sku "SKU"
记下当前的 defaultPrice,将其作为基础价格,并保存所有现有的 prices 条目。
3. 构建经 PPP 调整的价格 JSON(先获取再合并)
**必须包含所有现有地区价格,而不仅仅是 PPP 目标地区。**先获取当前商品,然后覆盖 PPP 地区。
{
"sku": "premium_upgrade",
"defaultPrice": {
"priceMicros": "9990000",
"currency": "USD"
},
"prices": {
"US": { "priceMicros": "9990000", "currency": "USD" },
"IN": { "priceMicros": "2499900", "currency": "INR" },
"BR": { "priceMicros": "24990000", "currency": "BRL" },
"GB": { "priceMicros": "9990000", "currency": "GBP" },
"DE": { "priceMicros": "9990000", "currency": "EUR" }
}
}
4. 更新商品
gplay iap update \
--package "PACKAGE" \
--sku "SKU" \
--json @ppp-prices.json
5. 验证价格
gplay iap get --package "PACKAGE" --sku "SKU"
工作流:创建采用 PPP 定价的新一次性商品
从头开始创建全新的一次性商品并设置 PPP 定价时,使用此工作流。
1. 参考现有商品的地区配置结构
如果已有一次性商品(OTP),请获取该商品,将其用作地区配置格式的模板:
gplay onetimeproducts get --package "PACKAGE" --product-id "EXISTING_PRODUCT_ID"
记下 regionsVersion 和 regionalPricingAndAvailabilityConfigs 的结构。
2. 构建包含 PPP 定价的商品 JSON
构建完整的商品 JSON,其中包括商品详情、购买选项和所有地区定价配置。价格格式使用 units/nanos/currencyCode(参见下方的格式参考)。
{
"productId": "premium_lifetime_50off",
"listings": [
{ "languageCode": "en-US", "title": "Premium (50% off)", "description": "Lifetime access at 50% off" }
],
"purchaseOptions": [
{
"buyOption": { "legacyCompatible": true },
"newRegionsConfig": {
"availability": "AVAILABLE",
"usdPrice": { "currencyCode": "USD", "units": "14", "nanos": 990000000 },
"eurPrice": { "currencyCode": "EUR", "units": "13", "nanos": 990000000 }
},
"regionalPricingAndAvailabilityConfigs": [
{ "regionCode": "US", "availability": "AVAILABLE", "price": { "currencyCode": "USD", "units": "14", "nanos": 990000000 } },
{ "regionCode": "IN", "availability": "AVAILABLE", "price": { "currencyCode": "INR", "units": "373", "nanos": 990000000 } },
{ "regionCode": "BR", "availability": "AVAILABLE", "price": { "currencyCode": "BRL", "units": "37", "nanos": 990000000 } }
]
}
]
}
3. 创建商品
即使是创建,也必须使用 --regions-version——create 命令内部使用了带 allowMissing=true 的 PATCH:
gplay onetimeproducts create \
--package "PACKAGE" \
--product-id "premium_lifetime_50off" \
--json @new-otp.json \
--regions-version "2025/03"
商品创建后处于 DRAFT 状态。
4. 激活购买选项
新商品初始状态为 DRAFT。使用 purchase-options batch-update-states 激活:
gplay purchase-options batch-update-states \
--package "PACKAGE" \
--product-id "premium_lifetime_50off" \
--json '{"requests":[{"activatePurchaseOptionRequest":{"packageName":"PACKAGE","productId":"premium_lifetime_50off","purchaseOptionId":"default"}}]}'
5. 验证商品
gplay onetimeproducts get --package "PACKAGE" --product-id "premium_lifetime_50off"
确认状态为 ACTIVE,且所有地区的价格均正确。
工作流:更新现有一次性商品的 PPP 定价(新变现 API)
将此工作流用于通过 gplay onetimeproducts 创建的现有一次性商品。此类商品使用 units/nanos/currencyCode 格式,并包含带有 regionalPricingAndAvailabilityConfigs 的 purchaseOptions。
1. 列出一次性商品
gplay onetimeproducts list --package "PACKAGE"
2. 获取当前商品并保存所有地区配置
gplay onetimeproducts get --package "PACKAGE" --product-id "PRODUCT_ID"
保存完整 JSON。请注意:
purchaseOptions[].regionalPricingAndAvailabilityConfigs数组——需要包含所有条目purchaseOptions[].newRegionsConfig——如果之前已设置,则必须包含(其中包含usdPrice、eurPrice、availability)
3. 构建经 PPP 调整的 JSON(先获取再合并)
先使用现有 regionalPricingAndAvailabilityConfigs 的完整列表,然后覆盖 PPP 目标地区的计算价格。其他地区保持不变。
价格格式使用 units(作为字符串的整数部分)和 nanos(作为整数的小数部分,范围为 0–999999999):
- $5.99 →
"units": "5", "nanos": 990000000 - ₹149.99 →
"units": "149", "nanos": 990000000 - ¥719 →
"units": "719", "nanos": 0
{
"productId": "premium_lifetime",
"purchaseOptions": [
{
"purchaseOptionId": "EXISTING_OPTION_ID",
"buyOption": { "legacyCompatible": true },
"newRegionsConfig": {
"availability": "AVAILABLE",
"usdPrice": { "currencyCode": "USD", "units": "29", "nanos": 990000000 },
"eurPrice": { "currencyCode": "EUR", "units": "27", "nanos": 990000000 }
},
"regionalPricingAndAvailabilityConfigs": [
{ "regionCode": "US", "availability": "AVAILABLE", "price": { "currencyCode": "USD", "units": "29", "nanos": 990000000 } },
{ "regionCode": "IN", "availability": "AVAILABLE", "price": { "currencyCode": "INR", "units": "746", "nanos": 990000000 } },
{ "regionCode": "BR", "availability": "AVAILABLE", "price": { "currencyCode": "BRL", "units": "74", "nanos": 990000000 } },
{ "regionCode": "AE", "availability": "AVAILABLE", "price": { "currencyCode": "AED", "units": "109", "nanos": 990000000 } }
]
}
]
}
重要:
regionalPricingAndAvailabilityConfigs数组必须包含现有商品的所有地区。仅覆盖 PPP 目标地区的价格。- 如果现有商品已设置
newRegionsConfig,则必须包含该项。省略会导致错误:“添加货币后,无法为新地区移除该货币。”
4. 对商品执行 Patch
gplay onetimeproducts patch \
--package "PACKAGE" \
--product-id "PRODUCT_ID" \
--json @ppp-otp.json \
--regions-version "2025/03" \
--update-mask "purchaseOptions"
5. 验证价格
gplay onetimeproducts get --package "PACKAGE" --product-id "PRODUCT_ID"
工作流:设置基于 PPP 的订阅定价
1. 列出订阅
gplay subscriptions list --package "PACKAGE"
2. 获取当前订阅并保存所有地区配置
gplay subscriptions get --package "PACKAGE" --product-id "PRODUCT_ID"
保存完整的 JSON。对于每个基础方案,请记录:
otherRegionsConfig(USD 和 EUR 基准价格)——如果之前已设置,则必须包含regionalConfigs数组——必须包含所有现有地区autoRenewingBasePlanType或prepaidBasePlanType
3. 构建经 PPP 调整的订阅 JSON(先获取,再合并)
先保留每个基础方案中完整的现有 regionalConfigs,然后覆盖 PPP 目标地区。其他所有地区保持不变。
订阅价格使用 units/nanos/currencyCode 格式:
{
"productId": "premium_monthly",
"basePlans": [
{
"basePlanId": "monthly",
"otherRegionsConfig": {
"newSubscriberAvailability": true,
"usdPrice": { "currencyCode": "USD", "units": "5", "nanos": 990000000 },
"eurPrice": { "currencyCode": "EUR", "units": "5", "nanos": 70000000 }
},
"regionalConfigs": [
{ "regionCode": "US", "newSubscriberAvailability": true, "price": { "currencyCode": "USD", "units": "5", "nanos": 990000000 } },
{ "regionCode": "IN", "newSubscriberAvailability": true, "price": { "currencyCode": "INR", "units": "149", "nanos": 990000000 } },
{ "regionCode": "BR", "newSubscriberAvailability": true, "price": { "currencyCode": "BRL", "units": "14", "nanos": 990000000 } },
{ "regionCode": "AE", "newSubscriberAvailability": true, "price": { "currencyCode": "AED", "units": "22", "nanos": 990000000 } }
],
"autoRenewingBasePlanType": { "billingPeriodDuration": "P1M" }
}
]
}
重要: regionalConfigs 数组必须包含现有基础方案中的所有地区。如果订阅已有 173 个地区,则必须包含全部 173 个。仅覆盖 PPP 目标地区的价格。
4. 更新订阅
gplay subscriptions update \
--package "PACKAGE" \
--product-id "PRODUCT_ID" \
--json @ppp-subscription.json \
--regions-version "2025/03" \
--update-mask "basePlans"
必须提供全部三个标志:
--json:包含合并后地区配置的订阅 JSON--regions-version:使用最新版本(参见下文“查找地区版本”)--update-mask "basePlans":告知 API 要更新哪些字段
5. 验证价格
gplay subscriptions get --package "PACKAGE" --product-id "PRODUCT_ID"
检查所有基础方案中的 regionalConfigs,确认 PPP 目标地区的价格已更新,且其他所有地区均已保留。
查找地区版本
更新价格时必须使用 --regions-version 标志。查找最新版本的方法:
- 使用任意版本(例如
"2022/02")尝试更新 - 如果版本已过期,API 错误会告知最新版本:
Invalid regions version 2024/01, latest value is ExternalRegionLaunchVersionId{versionId=2025/03} - 使用错误消息中的版本重试
不同版本之间的货币代码可能会变化(例如,有国家加入欧元区)。始终使用获取到的现有数据中的货币代码,而不要使用硬编码映射。
工作流:迁移现有订阅者价格
更新有活跃订阅者的订阅的 PPP 价格时,新价格仅适用于新订阅者。要迁移现有订阅者:
1. 更新价格(以上步骤)
2. 将现有订阅者迁移到新价格
gplay baseplans migrate-prices \
--package "PACKAGE" \
--product-id "PRODUCT_ID" \
--base-plan-id "BASE_PLAN_ID" \
--json @migration.json
3. 对每个基础方案重复操作
对所有价格已更改的基础方案应用迁移:
# Monthly plan
gplay baseplans migrate-prices \
--package "PACKAGE" \
--product-id "PRODUCT_ID" \
--base-plan-id monthly \
--json @migration.json
# Yearly plan
gplay baseplans migrate-prices \
--package "PACKAGE" \
--product-id "PRODUCT_ID" \
--base-plan-id yearly \
--json @migration.json
4. 验证迁移
gplay subscriptions get --package "PACKAGE" --product-id "PRODUCT_ID"
更新现有 PPP 价格
要更改某个地区的价格:
- 获取当前产品/订阅,以取得所有现有地区配置。
- 使用新的基准价格或新乘数重新计算经 PPP 调整的价格。
- 将新的 PPP 价格合并到完整的地区配置列表中。
- 使用合并后的 JSON 更新(必须包含所有地区,而不只是已更改的地区)。
- 对有活跃订阅者的订阅,针对每个受影响的基础方案运行
migrate-prices。 - 通过获取数据并查看摘要来验证。
批量处理多个产品的 PPP
多个旧版 IAP
gplay iap batch-update \
--package "PACKAGE" \
--json @ppp-all-iaps.json
多个一次性产品
批量更新时,regionsVersion 和 updateMask 必须放在 JSON 的每个请求中(而不是作为 CLI 标志):
gplay onetimeproducts batch-update \
--package "PACKAGE" \
--json @ppp-all-otps.json
批量 JSON 格式:
{
"requests": [
{
"oneTimeProduct": { "productId": "product_1", "purchaseOptions": [...] },
"regionsVersion": { "version": "2025/03" },
"updateMask": "purchaseOptions"
},
{
"oneTimeProduct": { "productId": "product_2", "purchaseOptions": [...] },
"regionsVersion": { "version": "2025/03" },
"updateMask": "purchaseOptions"
}
]
}
多个订阅
逐个更新每个订阅:
gplay subscriptions update --package "PACKAGE" --product-id "sub_1" --json @ppp-sub1.json --regions-version "2025/03" --update-mask "basePlans"
gplay subscriptions update --package "PACKAGE" --product-id "sub_2" --json @ppp-sub2.json --regions-version "2025/03" --update-mask "basePlans"
常见 PPP 策略
BigMac 指数法
根据相对购买力调整价格:
- 美国:$9.99(基准)
- 印度:$2.99(约 7 折)
- 巴西:$4.99(约 5 折)
- 英国:$9.99(相近)
- 瑞士:$10.99(溢价)
分级地区定价
将国家分为不同价格层级:
- 第 1 级(全价):美国、英国、德国、澳大利亚、瑞士、加拿大
- 第 2 级(中等):法国、西班牙、意大利、日本、韩国、沙特阿拉伯
- 第 3 级(低价):印度、巴西、墨西哥、印度尼西亚、土耳其、越南、埃及
收入优化
- 从第 3 级折扣开始,以在价格敏感型市场获取更多用户。
- 应用 PPP 后,按地区监测转化率。
- 根据实际收入数据调整乘数。
常见陷阱
- 只发送 PPP 地区 — API 会拒绝删除现有地区的更新。请始终先获取数据,再合并。
- 缺少
--regions-version— 任何价格更新都必须提供此参数。如果填写错误,API 错误会告知最新版本。 - 缺少
--update-mask— 订阅使用"basePlans",一次性商品使用"purchaseOptions"。 - 缺少
otherRegionsConfig— 如果订阅基础方案之前设置了otherRegionsConfig,则更新时必须包含它。 - 缺少
newRegionsConfig— 如果一次性商品的购买选项之前设置了newRegionsConfig,则必须包含它。省略此项会导致错误:“添加新地区的货币后,无法移除该货币。” - 货币代码错误 — 不要自行假定货币代码。请从 Google Play 获取,因为货币代码会随地区版本变化。
- 混用 API 格式 — 旧版 IAP 使用
priceMicros/currency。新版订阅和一次性商品使用units/nanos/currencyCode。请勿混用。 --dry-run是全局标志 — 将它放在子命令之前:gplay --dry-run subscriptions update ...,而不是gplay subscriptions update --dry-run ...。后一种写法会报错:“提供了未定义的标志。”- 批量更新 JSON 格式 — 对于
onetimeproducts batch-update和subscriptions batch-update,regionsVersion和updateMask应放在 JSON 中的每个请求对象内,而不是作为 CLI 标志。 - 商品 ID 是永久的 — 删除商品后,Google Play 会永久保留其商品 ID。如果你通过
gplay iap create创建商品后将其删除,该 ID 将无法再次使用,甚至不能通过gplay onetimeproducts create重用。请务必谨慎选择商品 ID。请勿先通过旧版 API 创建商品,再尝试通过新版 API 重新创建。 - 新的 OTP 商品初始状态为 DRAFT — 执行
gplay onetimeproducts create后,购买选项处于 DRAFT 状态。必须使用gplay purchase-options batch-update-states将其激活,用户才能使用。 - 创建时也必须提供
--regions-version—onetimeproducts create内部使用allowMissing=true执行 PATCH,因此创建新商品时也必须提供--regions-version,而不仅仅是在更新时需要。 - 使用
gplay --help查找命令 — 购买选项的激活命令位于gplay purchase-options下,而非gplay onetimeproducts下。请始终运行gplay --help查看所有顶层命令组。
注意事项
- 订阅价格变更会立即对新订阅者生效。
- 现有订阅者需要通过
migrate-prices显式迁移价格。 - 使用
gplay pricing convert参考货币换算,但还需叠加 PPP 乘数。 - 更新后请务必获取商品并查看摘要,以验证价格。
- PPP 乘数表提供了起始参考值,请根据市场数据和营收目标进行调整。