// src/Webshop.Application/Services/Admin/AdminPaymentMethodService.cs using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; // Wichtig für JsonSerializer using System.Threading.Tasks; using Webshop.Application.DTOs.Payments; // AdminPaymentMethodDto und die neuen Configuration-DTOs using Webshop.Domain.Entities; // PaymentMethod using Webshop.Domain.Enums; // PaymentGatewayType using Webshop.Domain.Interfaces; // IPaymentMethodRepository namespace Webshop.Application.Services.Admin { public class AdminPaymentMethodService : IAdminPaymentMethodService { private readonly IPaymentMethodRepository _paymentMethodRepository; public AdminPaymentMethodService(IPaymentMethodRepository paymentMethodRepository) { _paymentMethodRepository = paymentMethodRepository; } public async Task> GetAllAsync() { var paymentMethods = await _paymentMethodRepository.GetAllAsync(); return paymentMethods.Select(pm => new AdminPaymentMethodDto { Id = pm.Id, Name = pm.Name, Description = pm.Description, IsActive = pm.IsActive, PaymentGatewayType = pm.PaymentGatewayType, // Deserialisiere den JSON-String aus der DB in ein Objekt für die Admin-Ansicht Configuration = pm.Configuration != null ? JsonSerializer.Deserialize(pm.Configuration) : null, ProcessingFee = pm.ProcessingFee }).ToList(); } public async Task GetByIdAsync(Guid id) { var paymentMethod = await _paymentMethodRepository.GetByIdAsync(id); if (paymentMethod == null) return null; return new AdminPaymentMethodDto { Id = paymentMethod.Id, Name = paymentMethod.Name, Description = paymentMethod.Description, IsActive = paymentMethod.IsActive, PaymentGatewayType = paymentMethod.PaymentGatewayType, // Deserialisiere den JSON-String aus der DB in ein Objekt Configuration = paymentMethod.Configuration != null ? JsonSerializer.Deserialize(paymentMethod.Configuration) : null, ProcessingFee = paymentMethod.ProcessingFee }; } public async Task CreateAsync(AdminPaymentMethodDto paymentMethodDto) { var (isValid, configJson, errorMessage) = ValidateAndSerializeConfiguration(paymentMethodDto.PaymentGatewayType, paymentMethodDto.Configuration); if (!isValid) { // In einer echten Anwendung würden Sie hier eine benutzerdefinierte Validierungs-Exception werfen, // damit der Controller einen 400 Bad Request zurückgeben kann. throw new ArgumentException(errorMessage); } var newPaymentMethod = new PaymentMethod { Id = Guid.NewGuid(), Name = paymentMethodDto.Name, Description = paymentMethodDto.Description, IsActive = paymentMethodDto.IsActive, PaymentGatewayType = paymentMethodDto.PaymentGatewayType, Configuration = configJson, // Speichere den validierten JSON-String ProcessingFee = paymentMethodDto.ProcessingFee }; await _paymentMethodRepository.AddAsync(newPaymentMethod); paymentMethodDto.Id = newPaymentMethod.Id; return paymentMethodDto; } public async Task UpdateAsync(AdminPaymentMethodDto paymentMethodDto) { var existingPaymentMethod = await _paymentMethodRepository.GetByIdAsync(paymentMethodDto.Id); if (existingPaymentMethod == null) return false; var (isValid, configJson, errorMessage) = ValidateAndSerializeConfiguration(paymentMethodDto.PaymentGatewayType, paymentMethodDto.Configuration); if (!isValid) { throw new ArgumentException(errorMessage); } existingPaymentMethod.Name = paymentMethodDto.Name; existingPaymentMethod.Description = paymentMethodDto.Description; existingPaymentMethod.IsActive = paymentMethodDto.IsActive; existingPaymentMethod.PaymentGatewayType = paymentMethodDto.PaymentGatewayType; existingPaymentMethod.Configuration = configJson; existingPaymentMethod.ProcessingFee = paymentMethodDto.ProcessingFee; await _paymentMethodRepository.UpdateAsync(existingPaymentMethod); return true; } public async Task DeleteAsync(Guid id) { var paymentMethod = await _paymentMethodRepository.GetByIdAsync(id); if (paymentMethod == null) return false; await _paymentMethodRepository.DeleteAsync(id); return true; } private (bool IsValid, string? ConfigJson, string? ErrorMessage) ValidateAndSerializeConfiguration(PaymentGatewayType type, object? configObject) { if (configObject == null) return (true, null, null); var configElement = (JsonElement)configObject; try { switch (type) { case PaymentGatewayType.BankTransfer: var bankConfig = configElement.Deserialize(); if (bankConfig == null || string.IsNullOrEmpty(bankConfig.IBAN) || string.IsNullOrEmpty(bankConfig.BIC)) { return (false, null, "Für Banküberweisung müssen IBAN und BIC angegeben werden."); } return (true, JsonSerializer.Serialize(bankConfig), null); case PaymentGatewayType.Stripe: var stripeConfig = configElement.Deserialize(); if (stripeConfig == null || string.IsNullOrEmpty(stripeConfig.PublicKey) || string.IsNullOrEmpty(stripeConfig.SecretKey)) { return (false, null, "Für Stripe müssen PublicKey und SecretKey angegeben werden."); } return (true, JsonSerializer.Serialize(stripeConfig), null); case PaymentGatewayType.PayPal: var payPalConfig = configElement.Deserialize(); if (payPalConfig == null || string.IsNullOrEmpty(payPalConfig.ClientId) || string.IsNullOrEmpty(payPalConfig.ClientSecret)) { return (false, null, "Für PayPal müssen ClientId und ClientSecret angegeben werden."); } return (true, JsonSerializer.Serialize(payPalConfig), null); default: // Für Typen wie Invoice oder CashOnDelivery, die keine spezielle Konfiguration brauchen, // ist ein leeres JSON-Objekt '{}' ein gültiger Wert. return (true, JsonSerializer.Serialize(new object()), null); } } catch (JsonException ex) { return (false, null, $"Ungültiges JSON-Format für die Konfiguration: {ex.Message}"); } } } }