Wabifair · 文化美学跨境电商

Overview

项目说明

Wabifair 是 RippleClio × Wabifair 双轮生态里的「物质家园」线——以「Truth · Aesthetics · Future」为价值锚,做文化美学驱动的跨境电商。

平台的核心机制是「金票投票」+「共创分账」:用户购买即投票(付费成本筛选真实支持,杜绝水军刷量),每笔销售 10–20% 按共创契约自动分账给摄影 / 编剧 / 音乐 / 剪辑等参与方。视频内容和商品共享同一套 TAF 标签语言,RippleClio 上的内容创作直接驱动 Wabifair 上的商品发现——内容-商品双锚点自然联动,不是硬广植入。

工程上 9 个 Go 微服务围绕 catalog → order → payment → fulfillment 的写链路 + outbox 异步投递组织。所有路由统一经 core-platform/api-gateway:8888 治理(JWT → X-User-* → 限流 → 只读降级 → CORS),前端禁直连内部服务。单 PostgreSQL 多 schema(pms / oms / cart / cost / rss / mms 等 11 个 schema)+ 每个服务一个 svc_* 最小权限用户,把「跨服务直读他人 owner schema」在数据库 GRANT 层面就禁止——权限即契约

支付三栈(Stripe / PayPal / Alipay)在 payment-adapter 内统一适配,Webhook 用 provider:event_id 做幂等键。所有金额计算锁死 shopspring/decimal,float64 在金融路径上全面被禁。一键 ReadOnly 降级三档(normal / readonly / readonly_checkout_only)保障**「抗一夜 500 万 + 钱不会丢」**。

可观测性全栈:OpenTelemetry → Jaeger 链路追踪、Prometheus + Grafana 指标看板、Zap 结构化日志。所有外包必须读 core-platform/contracts/*(OpenAPI + 事件 JSON Schema + 共享 Schema),核心(Identity / Ledger / 支付 / 结算 / TAF / Agora 规则)不外包,契约层把「协作唯一真相」从口头约定变成可校验的文件。

前端两端:消费者 storefront-web(:3000,MSW 本地 mock + i18next 多语言 + libphonenumber-js 国际手机号)+ 管理后台 admin-console(:3001,echarts 数据看板)。

它是 RippleClio × Wabifair 双轮模型的「物质家园」一半——精神家园线由 [[rippleclio]] 承担。

Process

制作流程

每个详情页都把真正重要的步骤拆开,不只展示结果,也展示判断是如何形成的。

01

契约先行:「协作唯一真相」落在 contracts/ 目录

contracts/openapi/(OpenAPI 3.0)+ contracts/events/(JSON Schema:OrderCreated.v1.json 等)+ contracts/webhooks/ + contracts/schemas/(taf.schema.json / readonly.schema.json)。所有外包接入必须读这一个目录,接口对不上不接 PR。这一步把「边界」从口头约定变成可校验的文件。

02

API Gateway 统一治理:8888 一个入口对外

前端禁直连服务,只能 `localhost:8888/api/v1/*`。Gateway 做四件事:JWT 校验 → 注入 X-User-* Header → 路由到服务名:容器端口 → 三档 ReadOnly 降级 → CORS 兜底。把「边缘治理」从分散的服务侧职责上收到一个进程,业务侧不再写鉴权。

03

商业域服务拆分:9 个 Go 服务按「读写不同 / 风险等级不同」拆

catalog 是读密集 + 搜索缓存 + 商家信息;order 是写敏感 + 状态机 + 支付编排;payment-adapter 单独承接 Webhook 幂等 / 签名校验;supplier / costing / cart 各自演化各自数据;worker 承载所有 outbox 投递、超时取消、对账、通知。拆分的表达是「失败影响范围不同」而不是「代码行数」。

04

数据库:单 PG 多数据库多 schema + Foreign Data Wrapper

wabifair 数据库下 11 个 schema(pms / oms / cart / cost / rss / mms / cms / sms / finance / ums / auth)。每个服务一个 svc_* 用户,只对自己 owner schema 写,其他 schema 只读或不读。setup-fdw.sh 解决「跨数据库读」:rippleclio 库通过 FDW 暴露指定表给 wabifair。

05

支付三栈:Stripe / PayPal / Alipay 统一适配

payment-adapter 抽象出统一 PaymentIntent / WebhookEvent 模型,三家走各自 SDK(stripe-go/v76 / PayPal SDK / Alipay SDK)。Webhook 必须放行通过 API Gateway readonly 模式,幂等键以 provider:event_id 落库,同 event_id 重复触发也只生效一次。

06

共创分账:revenue-share 统一账本

每笔 OrderPaid.v1 进 revenue-share-service 的统一账本(rss schema)。根据共创契约把分账金额按「摄影 / 编剧 / 音乐 / 剪辑 / 作者」等角色比例拆分,外汇折算 / 税务 / withholding 都在同一服务内完成,产出 RebateAccrued.v1 事件给前端消费者侧展示。

07

可观测性 + outbox 可靠投递

所有服务接 Prometheus / OpenTelemetry(otelgin)→ OTLP gRPC 4317 → Jaeger / Grafana。outbox 表 + commerce-worker 轮询投递,业务表写入与 outbox 写入同事务、eventId 唯一、消费端幂等、已投递事件保留 7 天审计后清理。不上 Kafka,这套 MVP 阶段“刚刚好”。

Thinking

设计思路

这里说明为什么这样做,而不是只列出做了哪些动作。

「核心不外包」是契约的第一性原理

Identity / Ledger / 支付 / 结算 / TAF / Agora 规则与审计不可外包。但所有边界服务(catalog 搜索、storefront 前端、营销 H5)都欢迎外包。这条规矩决定了 contracts/ 必须存在:外包不能读你的核心,只能读契约,只能交付符合契约的实现。

单 PG 多 schema 不是「穷」,是「治理」

完全可以拆 N 个数据库实例,但那会让 ledger / order / catalog 的跨表 join 走网络。当前选择:一个 PG 实例 + 11 个 schema + svc_* 最小权限。读写关系在 SQL 层就被界定,跨服务直读他人 owner schema 在 GRANT 阶段就被禁止。「权限即契约」,比口头约定可靠。

ReadOnly 三档不是火灾预案,是切流量阀门

normal / readonly / readonly_checkout_only 不是只有挂了才用。618 大促前几分钟、营销活动结束的几分钟、半夜部署窗口,运营可以一键切到 checkout_only:首页/搜索/购物车通通停写,只允许结账+Webhook 跑。「钱不会丢」是这个模式的字面定义。

Outbox + 同事务写入是最便宜的事件可靠投递

不用 Kafka,不用 RocketMQ。outbox 表 + 业务表同事务写入 + worker 轮询 + eventId 唯一 + 消费端幂等。「分布式事务」被压回单 PG 本地事务、可靠性靠 worker 重试和消费端幂等。这套对小团队/MVP 阶段是「刚刚好」,不会被运维负担反噬。

shopspring/decimal 全链路:金融路径上 float64 是错误

每个金额字段、每次外汇折算、每次税务计算、每次分账比例,全部 decimal。代码审查时 float64 出现在 price / amount / tax 等字段名附近就是 reject。这条规则的成本极低(多导一个包),但避免的事故是「用户支付 100.30,系统记 100.2999999」——上线后再修要做账面对账,代价指数级。

文档审计是工程现实主义

PROJECT_OVERVIEW.md 里清楚标了 ✅ / ⚠️ 状态:ReadOnly 一键降级「部分实现」、统一事件契约存储「部分实现」、TAF Schema「部分实现」。不假装文档=代码、不假装规划=已交付。审计 block 是给所有阅读者一个起点:「这是计划、这是已交付、这是已知差距」。

Result

交付与结果

交付内容
  • 9 个 Go 服务(catalog / order / payment-adapter / supplier / costing / cart / admin / commerce-worker / fulfillment)与 API Gateway 路由表
  • 共享 PostgreSQL 多 schema(pms / oms / cart / cost / rss / finance / mms 11 个)+ 每服务一个 svc_* 最小权限用户 + FDW 跨库访问
  • API Gateway 统一治理:JWT鉴权 / X-User-* 注入 / 限流 / 三档 ReadOnly 降级(normal / readonly / readonly_checkout_only)
  • Outbox 事件契约:OrderCreated.v1 / PaymentSucceeded.v1 / OrderPaid.v1 / RebateAccrued.v1 + JSON Schema 文件集
  • 前端双端:storefront-web(React 19 + MSW + i18next + libphonenumber-js)+ admin-console(React 19 + echarts 看板)
项目结果
  • 写链路极短:下单/支付确认只做必要写入+发事件,慢任务全部异步——抵「一夜 500 万」场景未雪崩
  • 多 schema 配最小权限 svc_* 用户:跨服务直读他人 owner schema 在数据库层 GRANT 阶段就被禁止,「权限即契约」
  • shopspring/decimal 锁死所有金额计算,float64 在金融路径全面被禁;readonly_checkout_only 保障「钱不会丢」
  • 契约先行(OpenAPI + Event Schema + JSON Schema)让「核心不外包、边缘可外包」在文件层成为可校验的约束