Wykonanie HTTP GET i POST np. za pomocą Indy

0

Potrzebuje wykonać

GET:

http://localhost:3333/api/public_things/:teste

http://localhost:3333/api/protected_things
POST:

http://localhost:3333/api/[email protected]&password=12345678

{
    "user": {
        "id": 35,
        "email": "[email protected]",
        "role": "BASE"
    },
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhYWJAb3AucGwiLCJyb2xlIjoiQkFTRSIsImlhdCI6MTY0NDQzMjYyMiwiZXhwIjoxNjQ0NDMyOTgyfQ.PGKVYi3xFO8Bws5dhO8_HXhBPUyKJAd_8atI31NNFrg"
}


http://localhost:3333/api/[email protected]&password=12345678

{
    "user": {
        "id": 27,
        "email": "[email protected]",
        "password": "$2b$10$R0/mxnhMbwWz8a4YtaKmEub1m6XAFTZ8AXkmdfLH3mx/O7GayaZyG",
        "role": "BASE"
    },
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhQG9wLnBsIiwicm9sZSI6IkJBU0UiLCJpYXQiOjE2NDQ0MzI1MTMsImV4cCI6MTY0NDQzMjc1M30.GgxNFhFQ5fvVErtu6I5Gem3F5bWS3RP-cLWU420Hlbc"
}

http://localhost:3333/api/[email protected]&password=1234

{
    "user": {
        "email": "[email protected]",
        "password": "$2b$10$.Rnew68cFs31uteU04tK2.zo0eRhqLsceAMaPuMCQNmnIpuLUASKS"
    },
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhQG9wLnBsIiwiaWF0IjoxNjQ0NDMyNzYyLCJleHAiOjE2NDQ0MzMxMjJ9.a__ulsgDS8GkJ_0PCvnW1tbEd6E5Sd9kxvJo63LiyHw"

chcę to zrobić przez komponent w Delphi, np Indy albo cokolwiek innego. Tak jak to wykonuję postmanem czyli to co powyżej odczytać jako string/json

0

no to weź i zrób - google ci zamknęli????
https://www.google.com/search?q=delphi+http+get+example

0

Google mi nie zamknęli - jak to znawca pisze,

sam sobie odpowiem :)


uses
  IdHTTP, IdGlobal, SysUtils, Classes;

const cToken = '*****************************************';

var
  HTTP: TIdHTTP;
  RequestBody: TStream;
  ResponseBody: string;
begin
  HTTP := TIdHTTP.Create;
  try
    try
      RequestBody := TStringStream.Create('{"English":42}', TEncoding.UTF8);
      try
        HTTP.Request.Accept := 'application/json';
        HTTP.Request.ContentType := 'application/json';
        ResponseBody := HTTP.Post('http://localhost:3333/api/[email protected]&password=1234', RequestBody);
        WriteLn(ResponseBody);
        WriteLn(HTTP.ResponseText);

        Writeln(' ');
        Writeln('******************************************');
        Writeln(' ');

        HTTP.Request.CustomHeaders.Add('Authorization: Bearer ' + cToken);
        ResponseBody := HTTP.Get('http://localhost:3333/api/[email protected]');
        WriteLn(ResponseBody);
        WriteLn(HTTP.ResponseText);


      finally
        RequestBody.Free;
      end;
    except
      on E: EIdHTTPProtocolException do
      begin
        WriteLn(E.Message);
        WriteLn(E.ErrorMessage);
      end;
      on E: Exception do
      begin
        WriteLn(E.Message);
      end;
    end;
  finally
    HTTP.Free;
  end;
  ReadLn;
  ReportMemoryLeaksOnShutdown := True;
end.



0
piars napisał(a):

Google mi nie zamknęli - jak to znawca pisze,

sam sobie odpowiem :)


uses
  IdHTTP, IdGlobal, SysUtils, Classes;

const cToken = '*****************************************';

var
  HTTP: TIdHTTP;
  RequestBody: TStream;
  ResponseBody: string;
begin
  HTTP := TIdHTTP.Create;
  try
    try
      RequestBody := TStringStream.Create('{"English":42}', TEncoding.UTF8);
      try
        HTTP.Request.Accept := 'application/json';
        HTTP.Request.ContentType := 'application/json';
        ResponseBody := HTTP.Post('http://localhost:3333/api/[email protected]&password=1234', RequestBody);
        WriteLn(ResponseBody);
        WriteLn(HTTP.ResponseText);

        Writeln(' ');
        Writeln('******************************************');
        Writeln(' ');

        HTTP.Request.CustomHeaders.Add('Authorization: Bearer ' + cToken);
        ResponseBody := HTTP.Get('http://localhost:3333/api/[email protected]');
        WriteLn(ResponseBody);
        WriteLn(HTTP.ResponseText);


      finally
        RequestBody.Free;
      end;
    except
      on E: EIdHTTPProtocolException do
      begin
        WriteLn(E.Message);
        WriteLn(E.ErrorMessage);
      end;
      on E: Exception do
      begin
        WriteLn(E.Message);
      end;
    end;
  finally
    HTTP.Free;
  end;
  ReadLn;
  ReportMemoryLeaksOnShutdown := True;
end.



Ma ktoś może działający kod inicjalizacji sesji ksef w Delphi z wykorzystaniem Indy?

1

const
  challengeJSON = //
    '{' + //
    '  "contextIdentifier": {' + #13 + //
    '    "type": "onip",' + #13 + //
    '    "identifier": "%s"' + #13 + //
    '}}'

 challengeResource = 'online/Session/AuthorisationChallenge';
 initTokenResource = 'online/Session/InitToken';
 

 initTokenXML_1 = //
    '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + #13 + //
    '<ns3:InitSessionTokenRequest' + #13 + //
    '	xmlns="http://ksef.mf.gov.pl/schema/gtw/svc/online/types/2021/10/01/0001"' + #13 + //
    '	xmlns:ns2="http://ksef.mf.gov.pl/schema/gtw/svc/types/2021/10/01/0001"' + #13 + //
    '	xmlns:ns3="http://ksef.mf.gov.pl/schema/gtw/svc/online/auth/request/2021/10/01/0001">' + #13 + //
    '	<ns3:Context>' + #13 + //
    '		<Challenge>%s</Challenge>' + #13 + //
    '		<Identifier xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:SubjectIdentifierByCompanyType">' + #13 + //
    '			<ns2:Identifier>%s</ns2:Identifier>' + #13 + //
    '		</Identifier>' + #13 + //
    '		<DocumentType>' + #13 + //
    '			<ns2:Service>KSeF</ns2:Service>' + #13 + // '
    '			<ns2:FormCode>' + #13 + //
    '		     <ns2:SystemCode>FA (1)</ns2:SystemCode>' + #13 + //
    '			   <ns2:SchemaVersion>1-0E</ns2:SchemaVersion>' + #13 + //
    '			   <ns2:TargetNamespace>http://crd.gov.pl/wzor/2021/11/29/11089/</ns2:TargetNamespace>' + #13 + //
    '			   <ns2:Value>FA</ns2:Value>' + #13 + //
    '		  </ns2:FormCode>' + #13 + //
    '	 </DocumentType>' + #13 + //
    '	 <Token>%s</Token>' + #13 + //
    ' </ns3:Context>' + #13 + //
    '</ns3:InitSessionTokenRequest>';

function myStrToUnixDateTime(aString: string): int64;
var
  yy, mm, dd, hh, min, ss, ms: word;
begin
  result:=0;
  try
    yy := strtoint(leftstr(aString, 4));
    mm := strtoint(midstr(aString, 6, 2));
    dd := strtoint(midstr(aString, 9, 2));
    hh := strtoint(midstr(aString, 12, 2));
    min := strtoint(midstr(aString, 15, 2));
    ss := strtoint(midstr(aString, 18, 2));
    ms := strtoint(midstr(aString, 21, 3));
    result := DateTimeToUnix( encodedatetime(yy, mm, dd, hh, min, ss, ms)) * 1000;
  except
    result := -1;
  end;
end;


function TKsef.authorizationChallenge: integer;
var
  Response: string;
begin
  RRequest.Accept := 'application/json';
  RRequest.Resource := challengeResource;
  RRequest.body.Add(format(challengeJSON, [self.nip]), trestcontenttype.ctAPPLICATION_JSON);
  RRequest.Method := rmpost;
  RRequest.Execute;
  result := RResponse.StatusCode;
  if result = 201 then
  begin
    Response := RResponse.Content;
    self.chalengeID := parseJson(Response, 'challenge');
    self.timestamp := parseJson(Response, 'timestamp');
  end;
end;

function TKsef.TokenTimeStamp: ansistring;
begin
  // token -    wygenerowany na stronie https://ksef-test.mf.gov.pl/web/home
  result := self.token + '|' + ansistring(inttostr(myStrToUnixDateTime(self.timestamp)));
end;


function TKsef.initToken: integer;
var
  bufIn, bufOut: Tbytes;
  tmpStr: ansistring;
  Response: string;
begin

  // szyfruję token
  tmpStr := self.TokenTimeStamp;
  setlength(bufIn, length(tmpStr));
  copymemory(@bufIn[0], @tmpStr[1], length(tmpStr));
  encryptRSA(self.FpublicKeyPemFilename, bufIn, bufOut);
  self.tokenEncryptedRSA := tnetencoding.Base64.EncodeBytesToString(bufOut);
  self.tokenEncryptedRSA := replacestr(self.tokenEncryptedRSA, #13, '');
  self.tokenEncryptedRSA := replacestr(self.tokenEncryptedRSA, #10, '');

  xmlBody := ansistring(format(initTokenXML_1, //
    [self.chalengeID, self.nip, self.tokenEncryptedRSA]));

  RRequest.Accept := 'application/json';
  RRequest.AddBody(string(xmlBody), trestcontenttype.ctAPPLICATION_OCTET_STREAM);
  RRequest.Resource := initTokenResource;
  RRequest.Method := rmpost;
  RRequest.Execute;
  result := RResponse.StatusCode;
  if result = 201 then
  begin
    Response := RResponse.Content;
    self.sessionToken := parseJson(Response, 'sessionToken.token');
    self.referenceNumber := parseJson(Response, 'referenceNumber');
  end;
end;
0

Dzięki za szybką odpowiedź, ale RRequest to chyba RestRequest z biblioteki REST.
A ja potrzebuję kodu inicjalizacji sesji ksef z wykorzystaniem Indy (Indy10 w D6).

0

Cześć,

Wykonuję AuthorisationChallenge i dalej jak poniżej:

Memo1.Lines.Clear;
Memo1.Lines.Text := xmlBody;
Memo1.Lines.SaveToFile('initToken.xml');
if chTylkoXML.Checked then exit;

RRequest.Accept := 'application/json';
RRequest.AcceptCharset := 'utf-8';
RRequest.Body.ClearBody;
RRequest.AddBody(xmlBody, trestcontenttype.ctAPPLICATION_OCTET_STREAM);

RRequest.Resource := initTokenResource;
RRequest.Method := rmpost;
RRequest.Execute;
StatusCode := RResponse.StatusCode;

Niestety, uzyskuję odpowiedź:

{"exception":{"serviceCtx":"srvTEMFC","serviceCode":"20230428-EX-14803F60A9-84FBE63171-34","serviceName":"online.session.session.token.init","timestamp":"2023-04-28T06:57:25.027Z","referenceNumber":"20230428-SE-F2BAFFD2AE-1A25C0EB63-06","exceptionDetailList":[{"exceptionCode":21401,"exceptionDescription":"Dokument nie jest zgodny ze schemą (xsd)."}]}}

Dla celów testowych xmlBody zapisuję do pliku initToken.xml i jak go wysyłam za pomocą Postman to zwraca token sesji, więc problem chyba tkwi w samej wysyłce z Delphi.

Jakieś pomysły?
Dziękuję.

0

Podany kod wygląda na prawidłowy.
Co masz w w InitTokenResource ?

0
grzegorz_so napisał(a):

Podany kod wygląda na prawidłowy.
Co masz w w InitTokenResource ?

initTokenResource = 'online/Session/InitToken';
Nie rozumiem, dlaczego zapisane body do pliku, po wysłaniu postamanem działa.

0

Podejrzewam, że chodzi o kodowanie, spróbuj wymusić Utf-8 na xmlbody

RRequest.AddBody(AnsiToUtf8(xmlBody), trestcontenttype.ctAPPLICATION_OCTET_STREAM);
0

Ja sądzę że TRESTContentType.ctAPPLICATION_OCTET_STREAM nie jest właściwym typem i raczej powinno być coś z XML ale nie wiem co musisz popróbować.
https://docwiki.embarcadero.com/Libraries/Sydney/en/REST.Types.TRESTContentType

0

@twister.akozlowicz:
Pokaż więcej kodu . Obiekt RRequest wyklikałeś w IDE czy tworzysz w kodzie aplikacji ?

0
var
    tokenUser: string;
    Response, ChallengeID, TimeStamp, TokenSesji, ReferenceNumber, xmlBody: string;
    JsonValue: TJSONValue;
    StatusCode:integer;

function myStrToUnixDateTime(sData: string): string;
var Data: TDateTime;
    ms : int64;
    r,m,d,g,n,s,z: integer;
begin
  Result := '';
  try
  r := StrToInt(Copy(sData, 1,4));
  m := StrToInt(Copy(sData, 6,2));
  d := StrToInt(Copy(sData, 9,2));
  g := StrToInt(Copy(sData, 12,2));
  n := StrToInt(Copy(sData, 15,2));
  s := StrToInt(Copy(sData, 18,2));
  z := StrToInt(Copy(sData, 21,3));

  Data := EncodeDateTime(r,m,d,g,n,s,z);
  ms := Round((Data - UnixDateDelta) * SecsPerDay*1000);
  Result := IntToStr(ms);
  except
  end;
end;

procedure TForm1.AuthorisationChallenge;
begin
  StatusCode := 0;
  RRequest.Accept := 'application/json';
  RRequest.Resource := challengeResource;
  RRequest.body.Add(format(challengeJSON, [NIPFirmy]), trestcontenttype.ctAPPLICATION_JSON);
  RRequest.Method := rmpost;
  RRequest.Execute;
  StatusCode := RResponse.StatusCode;
  Memo1.Lines.Clear;
  Memo1.Lines.Add(RResponse.Content);
  if StatusCode = 201 then
  begin
    JSONValue := TJSONObject.ParseJSONValue(RResponse.Content);
    JSONValue.TryGetValue('challenge', ChallengeID);
    JSONValue.TryGetValue('timestamp', TimeStamp);
  end;
end;

procedure TForm1.InitToken;
begin
  StatusCode := 0;

  Memo1.Lines.Clear;
  Memo1.Text := tokenUser+'|'+myStrToUnixDateTime(timestamp);
  Memo1.Lines.SaveToFile('tekst_in.txt');

  DeleteFile('base64_out.txt');
  winexec('encryptBase64.bat',sw_Normal);//szyfruję za pomocą OpenSSL.exe

  if chTylkoToken.Checked then Exit;

  sleep(1000);
  if FileExists('base64_out.txt') then begin
    Memo1.Lines.Clear;
    Memo1.Lines.LoadFromFile('base64_out.txt');
    tokenSesji := Memo1.Text;
    tokenSesji := StringReplace(tokenSesji, #13,'',[rfReplaceAll]);
    tokenSesji := StringReplace(tokenSesji, #10,'',[rfReplaceAll]);
    xmlBody := format(initTokenXML_1, [ChallengeID, NIPFirmy, tokenSesji]);

    Memo1.Lines.Clear;
    Memo1.Lines.Text := xmlBody;
    Memo1.Lines.SaveToFile('initToken.xml');
    if chTylkoXML.Checked then exit;
    sleep(1000);

    RRequest.Accept := 'application/json';
    RRequest.AcceptCharset := 'utf-8';
    RRequest.Body.ClearBody;
    RRequest.AddBody(xmlBody, trestcontenttype.ctAPPLICATION_OCTET_STREAM);

    RRequest.Resource := 'online/Session/InitToken';
    RRequest.Method := rmPost;
    RRequest.Execute;
    StatusCode := RResponse.StatusCode;
    Memo1.Lines.Clear;
    Memo1.Lines.Add(RResponse.Content);
    if StatusCode = 201 then
    begin
     JSONValue := TJSONObject.ParseJSONValue(RResponse.Content);
     JSONValue.TryGetValue('sessionToken.token', tokenSesji);
     JSONValue.TryGetValue('referenceNumber', referenceNumber);
   end;
 end;

end;

RRequest, RResponse i RClient położyłem na formularzu i powiązałem , nie zmieniałem żadnych ustawień oprócz wpisania w BaseUrl: https://ksef-test.mf.gov.pl/api.

  1. Wywołuję AuthorisationChallenge i potem InitToken i zwraca błąd niezgodności z xsd
  2. Wywołuję AuthorisationChallenge i potemInitToken i przerywam: tworzę initToken.xml wklejam do Postman, wykonuję i zwraca StatusCode 201

Próbowałem z różnymi ustawieniami string, ansistring, AnsiToUtf8, ale nic to nie daje.
Przy innym typie niż ctAPPLICATION_OCTET_STREAM np. ctAPPLICATION_XML zwraca błąd złej zawartości.

Może coś we właściwościach RRequest, RResponse, RClient trzeba ustawić?

0

ja stworzyłem sobie własną klasę

type
  TmREST = class
  public
    RClient: TRESTClient;
    RRequest: TRESTRequest;
    RResponse: TRESTResponse;
    procedure clear;
    constructor Create;
    destructor Destroy; 
  end;


procedure TmREST.clear;
begin
  self.RRequest.Params.clear;
  self.RRequest.body.ClearBody;
end;

constructor TmREST.Create;
begin
  RClient := TRESTClient.Create(nil);
  RRequest := TRESTRequest.Create(nil);
  RResponse := TRESTResponse.Create(nil);
  RRequest.Client := RClient;
  RRequest.response := RResponse;
  RClient.baseUrl := baseUrl[svrMode];
end;

destructor TmREST.Destroy;
begin
  RResponse.Free;
  RRequest.Free;
  RClient.Free;
end;

sprawdź co masz pod RClient.baseUrl

0

Usunąłem kontrolki, zrobiłem tworzenie w kodzie i pomogło. Dzięki

0
twister.akozlowicz napisał(a):
var
    tokenUser: string;
    Response, ChallengeID, TimeStamp, TokenSesji, ReferenceNumber, xmlBody: string;
    JsonValue: TJSONValue;
    StatusCode:integer;

function myStrToUnixDateTime(sData: string): string;
var Data: TDateTime;
    ms : int64;
    r,m,d,g,n,s,z: integer;
begin
  Result := '';
  try
  r := StrToInt(Copy(sData, 1,4));
  m := StrToInt(Copy(sData, 6,2));
  d := StrToInt(Copy(sData, 9,2));
  g := StrToInt(Copy(sData, 12,2));
  n := StrToInt(Copy(sData, 15,2));
  s := StrToInt(Copy(sData, 18,2));
  z := StrToInt(Copy(sData, 21,3));

  Data := EncodeDateTime(r,m,d,g,n,s,z);
  ms := Round((Data - UnixDateDelta) * SecsPerDay*1000);
  Result := IntToStr(ms);
  except
  end;
end;

procedure TForm1.AuthorisationChallenge;
begin
  StatusCode := 0;
  RRequest.Accept := 'application/json';
  RRequest.Resource := challengeResource;
  RRequest.body.Add(format(challengeJSON, [NIPFirmy]), trestcontenttype.ctAPPLICATION_JSON);
  RRequest.Method := rmpost;
  RRequest.Execute;
  StatusCode := RResponse.StatusCode;
  Memo1.Lines.Clear;
  Memo1.Lines.Add(RResponse.Content);
  if StatusCode = 201 then
  begin
    JSONValue := TJSONObject.ParseJSONValue(RResponse.Content);
    JSONValue.TryGetValue('challenge', ChallengeID);
    JSONValue.TryGetValue('timestamp', TimeStamp);
  end;
end;

procedure TForm1.InitToken;
begin
  StatusCode := 0;

  Memo1.Lines.Clear;
  Memo1.Text := tokenUser+'|'+myStrToUnixDateTime(timestamp);
  Memo1.Lines.SaveToFile('tekst_in.txt');

  DeleteFile('base64_out.txt');
  winexec('encryptBase64.bat',sw_Normal);//szyfruję za pomocą OpenSSL.exe

  if chTylkoToken.Checked then Exit;

  sleep(1000);
  if FileExists('base64_out.txt') then begin
    Memo1.Lines.Clear;
    Memo1.Lines.LoadFromFile('base64_out.txt');
    tokenSesji := Memo1.Text;
    tokenSesji := StringReplace(tokenSesji, #13,'',[rfReplaceAll]);
    tokenSesji := StringReplace(tokenSesji, #10,'',[rfReplaceAll]);
    xmlBody := format(initTokenXML_1, [ChallengeID, NIPFirmy, tokenSesji]);

    Memo1.Lines.Clear;
    Memo1.Lines.Text := xmlBody;
    Memo1.Lines.SaveToFile('initToken.xml');
    if chTylkoXML.Checked then exit;
    sleep(1000);

    RRequest.Accept := 'application/json';
    RRequest.AcceptCharset := 'utf-8';
    RRequest.Body.ClearBody;
    RRequest.AddBody(xmlBody, trestcontenttype.ctAPPLICATION_OCTET_STREAM);

    RRequest.Resource := 'online/Session/InitToken';
    RRequest.Method := rmPost;
    RRequest.Execute;
    StatusCode := RResponse.StatusCode;
    Memo1.Lines.Clear;
    Memo1.Lines.Add(RResponse.Content);
    if StatusCode = 201 then
    begin
     JSONValue := TJSONObject.ParseJSONValue(RResponse.Content);
     JSONValue.TryGetValue('sessionToken.token', tokenSesji);
     JSONValue.TryGetValue('referenceNumber', referenceNumber);
   end;
 end;

end;

RRequest, RResponse i RClient położyłem na formularzu i powiązałem , nie zmieniałem żadnych ustawień oprócz wpisania w BaseUrl: https://ksef-test.mf.gov.pl/api.

  1. Wywołuję AuthorisationChallenge i potem InitToken i zwraca błąd niezgodności z xsd
  2. Wywołuję AuthorisationChallenge i potemInitToken i przerywam: tworzę initToken.xml wklejam do Postman, wykonuję i zwraca StatusCode 201

Próbowałem z różnymi ustawieniami string, ansistring, AnsiToUtf8, ale nic to nie daje.
Przy innym typie niż ctAPPLICATION_OCTET_STREAM np. ctAPPLICATION_XML zwraca błąd złej zawartości.

Może coś we właściwościach RRequest, RResponse, RClient trzeba ustawić?

Byłbym bardzo wdzięczny za treść pliku 'encryptBase64.bat' z powyższego kodu. Z jakimi parametrami wywołać openssl aby dostać prawidłowo zaszyfrowaną wartość tokenUser+'|'+myStrToUnixDateTime(timestamp)

1 użytkowników online, w tym zalogowanych: 0, gości: 1