Creem 配置

配置 Creem 产品、Edge secrets 与 Webhook。

Creem 运行在桌面应用之外。Electron 模板只在 renderer 中携带公开 product IDs,并用 server-side Edge Functions 保存 Creem API key、验证 webhooks、写入 Supabase entitlement rows。

创建 products

在 Creem 中创建你要销售的 products:

模板 planCreem product typeApp env
Pro monthlySubscriptionVITE_CREEM_PRODUCT_PRO_MONTHLY=prod_...
Pro yearlySubscriptionVITE_CREEM_PRODUCT_PRO_YEARLY=prod_...
LifetimeOne-timeVITE_CREEM_PRODUCT_LIFETIME=prod_...

把这些 IDs 放进 soar-electron/.env。它们是 renderer-public,安全可打包。不要把 CREEM_API_KEY 放进 app .env

Creem API 选择由 Edge secret CREEM_SERVER_IDX 控制:

API base
0Production API (https://api.creem.io)
1Test API (https://test-api.creem.io)

验证 checkout 和 webhook handling 时使用 test mode。

设置 Edge secrets

在 Supabase 项目中设置 secrets:

supabase secrets set \
  CREEM_API_KEY=creem_test_xxx \
  CREEM_WEBHOOK_SECRET=whsec_xxx \
  CREEM_SERVER_IDX=1 \
  --project-ref <ref>

或者复制 supabase/functions/.env.example 到 gitignored 的 supabase/functions/.env,填入值后上传:

supabase secrets set --env-file supabase/functions/.env --project-ref <ref>
Secret使用方说明
CREEM_API_KEYcreate-checkoutcustomer-portalactivate-licenseServer-side Creem API key。
CREEM_WEBHOOK_SECRETcreem-webhook必须与 Creem 中配置的 signing secret 一致。
CREEM_SERVER_IDX所有 Creem functions0 production,1 test。
BILLING_SUCCESS_URLcreate-checkout可选托管页面,把浏览器 bounce 回桌面 app。

Supabase 会向 Edge Functions 注入 SUPABASE_URLSUPABASE_ANON_KEYSUPABASE_SERVICE_ROLE_KEY。不要在 app 或 Edge secret file 中设置它们。

部署 functions

部署 functions 前先应用 billing migration:

supabase db push --project-ref <ref>

然后部署:

pnpm supabase:deploy
pnpm supabase:deploy <project-ref>

Helper script 会部署 supabase/functions/ 下除 _shared 外的每个目录。它还会对 creem-webhook 传入 --no-verify-jwt;其他 functions 通过 supabase/config.toml 保持 JWT verification on。

预期 functions:

FunctionJWT作用
create-checkout为已登录用户创建 Creem checkout,并记录 pending payment row。
customer-portal使用已登录用户保存的 customer id 创建 Creem portal URL。
activate-license可选 license-key 激活与停用。
creem-webhookPublic Creem webhook;验证 creem-signature 后写入 entitlements。

用下面命令验证部署:

supabase functions list --project-ref <ref>

配置 webhook

在 Creem 中添加 webhook URL:

https://<ref>.supabase.co/functions/v1/creem-webhook

Webhook signing secret 必须与你保存为 CREEM_WEBHOOK_SECRET 的值一致。

当前 handler 实现的 event set 是:

Event行为
checkout.completedobject.request_id / order_no 找到 payments 行,更新为 status = 'success',保存 Creem order/customer ids,然后返回。
subscription.paidobject.metadata.userId、product、customer 和 subscription period data upsert 用户的 subscriptions 行。

其他 event types 今天会被忽略。如果你的产品需要 cancellation、refund、pause 或 past-due 状态反映到 app,请扩展 supabase/functions/_shared/creem.ts,并保持客户端 read model 不变。

Webhook trust 与 idempotency:

  • creem-webhook 在 JSON parse 前读取 raw request body。
  • verifyCreemSignature() 使用 CREEM_WEBHOOK_SECRET 重新计算 HMAC-SHA256,并与 creem-signature header 比较。
  • payments.order_no 是 unique,因此重复的 checkout.completed deliveries 会收敛到同一行。
  • subscriptions.user_id 是 unique,因此重复的 subscription.paid deliveries 会 upsert 同一个 entitlement row。
  • Handler errors 返回 500,让 Creem 可以 retry。

Checkout return page

桌面应用不能依赖浏览器 redirect 直接落回 app,所以 BILLING_SUCCESS_URL 可以指向一个很小的 托管 bounce page。模板包含 supabase/pay-success.sample.html

托管前,把 sample 中过时的 soar:// 链接改成当前 scheme:

soar-electron://billing?status=success&orderId=...

运行 pnpm rebrand --scheme 后使用你改名后的 scheme。

然后把托管页面设置为 Edge secret:

supabase secrets set BILLING_SUCCESS_URL=https://your-domain.com/pay-success --project-ref <ref>

create-checkout 会在发送给 Creem 前追加 status=success&orderId=<orderNo>。 如果没有设置 BILLING_SUCCESS_URL,Creem 会回退到 product 中配置的 redirect。

本地测试

用本地 Edge env file 启动 functions:

supabase functions serve --env-file supabase/functions/.env

本地 functions 地址是:

http://localhost:54321/functions/v1/<name>

如果你也需要本地 Postgres/Auth stack,再运行 supabase start。完整 hosted sandbox checkout 通常使用 remote deploy 更简单,因为 Creem 需要访问 webhook URL。

Sandbox checkout 后检查 rows:

select order_no, user_id, product_id, status, customer_id, updated_at
from public.payments
order by created_at desc
limit 10;

select user_id, product_id, product_type, status, period_end, customer_id, subscription_id
from public.subscriptions
order by updated_at desc
limit 10;

生产检查清单

  • 桌面构建中设置了 VITE_BILLING_ENABLED=true
  • VITE_CREEM_PRODUCT_* 与你使用的 Creem environment 匹配。
  • 已应用 billing migration。
  • CREEM_API_KEYCREEM_WEBHOOK_SECRETCREEM_SERVER_IDX 已作为 Supabase Edge secrets 设置。
  • pnpm supabase:deploy 已部署四个 functions。
  • Creem webhook 指向 https://<ref>.supabase.co/functions/v1/creem-webhook
  • 如果托管 bounce page,BILLING_SUCCESS_URL 使用 soar-electron://billing 或你改名后的 scheme。
  • Sandbox checkout 写入了 paymentssubscriptions
  • 如果产品需要 cancellations、refunds 或 past-due 状态在 app 中体现,已扩展 webhook handling。

相关页面

On this page