Skocz do zawartości

Wybrakowane API i brak obsługi błędów

Polecane posty

Użytkownik forum

Aktualnie testuję integrację Państwa API z moim wewnętrznym systemem. Testuję m.in. możliwość automatycznego wystawiania faktur czy tworzenia klientów. 

Próba używania tego API to jest droga przez mękę.  Schematy danych pokazywane w Portalu Dewelopera niby zaznaczają które z pól są obowiązkowe, ale podczas robienia zapytania okazuje się że potrzebne jest wypełnienie jeszcze kilkunastu. Sama walidacja po stronie serwera czasami działa i podpowiada czego brakuje, ale co z tego skoro usługa zapisująca te dane do realnej bazy już się z tą walidacją nie zgadza i wyrzuca np taki ładny stack trace:

System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. (Parameter 'Kind')
   at InsERT.Skylab.PublicApi.Application.Domain.Documents.v1.CreateDocument.ClientDtoExtensions.ToDomainEntity(ClientDto client) in C:\Builds\test_1\_work\35\s\InsERT.Skylab.PublicApi.Application\Domain\Documents\v1\CreateDocument\CreateDocumentDto.cs:line 124
   at InsERT.Skylab.PublicApi.Application.Domain.Documents.v1.CreateDocument.CreateDocumentDtoExtensions.ToDomainDocument(CreateDocumentDto dto) in C:\Builds\test_1\_work\35\s\InsERT.Skylab.PublicApi.Application\Domain\Documents\v1\CreateDocument\CreateDocumentDto.cs:line 67
   at InsERT.Skylab.PublicApi.Application.Domain.Documents.v1.CreateDocument.CreateDocumentCommandHandler.BuildDocument(CreateDocumentCommand cmd) in C:\Builds\test_1\_work\35\s\InsERT.Skylab.PublicApi.Application\Domain\Documents\v1\CreateDocument\CreateDocumentCommandHandler.cs:line 124
   at LanguageExt.TaskExtensions.MapAsync[T,U](Task`1 self, Func`2 map)
   at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at MediatR.Pipeline.RequestPostProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at MediatR.Pipeline.RequestPreProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at InsERT.Skylab.PublicApi.Api.Documents.v1.DocumentsController.Post(CreateDocumentDto document) in C:\Builds\test_1\_work\35\s\InsERT.Skylab.PublicApi\Api\Documents\v1\DocumentsController.cs:line 129
   at lambda_method(Closure , Object )
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at AspNetCoreRateLimit.RateLimitMiddleware`1.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

W powyższym przykładzie już w zasadzie nie wiem o co chodzi, mogę zgadywać że metoda POST /documents oczekuje konkretnej wartości słownika dla parametru "kind":

{
  "buyer": {
    "address": {
        "city": "city",
        "country": "PL",
        "line1": "line1",
        "name": null,
        "zipCode": "00-000"
    },
    "kind": "Company",
    "name": "buyer",
    "sourceClientId": 12345,
    "tin": "123456789",
    "tinKind": "Nip"
  },
  "calculationMethod": "Net",
  "client": {
    "address": {
        "city": "city",
        "country": "PL",
        "line1": "line1",
        "name": null,
        "zipCode": "00-000"
    },
    "kind": "Company",
    "sourceClientId": 12345
  },
  "communityTransaction": "SK",
  "currency": "PLN",
  "deliveryDate": "2023-10-19T00:00:00",
  "dueDate": "2023-10-26T00:00:00",
  "issueDate": "2023-10-19T00:00:00",
  "issuedByVatPayer": true,
  "issuer": "x x",
  "items": [
    {
      "discountKind": "None",
      "grossPrice": 0,
      "netPrice": 10,
      "no": 1,
      "note": "string",
      "pkwiu": "string",
      "productName": "string",
      "quantity": 17,
      "unit": "szt",
      "vatRate": "23%"
    }
  ],
  "kind": "Proforma",
  "paymentMethod": "Cash",
  "payments": [],
  "recipient": "string",
  "splitPayment": "False"
}

...tylko że podobno jest to prawidłowa wartość. To jest jeden z naprawdę wielu przykładów gdzie trzeba zgadywać co autor miał na myśli. Jestem też prawie pewien, że jeszcze kilkanaście dni temu taki zestaw danych działał. 

 

No i dochodzą jeszcze kwestie kompletności tego API, można generować i wyświetlać tylko paragony, faktury zwykłe i proformy, nawet bez możliwości sprawdzenia z jakimi korektami powiązana jest faktura. API wykorzystywane wewnętrznie przez Subiekta123 też ma oznaczenie v1, ale ono ma już dostęp do kompletu danych. Wygląda to jakby ktoś kiedyś stworzył zewnętrzne API i projekt został zaniechany. 

 

Żeby zakończyć ten rant jakimś sensownym pytaniem: czy są plany ulepszania i poprawiania tego API, czy lepiej szukać u konkurencji? Księgowy zapewnia mnie że tutaj byłoby mu wygodniej ze względu na integrację Subiekta123 z jego oprogramowaniem, ale musiałbym mieć jakąkolwiek pewność sprawnego działania i wsparcia. 

Link to postu

Dzień dobry,

Przepraszam że musiał Pan czekać na odpowiedź. Wymagała ona konsultacji. Poprawki z pierwszego wątku planujemy dodać w wersji wiosennej Subiekta 123. Jeżeli chodzi o wsparcie obsługi kolejnych dokumentów przez API to będziemy je dodawać sukcesywnie. Na ten moment nie mogę podać konkretnego terminu.

Link to postu
×
×
  • Dodaj nową pozycję...