ShamDevs.EFatoraJo.Sdk
1.0.1
dotnet add package ShamDevs.EFatoraJo.Sdk --version 1.0.1
NuGet\Install-Package ShamDevs.EFatoraJo.Sdk -Version 1.0.1
<PackageReference Include="ShamDevs.EFatoraJo.Sdk" Version="1.0.1" />
<PackageVersion Include="ShamDevs.EFatoraJo.Sdk" Version="1.0.1" />
<PackageReference Include="ShamDevs.EFatoraJo.Sdk" />
paket add ShamDevs.EFatoraJo.Sdk --version 1.0.1
#r "nuget: ShamDevs.EFatoraJo.Sdk, 1.0.1"
#:package ShamDevs.EFatoraJo.Sdk@1.0.1
#addin nuget:?package=ShamDevs.EFatoraJo.Sdk&version=1.0.1
#tool nuget:?package=ShamDevs.EFatoraJo.Sdk&version=1.0.1
JoFatora .NET Client
A high-performance .NET SDK for seamless integration with Jordan's JoFatora e-invoicing system. It's built with a clean architecture and comprehensive async support to make compliance with local tax regulations fast and hassle-free.
SDK عالي الأداء مخصص للربط السلس مع منصة الفوترة الإلكترونية الأردنية JoFatora. تم بناؤه بهيكلية نظيفة ودعم كامل للعمليات غير المتزامنة، لتسهيل الامتثال للمتطلبات الضريبية المحلية وجعل عملية الربط بسيطة وسريعة.
Table of Contents
- Features
- Installation
- Quick Start
- Usage Examples
- Core Components
- Validation
- Error Handling
- Response Handling
- Testing
- API Reference
- Requirements
- Contributing
- License
- Support
Features
- 🚀 Full UBL 2.1 Compliance – Generate standards-compliant invoices and credit notes.
- ✅ Pre-submission Validation – Comprehensive invoice validation before API calls.
- 📊 Rich Response Handling – Detailed submission results with error breakdowns and warnings.
- 🏗️ Strong Typing – Type-safe C# models for all entities and responses.
- ⚡ High Performance – Fully async operations with configurable timeouts and retry policies.
- 🔧 Multiple Invoice Types – Support for standard, income, special sales, and return invoices.
- 🌍 Multi-Currency Support – JOD, USD, EUR with proper formatting.
- 🛡️ Exception Safety – Structured exception handling with detailed error context.
- 🧪 Test Data Generation – Built-in utilities for generating test invoices.
- 🌐 Broad .NET Compatibility: Works across .NET Framework 4.6.1+, .NET Core 2.0+, and .NET 5+.
Installation
Package Manager
Install-Package ShamDevs.EFatoraJo.Sdk
.NET CLI
dotnet add package ShamDevs.EFatoraJo.Sdk
PackageReference
<PackageReference Include="ShamDevs.EFatoraJo.Sdk" Version="1.0.0" />
Quick Start
1. Submit a Standard Invoice
using ShamDevs.EFatoraJo;
using ShamDevs.EFatoraJo.Models;
using ShamDevs.EFatoraJo.Enums;
using ShamDevs.EFatoraJo.Exceptions;
var invoice = new Invoice
{
InvoiceNumber = "INV-2025-001",
UniqueSerialNumber = Guid.NewGuid().ToString(),
InvoiceDate = DateTime.Now.ToString("yyyy-MM-dd"),
InvoiceTypeCode = "Tax Invoice",
InvoiceNote = "Standard sales invoice",
Type = InvoiceType.Standard,
Currency = CurrencyCode.JOD,
Supplier = new Supplier
{
RegisteredSupplierName = "My Company Ltd",
TaxVATNumber = "123456789",
IncomeSourceSequence = "1"
},
Customer = new Customer
{
Name = "Customer Name",
IdentificationType = IdentificationType.NationalID,
IdentificationNumber = "987654321",
City = CityCode.Amman,
PostalCode = "11118",
PhoneNumber = "+962791234567"
},
InvoiceDetails = new List<InvoiceDetail>
{
new InvoiceDetail
{
ID = "1",
Description = "Product or Service",
Quantity = 1,
UnitPriceBeforeTax = 100.000m,
TotalBeforeTax = 100.000m,
TaxCategory = TaxCategoryCode.StandardRate,
TaxAmount = 16.000m,
TotalIncludingTax = 116.000m
}
},
InvoiceTotals = new InvoiceTotals
{
TotalBeforeDiscount = 100.000m,
TotalDiscountAmount = 0.000m,
TotalVATAmount = 16.000m,
TotalInvoiceAmount = 116.000m
}
};
try
{
var response = await EFatoraJoSdk.SendFatoraAsync(invoice, "your_client_id", "your_secret_key");
if (response.IsSuccessfullySubmitted())
{
Console.WriteLine($"✅ Invoice submitted successfully!");
Console.WriteLine($"📱 QR Code: {response.Qr}");
Console.WriteLine($"🆔 Submission ID: {response.Results?.SubmissionId}");
}
else
{
Console.WriteLine($"❌ Submission failed: {response.GetFormattedErrors()}");
}
}
catch (InvoiceValidationException ex)
{
Console.WriteLine($"❌ Validation failed: {string.Join(", ", ex.ValidationErrors)}");
}
catch (EInvoiceApiException ex)
{
Console.WriteLine($"❌ API Error: {ex.Message}");
}
2. Submit a Sales Return Invoice
var returnInvoice = new SalesReturnInvoice
{
InvoiceNumber = "RET-2025-001",
ReturnReason = "Customer requested refund",
OriginalInvoiceNumber = "INV-2025-001",
};
var returnResponse = await EFatoraJoSdk.SendReturnFatoraAsync(
returnInvoice,
"your_client_id",
"your_secret_key");
if (returnResponse.IsSuccessfullySubmitted())
{
Console.WriteLine("✅ Return invoice processed successfully!");
}
Usage Examples
Invoice Types
Standard Sales Invoice
var standardInvoice = new Invoice
{
Type = InvoiceType.Standard,
// VAT is calculated automatically
};
Income Invoice (No VAT)
var incomeInvoice = new Invoice
{
Type = InvoiceType.Income,
// No VAT calculations applied
};
Special Sales Invoice (with Special Tax)
var specialInvoice = new Invoice
{
Type = InvoiceType.SpecialSales,
InvoiceDetails = new List<InvoiceDetail>
{
new InvoiceDetail
{
SpecialTaxAmount = 5.000m, // Special tax amount
// ... other fields
}
}
};
Multi-Currency Support
// USD Invoice - CurrencyCode is set automatically
var usdInvoice = new Invoice
{
Currency = CurrencyCode.USD,
// CurrencyCode property will be automatically set to "USD"
// Amounts in USD
};
// EUR Invoice - CurrencyCode is set automatically
var eurInvoice = new Invoice
{
Currency = CurrencyCode.EUR,
// CurrencyCode property will be automatically set to "EUR"
// Amounts in EUR
};
Core Components
Models Overview
Model | Purpose | Required Fields |
---|---|---|
Invoice |
Standard tax invoice | InvoiceNumber, Supplier, Customer, InvoiceDetails, InvoiceTotals |
SalesReturnInvoice |
Credit notes / returns | All Invoice fields + ReturnReason |
Supplier |
Seller information | RegisteredSupplierName, TaxVATNumber |
Customer |
Buyer information | Name, IdentificationType, IdentificationNumber |
InvoiceDetail |
Line items | Description, Quantity, UnitPriceBeforeTax |
InvoiceTotals |
Invoice totals | TotalBeforeDiscount, TotalInvoiceAmount |
Service Classes
Service | Purpose |
---|---|
InvoiceValidator |
Pre-submission validation |
InvoiceGeneratorService |
UBL 2.1 document generation |
RandomInvoiceGenerator |
Test data generation |
InvoiceHelper |
UBL serialization utilities |
Validation
Manual Validation
var validator = new InvoiceValidator();
var validationResult = validator.Validate(invoice);
if (!validationResult.IsValid)
{
foreach (var error in validationResult.Errors)
{
Console.WriteLine($"❌ {error.PropertyName}: {error.ErrorMessage}");
}
}
Common Validation Rules
- Invoice Number: Must be unique and non-empty.
- Dates: Must be in ISO format (yyyy-MM-dd).
- Tax Numbers: Must be in a valid Jordan tax format.
- Amounts: Must be positive and properly formatted (3 decimal places).
- Phone Numbers: Must include the country code (+962).
- Currency: Must match the invoice currency throughout.
Error Handling
Exception Types
Exception | Description | Common Causes |
---|---|---|
InvoiceValidationException |
Invoice data validation failed | Missing required fields, invalid formats |
UblGenerationException |
UBL document creation failed | Malformed data, XML generation issues |
EInvoiceApiException |
API communication error | Network issues, server errors, invalid credentials |
EInvoiceSerializationException |
Serialization/deserialization failed | Invalid XML/JSON, encoding issues |
Comprehensive Error Handling
try
{
var response = await EFatoraJoSdk.SendFatoraAsync(invoice, clientId, secretKey);
return response;
}
catch (InvoiceValidationException ex)
{
_logger.LogWarning("Invoice validation failed: {Errors}",
string.Join(", ", ex.ValidationErrors));
// Handle validation errors - usually user input issues
return BadRequest(ex.ValidationErrors);
}
catch (EInvoiceApiException ex)
{
_logger.LogError(ex, "JoFatora API error: {StatusCode}", ex.StatusCode);
// Handle API errors - retry logic or user notification
if (ex.IsRetryable)
{
// Implement retry logic
return await RetrySubmission(invoice, clientId, secretKey);
}
return StatusCode(502, "External service unavailable");
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error during invoice submission");
return StatusCode(500, "Internal server error");
}
Response Handling
Response Status Checking
var response = await EFatoraJoSdk.SendFatoraAsync(invoice, clientId, secretKey);
// Check overall success
if (response.IsSuccessfullySubmitted())
{
Console.WriteLine("✅ Success");
}
// Check for errors
if (response.HasErrors())
{
var errors = response.GetFormattedErrors();
Console.WriteLine($"❌ Errors: {errors}");
}
// Check for warnings
if (response.HasWarnings())
{
var warnings = response.GetFormattedWarnings();
Console.WriteLine($"⚠️ Warnings: {warnings}");
}
// Get detailed status
Console.WriteLine($"Status: {response.Results?.Status}");
Console.WriteLine($"Processing Status: {response.Results?.ProcessingStatus}");
Response Data Extraction
if (response.IsSuccessfullySubmitted())
{
// QR Code for printing
var qrCode = response.Qr;
// Submission tracking
var submissionId = response.Results?.SubmissionId;
var timestamp = response.Results?.SubmissionTime;
// Tax authority reference
var taxReference = response.Results?.TaxAuthorityReference;
// Use these for record keeping, printing, etc.
await SaveInvoiceRecord(invoice.InvoiceNumber, submissionId, qrCode);
}
Testing
Generate Test Data
The SDK includes RandomInvoiceGenerator
for generating realistic, valid test data for direct testing with the JoFatora API.
// Generate random standard invoice for testing
var testInvoice = RandomInvoiceGenerator.GenerateRandomInvoice();
// Generate random return invoice for testing
var testReturn = RandomInvoiceGenerator.GenerateRandomSalesReturnInvoice();
Console Application Example
The SDK includes a dedicated console application that you can use to generate and submit random invoices to the JoFatora test environment. This is a great way to validate your setup and explore different invoice types.
The application works in these simple steps:
- Configuration: It reads your JoFatora API credentials and supplier information from user secrets.
- User Input: It prompts you to select the type of invoice you want to test (e.g., General Sales, Special Sales, or Income) and the payment method.
- Generation: It uses the
RandomInvoiceGenerator
to create a complete, valid invoice based on your selections. - Submission: It submits the generated invoice to the JoFatora API.
- Return Invoice: For invoice types that support returns, it automatically generates and submits a corresponding return invoice to test the full lifecycle.
- Reporting: It displays a detailed report on the submission status, including the QR code, submission ID, or any errors and warnings that occurred.
You can run this application directly to test your credentials and confirm that your setup is working correctly before integrating the SDK into your main application.
API Reference
For detailed API documentation, including:
- Complete property mappings between C# classes and UBL 2.1 XML elements.
- Jordan e-Invoicing Arabic labels.
- Response classes and enums.
- Advanced configuration options.
See REFERENCE.md for the comprehensive developer reference guide.
Requirements
- JoFatora API credentials (Client ID and Secret Key).
- Network access to JoFatora API endpoints.
Compatibility
The JoFatora .NET Client SDK is built on .NET Standard 2.0+, ensuring broad compatibility across various .NET platforms. This means you can seamlessly integrate it into applications targeting:
- .NET Framework 4.6.1+
- .NET Core 2.0+ (including all subsequent .NET Core versions)
- All versions of .NET 5+ (e.g., .NET 5, .NET 6, .NET 7, .NET 8, and future versions)
Dependencies
The SDK automatically includes these dependencies:
System.Text.Json
for JSON processing.System.Xml
for UBL document generation.System.Net.Http
for API communication.
🤝 Contributing
We welcome contributions! Please see our Contributing Guidelines for details on:
- 🔧 How to set up your development environment
- 📋 Our coding standards and best practices
- 🔄 The pull request process
- 🐛 How to report bugs and request features
- 💬 Where to ask questions
Reporting Issues
Please report issues on our GitHub Issues page with:
- A clear description of the problem.
- Steps to reproduce.
- Expected vs. actual behavior.
- Sample code (if applicable).
- Environment details (.NET version, OS, etc.).
Changelog
See CHANGELOG.md for a detailed version history.
License
MIT License - see LICENSE file for the full license text.
Support
- 📖 Documentation: Full API Reference
- 🐛 Issues: GitHub Issues
- 💬 Discussions: GitHub Discussions
Made with ❤️ by Sham Software Consultancy for the Jordanian developer community
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Bcl.AsyncInterfaces (>= 9.0.8)
- Newtonsoft.Json (>= 13.0.3)
- System.Buffers (>= 4.5.1)
- System.Diagnostics.DiagnosticSource (>= 8.0.1)
- System.Memory (>= 4.5.5)
- System.Net.Http (>= 4.3.4)
- System.Numerics.Vectors (>= 4.5.0)
- System.Text.Encodings.Web (>= 9.0.8)
- System.Text.Json (>= 9.0.8)
- System.Threading.Tasks.Extensions (>= 4.5.4)
- UblSharp (>= 1.1.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.