• พิมพ์คำที่อยู่ในใจ เช่น “หมดเวลาชำระ” “ปล่อยโต๊ะ” “เครดิต”
← กลับแอป
วิธีทำ· แก้งานที่ต้องทำตอนนี้

ตั้งค่า Supabase ที่ต้องดูแล

อ่านจบแล้วลิงก์เชิญ/รีเซ็ต/ยืนยันอีเมลจะทำงาน เจ้าของร้านสมัครเองได้ และอีเมลส่งออกได้จริง

อัปเดตล่าสุด 2026-09-18 · เวอร์ชันแอป 0.1.0

อ่านจบแล้วคุณจะ

ลิงก์เชิญ/รีเซ็ต/ยืนยันอีเมลเปิดได้จากทุกเครื่อง เจ้าของร้านสมัครเองได้ (ADR-0009) และอีเมลของระบบส่งออกได้จริง

ทำที่ Supabase Dashboard ของโปรเจกต์ (สคริปต์ bash scripts/setup-deploy.sh พาทำครั้งแรก หน้านี้คือรายการที่ต้องคงไว้)

  1. Authentication → URL Configuration

    ต้องลงท้ายด้วย ** เพราะแอปส่ง ?next=/apply / ?next=/auth/reset-password ต่อท้าย — ถ้าใส่แบบไม่มี ** Supabase จะถือว่าไม่ตรงและตัด {{ .RedirectTo }} เหลือแค่ Site URL (ลิงก์ในอีเมลกลายเป็น …vercel.app&token_hash=… เปิดไม่ได้ — เจอจริง 7 ก.ย. 2569)

    Site URL = โดเมนแอป (ปัจจุบัน https://tablezups.com) · Redirect URLs มี `https://<แอป>/auth/callback**` และ `http://localhost:3000/auth/callback**` (ใส่โดเมนเก่าที่ยังใช้ด้วย)
  2. Authentication → Sign In / Providers → Email

    ตั้งแต่ 7 ก.ย. 2569 เจ้าของร้านสมัครเองที่ /signup แล้วยื่นคำขอเปิดร้าน (บัญชีใหม่ไม่มีสิทธิ์ใด ๆ จนกว่าคุณจะอนุมัติ) · Confirm email ต้องเปิด ไม่งั้นอีเมลปลอมสมัครได้ · CAPTCHA อยู่ในขั้นถัดไป (ไม่บังคับ เปิดเมื่อเจอสแปม)

    “Allow new users to sign up” = **เปิด** · “Confirm email” = เปิด
  3. (ไม่บังคับ) Attack Protection → CAPTCHA ด้วย Cloudflare Turnstile

    ทำเมื่อเจอสแปมสมัคร/ลองรหัสผ่าน — ลำดับห้ามสลับ:

    1. สร้าง widget ที่ Cloudflare Turnstile → Domain = โดเมนแอป (ใส่ localhost ด้วยถ้าจะทดสอบในเครื่อง) → Widget Mode: Managed
      • เปลี่ยนโดเมนเมื่อไหร่ ต้องกลับมาเพิ่มชื่อโฮสต์ใหม่ใน Hostname Management ของ widget ทุกครั้ง — ไม่งั้น Turnstile ตอบ error 110200 บนโดเมนใหม่ ช่องยืนยันขึ้นข้อความ “โหลดช่องยืนยันไม่สำเร็จ” และล็อกอินไม่ได้เลยทั้งระบบ (เจอจริงตอนย้ายมา tablezups.com — ADR-0033) · แก้แล้วมีผลทันที ไม่ต้อง redeploy เพราะ site key ไม่เปลี่ยน
    2. เอา Site key ใส่เป็น env NEXT_PUBLIC_TURNSTILE_SITE_KEY บน Vercel แล้ว redeploy ก่อน (ค่านี้ถูกฝังตอน build)
    3. ค่อยกลับมาเปิด Supabase → Authentication → Attack Protection → Enable CAPTCHA → Turnstile แล้วใส่ Secret key (secret อยู่ที่ Supabase เท่านั้น ไม่ต้องใส่ใน env ของแอป)

    ถ้าเปิดสวิตช์ใน Supabase ก่อน redeploy: ทุกคนจะสมัคร/ล็อกอิน/ขอรีเซ็ตไม่ได้ทันที เพราะแอปยังไม่ได้ส่ง token · ปิดกลับได้ทันทีที่ Supabase (โค้ดไม่ต้องแก้)

    เปิดแล้วต้องทดสอบ 3 อย่าง

    (1) สมัครใหม่ที่ /signup และเปิดลิงก์ยืนยันจากอีเมลจริง (2) ล็อกอินและ “ลืมรหัสผ่าน?” (3) ปุ่ม “ส่งอีเมลรีเซ็ต” ในหน้าทีมของร้านและหน้าผู้ใช้ทั้งระบบ — ปุ่มสองตัวหลังไม่มีช่องยืนยัน จึงส่งผ่านสิทธิ์ผู้ดูแล (service role) ถ้าเจอ “ส่งอีเมลรีเซ็ตไม่สำเร็จ” ให้ใช้ “สร้างลิงก์รีเซ็ต (ใช้ครั้งเดียว)” แทนแล้วแจ้งผู้พัฒนา

    หน้า /signup /login และ “ลืมรหัสผ่าน?” มีช่องยืนยัน “ไม่ใช่บอท” (ส่วนใหญ่ผู้ใช้ไม่เห็นอะไรเลย ผ่านเองอัตโนมัติ)
  4. Authentication → Email Templates เปลี่ยนลิงก์จาก {{ .ConfirmationURL }} เป็นรูปแบบ token_hash ที่สร้างจาก {{ .SiteURL }}
    • Confirm signup: {{ .SiteURL }}/auth/callback?next=/apply&token_hash={{ .TokenHash }}&type=signup
    • Reset Password: {{ .SiteURL }}/auth/callback?next=/auth/reset-password&token_hash={{ .TokenHash }}&type=recovery
    • Invite user: {{ .SiteURL }}/auth/callback?next=/auth/reset-password&token_hash={{ .TokenHash }}&type=invite
    • Magic Link: {{ .SiteURL }}/auth/callback?next=/me&token_hash={{ .TokenHash }}&type=magiclink

    ใช้ {{ .SiteURL }} ไม่ใช่ {{ .RedirectTo }} เพราะ RedirectTo จะถูกตัดเหลือ Site URL ทันทีที่ redirect ของแอปไม่ตรง allow list · free tier ที่ใช้ SMTP เริ่มต้นแก้เทมเพลตไม่ได้ ต้องตั้ง custom SMTP ก่อน (ขั้นถัดไป) · ถ้ายังใช้เทมเพลตเดิม ลิงก์ก็ยังทำงานผ่านหน้า /auth/finish แต่ต้องเปิดในเบราว์เซอร์ที่รัน JavaScript

    ลิงก์ตรวจฝั่งเซิร์ฟเวอร์ เปิดจากเครื่องไหนก็ได้ ไม่พึ่ง JavaScript และไม่พึ่ง allow list
  5. Project Settings → Authentication → SMTP Settings

    ค่าเริ่มต้นของ Supabase ส่งได้ประมาณ 3 ฉบับ/ชั่วโมงจาก noreply@mail.app.supabase.io — ไม่พอสำหรับใช้จริง และแก้เทมเพลตไม่ได้ · หลังตั้ง SMTP เอง rate limit อีเมลของ Supabase เป็น 30 ฉบับ/ชั่วโมง (Authentication → Rate Limits)

    ใช้ SMTP ของตัวเอง — ไม่มีโดเมน: Brevo (smtp-relay.brevo.com:587, user = อีเมลบัญชี, pass = SMTP key, ฟรี 300 ฉบับ/วัน) · มีโดเมน: Resend (smtp.resend.com:465, user resend, pass = API key)
  6. Storage
    bucket สำหรับรูปผัง/โลโก้ (public) สลิปมัดจำ `slips` สลิปค่าบริการ `billing` และรูปแชท `support` (private) มีอยู่ (สคริปต์ `scripts/setup-supabase-storage.ts` สร้างให้)

ถ้าเห็นข้อความนี้ (ที่ผู้ใช้รายงานมา)

ถ้าเห็นข้อความนี้แปลว่าให้ทำ
ลิงก์หมดอายุหรือยังไม่ได้เปิดจากอีเมล กรุณาขอลิงก์ใหม่ลิงก์เกิน 1 ชั่วโมง ถูกใช้แล้ว โดเมนไม่อยู่ใน Redirect URLs หรือเทมเพลตส่ง token มาในรูปแบบที่เซิร์ฟเวอร์ไม่เห็นตรวจขั้น 1 และ 3 · ระหว่างแก้ ใช้ “สร้างลิงก์รีเซ็ต (ใช้ครั้งเดียว)” จากหน้าทีม/ผู้ใช้ (ไม่พึ่งอีเมล)
ลิงก์ในอีเมลเป็น https://<แอป>&token_hash=… (ไม่มี /auth/callback) เปิดไม่ได้เทมเพลตใช้ {{ .RedirectTo }} แต่ redirect ของแอปไม่ตรง allow list จึงเหลือแค่ Site URLใช้เทมเพลตแบบ {{ .SiteURL }}/auth/callback?… ตามขั้น 3 และใส่ `**` ท้าย Redirect URLs
ยังไม่ได้ตั้งค่า Supabaseแอปไม่มี NEXT_PUBLIC_SUPABASE_URL/ANON_KEYตั้ง env แล้ว redeploy
ยืนยันว่าไม่ใช่บอทไม่สำเร็จ กรุณาโหลดหน้าใหม่แล้วลองอีกครั้งเปิด CAPTCHA ใน Supabase แล้ว แต่แอปส่ง token ไม่ได้ (ยังไม่ได้ตั้ง Site key/ยังไม่ redeploy, โดเมนที่เปิดอยู่ไม่ได้อยู่ใน Hostname Management ของ widget, หรือ token หมดอายุ)ถ้าเพิ่งเปลี่ยนโดเมน ให้เพิ่มโฮสต์ใหม่ใน Cloudflare Turnstile ก่อน (มีผลทันที) · ไม่ใช่กรณีนั้นให้ตรวจ `NEXT_PUBLIC_TURNSTILE_SITE_KEY` บน Vercel แล้ว redeploy · แก้ด่วนให้ปิด Attack Protection ที่ Supabase ก่อน · ตรวจอัตโนมัติ: `npx tsx scripts/check-captcha-live.ts https://<โดเมน>`
ระบบยังไม่เปิดให้สมัครเอง — ติดต่อผู้ดูแลระบบ“Allow new users to sign up” ยังปิดอยู่เปิดตามขั้น 2

หัวข้อที่เกี่ยวข้อง

หน้านี้ช่วยได้ไหม