工程 · 2026.09.30 · 3 min · 更新於 2026.10.26
SaaS 從績效抽成改成年繳訂閱:方案上限、促銷與停權的帳單設計
自動放貸 SaaS 的收費從績效抽成改成固定價訂閱。方案上限比收費先落地,促銷加送在開票當下凍結在帳單上,30 天通知只擋被動收費,停權不碰使用者自己的放貸開關。
閱讀設定
Bot 幫你多賺多少,就從裡面抽一部分,這是績效抽成的想法。我的 Bitfinex 自動放貸 SaaS 把這種收費改成了固定價的訂閱制。
訂閱帳單有幾個主要的設計決定。方案上限比收費先落地;促銷加送的月數在開票當下凍結在帳單上,之後改規則不會回頭改寫已成立的權益。
「收費前 30 天通知」只擋使用者沒有主動參與的收費路徑;停權交給引擎排除,不去動使用者自己的放貸開關。
價格和方案細節這篇不放。
績效抽成的計費問題
績效抽成的想法很直覺,我先做了一版只量不收的 shadow ledger,只記帳、不真的收錢。
問題是績效費要精準量出 Bot 的貢獻、還沒平倉的收益和實際入帳的金額,計費語意很複雜,帳面上一點誤差就會影響收費。
改成訂閱制也不是換個價格就好。方案上限、帳單狀態機、付款地址監控、到期提醒、管理端的修正、對使用者的通知,全部都要有。
方案上限先落地,再收費
訂閱的資料模型和方案上限先落地,之後才開始收費,避免先收了錢、再回頭補限制。
方案上限後來還修過一次。
同一個使用者可以有多個放貸設定,原本各自檢查上限,等於上限被放大好幾倍。現在同一輪的多個設定共用同一份額度。
示意圖,長條長度不代表實際額度。
付款走帳單加上 movements watcher(movements 是 Bitfinex 帳戶的入出金紀錄)。watcher 直接對接 Bitfinex 的真實資料,讓收款地址、入金事件和帳單狀態可以互相對帳。
自建這段的好處是少依賴一個外部付款服務,代價是對帳的責任落在自己身上。
付款頁、通知和後台操作一起上,使用者和營運端看到的是同一套狀態。
促銷:加送凍結在帳單上
年繳促銷做成資料模型和規則,不寫死在前端文案裡。
最重要的決定是,加送的月數在開票當下就凍結在帳單的 period_end 裡。
之後活動規則怎麼改,都不會回頭改寫已經成立的帳單權益。
示意圖,長度不代表實際的方案或加送月數。
其他幾條規則:
- 符合多個活動可以疊加,但同一個人對同一個活動只能兌換一次。
- 有兌換紀錄的活動不能刪除,保留帳務的稽核鏈。
- 帳單逾期作廢時,也會釋放這張帳單用掉的活動兌換。
- 活動只套在使用者自己按的結帳,不套自動續訂,避免長期的收費規則被一個舊活動綁住。
權限也分開。管理活動要能管理費用的權限,只讀取的話,能看使用者的權限就夠,營運查詢和價格控制不混在一起。
30 天通知只擋被動收費
開始收費前要先通知 30 天。這道 gate 管的是使用者沒有主動參與的路徑:自動開續訂帳單,以及試用到期。
使用者自己按結帳,刻意不受這個 gate 限制。
主動購買不是被動開始收費。
停權不碰使用者的開關
停權原本是直接把使用者的放貸開關關掉。
問題是使用者的意圖和帳務資格混在同一個旗標裡,停權的人自己按恢復,就能繼續放貸。
現在改成引擎挑設定時直接排除停權的使用者,放貸開關完全不動。付款恢復之後,使用者自己按過的暫停照樣保留。

使用者的意圖和系統的帳務狀態要分開存,停權這種系統動作,不要去改使用者自己設定的值。

工程
Java 搬到 Rust 後的 code review:15 條 finding,6 條是從 Java 照搬的 bug
後端從 Java 換成 Rust 之後做了一次完整 code review。這篇挑四條最有教訓價值的:照註解搬錯的交易語意、sqlx 對失敗交易回 Ok、client 斷線砍掉 handler,以及停權跟放貸開關共用旗標。
留言
載入留言中…