WappSync Phone Verify - Documentația API
Verificare telefonică în care utilizatorul dumneavoastră trimite un cod către noi prin WhatsApp - fără tastare OTP, o atingere, complet verificat.
Cuprins
Cum Funcționează
Dumneavoastră solicitați un cod
Backend-ul dumneavoastră apelează API-ul nostru cu numărul de telefon al utilizatorului. Returnăm un cod unic și numărul WhatsApp către care să fie trimis.
Utilizatorul îl trimite prin WhatsApp
Utilizatorul dumneavoastră atinge un link WhatsApp - codul este precompletat. Fără tastare, fără copiere-lipire. Doar apasă trimite.
Verificat instantaneu
Primim mesajul, vedem de la ce număr WhatsApp a fost trimis, iar interogarea dumneavoastră returnează auth=1 cu telefonul certificat. Gata!
Obțineți credențialele dumneavoastră
Înregistrați-vă la wappsync.com/mybusiness pentru a primi:
| Credențiale | Descriere |
|---|---|
businessid | ID-ul dumneavoastră numeric de afaceri |
businesskey | Cheia dumneavoastră secretă - nu o partajați niciodată, nu o puneți niciodată în codul client-side |
businesskey este folosit pentru semnarea HMAC și nu trebuie să apară niciodată în JavaScript din browser, în sursa HTML sau în codul aplicației mobile.Două moduri de verificare
Phone Verify funcționează în două moduri, alese per cerere. În ambele, utilizatorul dumneavoastră trimite codul către noi prin WhatsApp - singura diferență este care număr de telefon este certificat.
confirm_phone (default) | verify_sender | |
|---|---|---|
| Dumneavoastră trimiteți | un număr de telefon N | nimic (niciun număr) |
| Ce se certifică | că apelantul controlează în mod specific N | oricare număr care trimite efectiv codul înapoi |
| Utilizare tipică | autentificare / recuperare pe un număr din evidență, protecție împotriva schimbării SIM | înregistrare nouă - „dă-mi un telefon real și dovedit pentru acest client” |
| Livrare cod | Trimis prin WhatsApp către N și afișat în interfața dumneavoastră (delivery: pushed_to_phone) | doar prin dumneavoastră (delivery: relay_by_business) - dumneavoastră îi înmânați codul clientului |
| Rezultatul interogării | sender_matches_intended vă spune dacă expeditorul este N | phoneEnc este numărul certificat; sender_matches_intended este omis |
confirm_phone dovedește controlul asupra unui număr declarat specific; verify_sender dovedește controlul asupra unui număr și raportează care. Dacă fluxul dumneavoastră necesită „numărul din acest cont aparține cu adevărat utilizatorului”, rămâneți la confirm_phone cu on_mismatch: reject.Telefon corectat (on_mismatch): un caz frecvent este clientul care declară A dar trimite codul de pe B (greșeală de tastare / dual-SIM). În confirm_phone, reject (implicit) tratează aceasta ca o încercare eșuată; accept_sender certifică în schimb expeditorul real B (sender_matches_intended: false, phoneEnc = B), iar backend-ul dumneavoastră decide dacă acceptă numărul corectat B sau solicită un OTP nou pentru A.
Solicitați un OTP invers
Apelați acest lucru din backend-ul dumneavoastră când trebuie să verificați un utilizator:
POSThttps://wappsync.com/phone-verify/api/getReverseOTP
Corpul cererii (JSON)
| Câmp | Tip | Descriere |
|---|---|---|
businessid | int | ID-ul dumneavoastră de afaceri |
businessref | string | O referință unică pe care o generați pentru această cerere de autentificare (de ex. bin2hex(random_bytes(4))) |
phone | string | Numărul de telefon al utilizatorului în format internațional (+40755123456). Obligatoriu în modul confirm_phone; omiteți sau lăsați gol în verify_sender. |
mode | string | Opțional - confirm_phone (implicit când se furnizează un telefon) sau verify_sender (implicit când telefonul lipsește) |
on_mismatch | string | Opțional (doar confirm_phone) - reject (implicit) sau accept_sender (certifică expeditorul real dacă codul ajunge de la alt număr) |
ts | int | Timestamp Unix curent |
hmac | string | Semnătură HMAC-SHA256 |
Semnare HMAC
Semnați acest șir cu businesskey:
{businessid}|{businessref}|{phone}|{ts}
În modul verify_sender nu există telefon, deci șirul semnat este {businessid}|{businessref}||{ts} (slotul din mijloc gol).
Exemplu:
$hmac = hash_hmac('sha256', "{$businessid}|{$businessref}|{$phone}|{$ts}", $businesskey);
Răspuns
| Câmp | Tip | Descriere |
|---|---|---|
status | string | "ok" or "error" |
reverseotp_display | string | Codul pe care îl trimite utilizatorul dumneavoastră, de ex. "2FA-828161" |
waphone | string | Numărul WhatsApp CĂTRE care utilizatorul dumneavoastră trimite codul |
logincode | string | Cod intern de folosit la interogare |
in_ts | int | Timestamp pentru cererea de interogare |
out_ts | int | Timestamp al răspunsului |
otp_valid_minutes | int | Cât timp este valabil codul (implicit 10) |
mode | string | Modul activ: confirm_phone sau verify_sender |
delivery | string | pushed_to_phone (confirm_phone: codul este trimis prin WhatsApp și către telefonul declarat) sau relay_by_business (verify_sender: trebuie să livrați codul clientului dumneavoastră) |
hmac | string | HMAC-ul răspunsului - verificați cu businesskey |
Verificați HMAC-ul răspunsului against {businessid}|{businessref}|{logincode}|{reverseotp_display}|{waphone}|{out_ts}.
Ce să afișați utilizatorului dumneavoastră
Afișați codul și numărul de telefon. Folosiți un link whatsapp://send pentru ca utilizatorul să îl poată trimite cu o singură atingere:
<a href="whatsapp://send?phone=40725296320&text=2FA-828161">
💬 Send Code via WhatsApp
</a>
Interogare pentru verificare
Interogați la fiecare 2-3 secunde până când utilizatorul este verificat:
POSThttps://wappsync.com/phone-verify/api/getReverseOTPStatus
Corpul cererii (JSON)
| Câmp | Tip | Descriere |
|---|---|---|
businessid | int | ID-ul dumneavoastră de afaceri |
businessref | string | Aceeași referință ca la apelul anterior |
logincode | string | logincode din răspunsul getReverseOTP |
in_ts | int | ts-ul original din cererea getReverseOTP |
hmac | string | HMAC-SHA256 pentru {businessid}|{businessref}|{logincode}|{in_ts} |
Răspuns
| Câmp | Tip | Semnificație |
|---|---|---|
used | 0 | ⏳ Încă se așteaptă - interogați din nou |
used | 1 | ✅ Tocmai verificat - prima interogare care vede acest lucru îl consumă |
used | 2 | 🔒 Deja consumat de o interogare anterioară |
auth | 1 | Utilizatorul este verificat - autentificați-l! |
phoneEnc | string | Telefon certificat criptat AES-256-CBC (doar când auth=1) - expeditorul când un cod a fost primit (identic cu numărul dumneavoastră declarat în confirm_phone strict) |
tries | int | Încercările eșuate sunt numărate (cod greșit sau telefon greșit) |
expired | bool | true când prea multe încercări eșuate (încercări ≥ 4) - solicitați un OTP nou |
mode | string | Modul acestei cereri: confirm_phone sau verify_sender |
sender_matches_intended | bool | confirm_phone numai, după ce un cod a fost primit - true = expeditorul este numărul pe care ați cerut să îl verificați; false = un expeditor corectat a fost certificat. Omis în verify_sender. |
out_ts | int | Timestamp al răspunsului |
hmac | string | HMAC - verificați cu {businessid}|{businessref}|{logincode}|{used}|{phoneEnc}|{out_ts} |
Când auth === 1, un cod valid a fost primit. Decriptați phoneEnc pentru a obține telefonul certificat (verificați sender_matches_intended în modul confirm_phone), apoi autentificați utilizatorul.
Decriptați numărul de telefon
Când auth=1, phoneEnc conține telefonul certificat (expeditorul care s-a dovedit) criptat cu AES-256-CBC folosind 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
Exemplu frontend
Singura interfață de care aveți nevoie - afișați după ce backend-ul dumneavoastră apelează 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>
Exemplu PHP complet
Gata de copiere-lipire. Înlocuiți YOUR_BUSINESS_ID și 'your-secret-key' cu valorile de la 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: trimiteți phone => '' (și opțional mode => 'verify_sender') - nu se trimite nimic pe WhatsApp, deci transmiteți dumneavoastră codul reverseotp_display clientului. La auth=1, phoneEnc se decriptează la numărul certificat al expeditorului; nu există sender_matches_intended de verificat.
accept_sender: pentru confirm_phone, adăugați 'on_mismatch' => 'accept_sender'. Dacă auth=1 și sender_matches_intended este false, numărul certificat diferă de cel solicitat - acceptați-l ca număr corectat sau solicitați un OTP nou pentru numărul de care aveți nevoie.
Gestionarea erorilor
API-ul returnează "status": "error" cu un message inteligibil:
| HTTP | message | Când |
|---|---|---|
| 400 | Missing required parameters | Ați uitat un câmp obligatoriu |
| 400 | A phone is required in confirm_phone mode | confirm_phone solicitat fără un telefon |
| 400 | Invalid mode / Invalid on_mismatch | Valoare enum necunoscută |
| 400 | The phone number is invalid or not a mobile number. | Format de telefon incorect |
| 403 | Unknown or invalid business ID | businessid greșit |
| 403 | Invalid HMAC | Semnătura nu corespunde - verificați șirul de semnat |
| 409 | This request was already used. | businessref+in_ts duplicat |
Securitate
| 🔐 HMAC-signed | Fiecare cerere și răspuns este verificat cu businesskey |
| 📱 Potrivire de telefon în funcție de mod | confirm_phone verifică că expeditorul corespunde numărului solicitat; verify_sender / accept_sender certifică doar expeditorul real - niciodată un număr care nu a trimis |
| 🎯 Coduri live unice | Două coduri în așteptare nu au aceeași valoare, astfel încât un cod primit se mapează determinist la o singură cerere |
| 🔂 Single-use | Codurile trec prin 0→1→2, niciodată reutilizabile |
| ⏱ Time-limited | Codurile expiră după 10 minute, maximum 4 încercări de livrare |
| 🔒 Fără secrete de client | businesskey rămâne pe serverul dumneavoastră; niciodată în codul din browser |
| 🛡 Criptat AES-256 | Numerele de telefon din răspunsuri sunt criptate cu businesskey |
Încercați live
🎮 Flux de autentificare demo - un demo funcțional care arată experiența completă a utilizatorului.
🧪 Instrument de testare API - necesită propriile businessid și businesskey de la wappsync.com/mybusiness.