Flash Call
Flash Call är en telefonverifieringsmetod som använder ett missat samtal istället för SMS för att verifiera telefonnummer. Det är snabbare, säkrare och kostnadseffektivt.
Översikt
Flash Call-verifiering fungerar av:
- Användaren begär verifiering
- Systemet initierar ett samtal till användarens telefon
- Samtalet avslutas automatiskt efter 1-2 ringsignaler
- Användarens app fångar nummerpresentationen
- Nummerpresentation verifieras mot förväntat mönster
- Användaren är autentiserad
Fördelar
Kostnadseffektiv
- Upp till 10 gånger billigare än SMS
- Inga meddelandeleveransavgifter
- Minskade kostnader för verifiering i hög volym
Snabbare
- Omedelbar verifiering (1-3 sekunder)
- Ingen väntan på SMS-leverans
- Bättre användarupplevelse
Säkrare
- Svårare att avlyssna än SMS
- Ingen OTP synlig i aviseringar
- Motståndskraftig mot SIM-bytesattacker
Global räckvidd
- Fungerar i länder med SMS-begränsningar
- Inga problem med SMS-filtrering
- Universell telefonkompatibilitet
Basic Flash Call
Begäran
{
"from": "YourApp",
"to": "+380XXXXXXXXX",
"type": "flashcall",
"messageData": {
"callerId": "+380123456789"
}
}
Parametrar
| Parameter | Skriv | Krävs | Beskrivning |
|---|---|---|---|
från |
sträng | Ja | Din avsändaridentifierare |
till |
sträng | Ja | Mottagarens telefonnummer (E.164) |
typ |
sträng | Ja | Ställ in på "flashcall" |
callerId |
sträng | Ja | Telefonnummer som ringer användaren |
ttl |
heltal | Nej | Tid att leva i sekunder (standard: 60) |
Hur det fungerar
1. Användare anger telefonnummer
Användaren anger sitt telefonnummer i din app:
2. Begär Flash Call
Din server begär snabbsamtalsverifiering:
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-svar
API returnerar det förväntade anrops-ID-mönstret:
{
"messagelistId": 123456,
"messages": [
{
"messageId": "abc123def456",
"status": "accepted",
"callerId": "+380123456789",
"pattern": "***456789",
"to": "+380XXXXXXXXX"
}
]
}
4. Initiera samtal
Systemet initierar ett samtal till användarens telefon och avslutas efter 1-2 ringsignaler.
5. Fånga nummerpresentation
Användarens app fångar det inkommande samtalets nummerpresentation:
// Android example
val cursor = contentResolver.query(
CallLog.Calls.CONTENT_URI,
arrayOf(CallLog.Calls.NUMBER),
null, null,
CallLog.Calls.DATE + " DESC"
)
6. Verifiera mönster
Jämför fångad nummerpresentation med förväntat mönster:
// 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);
}
Implementeringsexempel
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
}
}
Webb (serversidan)
// 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' });
}
});
Svarsformat
Framgångssvar
{
"messagelistId": 123456,
"messages": [
{
"messageId": "abc123def456",
"status": "accepted",
"callerId": "+380123456789",
"pattern": "***456789",
"to": "+380XXXXXXXXX",
"ttl": 60
}
]
}
Svarsfält
| Fält | Skriv | Beskrivning |
|---|---|---|
meddelande-ID |
sträng | Unikt verifierings-ID |
status |
sträng | Status: accepterad, avvisad |
callerId |
sträng | Fullständigt nummer för nummerpresentation |
mönster |
sträng | Mönster att matcha (siffror + asterisker) |
till |
sträng | Mottagarens telefonnummer |
ttl |
heltal | Giltighetsperiod i sekunder |
Mönstermatchning
API:et returnerar ett mönster med asterisker som maskerar några siffror:
Din app bör:
- Fånga inkommande nummerpresentation
- Extrahera siffror från nummerpresentation
- Matcha mot mönster (asterisker = valfri siffra)
- Verifiera matchningen inom TTL-perioden
Alternativ till SMS
Om Flash Call misslyckas, faller du automatiskt tillbaka till SMS:
{
"from": "YourApp",
"to": "+380XXXXXXXXX",
"type": "flashcall",
"messageData": {
"callerId": "+380123456789"
},
"fallback": {
"type": "sms",
"text": "Your verification code is: 123456"
},
"ttl": 60
}
Användningsfall
Kontoregistrering
Verifiera telefonnummer under registreringen utan SMS-kostnader.
Inloggningsverifiering
Tvåfaktorsautentisering med flashsamtal.
Uppdatering av telefonnummer
Verifiera nytt telefonnummer när användaren uppdaterar profilen.
Transaktionsbekräftelse
Bekräfta transaktioner med högt värde med flash-samtal.
Bästa metoder
TTL
- ✅ Ställ in TTL på 60-90 sekunder
- ✅ Tillåt användaren att försöka igen efter utgången
- ❌ Använd inte TTL längre än 120 sekunder
Användarupplevelse
- Visa meddelandet "Väntar på samtal...".
- Visa nedräkningstimer (60 sekunder)
- Ge alternativet "Använd SMS istället"
- Upptäck och verifiera nummerpresentation automatiskt
Felhantering
- Hantera saknade telefonbehörigheter
- Timeout efter att TTL löper ut
- Tillhandahålla alternativ för SMS
- Visa tydliga felmeddelanden
Behörigheter
Begär telefonbehörigheter innan flashsamtal:
Android:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
iOS:
Testning
- Testa på olika enheter
- Testa med olika bärare
- Testa scenarier för nekande av tillstånd
- Testa scenarier för nätverkstimeout
Begränsningar
Plattformsstöd
- Fungerar på alla mobila enheter
- Kräver telefonsamtalskapacitet
- Behöver READ_PHONE_STATE-tillstånd – Fungerar kanske inte på surfplattor utan telefon
Nätverk
- Kräver aktiv telefonanslutning
- Kan misslyckas under dåliga nätverksförhållanden
- Operatörsbegränsningar kan gälla
- Internationella priser kan variera
Sekretess
- Användare kan blockera okända nummer
- Vissa enheter har samtalsblockering
- Kräver uttryckliga tillstånd
- Tänk på användarnas integritetsproblem
Felsökning
Samtal ej mottaget
- Kontrollera att telefonen har signal
- Verifiera nummerformat (E.164)
- Kontrollera operatörens begränsningar
- Testa att använda SMS
Mönster matchar inte
- Se till att fånga korrekt nummerpresentation
- Ta bort icke-siffriga tecken
- Kontrollera mönsterformatet
- Verifiera inom TTL-perioden
Tillstånd nekad
- Begär behörigheter korrekt
- Förklara varför behörigheter behövs
- Tillhandahålla alternativ (SMS)
- Hantera graciöst
Nästa steg
- Viber OTP - Alternativ OTP-leverans
- SMS-meddelanden - Alternativ för SMS
- Kontrollera status - Spåra status för flashsamtal