Fully implement Kavenegar SMS support
Core changes: - ISmsService: add SendBulkAsync (batches of 200) + GetAccountInfoAsync - KavenegarSmsService: POST requests, sender number config, bulk send via comma-separated receptors, account balance, full error code mapping (HTTP 400-432), enabled-flag check before any send - SmsMarketingService: replaced per-recipient loop with SendBulkAsync - SmsController: new GET /sms/balance endpoint returns Kavenegar credit - SmsDtos: SmsBalanceDto - IntegrationDtos + PlatformIntegrationService: SenderNumber field - appsettings.json + docker-compose: Kavenegar__SenderNumber = 90005671 Dashboard: - sms-screen: char counter, SMS parts indicator (Persian 70/67 chars, Latin 160/153), account balance card, sender line display, result banner Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -17,9 +17,10 @@ public interface IPlatformIntegrationService
|
||||
public class PlatformIntegrationService : IPlatformIntegrationService
|
||||
{
|
||||
public const string KeyActiveGateway = "payment.activeGateway";
|
||||
public const string KeyKavenegarApi = "integrations.kavenegar.apiKey";
|
||||
public const string KeyKavenegarOtpTemplate = "integrations.kavenegar.otpTemplate";
|
||||
public const string KeyKavenegarEnabled = "integrations.kavenegar.enabled";
|
||||
public const string KeyKavenegarApi = "integrations.kavenegar.apiKey";
|
||||
public const string KeyKavenegarOtpTemplate = "integrations.kavenegar.otpTemplate";
|
||||
public const string KeyKavenegarEnabled = "integrations.kavenegar.enabled";
|
||||
public const string KeyKavenegarSender = "integrations.kavenegar.senderNumber";
|
||||
|
||||
private static readonly (string Id, string NameFa, string Prefix)[] Gateways =
|
||||
[
|
||||
@@ -56,6 +57,7 @@ public class PlatformIntegrationService : IPlatformIntegrationService
|
||||
map.GetValueOrDefault(KeyKavenegarEnabled) is "true",
|
||||
MaskSecret(map.GetValueOrDefault(KeyKavenegarApi)),
|
||||
map.GetValueOrDefault(KeyKavenegarOtpTemplate) ?? "verify",
|
||||
map.GetValueOrDefault(KeyKavenegarSender) ?? string.Empty,
|
||||
HasSecret(map, KeyKavenegarApi));
|
||||
|
||||
var ai = new AiIntegrationsConfigDto(
|
||||
@@ -109,6 +111,8 @@ public class PlatformIntegrationService : IPlatformIntegrationService
|
||||
await UpsertAsync(KeyKavenegarOtpTemplate, request.Kavenegar.OtpTemplate.Trim(), "integrations", "قالب OTP", ct);
|
||||
if (!string.IsNullOrWhiteSpace(request.Kavenegar.ApiKey) && !IsMaskedPlaceholder(request.Kavenegar.ApiKey))
|
||||
await UpsertAsync(KeyKavenegarApi, request.Kavenegar.ApiKey.Trim(), "integrations", "API Key کاوهنگار", ct);
|
||||
if (!string.IsNullOrWhiteSpace(request.Kavenegar.SenderNumber))
|
||||
await UpsertAsync(KeyKavenegarSender, request.Kavenegar.SenderNumber.Trim(), "integrations", "شماره فرستنده کاوهنگار", ct);
|
||||
|
||||
await UpsertAsync(PlatformIntegrationKeys.OpenAiEnabled, request.Ai.OpenAi.IsEnabled ? "true" : "false", "integrations", "فعال OpenAI", ct);
|
||||
await UpsertAsync(PlatformIntegrationKeys.OpenAiModel, string.IsNullOrWhiteSpace(request.Ai.OpenAi.Model) ? "gpt-4o-mini" : request.Ai.OpenAi.Model.Trim(), "integrations", "مدل OpenAI", ct);
|
||||
|
||||
Reference in New Issue
Block a user