跳轉到內容
Supastack
TW
主題
登入獲取終身訪問權
全部文章

在 Next.js、Expo 行動端與 Tauri v2 之間共享認證與 8 種支付閘道

跨端 SaaS 最難的兩條縫:行動端的 Deep Link 登入回呼,以及讓 Web 支付、RevenueCat 內購與桌面收款共用一份權益。一個 Monorepo 如何同時解決兩者。

Noah Zixin Zhang約 4 分鐘閱讀

如何在 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 WebHttpOnly Cookie8 家閘道任一 → webhook 帳本共享 Postgres 權益行
TanStack Start WebHttpOnly Cookie同一批轉接器,同一本帳共享 Postgres 權益行
Expo iOS / Androidexpo-secure-store 中的 Bearer TokenRevenueCat 內購 → 伺服端校驗收據同一批行(經型別化 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 應用的工作階段與收銀台,沒有第二個支付端面需要設防。

下一個產品,從這裡開始。

一次付費,持續打造盈利的產品。