Automatyczne wpisywanie kodu z SMS
Kod weryfikacyjny wysyłany SMS-em (logowanie numerem telefonu, rezerwacja bez konta, zapis na zajęcia próbne, potwierdzanie numeru w profilu) może zostać wpisany przez telefon jednym dotknięciem, zamiast przepisywania sześciu cyfr z powiadomienia.
👤 Instrukcja dla klienta
iPhone
Po otrzymaniu SMS-a nad klawiaturą pojawia się podpowiedź z kodem — wystarczy ją dotknąć. Podpowiedź działa zarówno w Safari, jak i w aplikacji AcePark.
Android
Chrome pokazuje okienko „Czy chcesz wypełnić kod?”. Po potwierdzeniu pole wypełnia się samo i weryfikacja rusza dalej bez dodatkowego kliknięcia.
Kiedy podpowiedź się nie pojawi
- Gdy kod jest przepisywany na innym urządzeniu niż to, które dostało SMS-a.
- Gdy strona jest otwarta w przeglądarce innej niż Safari (iOS) lub Chrome (Android).
- Gdy kalendarz rezerwacji jest osadzony jako ramka na stronie zewnętrznej — podpowiedź obejmuje wtedy tylko domenę samej ramki.
🔧 Dokumentacja techniczna
Treść SMS-a
sendVerificationSms w lib/sms.ts buduje
wiadomość w formacie, którego szukają obie platformy — ostatnia linia to
@domena #kod:
Twój kod weryfikacyjny to: 034992
@klient.acepark.pl #034992
Domena musi być dokładnie tym hostem, na którym klient wpisuje kod. Nie ma
dopasowania po masce ani dziedziczenia z domeny nadrzędnej: @acepark.pl nie
zadziała na klient.acepark.pl. Co ważniejsze, sam ten format wyłącza
heurystyczne wykrywanie kodu w iOS — niepasująca domena jest gorsza niż brak
tej linii, bo nie zostaje żaden mechanizm zapasowy.
Dlatego domena czytana jest z nagłówka host bieżącego żądania, a nie ze
zmiennej BETTER_AUTH_URL, która potrafi wskazywać inny host niż ten otwarty w
przeglądarce (w środowisku dev różniły się: klientdev.acepark.pl vs
dev.klient.acepark.pl). Poza kontekstem żądania — np. w cronie — helper wraca
do wartości ze zmiennej środowiskowej.
iOS: powiązanie aplikacji z domeną
W WebView aplikacji (Capacitor) podpowiedź wymaga zweryfikowanego powiązania domeny z aplikacją:
ios/App/App/App.entitlementsdeklarujewebcredentials:dla domeny klienta i dla domen deweloperskich,app/.well-known/apple-app-site-association/route.tsserwuje plik powiązania z nagłówkiemapplication/json,- middleware przepuszcza cały prefiks
/.well-known/bez sesji — Apple pobiera ten plik anonimowo i nie podąża za przekierowaniem, więc odesłanie na ekran logowania po cichu psuje całe powiązanie.
Sekcja applinks.details jest celowo pusta: universal links nigdy nie były na
tej domenie aktywne, a ich włączenie zaczęłoby przechwytywać wszystkie linki do
aplikacji.
Po zmianie domen w entitlements potrzebny jest nowy build aplikacji — iOS pobiera plik powiązania przy instalacji, nie przy każdym uruchomieniu.
Android: Web OTP API
Chrome nie reaguje na sam atrybut autocomplete="one-time-code" — strona musi
sama poprosić o kod. Robi to hook
hooks/useWebOtpAutofill.ts, wpięty w
współdzielony komponent components/ui/input-otp.tsx, więc obejmuje wszystkie
ekrany z kodem bez zmian w każdym z osobna.
Hook pyta o kod tylko wtedy, gdy przeglądarka wspiera OTPCredential i strona
jest w bezpiecznym kontekście, a przy odmontowaniu pola przerywa żądanie przez
AbortController. Aplikacja Android to TWA renderowane przez Chrome, więc
działa tam ten sam mechanizm co w przeglądarce.
Testy
| Plik | Co pokrywa |
|---|---|
__tests__/lib/sms.test.ts | domena z hosta żądania, obcięcie portu, fallback poza żądaniem, pozycja linii |
__tests__/middleware.well-known.test.ts | brak przekierowania /.well-known/ na logowanie |
__tests__/components/input-otp-web-otp.test.tsx | wywołanie Web OTP, przycięcie kodu do długości pola, brak wywołania bez wsparcia |