你做了一個 SaaS 產品,想加上訂閱收款。打開 Stripe 文件,發現要處理 checkout session、webhook、subscription lifecycle、invoice、proration——光是讀完文件就花掉一個下午。
Polar.sh 是另一個選擇。它專門為獨立開發者和小團隊設計,把 Stripe 那套複雜的計費邏輯包成更簡單的 API,讓你用最少的 code 就能開始收錢。
Polar.sh 是什麼
Polar.sh 是一個開源的 merchant of record 平台。它不只是 payment gateway,而是幫你處理整個交易流程:收款、發票、稅務計算、退款、訂閱管理。
跟 Stripe 的定位差異:
| Polar.sh | Stripe | |
|---|---|---|
| 定位 | Merchant of Record | Payment Infrastructure |
| 稅務處理 | Polar 負責全球稅務 | 你自己處理(或用 Stripe Tax) |
| 手續費 | 低抽成 + 交易費 | 2.9% + 30¢ per transaction |
| 複雜度 | 高層 API,幾行 code 搞定 | 底層 API,彈性大但 code 多 |
| 適合 | Indie builder、開源專案、內容產品 | 大型 SaaS、複雜計費邏輯 |
| 開源 | 是 | 否 |
關鍵差異在 merchant of record 模式。Stripe 是你自己當賣家,稅務、合規都是你的事。Polar 是它當賣家再分潤給你,全球稅務它來處理。對獨立開發者來說,這省掉非常多麻煩。
適合誰用
三類人最適合:
- 獨立開發者 — 不想花時間搞稅務和合規,想專注在產品上
- 開源專案 — 需要一個簡單的方式讓使用者付費支持或購買 pro 功能
- 內容創作者 — 賣課程包、訂閱制內容、付費 newsletter
如果你的計費邏輯很複雜(per-seat pricing、usage-based billing、enterprise 合約),Stripe 還是更合適。但對大多數獨立產品來說,Polar 的功能綽綽有餘。
設定流程
Step 1:建立 Polar 帳號和產品
到 Polar.sh dashboard 註冊後,建立你的第一個產品:
- 進入 Products 頁面,點 Create Product
- 選擇產品類型:Subscription(訂閱)或 One-time(一次性購買)
- 設定名稱、描述、價格
- 選擇計費週期(月繳 / 年繳)
Polar 支援多個 price tier,你可以建立 Free、Pro、Team 這樣的方案層級。
Step 2:取得 API 憑證
在 Settings → Developers 裡取得:
# .env.local
POLAR_ACCESS_TOKEN=polar_at_xxxxx
POLAR_ORGANIZATION_ID=org_xxxxx
POLAR_WEBHOOK_SECRET=whsec_xxxxx
POLAR_ACCESS_TOKEN 用於 server 端 API 呼叫,不要放到 NEXT_PUBLIC_ 環境變數裡。
Step 3:安裝 SDK
pnpm add @polar-sh/sdk
Next.js 整合
Checkout:引導使用者付款
// app/api/checkout/route.ts
import { Polar } from '@polar-sh/sdk'
const polar = new Polar({
accessToken: process.env.POLAR_ACCESS_TOKEN!,
})
export async function POST(req: Request) {
const { priceId, customerEmail } = await req.json()
const checkout = await polar.checkouts.create({
productPriceId: priceId,
successUrl: 'https://yoursite.com/checkout/success',
customerEmail,
})
return Response.json({ url: checkout.url })
}
前端呼叫這個 API 拿到 checkout.url,再 redirect 過去就好。使用者會看到 Polar 的 checkout 頁面,完成付款後跳回你的 successUrl。
查詢訂閱狀態
// lib/polar.ts
import { Polar } from '@polar-sh/sdk'
const polar = new Polar({
accessToken: process.env.POLAR_ACCESS_TOKEN!,
})
export async function getSubscriptionStatus(customerId: string) {
const subscriptions = await polar.subscriptions.list({
customerId,
active: true,
})
if (subscriptions.result.items.length === 0) {
return { active: false, plan: null }
}
const sub = subscriptions.result.items[0]
return {
active: true,
plan: sub.product.name,
currentPeriodEnd: sub.currentPeriodEnd,
}
}
在 Server Component 或 API route 裡呼叫 getSubscriptionStatus(),就能判斷使用者是否為付費用戶。
Webhook:接收付款事件
// app/api/webhook/polar/route.ts
import { validateEvent, WebhookVerificationError } from '@polar-sh/sdk/webhooks'
export async function POST(req: Request) {
const body = await req.text()
const headers = Object.fromEntries(req.headers.entries())
let event
try {
event = validateEvent(body, headers, process.env.POLAR_WEBHOOK_SECRET!)
} catch (e) {
if (e instanceof WebhookVerificationError) {
return new Response('Invalid signature', { status: 403 })
}
throw e
}
switch (event.type) {
case 'subscription.created':
// 新訂閱建立:更新 database、開通權限
console.log('新訂閱:', event.data.customer.email)
break
case 'subscription.updated':
// 訂閱更新:升降級、續約
break
case 'subscription.canceled':
// 訂閱取消:關閉權限(注意是 period end 才失效)
break
}
return new Response('ok')
}
Webhook 是整個計費整合最重要的部分。付款成功、訂閱取消、退款——所有狀態變化都靠 webhook 通知你的系統。
在 Polar dashboard 的 Settings → Webhooks 設定你的 endpoint URL 和要監聽的事件類型。
Customer Portal
Polar 提供內建的 Customer Portal,讓使用者自己管理訂閱、更換方案、更新付款方式:
// app/api/portal/route.ts
import { Polar } from '@polar-sh/sdk'
const polar = new Polar({
accessToken: process.env.POLAR_ACCESS_TOKEN!,
})
export async function POST(req: Request) {
const { customerId } = await req.json()
const session = await polar.customerSessions.create({
customerId,
})
return Response.json({ url: session.customerPortalUrl })
}
拿到 customerPortalUrl 後,把使用者導過去就行。不需要自己建訂閱管理頁面。
實際架構建議
把 Polar 整合到你的 Next.js 應用,建議的架構是:
app/
├── api/
│ ├── checkout/route.ts # 建立 checkout session
│ ├── portal/route.ts # Customer Portal redirect
│ └── webhook/polar/route.ts # 接收 Polar 事件
lib/
└── polar.ts # SDK client 和工具函式
核心邏輯集中在三個 API route 和一個工具模組。Webhook 負責同步狀態到你的 database,checkout 和 portal 負責使用者操作。
台灣用戶注意事項
幾個在台灣使用 Polar 需要知道的事:
- 收款幣別 — Polar 支援 USD,你的定價會是美元。台灣用戶付款時銀行會自動換匯
- 發票 — Polar 作為 merchant of record 會開立發票,但這不是台灣的統一發票。如果你的客戶需要台灣統一發票,需要另外處理
- 提領 — 收入可以提領到銀行帳戶,Polar 使用 Stripe Connect 處理 payout,台灣的銀行帳戶可以接收
- 稅務 — Polar 處理的是買家端的稅務(VAT、GST 等)。你自己的所得稅申報還是要自己處理
跟 Stripe 的選擇建議
簡單的判斷標準:
- 你是獨立開發者,想最快開始收錢 → Polar
- 你需要複雜計費(per-seat、metered、enterprise) → Stripe
- 你不想處理全球稅務 → Polar(merchant of record)
- 你需要完全客製化的 checkout 體驗 → Stripe
- 你的產品是開源專案想加 premium tier → Polar
兩者不互斥。你可以先用 Polar 快速上線,等規模到了再考慮搬到 Stripe。
想看我們怎麼用 Polar 建立完整的訂閱和 course-pack 變現系統?到 Docs 查看實作細節和架構設計。