WhatsApp арқылы OTP интеграциясы
Қосымшаңызды Cascade сервисіне қосуға арналған құжаттама.
Базалық URL: https://otp.kztusdt.kz/api
Мазмұны
- Жалпы схема
- API-токенді алу
- Авторизация
- Телефон нөмірінің пішімі
- OTP жіберу
- Қысқа сілтемелер
- OTP тексеру
- Жауап кодтары мен қателер
- Шектеулер
- Интеграция мысалдары
- Ұсыныстар
- Шығыс webhooks
Жалпы схема
┌─────────────────┐ POST /otp/send ┌──────────────────┐
│ Сіздің қосымша │ ──────────────────────► │ otp.kztusdt.kz │
│ (сайт, API) │ │ Laravel API │
└────────┬────────┘ └────────┬─────────┘
│ │
│ Пайдаланушы кодты енгізеді │ WhatsApp
│ ▼
│ ┌──────────────────┐
│ POST /otp/verify │ Клиент нөмірі │
└───────────────────────────────► └──────────────────┘
Типтік сценарий:
- Пайдаланушы қосымшаңызда телефон нөмірін енгізеді.
- Сіздің бэкенд
POST /api/otp/sendшақырады. - Клиент көрсетілген нөмірге WhatsApp арқылы код алады.
- Пайдаланушы кодты сіздің формаңызда енгізеді.
- Сіздің бэкенд
POST /api/otp/verifyшақырады. - Сәтті болғанда — аккаунтты / кіруді / операцияны растайсыз.
API-токенді алу
- Компания кабинетіне кіріңіз: https://otp.kztusdt.kz/cabinet
- API-кілттер бөлімін ашыңыз
- Жасау батырмасын басыңыз
- Атауын көрсетіңіз (мысалы,
Менің сайтым) - Кілтті көшіріңіз — оны тізімнен қайта көруге болады («Көрсету» батырмасы)
Токенді тек серверде сақтаңыз (орта айнымалылары, secrets). Оны фронтендке, мобильді қосымшаға немесе ашық репозиторийге салмаңыз.
Авторизация
OTP API-ға барлық сұрауларда мына тақырып қажет:
Authorization: Bearer <СІЗДІҢ_API_ТОКЕНІҢІЗ>
Content-Type: application/json
Accept: application/json
Токен дұрыс емес немесе жоқ болса, сервер 401 Unauthorized қайтарады:
{
"success": false,
"message": "Invalid API token"
}
Телефон нөмірінің пішімі
phone өрісі — жол, тек цифрлар немесе пішімдеу таңбаларымен (олар жойылады).
| Енгізу | Нормаланған түрі |
|---|---|
+7 700 123 45 67 |
77001234567 |
87001234567 |
77001234567 |
77001234567 |
77001234567 |
Ережелер:
- Нормалаудан кейінгі ұзындығы: 10–15 цифр
- Басында
8бар нөмір (11 цифр, Қазақстан) автоматты түрде7…болып ауыстырылады
OTP жіберу
Сұрау
POST /api/otp/send
Дене (JSON):
| Өріс | Түрі | Міндетті | Сипаттама |
|---|---|---|---|
phone |
string | иә | Алушының телефон нөмірі |
purpose |
string | жоқ | Кодтың мақсаты (әдепкі verification) |
channel |
string | жоқ | whatsapp, telegram, sms немесе auto. Берілмесе — кабинеттегі әдепкі канал (Откуда отправлять). auto WhatsApp пен Telegram нөмірлері арасында жүктемені тең бөледі; Telegram жібермесе — WhatsApp арқылы қайталайды. Өшірілген канал қате қайтарады. |
link |
string | жоқ | Толық http/https URL — қысқартылып, сол хабарламаға қосылады |
link_expires_in |
integer | жоқ | Қысқа сілтеменің мерзімі секундпен (60–2592000) |
Мысал:
{
"phone": "77001234567",
"purpose": "registration",
"link": "https://example.com/confirm/abc"
}
purpose өрісі әртүрлі сценарийлер үшін кодтарды бөлуге мүмкіндік береді (тіркелу, кіру, құпия сөзді қалпына келтіру). Тексеру кезінде сол purpose берілуі керек.
link берілсе, сервис https://otp.kztusdt.kz/s/Ab3xK9 сияқты қысқа сілтеме жасап, оны кодпен бір хабарламаға қосады. Жеткізу құны: WhatsApp/Telegram = 1 токен, SMS = 16 токен (код+сілтеме бірге құнын екі еселемейді).
Сәтті жауап — 200 OK
{
"success": true,
"message": "OTP отправлен через WhatsApp",
"expires_in": 300,
"short_url": "https://otp.kztusdt.kz/s/Ab3xK9"
}
| Өріс | Сипаттама |
|---|---|
expires_in |
Кодтың өмір сүру уақыты секундпен (әдепкі 300 = 5 минут) |
short_url |
Қысқа сілтеме (тек link берілгенде) |
Қателер — 422 Unprocessable Entity
{
"success": false,
"message": "Неверный формат номера телефона"
}
{
"success": false,
"message": "WhatsApp не подключён. Обратитесь к администратору."
}
{
"success": false,
"message": "Подождите перед повторной отправкой OTP"
}
{
"success": false,
"message": "Не удалось отправить OTP через WhatsApp"
}
Қысқа сілтемелер
Қысқа сілтемелер сол доменде жұмыс істейді: https://otp.kztusdt.kz/s/{slug} → мақсатты URL-ге 302. Кликтар есептеледі. Белсенді емес немесе мерзімі өткен сілтемелер 404 қайтарады.
Басқару — компания кабинетінде (Қысқа сілтемелер): жасау, көшіру, кликтар, мерзім, қосу/өшіру.
Жібермей қысқарту — тегін
POST /api/links/shorten
| Өріс | Түрі | Міндетті | Сипаттама |
|---|---|---|---|
url |
string | иә | Мақсатты http/https URL |
alias |
string | жоқ | Өз slug (3–32: әріптер, цифрлар, -, _) |
title |
string | жоқ | Кабинетке арналған атау |
expires_in |
integer | жоқ | Мерзім секундпен |
{
"url": "https://example.com/very/long/path",
"alias": "promo-may"
}
{
"success": true,
"short_url": "https://otp.kztusdt.kz/s/promo-may",
"slug": "promo-may",
"expires_at": null
}
Кодсыз сілтеме жіберу — 1 токен
POST /api/links/send
| Өріс | Түрі | Міндетті | Сипаттама |
|---|---|---|---|
phone |
string | иә | Алушының нөмірі |
url |
string | иә | Мақсатты http/https URL |
channel |
string | жоқ | whatsapp, telegram, sms немесе auto (компания баптауларында рұқсат / жарамды болуы керек) |
text |
string | жоқ | :link плейсхолдері бар мәтін (әйтпесе әдепкі шаблон) |
expires_in |
integer | жоқ | Қысқа сілтеменің мерзімі |
{
"phone": "77001234567",
"url": "https://example.com/promo",
"text": "Жеңілдік: :link"
}
{
"success": true,
"message": "Ссылка отправлена через WhatsApp",
"short_url": "https://otp.kztusdt.kz/s/Ab3xK9",
"slug": "Ab3xK9"
}
Биллинг: WhatsApp пен Telegram жеткізуі 1 токен, SMS — 16 токен. auto режимінде алдымен ең аз жүктелген WhatsApp/Telegram нөмірі таңдалады; SMS тек мессенджерлер қолжетімсіз болғанда қолданылады (SMS қосулы, баланс ≥ 16). Жібермей қысқарту тегін.
OTP тексеру
Сұрау
POST /api/otp/verify
Дене (JSON):
| Өріс | Түрі | Міндетті | Сипаттама |
|---|---|---|---|
phone |
string | иә | Жіберу кезіндегі сол нөмір |
code |
string | иә | WhatsApp-тан келген код |
purpose |
string | жоқ | send кезіндегі сол мән (әдепкі verification) |
Мысал:
{
"phone": "77001234567",
"code": "482910",
"purpose": "registration"
}
Сәтті жауап — 200 OK
{
"success": true,
"message": "Номер подтверждён"
}
Сәтті тексеруден кейін код бір реттік — сол кодты қайта пайдалану қате қайтарады.
Қате — 422 Unprocessable Entity
{
"success": false,
"message": "Неверный или просроченный код"
}
Жауап кодтары мен қателер
| HTTP | Мағынасы |
|---|---|
200 |
Сәтті (success: true) |
401 |
API-токен жоқ немесе дұрыс емес |
422 |
Бизнес-логика қатесі (success: false) |
422 |
Өрістерді валидациялау қатесі (Laravel validation) |
Валидация (мысал):
{
"message": "The phone field is required.",
"errors": {
"phone": ["The phone field is required."]
}
}
Жауап денесіндегі success өрісін әрдайым тексеріңіз, тек HTTP-статусқа ғана қарамаңыз.
Шектеулер
| Параметр | Әдепкі мән |
|---|---|
| Код ұзындығы | 6 цифр |
| Жарамдылық мерзімі | 300 сек (5 мин) |
| Сол нөмірге қайта жіберу | 60 сек ішінде 1 реттен жиі емес |
WhatsApp хабарламасы (үлгі):
Ваш код подтверждения: 123456. Действителен 5 мин. Не сообщайте код никому.
Интеграция мысалдары
cURL
# OTP жіберу
curl -X POST "https://otp.kztusdt.kz/api/otp/send" \
-H "Authorization: Bearer СІЗДІҢ_API_ТОКЕНІҢІЗ" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"phone":"77001234567","purpose":"registration"}'
# Кодты тексеру
curl -X POST "https://otp.kztusdt.kz/api/otp/verify" \
-H "Authorization: Bearer СІЗДІҢ_API_ТОКЕНІҢІЗ" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"phone":"77001234567","code":"482910","purpose":"registration"}'
PHP (Laravel / Guzzle)
<?php
declare(strict_types=1);
use Illuminate\Support\Facades\Http;
final class OtpClient
{
public function __construct(
private readonly string $baseUrl = 'https://otp.kztusdt.kz/api',
private readonly string $token = '', // env('OTP_API_TOKEN')-ден
) {}
public function send(string $phone, string $purpose = 'verification'): array
{
$response = Http::withToken($this->token)
->acceptJson()
->post("{$this->baseUrl}/otp/send", [
'phone' => $phone,
'purpose' => $purpose,
]);
return $response->json();
}
public function verify(string $phone, string $code, string $purpose = 'verification'): array
{
$response = Http::withToken($this->token)
->acceptJson()
->post("{$this->baseUrl}/otp/verify", [
'phone' => $phone,
'code' => $code,
'purpose' => $purpose,
]);
return $response->json();
}
}
// Пайдалану
$otp = new OtpClient(token: config('services.otp.token'));
$result = $otp->send('77001234567', 'registration');
if (! ($result['success'] ?? false)) {
throw new RuntimeException($result['message'] ?? 'OTP send failed');
}
$check = $otp->verify('77001234567', '482910', 'registration');
if ($check['success'] ?? false) {
// нөмір расталды — сессия жасаңыз / пайдаланушыны белсендіріңіз
}
JavaScript (Node.js / fetch)
const BASE_URL = 'https://otp.kztusdt.kz/api';
const API_TOKEN = process.env.OTP_API_TOKEN;
async function sendOtp(phone, purpose = 'verification') {
const res = await fetch(`${BASE_URL}/otp/send`, {
method: 'POST',
headers: {
Authorization: `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({ phone, purpose }),
});
return res.json();
}
async function verifyOtp(phone, code, purpose = 'verification') {
const res = await fetch(`${BASE_URL}/otp/verify`, {
method: 'POST',
headers: {
Authorization: `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({ phone, code, purpose }),
});
return res.json();
}
// Мысал
const sent = await sendOtp('77001234567', 'login');
if (!sent.success) {
console.error(sent.message);
}
const verified = await verifyOtp('77001234567', '123456', 'login');
if (verified.success) {
console.log('OK');
}
Python
import os
import requests
BASE_URL = "https://otp.kztusdt.kz/api"
TOKEN = os.environ["OTP_API_TOKEN"]
headers = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
}
def send_otp(phone: str, purpose: str = "verification") -> dict:
r = requests.post(
f"{BASE_URL}/otp/send",
json={"phone": phone, "purpose": purpose},
headers=headers,
timeout=30,
)
return r.json()
def verify_otp(phone: str, code: str, purpose: str = "verification") -> dict:
r = requests.post(
f"{BASE_URL}/otp/verify",
json={"phone": phone, "code": code, "purpose": purpose},
headers=headers,
timeout=30,
)
return r.json()
Ұсыныстар
Қауіпсіздік
- API-ды тек бэкендтен шақырыңыз, браузерден тікелей емес.
- API-токен мен OTP-кодтарды ашық түрде логқа жазбаңыз.
- Өз жағыңызда код енгізу әрекеттерін шектеңіз (мысалы, 5 әрекет → 15 минутқа бұғаттау).
UX
- Қайта жіберуге дейін таймер көрсетіңіз (кемінде 60 сек).
- Пайдаланушыға код WhatsApp-қа келетінін, SMS емес екенін айтыңыз.
- Нөмірде WhatsApp орнатылған болуы керек.
Әртүрлі сценарийлер (purpose)
| purpose | Қашан қолдану |
|---|---|
registration |
Жаңа пайдаланушыны тіркеу |
login |
Нөмір бойынша кіру |
password_reset |
Құпия сөзді қалпына келтіру |
verification |
Жалпы верификация (әдепкі) |
Бір нөмір үшін бір уақытта әртүрлі purpose бар бірнеше белсенді код болуы мүмкін.
Өз жағыңызда қателерді өңдеу
| API хабарламасы | Қосымшадағы әрекет |
|---|---|
WhatsApp не подключён |
«Сервис уақытша қолжетімсіз» көрсету, әкімшіге хабарлау |
Подождите перед повторной отправкой |
Таймері бар «Қайта жіберу» батырмасын көрсету |
Неверный или просроченный код |
Кодты қайта енгізуді немесе жаңасын сұрауды ұсыну |
Неверный формат номера |
Телефон өрісін бөлектеу |
Продакшенге дейінгі тексеру
- Админкада WhatsApp қосылған (WhatsApp → Қосу).
- API-токен жасалған және белсенді.
- Нақты WhatsApp нөміріне тесттік
send+verify. - OTP тарихында жіберу туралы жазба көрінеді.
Шығыс webhooks
Кабинетте (Интеграция → Webhooks) сервис оқиғалар жіберетін URL көрсетуге болады:
| Оқиға | Қашан |
|---|---|
otp.sent |
Код сәтті жіберілді |
otp.verified |
Код расталды |
otp.failed |
Жіберу / есептен шығару қатесі |
Сұрау: JSON-денені POST. Тақырыптар:
Content-Type: application/json
X-Webhook-Event: otp.sent
X-Webhook-Signature: sha256=<hmac_sha256_hex_of_raw_body>
Қолтаңба: webhook құпиясымен сұраудың шикі денесінен HMAC-SHA256 (жасау / ротация кезінде бір рет көрсетіледі).
Тексеру мысалы (PHP):
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
hash_equals($expected, $request->header('X-Webhook-Signature'));
Payload мысалы:
{
"id": "evt_01h…",
"event": "otp.sent",
"created_at": "2026-07-21T10:00:00+00:00",
"company_id": 1,
"data": {
"otp_log_id": 42,
"phone": "77001234567",
"purpose": "verification",
"status": "sent",
"api_token_id": 3,
"session_name": "wa-1",
"expires_at": "2026-07-21T10:05:00+00:00",
"verified_at": null,
"error_message": null
}
}
Жеткізу асинхронды (кезек). php artisan queue:work қажет. 3 әрекетке дейін қайталау.
Қолдау
Қосу, төлем және сервистің жұмысы бойынша сұрақтар үшін:
- Email: support@otp.kztusdt.kz
- Телефон: +7 (777) 123-45-67