[SOLVED] Help to convert C# code to FPHTTPClient lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- patyit · 2022-01-29 14:52 Hello everyone ! I'm not a C# expert or a web expert. This code below is a template code for communicating with a fiscal processor server. I am trying to convert it to Lazarus, preferably with FPHTTPClient, Indy IdHTTP or with Synops components. Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i using Newtonsoft.Json;using System;using System.Collections.Generic;using System.Linq;using System.Net.Http;using System.Net.Http.Headers;using System.Security.Cryptography.X509Certificates;using System.Text;using System.Threading.Tasks;using VSDCRequestSubmitter.Models; namespace VSDCRequestSubmitter.Proxies{    public class VSDCApiProxy    {      private string VSDCAddress { get; set; }         private string Cn { get; set; }        private string PAC { get; set; }        private string RequestId { get; set; }        private string AcceptedLanguage { get; set; }        public VSDCApiProxy(string vSDCAddress, string cn, string pac, string acceptedLanguage, string requestId)        {          this.VSDCAddress = vSDCAddress;            this.Cn = cn;          this.PAC = pac;            this.AcceptedLanguage = acceptedLanguage;            this.RequestId = requestId;        }       public string ExecuteRequest(InvoiceRequest request)        {          using (var handler = new WebRequestHandler())            {              handler.ClientCertificateOptions = ClientCertificateOption.Manual;                handler.ClientCertificates.Add(LoadMyCertificate(Cn));                using (var client = new HttpClient(handler))                {                  client.BaseAddress = new Uri(VSDCAddress);                   client.DefaultRequestHeaders.Accept.Clear();                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));                  client.DefaultRequestHeaders.Add("PAC", PAC);                    if (AcceptedLanguage != "default")                    {                      client.DefaultRequestHeaders.Add("Accept-Language", AcceptedLanguage);                    }                    if (!String.IsNullOrEmpty(RequestId))                    {                      client.DefaultRequestHeaders.Add("RequestId", RequestId);                  }                     return client.PostAsJsonAsync($"{VSDCAddress}/api/v3/invoices", request).Result.Content.ReadAsStringAsync().Result;                }          }        }         private X509Certificate2 LoadMyCertificate(string cn)        {            var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);            store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);          var result = store.Certificates.Find(X509FindType.FindBySubjectName, cn, true);             return (result.Count > 0) ? result[0] : null;      }    }  Here is my code in Lazarus, I can't go through the authentication section, I don't know how to convert the code from the C# template "private X509Certificate2 LoadMyCertificate (string cn)" Please if anyone knows this cod, and knows the solution to advise me! Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses ...,  openssl, ssockets, sslsockets, opensslsockets, fphttpclient, procedure TForm1.SBInvoiceClick(Sender: TObject);var  htt : TFPHttpClient;  s : string;begin  InitSSLInterface;   s := '';  htt := TFPHttpClient.Create(nil);  htt.OnGetSocketHandler := @SSLClientCertSetup;  try     htt.AddHeader('Accept', 'application/json');    htt.AddHeader('Content-Type', 'application/json');    htt.AddHeader('RequestId', 'K1234');    htt.AddHeader('Accept-Language', 'sr-Cyrl-RS');    htt.AddHeader('PAC', 'XXXXXX');    try      htt.RequestBody := TStringStream.Create(Memo1.Lines.Text); // Memo contains Json      s := htt.Post(url+'/api/v3/invoices');  // HTTP API command      Memo1.Lines.Text := s;  // Result in Memo    except      on E: Exception do        ShowMessage('Error: HTTP Post: ('+IntToStr(htt.ResponseStatusCode)+') '+                                         htt.ResponseStatusText+#13#13+                                       E.Message);    end;  finally    htt.RequestBody.Free;    htt.Free;  end;end; procedure TForm1.SSLClientCertSetup(Sender: TObject;                           const UseSSL: Boolean; out AHandler: TSocketHandler);begin  AHandler := nil;  if {UseSSL and} (cer <> '') then begin    AHandler := TOpenSSLSocketHandler.Create;  TOpenSSLSocketHandler(AHandler).CertificateData.PFX.FileName := cer;  // I have a personal certificate with PFX extension //    TOpenSSLSoc ketHandler(AHandler).CertificateData.TrustedCertificate.FileName := cer;  // I'm not sure if this is necessary   end;end;     So I'm especially interested in the conversion for the "TForm1.SSLClientCertSetup()" procedure, how to define certification parameters based on a C# template ! ---------------------------------------------------------------------- patyit · 2022-02-02 21:57 Problem solved ! Here is my function to post request using sertificate with Indy 10.6.2 Lazarus and Delphi 7 : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function FSInvoice(jsn, pac: string; rid: string=''; url: string=''): string;var  idHttp : TIdHTTP;  soc : TIdSSLIOHandlerSocketOpenSSL;  res, req : TStringStream;begin  Result := '';  idHttp := TIdHTTP.Create;  try    idHttp.HandleRedirects := False;    idHttp.ReadTimeout     := 5000;    idHttp.Request.Accept  := 'application/json';    idHttp.Request.ContentType := 'application/json';    if rid > '' then      idHttp.Request.CustomHeaders.Add('RequestId: "'+rid+'"');    if Pos('https://', url) > 0 then begin      idHttp.Request.CustomHeaders.Add('PAC: "'+pac+'"');      soc := TIdSSLIOHandlerSocketOpenSSL.Create(idHttp);      soc.SSLOptions.CertFile := 'certificate.cer'; // extracted from certificate.pfx as certificate with OpenSSL      soc.SSLOptions.KeyFile  := 'certificate.key'; // extracted from certificate.pfx as key with OpenSSL      soc.SSLOptions.Mode     := sslmClient;      soc.SSLOptions.Method   := sslvSSLv23;       idHttp.IOHandler := soc;    end;    res := TStringStream.Create('');  try      req := TStringStream.Create(jsn);      try        try        idHttp.Post(url+'/api/v3/invoices', req, res);          if idHttp.ResponseCode = 200 then            Result := res.DataString        else            MessageDlg('Error: ('+IntToStr(IdHttp.ResponseCode)+') '+                                idHttp.ResponseText, mtError, [mbOk], 0);        except          on E: Exception do            MessageDlg('Error ! '+E.Message, mtError, [mbOk], 0);        end;      finally        req.Free;      end;    finally      res.Free;    end;  finally    if Assigned(soc) then      soc.Free;    idHttp.Free;  end;end;  To generate a private key file from PFX (PKCS#12 format), we can use this command: Code: Bash  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i openssl pkcs12 -in INFILE.pfx -out OUTFILE.key -nodes -nocertsAnd to create a file including only the certificates, use this: Code: Bash  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i openssl pkcs12 -in INFILE.pfx -out OUTFILE.crt -nokeys We add these extracted certificate files to the soc.SSLOptions.CertFile and soc.SSLOptions.KeyFile properties, it does its job perfectly ! I hope someone finds the solution useful and can apply it successfully !