WappSync
A

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.

Cum Funcționează

1

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.

2

Utilizatorul îl trimite prin WhatsApp

Utilizatorul dumneavoastră atinge un link WhatsApp - codul este precompletat. Fără tastare, fără copiere-lipire. Doar apasă trimite.

3

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țialeDescriere
businessidID-ul dumneavoastră numeric de afaceri
businesskeyCheia dumneavoastră secretă - nu o partajați niciodată, nu o puneți niciodată în codul client-side
Important: Toate apelurile API trebuie să vină de la backend-ul dumneavoastră. 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țiun număr de telefon Nnimic (niciun număr)
Ce se certificăcă apelantul controlează în mod specific Noricare 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 codTrimis 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ăriisender_matches_intended vă spune dacă expeditorul este NphoneEnc este numărul certificat; sender_matches_intended este omis
Securitate: 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âmpTipDescriere
businessidintID-ul dumneavoastră de afaceri
businessrefstringO referință unică pe care o generați pentru această cerere de autentificare (de ex. bin2hex(random_bytes(4)))
phonestringNumă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.
modestringOpțional - confirm_phone (implicit când se furnizează un telefon) sau verify_sender (implicit când telefonul lipsește)
on_mismatchstringOpțional (doar confirm_phone) - reject (implicit) sau accept_sender (certifică expeditorul real dacă codul ajunge de la alt număr)
tsintTimestamp Unix curent
hmacstringSemnă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âmpTipDescriere
statusstring"ok" or "error"
reverseotp_displaystringCodul pe care îl trimite utilizatorul dumneavoastră, de ex. "2FA-828161"
waphonestringNumărul WhatsApp CĂTRE care utilizatorul dumneavoastră trimite codul
logincodestringCod intern de folosit la interogare
in_tsintTimestamp pentru cererea de interogare
out_tsintTimestamp al răspunsului
otp_valid_minutesintCât timp este valabil codul (implicit 10)
modestringModul activ: confirm_phone sau verify_sender
deliverystringpushed_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ă)
hmacstringHMAC-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âmpTipDescriere
businessidintID-ul dumneavoastră de afaceri
businessrefstringAceeași referință ca la apelul anterior
logincodestringlogincode din răspunsul getReverseOTP
in_tsintts-ul original din cererea getReverseOTP
hmacstringHMAC-SHA256 pentru {businessid}|{businessref}|{logincode}|{in_ts}

Răspuns

CâmpTipSemnificație
used0⏳ Încă se așteaptă - interogați din nou
used1✅ Tocmai verificat - prima interogare care vede acest lucru îl consumă
used2🔒 Deja consumat de o interogare anterioară
auth1Utilizatorul este verificat - autentificați-l!
phoneEncstringTelefon 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)
triesintÎncercările eșuate sunt numărate (cod greșit sau telefon greșit)
expiredbooltrue când prea multe încercări eșuate (încercări ≥ 4) - solicitați un OTP nou
modestringModul acestei cereri: confirm_phone sau verify_sender
sender_matches_intendedboolconfirm_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_tsintTimestamp al răspunsului
hmacstringHMAC - 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:

HTTPmessageCând
400Missing required parametersAți uitat un câmp obligatoriu
400A phone is required in confirm_phone modeconfirm_phone solicitat fără un telefon
400Invalid mode / Invalid on_mismatchValoare enum necunoscută
400The phone number is invalid or not a mobile number.Format de telefon incorect
403Unknown or invalid business IDbusinessid greșit
403Invalid HMACSemnătura nu corespunde - verificați șirul de semnat
409This request was already used.businessref+in_ts duplicat

Securitate

🔐 HMAC-signedFiecare cerere și răspuns este verificat cu businesskey
📱 Potrivire de telefon în funcție de modconfirm_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 uniceDouă coduri în așteptare nu au aceeași valoare, astfel încât un cod primit se mapează determinist la o singură cerere
🔂 Single-useCodurile trec prin 0→1→2, niciodată reutilizabile
⏱ Time-limitedCodurile expiră după 10 minute, maximum 4 încercări de livrare
🔒 Fără secrete de clientbusinesskey rămâne pe serverul dumneavoastră; niciodată în codul din browser
🛡 Criptat AES-256Numerele 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.