Pāriet uz saturu

Flash Call

Flash Call ir tālruņa verifikācijas metode, kas izmanto neatbildētu zvanu, nevis īsziņu, lai pārbaudītu tālruņa numurus. Tas ir ātrāk, drošāk un izmaksu ziņā izdevīgāk.

Pārskats

Flash Call verifikācija darbojas, izmantojot:

1. Lietotājs pieprasa verifikāciju 2. Sistēma uzsāk zvanu uz lietotāja tālruni 3. Saruna tiek automātiski pārtraukta pēc 1-2 zvaniem 4. Lietotāja lietotne fiksē zvanītāja ID 5. Zvanītāja ID tiek pārbaudīts, salīdzinot ar paredzamo modeli 6. Lietotājs ir autentificēts

Ieguvumi

Rentabli

  • Līdz 10x lētāk nekā SMS
  • Nav ziņojumu piegādes maksas
  • Samazinātas liela apjoma verifikācijas izmaksas

Ātrāk

  • Tūlītēja pārbaude (1–3 sekundes)
  • Nav jāgaida SMS piegāde
  • Labāka lietotāja pieredze

Drošāka

  • Grūtāk pārtvert nekā SMS
  • Paziņojumos nav redzama OTP
  • Izturīgs pret SIM maiņas uzbrukumiem

Globālā sasniedzamība

  • Darbojas valstīs ar SMS ierobežojumiem
  • Nav problēmu ar SMS filtrēšanu
  • Universāla tālruņa saderība

Pamata zibatmiņas zvans

Pieprasījums

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

Parametri

Parametrs Tips Nepieciešams Apraksts
no stīga Jūsu sūtītāja identifikators
uz stīga Saņēmēja tālruņa numurs (E.164)
"tips" stīga Iestatīt uz "flashcall"
zvanītāja ID stīga Tālruņa numurs, kas zvanīs lietotājam
ttl vesels skaitlis Dzīves laiks sekundēs (noklusējums: 60)

Kā tas darbojas

1. Lietotājs ievada tālruņa numuru

Lietotājs jūsu lietotnē norāda savu tālruņa numuru:

Phone: +380XXXXXXXXX

2. Pieprasiet zibzvanu

Jūsu serveris pieprasa zibzvana verifikāciju:

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

API atgriež paredzamo zvanītāja ID modeli:

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

4. Sāciet zvanu

Sistēma uzsāk zvanu uz lietotāja tālruni un beidz pēc 1-2 zvaniem.

5. Uzņemiet zvanītāja ID

Lietotāja lietotne fiksē ienākošā zvana zvanītāja ID:

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

6. Verify Pattern

Salīdziniet uzņemto zvanītāja ID ar paredzamo modeli:

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

Īstenošanas piemēri

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

Tīmeklis (servera pusē)

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

Atbildes formāts

Veiksmīga atbilde

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

Atbildes lauki

Lauks Tips Apraksts
messageId stīga Unikāls verifikācijas ID
statuss stīga Statuss: "pieņemts", "noraidīts"
zvanītāja ID stīga Pilns zvanītāja ID numurs
raksts stīga Atbilstošais raksts (cipari + zvaigznītes)
uz stīga Saņēmēja tālruņa numurs
ttl vesels skaitlis Derīguma termiņš sekundēs

Rakstu saskaņošana

API atgriež modeli ar zvaigznītēm, kas maskē dažus ciparus:

Full number: +380123456789
Pattern:     ***456789

Jūsu lietotnei vajadzētu:

  1. Uzņemiet ienākošā zvanītāja ID
  2. Izņemiet ciparus no zvanītāja ID 3. Saskaņot paraugu (zvaigznītes = jebkurš cipars)
  3. Pārbaudiet atbilstību TTL periodā

Atkāpšanās uz SMS

Ja Flash Call neizdodas, automātiski atgriezieties pie SMS:

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

Lietošanas gadījumi

Konta reģistrācija

Reģistrācijas laikā pārbaudiet tālruņu numurus bez maksas par SMS.

Pieteikšanās verifikācija

Divu faktoru autentifikācija, izmantojot zibatmiņas zvanu.

Tālruņa numura atjaunināšana

Apstipriniet jauno tālruņa numuru, kad lietotājs atjaunina profilu.

Darījuma apstiprinājums

Apstipriniet lielas vērtības darījumus, izmantojot zibatmiņas zvanu.

Labākā prakse

TTL

  • ✅ Iestatiet TTL uz 60-90 sekundēm
  • ✅ Ļaujiet lietotājam mēģināt vēlreiz pēc derīguma termiņa beigām
  • ❌ Neizmantojiet TTL ilgāk par 120 sekundēm

Lietotāja pieredze

  • Parādiet ziņojumu "Gaida zvanu...".
  • Displeja atpakaļskaitīšanas taimeris (60 sekundes)
  • Nodrošiniet iespēju "Tā vietā izmantot SMS"
  • Automātiski noteikt un pārbaudīt zvanītāja ID

Kļūdu apstrāde

  • Apstrādājiet trūkstošās tālruņa atļaujas
  • Taimauts pēc TTL termiņa beigām
  • Nodrošiniet SMS atkāpšanās iespēju
  • Rādīt skaidrus kļūdu ziņojumus

Atļaujas

Pieprasiet tālruņa atļaujas pirms zibatmiņas:

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>

Testēšana

  • Testēšana dažādās ierīcēs
  • Pārbaude ar dažādiem nesējiem - Pārbaudiet atļauju atteikuma scenārijus
  • Pārbaudiet tīkla noildzes scenārijus

Ierobežojumi

Platformas atbalsts

  • Darbojas visās mobilajās ierīcēs
  • Nepieciešama tālruņa zvanu iespēja
  • Nepieciešama READ_PHONE_STATE atļauja
  • Var nedarboties planšetdatoros bez tālruņa

Tīkls

  • Nepieciešams aktīvs tālruņa savienojums
  • Sliktos tīkla apstākļos var neizdoties
  • Var tikt piemēroti mobilo sakaru operatoru ierobežojumi
  • Starptautiskie tarifi var atšķirties

Privātums

  • Lietotāji var bloķēt nezināmus numurus
  • Dažām ierīcēm ir zvanu bloķēšana
  • Nepieciešamas skaidras atļaujas
  • Apsveriet lietotāju konfidencialitātes problēmas

Traucējummeklēšana

Zvans nav saņemts

  • Pārbaudiet, vai tālrunim ir signāls - Pārbaudiet skaitļa formātu (E.164)
  • Pārbaudiet operatora ierobežojumus
  • Izmēģiniet atkāpšanos no SMS

Raksts neatbilst

  • Nodrošiniet pareizu zvanītāja ID uztveršanu - Noņemiet rakstzīmes, kas nav cipari
  • Pārbaudiet modeļa formātu
  • Pārbaudiet TTL periodā

Atļauja liegta

  • Pieprasiet atļaujas pareizi - Paskaidrojiet, kāpēc nepieciešamas atļaujas
  • Sniegt alternatīvu (SMS)
  • Rīkojieties graciozi

Nākamie soļi