first commit
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
using System.Net;
|
||||
using System.Net.Mail;
|
||||
using System.Text.Json;
|
||||
using Fitness_core_BE.Interfaces.Services;
|
||||
using Fitness_core_BE.Models.IOs;
|
||||
|
||||
namespace Fitness_core_BE.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Combines the two outbound notification channels — SMS (Introps) and email (Gmail SMTP) —
|
||||
/// into one service, matching the pattern already used by Core-Hex-Auth's ThirdPartyService.
|
||||
/// </summary>
|
||||
public class ThirdPartyService : IThirdPartyService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly IConfiguration _config;
|
||||
|
||||
// Email (Gmail SMTP). Use a Gmail App Password, not the account password.
|
||||
private readonly string _gmailUser;
|
||||
private readonly string _gmailPassword;
|
||||
private readonly string _gmailHost;
|
||||
private readonly int _gmailPort;
|
||||
private readonly string _gmailFromName;
|
||||
|
||||
public ThirdPartyService(IHttpClientFactory httpClientFactory, IConfiguration config)
|
||||
{
|
||||
_httpClient = httpClientFactory.CreateClient();
|
||||
_config = config;
|
||||
|
||||
_gmailUser = Environment.GetEnvironmentVariable("GMAIL_USER") ?? config["Gmail:User"] ?? "";
|
||||
_gmailPassword = Environment.GetEnvironmentVariable("GMAIL_APP_PASSWORD") ?? config["Gmail:AppPassword"] ?? "";
|
||||
_gmailHost = config["Gmail:Host"] ?? "smtp.gmail.com";
|
||||
_gmailPort = int.TryParse(config["Gmail:Port"], out var p) ? p : 587;
|
||||
_gmailFromName = config["Gmail:FromName"] ?? "GYM OS";
|
||||
}
|
||||
|
||||
// ---------- SMS ----------
|
||||
|
||||
public async Task<OtpResponse> SendSmsAsync(string mobileNumber, string? otpCode = null, string? message = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(mobileNumber))
|
||||
{
|
||||
return new OtpResponse
|
||||
{
|
||||
StatusCode = 400,
|
||||
Message = "Mobile number is required"
|
||||
};
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(otpCode) && string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
return new OtpResponse
|
||||
{
|
||||
StatusCode = 400,
|
||||
Message = "Either an OTP code or a message is required"
|
||||
};
|
||||
}
|
||||
|
||||
string contactNumber = mobileNumber;
|
||||
string apiUrl = _config["Sms:ApiUrl"] ?? "https://backup.introps.com/Sms_common/send_sms";
|
||||
string apiKey = Environment.GetEnvironmentVariable("SMS_API_KEY") ?? _config["Sms:ApiKey"] ?? "8989898989";
|
||||
|
||||
var msgText = string.IsNullOrWhiteSpace(message) ? $"Your otp code is: {otpCode}" : message;
|
||||
|
||||
var smsRequest = new SmsRequest
|
||||
{
|
||||
api_key = apiKey,
|
||||
phone_number = contactNumber,
|
||||
msg_text = msgText
|
||||
};
|
||||
|
||||
var formContent = new FormUrlEncodedContent(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("api_key", smsRequest.api_key),
|
||||
new KeyValuePair<string, string>("phone_number", smsRequest.phone_number),
|
||||
new KeyValuePair<string, string>("msg_text", smsRequest.msg_text)
|
||||
});
|
||||
|
||||
var response = await _httpClient.PostAsync(apiUrl, formContent);
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
|
||||
if (response.IsSuccessStatusCode && responseContent.Contains("agent:d"))
|
||||
{
|
||||
string jsonString = responseContent.Split(new[] { "agent:d" }, StringSplitOptions.None)[1];
|
||||
|
||||
var responseJson = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonString);
|
||||
|
||||
if (responseJson is not null &&
|
||||
responseJson.TryGetValue("stt", out var statusValue) &&
|
||||
statusValue?.ToString() == "ok")
|
||||
{
|
||||
Console.WriteLine($"SMS sent to {contactNumber}");
|
||||
return new OtpResponse
|
||||
{
|
||||
StatusCode = 200,
|
||||
Message = "SMS sent successfully."
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine($"Failed to send SMS to {contactNumber}. Response: {responseContent}");
|
||||
return new OtpResponse
|
||||
{
|
||||
StatusCode = 500,
|
||||
Message = "Failed to send SMS.",
|
||||
ApiResponse = responseContent
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Exception sending SMS: {ex.Message}");
|
||||
|
||||
return new OtpResponse
|
||||
{
|
||||
StatusCode = 500,
|
||||
Message = "Exception occurred while sending SMS.",
|
||||
Error = ex.Message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- Email ----------
|
||||
|
||||
public async Task SendEmailAsync(string toEmail, string subject, string htmlBody, byte[]? attachment = null, string? attachmentName = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_gmailUser) || string.IsNullOrWhiteSpace(_gmailPassword))
|
||||
throw new InvalidOperationException("Gmail SMTP is not configured (set GMAIL_USER / GMAIL_APP_PASSWORD).");
|
||||
|
||||
using var mail = new MailMessage
|
||||
{
|
||||
From = new MailAddress(_gmailUser, _gmailFromName),
|
||||
Subject = subject,
|
||||
Body = htmlBody,
|
||||
IsBodyHtml = true
|
||||
};
|
||||
mail.To.Add(toEmail);
|
||||
|
||||
MemoryStream? attachmentStream = null;
|
||||
if (attachment != null)
|
||||
{
|
||||
attachmentStream = new MemoryStream(attachment);
|
||||
mail.Attachments.Add(new Attachment(attachmentStream, attachmentName ?? "receipt.pdf", "application/pdf"));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using var client = new SmtpClient(_gmailHost, _gmailPort)
|
||||
{
|
||||
EnableSsl = true,
|
||||
Credentials = new NetworkCredential(_gmailUser, _gmailPassword)
|
||||
};
|
||||
await client.SendMailAsync(mail);
|
||||
}
|
||||
finally
|
||||
{
|
||||
attachmentStream?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user