跳轉到主要內容

Documentation Index

Fetch the complete documentation index at: https://docs.superun.com/llms.txt

Use this file to discover all available pages before exploring further.

superun SMS Provider

superun 雲計算 預設已經為你啟用手機登入並配置好 send_sms 鉤子,可直接使用;如果希望走自家簡訊通道,也可以配置自訂 Webhook 接管。

客戶端整合

無論使用預設 Provider 還是自訂 Provider,客戶端代碼完全一致:
import { supabase } from "@/integrations/supabase/client";

// 發送 OTP
async function sendOTP(phone: string) {
  const { data, error } = await supabase.auth.signInWithOtp({ phone });
  if (error) throw new Error(error.message);
  return data;
}

// 驗證 OTP
async function verifyOTP(phone: string, token: string) {
  const { data, error } = await supabase.auth.verifyOtp({
    phone,
    token,
    type: "sms",
  });
  if (error) throw new Error(error.message);
  return data;
}
使用流程:
  1. 用戶點擊「發送驗證碼」時調用 sendOTP(phone),平台或你的自訂 Webhook 會收到事件並下發簡訊
  2. 用戶填入收到的驗證碼後調用 verifyOTP(phone, token) 完成驗證

預設 Provider(推薦)

開通 superun 雲計算 後手機登入已自動啟用,無需任何額外操作,適合絕大多數場景,零維運成本。

自訂 Provider(進階)

適用場景:希望使用自家簡訊通道、按國家/電信業者分流、出海合規要求自建發送鏈路等。 啟用後,Supabase 會把 send_sms 事件簽名轉發到你提供的 Webhook,由你的服務調用最終的簡訊通道(阿里雲/騰訊雲/Twilio 等)下發驗證碼。

1. 在控制台設定自訂 Hook

進入專案 superun雲計算 → 身分驗證設定 → 電話 Provider,展開 自訂 SMS Hook 卡片: superun雲計算 電話登入 填寫兩個欄位:
  • Hook URI:你部署的 Webhook 接口位址,必須是 https://
  • Hook Secret:用於驗證 Webhook 請求簽名的密鑰。點擊右側 隨機產生 按鈕產生符合 v1,whsec_<base64> 格式的密鑰,再用 複製 按鈕把它保存到你自己的服務設定裡
設定webhook
兩個欄位必須同時填寫或同時留空。留空則繼續使用平台預設 Hook,要回退到預設 Provider 直接清空兩個欄位並儲存即可。
儲存後,下一次手機登入的 OTP 事件就會被轉發到你的 Webhook。

2. 實作 Webhook 服務

下面是一個最小化的 Express 範例,演示如何接收 Supabase 的 send_sms 事件、驗證簽名、提取手機號與驗證碼,再轉交給你自己的簡訊通道。 簽名驗證使用的是 Supabase 官方推薦的 standardwebhooks 套件(與 superun 平台預設 Hook 使用同一套規範),先安裝相依套件:
npm install express standardwebhooks
# 如果使用 TypeScript
npm install -D @types/express
import express from "express";
import { Webhook } from "standardwebhooks";

const app = express();

// 必須使用 raw body:standardwebhooks 是基於原始請求體計算簽名的,
// 先被 express.json() 反序列化後會導致驗證失敗
app.use("/webhook/send-sms", express.raw({ type: "application/json" }));

// 用控制台填寫的 Secret 初始化(去掉 v1,whsec_ 前綴)
const SECRET = process.env.SMS_HOOK_SECRET!.replace(/^v1,whsec_/, "");
const webhook = new Webhook(SECRET);

app.post("/webhook/send-sms", async (req, res) => {
  try {
    const verified = webhook.verify(
      req.body,
      req.headers as Record<string, string>
    ) as {
      user: { phone?: string; new_phone?: string };
      sms: { otp: string; phone?: string };
    };

    const { user, sms } = verified;
    let phone = sms?.phone || user?.new_phone || user?.phone || "";
    const otp = sms?.otp;

    if (!phone || !otp) {
      return res.status(400).json({ error: "missing phone or otp" });
    }
    // Supabase 通常會帶 + 號傳過來;按下游通道需要決定是否去掉
    if (phone.startsWith("+")) phone = phone.slice(1);

    // === 這裡替換成你自己的簡訊通道調用 ===
    await sendSmsViaYourGateway(phone, otp);

    return res.status(200).json({ success: true });
  } catch (err) {
    console.error("send-sms webhook failed", err);
    return res.status(401).json({ error: "invalid signature or payload" });
  }
});

async function sendSmsViaYourGateway(phone: string, code: string) {
  // TODO: 接入你的簡訊服務(阿里雲、騰訊雲、Twilio 等)
}

app.listen(3000, () => console.log("Webhook listening on :3000"));
要點:
  • 必須使用 raw bodyexpress.raw),先 JSON parse 會導致簽名驗證失敗;同一路由上不要再掛 express.json(),它會把 body 解析成物件、覆蓋 raw 位元組
  • Secret 傳給 standardwebhooks 時務必去掉 v1,whsec_ 前綴
  • 簽名相關的 header(webhook-id / webhook-timestamp / webhook-signature)由 Express 統一規範化為小寫,standardwebhooks 內部也按小寫讀取,直接傳 req.headers 即可;如果中間走了反向代理或 APM,要確認它們沒有改寫 body 位元組或丟掉這三個 header
  • 該接口必須以 HTTPS 對外暴露(控制台也會驗證 https://
  • 驗證失敗一律回傳 4xx,避免 Supabase 誤判已下發

3. 聯調驗證

完成上面兩步後,在你的應用裡走一遍 signInWithOtp(phone),確認:
  1. Webhook 服務收到請求且簽名驗證通過
  2. 你的簡訊通道確實下發了驗證碼
  3. 用戶輸入驗證碼後 verifyOtp 回傳成功

運作方式

無論是預設還是自訂 Provider,鏈路都一樣:
  1. 客戶端調用 signInWithOtp({ phone })
  2. Supabase 生成 OTP 並觸發 send_sms 鉤子
  3. 鉤子帶簽名 POST 到 Webhook 位址(預設 = superun Gateway;自訂 = 你部署的服務)
  4. Webhook 驗證簽名後調用底層簡訊通道下發驗證碼
  5. 用戶輸入驗證碼,客戶端 verifyOtp 完成驗證
預設 Provider 下的 Edge Function、簽名密鑰、SMS 閘道整合都由 superun 雲計算 自動維護,你只需要關心客戶端流程。自訂 Provider 下,你額外負責 Webhook 服務與簡訊通道的穩定性。