Zum Inhalt

Flash-Anruf

Flash Call ist eine Telefonverifizierungsmethode, die zur Verifizierung von Telefonnummern einen verpassten Anruf anstelle einer SMS verwendet. Es ist schneller, sicherer und kostengünstiger.

Übersicht

Die Überprüfung von Flash-Anrufen funktioniert wie folgt:

  1. Der Benutzer fordert eine Verifizierung an
  2. Das System leitet einen Anruf an das Telefon des Benutzers ein
  3. Der Anruf wird nach 1-2 Klingeltönen automatisch beendet
  4. Die App des Benutzers erfasst die Anrufer-ID
  5. Die Anrufer-ID wird anhand des erwarteten Musters überprüft
  6. Der Benutzer ist authentifiziert

Vorteile

Kostengünstig

  • Bis zu 10x günstiger als SMS
  • Keine Gebühren für die Nachrichtenübermittlung
  • Reduzierte Kosten für die Verifizierung großer Mengen

Schneller

  • Sofortige Verifizierung (1-3 Sekunden)
  • Kein Warten auf SMS-Zustellung
  • Bessere Benutzererfahrung

Sicherer

  • Schwieriger abzufangen als SMS
  • In Benachrichtigungen ist kein OTP sichtbar
  • Resistent gegen SIM-Swap-Angriffe

Globale Reichweite

  • Funktioniert in Ländern mit SMS-Beschränkungen
  • Keine Probleme mit der SMS-Filterung
  • Universelle Telefonkompatibilität

Einfacher Flash-Anruf

Anfrage

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

Parameter

Parameter Geben Sie ein Erforderlich Beschreibung
„von“ Zeichenfolge Ja Ihre Absender-ID
„zu“ Zeichenfolge Ja Telefonnummer des Empfängers (E.164)
„Typ“ Zeichenfolge Ja Auf „Flashcall“ setzen
callerId Zeichenfolge Ja Telefonnummer, unter der der Benutzer
ttl Ganzzahl Nein Lebensdauer in Sekunden (Standard: 60)

Wie es funktioniert

1. Benutzer gibt Telefonnummer ein

Der Benutzer gibt seine Telefonnummer in Ihrer App an:

Phone: +380XXXXXXXXX

2. Flash-Anruf anfordern

Ihr Server fordert eine Flash-Anrufverifizierung an:

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

Die API gibt das erwartete Anrufer-ID-Muster zurück:

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

4. Anruf einleiten

Das System leitet einen Anruf an das Telefon des Benutzers ein und beendet ihn nach 1–2 Klingeltönen.

5. Erfassen Sie die Anrufer-ID

Die App des Benutzers erfasst die Anrufer-ID des eingehenden Anrufs:

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

6. Muster überprüfen

Vergleichen Sie die erfasste Anrufer-ID mit dem erwarteten Muster:

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

Implementierungsbeispiele

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 (serverseitig)

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

Antwortformat

Erfolgsantwort

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

Antwortfelder

Feld Geben Sie ein Beschreibung
messageId Zeichenfolge Eindeutige Verifizierungs-ID
Status Zeichenfolge Status: „akzeptiert“, „abgelehnt“
callerId Zeichenfolge Vollständige Anrufer-ID-Nummer
„Muster“ Zeichenfolge Muster zum Abgleichen (Ziffern + Sternchen)
„zu“ Zeichenfolge Telefonnummer des Empfängers
ttl Ganzzahl Gültigkeitsdauer in Sekunden

Mustervergleich

Die API gibt ein Muster mit Sternchen zurück, die einige Ziffern maskieren:

Full number: +380123456789
Pattern:     ***456789

Ihre App sollte:

  1. Erfassen Sie die ID des eingehenden Anrufs
  2. Extrahieren Sie Ziffern aus der Anrufer-ID
  3. Vergleich mit Muster (Sternchen = beliebige Ziffer)
  4. Überprüfen Sie die Übereinstimmung innerhalb des TTL-Zeitraums

Rückfall auf SMS

Wenn Flash Call fehlschlägt, greifen Sie automatisch auf SMS zurück:

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

Anwendungsfälle

Kontoregistrierung

Verifizieren Sie Telefonnummern bei der Anmeldung ohne SMS-Kosten.

Anmeldebestätigung

Zwei-Faktor-Authentifizierung per Flash-Call.

Aktualisierung der Telefonnummer

Überprüfen Sie die neue Telefonnummer, wenn der Benutzer sein Profil aktualisiert.

Transaktionsbestätigung

Bestätigen Sie hochwertige Transaktionen mit einem Flash-Anruf.

Best Practices

TTL

  • ✅ TTL auf 60-90 Sekunden einstellen
  • ✅ Ermöglichen Sie dem Benutzer, es nach Ablauf erneut zu versuchen
  • ❌ Verwenden Sie TTL nicht länger als 120 Sekunden

Benutzererfahrung

  • Meldung „Warten auf Anruf...“ anzeigen
  • Countdown-Timer anzeigen (60 Sekunden)
  • Option „Stattdessen SMS verwenden“ bereitstellen
  • Anrufer-ID automatisch erkennen und überprüfen

Fehlerbehandlung

  • Behandeln Sie fehlende Telefonberechtigungen
  • Zeitüberschreitung nach Ablauf der TTL
  • Bereitstellung einer SMS-Fallback-Option
  • Klare Fehlermeldungen anzeigen

Berechtigungen

Fordern Sie vor dem Flash-Anruf Telefonberechtigungen an:

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>

Testen

  • Testen Sie auf verschiedenen Geräten
  • Testen Sie mit verschiedenen Anbietern
  • Testen Sie Szenarien zur Berechtigungsverweigerung
  • Testen Sie Netzwerk-Timeout-Szenarien

Einschränkungen

Plattformunterstützung

  • Funktioniert auf allen Mobilgeräten
  • Erfordert Telefonanruffunktion
  • Benötigt die Berechtigung READ_PHONE_STATE
  • Funktioniert möglicherweise nicht auf Tablets ohne Telefon

Netzwerk

  • Erfordert eine aktive Telefonverbindung – Kann bei schlechten Netzwerkbedingungen fehlschlagen
  • Es können Beschränkungen des Mobilfunkanbieters gelten
  • Internationale Preise können variieren

Datenschutz

  • Benutzer können unbekannte Nummern blockieren
  • Einige Geräte verfügen über eine Anrufsperre
  • Erfordert explizite Berechtigungen
  • Berücksichtigen Sie Bedenken hinsichtlich der Privatsphäre der Benutzer

Fehlerbehebung

Anruf nicht erhalten

  • Überprüfen Sie, ob das Telefon ein Signal hat
  • Zahlenformat überprüfen (E.164)
  • Überprüfen Sie die Beschränkungen des Mobilfunkanbieters
  • Versuchen Sie es mit einem SMS-Fallback

Muster stimmt nicht überein

  • Stellen Sie sicher, dass die korrekte Anrufer-ID erfasst wird
  • Nicht-stellige Zeichen entfernen
  • Musterformat prüfen
  • Überprüfen Sie innerhalb des TTL-Zeitraums

Berechtigung verweigert

  • Fordern Sie Berechtigungen ordnungsgemäß an
  • Erklären Sie, warum Berechtigungen erforderlich sind
  • Alternative bereitstellen (SMS)
  • Gehen Sie mit Würde vor

Nächste Schritte

Viber OTP – Alternative OTP-Zustellung – SMS-Nachrichten – SMS-Fallback - Status prüfen - Verfolgen Sie den Status des Flash-Anrufs