65 lines
2.5 KiB
C#
65 lines
2.5 KiB
C#
|
|
using JobsMedical.Web.Models;
|
||
|
|
|
||
|
|
namespace JobsMedical.Web.Services;
|
||
|
|
|
||
|
|
public interface ISmsSender
|
||
|
|
{
|
||
|
|
/// <summary>Send the OTP code. Returns false if not configured or the gateway call fails.</summary>
|
||
|
|
Task<bool> SendOtpAsync(string phone, string code, AppSetting settings, CancellationToken ct = default);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Kavenegar SMS gateway (Iran). Prefers the verify/lookup API (a pre-approved OTP template, no
|
||
|
|
/// dedicated line needed); falls back to plain sms/send if only a sender line is configured.
|
||
|
|
/// Credentials live in AppSetting (admin panel), so no redeploy to set them.
|
||
|
|
/// </summary>
|
||
|
|
public class KavenegarSmsSender : ISmsSender
|
||
|
|
{
|
||
|
|
private readonly IHttpClientFactory _http;
|
||
|
|
private readonly ILogger<KavenegarSmsSender> _log;
|
||
|
|
|
||
|
|
public KavenegarSmsSender(IHttpClientFactory http, ILogger<KavenegarSmsSender> log)
|
||
|
|
{
|
||
|
|
_http = http;
|
||
|
|
_log = log;
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<bool> SendOtpAsync(string phone, string code, AppSetting s, CancellationToken ct = default)
|
||
|
|
{
|
||
|
|
if (!s.SmsEnabled || string.IsNullOrWhiteSpace(s.SmsApiKey)) return false;
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var client = _http.CreateClient("sms");
|
||
|
|
client.Timeout = TimeSpan.FromSeconds(15);
|
||
|
|
string url;
|
||
|
|
if (!string.IsNullOrWhiteSpace(s.SmsTemplate))
|
||
|
|
{
|
||
|
|
// verify/lookup: template contains %token → the code
|
||
|
|
url = $"https://api.kavenegar.com/v1/{s.SmsApiKey}/verify/lookup.json" +
|
||
|
|
$"?receptor={Uri.EscapeDataString(phone)}&token={Uri.EscapeDataString(code)}" +
|
||
|
|
$"&template={Uri.EscapeDataString(s.SmsTemplate)}";
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
var msg = $"کد ورود همکادر: {code}";
|
||
|
|
url = $"https://api.kavenegar.com/v1/{s.SmsApiKey}/sms/send.json" +
|
||
|
|
$"?receptor={Uri.EscapeDataString(phone)}&message={Uri.EscapeDataString(msg)}" +
|
||
|
|
(string.IsNullOrWhiteSpace(s.SmsSender) ? "" : $"&sender={Uri.EscapeDataString(s.SmsSender)}");
|
||
|
|
}
|
||
|
|
|
||
|
|
using var resp = await client.GetAsync(url, ct);
|
||
|
|
if (!resp.IsSuccessStatusCode)
|
||
|
|
{
|
||
|
|
_log.LogWarning("Kavenegar OTP HTTP {Status} for {Phone}", (int)resp.StatusCode, phone);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
_log.LogWarning(ex, "Kavenegar OTP send failed for {Phone}", phone);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|