WELIFE Docs Swagger Admin Web

OWNER gates — Google · Firebase · SMS · MoMo · EAS (WELIFE)

Snapshot tổng: STATUS.md (2026-08-14). Bạn đăng ký dịch vụ + lấy credential. Agent cấu hình code/IPN/smoke sau khi secret có sẵn. Không commit secret. Không đặt secret vào EXPO_PUBLIC_*. Paste map: OWNER-WIRE-CHECKLIST.md (WP-OWNER-WIRE-01).

Thứ tự khuyến nghị: Google → Firebase Admin SA → SMS OTP · VNPay e2e → MoMo sandbox.

Firebase Hybrid (IdP): OWNER-FIREBASE-HYBRID.md · project welife-2412.

Status snapshot (2026-08-14)

Gate Status Ghi chú
Google OAuth DONE WP-AUTH-GOOGLE-LIVE-01 IMP
Firebase public (mobile) WIRED EXPO_PUBLIC_FIREBASE_WEB_APP_ID SET (1:3032…:web:…) · Android id giữ trong google-services.json
Firebase Web + Auth deploy OWNER verify Web App ID đã wire · Auth/Firestore deploy vẫn cần firebase login nếu chưa làm
Code Auth+Firestore IMP WP-AUTH-FIREBASE-WEB-01 — Firebase-first + Nest JWT
Firebase Admin SA OWNER (optional) VPS/api/.env CLIENT_EMAIL/PRIVATE_KEY MISSING → bridge off (EXPO_PUBLIC_FIREBASE_BRIDGE=0)
SMS (eSMS) KEYS ON VPS SMS_PROVIDER=esms · brand WELIFE · ready 2026-08-14 · re-smoke PASS preflight 2026-08-19 · e2e OTP phone OWNER (no_sms)
VNPay sandbox CREATE PASS preferred · init 201 · re-smoke PASS 2026-08-17 · OWNER còn mở payUrl → thanh toán test → ví
MoMo sandbox CREATE FAIL Keys SET · create 400 merchant inactive · 2026-08-14 · không preferred
P7a harden (Swagger/Wallet) IMP /docs 404 · wallet credit false · sync ép lại mỗi deploy
Email OTP (Gmail SMTP) WIRED PROD VPS smtp.gmail.com:465 · mailSent=true · scripts/sync-gmail-smtp-vps.mjs · MAIL-DNS
OWNER wire checklist PARTIAL STATUS · Pay create PASS · MoMo FAIL · SMS e2e · EAS DONE
EAS cloud APK DONE CON+DRV+PAR preview · EAS-BUILD

Bạn làm tiếp (chọn 1):

  1. Pay VNPay: mở payUrl sandbox (app nạp ví) → thanh toán test → xác nhận ví + return
  2. SMS: OTP SĐT thật (eSMS) → xác nhận tin nhắn đến
  3. MoMo: sửa merchant sandbox trên portal rồi nhắn agent smoke lại
  4. EAS: cloud APK DONE CON+DRV+PAR — cài device · smoke login/API (EAS-BUILD)
  5. (Tuỳ chọn) Paste Firebase Admin SA nếu cần Nest /auth/firebase bridge

EAS cloud (WP-EAS-01 / DRV / PAR)

App Expo Status
CON welife-consumer APK ready — 845b6a3d
DRV welife-driver APK ready — 18716e82
PAR welife-partner APK ready — e0e55329

Windows: $env:NODE_OPTIONS='--use-system-ca' trước mọi eas / npx eas-cli. Chi tiết: EAS-BUILD.md.

0. Phân tách env (hard rule)

Surface Được phép Cấm
mobile/.env · .env.local Chỉ EXPO_PUBLIC_* (Client ID public, API URL) Mọi *_SECRET · MoMo keys · SMS keys · JWT
api/.env JWT, DB, Google audiences, MoMo, SMS, SMTP —
Git *.env.example .env / .env.local (đã gitignore)
.env
.env.*
!.env.example
!.env.*.example

1. Google Login (OWNER #1 — DONE)

Cloud Console

  1. Google Cloud Console → APIs & Services → Credentials
  2. Tạo OAuth 2.0 Client riêng cho từng nền tảng (Google khuyến nghị):
    • Web application
    • Android (package cloud.minhtien.welife + SHA-1)
    • iOS (bundle cloud.minhtien.welife)

WELIFE hiện tại = ID Token flow (không cần client secret)

App lấy Google idToken → POST /api/v1/auth/google → API verify audience bằng google-auth-library. Không dùng Authorization Code + GOOGLE_CLIENT_SECRET (trừ khi sau này đổi sang server-side code flow).

Redirect FE (OAuth Web client): https://auth.expo.io/@adminmarketingnx/welife-consumer. Không dùng welife://oauth (Google chặn custom scheme) và không dùng @…/welife (sai slug).

Env

# mobile/.env.local  (PUBLIC — Client ID không phải secret)
EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID=xxxx.apps.googleusercontent.com
EXPO_PUBLIC_GOOGLE_ANDROID_CLIENT_ID=xxxx.apps.googleusercontent.com
EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID=xxxx.apps.googleusercontent.com

# api/.env  (verify audience — thường = Web Client ID)
GOOGLE_CLIENT_ID=xxxx.apps.googleusercontent.com
# Tuỳ chọn thêm audience native + **Firebase OAuth Web client**
# (bắt buộc nếu login Google qua Firebase popup trên web — aud ≠ WELIFE Web Client):
# GOOGLE_CLIENT_IDS=web....,android....,ios....,3032…firebase-web….apps.googleusercontent.com
# GOOGLE_ANDROID_CLIENT_ID=
# GOOGLE_IOS_CLIENT_ID=

Cấm tuyệt đối:

EXPO_PUBLIC_GOOGLE_CLIENT_SECRET=...   # ❌ lộ trong APK

GOOGLE_CLIENT_SECRET / GOOGLE_REDIRECT_URI chỉ cần nếu sau này chuyển sang server Authorization Code — hiện không dùng.

Sau khi điền:

$env:NODE_OPTIONS='--use-system-ca'   # Windows TLS — bắt buộc để verify Google JWKS
npm run env:check
# restart API + npx expo start -c

Nếu /auth/google trả TLS/CA hoặc N audience attempt(s) failed dù Client ID đúng: API đang chạy không có --use-system-ca (corp AV MITM). npm run api:prod:local / start:prod:local đã tự gắn flag này. Agent: WP-AUTH-GOOGLE-LIVE-01 IMP (2026-08-10).


1b. Firebase Web app + Auth/Firestore deploy (OWNER #NEXT)

Chi tiết: OWNER-FIREBASE-HYBRID.md §0.

$env:NODE_OPTIONS='--use-system-ca'
npx -y firebase-tools@latest login --no-localhost
node scripts/firebase-owner-setup.mjs
# merge mobile/.env.firebase-web.snippet → mobile/.env.local

1c. Firebase Admin SA (optional — Nest /auth/firebase)

# api/.env
FIREBASE_CLIENT_EMAIL=
FIREBASE_PRIVATE_KEY=
# mobile/.env.local
EXPO_PUBLIC_FIREBASE_BRIDGE=1

Google login không bắt buộc bước này (Nest /auth/google).


2. SMS OTP (OWNER — READY keys · e2e thủ công)

VPS: SMS_PROVIDER=esms + ESMS_* SET · brand WELIFE · OWNER-SMS-READY-2026-08-14.

Owner bỏ qua tạm (local): SMS_PROVIDER=console + OTP email. Chốt go-live: eSMS (đang bật) · Twilio · HTTP bridge.

Flow an toàn

Mobile → POST /auth/.../otp → API generate + hash Redis → SMS provider → user
Mobile → POST verify → API verify  (Mobile KHÔNG gọi SMS provider)

Env (chỉ api/.env)

eSMS (khuyến nghị VN):

SMS_PROVIDER=esms
ESMS_API_KEY=
ESMS_SECRET_KEY=
ESMS_BRAND_NAME=WELIFE
ESMS_SMS_TYPE=2

Twilio (tên biến đúng code WELIFE):

SMS_PROVIDER=twilio
TWILIO_ACCOUNT_SID=
TWILIO_AUTH_TOKEN=
TWILIO_FROM_NUMBER=

Local: SMS_PROVIDER=console + email OTP (OTP_CHANNEL=email) vẫn OK.

Agent tiếp: WP-AUTH-SMS-01 e2e khi key sẵn (không schedule trước MoMo).


3. Pay live — VNPay sandbox PRIMARY (2026-08-10)

PAYMENTS_MOCK=false · default gateway VNPAY (preferred trên /payments/providers). Smoke: create → payUrl sandbox.vnpayment.vn · report.

# api/.env
PAYMENTS_MOCK=false
VNPAY_TMN_CODE=
VNPAY_HASH_SECRET=
VNPAY_URL=https://sandbox.vnpayment.vn/paymentv2/vpcpay.html
VNPAY_RETURN_URL=
# VNPAY_IPN / return cần URL public khi test callback đầy đủ

MoMo (OWNER — CREATE FAIL 2026-08-14)

MoMo env SET (sandbox + IPN public) nhưng gateway reject merchant — không preferred. Report: OWNER-MOMO-FAIL-2026-08-14.

Khi có key / merchant sandbox đúng:

MOMO_PARTNER_CODE=
MOMO_ACCESS_KEY=
MOMO_SECRET_KEY=
MOMO_ENV=sandbox
MOMO_ENDPOINT=https://test-payment.momo.vn/v2/gateway/api/create

Flow: App → API ký → cổng → IPN/return → PAID. Secret chỉ trên API.


4. Production split (tóm tắt)

Mobile — public only

EXPO_PUBLIC_ENV=production
EXPO_PUBLIC_API_URL=https://api.welife.cloud/api/v1
EXPO_PUBLIC_WS_URL=https://api.welife.cloud
EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID=
EXPO_PUBLIC_GOOGLE_ANDROID_CLIENT_ID=
EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID=

API — secrets

GOOGLE_CLIENT_ID=
# MoMo / SMS / JWT / DB — xem api/.env.production.example
PAYMENTS_MOCK=false
SMS_PROVIDER=esms
ALLOW_INTERNAL_WALLET_CREDIT=false

5. Stop-gate bảng

Gate OWNER làm Agent làm sau khi có key
Google OAuth Web/Android/iOS — DONE WP-AUTH-GOOGLE-LIVE-01 IMP
Firebase SA Service account JSON → api/.env Smoke POST /auth/firebase + bridge
SMS Chọn/đăng ký provider + key OTP send/verify e2e
Pay MoMo merchant + sandbox keys Payment + IPN + HMAC verify
Production Secret lên VPS (chmod 600) Deploy + smoke

Bạn không cần tự code ba phần này — chỉ đăng ký dịch vụ và đưa credential vào api/.env / mobile/.env.local (không commit).