Yamgooo.SRI.Client 1.1.1

dotnet add package Yamgooo.SRI.Client --version 1.1.1
                    
NuGet\Install-Package Yamgooo.SRI.Client -Version 1.1.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Yamgooo.SRI.Client" Version="1.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Yamgooo.SRI.Client" Version="1.1.1" />
                    
Directory.Packages.props
<PackageReference Include="Yamgooo.SRI.Client" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Yamgooo.SRI.Client --version 1.1.1
                    
#r "nuget: Yamgooo.SRI.Client, 1.1.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Yamgooo.SRI.Client@1.1.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Yamgooo.SRI.Client&version=1.1.1
                    
Install as a Cake Addin
#tool nuget:?package=Yamgooo.SRI.Client&version=1.1.1
                    
Install as a Cake Tool

SRI Client Service

.NET License NuGet

A professional .NET library for SRI (Servicio de Rentas Internas) client operations in Ecuador. This package provides seamless integration with SRI web services for document validation and authorization of electronic invoices, as well as contributor information queries.

Also available in Spanish: README_es.md

๐Ÿš€ Features

  • Document Validation: Send signed XML documents to SRI for validation and reception
  • Authorization Requests: Request document authorization using access keys
  • Contributor Queries: Get complete contributor information by RUC or cedula
  • Existence Validation: Automatically verify if contributors exist before retrieving their data
  • Environment Support: Support for both test and production SRI environments
  • Async Operations: High-performance asynchronous operations
  • Configuration Support: Multiple configuration options (appsettings.json, code-based, dynamic)
  • Retry Logic: Built-in retry mechanism with configurable parameters
  • Logging: Comprehensive logging with structured logging support
  • Error Handling: Robust error handling with detailed error messages
  • Performance Monitoring: Built-in performance metrics and timing

๐Ÿ“ฆ Installation

NuGet Package

dotnet add package Yamgooo.SRI.Client

Manual Installation

git clone https://github.com/yamgooo/Sri.Client.git
cd Sri.Client
dotnet build

๐Ÿ› ๏ธ Quick Start

1. Basic Usage (Default Configuration)

using Microsoft.Extensions.DependencyInjection;
using Yamgooo.SRI.Client;

var services = new ServiceCollection();

// Register the service with default configuration
services.AddLogging();
services.AddSriClientService();

var provider = services.BuildServiceProvider();
var sriClient = provider.GetRequiredService<ISriClientService>();

// Validate a signed document
var validationResult = await sriClient.ValidateDocumentAsync(signedXml, SriEnvironment.Test);

if (validationResult.Success)
{
    Console.WriteLine($"Document validated successfully. Access Key: {validationResult.AccessKey}");
    
    // Request authorization
    var authResult = await sriClient.RequestAuthorizationAsync(validationResult.AccessKey, SriEnvironment.Test);
    
    if (authResult.Success)
    {
        Console.WriteLine($"Document authorized. Number: {authResult.AuthorizationNumber}");
    }
}

2. Configuration-based Usage

appsettings.json
{
  "SriClient": {
    "TimeoutSeconds": 120,
    "MaxRetries": 3,
    "RetryDelaySeconds": 5
  }
}
Program.cs
// Register with configuration
services.AddSriClientService(configuration);

// Use the service
var sriClient = serviceProvider.GetRequiredService<ISriClientService>();
var result = await sriClient.ValidateDocumentAsync(signedXml);

3. Custom Configuration

var config = new SriServiceConfiguration
{
    TimeoutSeconds = 180,
    MaxRetries = 5,
    RetryDelaySeconds = 10
};

services.AddSriClientService(config);

๐Ÿ“‹ API Reference

ISriClientService Interface

Document Validation
Task<SriValidationResult> ValidateDocumentAsync(string signedXml, SriEnvironment environment = SriEnvironment.Test);
Authorization Request
Task<SriAuthorizationResult> RequestAuthorizationAsync(string accessKey, SriEnvironment environment = SriEnvironment.Test);
Configuration Management
SriServiceConfiguration GetConfiguration();
void UpdateConfiguration(SriServiceConfiguration configuration);

IRucService Interface

Contributor Query by RUC
Task<ContribuyenteCompleteDto> GetRucSriAsync(string ruc);

Features:

  • Automatically validates that RUC has 13 numeric digits
  • Verifies contributor existence in SRI before retrieving data
  • Returns complete contributor information including establishments
  • Throws appropriate exceptions in case of error

ICedulaService Interface

Contributor Query by Cedula
Task<ContribuyenteCedulaDto> GetCedulaSriAsync(string cedula);

Features:

  • Automatically validates that cedula has 10 numeric digits
  • Verifies contributor existence in Civil Registry before retrieving data
  • Returns basic contributor information (identification, full name, death date)
  • Throws appropriate exceptions in case of error

Result Models

SriValidationResult
public class SriValidationResult : SriBaseResult
{
    public string AccessKey { get; set; }
}
SriAuthorizationResult
public class SriAuthorizationResult : SriBaseResult
{
    public string AccessKey { get; set; }
    public string AuthorizationNumber { get; set; }
    public DateTime? AuthorizationDate { get; set; }
    public string Environment { get; set; }
    public string DocumentContent { get; set; }
    public int DocumentCount { get; set; }
}
ContribuyenteCompleteDto
public record ContribuyenteCompleteDto
{
    public required ContribuyenteRucDto Contribuyente { get; set; }
    public required List<EstablecimientoDto> Establecimientos { get; set; }
}
ContribuyenteCedulaDto
public class ContribuyenteCedulaDto
{
    public string Identificacion { get; set; }
    public string NombreCompleto { get; set; }
    public string FechaDefuncion { get; set; }
}

๐Ÿ”ง Configuration Options

Service Registration Methods

// From appsettings.json
services.AddSriClientService(configuration, "SriClient");

// With custom configuration object
services.AddSriClientService(customConfig);

// With direct parameters
services.AddSriClientService(timeoutSeconds: 120, maxRetries: 3, retryDelaySeconds: 5);

// Without configuration (uses defaults)
services.AddSriClientService();

Configuration Properties

  • TimeoutSeconds: Request timeout in seconds (default: 120)
  • MaxRetries: Maximum number of retries (default: 3)
  • RetryDelaySeconds: Delay between retries in seconds (default: 5)

๐Ÿ“ Examples

Complete SRI Document Processing Example

public class SriDocumentProcessor
{
    private readonly ISriClientService _sriClient;
    private readonly ILogger<SriDocumentProcessor> _logger;

    public SriDocumentProcessor(ISriClientService sriClient, ILogger<SriDocumentProcessor> logger)
    {
        _sriClient = sriClient;
        _logger = logger;
    }

    public async Task<ProcessingResult> ProcessDocumentAsync(string signedXml, SriEnvironment environment)
    {
        try
        {
            // Step 1: Validate document
            _logger.LogInformation("Starting document validation");
            var validationResult = await _sriClient.ValidateDocumentAsync(signedXml, environment);
            
            if (!validationResult.Success)
            {
                _logger.LogError("Document validation failed: {ErrorMessage}", validationResult.ErrorMessage);
                return ProcessingResult.CreateFailure(validationResult.ErrorMessage);
            }

            _logger.LogInformation("Document validated successfully. Access Key: {AccessKey}", validationResult.AccessKey);

            // Step 2: Request authorization
            _logger.LogInformation("Requesting document authorization");
            var authResult = await _sriClient.RequestAuthorizationAsync(validationResult.AccessKey, environment);
            
            if (!authResult.Success)
            {
                _logger.LogError("Document authorization failed: {ErrorMessage}", authResult.ErrorMessage);
                return ProcessingResult.CreateFailure(authResult.ErrorMessage);
            }

            _logger.LogInformation("Document authorized successfully. Number: {AuthNumber}", authResult.AuthorizationNumber);
            
            return ProcessingResult.CreateSuccess(authResult);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error processing SRI document");
            return ProcessingResult.CreateFailure(ex.Message);
        }
    }
}

Contributor Query by RUC Example

public class ContributorService
{
    private readonly IRucService _rucService;
    private readonly ILogger<ContributorService> _logger;

    public ContributorService(IRucService rucService, ILogger<ContributorService> logger)
    {
        _rucService = rucService;
        _logger = logger;
    }

    public async Task<ContribuyenteCompleteDto> QueryContributorByRucAsync(string ruc)
    {
        try
        {
            _logger.LogInformation("Querying contributor by RUC: {Ruc}", ruc);
            
            var result = await _rucService.GetRucSriAsync(ruc);
            
            _logger.LogInformation("Contributor found: {Name}", result.Contribuyente.RazonSocial);
            _logger.LogInformation("Establishments found: {Count}", result.Establecimientos.Count);
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error querying contributor by RUC: {Ruc}", ruc);
            throw;
        }
    }
}

Contributor Query by Cedula Example

public class CedulaService
{
    private readonly ICedulaService _cedulaService;
    private readonly ILogger<CedulaService> _logger;

    public CedulaService(ICedulaService cedulaService, ILogger<CedulaService> logger)
    {
        _cedulaService = cedulaService;
        _logger = logger;
    }

    public async Task<ContribuyenteCedulaDto> QueryContributorByCedulaAsync(string cedula)
    {
        try
        {
            _logger.LogInformation("Querying contributor by cedula: {Cedula}", cedula);
            
            var result = await _cedulaService.GetCedulaSriAsync(cedula);
            
            _logger.LogInformation("Contributor found: {Name}", result.NombreCompleto);
            
            if (!string.IsNullOrEmpty(result.FechaDefuncion))
            {
                _logger.LogWarning("Contributor deceased: {DeathDate}", result.FechaDefuncion);
            }
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error querying contributor by cedula: {Cedula}", cedula);
            throw;
        }
    }
}

Complete Integration Example with All Services

public class SriIntegrationService
{
    private readonly ISriClientService _sriClient;
    private readonly IRucService _rucService;
    private readonly ICedulaService _cedulaService;
    private readonly ILogger<SriIntegrationService> _logger;

    public SriIntegrationService(
        ISriClientService sriClient,
        IRucService rucService,
        ICedulaService cedulaService,
        ILogger<SriIntegrationService> logger)
    {
        _sriClient = sriClient;
        _rucService = rucService;
        _cedulaService = cedulaService;
        _logger = logger;
    }

    public async Task<IntegrationResult> ProcessCompleteDocumentAsync(
        string signedXml, 
        string issuerRuc, 
        string receiverCedula)
    {
        try
        {
            // 1. Validate that issuer exists
            var issuerResult = await _rucService.GetRucSriAsync(issuerRuc);
            if (!issuerResult.IsSuccess)
            {
                return IntegrationResult.CreateFailure($"Issuer not found: {issuerResult.Message}");
            }

            // 2. Validate that receiver exists (if natural person)
            if (!string.IsNullOrEmpty(receiverCedula))
            {
                var receiverResult = await _cedulaService.GetCedulaSriAsync(receiverCedula);
                if (!receiverResult.IsSuccess)
                {
                    return IntegrationResult.CreateFailure($"Receiver not found: {receiverResult.Message}");
                }
            }

            // 3. Process SRI document
            var validationResult = await _sriClient.ValidateDocumentAsync(signedXml);
            if (!validationResult.Success)
            {
                return IntegrationResult.CreateFailure($"Validation failed: {validationResult.ErrorMessage}");
            }

            var authResult = await _sriClient.RequestAuthorizationAsync(validationResult.AccessKey);
            if (!authResult.Success)
            {
                return IntegrationResult.CreateFailure($"Authorization failed: {authResult.ErrorMessage}");
            }

            return IntegrationResult.CreateSuccess(new
            {
                Issuer = issuerResult.Data,
                Receiver = receiverCedula,
                Authorization = authResult
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error in complete processing");
            return IntegrationResult.CreateFailure($"Unexpected error: {ex.Message}");
        }
    }
}

๐Ÿ”’ Security Considerations

  • HTTPS Only: Always use HTTPS for production environments
  • Certificate Validation: Ensure proper certificate validation for SRI endpoints
  • Access Key Security: Never log or expose access keys in plain text
  • Network Security: Use secure network configurations
  • Logging: Be careful not to log sensitive information

๐Ÿงช Testing

Unit Testing Example

[Test]
public async Task ValidateDocumentAsync_WithValidXml_ReturnsSuccess()
{
    // Arrange
    var mockLogger = new Mock<ILogger<SriClientService>>();
    var mockHttpClient = new Mock<HttpClient>();
    var service = new SriClientService(mockLogger.Object, mockHttpClient.Object);
    
    var signedXml = "<signed>document</signed>";

    // Act
    var result = await service.ValidateDocumentAsync(signedXml, SriEnvironment.Test);

    // Assert
    Assert.IsNotNull(result);
    // Add more specific assertions based on your test scenario
}

๐Ÿš€ Performance

The service is optimized for high-performance operations:

  • Async Operations: All I/O operations are asynchronous
  • Connection Pooling: Uses HttpClient with connection pooling
  • Retry Logic: Intelligent retry mechanism with exponential backoff
  • Timeout Management: Configurable timeouts for different scenarios
  • Metrics: Built-in performance monitoring

Typical performance metrics:

  • Document validation: ~2-5 seconds
  • Authorization request: ~1-3 seconds
  • Retry scenarios: Additional 5-15 seconds depending on configuration

๐Ÿ“ฆ Dependencies

  • .NET 8.0: Target framework
  • Microsoft.Extensions.Configuration: Configuration support
  • Microsoft.Extensions.DependencyInjection: DI container support
  • Microsoft.Extensions.Http: HttpClient factory
  • Microsoft.Extensions.Logging: Logging infrastructure
  • Microsoft.Extensions.Options: Options pattern support

๐Ÿค Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ“ž Support

๐Ÿ™ Credits

This project was inspired by and builds upon the work of the Acontplus team:

Special thanks to the Acontplus-S-A-S team for their original implementation and contribution to the Ecuadorian developer community.


Made with โค๏ธ for the Ecuadorian developer community

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.1 133 9/2/2025
1.1.0 199 8/25/2025
1.0.2 136 8/14/2025
1.0.1 135 8/13/2025
1.0.0 131 8/13/2025