یکپارچهسازی سامانههای پیامکی ایران در .NET — نسخه 0.2.0-beta.2
فارسی | English
کتابخانهای سبک، مستقل از وابستگیهای جانبی و بدون وابسته کردن پروژه به اپراتوری خاص برای ارسال پیامک در .NET. این کتابخانه یک قرارداد یکپارچه (ISmsClient)، قابلیتهای قابل کشف (SmsCapabilities) و پشتیبانی از تزریق وابستگی (DI) را بدون وابستگی مستقیم به ارائهدهندهای ارائه میدهد.
| پکیج | کلاینت | قابلیتها | وابستگی افزوده | ملاحظات |
|---|---|---|---|---|
| IranSms.Core | ISmsClient | قراردادهای پایه و اینترفیس قابلیتها | — | بدون وابستگی |
| IranSms.Providers.Kavenegar | KavenegarClient | تکی · انبوه · الگویی (OTP) · وضعیت تحویل · موجودی · خطوط | System.Text.Json | ارسال انبوه تا ۲۰۰ گیرنده |
| IranSms.Providers.Ghasedak | GhasedakClient | تکی · انبوه · الگویی (OTP) · وضعیت تحویل · موجودی | System.Text.Json | ارسال انبوه تا ۱۰۰ گیرنده؛ حداکثر ۱۰۰۰ کاراکتر |
| IranSms.Providers.SmsIr | SmsIrClient | تکی · انبوه · الگویی (OTP) · وضعیت تحویل · موجودی · خطوط | System.Text.Json | ارسال انبوه تا ۱۰۰ گیرنده؛ الزام عددی بودن senderLine |
| IranSms.Providers.Melipayamak | MelipayamakClient | تکی · انبوه · الگویی (OTP) · وضعیت تحویل · موجودی · خطوط | System.Text.Json | الزامی بودن senderLine |
| IranSms.Providers.Mock | MockSmsClient | تکی · انبوه · الگویی (OTP) · وضعیت تحویل · موجودی · خطوط | — | مبتنی بر حافظه با شناسه معین mock-{n} |
| IranSms.DependencyInjection | AddIranSms | ثبت هوشمند مبتنی بر قابلیت | DI.Abstractions | وابستگی انحصاری به Core |
IranSms.Core (netstandard2.0 — بدون هیچ وابستگی)
↑ ↑
│ │
IranSms.DependencyInjection IranSms.Providers.* (هرکدام فقط وابسته به Core)
↑ │
└──── برنامه شما ──── new KavenegarClient(apiKey)
- هر ارائهدهنده صرفاً به Core وابسته است؛ نصب پکیج Kavenegar هیچ وابستگی اضافه مانند Microsoft.Extensions.* را به پروژه تحمیل نمیکند.
- پکیج IranSms.DependencyInjection تنها به Core و Microsoft.Extensions.DependencyInjection.Abstractions وابسته است.
- مدیریت طول عمر HttpClient و اعتبارنامهها بر عهده برنامه شماست و ثبت آن از طریق AddIranSms انجام میشود.
| قابلیت | پرچم (Flag) | اینترفیس | وضعیت |
|---|---|---|---|
| ارسال تکی | Send | ISmsClient.SendAsync | ✅ پیادهسازیشده |
| ارسال انبوه | BulkSend | ISmsBulkSender.SendBulkAsync | ✅ پیادهسازیشده |
| ارسال الگویی / کد تأیید | OtpSend | ISmsOtpSender.SendOtpAsync | ✅ پیادهسازیشده |
| وضعیت تحویل | DeliveryStatus | ISmsDeliveryReporter.GetMessageStatusAsync | ✅ پیادهسازیشده |
| ارسال ناهمگون | HeterogeneousSend | — | 🗓 نقشه راه |
| ارسال زمانبندیشده | ScheduledSend | — | 🗓 نقشه راه |
| تاریخچه پیامها | MessageHistory | — | 🗓 نقشه راه |
| دریافت پیام | Receive | — | 🗓 نقشه راه |
| اطلاعات حساب | AccountInfo | ISmsAccountInfo.GetBalanceAsync | ✅ پیادهسازیشده |
| فهرست خطوط | SenderLines | ISmsAccountInfo.GetSenderLinesAsync | ✅ پیادهسازیشده |
| مدیریت قالبها | TemplateManagement | — | 🗓 نقشه راه |
| پیام فلش | FlashMessage | — | 🗓 نقشه راه |
| پیام صوتی | VoiceMessage | — | 🗓 نقشه راه |
| اعتبارسنجی پارامترهای قالب | OtpTemplateInspection | — | 🗓 نقشه راه |
بررسی قابلیتها بدون استفاده از HasFlag (جهت جلوگیری از سربار Boxed-Type در netstandard2.0):
if ((client.Capabilities & SmsCapabilities.OtpSend) == SmsCapabilities.OtpSend) { ... }
// یا
if (client.Supports(SmsCapabilities.OtpSend)) { ... }
// یا
if (client is ISmsOtpSender otp) { ... }- ✅ بدون وابستگی اضافی: هسته پروژه بدون هیچ وابستگی خارجی است؛ هر پکیج ارائهدهنده تنها به Core وابستگی دارد.
- ✅ مدیریت مستقیم کلاینت: ساخت و نگهداری چرخه عمر HttpClient و کلیدهای دسترسی در اختیار مصرفکننده است.
- ✅ ثبت هوشمند مبتنی بر قابلیت: در تزریق وابستگی، فقط اینترفیسهایی ثبت میشوند که توسط کلاینت مربوطه پیادهسازی شده باشند.
- ✅ قابلیت تستپذیری بالا: ارائه کلاینت Mock با شناسه قطعی mock-{n} جهت تستهای محلی.
- ✅ تایماوت HTTP: چرخه عمر HttpClient در اختیار مصرفکننده است؛ client داخلی با timeout سی ثانیه و بدون redirect خودکار ساخته میشود. برای تنظیم دقیق، HttpClient پیکربندیشده خودتان را به سازنده کلاینت بدهید.
- ✅ پشتیبانی از netstandard2.0: قابل استفاده در تمام نسخههای .NET (از .NET Framework تا .NET 10).
- ✅ مدیریت خطای دقیق: عدم ارائه مقادیر ساختگی در صورت نبود MessageId و صدور صریح استثنا.
dotnet add package IranSms.Core
dotnet add package IranSms.Providers.Kavenegar # یا Ghasedak / SmsIr / Melipayamak
dotnet add package IranSms.Providers.Mock # جهت تستهای محلی
dotnet add package IranSms.DependencyInjection # اختیاری — صرفاً در صورت نیاز به DIusing IranSms.Providers.Kavenegar;
var client = new KavenegarClient(Environment.GetEnvironmentVariable("KAVENEGAR_API_KEY")!);
var result = await client.SendAsync("09121234567", "سلام از IranSMS!");
Console.WriteLine(result.MessageId);
if (client is ISmsOtpSender otp)
{
var r = await otp.SendOtpAsync("09121234567", new OtpRequest
{
Code = "48291",
TemplateId = "LoginTemplate",
});
}
if (client is ISmsDeliveryReporter reporter)
{
var status = await reporter.GetMessageStatusAsync(
new MessageIdentifier(result.MessageId, MessageIdentifierType.ProviderMessageId));
Console.WriteLine(status.State);
}using IranSms.DependencyInjection;
using IranSms.Providers.Kavenegar;
builder.Services.AddIranSms(new KavenegarClient(
builder.Configuration["Kavenegar:ApiKey"]!));
app.MapPost("/sms/send", async (SendRequest req, ISmsClient sms, CancellationToken ct) =>
{
var r = await sms.SendAsync(req.Recipient, req.Message, req.SenderLine, ct);
return Results.Ok(new { r.MessageId });
});نکته: هرگز کلیدهای دسترسی (API Keys) را در سورسکد به صورت کُدسخت (Hard-code) قرار ندهید. آنها را از IConfiguration، UserSecrets یا Key Vault بخوانید.
services.AddIranSms(new MockSmsClient("Mock"));
services.AddIranSms(new KavenegarClient(kavenegarKey));
services.AddIranSms(new GhasedakClient(ghasedakKey));
var clients = provider.GetServices<ISmsClient>();
var otpSender = clients.FirstOrDefault(c => c.Supports(SmsCapabilities.OtpSend)) as ISmsOtpSender;try
{
var r = await client.SendAsync(recipient, message);
}
catch (IranSmsException ex) when (ex.ProviderName == "Ghasedak")
{
// فیلدهای ex.ProviderStatusCode و ex.RawResponseBody مقداردهی شدهاند
// از ثبت RawResponseBody در لاگهای عمومی خودداری کنید؛ زیرا ممکن است حاوی متن پیام یا شماره باشد
logger.LogWarning("خطای قاصدک {Code}: {Message}", ex.ProviderStatusCode, ex.Message);
}
catch (HttpRequestException)
{
// خطای شبکه یا تایماوت — فاقد RawResponseBody
}| نمونه | توضیحات | نحوه اجرا |
|---|---|---|
| samples/Basic | برنامه کنسول بدون DI جهت نمایش تمامی قابلیتها با Mock | dotnet run --project samples/Basic |
| samples/AspNetCore | پروژه Minimal API به همراه AddIranSms، احراز هویت sample و rate limit | dotnet run --project samples/AspNetCore با X-Sample-Api-Key |
| samples/MultiProvider | ثبت ۵ ارائهدهنده و مسیریابی پویا بر اساس قابلیتها | dotnet run --project samples/MultiProvider |
مقداردهی کلیدها از طریق متغیرهای محیطی:
export KAVENEGAR_API_KEY=...
export GHASEDAK_API_KEY=...
export SMSIR_API_KEY=...
export MELIPAYAMAK_USERNAME=... MELIPAYAMAK_PASSWORD=...
export IRANSMS_SAMPLE_API_KEY=...| پکیج | وضعیت | کاربرد |
|---|---|---|
| IranSms.Core | ✅ | قراردادها و قابلیتهای اصلی — بدون وابستگی |
| IranSms.Providers.Kavenegar | ✅ | ارسال پیامک از طریق کاوهنگار |
| IranSms.Providers.Ghasedak | ✅ | ارسال پیامک از طریق قاصدک |
| IranSms.Providers.SmsIr | ✅ | ارسال پیامک از طریق SMS.ir |
| IranSms.Providers.Melipayamak | ✅ | ارسال پیامک از طریق ملیپیامک |
| IranSms.Providers.Mock | ✅ | پیادهسازی مبتنی بر حافظه جهت تست |
| IranSms.DependencyInjection | ✅ | ثبت هوشمند در سیستم تزریق وابستگی (DI) |
ویندوز (PowerShell):
dotnet build -c Release
dotnet run --project tests\IranSms.Tests -c Release --no-build --framework net10.0
dotnet run --project tests\IranSms.Tests -c Release --no-build --framework net8.0لینوکس / مک (bash):
dotnet build -c Release
dotnet run --project tests/IranSms.Tests -c Release --no-build --framework net10.0
dotnet run --project tests/IranSms.Tests -c Release --no-build --framework net8.0شامل ۲۲۲ تست پاسشده (xunit v3 + FluentAssertions).
- گردش کار build.yml: اجرا و اعتبارسنجی تستها در هر push و pull_request
- گردش کار release.yml: انتشار packageها در GitHub Packages و ایجاد GitHub Release هنگام ثبت تگهای v*. انتشار به NuGet.org فعلاً فعال نیست.
-
نسخه را در Directory.Build.props و READMEها بهروزرسانی کنید.
-
تغییرات را commit کنید و سپس یک تگ نسخه بسازید:
git tag -a v0.2.0-beta.2 -m "Release v0.2.0-beta.2" git push origin v0.2.0-beta.2 -
workflow release.yml را بررسی کنید؛ packageهای nupkg و snupkg را در GitHub Packages و GitHub Release منتشر میکند.
-
NuGet.org فعلاً در workflow فعال نیست؛ پس از پیکربندی NuGet Trusted Publishing باید مسیر جداگانهٔ آن اضافه شود.
این پروژه تحت مجوز MIT منتشر شده است.