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.
Found Solution. Thanks for the suggestions!
The 400 Bad Request Error was due to an "invalid authorization header"
My solution:
1. Went into the Embarcadero built in RestDebugger and got it to work in there by setting the BASEURL, CONTENT-TYPE, AUTHORIZATION(APIKey in Params), and CustomBody.
2. Clicked on the 'Copy Components' button and pasted
RESTClient,RESTRequest,RESTResponseonto an empty form.3. Built the JSON String and passed it as parameter to
RESTRequest.AddBodythen executed.(Code below)There are better ways to do this, but this worked for me.