Power Parity Pricing Strategies 实战:基于 purchasing-power-parity API 的区域定价计算与 Edge 定价策略
【免费下载链接】examplesEnjoy our curated collection of examples and solutions. Use these patterns to build your own robust and scalable applications.项目地址: https://gitcode.com/GitHub_Trending/examples1/examples
购买力平价(Purchasing Power Parity, PPP)定价的核心难题是:如何把全球 250 多个国家/地区,稳定、可复现地映射到有限的几个定价区域。本文以仓库edge-middleware/power-parity-pricing-strategies中的 PPP.md 为主体,完整拆解其 PPP 计算函数——如何调用购买力平价 API 获取每个国家的换算因子,再通过阶梯匹配算法落到 5 档价格区域;同时结合仓库中的 Edge Middleware、SSR、静态渲染三种落地实现,说明"算出来的区域"如何真正驱动商品折扣与下单链接。读完本文,你将掌握一套可直接复制的 PPP 区域划分算法,并能理解它在一个真实 Next.js 示例中的三种部署形态。
一、购买力平价定价的出发点
不同国家/地区的货币购买力差异巨大:同样的 15 美元,在美国可能只是一杯咖啡,在部分发展中市场却是一天的生活开支。PPP(购买力平价)定价正是为了让定价"对齐购买力"——收入与物价水平较低的国家/地区获得更大的折扣,从而在保证营收的同时提升当地用户的转化率。
本示例以一款15 美元的 Vercel Mug(限量版马克杯)为商品原型(见 api.ts 中的PRODUCT定义),目标是:根据访客所在国家,动态决定展示原价还是某个区域折扣价。而"国家 → 区域"的映射,正是 PPP.md 这份文档要解决的核心问题。
二、PPP 计算脚本全解
PPP.md 给出了一段独立的 Node.js 脚本,用来为约 250 个国家逐个计算"应该落在哪个定价区域"。以下代码即为原文档的完整实现(含全部国家代码列表),可直接复制运行:
let prices = {} const PRICE = 15 const COUNTRIES = [ 'af', 'al', 'dz', 'as', 'ad', 'ao', 'ai', 'aq', 'ag', 'ar', 'am', 'aw', 'au', 'at', 'az', 'bs', 'bh', 'bd', 'bb', 'by', 'be', 'bz', 'bj', 'bm', 'bt', 'bo', 'bq', 'ba', 'bw', 'bv', 'br', 'io', 'bn', 'bg', 'bf', 'bi', 'cv', 'kh', 'cm', 'ca', 'ky', 'cf', 'td', 'cl', 'cn', 'cx', 'cc', 'co', 'km', 'cd', 'cg', 'ck', 'cr', 'hr', 'cu', 'cw', 'cy', 'cz', 'ci', 'dk', 'dj', 'dm', 'do', 'ec', 'eg', 'sv', 'gq', 'er', 'ee', 'sz', 'et', 'fk', 'fo', 'fj', 'fi', 'fr', 'gf', 'pf', 'tf', 'ga', 'gm', 'ge', 'de', 'gh', 'gi', 'gr', 'gl', 'gd', 'gp', 'gu', 'gt', 'gg', 'gn', 'gw', 'gy', 'ht', 'hm', 'va', 'hn', 'hk', 'hu', 'is', 'in', 'id', 'ir', 'iq', 'ie', 'im', 'il', 'it', 'jm', 'jp', 'je', 'jo', 'kz', 'ke', 'ki', 'kp', 'kr', 'kw', 'kg', 'la', 'lv', 'lb', 'ls', 'lr', 'ly', 'li', 'lt', 'lu', 'mo', 'mg', 'mw', 'my', 'mv', 'ml', 'mt', 'mh', 'mq', 'mr', 'mu', 'yt', 'mx', 'fm', 'md', 'mc', 'mn', 'me', 'ms', 'ma', 'mz', 'mm', 'na', 'nr', 'np', 'nl', 'nc', 'nz', 'ni', 'ne', 'ng', 'nu', 'nf', 'mp', 'no', 'om', 'pk', 'pw', 'ps', 'pa', 'pg', 'py', 'pe', 'ph', 'pn', 'pl', 'pt', 'pr', 'qa', 'mk', 'ro', 'ru', 'rw', 're', 'bl', 'sh', 'kn', 'lc', 'mf', 'pm', 'vc', 'ws', 'sm', 'st', 'sa', 'sn', 'rs', 'sc', 'sl', 'sg', 'sx', 'sk', 'si', 'sb', 'so', 'za', 'gs', 'ss', 'es', 'lk', 'sd', 'sr', 'sj', 'se', 'ch', 'sy', 'tw', 'tj', 'tz', 'th', 'tl', 'tg', 'tk', 'to', 'tt', 'tn', 'tr', 'tm', 'tc', 'tv', 'ug', 'ua', 'ae', 'gb', 'um', 'us', 'uy', 'uz', 'vu', 've', 'vn', 'vg', 'vi', 'wf', 'eh', 'ye', 'zm', 'zw', 'ax', ] const REGIONS = { 1: 13, 2: 12, 3: 10, 4: 9, 5: 7.5, } for await (const country of COUNTRIES) { let factor = 1 try { factor = await fetch( `https://api.purchasing-power-parity.com/?target=${country.toUpperCase()}` ) .then((res) => res.json()) .then(({ ppp: { pppConversionFactor: factor } }) => factor) } catch (e) { console.warn(`Failed for ${country}`) } prices[country] = Object.entries(REGIONS).reduce( (match, item) => (PRICE * factor < match[1] ? item : match), ['1', Infinity] )[0] } console.log(prices)脚本整体分为四个部分,下面逐一拆解。
1. 三个输入常量
PRICE = 15:商品的美元基准价,即不享受任何区域折扣时的售价(与 api.ts 中PRODUCT.price保持一致)。COUNTRIES:ISO 3166-1 alpha-2 格式的国家/地区代码列表,覆盖全球主要市场(af=阿富汗、cn=中国、jp=日本、us=美国……),这也是脚本要逐一遍历计算的对象。REGIONS:定价区域的"价格档位"表,共 5 档,键为区域编号1~5,值为该区域的目标售价(美元):区域 1 卖 13 美元、区域 2 卖 12 美元、区域 3 卖 10 美元、区域 4 卖 9 美元、区域 5 卖 7.5 美元。档位越低,说明该区域的购买力越弱,商品定价越低。
2. 通过 PPP API 获取换算因子
对每个国家,脚本向购买力平价 API 发起请求:
https://api.purchasing-power-parity.com/?target=${country.toUpperCase()}target参数传入大写的国家代码;- 响应结构为
{ ppp: { pppConversionFactor: factor } },从中解构出pppConversionFactor,即该国的购买力平价换算因子; - 换算因子的语义大致是:1 美元在该国的实际购买力相当于多少美元在美国的购买力。因子越小,代表当地物价越低、购买力越强,相应地应给出更大的折扣;
- 请求被包在
try/catch中,失败时通过console.warn(\Failed for ${country}`)打印警告,同时factor保持默认值1`,即按原价(区域 1)兜底,避免单个国家请求失败导致整个脚本中断。
3. 区域匹配的 reduce 阶梯算法
这是整个脚本的核心。PRICE * factor计算出该国的购买力平价等效价格(记作PF),随后用reduce在 5 个价格档位中寻找最合适的区域:
Object.entries(REGIONS).reduce( (match, item) => (PRICE * factor < match[1] ? item : match), ['1', Infinity] )[0]reduce的初始值是['1', Infinity](区域 1,价格视为无穷大),随后依次与['1', 13]、['2', 12]、['3', 10]、['4', 9]、['5', 7.5]比较:只要当前档位的价格小于已匹配档位的价格,就切换到当前档位。由于档位价格单调递减(13 → 12 → 10 → 9 → 7.5),最终结果等价于"找到第一个价格低于PF的档位":
| 购买力平价等效价格 PF | 匹配区域 | 区域目标售价 |
|---|---|---|
PF ≥ 12 | 区域 1 | 13 美元 |
10 ≤ PF < 12 | 区域 2 | 12 美元 |
9 ≤ PF < 10 | 区域 3 | 10 美元 |
7.5 ≤ PF < 9 | 区域 4 | 9 美元 |
PF < 7.5 | 区域 5 | 7.5 美元 |
规律很直观:PF越高(购买力越接近/超过美国水平),落入靠前的区域,折扣越小;PF越低(当地物价越便宜),落入靠后的区域,折扣越大。reduce最后取[0]拿到区域编号字符串(如'5'),存入prices[country]。
4. 输出结果
脚本最终通过console.log(prices)输出一份"国家 → 区域编号"的完整映射,例如{ af: '5', cn: '5', jp: '2', us: '1', ... }。这份结果即可作为后续定价系统的数据源——在本仓库中,它的落地产物就是 api.ts 中那份近 250 个国家的PRODUCTS映射表。
三、区域编号如何落地为折扣:constants.ts 与 utils.ts
PPP.md 中的REGIONS是"售价档位"视角,而仓库运行时使用的是 constants.ts 中定义的"折扣与商店变体"视角,两者通过区域编号1~5一一对应:
export const STORE_URL = `https://vercel-merchandise.myshopify.com` export const DELAY = process.env.NODE_ENV === 'production' ? 250 : 0 export const REGIONS = { '1': { id: '41891558719737', discount: 10 }, '2': { id: '41891558752505', discount: 20 }, '3': { id: '41891558785273', discount: 30 }, '4': { id: '41891558818041', discount: 40 }, '5': { id: '41891558850809', discount: 50 }, default: { id: '41893825478905', discount: 0 }, }discount:区域折扣百分比,从区域 1 的 10% 到区域 5 的 50%。以基准价 15 美元计算,15 × (1 - 50%) = 7.5,恰好与 PPP.md 中区域 5 的价格档位 7.5 美元吻合;区域 2(20%)对应 12 美元、区域 4(40%)对应 9 美元也同样精确对应,可见两处配置出自同一套定价设计;id:Shopify 商店中对应折扣商品的变体 ID,用于拼出"加入购物车"链接(/cart/{id}:1);default:无区域匹配时的兜底选项,折扣为 0(原价);DELAY:模拟网络延迟用的,生产环境 250ms、开发环境 0ms,用于在演示中体现不同渲染策略的响应差异。
商品最终的展示价格由 utils.ts 中的getDiscountedPrice计算,并按 USD 格式本地化输出:
export function getDiscountedPrice(price: number, discount: number): string { return Number(price * ((100 - discount) / 100)).toLocaleString('en-US', { currency: 'USD', }) }四、从"算出的区域"到"商品折扣":api.ts 的国家映射表
PPP.md 中脚本算出的"国家 → 区域"结果,在 api.ts 中被固化成了一张可直接查询的PRODUCTS表。它以基准商品PRODUCT(价格 15、折扣 10%、美国区域)为原型,为每个国家覆盖discount与link两个字段,例如:
// Argentina ar: { ...PRODUCT, name: 'Taza Vercel', description: 'Edición Limitada', discount: REGIONS['5'].discount, link: `${STORE_URL}/cart/${REGIONS['5'].id}:1`, }, // China cn: { ...PRODUCT, name: 'Vercel 马克杯', description: '限量版', discount: REGIONS['5'].discount, link: `${STORE_URL}/cart/${REGIONS['5'].id}:1`, }, // Japan jp: { ...PRODUCT, name: 'Vercel マグ', description: '限定版', discount: REGIONS['2'].discount, link: `${STORE_URL}/cart/${REGIONS['2'].id}:1`, },从这张表可以观察到:阿根廷、中国等国家被映射到区域 5(50% 折扣),日本映射到区域 2(20% 折扣),美国、德国等映射到区域 1(10% 折扣);部分市场还针对商品名和描述做了本地化(如阿根廷的西班牙语Taza Vercel、中国的Vercel 马克杯、日本的Vercel マグ)。
文件末尾导出了统一的查询接口(api.ts):
export default { product: { fetch: async ({ country }: { country?: Country } = {}): Promise<Product> => { let product = PRODUCT if (country && PRODUCTS[country]) { product = PRODUCTS[country] } let delay = DELAY if (country === 'jp') { delay = 1250 } return new Promise((resolve) => setTimeout(() => resolve(product), delay)) }, countries: async (): Promise<Country[]> => Object.keys(PRODUCTS) as Country[], }, }其中fetch按国家返回对应商品(含折扣与购物车链接),并为日本场景特意将延迟拉长到 1250ms,用于演示高延迟地区在三种渲染策略下的体验差异;countries则返回全部国家列表,供getStaticPaths预生成页面使用。商品结构由 types.ts 中的Product接口约束(id / price / name / description / image / link / discount)。
五、三种渲染策略中的 PPP 落地
仓库的完整示例(见 README.md)展示了同一套定价数据在三种渲染策略下的差异,这也是 PPP.md 中计算结果的三种消费方式。
1. Edge Middleware:请求时动态定价
middleware.ts 在边缘网络层拦截/edge请求,利用@vercel/functions提供的geolocation对象获取访客国家,再通过NextResponse.rewrite重写到对应的国家页:
import { geolocation } from '@vercel/functions' import { type NextRequest, NextResponse } from 'next/server' export const config = { matcher: '/edge', } export default function middleware(req: NextRequest) { const country = geolocation(req).country?.toLowerCase() || 'us' req.nextUrl.pathname = `/edge/${country}` return NextResponse.rewrite(req.nextUrl) }国家页 pages/edge/[country].tsx 通过getStaticPaths(fallback:'blocking')预生成全部国家页面,getStaticProps按国家取回对应商品,页面渲染时默认开启"Activate X% off with regional pricing",用户可以手动切换开关对比原价与区域价。该页还通过/flags/${country}.svg展示访客国家旗帜(旗帜资源位于 public/flags)。
2. Node.js SSR:服务端请求时定价
pages/ssr.tsx 使用getServerSideProps,在 Node.js 服务端读取请求头x-vercel-ip-country(Vercel 在部署环境中注入的国家信息)来识别访客:
export const getServerSideProps: GetServerSideProps = async ({ req }) => { const country = String(req.headers['x-vercel-ip-country'] || 'us').toLowerCase() as Country const product = await api.product.fetch({ country }) return { props: { country, product } } }3. 静态渲染:统一原价
pages/static.tsx 是纯静态版本:getStaticProps不传国家,api.product.fetch()返回无折扣的基准商品,页面固定展示原价 15 美元,仅提供一个"Get Discount via Edge"按钮跳转到/edge体验动态定价。
三种策略的对比点很清晰:Edge Middleware 在离用户最近的边缘节点完成国家识别与重写,延迟最低;SSR 在 Node.js 服务端完成,依赖部署平台注入的国家请求头;静态渲染则完全不做差异化。这正是该示例命名为 "Power Parity Pricing Strategies"(多种 PPP 定价策略)的原因。
六、运行与验证
仓库 README.md 提供了两种使用方式:
克隆仓库后本地运行:克隆本仓库后进入
edge-middleware/power-parity-pricing-strategies目录,安装依赖(pnpm install),然后执行:pnpm dev启动后访问
/edge、/ssr、/static三个路由即可对比三种策略的定价差异;若想验证不同国家的定价结果,可直接访问/edge/{country}(如/edge/jp、/edge/ar),或对照 api.ts 中的PRODUCTS表查看各国折扣。部署到 Vercel:将仓库推送到支持 Next.js 的部署平台(如 Vercel)即可上线,
middleware.ts的geolocation能力与x-vercel-ip-country请求头由平台在边缘/服务端自动注入,无需额外配置。
说明:PPP.md 中脚本依赖的
api.purchasing-power-parity.com为第三方外部接口,实际生产环境中建议将其替换为自维护的 PPP 因子数据,或对接口响应做缓存与兜底(脚本中factor = 1的默认值即为兜底路径)。
七、小结
PPP.md 用一段约 290 行的脚本,完整示范了"购买力平价定价"中最关键的一环——将全球国家映射到有限的定价区域:
- 通过
api.purchasing-power-parity.com获取每个国家的pppConversionFactor; - 用
PRICE × factor计算购买力平价等效价格; - 用
reduce阶梯匹配算法将等效价格落到 5 档区域(13 / 12 / 10 / 9 / 7.5 美元); - 区域编号进一步驱动 constants.ts 中的折扣百分比与商店变体,最终在 api.ts 中固化为完整的国家商品映射表。
这套"外部 PPP 数据 → 区域匹配算法 → 折扣与下单链接"的链路,加上 Edge / SSR / 静态三种渲染策略的对照实现,为跨境电商与 SaaS 产品的区域差异化定价提供了一个可直接复用的完整参考。文中涉及的代码与配置均可从仓库对应文件中继续深入研读。
【免费下载链接】examplesEnjoy our curated collection of examples and solutions. Use these patterns to build your own robust and scalable applications.项目地址: https://gitcode.com/GitHub_Trending/examples1/examples
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考