Ejemplo en CSHARP

Ejemplo de uso del API SAT en csharp.

Archivo fuente: csharp.cs

// Ejemplo C# — POST /api/v1/usuario/datos-fiscales

// Requiere .NET 6+ y System.Text.Json (incluido).

//

// Uso:

//   setx SAT_API_KEY "sat_xxxxxxxxxxxx"  (Windows)

//   export SAT_API_KEY="sat_xxxxxxxxxxxx" (Linux/macOS)

//   dotnet run --project SatApiExample.cs [RFC]


using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

class SatApiExample
{
    private const string BASE_URL = "https://api.cfdi4.com";

    private const string USER_AGENT = "csharp-sat-api/1.0";

    private readonly HttpClient _http;
    private readonly string _apiKey;

    public SatApiExample(string apiKey)
    {
        _apiKey = apiKey;
        _http = new HttpClient
        {
            BaseAddress = new Uri(BASE_URL),
            Timeout = TimeSpan.FromSeconds(30),
        };
        _http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
        _http.DefaultRequestHeaders.UserAgent.ParseAdd(USER_AGENT);
    }

    public async Task<JsonElement> DatosFiscalesAsync(string rfc)
    {
        return await PostAsync("/api/v1/usuario/datos-fiscales", new
        {
            rfc = rfc.ToUpper().Trim()
        });
    }

    private async Task<JsonElement> PostAsync(string endpoint, object body)
    {
        var json = JsonSerializer.Serialize(body);
        var content = new StringContent(json, Encoding.UTF8, "application/json");
        var response = await _http.PostAsync(endpoint, content);
        var responseText = await response.Content.ReadAsStringAsync();
        using var doc = JsonDocument.Parse(responseText);
        return doc.RootElement.GetProperty("body").Clone();
    }

    static async Task<int> Main(string[] args)
    {
        var apiKey = Environment.GetEnvironmentVariable("SAT_API_KEY");
        if (string.IsNullOrEmpty(apiKey))
        {
            Console.Error.WriteLine("ERROR: configura la variable de entorno SAT_API_KEY");
            Console.Error.WriteLine("  setx SAT_API_KEY \"sat_xxxxxxxxxxxx\"");
            return 1;
        }

        var rfc = args.Length > 0 ? args[0] : "XAXX010101000";
        Console.WriteLine($"Consultando datos fiscales de RFC: {rfc}\n");

        try
        {
            var client = new SatApiExample(apiKey);
            var result = await client.DatosFiscalesAsync(rfc);

            var codigo = result.GetProperty("cfdi_codigo").GetInt32();
            var texto = result.GetProperty("cfdi_texto").GetString() ?? "";
            var desc = result.GetProperty("cfdi_descripcion").GetString() ?? "";
            var saldo = result.TryGetProperty("saldo", out var s) ? s.GetInt32() : 0;

            Console.WriteLine($"  Código:    {codigo}");
            Console.WriteLine($"  Texto:     {texto}");
            Console.WriteLine($"  Detalle:   {desc}");
            Console.WriteLine($"  Saldo:     {saldo} créditos");

            if (codigo == 1)
            {
                if (result.TryGetProperty("data", out var data))
                {
                    Console.WriteLine("\n  Datos fiscales:");
                    Console.WriteLine("  " + JsonSerializer.Serialize(data,
                        new JsonSerializerOptions { WriteIndented = true, Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping }));
                }
                return 0;
            }
            if (codigo == 1004) Console.WriteLine("\n  ⚠️  Saldo insuficiente. Recarga en https://panel.cfdi4.com/saldos");

            if (codigo == 1001) Console.WriteLine("\n  ⚠️  API key inválida");
        }
        catch (Exception e)
        {
            Console.Error.WriteLine($"Error: {e.Message}");
        }
        return 1;
    }
}