ارسال و اعتبارسنجی OTP

SMSDaily دو مدل OTP ارائه می‌کند. در هر دو مدل، الگوی OTP باید قبلاً در حساب تعریف و فعال شده باشد و شامل متغیر کد باشد. مدل اول برای اغلب سامانه‌ها پیشنهاد می‌شود، چون خود کد OTP از Backend مشتری خارج نمی‌شود.

مدل اول: تایید سمت SMSDaily

۱. ایجاد چالش OTP

POST /v1/otp/challenges
X-API-Key: YOUR_API_KEY
Idempotency-Key: login-09121234567-781
Content-Type: application/json
{
  "mobile": "09121234567",
  "patternCode": "login-otp",
  "sender": "300099000121",
  "clientReference": "login-781"
}
فیلد نوع الزام توضیح
mobile string الزامی شماره موبایل دریافت‌کننده OTP
patternCode string الزامی کد الگوی OTP فعال حساب
sender string/null اختیاری فرستنده موردنظر؛ در صورت وجود فرستنده پیش‌فرض الگو قابل حذف است
clientReference string/null اختیاری شناسه عملیات در Backend مشتری

پاسخ:

{
  "trackingCode": "SMS-20260810-A1B2C3D4",
  "expiresAt": "2026-08-10T07:32:00Z"
}

در این مدل کد OTP در پاسخ API برگردانده نمی‌شود. trackingCode را همراه نشست یا عملیات ورود خود نگهداری کنید.

۲. بررسی کد واردشده توسط مخاطب

POST /v1/otp/challenges/SMS-20260810-A1B2C3D4/verify
X-API-Key: YOUR_API_KEY
Content-Type: application/json
{
  "code": "481923"
}

نمونه پاسخ صحیح:

{
  "trackingCode": "SMS-20260810-A1B2C3D4",
  "valid": true,
  "status": "verified",
  "verifiedAt": "2026-08-10T07:30:14Z"
}

نمونه پاسخ کد اشتباه:

{
  "trackingCode": "SMS-20260810-A1B2C3D4",
  "valid": false,
  "status": "pending",
  "verifiedAt": null
}

وضعیت‌های عمومی OTP در این قرارداد:

status معنا
pending چالش هنوز قابل بررسی است
verified کد صحیح تایید شده است
expired زمان اعتبار چالش تمام شده است
locked چالش دیگر اجازه تلاش جدید ندارد

کد اشتباه یک خطای HTTP محسوب نمی‌شود؛ پاسخ 200 OK با valid: false دریافت می‌کنید. بنابراین منطق برنامه را براساس valid و status بنویسید، نه صرفاً Status Code HTTP.

نمونه C# برای مدل تایید سمت SMSDaily

using System.Net.Http.Json;
using System.Text.Json;

var client = new HttpClient
{
    BaseAddress = new Uri("https://service.smsdaily.ir")
};
client.DefaultRequestHeaders.Add("X-API-Key", apiKey);

var start = new HttpRequestMessage(HttpMethod.Post, "/v1/otp/challenges");
start.Headers.Add("Idempotency-Key", $"login-{userId}-{attemptId}");
start.Content = JsonContent.Create(new
{
    mobile = "09121234567",
    patternCode = "login-otp",
    clientReference = $"login-{attemptId}"
});

using var startResponse = await client.SendAsync(start);
startResponse.EnsureSuccessStatusCode();
using var startJson = JsonDocument.Parse(await startResponse.Content.ReadAsStringAsync());
var trackingCode = startJson.RootElement.GetProperty("trackingCode").GetString()!;

var verifyResponse = await client.PostAsJsonAsync(
    $"/v1/otp/challenges/{trackingCode}/verify",
    new { code = userEnteredCode });
verifyResponse.EnsureSuccessStatusCode();

using var verifyJson = JsonDocument.Parse(await verifyResponse.Content.ReadAsStringAsync());
var valid = verifyJson.RootElement.GetProperty("valid").GetBoolean();
if (valid)
{
    // عملیات ورود/تایید را در Backend خود تکمیل کنید.
}

مدل دوم: تایید در Backend مشتری

اگر سامانه مشتری خودش کد را ذخیره و بررسی می‌کند، از مسیر زیر استفاده کنید:

POST /v1/otp/codes
X-API-Key: YOUR_API_KEY
Idempotency-Key: legacy-login-781
Content-Type: application/json
{
  "mobile": "09121234567",
  "patternCode": "login-otp",
  "sender": "300099000121",
  "clientReference": "legacy-login-781"
}

نمونه پاسخ:

{
  "trackingCode": "SMS-20260810-5F9A04C1",
  "code": "735291",
  "expiresAt": "2026-08-10T07:32:00Z"
}

در این مدل، code فقط باید داخل Backend امن مشتری نگهداری شود. آن را در Log عمومی، Analytics، URL، Local Storage مرورگر یا پاسخ API خودتان به Frontend قرار ندهید.

نمونه C# برای مدل تایید سمت مشتری

var request = new HttpRequestMessage(HttpMethod.Post, "/v1/otp/codes");
request.Headers.Add("Idempotency-Key", $"otp-{userId}-{attemptId}");
request.Content = JsonContent.Create(new
{
    mobile = "09121234567",
    patternCode = "login-otp",
    clientReference = $"login-{attemptId}"
});

using var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();

using var json = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
var trackingCode = json.RootElement.GetProperty("trackingCode").GetString()!;
var otpCode = json.RootElement.GetProperty("code").GetString()!;
var expiresAt = json.RootElement.GetProperty("expiresAt").GetDateTimeOffset();

// otpCode را فقط در ذخیره‌سازی امن و کوتاه‌عمر Backend نگهداری کنید.

پاسخ‌ها و خطاهای مهم

HTTP کاربرد
202 چالش یا کد جدید ایجاد و برای ارسال ثبت شد
200 درخواست تکراری معتبر یا نتیجه Verify
400 ورودی نامعتبر
401 API Key نامعتبر
404 الگو یا trackingCode پیدا نشد
409 وضعیت درخواست با عملیات سازگار نیست
429 محدودیت نرخ
503 سرویس موقتاً در دسترس نیست

توصیه انتخاب مدل

برای ورود، تایید شماره همراه و عملیات حساس، مدل تایید سمت SMSDaily انتخاب ساده‌تر و امن‌تری است. مدل دوم برای سامانه‌هایی نگه داشته شده که الزام معماری دارند اعتبارسنجی OTP را در Backend خود انجام دهند.