Huly 如何叠加 billing 与 payment 服务并配置 Stripe 沙箱
【免费下载链接】platformHuly — All-in-One Project Management Platform (alternative to Linear, Jira, Slack, Notion, Motion)项目地址: https://gitcode.com/GitHub_Trending/platform80/platform
Huly 的 docker compose 开发栈默认并不运行真实的 billing 与 payment 服务:基础 compose 文件只是向前端宣告了PAYMENT_URL=http://huly.local:3040(见 dev/docker-compose.yaml)。要让客户端能够访问计费功能并启用套餐限制(plan-limit restrictions),需要叠加 dev/docker-compose.ext.yaml 这个 overlay,把payment和billing两个服务实际拉起来,并配置 Stripe 提供商。本文基于一个已可运行的 Huly docker compose 开发环境,完成 overlay 叠加、Stripe 沙箱凭据配置与结果验证。
两个服务各自的职责
- payment(镜像
hardcoreeng/payment,端口 3040):provider 无关的支付服务,负责通过提供商 API 创建订阅 checkout 并接收 webhook。完整流程见 services/payment/pod-payment/README.md:客户端POST /api/v1/subscriptions/:workspace/subscribe→ payment 服务经提供商创建 checkout → 用户完成支付 → 提供商向POST /api/v1/webhooks/stripe发送事件 → payment 服务把订阅写回 accounts 服务。 - billing(镜像
hardcoreeng/billing,端口 4042):依赖cockroach、minio(要求service_healthy)、account三个服务;overlay 中设置USAGE_UPDATE_INTERVAL=600,注释说明开发环境每 10 分钟复核一次 workspace 用量(默认值为 1 小时)。
基础 compose 已经设置PAYMENT_URL,所以 ext overlay 只需给 front 补充BILLING_URL=http://huly.local:4042(环境变量是加性合并的)。前端只有在BILLING_URL非空时才会注册 billing 插件,这一点可在 dev/prod/src/platform.ts 中确认。
准备 Stripe 沙箱凭据
按 services/payment/pod-payment/README.md 的 Stripe Provider 一节,需要三个环境变量:
| 变量 | 说明 | 文档示例值 |
|---|---|---|
STRIPE_API_KEY | Stripe API secret key | sk_live_...或sk_test_... |
STRIPE_WEBHOOK_SECRET | Webhook 签名密钥 | whsec_... |
STRIPE_SUBSCRIPTION_PLANS | 套餐到 Price ID 的映射 | common@tier:price_1a;rare@tier:price_2;epic@tier:price_3;legendary@tier:price_4 |
映射格式为{plan}@{type}:{priceId};...,其中priceId是 Stripe Price ID(形如price_1abc123),文档说明可以在 Stripe Dashboard 的 Products 下找到。沙箱场景对应 README 示例中的sk_test_...形式密钥;webhook 端点注册在/api/v1/webhooks/stripe。
一个必须注意的限制:同一时间只能有一个 provider 生效。README 明确写道,如果配置了 Polar(POLAR_ACCESS_TOKEN等),Stripe 不会被初始化;使用 Stripe 时就不要设置POLAR_*变量。
在宿主环境设置变量
overlay 文件头注释说明:提供商凭据从宿主环境读取(示例为dev/.env或 shell 变量),包括:
PAYMENT_USE_SANDBOX(默认true);STRIPE_API_KEY、STRIPE_WEBHOOK_SECRET、STRIPE_SUBSCRIPTION_PLANS;- Polar 对应的
POLAR_ACCESS_TOKEN、POLAR_WEBHOOK_SECRET、POLAR_ORGANIZATION_ID、POLAR_SUBSCRIPTION_PLANS(本场景不使用)。
overlay 中传给 payment 容器的写法是STRIPE_API_KEY=${STRIPE_API_KEY:-}这类空回退形式,即宿主环境未设置时容器内拿到空值,服务仍会启动。billing 容器还有DB_URL=${DB_CR_URL}和STORAGE_CONFIG=${STORAGE_CONFIG}两个引用宿主环境的变量,需要确保宿主环境同样提供它们。
这里存在两处文档口径不一致,如实说明:dev/docker-compose.ext.yaml 注释写 "All are optional — without them the service starts in sandbox mode"(无凭据时以沙箱模式启动、不对外发起调用);而 common/config/rush/command-line.json 中docker:up:ext命令的 description 把STRIPE_API_KEY、STRIPE_WEBHOOK_SECRET、STRIPE_SUBSCRIPTION_PLANS(或POLAR_*等价项)列为 "Required env"。按 overlay 注释,无凭据也能启动但不发起外呼;要真正完成 Stripe 沙箱订阅流程,应按 rush 命令的说明把这三个变量配置齐全。
用 overlay 启动服务栈
最短主路径(对应 overlay 文件头注释的用法):
docker compose -f docker-compose.yaml -f docker-compose.ext.yaml up或等价的 rush 命令(common/config/rush/command-line.json 中docker:up:ext的 shellCommand 为cd ./dev && docker compose -f docker-compose.yaml -f docker-compose.ext.yaml up -d --force-recreate):
rush docker:up:ext可选分支:如果希望保持小占用、只在 min 配置上叠加 billing/payment,overlay 注释给出的组合是:
docker compose -f docker-compose.yaml -f docker-compose.min.yaml -f docker-compose.ext.yaml up这能工作是因为 dev/docker-compose.min.yaml 会把payment、billing收进profiles: ["full"],而 ext overlay 用profiles: !override []清掉该门禁。
overlay 中影响本次任务的关键配置摘录(原文见 dev/docker-compose.ext.yaml):
payment:ports: 3040:3040,depends_on: account,环境变量含ACCOUNTS_URL=http://huly.local:3000、FRONT_URL=http://huly.local:8087、USE_SANDBOX=${PAYMENT_USE_SANDBOX:-true}及三个STRIPE_*透传;billing:ports: 4042:4042,depends_on为 cockroach(service_started)、minio(service_healthy)、account(service_started);front:新增BILLING_URL=http://huly.local:4042。
结果验证
- 端口与依赖:overlay 声明
payment监听 3040、billing监听 4042;billing 对 minio 要求service_healthy,minio 未就绪时 billing 不会进入运行状态。 - 客户端识别:前端仅当
BILLING_URL非空时才注册 billing 应用(dev/prod/src/platform.ts 中的条件判断),叠加 overlay 后客户端应能看到 billing 入口;这是 overlay 注释中 "so the client picks them up" 所指的生效标志。 - 订阅流程(payment README 记载的请求路径与成功回跳):客户端
POST /api/v1/subscriptions/:workspace/subscribe(Bearer token,body 含type(tier或support)与plan),成功响应返回checkoutId与checkoutUrl(文档示例中为checkout_abc123/ Polar 的 checkout 链接,仅作文档示例);用户完成支付后被重定向到FRONT_URL/workbench/setting/setting/billing?payment=success&checkout_id={CHECKOUT_ID},payment=success查询参数即文档给出的成功标志。 - webhook 与管理端点:Stripe 事件发送到
/api/v1/webhooks/stripe;管理侧可用GET /api/v1/subscriptions/:subscriptionId(admin only)查看订阅、POST /api/v1/subscriptions/:subscriptionId/cancel取消订阅。
限制
- 只有一个 provider 可以生效:配置了
POLAR_*时 Stripe 不会初始化,两者不能同时使用。 - 不设提供商凭据时服务以沙箱模式运行、不发起外呼,此时订阅 checkout 无法真正创建;两处文档对凭据是否"必需"的表述不一致,如前所述,完成 Stripe 沙箱订阅应配齐
STRIPE_API_KEY、STRIPE_WEBHOOK_SECRET、STRIPE_SUBSCRIPTION_PLANS。 STRIPE_SUBSCRIPTION_PLANS中的 Price ID 必须与你在 Stripe 账户中实际创建的 Price 一致,README 未提供可用的公共测试值。
【免费下载链接】platformHuly — All-in-One Project Management Platform (alternative to Linear, Jira, Slack, Notion, Motion)项目地址: https://gitcode.com/GitHub_Trending/platform80/platform
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考