Preskočiť na obsah

Bleskový hovor

Flash Call je metóda telefonického overenia, ktorá na overenie telefónnych čísel používa namiesto SMS zmeškaný hovor. Je to rýchlejšie, bezpečnejšie a nákladovo efektívne.

Prehľad

Overenie Flash Call funguje takto:

  1. Používateľ požaduje overenie
  2. Systém inicializuje hovor na telefón užívateľa
  3. Hovor sa automaticky ukončí po 1-2 zvoneniach
  4. Aplikácia používateľa zachytáva ID volajúceho
  5. Identifikácia volajúceho je overená podľa očakávaného vzoru
  6. Používateľ je overený

Výhody

Nákladovo efektívne

  • Až 10x lacnejšie ako SMS
  • Žiadne poplatky za doručenie správ
  • Znížené náklady na overovanie veľkého objemu

Rýchlejšie

  • Okamžité overenie (1-3 sekundy)
  • Žiadne čakanie na doručenie SMS
  • Lepší používateľský zážitok

Bezpečnejšie

  • Ťažšie zachytiť ako SMS
  • Žiadne OTP viditeľné v upozorneniach
  • Odolné voči útokom na výmenu SIM karty

Globálny dosah

  • Funguje v krajinách s obmedzeniami SMS
  • Žiadne problémy s filtrovaním SMS
  • Univerzálna kompatibilita s telefónmi

Základný bleskový hovor

Žiadosť

{
  "from": "YourApp",
  "to": "+380XXXXXXXXX",
  "type": "flashcall",
  "messageData": {
    "callerId": "+380123456789"
  }
}

Parametre

Parameter Typ povinné Popis
"od" reťazec áno Váš identifikátor odosielateľa
"do" reťazec áno Telefónne číslo príjemcu (E.164)
"typ" reťazec áno Nastaviť na "flashcall"
ID volajúceho reťazec áno Telefónne číslo, ktoré zavolá používateľovi
ttl celé číslo Nie Čas do žitia v sekundách (predvolené: 60)

Ako to funguje

1. Používateľ zadá telefónne číslo

Používateľ poskytne svoje telefónne číslo vo vašej aplikácii:

Phone: +380XXXXXXXXX

2. Požiadajte o bleskový hovor

Váš server požaduje overenie bleskovým hovorom:

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. Odozva API

API vracia očakávaný vzor ID volajúceho:

{
  "messagelistId": 123456,
  "messages": [
    {
      "messageId": "abc123def456",
      "status": "accepted",
      "callerId": "+380123456789",
      "pattern": "***456789",
      "to": "+380XXXXXXXXX"
    }
  ]
}

4. Začnite hovor

Systém zaháji hovor na telefón užívateľa a ukončí ho po 1-2 zvoneniach.

5. Zaznamenajte ID volajúceho

Aplikácia používateľa zachytáva ID volajúceho prichádzajúceho hovoru:

// Android example
val cursor = contentResolver.query(
    CallLog.Calls.CONTENT_URI,
    arrayOf(CallLog.Calls.NUMBER),
    null, null,
    CallLog.Calls.DATE + " DESC"
)

6. Overte vzor

Porovnajte zachytené ID volajúceho s očakávaným vzorom:

// 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);
}

Príklady implementácie

Android

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
    }
}

Web (na strane servera)

// 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' });
  }
});

Formát odpovede

Úspešná odpoveď

{
  "messagelistId": 123456,
  "messages": [
    {
      "messageId": "abc123def456",
      "status": "accepted",
      "callerId": "+380123456789",
      "pattern": "***456789",
      "to": "+380XXXXXXXXX",
      "ttl": 60
    }
  ]
}

Polia odpovedí

Pole Typ Popis
messageId reťazec Jedinečné overovacie ID
"stav" reťazec Stav: prijatý, odmietnutý
ID volajúceho reťazec Úplné identifikačné číslo volajúceho
"vzor" reťazec Vzor na zhodu (číslice + hviezdičky)
"do" reťazec Telefónne číslo príjemcu
ttl celé číslo Doba platnosti v sekundách

Zhoda vzorov

Rozhranie API vracia vzor s hviezdičkami, ktoré maskujú niektoré číslice:

Full number: +380123456789
Pattern:     ***456789

Vaša aplikácia by mala:

  1. Zaznamenajte ID prichádzajúceho volajúceho
  2. Extrahujte číslice z ID volajúceho
  3. Porovnajte so vzorom (hviezdičky = ľubovoľná číslica)
  4. Overte zhodu v rámci obdobia TTL

Náhrada na SMS

Ak Flash Call zlyhá, automaticky sa vráťte k SMS:

{
  "from": "YourApp",
  "to": "+380XXXXXXXXX",
  "type": "flashcall",
  "messageData": {
    "callerId": "+380123456789"
  },
  "fallback": {
    "type": "sms",
    "text": "Your verification code is: 123456"
  },
  "ttl": 60
}

Prípady použitia

Registrácia účtu

Overte telefónne čísla počas registrácie bez poplatkov za SMS.

Overenie prihlásenia

Dvojfaktorová autentifikácia pomocou bleskového hovoru.

Aktualizácia telefónneho čísla

Overte nové telefónne číslo, keď používateľ aktualizuje profil.

Potvrdenie transakcie

Potvrďte transakcie s vysokou hodnotou pomocou bleskového hovoru.

Osvedčené postupy

TTL

  • ✅ Nastavte TTL na 60-90 sekúnd
  • ✅ Umožnite používateľovi opakovať pokus po uplynutí platnosti
  • ❌ Nepoužívajte TTL dlhšie ako 120 sekúnd

Používateľská skúsenosť

  • Zobraziť správu „Čaká sa na hovor...“.
  • Zobrazte časovač odpočítavania (60 sekúnd)
  • Poskytnite možnosť „Použiť namiesto toho SMS“
  • Automatická detekcia a overenie ID volajúceho

Spracovanie chýb

  • Vyriešte chýbajúce povolenia telefónu
  • Časový limit po vypršaní TTL
  • Poskytnite možnosť núdzovej správy SMS
  • Zobraziť jasné chybové hlásenia

Povolenia

Požiadajte o povolenia telefónu pred bleskovým hovorom:

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>

Testovanie

  • Test na rôznych zariadeniach
  • Testujte s rôznymi dopravcami
  • Testujte scenáre odmietnutia povolenia
  • Otestujte scenáre časového limitu siete

Obmedzenia

Podpora platformy

  • Funguje na všetkých mobilných zariadeniach
  • Vyžaduje možnosť telefonického hovoru – Vyžaduje sa povolenie READ_PHONE_STATE
  • Nemusí fungovať na tabletoch bez telefónu

Sieť

  • Vyžaduje aktívne telefónne pripojenie
  • Môže zlyhať v zlých podmienkach siete
  • Môžu platiť obmedzenia operátora
  • Medzinárodné sadzby sa môžu líšiť

Súkromie

  • Používatelia môžu blokovať neznáme čísla
  • Niektoré zariadenia majú blokovanie hovorov
  • Vyžaduje explicitné povolenia
  • Zvážte obavy o súkromie používateľov

Riešenie problémov

Hovor neprijatý

  • Skontrolujte, či má telefón signál – Overte formát čísla (E.164)
  • Skontrolujte obmedzenia operátora
  • Vyskúšajte záložnú SMS

Vzor sa nezhoduje

  • Zaistite správne zachytenie ID volajúceho
  • Odstráňte znaky, ktoré nie sú číslice
  • Skontrolujte formát vzoru
  • Overte v rámci obdobia TTL

Povolenie odmietnuté

  • Požiadajte správne o povolenia
  • Vysvetlite, prečo sú potrebné povolenia
  • Poskytnite alternatívu (SMS)
  • Zaobchádzajte s gráciou

Ďalšie kroky