using System; using System.Net.Http; using System.Net.Http.Headers; using System.Text.Json; using System.Threading.Tasks; namespace Gott.Services { public class StripeCheckResult { public string Status { get; set; } // "ok", "invalid", "error" public string Message { get; set; } public bool IsLiveKey { get; set; } public string Currency { get; set; } public long? BalanceAvailable { get; set; } public long? BalancePending { get; set; } public string AccountId { get; set; } public string AccountName { get; set; } public string AccountEmail { get; set; } public string AccountCountry { get; set; } public bool? PayoutsEnabled { get; set; } public bool? ChargesEnabled { get; set; } } public static class StripeKeyChecker { public static async Task CheckKeyAsync(IHttpClientFactory httpFactory, string apiKey) { try { var client = httpFactory.CreateClient(); client.Timeout = TimeSpan.FromSeconds(30); var isLive = apiKey.StartsWith("sk_live_", StringComparison.Ordinal); // Step 1: Check /v1/balance (read-only, no cost) var balanceRequest = new HttpRequestMessage(HttpMethod.Get, "https://api.stripe.com/v1/balance"); balanceRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", apiKey); var balanceResp = await client.SendAsync(balanceRequest); var balanceBody = await balanceResp.Content.ReadAsStringAsync(); var balanceCode = (int)balanceResp.StatusCode; if (balanceCode == 401) { return new StripeCheckResult { Status = "invalid", Message = "Ungültig oder revoked (401)", IsLiveKey = isLive }; } if (balanceCode >= 400) { // Parse error var errorMsg = "Unbekannter Fehler"; try { using var errDoc = JsonDocument.Parse(balanceBody); if (errDoc.RootElement.TryGetProperty("error", out var errObj) && errObj.TryGetProperty("message", out var msg)) errorMsg = msg.GetString(); } catch { } return new StripeCheckResult { Status = "error", Message = $"API-Fehler ({balanceCode}): {errorMsg}", IsLiveKey = isLive }; } // Parse balance string currency = null; long balanceAvailable = 0; long balancePending = 0; try { using var balDoc = JsonDocument.Parse(balanceBody); var root = balDoc.RootElement; if (root.TryGetProperty("available", out var available) && available.GetArrayLength() > 0) { var first = available[0]; if (first.TryGetProperty("currency", out var cur)) currency = cur.GetString()?.ToUpperInvariant(); if (first.TryGetProperty("amount", out var amt)) balanceAvailable = amt.GetInt64(); } if (root.TryGetProperty("pending", out var pending) && pending.GetArrayLength() > 0) { var first = pending[0]; if (first.TryGetProperty("amount", out var amt)) balancePending = amt.GetInt64(); } } catch { } // Step 2: Get account info via /v1/account string accountId = null; string accountName = null; string accountEmail = null; string accountCountry = null; bool? payoutsEnabled = null; bool? chargesEnabled = null; try { var accountRequest = new HttpRequestMessage(HttpMethod.Get, "https://api.stripe.com/v1/account"); accountRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", apiKey); var accountResp = await client.SendAsync(accountRequest); if ((int)accountResp.StatusCode == 200) { var accountBody = await accountResp.Content.ReadAsStringAsync(); using var accDoc = JsonDocument.Parse(accountBody); var acc = accDoc.RootElement; if (acc.TryGetProperty("id", out var id)) accountId = id.GetString(); if (acc.TryGetProperty("business_profile", out var bp) && bp.TryGetProperty("name", out var name)) accountName = name.GetString(); if (acc.TryGetProperty("email", out var email)) accountEmail = email.GetString(); if (acc.TryGetProperty("country", out var country)) accountCountry = country.GetString(); if (acc.TryGetProperty("payouts_enabled", out var pe)) payoutsEnabled = pe.GetBoolean(); if (acc.TryGetProperty("charges_enabled", out var ce)) chargesEnabled = ce.GetBoolean(); } } catch { } // Build message var parts = new System.Collections.Generic.List(); parts.Add(isLive ? "🔴 LIVE Key" : "🟡 Test Key"); if (accountName != null) parts.Add($"Account: {accountName}"); else if (accountId != null) parts.Add($"Account: {accountId}"); if (accountEmail != null) parts.Add($"Email: {accountEmail}"); if (accountCountry != null) parts.Add($"Land: {accountCountry}"); if (currency != null) { var availFormatted = FormatAmount(balanceAvailable, currency); var pendingFormatted = FormatAmount(balancePending, currency); parts.Add($"Balance: {availFormatted} verfügbar, {pendingFormatted} ausstehend"); } if (chargesEnabled.HasValue) parts.Add(chargesEnabled.Value ? "✅ Charges aktiv" : "❌ Charges deaktiviert"); if (payoutsEnabled.HasValue) parts.Add(payoutsEnabled.Value ? "✅ Payouts aktiv" : "❌ Payouts deaktiviert"); return new StripeCheckResult { Status = "ok", Message = string.Join(" · ", parts), IsLiveKey = isLive, Currency = currency, BalanceAvailable = balanceAvailable, BalancePending = balancePending, AccountId = accountId, AccountName = accountName, AccountEmail = accountEmail, AccountCountry = accountCountry, PayoutsEnabled = payoutsEnabled, ChargesEnabled = chargesEnabled }; } catch (Exception ex) { return new StripeCheckResult { Status = "error", Message = ex.Message, IsLiveKey = apiKey.StartsWith("sk_live_", StringComparison.Ordinal) }; } } private static string FormatAmount(long amountInCents, string currency) { var amount = amountInCents / 100.0; return $"{amount:N2} {currency}"; } } }