using GreenHome.Application; using GreenHome.Sms.Ippanel; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; namespace GreenHome.Infrastructure; /// /// سرویس مدیریت توکن و تنظیمات دستگاه /// public sealed class DeviceTokenService : IDeviceTokenService { private readonly GreenHomeDbContext dbContext; private readonly ISmsService smsService; private readonly ILogger logger; public DeviceTokenService( GreenHomeDbContext dbContext, ISmsService smsService, ILogger logger) { this.dbContext = dbContext; this.smsService = smsService; this.logger = logger; } /// /// دریافت فاصله زمانی آپلود بر اساس شماره تلفن یا شناسه دستگاه /// public async Task GetUploadIntervalAsync( GetUploadIntervalRequest request, CancellationToken cancellationToken) { try { Domain.DeviceSettings? settings = null; // جستجو بر اساس DeviceId یا DevicePhoneNumber if (request.DeviceId.HasValue) { settings = await dbContext.DeviceSettings .AsNoTracking() .FirstOrDefaultAsync(ds => ds.DeviceId == request.DeviceId.Value, cancellationToken); } else if (!string.IsNullOrWhiteSpace(request.DevicePhoneNumber)) { settings = await dbContext.DeviceSettings .AsNoTracking() .FirstOrDefaultAsync(ds => ds.DevicePhoneNumber == request.DevicePhoneNumber, cancellationToken); } if (settings == null) { return new GetUploadIntervalResponse { Success = false, Message = "دستگاه یافت نشد" }; } return new GetUploadIntervalResponse { Success = true, UploadIntervalMin = settings.UploadIntervalMin }; } catch (Exception ex) { logger.LogError(ex, "Error getting upload interval for device"); return new GetUploadIntervalResponse { Success = false, Message = "خطا در دریافت اطلاعات" }; } } /// /// درخواست توکن دستگاه (تولید و ارسال کد) /// public async Task RequestDeviceTokenAsync( RequestDeviceTokenRequest request, CancellationToken cancellationToken) { try { // پیدا کردن تنظیمات دستگاه بر اساس شماره تلفن var settings = await dbContext.DeviceSettings .FirstOrDefaultAsync(ds => ds.DevicePhoneNumber == request.DevicePhoneNumber, cancellationToken); if (settings == null) { return new RequestDeviceTokenResponse { Success = false, Message = "دستگاه با این شماره تلفن یافت نشد" }; } // تولید کد توکن 5 رقمی var random = new Random(); var tokenCode = random.Next(10000, 99999).ToString(); // تولید کد تایید بر اساس فرمول: (TokenCode * 7 + 12345) % 100000 var verificationCode = ((int.Parse(tokenCode) * 7 + 12345) % 100000).ToString("D5"); // ذخیره کدها settings.TokenCode = tokenCode; settings.VerificationCode = verificationCode; settings.TokenExpiresAt = DateTime.UtcNow.AddMinutes(30); // اعتبار 10 دقیقه settings.UpdatedAt = DateTime.UtcNow; await dbContext.SaveChangesAsync(cancellationToken); // ارسال کد توکن از طریق پیامک try { await smsService.SendWebserviceSmsAsync(new WebserviceSmsRequest { Recipient = request.DevicePhoneNumber, Message = $"0911925302120#{tokenCode}" }, cancellationToken); } catch (Exception smsEx) { logger.LogError(smsEx, "Error sending token SMS to {PhoneNumber}", request.DevicePhoneNumber); return new RequestDeviceTokenResponse { Success = false, Message = "خطا در ارسال پیامک" }; } logger.LogInformation("Token requested for device phone {PhoneNumber}", request.DevicePhoneNumber); return new RequestDeviceTokenResponse { Success = true, Message = "کد تایید با موفقیت ارسال شد", TokenCode = $"0911925302120#{tokenCode}" }; } catch (Exception ex) { logger.LogError(ex, "Error requesting device token"); return new RequestDeviceTokenResponse { Success = false, Message = "خطا در درخواست توکن" }; } } /// /// تایید توکن دستگاه (ارسال تنظیمات) /// public async Task VerifyDeviceTokenAsync( VerifyDeviceTokenRequest request, CancellationToken cancellationToken) { try { // پیدا کردن تنظیمات دستگاه var settings = await dbContext.DeviceSettings .Include(ds => ds.Device) .FirstOrDefaultAsync(ds => ds.DevicePhoneNumber == request.DevicePhoneNumber, cancellationToken); if (settings == null) { return new VerifyDeviceTokenResponse { Success = false, Message = "دستگاه با این شماره تلفن یافت نشد" }; } // بررسی انقضای توکن if (settings.TokenExpiresAt == null || settings.TokenExpiresAt < DateTime.UtcNow) { return new VerifyDeviceTokenResponse { Success = false, Message = "کد تایید منقضی شده است" }; } // بررسی کد تایید if (settings.VerificationCode != request.VerificationCode) { return new VerifyDeviceTokenResponse { Success = false, Message = "کد تایید نادرست است" }; } Random rnd = new Random(); // رمزگذاری ساده تنظیمات: DeviceName|UploadIntervalMin به Base64 var deviceId = settings.Device.Id; var uploadInterval = settings.UploadIntervalMin; string smsConfig = (settings.MinimumSmsIntervalMinutes != 0 ? "1" : rnd.Next(2, 9).ToString()) + settings.MinimumSmsIntervalMinutes; var plainText = $"{deviceId}01|{rnd.Next(1,9)}{uploadInterval}|{smsConfig}|{rnd.Next(139,97654)}|{rnd.Next(1,9)}{(int)settings.SimCardType}"; var encodedSettings = plainText; //Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(plainText)); // ارسال تنظیمات کدشده از طریق پیامک try { await smsService.SendWebserviceSmsAsync(new WebserviceSmsRequest { Recipient = request.DevicePhoneNumber, Message = $"{encodedSettings}" }, cancellationToken); } catch (Exception smsEx) { logger.LogError(smsEx, "Error sending settings SMS to {PhoneNumber}", request.DevicePhoneNumber); return new VerifyDeviceTokenResponse { Success = false, Message = "خطا در ارسال پیامک" }; } // پاک کردن کدها بعد از استفاده موفق settings.TokenCode = null; settings.VerificationCode = null; settings.TokenExpiresAt = null; settings.UpdatedAt = DateTime.UtcNow; await dbContext.SaveChangesAsync(cancellationToken); logger.LogInformation("Device token verified for {PhoneNumber}", request.DevicePhoneNumber); return new VerifyDeviceTokenResponse { Success = true, Message = "تنظیمات با موفقیت ارسال شد", EncodedSettings = encodedSettings }; } catch (Exception ex) { logger.LogError(ex, "Error verifying device token"); return new VerifyDeviceTokenResponse { Success = false, Message = "خطا در تایید توکن" }; } } }