![]() |
VOOZH | about |
dotnet add package RoeFactura --version 1.1.2
NuGet\Install-Package RoeFactura -Version 1.1.2
<PackageReference Include="RoeFactura" Version="1.1.2" />
<PackageVersion Include="RoeFactura" Version="1.1.2" />Directory.Packages.props
<PackageReference Include="RoeFactura" />Project file
paket add RoeFactura --version 1.1.2
#r "nuget: RoeFactura, 1.1.2"
#:package RoeFactura@1.1.2
#addin nuget:?package=RoeFactura&version=1.1.2Install as a Cake Addin
#tool nuget:?package=RoeFactura&version=1.1.2Install as a Cake Tool
RoEFactura is a .NET library for integrating with the Romanian ANAF eFactura system. It supports certificate-based authentication for desktop/server scenarios and OAuth 2.0 redirect flow for web apps. It also provides local UBL 2.1 processing with RO_CIUS validation.
Install-Package RoEFactura
dotnet add package RoEFactura
<PackageReference Include="RoEFactura" Version="1.1.1" />
using Microsoft.Extensions.DependencyInjection;
using RoEFactura;
using RoEFactura.Services.Api;
using RoEFactura.Services.Authentication;
var services = new ServiceCollection();
services.AddRoEFactura();
var provider = services.BuildServiceProvider();
var auth = provider.GetRequiredService<IAnafOAuthClient>();
var invoices = provider.GetRequiredService<IAnafEInvoiceClient>();
var token = await auth.GetAccessTokenAsync(
clientId: "your_client_id",
clientSecret: "your_client_secret",
callbackUrl: "https://yourapp.com/callback");
var items = await invoices.ListEInvoicesAsync(
token.AccessToken, days: 30, cui: "RO12345678");
// Program.cs
builder.Services.AddRoEFacturaWithOAuth(builder.Configuration, "AnafOAuth");
// appsettings.json
{
"AnafOAuth": {
"ClientId": "your_client_id",
"ClientSecret": "your_client_secret",
"RedirectUri": "https://yourapp.com/api/oauth/callback"
}
}
// Controller example
[HttpPost("oauth/initiate")]
public IActionResult Initiate()
{
var state = GenerateState();
var authUrl = _anafClient.GenerateAuthorizationUrl(_options, state);
return Ok(new { authorizationUrl = authUrl, state });
}
[HttpGet("oauth/callback")]
public async Task<IActionResult> Callback(string code, string state)
{
ValidateState(state);
var token = await _anafClient.ExchangeAuthorizationCodeAsync(code, _options);
await StoreTokenAsync(token);
return Redirect("/dashboard?authorized=true");
}
You can configure OAuth options via configuration or direct options:
services.AddRoEFacturaWithOAuth(new AnafOAuthOptions
{
ClientId = "your_client_id",
ClientSecret = "your_client_secret",
RedirectUri = "https://yourapp.com/oauth/callback",
AuthorizeUrl = "https://logincert.anaf.ro/anaf-oauth2/v1/authorize",
TokenUrl = "https://logincert.anaf.ro/anaf-oauth2/v1/token",
IncludeTokenContentType = true
});
var items = await invoiceClient.ListEInvoicesAsync(token.AccessToken, 30, "RO12345678", filter: null);
long start = DateTimeOffset.UtcNow.AddDays(-30).ToUnixTimeMilliseconds();
long end = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var page = await invoiceClient.ListPagedEInvoicesAsync(
token.AccessToken, start, end, "RO12345678", filter: null, page: 1);
var result = await invoiceClient.ProcessDownloadedInvoiceAsync(token.AccessToken, "download_id");
if (result.IsSuccess)
{
var invoice = result.Data;
var totalDue = invoice.GetTotalAmountDue();
}
var localResult = await invoiceClient.ValidateInvoiceXmlAsync(xmlContent);
if (!localResult.IsSuccess)
{
foreach (var error in localResult.Errors)
{
Console.WriteLine($"{error.ErrorCode}: {error.ErrorMessage}");
}
}
string validateResponse = await invoiceClient.ValidateXmlContentAsync(token.AccessToken, xmlContent);
string uploadResponse = await invoiceClient.UploadXmlContentAsync(token.AccessToken, xmlContent);
Notes:
filter is passed as ANAF query parameter filtru. Accepted values are defined by ANAF.Steps:
var list = await invoiceClient.ListEInvoicesAsync(token.AccessToken, 30, "RO12345678");
foreach (var item in list)
{
var processed = await invoiceClient.ProcessDownloadedInvoiceAsync(token.AccessToken, item.Id);
if (processed.IsSuccess)
{
Console.WriteLine(processed.Data?.ID?.Value);
}
}
Steps:
var local = await invoiceClient.ValidateInvoiceXmlAsync(xmlContent);
if (!local.IsSuccess)
{
return; // handle errors
}
await invoiceClient.ValidateXmlContentAsync(token.AccessToken, xmlContent);
await invoiceClient.UploadXmlContentAsync(token.AccessToken, xmlContent);
var expiresAt = DateTime.UtcNow.AddSeconds(token.ExpiresIn);
if (expiresAt <= DateTime.UtcNow.AddMinutes(5))
{
token = await auth.GetAccessTokenAsync(clientId, clientSecret, callbackUrl);
}
var result = await invoiceClient.ProcessDownloadedInvoiceAsync(token.AccessToken, "download_id");
if (result.IsSuccess && result.Data != null)
{
var invoice = result.Data;
var sellerVat = invoice.GetSellerVatId();
var totalWithVat = invoice.GetTotalWithVat();
var summary = invoice.GetValidationSummary();
}
var local = await invoiceClient.ValidateInvoiceXmlAsync(xmlContent);
if (!local.IsSuccess)
{
// local RO_CIUS errors
}
var anafResponse = await invoiceClient.ValidateXmlContentAsync(token.AccessToken, xmlContent);
| Method | Returns | Description |
|---|---|---|
IsRomanianInvoice() |
bool | Detects Romanian invoices (RO_CIUS or RO parties) |
GetCurrencyCode() |
string | Document currency code |
GetTotalAmountDue() |
decimal | Payable amount |
GetTotalWithoutVat() |
decimal | Tax exclusive amount |
GetTotalWithVat() |
decimal | Tax inclusive amount |
GetTotalVat() |
decimal | Total VAT amount |
GetSumOfLineNet() |
decimal | Sum of line net amounts |
GetValidationSummary() |
string | Human-readable validation summary |
GetSellerVatId() |
string? | Seller VAT identifier |
GetBuyerVatId() |
string? | Buyer VAT identifier |
GetSellerLegalId() |
string? | Seller legal registration id |
GetBuyerLegalId() |
string? | Buyer legal registration id |
LoadInvoiceFromXml() |
InvoiceType? | Parse UBL XML to object |
SaveInvoiceToXml() |
string | Serialize UBL invoice to XML |
| Constant | Values |
|---|---|
RoCiusCustomizationId |
urn:cen.eu:en16931:2017#compliant#urn:efactura.mfinante.ro:RO_CIUS:1.0.0.2021 |
ValidInvoiceTypeCodes |
380, 389, 384, 381, 751 |
ValidVatPointDateCodes |
3, 35, 432 |
ValidCountyCodes |
AB, AR, AG, B, BC, BH, BN, BT, BV, BR, BZ, CS, CL, CJ, CT, CV, DB, DJ, GL, GR, GJ, HR, HD, IL, IS, IF, MM, MH, MS, NT, OT, PH, SM, SJ, SB, SV, TR, TM, TL, VS, VL, VN |
flowchart TB
subgraph Authentication [Authentication Layer]
cert[Certificate Auth]
oauth[OAuth Web Flow]
end
subgraph API [API Layer]
client[AnafEInvoiceClient]
end
subgraph Processing [Processing Layer]
ubl[UblProcessingService]
valid[RoCiusUblValidator]
end
cert --> client
oauth --> client
client --> ubl
ubl --> valid
AnafEInvoiceClient.Contributions are welcome. Please open an issue with details and a minimal reproduction. Pull requests should include documentation updates where relevant.
MIT License. See .
dotnet add package RoEFactura
services.AddRoEFactura();
var token = await anafOAuthClient.GetAccessTokenAsync(clientId, clientSecret, callbackUrl);
var invoices = await anafEInvoiceClient.ListEInvoicesAsync(token.AccessToken, 30, "RO12345678");
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 net9.0 is compatible. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.
See CHANGELOG.md