Μετάβαση στο περιεχόμενο

Flash Call

Η Flash Call είναι μια μέθοδος επαλήθευσης τηλεφώνου που χρησιμοποιεί μια αναπάντητη κλήση αντί για SMS για την επαλήθευση αριθμών τηλεφώνου. Είναι πιο γρήγορο, πιο ασφαλές και οικονομικό.

Επισκόπηση

Η επαλήθευση κλήσεων Flash λειτουργεί από:

  1. Επαλήθευση αιτημάτων χρήστη
  2. Το σύστημα ξεκινά μια κλήση στο τηλέφωνο του χρήστη
  3. Η κλήση τερματίζεται αυτόματα μετά από 1-2 κουδουνίσματα
  4. Η εφαρμογή του χρήστη καταγράφει το αναγνωριστικό καλούντος
  5. Η ταυτότητα καλούντος επαληθεύεται σύμφωνα με το αναμενόμενο μοτίβο
  6. Ο χρήστης έχει πιστοποιηθεί

Οφέλη

Οικονομικά αποδοτική

  • Έως και 10 φορές φθηνότερα από τα SMS
  • Χωρίς τέλη αποστολής μηνυμάτων
  • Μειωμένο κόστος για επαλήθευση μεγάλου όγκου

Πιο γρήγορα

  • Άμεση επαλήθευση (1-3 δευτερόλεπτα)
  • Δεν υπάρχει αναμονή για παράδοση SMS
  • Καλύτερη εμπειρία χρήστη

Πιο ασφαλές

  • Πιο δύσκολο να υποκλαπούν από SMS
  • Δεν εμφανίζεται OTP στις ειδοποιήσεις
  • Ανθεκτικό σε επιθέσεις ανταλλαγής SIM

Παγκόσμια προσέγγιση

  • Λειτουργεί σε χώρες με περιορισμούς SMS
  • Δεν υπάρχουν προβλήματα με το φιλτράρισμα SMS
  • Συμβατότητα τηλεφώνου γενικής χρήσης

Βασική κλήση Flash

Αίτημα

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

Παράμετροι

Παράμετρος Τύπος Απαιτείται Περιγραφή
«από» χορδή Ναι Το αναγνωριστικό αποστολέα σας
«προς» χορδή Ναι Αριθμός τηλεφώνου παραλήπτη (E.164)
«τύπος» χορδή Ναι Ορισμός σε "flashcall"
callerId χορδή Ναι Αριθμός τηλεφώνου που θα καλέσει χρήστη
ttl ακέραιος Όχι Χρόνος ζωής σε δευτερόλεπτα (προεπιλογή: 60)

Πώς λειτουργεί

1. Ο χρήστης εισάγει τον αριθμό τηλεφώνου

Ο χρήστης παρέχει τον αριθμό τηλεφώνου του στην εφαρμογή σας:

Phone: +380XXXXXXXXX

2. Ζητήστε Flash Call

Ο διακομιστής σας ζητά επαλήθευση κλήσεων 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. Απόκριση API

Το API επιστρέφει το αναμενόμενο μοτίβο αναγνώρισης καλούντος:

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

4. Έναρξη κλήσης

Το σύστημα ξεκινά μια κλήση στο τηλέφωνο του χρήστη και τερματίζει μετά από 1-2 κουδουνίσματα.

5. Λήψη αναγνωριστικού καλούντος

Η εφαρμογή του χρήστη καταγράφει το αναγνωριστικό καλούντος της εισερχόμενης κλήσης:

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

6. Επαληθεύστε το μοτίβο

Συγκρίνετε το αναγνωριστικό καλούντος που καταγράφηκε με το αναμενόμενο μοτίβο:

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

Παραδείγματα Εφαρμογής

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

Ιστός (από την πλευρά του διακομιστή)

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

Μορφή απόκρισης

Απόκριση επιτυχίας

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

Πεδία απόκρισης

Πεδίο Τύπος Περιγραφή
MessageId χορδή Μοναδικό αναγνωριστικό επαλήθευσης
«κατάσταση» χορδή Κατάσταση: "αποδοχή", "απορρίφθηκε"
callerId χορδή Πλήρης αριθμός αναγνώρισης καλούντος
«μοτίβο» χορδή Μοτίβο για αντιστοίχιση (ψηφία + αστερίσκοι)
«προς» χορδή Αριθμός τηλεφώνου παραλήπτη
ttl ακέραιος Περίοδος ισχύος σε δευτερόλεπτα

Αντιστοίχιση προτύπων

Το API επιστρέφει ένα μοτίβο με αστερίσκους που καλύπτουν ορισμένα ψηφία:

Full number: +380123456789
Pattern:     ***456789

Η εφαρμογή σας θα πρέπει:

  1. Καταγράψτε το αναγνωριστικό εισερχόμενου καλούντος
  2. Εξαγωγή ψηφίων από το αναγνωριστικό καλούντος
  3. Ταίριασμα με μοτίβο (αστερίσκοι = οποιοδήποτε ψηφίο)
  4. Επαληθεύστε την αντιστοίχιση εντός της περιόδου TTL

Εναλλαγή στα SMS

Εάν η κλήση Flash αποτύχει, επιστρέψτε αυτόματα στο SMS:

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

Περιπτώσεις χρήσης

Εγγραφή λογαριασμού

Επαληθεύστε τους αριθμούς τηλεφώνου κατά την εγγραφή χωρίς κόστος SMS.

Επαλήθευση σύνδεσης

Έλεγχος ταυτότητας δύο παραγόντων με χρήση κλήσης flash.

Ενημέρωση αριθμού τηλεφώνου

Επαληθεύστε τον νέο αριθμό τηλεφώνου όταν ο χρήστης ενημερώνει το προφίλ.

Επιβεβαίωση συναλλαγής

Επιβεβαιώστε συναλλαγές υψηλής αξίας με κλήση flash.

Βέλτιστες πρακτικές

TTL

  • ✅ Ρυθμίστε το TTL στα 60-90 δευτερόλεπτα
  • ✅ Επιτρέψτε στον χρήστη να δοκιμάσει ξανά μετά τη λήξη
  • ❌ Μην χρησιμοποιείτε το TTL για περισσότερο από 120 δευτερόλεπτα

Εμπειρία χρήστη

  • Εμφάνιση μηνύματος "Αναμονή κλήσης...".
  • Εμφάνιση χρονοδιακόπτη αντίστροφης μέτρησης (60 δευτερόλεπτα)
  • Παρέχετε την επιλογή "Χρήση SMS αντί"
  • Αυτόματος εντοπισμός και επαλήθευση αναγνώρισης καλούντος

Χειρισμός σφαλμάτων

  • Χειριστείτε τις άδειες τηλεφώνου που λείπουν
  • Timeout μετά τη λήξη του TTL
  • Παρέχετε εναλλακτική επιλογή SMS
  • Εμφάνιση καθαρών μηνυμάτων σφάλματος

Δικαιώματα

Ζητήστε άδειες τηλεφώνου πριν από την κλήση flash:

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

Δοκιμή

  • Δοκιμή σε διαφορετικές συσκευές
  • Δοκιμή με διαφορετικούς φορείς
  • Δοκιμή σεναρίων άρνησης άδειας
  • Δοκιμή σεναρίων χρονικού ορίου λήξης δικτύου

Περιορισμοί

Υποστήριξη πλατφόρμας

  • Λειτουργεί σε όλες τις κινητές συσκευές
  • Απαιτεί δυνατότητα τηλεφωνικής κλήσης
  • Χρειάζεται άδεια READ_PHONE_STATE
  • Μπορεί να μην λειτουργεί σε tablet χωρίς τηλέφωνο

Δίκτυο

  • Απαιτεί ενεργή σύνδεση τηλεφώνου
  • Μπορεί να αποτύχει σε κακές συνθήκες δικτύου
  • Ενδέχεται να ισχύουν περιορισμοί μεταφορέα
  • Οι διεθνείς τιμές ενδέχεται να διαφέρουν

Απόρρητο

  • Οι χρήστες μπορούν να αποκλείσουν άγνωστους αριθμούς
  • Ορισμένες συσκευές έχουν αποκλεισμό κλήσεων
  • Απαιτεί ρητές άδειες
  • Λάβετε υπόψη τις ανησυχίες σχετικά με το απόρρητο των χρηστών

Αντιμετώπιση προβλημάτων

Η κλήση δεν ελήφθη

  • Ελέγξτε ότι το τηλέφωνο έχει σήμα
  • Επαλήθευση μορφής αριθμού (E.164)
  • Ελέγξτε τους περιορισμούς του φορέα
  • Δοκιμάστε εναλλακτικό SMS

Το μοτίβο δεν ταιριάζει

  • Βεβαιωθείτε ότι έχετε καταγράψει το σωστό αναγνωριστικό καλούντος
  • Απογύμνωση μη ψηφιακών χαρακτήρων
  • Ελέγξτε τη μορφή μοτίβου
  • Επαλήθευση εντός περιόδου TTL

Δεν επιτρέπεται η άδεια

  • Ζητήστε άδειες σωστά
  • Εξηγήστε γιατί χρειάζονται δικαιώματα
  • Παροχή εναλλακτικών (SMS)
  • Χειριστείτε με χάρη

Επόμενα βήματα