Połączenie błyskawiczne
Flash Call to metoda weryfikacji telefonu, która wykorzystuje nieodebrane połączenie zamiast SMS-a do weryfikacji numerów telefonów. Jest to szybsze, bezpieczniejsze i tańsze rozwiązanie.
Przegląd
Weryfikacja połączenia Flash działa poprzez:
- Użytkownik prosi o weryfikację
- System inicjuje połączenie na telefon użytkownika
- Połączenie zostaje automatycznie zakończone po 1-2 dzwonkach
- Aplikacja użytkownika rejestruje identyfikator dzwoniącego
- Identyfikator dzwoniącego jest weryfikowany zgodnie z oczekiwanym wzorcem
- Użytkownik zostaje uwierzytelniony
Korzyści
Opłacalne
- Do 10x taniej niż SMS
- Brak opłat za dostarczenie wiadomości
- Obniżone koszty weryfikacji masowej
Szybciej
- Natychmiastowa weryfikacja (1-3 sekundy)
- Nie trzeba czekać na dostarczenie wiadomości SMS
- Lepsze doświadczenie użytkownika
Bardziej bezpieczne
- Trudniejsze do przechwycenia niż SMS
- W powiadomieniach nie widać hasła jednorazowego
- Odporność na ataki typu SIM Swap
Globalny zasięg
- Działa w krajach, w których obowiązują ograniczenia dotyczące SMS-ów
- Brak problemów z filtrowaniem SMS-ów
- Uniwersalna kompatybilność z telefonem
Podstawowe połączenie błyskawiczne
Żądanie
{
"from": "YourApp",
"to": "+380XXXXXXXXX",
"type": "flashcall",
"messageData": {
"callerId": "+380123456789"
}
}
Parametry
| Parametr | Wpisz | Wymagane | Opis |
|---|---|---|---|
od | ciąg | Tak | Twój identyfikator nadawcy |
do | ciąg | Tak | Numer telefonu odbiorcy (E.164) |
typ | ciąg | Tak | Ustaw na "flashcall" |
Identyfikator dzwoniącego | ciąg | Tak | Numer telefonu, z którego będziemy dzwonić do użytkownika |
ttl | liczba całkowita | Nie | Czas życia w sekundach (domyślnie: 60) |
Jak to działa
1. Użytkownik wprowadza numer telefonu
Użytkownik podaje swój numer telefonu w Twojej aplikacji:
Phone: +380XXXXXXXXX
2. Poproś o połączenie błyskawiczne
Twój serwer żąda weryfikacji połączenia flash:
curl -X POST https://restapi.smsbat.com/bat/messagelist \
-H "X-Authorization-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"messages": [{
"from": "YourApp",
"to": "+380XXXXXXXXX",
"type": "flashcall",
"messageData": {
"callerId": "+380123456789"
},
"ttl": 60
}]
}'
3. Odpowiedź API
API zwraca oczekiwany wzorzec identyfikatora dzwoniącego:
{
"messagelistId": 123456,
"messages": [
{
"messageId": "abc123def456",
"status": "accepted",
"callerId": "+380123456789",
"pattern": "***456789",
"to": "+380XXXXXXXXX"
}
]
}
4. Zainicjuj połączenie
System inicjuje połączenie na telefon użytkownika i kończy po 1-2 dzwonkach.
5. Przechwyć identyfikator dzwoniącego
Aplikacja użytkownika przechwytuje identyfikator rozmówcy przychodzącego połączenia:
// Android example
val cursor = contentResolver.query(
CallLog.Calls.CONTENT_URI,
arrayOf(CallLog.Calls.NUMBER),
null, null,
CallLog.Calls.DATE + " DESC"
)
6. Sprawdź wzór
Porównaj przechwycony identyfikator rozmówcy z oczekiwanym wzorcem:
// JavaScript example
function verifyFlashCall(callerId, pattern) {
// Remove non-digits
const callerDigits = callerId.replace(/\D/g, '');
const patternDigits = pattern.replace(/\*/g, '.');
// Check if matches pattern
const regex = new RegExp(patternDigits);
return regex.test(callerDigits);
}
Przykłady implementacji
Androida
class FlashCallVerification {
fun requestFlashCall(phoneNumber: String) {
// 1. Request flash call from API
val response = api.requestFlashCall(phoneNumber)
val pattern = response.pattern
// 2. Wait for incoming call
val callReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == TelephonyManager.ACTION_PHONE_STATE_CHANGED) {
val state = intent.getStringExtra(TelephonyManager.EXTRA_STATE)
if (state == TelephonyManager.EXTRA_STATE_RINGING) {
val callerId = intent.getStringExtra(
TelephonyManager.EXTRA_INCOMING_NUMBER
)
// 3. Verify caller ID against pattern
if (verifyPattern(callerId, pattern)) {
onVerificationSuccess()
}
}
}
}
}
// Register receiver
context.registerReceiver(
callReceiver,
IntentFilter(TelephonyManager.ACTION_PHONE_STATE_CHANGED)
)
}
private fun verifyPattern(callerId: String?, pattern: String): Boolean {
if (callerId == null) return false
val regex = pattern.replace("*", "\\d").toRegex()
return regex.matches(callerId)
}
}
iOS
class FlashCallVerification {
func requestFlashCall(phoneNumber: String) {
// 1. Request flash call from API
api.requestFlashCall(phoneNumber) { response in
let pattern = response.pattern
// 2. Use CallKit to detect incoming call
let provider = CXProvider(configuration: providerConfiguration)
provider.setDelegate(self, queue: nil)
// Store pattern for verification
self.expectedPattern = pattern
}
}
// CallKit delegate
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
// Capture caller ID
let callerId = action.callUUID.uuidString
// Verify against pattern
if verifyPattern(callerId: callerId, pattern: expectedPattern) {
onVerificationSuccess()
}
action.fulfill()
}
private func verifyPattern(callerId: String, pattern: String) -> Bool {
let regex = try! NSRegularExpression(
pattern: pattern.replacingOccurrences(of: "*", with: "\\d")
)
let range = NSRange(location: 0, length: callerId.count)
return regex.firstMatch(in: callerId, range: range) != nil
}
}
Sieć (po stronie serwera)
// Node.js example
const express = require('express');
const app = express();
app.post('/request-verification', async (req, res) => {
const { phoneNumber } = req.body;
// 1. Request flash call
const response = await fetch('https://restapi.smsbat.com/bat/messagelist', {
method: 'POST',
headers: {
'X-Authorization-Key': process.env.SMSBAT_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
messages: [{
from: 'YourApp',
to: phoneNumber,
type: 'flashcall',
messageData: {
callerId: process.env.FLASH_CALL_NUMBER
},
ttl: 60
}]
})
});
const data = await response.json();
const { messageId, pattern } = data.messages[0];
// 2. Store pattern for verification
await redis.setex(`flashcall:${messageId}`, 60, pattern);
// 3. Return pattern to client
res.json({ messageId, pattern });
});
app.post('/verify-flashcall', async (req, res) => {
const { messageId, callerId } = req.body;
// 1. Get expected pattern
const pattern = await redis.get(`flashcall:${messageId}`);
if (!pattern) {
return res.status(400).json({ error: 'Verification expired' });
}
// 2. Verify caller ID
const regex = new RegExp(pattern.replace(/\*/g, '\\d'));
const isValid = regex.test(callerId);
if (isValid) {
// Mark phone as verified
await markPhoneVerified(callerId);
res.json({ verified: true });
} else {
res.status(400).json({ error: 'Invalid caller ID' });
}
});
##Format odpowiedzi
Odpowiedź pomyślna
{
"messagelistId": 123456,
"messages": [
{
"messageId": "abc123def456",
"status": "accepted",
"callerId": "+380123456789",
"pattern": "***456789",
"to": "+380XXXXXXXXX",
"ttl": 60
}
]
}
Pola odpowiedzi
| Pole | Wpisz | Opis |
|---|---|---|
Identyfikator wiadomości | ciąg | Unikalny identyfikator weryfikacyjny |
stan | ciąg | Status: „zaakceptowany”, „odrzucony” |
Identyfikator dzwoniącego | ciąg | Pełny numer identyfikacyjny rozmówcy |
wzór | ciąg | Wzór do dopasowania (cyfry + gwiazdki) |
do | ciąg | Numer telefonu odbiorcy |
ttl | liczba całkowita | Okres ważności w sekundach |
Dopasowanie wzorca
API zwraca wzór z gwiazdkami maskującymi niektóre cyfry:
Full number: +380123456789
Pattern: ***456789
Twoja aplikacja powinna:
- Przechwyć identyfikator rozmówcy przychodzącego
- Wyodrębnij cyfry z identyfikatora dzwoniącego
- Dopasuj do wzorca (gwiazdki = dowolna cyfra)
- Sprawdź dopasowanie w okresie TTL
Powrót do SMS-ów
Jeśli połączenie Flash nie powiedzie się, automatycznie powróć do wiadomości SMS:
{
"messages": [
{
"from": "ALPHANAME",
"to": "380936670003",
"type": "flashcall",
"text": 321,
"ttl": 30,
"fallbacks": [
{
"from": "ALPHANAME",
"to": "380936670003",
"type": "viber_otp",
"text": "",
"ttl": 90,
"messageData": {
"templateId": "6c929cef-29b4-4349-bc9d-2a07bdbb6e43",
"templateLang": "uk",
"templateParams": {
"pin": 321,
"business_platform_name": "SMSBAT",
"code_validity_time": 7
}
}
},
{
"from": "ALPHANAME",
"to": "380936670003",
"type": "sms",
"text": "Your SMS code: 321"
}
]
}
]
}
Przypadki użycia
Rejestracja konta
Weryfikuj numery telefonów podczas rejestracji bez opłat za SMS-y.
Weryfikacja logowania
Uwierzytelnianie dwuskładnikowe za pomocą połączenia flash.
Aktualizacja numeru telefonu
Zweryfikuj nowy numer telefonu, gdy użytkownik zaktualizuje profil.
Potwierdzenie transakcji
Potwierdzaj transakcje o dużej wartości za pomocą połączenia błyskawicznego.
Najlepsze praktyki
TTL
- ✅ Ustaw TTL na 60-90 sekund
- ✅ Zezwalaj użytkownikowi na ponowną próbę po wygaśnięciu
- ❌ Nie używaj TTL dłuższego niż 120 sekund
Doświadczenie użytkownika
- Pokaż komunikat „Oczekiwanie na połączenie…”
- Wyświetl licznik czasu (60 sekund)
- Zapewnij opcję „Zamiast tego użyj SMS-a”
- Automatyczne wykrywanie i weryfikowanie identyfikatora dzwoniącego
Obsługa błędów
- Zajmij się brakującymi uprawnieniami telefonu
- Limit czasu po wygaśnięciu TTL
- Zapewnij opcję zastępczego SMS-a
- Pokaż jasne komunikaty o błędach
Uprawnienia
Poproś o uprawnienia telefonu przed rozmową flashową:
Android:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
iOS:
<key>NSPhoneCallUsageDescription</key>
<string>We need phone access to verify your number</string>
Testowanie
- Testuj na różnych urządzeniach
- Przetestuj z różnymi przewoźnikami
- Scenariusze odmowy pozwolenia na testowanie
- Przetestuj scenariusze przekroczenia limitu czasu sieci
Ograniczenia
Obsługa platformy
- Działa na wszystkich urządzeniach mobilnych
- Wymaga możliwości prowadzenia rozmów telefonicznych
- Wymaga pozwolenia READ_PHONE_STATE
- Może nie działać na tabletach bez telefonu
Sieć
- Wymaga aktywnego połączenia telefonicznego
- Może zawieść w złych warunkach sieciowych
- Mogą obowiązywać ograniczenia przewoźnika
- Stawki międzynarodowe mogą się różnić
Prywatność
- Użytkownicy mogą blokować nieznane numery
- Niektóre urządzenia mają blokowanie połączeń
- Wymaga wyraźnych uprawnień
- Weź pod uwagę obawy dotyczące prywatności użytkowników
Rozwiązywanie problemów
Połączenie nieodebrane
- Sprawdź, czy telefon ma sygnał
- Sprawdź format numeru (E.164)
- Sprawdź ograniczenia przewoźnika
- Spróbuj zastępczej wiadomości SMS
Wzór nie pasuje
- Upewnij się, że przechwytujesz prawidłowy identyfikator dzwoniącego
- Usuń znaki niecyfrowe
- Sprawdź format wzoru
- Sprawdź w okresie TTL
Odmowa pozwolenia
- Zapytaj o uprawnienia prawidłowo
- Wyjaśnij, dlaczego potrzebne są uprawnienia
- Zapewnij alternatywę (SMS)
- Postępuj elegancko
Następne kroki
- Viber OTP – Alternatywna dostawa OTP
- Wiadomości SMS – zastępcza wiadomość SMS
- Sprawdź status - Śledź status połączenia flash