如何在 Next.js、Expo 與 Tauri 之間共享認證和支付?
取決於能否保持同一身分模型與同一權益儲存。Web 用 HttpOnly Cookie 工作階段;Expo 在 Deep Link 的 OAuth 回呼後把 Bearer Token 存入 expo-secure-store;Tauri 在 Webview 內直接複用 Web 工作階段——三者由同一個 Better Auth 實例校驗。支付同理:8 家 Web 閘道與 RevenueCat 行動內購匯入同一個冪等 webhook 帳本,寫入每個端面都能讀取的工作區級權益。
跨端 SaaS 斷裂的兩條縫
問任何一個把行動應用焊接到 Web SaaS 上的團隊真正疼在哪,答案永遠不是 UI。是身分和錢:在瀏覽器裡乾淨回跳的 OAuth 流程,必須透過 Deep Link 跳回應用內;而在 Web 上付過款的客戶,期望權益立刻出現在手機裡。
團隊通常在上線過兩個半成品之後才發現這一點:在 WKWebView 裡悄悄失效的 Cookie 邏輯,以及與 Web 資料庫裡 Stripe 訂閱互相打架的 RevenueCat 權益。修復是架構層面的,而且是同一個修復用兩次——一個身分模型,一個權益儲存。
一個 Better Auth 實例,三種工作階段傳輸
supastack 在 @supastack/auth 中保留單一的 Better Auth 設定,為每個端面提供不同入口。兩個 Web 應用(Next.js 16 與 TanStack Start)使用 HttpOnly、SameSite=Lax 的 Cookie 工作階段——預設防 CSRF 且與 Server Components 天然契合。Expo 應用在 Deep Link 回呼結束時把 OAuth 或魔法連結的完成態換成 Bearer Token,持久化到 expo-secure-store(iOS Keychain / Android Keystore),隨後以 Authorization 標頭傳送,由同一個認證中介軟體校驗。
Tauri 的桌面殼是一個指向 Web 應用的單 Webview,因此直接繼承 Web 工作階段——沒有第三條認證流程要維護。行動端認證指南與 Deep Link 指南 記載了回呼契約;我們的 Web + 行動 Monorepo 指南 演示了共享用戶端程式碼。
// packages/auth/src/client.ts — one client, two storages
import { createAuthClient } from "better-auth/react";
import { expoClient } from "@better-auth/expo/client";
export function createCrossPlatformAuthClient(baseURL: string, storage?: any) {
return createAuthClient({
baseURL,
plugins: storage ? [expoClient({ scheme: "myapp", storage })] : [],
});
}
// Web: cookie session. Mobile: bearer token in SecureStore.
// Desktop: the web app's own session inside the Tauri webview.八家支付閘道,同一份契約
每一家 Web 支付商——Stripe、Lemon Squeezy、Polar、Creem、Dodo、Paddle、Whop 與 PayPal——都接入同一個 @supastack/billing 契約,每一條簽名 webhook 都先落進冪等的 webhook_event 帳本,才被允許觸碰權益。服務商重試與亂序送達在資料庫邊界變成無害空操作,而不是客服工單。
行動端內購透過 RevenueCat 匯入同一本帳:商店收據在伺服端校驗,權益寫到工作區而非裝置上——在 iOS 付過款的使用者,在 Web 與桌面端立刻同樣是已付費。RevenueCat 指南講 App Store / Play 的接線;冪等計費 webhook 解釋為什麼帳本才是承重件。
讓同步變得無聊的權益模型
這件事之所以能維持無聊,是因為權益放在工作區上、由伺服端解析。沒有任何用戶端儲存「已付費」——Web 問工作階段、行動端問 API、桌面端問 Web 應用——三者拿到同一個答案,因為只有一份記錄可答。
新手機上的恢復購買、Web 上的 Stripe 續費、後台裡新增的 Agency 席位——每一筆都是寫進同一些權益行,每個端面下次詢問時讀到它。沒有同步引擎可建,因為根本沒有東西需要同步。
| 端面 | 工作階段傳輸 | 支付路徑 | 權益讀取自 |
|---|---|---|---|
| Next.js 16 Web | HttpOnly Cookie | 8 家閘道任一 → webhook 帳本 | 共享 Postgres 權益行 |
| TanStack Start Web | HttpOnly Cookie | 同一批轉接器,同一本帳 | 共享 Postgres 權益行 |
| Expo iOS / Android | expo-secure-store 中的 Bearer Token | RevenueCat 內購 → 伺服端校驗收據 | 同一批行(經型別化 API) |
| Tauri 2 桌面端 | Webview 內的 Web 工作階段 | 殼內直接走 Web 收銀台 | 同一批行(經 Web 應用) |
| MV3 擴充套件 | 工作區 API 金鑰 | —(讀取工作區資料) | 同一批行(經 /api/v1) |
你省下的開發量
按業餘晚上的時間折算,這就是「地基」與「功能清單」的差別:Deep Link 登入回跳、SecureStore 權杖持久化、八個帶重送安全的 webhook 整合、App Store 收據校驗,以及一個跨裝置永不自相矛盾的權益模型。每一項都已交付、已測試(693+ 測試免憑證可跑)、已寫進文件。
$299 的 Full Bundle 在同一個倉庫裡包含全部端面——席位與外包檔位見 定價頁。
常見問題:跨平台共享認證與支付
團隊在押注統一技術棧之前常問的問題:
- 行動端使用者要脫離 Web 單獨登入嗎?, 不用。OAuth 或魔法連結流程透過 Deep Link 回到應用並簽發同一個工作階段;簽發方是同一個 Better Auth 實例,所以 Web 與行動端對「你是誰」答案一致。
- 有人在 iOS 上付款卻用 Web 端怎麼辦?, RevenueCat 在伺服端送達這筆購買;權益寫進 Web 讀取的同一批工作區行,Web 端下一次請求就顯示已付費。
- 能先只做 Web、之後再上應用嗎?, 能——認證與計費都在共享套件裡,行動端和桌面端應用在你開啟這些端面時直接繼承它們。
- Tauri 應用需要自己的收銀台嗎?, 不需要——桌面殼在 Webview 內複用 Web 應用的工作階段與收銀台,沒有第二個支付端面需要設防。