using System.Net.Http.Json; using System.Text.Json; namespace Distribution.Features.GeneralLedger; public record GeneralLedgerResult(int StatusCode, bool Success, JsonElement? Body); public interface IGeneralLedgerClient { Task IsHealthyAsync(CancellationToken ct = default); Task SendAsync(HttpMethod method, string path, object? payload = null, CancellationToken ct = default); } /// /// Service-to-service client for the General Ledger microservice. The GL service is not user-facing: /// every request carries the shared X-Api-Key (GeneralLedger:ApiKey, must equal the GL service's ApiKey:Value). /// is relative to GeneralLedger:BaseUrl and carries the API version (e.g. "v1/accounts", "v1/journal-entries"), so moving a call to v2 is a one-path change. /// public class GeneralLedgerClient(HttpClient http) : IGeneralLedgerClient { public async Task IsHealthyAsync(CancellationToken ct = default) { try { using var response = await http.GetAsync("/health", ct); return response.IsSuccessStatusCode; } catch (HttpRequestException) { return false; } } public async Task SendAsync(HttpMethod method, string path, object? payload = null, CancellationToken ct = default) { using var request = new HttpRequestMessage(method, path.TrimStart('/')); if (payload is not null) request.Content = JsonContent.Create(payload); using var response = await http.SendAsync(request, ct); JsonElement? body = null; if (response.Content.Headers.ContentLength != 0) { try { body = await response.Content.ReadFromJsonAsync(cancellationToken: ct); } catch (JsonException) { } } return new GeneralLedgerResult((int)response.StatusCode, response.IsSuccessStatusCode, body); } }