RomaniaEFacturaLibrary 2.0.0

dotnet add package RomaniaEFacturaLibrary --version 2.0.0
                    
NuGet\Install-Package RomaniaEFacturaLibrary -Version 2.0.0
                    
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="RomaniaEFacturaLibrary" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RomaniaEFacturaLibrary" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="RomaniaEFacturaLibrary" />
                    
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 RomaniaEFacturaLibrary --version 2.0.0
                    
#r "nuget: RomaniaEFacturaLibrary, 2.0.0"
                    
#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 RomaniaEFacturaLibrary@2.0.0
                    
#: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=RomaniaEFacturaLibrary&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=RomaniaEFacturaLibrary&version=2.0.0
                    
Install as a Cake Tool

Romania EFactura Library v2.0.0

A comprehensive C# library for integrating with the Romanian EFactura (SPV - Spatiu Privat Virtual) system from ANAF. Now with flexible token storage and enhanced security features.

๐Ÿš€ What's New in v2.0.0

  • ๐Ÿ”„ Flexible Token Storage: Choose between MemoryCache, Cookie, or custom storage
  • ๐Ÿ“ CIF as Parameters: CIF is now passed as method parameters instead of configuration
  • ๐Ÿ›ก๏ธ Enhanced Security: Secure cookie options and automatic token cleanup
  • ๏ฟฝ Comprehensive Examples: Complete controller examples for all operations
  • ๐Ÿ”ง Better API Design: Internal API client, cleaner public interface
  • ๐Ÿงช Extensive Testing: Comprehensive unit test coverage

Overview

This library provides a complete solution for:

  • ๐Ÿ” OAuth2 Authentication with flexible token storage (MemoryCache/Cookie)
  • ๐Ÿ“„ UBL 2.1 XML invoice creation and validation
  • ๐ŸŒ API Integration with ANAF test and production environments
  • ๐Ÿ“‹ Invoice Management (upload, download, status tracking, bulk operations)
  • ๐Ÿ”„ XML Processing with proper namespace handling and validation
  • ๐Ÿ›ก๏ธ Security Features with automatic token refresh and secure storage

๐Ÿ“ Repository Structure

  • RomaniaEFacturaLibrary/ - Main library with all EFactura functionality
    • Services/TokenStorage/ - Flexible token storage implementations
    • Services/Api/ - Internal ANAF API client (now internal)
    • Services/ - Public EFactura client and services
  • Examples/Controllers/ - Complete controller examples
    • AuthenticationController.cs - OAuth2 authentication flow
    • InvoiceController.cs - Invoice validation and upload
    • InvoiceManagementController.cs - Download and management
  • RomaniaEFacturaLibrary.Tests/ - Comprehensive test suite
    • TokenStorage/ - Token storage service tests
    • Services/ - Client and service tests
  • RomaniaEFacturaConsole/ - Interactive console application
  • Documentation:
    • TokenStorageGuide.md - Complete token storage guide
    • IMPLEMENTATION_GUIDE.md - Step-by-step implementation
    • CONFIGURATION_GUIDE.md - Configuration reference

โœจ Features

๐Ÿ” Authentication & Token Management

  • OAuth2 Authorization Flow with ANAF
  • Flexible Token Storage:
    • MemoryCache (server-side, fast)
    • Cookie (client-side, persistent)
    • Custom storage (database, Redis, etc.)
  • Automatic Token Refresh with 5-minute buffer
  • User-Isolated Storage based on HttpContext
  • Secure Cookie Options (HttpOnly, Secure, SameSite)

๐Ÿ“„ UBL 2.1 XML Support

  • Complete UBL 2.1 invoice models
  • Proper XML serialization/deserialization
  • Romanian EFactura-specific customizations
  • XML validation and formatting
  • PDF conversion support

๐ŸŒ ANAF API Integration

  • Upload Invoices to ANAF SPV with validation
  • Download Invoices in multiple formats (XML, PDF, raw ZIP)
  • Status Tracking with real-time monitoring
  • Bulk Operations for multiple invoice management
  • Search and Filter invoices by criteria
  • Support for test and production environments

๐Ÿ”ง Developer Experience

  • Comprehensive Examples with ready-to-use controllers
  • Extensive Documentation and usage guides
  • Unit Test Coverage for all major components
  • Dependency Injection support with multiple configuration options
  • Internal API Design - clean public interface
  • List recent invoices with filtering

๐Ÿš€ Quick Start

1. Installation

Install via NuGet Package Manager:

<PackageReference Include="RomaniaEFacturaLibrary" Version="2.0.0" />

Or via Package Manager Console:

Install-Package RomaniaEFacturaLibrary -Version 2.0.0

2. Configuration

Configure in appsettings.json:

{
  "EFactura": {
    "BaseUrl": "https://api.anaf.ro/prod/FCTEL/rest",
    "ClientId": "your-anaf-client-id",
    "ClientSecret": "your-anaf-client-secret", 
    "RedirectUri": "https://yourapp.com/auth/callback",
    "Scope": "efactura"
  }
}

3. Service Registration

Choose your preferred token storage method:

Option A: MemoryCache Storage (Default)
// In Program.cs
builder.Services.AddEFacturaServices(builder.Configuration);
// or
builder.Services.AddEFacturaServicesWithMemoryCache(config =>
{
    config.BaseUrl = "https://api.anaf.ro/prod/FCTEL/rest";
    config.ClientId = "your-client-id";
    config.ClientSecret = "your-client-secret";
    config.RedirectUri = "https://yourapp.com/auth/callback";
});
// In Program.cs
builder.Services.AddEFacturaServicesWithCookieStorage(builder.Configuration);
Option C: Custom Storage
// Implement your own storage
public class DatabaseTokenStorage : ITokenStorageService
{
    // Your implementation...
}

// Register in DI
builder.Services.AddEFacturaServicesWithCustomStorage<DatabaseTokenStorage>(config => 
{
    // Configuration...
});

4. Basic Usage

Note: In v2.0.0, CIF is now passed as a parameter to methods instead of configuration.

Authentication Flow
[ApiController]
public class AuthController : ControllerBase
{
    private readonly IAuthenticationService _authService;
    
    public AuthController(IAuthenticationService authService)
    {
        _authService = authService;
    }
    
    [HttpGet("login")]
    public IActionResult Login()
    {
        var authUrl = _authService.GetAuthorizationUrl(
            clientId: "your-client-id",
            redirectUri: "https://yourapp.com/auth/callback",
            scope: "efactura"
        );
        return Redirect(authUrl);
    }
    
    [HttpGet("callback")]
    public async Task<IActionResult> Callback(string code)
    {
        var token = await _authService.GetAccessTokenAsync(
            code: code,
            clientId: "your-client-id",
            clientSecret: "your-client-secret",
            redirectUri: "https://yourapp.com/auth/callback"
        );
        
        // Token is automatically stored
        return Ok("Authentication successful");
    }
}
Invoice Operations
[ApiController]
[Authorize]
public class InvoiceController : ControllerBase
{
    private readonly IEFacturaClient _eFacturaClient;
    
    public InvoiceController(IEFacturaClient eFacturaClient)
    {
        _eFacturaClient = eFacturaClient;
    }
    
    [HttpPost("validate")]
    public async Task<IActionResult> ValidateInvoice([FromBody] ValidateRequest request)
    {
        var result = await _eFacturaClient.ValidateInvoiceAsync(
            invoice: request.Invoice,
            cif: request.Cif  // CIF now required as parameter
        );
        
        return Ok(result);
    }
    
    [HttpPost("upload")]
    public async Task<IActionResult> UploadInvoice([FromBody] UploadRequest request)
    {
        var result = await _eFacturaClient.UploadInvoiceAsync(
            invoice: request.Invoice,
            cif: request.Cif,
            environment: "prod"  // Optional: "test" or "prod"
        );
        
        return Ok(result);
    }
    
    [HttpGet("messages")]
    public async Task<IActionResult> GetMessages([FromQuery] string cif)
    {
        var messages = await _eFacturaClient.GetInvoicesAsync(
            cif: cif,
            from: DateTime.UtcNow.AddDays(-30),
            to: DateTime.UtcNow
        );
        
        return Ok(messages);
    }
    
    [HttpGet("download/{messageId}")]
    public async Task<IActionResult> DownloadInvoice(string messageId)
    {
        var invoice = await _eFacturaClient.DownloadInvoiceAsync(messageId);
        return Ok(invoice);
    }
    
    [HttpGet("download/{messageId}/pdf")]
    public async Task<IActionResult> DownloadPdf(string messageId)
    {
        var invoice = await _eFacturaClient.DownloadInvoiceAsync(messageId);
        var pdfData = await _eFacturaClient.ConvertToPdfAsync(invoice);
        
        return File(pdfData, "application/pdf", $"invoice_{messageId}.pdf");
    }
}
public class AuthController : ControllerBase
{
    private readonly IAuthenticationService _authService;

    public AuthController(IAuthenticationService authService)
    {
        _authService = authService;
    }

    [HttpGet("login")]
    public IActionResult Login()
    {
        // Step 1: Get authorization URL for ANAF OAuth
        var authUrl = _authService.GetAuthorizationUrl("efactura", "unique-state");
        return Redirect(authUrl);
    }

    [HttpGet("callback")]
    public async Task<IActionResult> Callback(string code, string state)
    {
        // Step 2: Exchange authorization code for access token
        var token = await _authService.ExchangeCodeForTokenAsync(code);
        if (token != null)
        {
            // Store token securely (session, database, etc.)
            _authService.SetToken(token);
            return Ok("Authentication successful");
        }
        
        return BadRequest("Authentication failed");
    }
}

public class InvoiceController : ControllerBase
{
    private readonly IEFacturaClient _eFacturaClient;

    public InvoiceController(IEFacturaClient eFacturaClient)
    {
        _eFacturaClient = eFacturaClient;
    }

    [HttpPost("upload")]
    public async Task<IActionResult> UploadInvoice([FromBody] UblInvoice invoice)
    {
        // Upload to ANAF (token will be automatically used)
        var result = await _eFacturaClient.UploadInvoiceAsync(invoice);
        if (result.IsSuccess)
        {
            return Ok(new { UploadId = result.UploadId });
        }

        return BadRequest(result.Errors);
    }
}

Testing

Run the test suite:

dotnet test RomaniaEFacturaLibrary.Tests

Use the console application for interactive testing:

cd RomaniaEFacturaConsole
dotnet run

Requirements

  • .NET 9.0 or later
  • ANAF Application Registration (ClientId and ClientSecret)
  • Registered Redirect URI with ANAF for OAuth callback

Key Dependencies

  • Microsoft.Extensions.DependencyInjection - Dependency injection
  • Microsoft.Extensions.Logging - Logging framework
  • Microsoft.Extensions.Http - HTTP client factory
  • System.Security.Cryptography.X509Certificates - Certificate handling
  • System.Text.Json - JSON serialization

Build Status

โœ… Solution builds successfully
โœ… All 29 unit tests pass
โœ… Release configuration ready
โœ… Multi-target support (.NET 8.0 and .NET 9.0)
โœ… NuGet package ready

๐Ÿ”— Repository Information

Contributing

This library follows Romanian EFactura specifications and UBL 2.1 standards.

License

This project is provided as-is for educational and development purposes. Please ensure compliance with ANAF regulations and Romanian law when using in production.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  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 2.0.0: Major update with flexible token storage system (MemoryCache/Cookie), CIF parameters instead of configuration, comprehensive example controllers, enhanced security, and improved API design. Breaking changes: CIF now required as method parameters.