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
<PackageReference Include="Yamgooo.SRI.Client" Version="1.1.1" />
<PackageVersion Include="Yamgooo.SRI.Client" Version="1.1.1" />
<PackageReference Include="Yamgooo.SRI.Client" />
paket add Yamgooo.SRI.Client --version 1.1.1
#r "nuget: Yamgooo.SRI.Client, 1.1.1"
#:package Yamgooo.SRI.Client@1.1.1
#addin nuget:?package=Yamgooo.SRI.Client&version=1.1.1
#tool nuget:?package=Yamgooo.SRI.Client&version=1.1.1
SRI Client Service
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
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Support
- Issues: GitHub Issues
- Documentation: Wiki
- Email: erikportillapesantez@outlook.com
๐ Credits
This project was inspired by and builds upon the work of the Acontplus team:
- Acontplus RucService: https://github.com/Acontplus-S-A-S/acontplus-dotnet-libs/blob/main/src/Acontplus.FactElect/Services/Validation/RucService.cs
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 | Versions 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. |
-
net8.0
- Microsoft.AspNetCore.Mvc.Core (>= 2.3.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Http (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Options (>= 8.0.2)
- Newtonsoft.Json (>= 13.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.