RTC Forums
April 30, 2024, 05:53:33 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Login Register  
Pages: [1] 2
  Print  
Author Topic: sending a XML-file back with a TRctHTTPserver  (Read 16203 times)
Henk vd Boogaard
RTC Expired
*
Posts: 24


« on: May 22, 2013, 07:18:16 PM »

Hello,
Using the examples 1 and 2 I managed to make a webserver that receives a XML-file.
I can read the file and make an answer also in a  XML-file.
I madk the XML-file in a TXMLdocument.
How can I send this XML-file (in the TXMLDocument) as an answer?

Another question:
How can I test the webserver in FireFox or in MS-explorer?
Besides the URL I have also include the XML-file that must be processed.

Thanks in advance,
Henk van den Boogaard
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #1 on: May 22, 2013, 07:34:06 PM »

Sender:TRtcConnection object (sent to every RTC event) has Write and WriteEx methods, which are used for sending the content body (XML document). You will need your XML content in a String (Write) or a dynamic byte array (WriteEx) in order to send it out, so check if the class you are using (TXMLDocument?) has a method which returns your XML document in a String, or an array of bytes. One thing you obviously can't do, is send an object out.

PS. You could also write the XML document into a file and then send the file out by using the Read_File function (rtcInfo.pas unit), but ... if you are creating temporary files for sending, make sure the file does not already exist (you don't want to write to the same file over and over again if your Server has to work with more than one Client (especially if it is running with MultiThreaded=True).

Best Regards,
Danijel Tkalcec
Logged
Henk vd Boogaard
RTC Expired
*
Posts: 24


« Reply #2 on: September 02, 2018, 12:50:37 PM »

Hello,
I have an old program (windows service) that listens.
I if get an notify message that a pay has made and that the information can be fetched.
It then puts the information in a NexusDB database.

However the old program does not function anymore due to old SSL functions.

I will try to rewrite the program with the use of RTC and Streamsec2 and if possible no XMLdocument.

But I have not the knowledge to finsch it.

I hope someone can help me.
At the end is the old program with Indy.

This is so far I have got:
----------------------------------------------------
unit Work;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, rtcDataSrv, rtcSystem, rtcInfo, rtcConn, rtcHttpSrv, Vcl.StdCtrls, rtcDataCli, rtcHttpCli;

type
  TForm10 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Label1: TLabel;
    Ontvangen: TLabel;
    Edit1: TEdit;
    Button2: TButton;
    Server: TRtcHttpServer;
    RtcDataProvider1: TRtcDataProvider;
    RtcHttpClient1: TRtcHttpClient;
    RtcDataRequest1: TRtcDataRequest;
    procedure Button1Click(Sender: TObject);
    procedure RtcDataProvider1CheckRequest(Sender: TRtcConnection);
    procedure RtcDataProvider1DataReceived(Sender: TRtcConnection);
    procedure Button2Click(Sender: TObject);
    procedure RtcDataRequest1BeginRequest(Sender: TRtcConnection);
    procedure RtcDataRequest1DataReceived(Sender: TRtcConnection);
  private
    { Private declarations }
    TransactionID_str: rtcString;
    SiteURL, SitePort: rtcString;
    DoDebug: boolean;
  public
    { Public declarations }
  end;

var
  Form10: TForm10;

implementation

{$R *.dfm}

procedure TForm10.Button1Click(Sender: TObject);
begin
  Server.ServerPort := Edit1.Text;
  Server.Listen();
  Button2.Enabled := true;
  Button1.Enabled := false;
  DoDebug := true;
end;

procedure TForm10.Button2Click(Sender: TObject);
begin
  Server.StopListen;
  Button2.Enabled := false;
  Button1.Enabled := true;;
end;

procedure TForm10.RtcDataProvider1CheckRequest(Sender: TRtcConnection);
begin
  with Sender as TRtcDataServer do
    Memo1.Lines.Add(Request.FileName);
  with Sender as TRtcDataServer do
    if UpperCase(Request.FileName) = '/MSP' then
      Accept;

end;

procedure TForm10.RtcDataProvider1DataReceived(Sender: TRtcConnection);
begin
  with Sender as TRtcDataServer do
  begin
    if Request.Complete then
    begin
      if DoDebug then
        Memo1.Lines.Clear;
      TransactionID_str := Request.Query['transactionid'];
      if DoDebug then
        Memo1.Lines.Add(TransactionID_str);
      // now get the information
      RtcHttpClient1.ServerAddr := SiteURL;
      RtcHttpClient1.ServerPort := SitePort;
      with RtcDataRequest1 do
      begin
        Request.Method := 'GET';
        Request.FileName := '/' + TransactionID_str;
        // HERE THE XML?? HOW???
        //WITH REQUEST.QUERY??
        //WHAT BY 'Status ua' ??
        Post; // Post the request
      end;

    end;
  end;
end;

procedure TForm10.RtcDataRequest1BeginRequest(Sender: TRtcConnection);
begin
  with TRtcDataClient(Sender) do
  begin // make sure our request starts with "/"
    if Copy(Request.FileName, 1, 1) <> '/' then
      Request.FileName := '/' + Request.FileName;
    // define the "HOST" header
    if Request.Host = '' then
      Request.Host := ServerAddr;
    if DoDebug then
      Memo1.Text := 'Requesting "' + Request.FileName + '" from "' + ServerAddr + '".';
    // send request header out
    WriteHeader;
  end;

end;

procedure TForm10.RtcDataRequest1DataReceived(Sender: TRtcConnection);
begin
  with TRtcDataClient(Sender) do
  begin
    if Response.Started then
    begin { Executed only once per request,
        when we start receiving the response. }
      // Clear the info we wrote here in our "OnBeginRequest"
      // HERE COMES THE XML BACK?? HOW TO HANDLE THIS?
      //ALSO WITH REQUEST.QUERY??
      if DoDebug then
      begin
        Memo1.Clear;
        Memo1.Lines.Add('Status code: ' + IntToStr(Response.StatusCode));
        Memo1.Lines.Add('Status text:' + Response.StatusText);
        Memo1.Lines.Add('ALL Headers:');
        Memo1.Lines.Add(Response.HeaderText);
        Memo1.Lines.Add('Content Length:');
        Memo1.Lines.Add(IntToStr(Response.ContentLength));
        Memo1.Lines.Add('Content body:');
        Memo1.Lines.Add('START >');
      end; { Could be executed more than once,  depending on the content size }
      // add content received now.
      Memo1.Text := Memo1.Text + Read;
      if Response.Done then
      begin { Executed only once per request, when we have just received it all. }
        Memo1.Lines.Add('< END');
      end;
    end; //DoDebug
  end;
end;

end.
-------------------------------------------------

======================the old program===========================

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
  IdBaseComponent, IdComponent, IdCustomTCPServer, IdCustomHTTPServer,
  IdHTTPServer,
  Variants, Forms, xmldom, XMLIntf, msxmldom, XMLDoc, IdAntiFreezeBase, IdAntiFreeze,
  IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack, IdSSL, IdSSLOpenSSL,
  IdTCPConnection, IdTCPClient, IdHTTP, IdServerIOHandler,
  IniFiles, IdContext, IdHeaderList, ActiveX, DB, nxdb, nxsdServerEngine,
  nxreRemoteServerEngine, nxllComponent, nxllTransport, nxptBasePooledTransport,
  nxtwWinsockTransport, Xml.omnixmldom;

type
  TService1 = class(TService)
    IdHTTPServer1: TIdHTTPServer;
    IdServerIOHandlerSSLOpenSSL1: TIdServerIOHandlerSSLOpenSSL;
    IdHTTP1: TIdHTTP;
    IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
    IdAntiFreeze1: TIdAntiFreeze;
    XMLDoc1: TXMLDocument;
    XMLDoc2: TXMLDocument;
    nxWinsockTransport1: TnxWinsockTransport;
    nxRemoteServerEngine1: TnxRemoteServerEngine;
    nxSession1: TnxSession;
    nxDatabase1: TnxDatabase;
    DS_algpar: TDataSource;
    nxT_algpar: TnxTable;
    DS_IDealRecords: TDataSource;
    nxT_IDealRecords: TnxTable;

    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
    procedure IdHTTPServer1CreatePostStream(AContext: TIdContext; AHeaders: TIdHeaderList; var VPostStream: TStream);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
  private
    { Private declarations }
  protected
    function DoStop: Boolean; override;
    function DoPause: Boolean; override;
    function DoContinue: Boolean; override;
    procedure DoInterrogate; override;
    procedure DoShutdown; override;
  public
    constructor Create(AOwner: TComponent); override;
    function GetServiceController: TServiceController; override;
    { Public declarations }
  end;

var
  Service1: TService1;
  AppsPad: string;
  XML_Dir: string;
  LogAanUit: string;

implementation

uses
  CodeSiteLogging;
{$R *.DFM}

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  Service1.Controller(CtrlCode);
end;

constructor TService1.Create(AOwner: TComponent);
var
  Ini: TInifile;
  DB_naam: string;
  DB_Alias: string;
  DB_Poort: integer;
  ServerPoort: Word;
begin
  inherited;
  CoInitializeEx(nil, 2);
  CodeSite.Clear;
  DisplayName := 'AVN Service';

  // setup:
  AppsPad := ExtractFilePath(Application.ExeName); // BS geen JclSysInfo meer nodig...
  CodeSite.Send('AppsPad = ' + AppsPad);
  Ini := TInifile.Create(AppsPad + 'AVN_SERVICE_DB_Settings.ini');
  try
    DB_naam := Ini.ReadString('ServerInfo', 'Server', 'NEXUSDB');
    DB_Poort := Ini.ReadInteger('Transport', 'Poort', 16000); // 16000 voor gewoon 17000 voor secure
    DB_Alias := Ini.ReadString('Alias', 'Aliasnaam', 'AVN');
    ServerPoort := Ini.ReadInteger('Com', 'ServerPoort', 22333);
    XML_Dir := Ini.ReadString('FILES', 'XML_Dir', 'C:\TEMP\');
    LogAanUit := Ini.ReadString('LOG', 'LogAanUit', 'AAN');
    CodeSite.Send('1a');
  finally
    Ini.Free;
    CodeSite.Send('1b');
    CodeSite.Send('DB ' + DB_naam);
    CodeSite.Send('Poort ' + IntToStr(DB_Poort));
    CodeSite.Send('Alias ' + DB_Alias);
  end;
  Application.ProcessMessages;

  // setup de database connectie:
  // INDIEN ALS SERVICE DAN DE INI-FILE IN DE MAP WINDOWS/SYSTEM32 ZETTEN
  nxWinsockTransport1.Active := false;
  CodeSite.Send('1c');
  nxWinsockTransport1.ServerName := DB_naam;
  CodeSite.Send('1d');
  nxDatabase1.AliasPath := '';
  CodeSite.Send('1e');
  nxDatabase1.AliasName := DB_Alias;
  CodeSite.Send('1f');
  nxWinsockTransport1.Port := DB_Poort;
  CodeSite.Send('1g');
  nxWinsockTransport1.Active := true;
  CodeSite.Send('1h');
  Application.ProcessMessages;
  if nxWinsockTransport1.Connected then
  begin
    CodeSite.Send('Database geopend');
    nxRemoteServerEngine1.Active := true;
    nxSession1.Active := true;
    nxDatabase1.Active := true;
    CodeSite.Send('Bestanden geopend');
    // einde setup
    nxT_algpar.Open;
    nxT_IDealRecords.Open;
    Application.ProcessMessages;
    IdServerIOHandlerSSLOpenSSL1.SSLOptions.CertFile := nxT_algpar.FieldByName('IDeal_SSL_Cert_file').AsString;
    // '83.161.204.179.cer';
    IdServerIOHandlerSSLOpenSSL1.SSLOptions.KeyFile := nxT_algpar.FieldByName('IDeal_SSL_Cert_key').AsString;
    // '83.161.204.179.key';
    IdServerIOHandlerSSLOpenSSL1.SSLOptions.Method := sslvTLSv1_2;
    IdServerIOHandlerSSLOpenSSL1.SSLOptions.Mode := sslmBoth;
    IdServerIOHandlerSSLOpenSSL1.SSLOptions.VerifyMode := [];
    IdServerIOHandlerSSLOpenSSL1.SSLOptions.VerifyDepth := 0;
    IdSSLIOHandlerSocketOpenSSL1.SSLOptions.CertFile := nxT_algpar.FieldByName('IDeal_SSL_Cert_file').AsString;
    // '83.161.204.179.cer';
    IdSSLIOHandlerSocketOpenSSL1.SSLOptions.KeyFile := nxT_algpar.FieldByName('IDeal_SSL_Cert_key').AsString;
    // '83.161.204.179.key';
    IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1_2;
    IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode := sslmBoth;
    IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyMode := [];
    IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyDepth := 0;
    Application.ProcessMessages;
  end
  else
    CodeSite.Send('fout geen connectie');

  IdHTTPServer1.DefaultPort := ServerPoort;
  CodeSite.Send(IntToStr(ServerPoort));
  // IdHTTPServer1.Active := true; -- BS: Dat doen we pas in de ServiceStart zelf!
  OnStart := ServiceStart;
end;

function TService1.DoContinue: Boolean;
begin
  CodeSite.Send('Service Continue');
  try
    IdHTTPServer1.Active := true;
  except
    on E: Exception do
      CodeSite.SendException(E);
  end;
  Result := inherited;
end;

procedure TService1.DoInterrogate;
begin
  inherited;
end;

function TService1.DoPause: Boolean;
begin
  CodeSite.Send('Service Pause');
  try
    IdHTTPServer1.Active := false;
  except
    on E: Exception do
      CodeSite.SendException(E);
  end;
  Result := inherited;
end;

procedure TService1.DoShutdown;
begin
  CodeSite.Send('Service Shutdown');
  try
    IdHTTPServer1.Active := false;
  except
    on E: Exception do
      CodeSite.SendException(E);
  end;
  inherited;
end;

function TService1.DoStop: Boolean;
begin
  CodeSite.Send('Service Stop');
  try
    IdHTTPServer1.Active := false;
  except
    on E: Exception do
      CodeSite.SendException(E);
  end;
  Result := inherited;
end;

function TService1.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;

procedure TService1.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
  AResponseInfo: TIdHTTPResponseInfo);
var
  HtmlResult: String;
  Request: String;
  IDealRecNr: integer;
  Exportfilenaam: string;
  iChild, iNodeEwallet, iNodeStatus, iNode_Merchant, iNodeTransaction: IXMLNode;
  Resulttekst, Statustekst: string;
  Strm: TStringStream;

begin
  CodeSite.EnterMethod('command get');
  CoInitialize(nil);
  Request := Uppercase(ARequestInfo.Document);
  HtmlResult := ARequestInfo.Params.Values['transactionid'];
  if HtmlResult <> '' then
  begin
    try
      CodeSite.Send('IDealRecNr = ' + HtmlResult);
      CodeSite.Send('record ontvangen');
      IDealRecNr := StrToInt(HtmlResult);
      // nu in database Huurovereenkomst controleren - indien OK dan VerstuurHTML:
      // maak XML-file:

      { if not DirectoryExists(XML_Dir) then
        CreateDir(XML_Dir);
        Exportfilenaam := XML_Dir + 'IDeal_' + IntToStr(IDealRecNr) + '.XML';
        dit alleen voor testen anders de volgende regel: }

      Exportfilenaam := 'IDeal_' + IntToStr(IDealRecNr) + '.XML';
      CodeSite.Send('Exportfilename = ' + Exportfilenaam);
      XMLDoc1.Active := false;
      XMLDoc1.XML.Text := '';
      XMLDoc1.Active := true;
      XMLDoc1.Encoding := 'UTF-8';
      XMLDoc1.AddChild('Pricat', 'http://www.ean.nl');
      XMLDoc1.DocumentElement := XMLDoc1.CreateNode('status');
      XMLDoc1.DocumentElement.Attributes['ua'] := 'Mozilla/3.0 (compatible; Indy Library)';

      // merchant
      iNode_Merchant := XMLDoc1.DocumentElement.AddChild('merchant');
      iChild := iNode_Merchant.AddChild('account');
      iChild.Text := nxT_algpar.FieldByName('IDeal_account').AsString;
      iChild := iNode_Merchant.AddChild('site_id');
      iChild.Text := nxT_algpar.FieldByName('IDeal_site_id').AsString;
      iChild := iNode_Merchant.AddChild('site_secure_code');
      iChild.Text := nxT_algpar.FieldByName('IDeal_site_secure_id').AsString;

      // transaction
      iNodeTransaction := XMLDoc1.DocumentElement.AddChild('transaction');
      iChild := iNodeTransaction.AddChild('id');
      iChild.Text := IntToStr(IDealRecNr);
      // bestand maken:
      XMLDoc1.SaveToFile(Exportfilenaam);

      CodeSite.Send('XMLDoc1 saved to file');

      // versturen:
      Strm := TStringStream.Create;
      try
        // alleen voor debug anders regel hieronder Strm.LoadFromFile(Exportfilenaam);
        XMLDoc1.SaveToStream(Strm);
        IdHTTP1.Request.ContentType := 'text/xml';
        XMLDoc2.LoadFromXML(IdHTTP1.Post(nxT_algpar.FieldByName('IDeal_Site_URL').AsString, Strm));
        Resulttekst := XMLDoc2.DocumentElement.Attributes['result'];
        iNodeEwallet := XMLDoc2.DocumentElement.ChildNodes.FindNode('ewallet');
        iNodeStatus := iNodeEwallet.ChildNodes.FindNode('status');
        if Assigned(iNodeStatus) then
          Statustekst := iNodeStatus.Text;
        CodeSite.Send('Status = ' + Statustekst);
        // database bijwerken:
        if nxT_IDealRecords.FindKey([IDealRecNr]) then   //hier volgend in v.1.1.0 gewijzigd omdat de status niet juist werd vertaald:
        begin
          if Uppercase(Resulttekst) = 'OK' then
          begin
            nxT_IDealRecords.Edit;
            nxT_IDealRecords.FieldByName('StatusOntvangen').AsBoolean := true;
            nxT_IDealRecords.FieldByName('Status').AsString := Statustekst;
            if Uppercase(Statustekst) = 'COMPLETED' then
              nxT_IDealRecords.FieldByName('BetalingOK').AsBoolean := true;
            nxT_IDealRecords.Post;
          end
          else
          begin
            nxT_IDealRecords.Edit;
            nxT_IDealRecords.FieldByName('StatusOntvangen').AsBoolean := false;
            nxT_IDealRecords.FieldByName('Status').AsString := Statustekst;
             nxT_IDealRecords.FieldByName('Foutkode').AsString := Resulttekst;
            nxT_IDealRecords.Post;
          end;

        end
        else
          CodeSite.Send('Kan IDealrecord niet vinden');
        // bewaren als laatste zodat eerst de database wordt bijgewerkt
        // alleen voor debug:   XMLDoc2.SaveToFile(XML_Dir + 'result' + IntToStr(IDealRecNr) + '.xml');
      finally
        Strm.Free;
      end;

    except
      on E: Exception do
        CodeSite.SendException('fout(en) bij communicatie', E);
    end;

  end;
  CodeSite.ExitMethod('command get');
end;

procedure TService1.IdHTTPServer1CreatePostStream(AContext: TIdContext; AHeaders: TIdHeaderList; var VPostStream: TStream);
begin
  VPostStream := TMemoryStream.Create;
end;

procedure TService1.ServiceStart(Sender: TService; var Started: Boolean);
begin
  CodeSite.Send('Service Start');
  CoInitialize(nil);
  try
    IdHTTPServer1.Active := true;
    Started := true;
  except
    on E: Exception do
      CodeSite.SendException(E);
  end;
end;

procedure TService1.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  CoUninitialize
end;

end.
===================================

Greetings
Henk van den Boogaard
Logged
Henk vd Boogaard
RTC Expired
*
Posts: 24


« Reply #3 on: September 03, 2018, 12:28:13 PM »

Hello Danijel,

After I get a TransactionID from the client I must sent a XML to get back an XML with the information I need.
I was thinking to get that with a RtcHttpClient.


Henk
Logged
Henk vd Boogaard
RTC Expired
*
Posts: 24


« Reply #4 on: September 03, 2018, 12:35:55 PM »

I was thinking that a RtcDataRequest needs a RtcHttpClient
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #5 on: September 03, 2018, 01:08:20 PM »

If your Server can remain single-threaded (RtcHttpServer.MultiThreaded=FALSE), you can use a single RtcHttpClient component to send out requests to external Servers and get the data, but ... please keep in mind that doing this also means that your Server is ONLY capable of handling one request from your Clients at a time. If another Client sends a request to your Server while your Server is fetching data from the external Server, it will have to wait until the Server exits the "OnDataReceived" event where it's been waiting for a response from the external Server.

So far, your code looks OK. Now, you need to implement the "OnDataReceived" event for your "RtcDataReuqest" component, because that's where you will get the response from your external Server after you post the request with the "RtcDataRequest" and "RtcHttpClient1" component. Since your Server is single-threaded and you are only using one RtcHttpClient component, you can also use one private variable to store the response which you get from the external Server.

You will also need to make your client connection BLOCKING for this to work, which can either be done by setting the "useProxy", "useWinHttp" or "useBlocking" property to TRUE on your RtcHttpClient1 component (not sure if you did that already, since I don't see your Form). If you do that, you don't have to worry about RtcHttpClient1 or RtcDataRequest component events triggered asynchronously while you are waiting for a response from the Client.

Since you are using a single RtcHttpClient component and sending requests to a custom Server each time, also make sure to call Disconnect after you read the response, so you won't end up sending all the future requests to the same external Server.

Let me know if you need any more help.
Logged
Henk vd Boogaard
RTC Expired
*
Posts: 24


« Reply #6 on: September 03, 2018, 01:30:29 PM »

I have not made thinks clear to you so I try again.
I have a website where a customer can login to extent the hire of a car.
After he as filled in the necessary information he get redirected to MultisafePay (a firm that handles a payment by Ideal.
When the payment has made MultisafePay sent out a message (notification) to this program that there has been a mutation on the hire (a payment has been made or it did not succeed).
This program gets the notification and must the fetch the payment information by MultisafePay and process the information in the database.

My big question is how can process the information I get in a XML and how can I sent information to ask to get the payment information back in a XML.
In sort how can I handle the I get XML’s and I sent without using XMLDocument.
And also one tag of the outgoing XML is Attributes['ua']
(XMLDoc1.DocumentElement.Attributes['ua'] := 'Mozilla/3.0 (compatible; Indy Library)'Wink
What must I put in when using RTC?

Thanks for helping me.
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #7 on: September 03, 2018, 01:35:48 PM »

Since RTC does NOT include components for XML processing (you simply send out raw HTTP/S data and get raw HTTP/S data back), even if you are using RTC for communication, you still need something else to handle the XML. Is there a problem with the XML code you've used with Indy, or why are you looking for a solution which would NOT use that part of your old code?
Logged
Henk vd Boogaard
RTC Expired
*
Posts: 24


« Reply #8 on: September 03, 2018, 02:02:14 PM »

I thought RTC could handle XML’s, my mistake and that was easier.
Then I go use the old code again.
Still I have two questions:
1.   How van I sent / receice the XML’s I made / got.
2.   What must I put in the Attributes['ua'] tag

Henk
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #9 on: September 03, 2018, 02:14:47 PM »

1. Using RtcHttpClient and RtcDataRequest components, you can send any kind of HTTP request and receive a HTTP response. Check this topic from the RTC Classroom for a step-by-step guide on using the RTC SDK to send a request and receive a response from a Server:
https://rtc.teppi.net/realthinclient-sdk-demo-6-client-to-get-a-file-from-any-web-server/

2. I'm not sure what you mean, but looking at your code, it seems like the Attributes['ua'] from your example is just a name of the Client and only has informative functionality for the receiving Server, so ... you can either set the same as you've already used with Indy, or replace the "Indy Library" part of that text with "RTC" and see what happens Wink
Logged
Henk vd Boogaard
RTC Expired
*
Posts: 24


« Reply #10 on: September 03, 2018, 02:17:31 PM »

I will give it a try and give you the results.

Thanks,
Henk
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #11 on: September 03, 2018, 02:20:19 PM »

OK. Just keep in mind that your code needs to use "WaitForCompletion" after calling "Post" and "Connect" on the "RtcHttpClient" component to wait for the response (emulate blocking behavior), and ... you need to set "useProxy", "useWinHttp" or "useBlocking" property to TRUE on the "RtcHttpClient" component to make the communication blocking. Otherwise, your calls to "Post" and "Connect" will return immediately (before you get any data from the Server) and your request call would then be handled asynchronously (afterwards).

Also, if you have to communicate with different Servers for each request, make sure to call "Disconnect" after you get the data, to avoid problems with changing Servers (ServerAddr : ServerPort). On the other hand, if the Server is always the same and you expect to be sending more requests there, there's no need for a "Disconnect".

Logged
Henk vd Boogaard
RTC Expired
*
Posts: 24


« Reply #12 on: September 04, 2018, 03:56:05 PM »

Hi Danijel,

Will you take a short look if my code should work like this?

Also, the RtcDataRequest should be with HTTPS.
I try to use StreamSec2.
Is there an example how to do that?

here my code so far:
unit U_Work;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, rtcDataSrv, rtcSystem, rtcInfo, rtcConn, rtcHttpSrv, Vcl.StdCtrls, rtcDataCli, rtcHttpCli,
  Data.DB, Vcl.Grids, Vcl.DBGrids, Xml.xmldom, Xml.XMLIntf, Xml.omnixmldom, Xml.XMLDoc, Winapi.ActiveX;

type
  TWork = class(TForm)
    Memo1: TMemo;
    Ontvangen: TLabel;
    Server: TRtcHttpServer;
    RtcDataProvider1: TRtcDataProvider;
    RtcHttpClient1: TRtcHttpClient;
    RtcDataRequest1: TRtcDataRequest;
    DBGrid1: TDBGrid;
    label2: TLabel;
    XMLDoc1: TXMLDocument;
    XMLDoc2: TXMLDocument;
    procedure RtcDataProvider1CheckRequest(Sender: TRtcConnection);
    procedure RtcDataProvider1DataReceived(Sender: TRtcConnection);
    procedure RtcDataRequest1BeginRequest(Sender: TRtcConnection);
    procedure RtcDataRequest1DataReceived(Sender: TRtcConnection);
  private
    { Private declarations }
    TransactionID_str: rtcString;
    StatusText: string;
    IDealRecNr: integer;
    StatusReceived: boolean;
    Exportfilenaam: string;
    iChild, iNodeEwallet, iNodeStatus, iNode_Merchant, iNodeTransaction: IXMLNode;
    // Resulttekst, Statustekst: string;
    Strm: TStringStream;
    XML_string : rtcString;
    XML_response : rtcString;
    procedure FillRecords;

  public
    { Public declarations }
    DoDebug: boolean;
  end;

var
  Work: TWork;

implementation

{$R *.dfm}

uses U_DM1;

procedure TWork.FillRecords;
begin
  try
    if DM1.nxT_IDealRecords.FindKey([IDealRecNr]) then
    begin
      if Uppercase(StatusText) = 'OK' then
      begin
        DM1.nxT_IDealRecords.Edit;
        DM1.nxT_IDealRecords.FieldByName('StatusOntvangen').AsBoolean := true;
        DM1.nxT_IDealRecords.FieldByName('Status').AsString := StatusText;
        if Uppercase(StatusText) = 'COMPLETED' then
          DM1.nxT_IDealRecords.FieldByName('BetalingOK').AsBoolean := true;
        DM1.nxT_IDealRecords.Post;
      end
      else
      begin
        DM1.nxT_IDealRecords.Edit;
        DM1.nxT_IDealRecords.FieldByName('StatusOntvangen').AsBoolean := false;
        DM1.nxT_IDealRecords.FieldByName('Status').AsString := StatusText;
        DM1.nxT_IDealRecords.FieldByName('Foutkode').AsString := StatusText;
        DM1.nxT_IDealRecords.Post;
      end;

    end
    else if DoDebug then
      Memo1.Lines.Add('Kan IDealrecNr niet vinden');
  except
    on E: Exception do
      if DoDebug then
        Memo1.Lines.Add('Fout bij bewerken status in IDealrec. Error: ' + E.Message);
  end;
end;

procedure TWork.RtcDataProvider1CheckRequest(Sender: TRtcConnection);
begin
  with Sender as TRtcDataServer do
    Memo1.Lines.Add(Request.FileName);
  with Sender as TRtcDataServer do
    if Uppercase(Request.FileName) = '/MSP' then
      Accept;

end;

procedure TWork.RtcDataProvider1DataReceived(Sender: TRtcConnection);
begin
  with Sender as TRtcDataServer do
  begin
    if Request.Complete then
    begin
      if DoDebug then
        Memo1.Lines.Clear;
      TransactionID_str := Request.Query['transactionid'];
      if DoDebug then
        Memo1.Lines.Add(TransactionID_str);
      try
        IDealRecNr := StrToInt(TransactionID_str);
      except
        on E: Exception do
          if DoDebug then
            Memo1.Lines.Add('Fout bij vertalen recordnummer van parameter : ' + E.Message);
      end;

      with RtcDataRequest1 do
      begin
        Request.Method := 'GET';
        Request.FileName := '/' + TransactionID_str;
        CoInitialize(nil);
        // nu in database Huurovereenkomst controleren - indien OK dan VerstuurHTML:

        // maak XML-file:
        Exportfilenaam := 'IDeal_' + IntToStr(IDealRecNr) + '.XML';
        XMLDoc1.Active := false;
        XMLDoc1.Xml.Text := '';
        XMLDoc1.Active := true;
        XMLDoc1.Encoding := 'UTF-8';
        XMLDoc1.AddChild('Pricat', 'http://www.ean.nl');
        XMLDoc1.DocumentElement := XMLDoc1.CreateNode('status');
        XMLDoc1.DocumentElement.Attributes['ua'] := 'RTC Library)';

        // merchant
        iNode_Merchant := XMLDoc1.DocumentElement.AddChild('merchant');
        iChild := iNode_Merchant.AddChild('account');
        iChild.Text := DM1.nxT_algpar.FieldByName('IDeal_account').AsString;
        iChild := iNode_Merchant.AddChild('site_id');
        iChild.Text := DM1.nxT_algpar.FieldByName('IDeal_site_id').AsString;
        iChild := iNode_Merchant.AddChild('site_secure_code');
        iChild.Text := DM1.nxT_algpar.FieldByName('IDeal_site_secure_id').AsString;

        // transaction
        iNodeTransaction := XMLDoc1.DocumentElement.AddChild('transaction');
        iChild := iNodeTransaction.AddChild('id');
        iChild.Text := IntToStr(IDealRecNr);
        // bestand maken:
        if DoDebug then
          XMLDoc1.SaveToFile(DM1.XML_Dir + Exportfilenaam);

         XMLDoc1.SaveToXML(XML_string);
        // now get the information
        RtcHttpClient1.ServerAddr := DM1.SiteURL;
        RtcHttpClient1.ServerPort := IntToStr(DM1.SitePort);
        RtcHttpClient1.Write(XML_string);
        Post; // Post the request
        WaitForCompletion;
        XMLDoc1.Active := false;
        XMLDoc2.LoadFromXML(RtcHttpClient1.Response);   // Response is an XML file

        //NOW GET THE INFORMATION FROM xmldOC2


        CoUninitialize;
      end;

    end;
  end;
end;

procedure TWork.RtcDataRequest1BeginRequest(Sender: TRtcConnection);
begin
  with TRtcDataClient(Sender) do
  begin // make sure our request starts with "/"
    if Copy(Request.FileName, 1, 1) <> '/' then
      Request.FileName := '/' + Request.FileName;
    // define the "HOST" header
    if Request.Host = '' then
      Request.Host := ServerAddr;
    if DoDebug then
      Memo1.Text := 'Requeststring "' + Request.FileName + '" from "' + ServerAddr + '".';
    // send request header out
    WriteHeader;
  end;

end;

procedure TWork.RtcDataRequest1DataReceived(Sender: TRtcConnection);
begin
  with TRtcDataClient(Sender) do
  begin
    if Response.Started then
    begin { Executed only once per request,
        when we start receiving the response. }
      // Clear the info we wrote here in our "OnBeginRequest"
      // HERE COMES THE XML BACK?? HOW TO HANDLE THIS?
      // ALSO WITH REQUEST.QUERY??
      if DoDebug then
      begin
        Memo1.Clear;
        Memo1.Lines.Add('Status code: ' + IntToStr(Response.StatusCode));
        Memo1.Lines.Add('Status text:' + Response.StatusText);
        Memo1.Lines.Add('ALL Headers:');
        Memo1.Lines.Add(Response.HeaderText);
        Memo1.Lines.Add('Content Length:');
        Memo1.Lines.Add(IntToStr(Response.ContentLength));
        Memo1.Lines.Add('Content body:');
        Memo1.Lines.Add('START >');
      end; { Could be executed more than once,  depending on the content size }
      // add content received now.
      Memo1.Text := Memo1.Text + Read;
      if Response.Done then
      begin { Executed only once per request, when we have just received it all. }
        Memo1.Lines.Add('< END');
      end;
    end; // DoDebug
  end;
end;

end.

The DMF:

object Work: TWork
  Left = 0
  Top = 0
  Caption = 'AVN_MSP_SERVER'
  ClientHeight = 671
  ClientWidth = 947
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Ontvangen: TLabel
    Left = 20
    Top = 8
    Width = 72
    Height = 13
    Caption = 'Ontvangen/log'
  end
  object label2: TLabel
    Left = 20
    Top = 352
    Width = 120
    Height = 13
    Caption = 'test of database actief is'
  end
  object Memo1: TMemo
    Left = 146
    Top = 8
    Width = 671
    Height = 297
    ScrollBars = ssBoth
    TabOrder = 0
  end
  object DBGrid1: TDBGrid
    Left = 146
    Top = 352
    Width = 671
    Height = 233
    DataSource = DM1.DS_IDealRecords
    TabOrder = 1
    TitleFont.Charset = DEFAULT_CHARSET
    TitleFont.Color = clWindowText
    TitleFont.Height = -11
    TitleFont.Name = 'Tahoma'
    TitleFont.Style = []
  end
  object Server: TRtcHttpServer
    RestartOn.ListenLost = True
    RestartOn.ListenError = True
    RestartOn.Wait = 10
    Blocking = True
    Left = 848
    Top = 144
  end
  object RtcDataProvider1: TRtcDataProvider
    Server = Server
    OnCheckRequest = RtcDataProvider1CheckRequest
    OnDataReceived = RtcDataProvider1DataReceived
    Left = 848
    Top = 200
  end
  object RtcHttpClient1: TRtcHttpClient
    ReconnectOn.ConnectLost = True
    ReconnectOn.Wait = 5
    Blocking = True
    Left = 848
    Top = 264
  end
  object RtcDataRequest1: TRtcDataRequest
    AutoSyncEvents = True
    Client = RtcHttpClient1
    AutoRepost = 2
    OnBeginRequest = RtcDataRequest1BeginRequest
    OnDataReceived = RtcDataRequest1DataReceived
    Left = 848
    Top = 328
  end
  object XMLDoc1: TXMLDocument
    Left = 848
    Top = 400
    DOMVendorDesc = 'Omni XML'
  end
  object XMLDoc2: TXMLDocument
    Left = 848
    Top = 464
    DOMVendorDesc = 'Omni XML'
  end
end
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #13 on: September 05, 2018, 09:05:28 AM »

I've just realized that there are two topics from you related to the same question, so I've merged the two topics together now to avoid confusion.
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #14 on: September 05, 2018, 09:57:40 AM »

I've spotted a few problems with your latest code (related to wrong use of the RTC SDK)...

1. The Write method of the TRtcHttpClient component may ONLY be used from inside an event triggered by that component. In other words, your "RtcHttpClient1.Write(XML_string)" line inside the "RtcDataProvider1DataReceived" event is illegal and would most likely cause you problems.

However, if you already have the complete request headers and the request content body ready for sending and you are confident that the content is small enough to fit into memory without causing you memory problems, then you can use the "PostMethod" method on the "RtcDataRequest" component to have request headers and content body stored for you in temporary buffers and sent out after the "OnBeginRequest" event. This also works if you skip implementing the "OnBeginRequest", provided you also prepare all required headers before calling "PostMethod". In other words, this line replaces your "RtcHttpClient1.Write(XML_string);" and "Post" calls in the "RtcDataProvider1DataReceived", but it is entirely legal and does what you intended (provided you are using RTC SDK v9) ...

RtcDataRequest1.PostMethod('',XML_string);

2. You've set Request.Method='GET', but since you are posting a request with content body, I have a feeling that this is actually a "POST" request, so you might need to change that to Request.Method='POST' in your code, or simply remove that Request.Method assignment line from your code and use this line instead of the one I've recommended above (point 1) ...

RtcDataRequest1.PostMethod('POST',XML_string);

3. You are storing the response you get from the external Server inside the Memo.Text, which is fine for debugging but bad for production. You should change this to store the response content in a variable, so it doesn't get messed up with Memo component formatting.

In other words, instead of doing this inside your "RtcDataRequest1DataReceived" event ->

 // add content received now.
      Memo1.Text := Memo1.Text + Read;

You should declare a variable like "RecvContent:RtcString",
then you can do this inside the "RtcDataRequest1DataReceived" event ->

 // add content received now.
      RecvContent:=Sender.Read;
      Memo1.Text := RecvContent;

This makes your response content body accessible inside the "RtcDataProvider1DataReceived" event, after the "WaitForCompletion" call, so you can do this to access the XML string received as part of the response content body ->

XMLDoc2.LoadFromXML(RecvContent);   // Response is an XML file

Let me know if you have any other question.
Logged
Pages: [1] 2
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.046 seconds with 17 queries.