mcpField
P
polar-migration

polar-migration

github.com/polarsource开发5133 次安装2 周前更新
代码仓库

关于 polar-migration

面向开发者的 Polar 账单迁移指南,涵盖 Stripe 辅助迁移及其他服务商的迁移方式,并说明客户映射、订阅切换和核对要点。

主要功能

  1. 01Stripe 迁移流程
  2. 02其他账单服务商迁移指南
  3. 03客户与订阅映射
  4. 04切换事件处理
  5. 05测试与核对指南

适用场景

  1. 01规划从 Stripe 迁移到 Polar
  2. 02从其他服务商迁移订阅
  3. 03实现切换期间的 Webhook 处理

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/polarsource/agent-toolkit --skill polar-migration

安装后在 Claude Code 中输入/polar-migration确认已加载。

详细介绍

Polar 迁移指南

Polar 迁移指南是权威信息来源;在提出任何建议前,请先阅读。本文概述应用需要完成的工作。

选择迁移路径

  • 从 Stripe 迁移:使用 Polar 在设置 → 迁移中提供的辅助迁移功能。Polar 会导入产品、价格和客户,Stripe 会将已保存的银行卡直接复制到 Polar 的支付处理商,Polar 则会按照相同的已付费周期逐个切换订阅。大多数客户无需执行任何操作。迁移功能正在逐步推出;如果看不到该选项卡,请联系 Polar 支持。
  • **从 Paddle、Lemon Squeezy 或其他平台迁移:**没有自动迁移功能。请先联系 Polar 支持,然后按照下方的“其他服务商”部分操作。客户需要在 Polar 上重新结账。

所有迁移都必须遵守的规则

  • 除非由 Polar 执行切换,否则绝不要停止、取消或暂停旧服务商的计费,也不要激活已迁移的 Polar 订阅。不要编写自己的切换脚本:这会导致重复扣费。
  • 绝不要处理原始银行卡数据,也绝不要在聊天中索要 Stripe 或 Polar 密钥。
  • 将应用中不可变的客户 ID 用作 Polar 客户的 external_id(结账时传入 external_customer_id)。不要使用电子邮件地址;除非旧服务商的 ID 已是应用的规范 ID,否则也不要使用旧服务商的 ID。external_id 一经设置便无法更改。
  • 每个订阅必须且只能由一个系统负责下一次续订。请记录由哪个系统负责,而不是根据设置了哪些 ID 来推断。
  • 过去的付款记录保留在旧服务商中。不要为 Polar 未处理的交易创建 Polar 订单,并保留旧账户以处理退款、争议和会计事务。

从 Stripe 迁移

控制面板负责连接 Stripe、导入商品目录、复制银行卡并切换订阅。应用负责首尾阶段以及中间发生的事件。

1. 将新销售转移到 Polar

先集成 Polar 结账和 Webhook(polar-integration),并在每次结账时传入 external_customer_id。此后,新客户会在 Polar 上订阅,而现有订阅仍由 Stripe 续订。在 Stripe 不再有任何续订之前,请将 Stripe ID 保留在数据库中。

共存期间,访问权限检查必须接受任一服务商提供的有效权益;取消订阅或更改套餐时,则应发送给负责该订阅计费的系统。

2. 映射导入的客户

导入过程会创建或复用 Polar 客户,但 Polar 无法获知应用中的客户 ID。请仅根据准确且唯一的电子邮件地址,将每位导入客户匹配一次,然后为 external_id 仍为空的客户设置你的 ID。对于缺失、重复或已更改的电子邮件地址,请提交审核,不要猜测。

import { polar } from "./polar"; // client from polar-integration

const customer = await polar.customers.get(polarCustomerId);
if (customer.external_id === null) {
  await polar.customers.update(polarCustomerId, { external_id: appCustomerId });
}

导入的产品会成为新的 Polar 产品。请明确将每个内部套餐映射到新的 Polar 产品 ID 和价格 ID,切勿按名称映射。权益不会导入:如果访问权限依赖权益,请在切换前将权益附加到导入的产品上。

3. 为切换做好准备

Polar 会立即取消 Stripe 上每个已切换的订阅,不按比例计费,也不会生成最终账单。切换前:

  • 关闭 Stripe 的订阅取消邮件(Settings → Billing → Subscriptions and emails),并暂停任何由取消触发的 Stripe 自动化。

  • 让 Stripe 的 customer.subscription.deleted 处理程序忽略已切换的订阅,以免撤销访问权限或发送取消邮件:

    if (subscription.cancellation_details?.comment?.startsWith("Migrated to Polar")) {
      return; // billing moved to Polar; reconcile through subscription.migrated instead
    }
    
  • 将 Polar 的 subscription.migrated 事件作为切换信号。该事件包含 provider 和 provider_subscription_id。将其作为幂等的更新或插入处理:把 Polar 订阅 ID 关联到 Stripe 订阅,并记录由 Polar 负责下一次扣款。不要因此授予或撤销访问权限,也不要发送欢迎邮件:

    case "subscription.migrated":
      await recordMigratedSubscription({
        stripeSubscriptionId: event.provider_subscription_id,
        polarSubscriptionId: event.data.id,
      });
      break;
    

每个已切换的订阅都会收到 subscription.updated、subscription.migrated 和 customer.state_changed 事件,顺序不定。迁移不会发送 subscription.created 或 subscription.active,导入也不会发送 product.created 或 customer.created。

4. 切换、核对并清理

在仪表板中启动切换。此操作无法撤销;将在 24 小时内续订的订阅会留在 Stripe,直到下一次扣款尝试。之后,请确认每个已迁移的订阅都只在 Polar 扣款,并且只关联到一个客户和一项权益。只有在 Stripe 上不再有订阅续订后,才停用 Stripe 结账和订阅代码。

请提前了解以下限制:Stripe Connect 平台账户和印度的 Stripe 账户无法使用自动迁移流程。通过 Stripe Managed Payments 售出的订阅,以及包含多件商品、数量大于 1,或处于逾期、未付款或暂停状态的订阅,需要特别处理或会留在 Stripe。只会复制银行卡;复制真实银行卡需要使用正式环境的 Stripe 账户,且 Stripe 密钥模式必须与 Polar 环境一致。

如需全面评估,Polar 的指南中提供了一个编码助手提示词,可在修改代码前生成迁移计划和核对协议。

其他服务商

重新创建商品目录

计费周期属于商品,且每种货币的商品只能有一个固定价格。按月和按年计费需要创建两个商品:

await polar.products.create({
  name: "Pro (Monthly)",
  recurring_interval: "month",
  prices: [{ amount_type: "fixed", price_amount: 2900, price_currency: "usd" }],
});
await polar.products.create({
  name: "Pro (Yearly)",
  recurring_interval: "year",
  prices: [{ amount_type: "fixed", price_amount: 29000, price_currency: "usd" }],
});

重新创建权益(许可证密钥、文件下载、Discord 角色等),并使用 polar.products.updateBenefits(productId, { benefits: [benefitId] }) 将它们关联起来。

迁移客户

如果希望客户在结账前就出现在 Polar 中,可以提前创建客户:

await polar.customers.create({ external_id: appCustomerId, email, name });

无法通过 API 创建付费订阅;除 Stripe 的复制功能外,已保存的银行卡也无法在不同支付处理商之间迁移。每位客户都需要在 Polar 上结账,并在那里输入银行卡信息。请发送使用 external_customer_id 创建的结账链接。

为避免同一计费周期被重复扣款,请安排旧订阅在当前周期结束时取消,并为 Polar 结账设置一个覆盖剩余天数的试用期,使用 trial_interval: "day" 和 trial_interval_count。请联系 Polar 支持,确认此方案是否适用于你的情况。

许可证密钥

许可证密钥无法导入。在过渡期间,请继续通过旧服务商验证现有密钥;新购买的客户将获得 Polar 密钥。

与客户沟通

  • **Stripe 迁移:**客户无需采取任何操作。Polar 会在首次账单邮件(例如首次续订收据)中添加迁移通知。如果希望客户先从你这里得知此事,请在切换前发送简短通知。
  • **其他服务商:**客户需要重新结账。请明确告知他们需要在 Polar 上输入银行卡信息、何时会被扣款,以及旧订阅会在已付费周期结束时终止。

测试

先使用 Stripe 测试模式账户在 Polar 的沙盒中运行迁移。沙盒会验证应用端(客户映射、subscription.migrated 处理、访问检查),但无法复制真实银行卡。请参阅 polar-testing,了解沙盒设置和本地 webhook 测试。

评论

支持 Markdown