WappSync Phone Verify - Documentazione API
Verifica telefonica in cui il Suo utente invia un codice a noi tramite WhatsApp - nessun OTP da digitare, un tocco, completamente verificato.
Contenuti
Come Funziona
Lei richiede un codice
Il Suo backend chiama la nostra API con il numero di telefono dell'utente. Restituiamo un codice univoco e il numero WhatsApp a cui inviarlo.
L'utente lo invia tramite WhatsApp
Il Suo utente tocca un link WhatsApp - il codice è precompilato. Nessun digitare, nessun copia e incolla. Basta premere invia.
Verificato istantaneamente
Riceviamo il messaggio, vediamo da quale numero WhatsApp è stato inviato e la Sua interrogazione restituisce auth=1 con il telefono certificato. Fatto!
Ottenga le Sue credenziali
Registrati su wappsync.com/mybusiness per ricevere:
| Credenziale | Descrizione |
|---|---|
businessid | Il Suo ID aziendale numerico |
businesskey | La Sua chiave segreta - non condividerla mai, non inserirla mai nel codice lato client |
businesskey viene usata per la firma HMAC e non deve mai comparire nel JavaScript del browser, nel codice sorgente HTML o nel codice dell'app mobile.Due modalità di verifica
Phone Verify funziona in due modalità, scelte per singola richiesta. In entrambe, il Suo utente invia il codice a noi tramite WhatsApp - l'unica differenza è quale numero di telefono viene certificato.
confirm_phone (default) | verify_sender | |
|---|---|---|
| Lei invia | un numero di telefono N | nulla (nessun numero) |
| Cosa viene certificato | che il chiamante controlla N specificamente | qualunque numero rispedisca effettivamente il codice |
| Uso tipico | accesso / recupero su un numero in archivio, protezione contro il cambio di SIM | nuova registrazione - «dammi un telefono reale e dimostrato per questo cliente» |
| Consegna del codice | Inviato via WhatsApp a N e mostrato nella Sua interfaccia (delivery: pushed_to_phone) | solo tramite Lei (delivery: relay_by_business) - consegna Lei il codice al Suo cliente |
| Risultato dell'interrogazione | sender_matches_intended Le indica se il mittente è N | phoneEnc è il numero certificato; sender_matches_intended è omesso |
confirm_phone dimostra il controllo di un numero dichiarato specifico; verify_sender dimostra il controllo di un numero e indica quale. Se il Suo flusso richiede che «il numero su questo account appartenga davvero all'utente», resti su confirm_phone con on_mismatch: reject.Telefono corretto (on_mismatch): un caso comune è il cliente che dichiara A ma invia il codice da B (errore di digitazione / dual-SIM). In confirm_phone, reject (predefinito) lo tratta come un tentativo fallito; accept_sender certifica invece il mittente effettivo B (sender_matches_intended: false, phoneEnc = B), e il Suo backend decide se accettare il numero corretto B o richiedere un nuovo OTP per A.
Richieda un OTP inverso
Chiami questo dal Suo backend quando deve verificare un utente:
POSThttps://wappsync.com/phone-verify/api/getReverseOTP
Corpo della richiesta (JSON)
| Campo | Tipo | Descrizione |
|---|---|---|
businessid | int | Il Suo ID aziendale |
businessref | string | Un riferimento univoco che genera per questa richiesta di autenticazione (ad es. bin2hex(random_bytes(4))) |
phone | string | Il numero di telefono dell'utente in formato internazionale (+40755123456). Obbligatorio in modalità confirm_phone; ometta o lasci vuoto per verify_sender. |
mode | string | Facoltativo - confirm_phone (predefinito quando viene fornito un telefono) oppure verify_sender (predefinito quando il telefono è omesso) |
on_mismatch | string | Facoltativo (solo confirm_phone) - reject (predefinito) oppure accept_sender (certifica il mittente effettivo se il codice arriva da un numero diverso) |
ts | int | Timestamp Unix corrente |
hmac | string | Firma HMAC-SHA256 |
Firma HMAC
Firmi questa stringa con la Sua businesskey:
{businessid}|{businessref}|{phone}|{ts}
Nella modalità verify_sender non c'è telefono, quindi la stringa firmata è {businessid}|{businessref}||{ts} (slot centrale vuoto).
Esempio:
$hmac = hash_hmac('sha256', "{$businessid}|{$businessref}|{$phone}|{$ts}", $businesskey);
Risposta
| Campo | Tipo | Descrizione |
|---|---|---|
status | string | "ok" or "error" |
reverseotp_display | string | Il codice che invia il Suo utente, ad es. "2FA-828161" |
waphone | string | Il numero WhatsApp A CUI il Suo utente invia il codice |
logincode | string | Codice interno da usare durante l'interrogazione |
in_ts | int | Timestamp per la richiesta di interrogazione |
out_ts | int | Timestamp della risposta |
otp_valid_minutes | int | Per quanto tempo il codice è valido (predefinito 10) |
mode | string | La modalità attiva: confirm_phone o verify_sender |
delivery | string | pushed_to_phone (confirm_phone: il codice viene inviato via WhatsApp anche al telefono dichiarato) oppure relay_by_business (verify_sender: deve consegnare Lei il codice al Suo cliente) |
hmac | string | HMAC della risposta - verifichi con la Sua businesskey |
Verifica l'HMAC della risposta against {businessid}|{businessref}|{logincode}|{reverseotp_display}|{waphone}|{out_ts}.
Cosa mostrare al Suo utente
Mostri il codice e il numero di telefono. Usi un link whatsapp://send così l'utente può inviarlo con un solo tocco:
<a href="whatsapp://send?phone=40725296320&text=2FA-828161">
💬 Send Code via WhatsApp
</a>
Interroga la verifica
Interroga ogni 2-3 secondi finché l'utente non è verificato:
POSThttps://wappsync.com/phone-verify/api/getReverseOTPStatus
Corpo della richiesta (JSON)
| Campo | Tipo | Descrizione |
|---|---|---|
businessid | int | Il Suo ID aziendale |
businessref | string | Lo stesso riferimento della chiamata precedente |
logincode | string | Il logincode dalla risposta di getReverseOTP |
in_ts | int | Il ts originale dalla richiesta getReverseOTP |
hmac | string | HMAC-SHA256 di {businessid}|{businessref}|{logincode}|{in_ts} |
Risposta
| Campo | Tipo | Significato |
|---|---|---|
used | 0 | ⏳ Ancora in attesa - interroghi di nuovo |
used | 1 | ✅ Appena verificato - la prima interrogazione che lo vede lo consuma |
used | 2 | 🔒 Già consumato da un'interrogazione precedente |
auth | 1 | L'utente è verificato - effettui l'accesso! |
phoneEnc | string | Telefono certificato cifrato AES-256-CBC (solo quando auth=1) - il mittente quando è stato ricevuto un codice (identico al Suo numero dichiarato con confirm_phone rigoroso) |
tries | int | Vengono contati i tentativi falliti (codice errato o telefono errato) |
expired | bool | true quando ci sono troppi tentativi falliti (tentativi ≥ 4) - richieda un nuovo OTP |
mode | string | La modalità di questa richiesta: confirm_phone o verify_sender |
sender_matches_intended | bool | confirm_phone soltanto, una volta ricevuto un codice - true = il mittente è il numero che ha chiesto di verificare; false = è stato certificato un mittente corretto. Omesso in verify_sender. |
out_ts | int | Timestamp della risposta |
hmac | string | HMAC - verifichi con {businessid}|{businessref}|{logincode}|{used}|{phoneEnc}|{out_ts} |
Quando auth === 1, è stato ricevuto un codice valido. Decifri phoneEnc per ottenere il telefono certificato (controlli sender_matches_intended in modalità confirm_phone), poi effettui l'accesso dell'utente.
Decifra il numero di telefono
Quando auth=1, phoneEnc contiene il telefono certificato (il mittente che si è dimostrato) cifrato con AES-256-CBC usando la Sua businesskey:
function decryptPhoneAES($encryptedData, $businesskey) {
$method = 'AES-256-CBC';
$key = hash('sha256', $businesskey, true);
$enc = str_replace(['-', '_'], ['+', '/'], $encryptedData);
$enc = str_pad($enc, strlen($enc) % 4 === 0
? strlen($enc) : strlen($enc) + 4 - strlen($enc) % 4,
'=', STR_PAD_RIGHT);
$decoded = base64_decode($enc);
$iv = substr($decoded, 0, 16);
$ciphertext = substr($decoded, 16);
return openssl_decrypt($ciphertext, $method, $key, OPENSSL_RAW_DATA, $iv);
}
$phone = decryptPhoneAES($response['phoneEnc'], $businesskey);
// Store this phone - it's the user's verified identity
Esempio frontend
L'unica interfaccia di cui ha bisogno - la mostri dopo che il Suo backend ha chiamato getReverseOTP:
<div style="text-align:center; max-width:400px; margin:auto;">
<p>Send this exact code via WhatsApp from your phone:</p>
<div style="font-size:28px; font-weight:bold; color:#25D366;
letter-spacing:3px;">
2FA-828161
</div>
<p>to <strong>+40 725 296 320</strong></p>
<a href="whatsapp://send?phone=40725296320&text=2FA-828161"
style="display:inline-block; padding:14px 30px; background:#25D366;
color:white; font-size:18px; font-weight:bold; border-radius:8px;
text-decoration:none; margin-top:12px;">
💬 Send via WhatsApp
</a>
<p style="color:#888; font-size:13px; margin-top:12px;">
⏱ Code expires in 10 minutes - no typing required!
</p>
</div>
Esempio PHP completo
Pronto per il copia e incolla. Sostituisca YOUR_BUSINESS_ID e 'your-secret-key' con i valori di wappsync.com/mybusiness.
<?php
$businessid = YOUR_BUSINESS_ID; // from wappsync.com/mybusiness
$businesskey = 'your-secret-key'; // from wappsync.com/mybusiness - keep server-side
// ── Step 1: Request reverse OTP ──
$businessref = bin2hex(random_bytes(4));
$phone = $_POST['phone']; // user's phone from your form
$ts = time();
$hmac = hash_hmac('sha256',
"{$businessid}|{$businessref}|{$phone}|{$ts}",
$businesskey
);
$response = callAPI('https://wappsync.com/phone-verify/api/getReverseOTP', [
'businessid' => $businessid,
'businessref' => $businessref,
'phone' => $phone,
'ts' => $ts,
'hmac' => $hmac,
]);
$data = json_decode($response, true);
$code = $data['reverseotp_display']; // "2FA-828161"
$waphone = $data['waphone']; // "+40725296320"
$logincode = $data['logincode'];
$in_ts = $data['in_ts'];
// ── Show the code to your user (render frontend example above) ──
// ── Step 2: Poll until verified ──
$maxAttempts = 40; // ~2 minutes at 3s intervals
$attempt = 0;
do {
sleep(3);
$attempt++;
$hmac = hash_hmac('sha256',
"{$businessid}|{$businessref}|{$logincode}|{$in_ts}",
$businesskey
);
$response = callAPI(
'https://wappsync.com/phone-verify/api/getReverseOTPStatus',
[
'businessid' => $businessid,
'businessref' => $businessref,
'logincode' => $logincode,
'in_ts' => $in_ts,
'hmac' => $hmac,
]
);
$data = json_decode($response, true);
} while (($data['auth'] ?? 0) !== 1 && $attempt < $maxAttempts);
if (($data['auth'] ?? 0) === 1) {
// ✅ Verified - log the user in!
$phone = decryptPhoneAES($data['phoneEnc'], $businesskey);
$_SESSION['user_phone'] = $phone;
header('Location: /dashboard');
exit;
} else {
echo "Verification timed out. Please try again.";
}
// ── Helper ──
function callAPI($url, $payload) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
verify_sender: invii phone => '' (e facoltativamente mode => 'verify_sender') - non viene inviato nulla su WhatsApp, quindi deve trasmettere Lei il reverseotp_display al Suo cliente. Con auth=1, phoneEnc si decifra nel numero certificato del mittente; non c'è alcun sender_matches_intended da controllare.
accept_sender: per confirm_phone, aggiunga 'on_mismatch' => 'accept_sender'. Se auth=1 e sender_matches_intended è false, il numero certificato differisce da quello richiesto - lo accetti come numero corretto oppure richieda un nuovo OTP per il numero di cui ha effettivamente bisogno.
Gestione degli errori
L'API restituisce "status": "error" con un message leggibile:
| HTTP | message | Quando |
|---|---|---|
| 400 | Missing required parameters | Ha dimenticato un campo obbligatorio |
| 400 | A phone is required in confirm_phone mode | confirm_phone richiesto senza un telefono |
| 400 | Invalid mode / Invalid on_mismatch | Valore enum sconosciuto |
| 400 | The phone number is invalid or not a mobile number. | Formato del telefono non valido |
| 403 | Unknown or invalid business ID | businessid errato |
| 403 | Invalid HMAC | La firma non corrisponde - controlli la stringa da firmare |
| 409 | This request was already used. | businessref+in_ts duplicato |
Sicurezza
| 🔐 HMAC-signed | Ogni richiesta e risposta viene verificata con la Sua businesskey |
| 📱 Corrispondenza del telefono in base alla modalità | confirm_phone verifica che il mittente corrisponda al numero richiesto; verify_sender / accept_sender certificano solo il mittente effettivo - mai un numero che non ha inviato nulla |
| 🎯 Codici live univoci | Due codici in sospeso non condividono lo stesso valore, quindi un codice in arrivo viene associato in modo deterministico a una sola richiesta |
| 🔂 Single-use | I codici passano da 0→1→2, mai riutilizzabili |
| ⏱ Time-limited | I codici scadono dopo 10 minuti, massimo 4 tentativi di consegna |
| 🔒 Nessun segreto lato client | La Sua businesskey resta sul Suo server; mai nel codice del browser |
| 🛡 Cifrato AES-256 | I numeri di telefono nelle risposte sono cifrati con la Sua businesskey |
Provalo dal vivo
🎮 Flusso di accesso demo - una demo funzionante che mostra l'esperienza utente completa.
🧪 Strumento di test API - richiede il Suo businessid e la Sua businesskey da wappsync.com/mybusiness.