90 lines
3.2 KiB
C#
90 lines
3.2 KiB
C#
using Microsoft.OpenApi.Models;
|
|
using Newtonsoft.Json;
|
|
using Idoklad.Client;
|
|
using Idoklad.Configuration;
|
|
using Idoklad.Credentials;
|
|
using Idoklad.Infrastructure;
|
|
using Idoklad.Services;
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
// Configuration resolved from environment variables (single shared instance).
|
|
var settings = new IdokladSettings();
|
|
builder.Services.AddSingleton(settings);
|
|
|
|
// HttpClient for the iDoklad SDK, managed by IHttpClientFactory (recommended SDK usage).
|
|
builder.Services.AddHttpClient(DokladApiFactory.HttpClientName, client =>
|
|
{
|
|
client.Timeout = TimeSpan.FromSeconds(settings.RequestTimeoutSeconds);
|
|
});
|
|
|
|
builder.Services.AddHttpContextAccessor();
|
|
|
|
// Credential resolution + SDK client wiring.
|
|
builder.Services.AddScoped<RequestCredentialsProvider>();
|
|
builder.Services.AddScoped<DokladApiFactory>();
|
|
builder.Services.AddScoped<IdokladApiAccessor>();
|
|
|
|
// Agenda services.
|
|
builder.Services.AddScoped<ContactsService>();
|
|
builder.Services.AddScoped<IssuedInvoicesService>();
|
|
builder.Services.AddScoped<ReceivedInvoicesService>();
|
|
builder.Services.AddScoped<RegistersService>();
|
|
builder.Services.AddScoped<AccountService>();
|
|
|
|
// Use Newtonsoft.Json so request/response binding matches the iDoklad SDK model attributes.
|
|
builder.Services
|
|
.AddControllers()
|
|
.AddNewtonsoftJson(options =>
|
|
{
|
|
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
|
|
});
|
|
|
|
builder.Services.AddEndpointsApiExplorer();
|
|
builder.Services.AddSwaggerGen(options =>
|
|
{
|
|
options.SwaggerDoc("v1", new OpenApiInfo
|
|
{
|
|
Title = settings.AppName,
|
|
Version = settings.AppVersion,
|
|
Description =
|
|
"REST integration with iDoklad built on the official IdokladSdk (.NET) 5.3.0, " +
|
|
"using the OAuth2 client credentials flow.\n\n" +
|
|
"**Credentials.** Every agenda endpoint needs an iDoklad ClientId, ClientSecret and ApplicationId. " +
|
|
"Sensitive values are required in request headers and are never accepted in the query string or body:\n\n" +
|
|
"- `X-ClientId` — iDoklad OAuth2 ClientId\n" +
|
|
"- `X-ClientSecret` — iDoklad OAuth2 ClientSecret (sensitive; TLS only)\n" +
|
|
"- `X-ApplicationId` — iDoklad ApplicationId from the developer portal\n" +
|
|
"- `X-Idoklad-Language` — optional response language (Cz, Sk, En)\n\n" +
|
|
"If a header is omitted, the matching environment default " +
|
|
"(`IDOKLAD_CLIENT_ID`, `IDOKLAD_CLIENT_SECRET`, `IDOKLAD_APPLICATION_ID`) is used. " +
|
|
"If neither a header nor a default is available, the request is rejected with 401.",
|
|
});
|
|
options.OperationFilter<CredentialHeadersOperationFilter>();
|
|
|
|
var xmlPath = Path.Combine(AppContext.BaseDirectory, $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}.xml");
|
|
if (File.Exists(xmlPath))
|
|
{
|
|
options.IncludeXmlComments(xmlPath, includeControllerXmlComments: true);
|
|
}
|
|
});
|
|
|
|
var app = builder.Build();
|
|
|
|
if (!string.IsNullOrWhiteSpace(settings.RootPath))
|
|
{
|
|
app.UsePathBase(settings.RootPath);
|
|
}
|
|
|
|
app.UseMiddleware<ExceptionHandlingMiddleware>();
|
|
|
|
app.UseSwagger();
|
|
app.UseSwaggerUI(options =>
|
|
{
|
|
options.SwaggerEndpoint("v1/swagger.json", $"{settings.AppName} v1");
|
|
});
|
|
|
|
app.MapControllers();
|
|
|
|
app.Run();
|