دات‌نت (C# .NET 8 / 9) پلتفرم اصلی توسعه سیستم‌های سازمانی، پورتال‌های بانکی و سامانه‌های اداری کشور است. در این آموزش به شیوه اصولی و استاندارد، سرویس ارسال پیامک و اعتبارسنجی OTP را با استفاده از تزریق وابستگی (Dependency Injection) و IHttpClientFactory در ASP.NET Core پیاده‌سازی می‌کنیم.

تعریف اینترفیس سرویس (ISmsService.cs)

public interface ISmsService { Task<bool> SendOtpAsync(string mobile, string patternCode, Dictionary<string, object> parameters); Task<bool> SendSimpleSmsAsync(string mobile, string message); }

پیاده‌سازی سرویس با Typed HttpClient (FreeSmsService.cs)

using System.Net.Http.Json; public class FreeSmsService : ISmsService { private readonly HttpClient _httpClient; public FreeSmsService(HttpClient httpClient) { _httpClient = httpClient; } public async Task<bool> SendOtpAsync(string mobile, string patternCode, Dictionary<string, object> parameters) { var payload = new { to = mobile, pattern_code = patternCode, params = parameters }; var response = await _httpClient.PostAsJsonAsync("otp", payload); return response.IsSuccessStatusCode; } public async Task<bool> SendSimpleSmsAsync(string mobile, string message) { var payload = new { to = new[] { mobile }, text = message }; var response = await _httpClient.PostAsJsonAsync("send", payload); return response.IsSuccessStatusCode; } }

پیکربندی در فایل Program.cs

در فایل Program.cs سرویس را به عنوان Typed Client با تنظیمات هدر و تایم‌اوت اضافه کنید:

builder.Services.AddHttpClient<ISmsService, FreeSmsService>(client => { client.BaseAddress = new Uri("https://api.free-sms.ir/v1/"); client.DefaultRequestHeaders.Add("Authorization", $"Bearer {builder.Configuration["FreeSms:ApiKey"]}"); client.Timeout = TimeSpan.FromSeconds(5); });

تنظیمات فایل appsettings.json

{ "FreeSms": { "ApiKey": "YOUR_FREE_SMS_API_KEY" } }

استفاده در Minimal API یا Controller

app.MapPost("/api/auth/send-code", async (string mobile, ISmsService smsService) => { var code = new Random().Next(10000, 99999).ToString(); var parameters = new Dictionary<string, object> { { "code", code } }; var sent = await smsService.SendOtpAsync(mobile, "identity_otp_v1", parameters); if (!sent) return Results.Problem("ارسال پیامک با خطا مواجه شد"); return Results.Ok(new { message = "کد تایید ارسال گردید" }); });
Polly و قابلیت تاب‌آوری (Resilience): با استفاده از پکیج Microsoft.Extensions.Http.Resilience در .NET 8 می‌توانید سیاست‌های Retry و Circuit Breaker را به سادگی به کلاینت پیامک خود بیافزایید.

سوالات متداول

آیا این کلاینت با پروژه‌های Blazor و WPF هم کار می‌کند؟+

بله، معماری مبتنی بر .NET Standard 2.1 و .NET 8 بوده و در انواع پروژه‌های ASP.NET Core، Blazor، WPF و MAUI قابل استفاده است.

چگونه خطاهای مخابراتی را لاگ کنیم؟+

با تزریق ILogger<FreeSmsService> در سازنده کلاس، در صورتی که !response.IsSuccessStatusCode بود، متن خطای برگشتی از وب‌سرویس را لاگ کنید.

چرا باید به جای ایجاد مستقیم HttpClient از IHttpClientFactory در دات‌نت استفاده کنیم؟+

استفاده مستقیم از new HttpClient() باعث بحران نشت سوکت (Socket Exhaustion) در حجم بالای تراکنش می‌شود؛ IHttpClientFactory چرخه حیات سوکت‌ها و DNS pooling را مدیریت می‌کند.

چگونه کلید API وب‌سرویس را به صورت امن در پروژه ASP.NET Core ذخیره کنیم؟+

در محیط Development از قابلیت dotnet user-secrets و در محیط Production از متغیرهای محیطی سیستم‌عامل (Environment Variables) یا Azure KeyVault استفاده نمایید.