> ## Documentation Index
> Fetch the complete documentation index at: https://supastack.dev/llms.txt
> Use this file to discover all available pages before exploring further.
> For the full documentation corpus in one file, fetch: https://supastack.dev/llms-full.txt

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

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

_釋出於 2026-11-07._
_更新於 2026-11-07._

> **如何在 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 工作階段——沒有第三條認證流程要維護。[行動端認證指南](https://supastack.dev/zh-tw/docs/mobile/authentication.md)與 [Deep Link 指南](https://supastack.dev/zh-tw/docs/mobile/deep-links.md) 記載了回呼契約；我們的 [Web + 行動 Monorepo 指南](https://supastack.dev/zh-tw/blog/web-and-mobile-saas-nextjs-expo.md) 演示了共享用戶端程式碼。

```
// 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 指南](https://supastack.dev/zh-tw/docs/mobile/revenuecat.md)講 App Store / Play 的接線；[冪等計費 webhook](https://supastack.dev/zh-tw/blog/idempotent-billing-webhooks.md) 解釋為什麼帳本才是承重件。


## 讓同步變得無聊的權益模型

這件事之所以能維持無聊，是因為權益放在工作區上、由伺服端解析。沒有任何用戶端儲存「已付費」——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 在同一個倉庫裡包含全部端面——席位與外包檔位見 [定價頁](https://supastack.dev/#pricing)。


## 常見問題：跨平台共享認證與支付

團隊在押注統一技術棧之前常問的問題：

- 行動端使用者要脫離 Web 單獨登入嗎?, 不用。OAuth 或魔法連結流程透過 Deep Link 回到應用並簽發同一個工作階段；簽發方是同一個 Better Auth 實例，所以 Web 與行動端對「你是誰」答案一致。
- 有人在 iOS 上付款卻用 Web 端怎麼辦?, RevenueCat 在伺服端送達這筆購買；權益寫進 Web 讀取的同一批工作區行，Web 端下一次請求就顯示已付費。
- 能先只做 Web、之後再上應用嗎?, 能——認證與計費都在共享套件裡，行動端和桌面端應用在你開啟這些端面時直接繼承它們。
- Tauri 應用需要自己的收銀台嗎?, 不需要——桌面殼在 Webview 內複用 Web 應用的工作階段與收銀台，沒有第二個支付端面需要設防。
