Apel flash
Flash Call este o metodă de verificare a telefonului care utilizează un apel pierdut în loc de SMS pentru a verifica numerele de telefon. Este mai rapid, mai sigur și mai rentabil.
Prezentare generală
Verificarea Flash Call funcționează prin:
- Utilizatorul solicită verificarea
- Sistemul inițiază un apel către telefonul utilizatorului
- Apelul este terminat automat după 1-2 sunete
- Aplicația utilizatorului captează ID-ul apelantului
- ID-ul apelantului este verificat în funcție de modelul așteptat
- Utilizatorul este autentificat
Beneficii
Cost-eficient
- De până la 10 ori mai ieftin decât SMS-urile
- Fără taxe de livrare a mesajelor
- Costuri reduse pentru verificarea de volum mare
Mai repede
- Verificare instantanee (1-3 secunde)
- Fără așteptare pentru livrarea SMS-urilor
- Experiență de utilizator mai bună
Mai sigur
- Mai greu de interceptat decât SMS-urile
- Niciun OTP vizibil în notificări
- Rezistent la atacurile de schimb SIM
Acoperire globală
- Funcționează în țări cu restricții SMS
- Nu există probleme cu filtrarea SMS-urilor
- Compatibilitate universală cu telefonul
Apel flash de bază
Solicitare
{
"from": "YourApp",
"to": "+380XXXXXXXXX",
"type": "flashcall",
"messageData": {
"callerId": "+380123456789"
}
}
Parametri
| Parametru | Tip | Necesar | Descriere |
|---|---|---|---|
din |
șir | Da | Identificatorul expeditorului dvs. |
la |
șir | Da | Număr de telefon al destinatarului (E.164) |
tip |
șir | Da | Setați la "flashcall" |
callerId |
șir | Da | Număr de telefon care va apela utilizatorul |
ttl |
întreg | Nu | Timp de viață în secunde (implicit: 60) |
Cum funcționează
1. Utilizatorul introduce numărul de telefon
Utilizatorul oferă numărul de telefon în aplicația dvs.:
2. Solicitați un apel flash
Serverul dvs. solicită verificarea apelurilor 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. Răspuns API
API returnează modelul așteptat de ID apelant:
{
"messagelistId": 123456,
"messages": [
{
"messageId": "abc123def456",
"status": "accepted",
"callerId": "+380123456789",
"pattern": "***456789",
"to": "+380XXXXXXXXX"
}
]
}
4. Inițiați apelul
Sistemul inițiază un apel către telefonul utilizatorului și se încheie după 1-2 sunete.
5. Capturați ID apelant
Aplicația utilizatorului captează ID-ul apelantului apelului primit:
// Android example
val cursor = contentResolver.query(
CallLog.Calls.CONTENT_URI,
arrayOf(CallLog.Calls.NUMBER),
null, null,
CallLog.Calls.DATE + " DESC"
)
6. Verificați modelul
Comparați ID-ul apelantului capturat cu modelul așteptat:
// 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);
}
Exemple de implementare
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 (partea server)
// 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' });
}
});
Format de răspuns
Răspuns de succes
{
"messagelistId": 123456,
"messages": [
{
"messageId": "abc123def456",
"status": "accepted",
"callerId": "+380123456789",
"pattern": "***456789",
"to": "+380XXXXXXXXX",
"ttl": 60
}
]
}
Câmpuri de răspuns
| Câmp | Tip | Descriere |
|---|---|---|
messageId |
șir | ID unic de verificare |
starea |
șir | Stare: acceptat, respins |
callerId |
șir | Număr complet de identificare a apelantului |
model |
șir | Model pentru a se potrivi (cifre + asteriscuri) |
la |
șir | Numărul de telefon al destinatarului |
ttl |
întreg | Perioada de valabilitate în secunde |
Potrivirea modelului
API-ul returnează un model cu asteriscuri care maschează unele cifre:
Aplicația dvs. ar trebui să:
- Capturați ID-ul apelantului primit
- Extrageți cifre din ID-ul apelantului
- Potriviți cu model (asteriscuri = orice cifră)
- Verificați potrivirea în perioada TTL
Revenire la SMS
Dacă apelul flash nu reușește, reveniți automat la SMS:
{
"from": "YourApp",
"to": "+380XXXXXXXXX",
"type": "flashcall",
"messageData": {
"callerId": "+380123456789"
},
"fallback": {
"type": "sms",
"text": "Your verification code is: 123456"
},
"ttl": 60
}
Cazuri de utilizare
Înregistrarea contului
Verificați numerele de telefon în timpul înscrierii fără costuri prin SMS.
Verificare autentificare
Autentificare cu doi factori folosind apel flash.
Actualizare număr de telefon
Verificați noul număr de telefon când utilizatorul actualizează profilul.
Confirmarea tranzacției
Confirmați tranzacțiile de mare valoare cu apelul flash.
Cele mai bune practici
TTL
- ✅ Setați TTL la 60-90 de secunde
- ✅ Permiteți utilizatorului să reîncerce după expirare
- ❌ Nu utilizați TTL mai mult de 120 de secunde
Experiența utilizatorului
- Afișați mesajul „Se așteaptă apelul...”.
- Afișează cronometrul cu numărătoare inversă (60 de secunde)
- Oferiți opțiunea „Folosiți SMS-ul în schimb”
- Detectați și verificați automat ID-ul apelantului
Gestionarea erorilor
- Gestionați permisiunile telefonului lipsă
- Timeout după expirarea TTL
- Furnizați opțiunea de rezervă pentru SMS
- Afișați mesaje de eroare clare
Permisiuni
Solicitați permisiuni telefonice înainte de apelul flash:
Android:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
iOS:
Testare
- Testați pe diferite dispozitive
- Testați cu diferiți transportatori
- Testați scenariile de refuzare a permisiunii
- Testați scenariile de expirare a rețelei
Limitări
Suport platformă
- Funcționează pe toate dispozitivele mobile
- Necesită capacitatea de apel telefonic
- Are nevoie de permisiunea READ_PHONE_STATE
- Este posibil să nu funcționeze pe tablete fără telefon
Rețea
- Necesită conexiune telefonică activă
- Poate eșua în condiții proaste de rețea
- Se pot aplica restricții de transportator
- Tarifele internaționale pot varia
Confidențialitate
- Utilizatorii pot bloca numere necunoscute
- Unele dispozitive au blocarea apelurilor
- Necesită permisiuni explicite
- Luați în considerare preocupările privind confidențialitatea utilizatorilor
Depanare
Apel neprimit
- Verificați că telefonul are semnal
- Verificați formatul numărului (E.164)
- Verificați restricțiile operatorului
- Încercați SMS-uri de rezervă
Modelul nu se potrivește
- Asigurați-vă că capturați ID-ul apelantului corect
- Eliminați caracterele fără cifre
- Verificați formatul modelului
- Verificați în perioada TTL
Permisiune refuzată
- Solicitați permisiunile în mod corespunzător
- Explicați de ce sunt necesare permisiunile
- Oferiți alternative (SMS)
- Manevrează-te cu grație
Următorii pași
- Viber OTP - Livrare OTP alternativă
- Mesaje SMS - SMS de rezervă
- Verificați starea - Urmăriți starea apelului flash