Skoči na vsebino

Flash Call

Flash Call je način preverjanja telefona, ki za preverjanje telefonskih številk uporablja neodgovorjen klic namesto sporočila SMS. Je hitrejši, varnejši in stroškovno učinkovit.

Pregled

Hitro preverjanje klicev deluje tako:

  1. Uporabnik zahteva preverjanje
  2. Sistem sproži klic na uporabnikov telefon
  3. Klic se samodejno prekine po 1-2 zvonjenjih
  4. Uporabnikova aplikacija zajame ID klicatelja
  5. ID klicatelja se preveri glede na pričakovani vzorec
  6. Uporabnik je overjen

Prednosti

Stroškovno učinkovito

  • Do 10x ceneje kot SMS
  • Brez stroškov dostave sporočil
  • Zmanjšani stroški za preverjanje velikega obsega

Hitreje

  • Takojšnje preverjanje (1-3 sekunde)
  • Brez čakanja na dostavo SMS
  • Boljša uporabniška izkušnja

Bolj varno

  • Težje prestreči kot SMS
  • V obvestilih ni vidnega OTP-ja
  • Odporen na napade zamenjave kartice SIM

Globalni doseg

  • Deluje v državah z omejitvami SMS
  • Ni težav s filtriranjem SMS-ov
  • Univerzalna združljivost telefona

Osnovni bliskovni klic

Zahteva

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

Parametri

Parameter Vrsta Zahtevano Opis
od niz Da Vaš identifikator pošiljatelja
do niz Da Telefonska številka prejemnika (E.164)
tip niz Da Nastavite na "flashcall"
callerId niz Da Telefonska številka, ki bo poklicala uporabnika
ttl celo število Ne Življenjska doba v sekundah (privzeto: 60)

Kako deluje

1. Uporabnik vnese telefonsko številko

Uporabnik navede svojo telefonsko številko v vaši aplikaciji:

Phone: +380XXXXXXXXX

2. Zahtevajte hitri klic

Vaš strežnik zahteva hitro preverjanje klica:

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. Odziv API-ja

API vrne pričakovan vzorec ID klicatelja:

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

4. Začni klic

Sistem sproži klic na uporabnikov telefon in prekine po 1-2 zvonjenjih.

5. Zajemite ID klicatelja

Uporabnikova aplikacija zajame ID klicatelja dohodnega klica:

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

6. Preverite vzorec

Primerjajte zajeti ID klicatelja s pričakovanim vzorcem:

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

Primeri implementacije

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

Splet (strežniška stran)

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

Oblika odgovora

Uspešen odziv

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

Polja odgovora

Polje Vrsta Opis
id sporočila niz Enolični ID preverjanja
stanje niz Status: sprejeto, zavrnjeno
callerId niz Polna ID številka klicatelja
vzorec niz Vzorec za ujemanje (številke + zvezdice)
do niz Telefonska številka prejemnika
ttl celo število Obdobje veljavnosti v sekundah

Ujemanje vzorcev

API vrne vzorec z zvezdicami, ki prikrije nekaj števk:

Full number: +380123456789
Pattern:     ***456789

Vaša aplikacija bi morala:

  1. Zajemite ID dohodnega klicatelja
  2. Izvlecite številke iz ID-ja klicatelja
  3. Ujemanje z vzorcem (zvezdice = katera koli številka)
  4. Preverite ujemanje v obdobju TTL

Nazaj na SMS

Če Flash Call ne uspe, se samodejno vrnite na SMS:

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

Primeri uporabe

Registracija računa

Preverite telefonske številke med prijavo brez stroškov SMS-a.

Preverjanje prijave

Dvostopenjska avtentikacija z bliskovnim klicem.

Posodobitev telefonske številke

Preverite novo telefonsko številko, ko uporabnik posodobi profil.

Potrditev transakcije

Potrdite transakcije visoke vrednosti s hitrim klicem.

Najboljše prakse

TTL

  • ✅ Nastavite TTL na 60-90 sekund
  • ✅ Dovolite uporabniku, da po preteku poskusi znova
  • ❌ TTL ne uporabljajte dlje kot 120 sekund

Uporabniška izkušnja

  • Pokaži sporočilo "Čakanje na klic ...".
  • Prikaz odštevalnika časa (60 sekund)
  • Zagotovite možnost »Namesto tega uporabite SMS«
  • Samodejno zaznavanje in preverjanje ID-ja klicatelja

Obravnava napak

  • Obravnava manjkajoča dovoljenja za telefon
  • Časovna omejitev po poteku TTL
  • Zagotovite nadomestno možnost SMS
  • Prikaži jasna sporočila o napakah

Dovoljenja

Zahtevaj telefonska dovoljenja pred hitrim klicem:

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>

Testiranje

  • Test na različnih napravah
  • Test z različnimi nosilci
  • Preizkusite scenarije zavrnitve dovoljenja
  • Preizkusite scenarije časovne omejitve omrežja

Omejitve

Podpora za platformo

  • Deluje na vseh mobilnih napravah
  • Zahteva možnost telefoniranja
  • Potrebuje dovoljenje READ_PHONE_STATE
  • Morda ne bo delovalo na tablicah brez telefona

Omrežje

  • Zahteva aktivno telefonsko povezavo
  • Lahko odpove v slabih omrežnih razmerah
  • Morda veljajo omejitve operaterja
  • Mednarodne cene se lahko razlikujejo

Zasebnost

  • Uporabniki lahko blokirajo neznane številke
  • Nekatere naprave imajo blokiranje klicev
  • Zahteva izrecna dovoljenja
  • Upoštevajte pomisleke glede zasebnosti uporabnikov

Odpravljanje težav

Klic ni prejet

  • Preverite, ali ima telefon signal
  • Preverite obliko številke (E.164)
  • Preverite omejitve operaterja
  • Poskusite nadomestni SMS

Vzorec se ne ujema

  • Zagotovite zajem pravilne ID klicatelja
  • Odstrani neštevilčne znake
  • Preverite obliko vzorca
  • Preverite v obdobju TTL

Dovoljenje zavrnjeno

  • Pravilno zahtevajte dovoljenja
  • Pojasnite, zakaj so potrebna dovoljenja
  • Zagotovite alternativo (SMS)
  • Ravnajte elegantno

Naslednji koraki

Viber OTP – Nadomestna dostava OTP - Sporočila SMS - Nadomestni SMS - Preveri stanje - Sledite stanju hitrega klica