//using AyCode.Core.Loggers; using AyCode.Core.Loggers; using AyCode.Core.Serializers.Binaries; using AyCode.Services.Server.SignalRs; using AyCode.Services.SignalRs; using DevExpress.AspNetCore; using FruitBank.Common; using FruitBank.Common.Interfaces; using FruitBank.Common.Server.Interfaces; using FruitBank.Common.Server.Services.Loggers; using FruitBank.Common.Server.Services.SignalRs; using Mango.Nop.Services; using Mango.Nop.Services.Loggers; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http.Connections; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR.Protocol; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.DependencyInjection.Extensions; using Nop.Core.Domain.Orders; using Nop.Core.Infrastructure; using Nop.Data; using Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers; using Nop.Plugin.Misc.FruitBankPlugin.Controllers; using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer; using Nop.Plugin.Misc.FruitBankPlugin.Factories; using Nop.Plugin.Misc.FruitBankPlugin.Filters; using Nop.Plugin.Misc.FruitBankPlugin.Models; using Nop.Plugin.Misc.FruitBankPlugin.Services; using Nop.Plugin.Misc.FruitBankPlugin.Services.FileStorage; using Nop.Services.Catalog; using Nop.Services.Common; using Nop.Services.Events; using Nop.Services.Messages; using Nop.Web.Areas.Admin.Factories; using Nop.Web.Areas.Admin.Models.Catalog; using Nop.Web.Areas.Admin.Models.Orders; using System.Net.Http.Headers; using Mango.Nop.Core.Loggers; using AyCode.Services.Nav; using AyCode.Services.Nav.Ekaer; using FruitBank.Common.Services.Ekaer; using FruitBank.Common.Server.Services.Ekaer; using System.Security.Authentication; namespace Nop.Plugin.Misc.FruitBankPlugin.Infrastructure; public class PluginNopStartup : INopStartup { /// /// Add and configure any of the middleware /// /// Collection of service descriptors /// Configuration of the application public void ConfigureServices(IServiceCollection services, IConfiguration configuration) { // Enforce registration of source generated serializers which might not run due to AssemblyLoadContext restrictions Mango.Nop.Core.AcBinaryForcedInit.ForceRegister(); services.AddScoped(); services.AddTransient(); services.AddScoped(); services.AddSingleton(); //services.AddSingleton(); services.Configure(options => { options.ViewLocationExpanders.Add(new ViewLocationExpander()); }); services.AddSingleton(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); //services.AddScoped(); //services.AddScoped(); //services.AddScoped(); services.Replace( ServiceDescriptor.Scoped() ); //services.AddScoped(); services.Replace( ServiceDescriptor.Scoped() ); services.AddScoped, EventConsumer>(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddHttpClient(client => { client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "r8_MUApXYIE5mRjxqy20tsGLehWBJkCzNj0Cwvrh"); }); //services.AddScoped(); //services.AddScoped(); //services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); //services.AddScoped(); services.AddScoped(); // Z.ai GLM-OCR — nagy PDF-eknél 3 perces timeout szükséges (1.86 oldal/mp sebesség) services.AddHttpClient(client => { client.Timeout = TimeSpan.FromMinutes(3); }); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddSingleton(sp => new LocalFileStorageProvider() // Uses default wwwroot/uploads // Or specify custom path: // new LocalFileStorageProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyCustomPath")) ); // Register the file storage service services.AddScoped(); services.AddScoped(); // ── EKÁER (NAV közúti áruforgalom-bejelentés): map → validate → send ────────── services.AddScoped(); // FruitBank.Common — leképezés services.AddScoped(); // AyCode.Services — NAV-validáció services.AddScoped(); // AyCode.Services — validate→send services.AddScoped(); // FruitBank.Common.Server — fogyasztó services.AddHttpClient() // AyCode.Services — NAV HTTP .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { SslProtocols = SslProtocols.Tls12 }); // a NAV TLS 1.2-t vár // A NAV-fiók hitelesítő adatai + a saját telephely/raktár — konfigurációból (appsettings "Ekaer" szekció). // ⚠️ Titkos kulcsok: secret store / appsettings, SOHA NEM a forráskódba. services.AddSingleton(sp => { var c = sp.GetRequiredService().GetSection("Ekaer:Credentials"); return new NavCredentials { User = c["User"] ?? "", Password = c["Password"] ?? "", SigningKey = c["SigningKey"] ?? "", TaxNumber = c["TaxNumber"] ?? "", BaseUrl = c["BaseUrl"] ?? "https://import-test-b.ekaer.nav.gov.hu", // TEST; PROD: https://import.ekaer.nav.gov.hu }; }); services.AddSingleton(sp => { var c = sp.GetRequiredService().GetSection("Ekaer:Company"); return new EkaerCompanyInfo { Name = c["Name"], TaxId = c["TaxId"], CountryCode = c["CountryCode"] ?? "HU", // a NAV EKÁER magyar PostalCode = c["PostalCode"], City = c["City"], Street = c["Street"], // UnloadLocation (saját telephely): magyar címnél a NAV Name/VatNumber/Phone/Email-t is kér — TODO configból összeállítani. }; }); services.AddControllersWithViews(options => { options.Filters.AddService(); }); //services.AddLogging(logging => //{ // logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Error); // //logging.AddAcLogger(category => new Logger(category)); //Minden .net az aclogger-t használja. //}); services.AddSignalR(hubOptions => { hubOptions.EnableDetailedErrors = true; hubOptions.MaximumReceiveMessageSize = 30_000_000; // 256 * 1024; unlimited: null; hubOptions.KeepAliveInterval = TimeSpan.FromSeconds(FruitBankConstClient.SignalRKeepAliveIntervalSecond); hubOptions.ClientTimeoutInterval = TimeSpan.FromSeconds(FruitBankConstClient.SignarlRTimeoutIntervalSecond); //hubOptions.MaximumParallelInvocationsPerClient = 1; //default: 1; hubOptions.StatefulReconnectBufferSize = 30_000_000; //30MB; //default: 100,000 bytes; //hubOptions.HandshakeTimeout = TimeSpan.FromSeconds(15); //default timeout is 15 seconds }) .AddAcBinaryProtocol(opts => { opts.ProtocolMode = BinaryProtocolMode.AsyncSegment; opts.FlushPolicy = FlushPolicy.Coalesced; // Explicit AcLogger instance (name-based category, matches the previous setup). // If omitted, the options extension falls back to ILogger from DI. opts.Logger = new Logger(nameof(AyCodeBinaryHubProtocol)); // opts.FlushTimeout = TimeSpan.FromSeconds(10); // default — ~65 KB chunks transfer in ≤9s even on GPRS }); #if DEBUG using var tmpSp = services.BuildServiceProvider(); foreach (var p in tmpSp.GetServices()) Console.WriteLine($">>> HubProtocol: Name={p.Name} v{p.Version} Assembly={p.GetType().Assembly.GetName().Name}"); #endif } /// /// Configure the using of added middleware /// /// Builder for configuring an application's request pipeline public void Configure(IApplicationBuilder application) { var fruitBankHubEndPoint = $"/{FruitBankConstClient.DefaultHubName}"; application.UseWhen(context => context.Request.Path.StartsWithSegments(fruitBankHubEndPoint), app => { app.UseEndpoints(endpoints => { endpoints.MapHub(fruitBankHubEndPoint, options => { options.Transports = HttpTransportType.WebSockets;// | HttpTransportType.LongPolling; options.WebSockets.CloseTimeout = TimeSpan.FromSeconds(10); //default: 5 sec. //options.LongPolling.PollTimeout = new TimeSpan(0, 0, 90); //default: 90 sec. options.AllowStatefulReconnects = true; options.TransportMaxBufferSize = 30_000_000; // Increasing this value allows the server to receive larger messages. default: 65KB; unlimited: 0; options.ApplicationMaxBufferSize = 30_000_000; //Increasing this value allows the server to send larger messages. default: 65KB; unlimited: 0; options.TransportSendTimeout = TimeSpan.FromSeconds(60); //default: 10 sec. }); }); }); var loggrHubEndPoint = $"/{FruitBankConstClient.LoggerHubName}"; application.UseWhen(context => context.Request.Path.StartsWithSegments(loggrHubEndPoint), app => { app.UseEndpoints(endpoints => { endpoints.MapHub(loggrHubEndPoint, options => { options.Transports = HttpTransportType.WebSockets; options.AllowStatefulReconnects = false; }); }); }); } /// /// Gets order of this startup configuration implementation /// public int Order => 4000; }