I am programming in Delphi and I'm having a hard time converting a C++ API POST Request into delphi. I have tried using Indy as I have before with previous API's but this one seems to not work with whatever I try. Could someone help me with this?
C++ Code I need to convert:
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(hnd, CURLOPT_URL, "https://sandbox.checkbook.io/v3/check/digital");
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "accept: application/json");
headers = curl_slist_append(headers, "content-type: application/json");
headers = curl_slist_append(headers, "Authorization: xxxxxxxxxxxxxxxx:xxxxxxxxxxxxxxxxx");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "{\"recipient\":\"[email protected]\",\"name\":\"Widgets Inc.\",\"amount\":5,\"description\":\"Test Payment\"}");
CURLcode ret = curl_easy_perform(hnd);
Delphi Code that I have:
unit API_InvoiceCloud;
interface
uses
DB, SysUtils, System.Classes, System.JSON, IdSSLOpenSSL, VCL.Dialogs,
IdHTTP, XML.XMLIntf, xml.xmlDom, xml.XMLDoc, IDCoder, IDCoderMIME,
IdBaseComponent, IdException{, IdZLibCompressorBase{, IdCompressorZLib{,Rest.Client};
procedure CreateDigitalPayment_CheckBookAPI(mRecipientEmailAddress,
mRecipientName : String;
mPaymentAmount : Double;
mPaymentNumber,
mPaymentDescription : String);
implementation
var
{ INDY COMPONENT TO CONNECT TO API SERVER; MAKES CONNECTION }
IDHTTP1 : TidHttp;
{ SSL Connection }
SSL : TIdSSLIOHandlerSocketOpenSSL;
{ Request and Response vars }
JsonRequest, InJson : String;
JsonToSend : TStringStream; //object to store json text and pass API
JObj : TJSONObject;
Const
{ Constant variables holding the APIKEY+APISECRET and BASEURL }
nBASEURL = 'https://sandbox.checkbook.io/v3/check/digital';
nAPIKEY = 'xxxxxxxxx:xxxxxxxx';
procedure CreateDigitalPayment_CheckBookAPI(mRecipientEmailAddress,
mRecipientName : String;
mPaymentAmount : Double;
mPaymentNumber,
mPaymentDescription : String);
var
{ Response into String }
SinglePartyResponse : String;
ResponseCode : String;
{ -----------Testing---------- }
//lParamList: TStringList;
nBASEURL : String;
RequestBody : TStream;
ResponseBody : String;
begin
{ JSON body with request string }
JsonRequest := '{"recipient":"' + mRecipientEmailAddress
+ '","name":"' + mRecipientName
+ '","amount":' + FloatToStr(mPaymentAmount)
+ ',"number":"' + mPaymentNumber
+ '","description":"' + mPaymentDescription + '"}';
try
try
{ Create connection instance }
IDHTTP1 := TidHttp.Create;
{ SSL Configuration }
SSL := TIdSSLIOHandlerSocketOpenSSL.Create;
SSL.SSLOptions.SSLVersions := [sslvTLSv1_1, sslvTLSv1_2];
IDHTTP1.IOHandler := SSL;
{ Headers/Params }
IDHTTP1.Request.Clear;
IDHTTP1.Request.CustomHeaders.FoldLines := False;
IDHTTP1.Request.Accept := 'application/json';
IDHTTP1.Request.ContentType := 'application/json';
IDHTTP1.Request.CustomHeaders.Values['Authorization'] := nAPIKEY;
{ Saving JSON text to TStringStream Object }
JsonToSend := TStringStream.Create(JsonRequest, TEncoding.UTF8);
//JsonToSend := TStringStream.Create(JsonRequest, TEncoding.ASCII);
{ Making POST Request using INDYs TidHTTP component; Params are: URL, JsonStringObj - saving into variable }
SinglePartyResponse := IDHTTP1.Post(nBASEURL, JsonToSend);
ShowMessage(IDHTTP1.ResponseCode.ToString);
except
on E : Exception do
{ Display error message if cannot do API CALL }
begin
ShowMessage(E.ClassName+' error raised, with message : "' + E.Message + '".');
Abort;
end
end;
finally
{ Free objects from memory }
IDHTTP1.Free;
SSL.Free;
JsonToSend.Free;
end;
end;
end.
When I try to make the POST request I get a 400 Bad Request error. I'm not sure what I am doing wrong here.
TIdHTTPis concerned. So, the most likely culprit is the JSON is probably malformed, ie if one of the text values has a"char in it. Since you haveSystem.JSONin theusesclause, you really should useTJSONObjectto create the JSON string, let it handle any necessary escaping as needed.