VBA Rest API - DHL Return label - 401 - vba

I am trying to create a return shipping DHL parcel label with provided DHL api in the sandbox:
https://developer.dhl.com/api-reference/parcel-de-returns-post-parcel-germany#get-started-section/user-guide
With postman it works. But I would like to implement the HTTP Request in VBA.
I always receive status 401 Unauthorized
I guess it is the way how I pass the credentials.
Anyone has an idea how to get it working?
create return labels in the sandbox, with the following user data:
Username: "2222222222_customer"
Password: "uBQbZ62!ZiBiVVbhc"
Sub restAPICall()
Dim objRequest As MSXML2.ServerXMLHTTP60
Dim id_header_name As String, id_key As String, secret_header_name As String, secret_key As String
Dim strUrl As String
Dim blnAsync As Boolean
Dim strResponse As String
Dim json As Object
Dim authKey As String
Set objRequest = New ServerXMLHTTP60
strUrl = "https://api-sandbox.dhl.com/parcel/de/shipping/returns/v1/orders?labelType=BOTH" 'Endpoint Test
blnAsync = False
id_key = "2222222222_customer"
pass = "uBQbZ62!ZiBiVVbhc"
apiKey = "123456789"
body = "{""receiverId"":""deu"", " _
& " ""customerReference"":""Kundenreferenz"", " _
& " ""shipmentReference"":""Sendungsreferenz"", " _
& " ""shipper"": { " _
& " ""name1"":""Absender Retoure Zeile 1"", " _
& " ""name2"":""Absender Retoure Zeile 2"", " _
& " ""name3"":""Absender Retoure Zeile 3"", " _
& " ""addressStreet"":""Charles-de-Gaulle Str."", " _
& " ""addressHouse"":""20"", " _
& " ""city"":""Bonn"", " _
& " ""email"":""Max.Mustermann#dhl.local"", " _
& " ""phone"":""+49 421 987654321"", " _
& " ""postalCode"":""53113"", " _
& " ""state"":""NRW"", " _
& " }, " _
& " ""itemWeight"": { " _
& " ""uom"": ""g"", " _
& " ""value"":""1000"", " _
& " }, " _
& " ""itemValue"": { " _
& " ""currency"": ""EUR"", " _
& " ""value"":""100"", " _
& " }, " _
& "}"
With objRequest
.Open "POST", strUrl, blnAsync ', gkpuser, gkpass
.setRequestHeader "Authorization", "Basic " + EncodeBase64(id_key + ":" + pass)
.setRequestHeader "Content-Type", "application/json"
.setRequestHeader "Accept", "application/json"
.setRequestHeader "dhl-api-key", "apiKey"
.Send body
While objRequest.readyState <> 4
DoEvents
Wend
strResponseHeaders = .StatusText
strResponse = .responseText
allResponseHeader = .GetAllResponseHeaders
End With
Debug.Print body
Debug.Print allResponseHeader
Debug.Print strResponse
End Sub
Function EncodeBase64(text$)
Dim b
With CreateObject("ADODB.Stream")
.Open: .Type = 2: .Charset = "utf-8"
.WriteText text: .Position = 0: .Type = 1: b = .Read
With CreateObject("Microsoft.XMLDOM").createElement("b64")
.DataType = "bin.base64": .nodeTypedValue = b
EncodeBase64 = Replace(Mid(.text, 5), vbLf, "")
End With
.Close
End With
End Function
Many thanks :)
Alex

If apiKey is a variable, then you should leave the quotes out in:
.setRequestHeader "dhl-api-key", "apiKey"

Related

VBA send file in binary code to API via POST method

I have last problem with my code. Code sending via POST variables from Outlook to API.
My last problem is how to send variables and mail attachment in one POST request to API.
first 7zip comprimation for mail attachement:
strSource = cstrFileAttachment & "*.*"
strTarget = cstrFileattachment & "Zip\attachment.zip"
strPassword = randomPassword(cintLongPassword)
strCommand = """" & PathZipProgram & """ a -tzip """ & strTarget & _
""" -p" & strPassword & " """ & strSource & """"
Now i have c:\attachment\attachment.zip
Next part is send variables to API:
Dim SendDataToApi As String
strFrom = 1
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
URL = "https://url.domain.com/api/data"
objHTTP.Open "POST", URL, False
objHTTP.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded"
SendDataToApi = "mail_from=" & strFrom & "&mail_to=" & strKomu & "&file_attachment=" & fileAttachment & "&url_attribute=" & strWebLink & "&sms_code=" & strHeslo & "&id_message=" & IdMessage & "&mobile_phone=" & strPhone & "&date_send=" & strDateSend & "&date_expiration=" & strDateExp
objHTTP.Send SendDataToApi
Variables are sended, but fileAttachment is send as a string, so API get path where file is saved.
My question is how implement code below (found on internet) to my code sendDataToApi and POST attachment.zip as a binary insteed of string.
Private Function Upload(strUploadUrl, strFilePath, strFileField, strDataPairs)
'Uses POST to upload a file and miscellaneous form data
strUploadUrl = "https://url.domain.com/api/data"
strFilePath = cstrFilepathAttachment & "Zip\attachment.zip"
'strFileField is the web page equivalent form field name for the file (File1)
'strDataPairs are pipe-delimited form data pairs (foo=bar|snap=crackle)
Const MULTIPART_BOUNDARY = "---------------------------0123456789012"
Dim ado, rs
Dim lngCount
Dim bytFormData, bytFormStart, bytFormEnd, bytFile
Dim strFormStart, strFormEnd, strDataPair
Dim web
Const adLongVarBinary = 205
'Read the file into a byte array
Set ado = CreateObject("ADODB.Stream")
ado.Type = 1
ado.Open
ado.LoadFromFile strFilePath
bytFile = ado.Read
ado.Close
'Create the multipart form data.
'Define the end of form
strFormEnd = vbCrLf & "--" & MULTIPART_BOUNDARY & "--" & vbCrLf
'First add any ordinary form data pairs
strFormStart = ""
For Each strDataPair In Split(strDataPairs, "|")
strFormStart = strFormStart & "--" & MULTIPART_BOUNDARY & vbCrLf
strFormStart = strFormStart & "Content-Disposition: form-data; "
strFormStart = strFormStart & "name=""" & Split(strDataPair, "=")(0) & """"
strFormStart = strFormStart & vbCrLf & vbCrLf
strFormStart = strFormStart & Split(strDataPair, "=")(1)
strFormStart = strFormStart & vbCrLf
Next
'Now add the header for the uploaded file
strFormStart = strFormStart & "--" & MULTIPART_BOUNDARY & vbCrLf
strFormStart = strFormStart & "Content-Disposition: form-data; "
strFormStart = strFormStart & "name=""" & strFileField & """; "
strFormStart = strFormStart & "filename=""" & Mid(strFilePath, InStrRev(strFilePath, "\") + 1) & """"
strFormStart = strFormStart & vbCrLf
strFormStart = strFormStart & "Content-Type: application/upload" 'bogus, but it works
strFormStart = strFormStart & vbCrLf & vbCrLf
'Create a recordset large enough to hold everything
Set rs = CreateObject("ADODB.Recordset")
rs.Fields.Append "FormData", adLongVarBinary, Len(strFormStart) + LenB(bytFile) + Len(strFormEnd)
rs.Open
rs.AddNew
'Convert form data so far to zero-terminated byte array
For lngCount = 1 To Len(strFormStart)
bytFormStart = bytFormStart & ChrB(Asc(Mid(strFormStart, lngCount, 1)))
Next
rs("FormData").AppendChunk bytFormStart & ChrB(0)
bytFormStart = rs("formData").GetChunk(Len(strFormStart))
rs("FormData") = ""
'Get the end boundary as a zero-terminated byte array
For lngCount = 1 To Len(strFormEnd)
bytFormEnd = bytFormEnd & ChrB(Asc(Mid(strFormEnd, lngCount, 1)))
Next
rs("FormData").AppendChunk bytFormEnd & ChrB(0)
bytFormEnd = rs("formData").GetChunk(Len(strFormEnd))
rs("FormData") = ""
'Now merge it all
rs("FormData").AppendChunk bytFormStart
rs("FormData").AppendChunk bytFile
rs("FormData").AppendChunk bytFormEnd
bytFormData = rs("FormData")
rs.Close
'Upload it
Set web = CreateObject("WinHttp.WinHttpRequest.5.1")
web.Open "POST", strUploadUrl, False
web.SetRequestHeader "Content-Type", "multipart/form-data; boundary=" & MULTIPART_BOUNDARY
web.Send bytFormData
End Function
UPDATE:
when i added part of code from #Tim Williams
in my database is saved file as /tmp/phpAJOtVw what do i doing wrong ?
Upload is a standalone method, so you should be able to call it something like this:
sUrl = "https://url.domain.com/api/data" 'API endpoint
fPath = "c:\attachment\attachment.zip" 'attachment location
FileFieldName = "checkYourApiForThis" 'API specifies this
DataPairs = "mail_from=" & strFrom & _
"&mail_to=" & strKomu & _
"&file_attachment=" & fileAttachment & _
"&url_attribute=" & strWebLink & _
"&sms_code=" & strHeslo & _
"&id_message=" & IdMessage & _
"&mobile_phone=" & strPhone & _
"&date_send=" & strDateSend & _
"&date_expiration=" & strDateExp
'call the function
'expects |-delimited name/value pairs, not &, so do a replace
Upload sUrl, fPath, FileFieldName, Replace(DataPairs, "&", "|")
You should remove these hard-coded values from the top of Upload:
strUploadUrl = "https://url.domain.com/api/data"
strFilePath = cstrFilepathAttachment & "Zip\attachment.zip"

Out Of Memory (7) when upload file in VB6 using MSXML

i have a function to upload multipart/form-data with Visual Basic 6 using MSXML2.ServerXMLHTTP60, no problem with 100MB file size, but when i upload 200MB it's show "Run Time Error '7'" Out Of Memory.
this is my code:
Public Function PostFile(sUrl As String, sJSON As String, sFileName As String) As String
Const STR_BOUNDARY As String = "864d391d-4097-44e0-92e1-71aff17094c1"
Dim sPostData As String
Dim bytData
With CreateObject("ADODB.Stream")
.Type = 1
.Mode = 3
.Open
.LoadFromFile sFileName
bytData = .Read
End With
With CreateObject("ADODB.Stream")
.Mode = 3
.Charset = "Windows-1252"
.Open
.Type = 2
.WriteText "--" & STR_BOUNDARY & vbCrLf
.WriteText "Content-Disposition: form-data; name=""json""" & vbCrLf
.WriteText "Content-Type: application/json" & vbCrLf & vbCrLf
.WriteText sJSON & vbCrLf
.WriteText "--" & STR_BOUNDARY & vbCrLf
.WriteText "Content-Disposition: form-data; name=""uploadfile""; filename=""" & Mid$(sFileName, InStrRev(sFileName, "\") + 1) & """" & vbCrLf
.WriteText "Content-Type: application/octet-stream" & vbCrLf & vbCrLf
.Position = 0
.Type = 1
.Position = .Size
.Write bytData
.Position = 0
.Type = 2
.Position = .Size
.WriteText vbCrLf & "--" & STR_BOUNDARY & "--"
.Position = 0
.Type = 1
sPostData = StrConv(.Read, vbUnicode)
End With
With New MSXML2.ServerXMLHTTP60
.Open "POST", sUrl, True
.setRequestHeader "Content-Type", "multipart/form-data; boundary=" & STR_BOUNDARY
.send ToByteArray(sPostData)
.waitForResponse 300 'second
If .Status = 200 Then PostFile = .responseText Else .abort
End With
End Function
Private Function ToByteArray(sText As String) As Byte()
ToByteArray = StrConv(sText, vbFromUnicode)
End Function
Before i update the script above i using "open file method" to read binary file like below:
Public Function PostFile(sUrl As String, sJSON As String, sFileName As String) As String
Const STR_BOUNDARY As String = "864d391d-4097-44e0-92e1-71aff17094c1"
Dim nFile As Integer
Dim baBuffer() As Byte
Dim sPostData As String
nFile = FreeFile
Open sFileName For Binary Access Read As nFile
If LOF(nFile) > 0 Then
ReDim baBuffer(0 To LOF(nFile) - 1) As Byte
Get nFile, , baBuffer
sPostData = StrConv(baBuffer, vbUnicode)
End If
Close nFile
'--- prepare body
sPostData = "--" & STR_BOUNDARY & vbCrLf & _
"Content-Disposition: form-data; name=""json""" & vbCrLf & _
"Content-Type: application/json" & vbCrLf & vbCrLf & _
sJSON & vbCrLf & _
"--" & STR_BOUNDARY & vbCrLf & _
"Content-Disposition: form-data; name=""uploadfile""; filename=""" & Mid$(sFileName, InStrRev(sFileName, "\") + 1) & """" & vbCrLf & _
"Content-Type: application/octet-stream" & vbCrLf & vbCrLf & _
sPostData & vbCrLf & _
"--" & STR_BOUNDARY & "--"
'--- post
With New MSXML2.ServerXMLHTTP60
.Open "POST", sUrl, True
.setRequestHeader "Content-Type", "multipart/form-data; boundary=" & STR_BOUNDARY
.send ToByteArray(sPostData)
.waitForResponse 300 'second
If .Status = 200 Then PostFile = .responseText Else .abort
End With
End Function
Private Function ToByteArray(sText As String) As Byte()
ToByteArray = StrConv(sText, vbFromUnicode)
End Function
But, that show error "Run Time Error '14'" Out of string space
how to handle this error?

can I use goole calender API with VBA (to create a calender entry from MS-Excel)

I like to create a new google calender entry from Microsoft Excel 2016, how can I do this?
I tried the following code, but I get a Timeout at "xmlhttp.send ...".
Sub AddGoogleKalenderEntry()
Set xmlhttp = CreateObject("MSXML2.ServerXMLHTTP")
xmlhttp.Open "POST", "https://www.google.com/accounts/ClientLogin", False
xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
xmlhttp.send "accountType=HOSTED_OR_GOOGLE&Email=<User>#gmail.com&Passwd=<PWD>" & "&source=Gulp-CalGulp-1.05&service=cl"
Lines = Split(xmlhttp.responseText, vbLf)
nvp = Split(Lines(2), "=")
Set xmlhttp = Nothing
calentry = "<?xml version='1.0' ?><entry xmlns='http://www.w3.org/2005/Atom' " _
& "xmlns:gd='http://schemas.google.com/g/2005'>" _
& "<category scheme='http://schemas.google.com/g/2005#kind' " _
& "term='http://schemas.google.com/g/2005#event'></category>" _
& "<title type='text'>Tennis with Beth</title>" _
& "<content type='text'>Meet for a quick lesson.</content>" _
& "<gd:transparency " _
& "value='http://schemas.google.com/g/2005#event.opaque'>" _
& "</gd:transparency>" _
& "<gd:eventStatus " _
& "value='http://schemas.google.com/g/2005#event.confirmed'>" _
& "</gd:eventStatus>" _
& "<gd:where valueString='Rolling Lawn Courts'></gd:where>" _
& "<gd:when startTime='2010-01-22T15:00:00.000Z' " _
& "endTime='2010-01-22T17:00:00.000Z'></gd:when>" _
& "</entry>"
url = "http://www.google.com/calendar/feeds/default/private/full"
Call postEntry(url, nvp)
End Sub

MSXML2.xmlhttp Sends empty PDF

I'm trying to send PDF file using MSXML2.xmlhttp but the client receive empty PDF File as an attachment without any errors. I'm using Visual Basic 6.0 to send requests.
I sent the same file with RingCentral Web App and it works. I think the binary conversion is not working properly. Here is my code:
Function CreateFaxMessage(strPath, _
strStatus, _
Receiver, _
Optional coverPageText = "", _
Optional strResponse = "", _
Optional faxResolution As String = "High") As Boolean
Dim strFile, strExt, strContentType, strBoundary, bytData, bytPayLoad
On Error Resume Next
104 With CreateObject("Scripting.FileSystemObject")
106 If .FileExists(strPath) Then
108 strFile = .GetFileName(strPath)
110 strExt = .GetExtensionName(strPath)
Else
112 strStatus = "File not found"
114 CreateFaxMessage = False
Exit Function
End If
End With
116 With CreateObject("Scripting.Dictionary")
146 .Add "pdf", "application/pdf"
148 strContentType = .Item(LCase(strExt))
End With
150 If strContentType = "" Then
152 strStatus = "Invalid file type"
154 CreateFaxMessage = False
Exit Function
End If
174 strBoundary = String(2, "-") & Replace(Mid(CreateObject("Scriptlet.TypeLib").Guid, 2, 36), "-", "")
Dim nFile As Integer
Dim baBuffer() As Byte
Dim sPostData As String
'--- read file
nFile = FreeFile
Open strPath For Binary Access Read As nFile
If LOF(nFile) > 0 Then
ReDim baBuffer(0 To LOF(nFile) - 1) As Byte
Get nFile, , baBuffer
sPostData = StrConv(baBuffer, vbFromUnicode)
End If
Close nFile
'--- prepare body
sPostData = strBoundary & vbCrLf & _
"Content-Disposition: form-data; name=""attachment""; filename=""" & strFile & """" & vbCrLf & _
"Content-Transfer-Encoding: binary" & vbCrLf & _
"Content-Type: " & strContentType & vbCrLf & vbCrLf & _
sPostData & vbCrLf
sPostData = sPostData & strBoundary & "--"
Dim params As String
220 params = strBoundary & vbCrLf
222 params = params & "Content-Disposition: form-data; name=""faxResolution""" & vbCrLf & vbCrLf
224 params = params & faxResolution & vbCrLf
232 params = params & strBoundary & vbCrLf
params = params & "Content-Disposition: form-data; name=""to""" & vbCrLf & vbCrLf
params = params & Receiver & vbCrLf
Dim XMLHTTP As Object
218 Set XMLHTTP = CreateObject("MSXML2.ServerXMLHTTP")
240 With XMLHTTP
242 .setTimeouts 0, 60000, 300000, 300000
244 .Open "POST", FaxURL, False
246 '.setRequestHeader "Accept", "application/json; boundary=" & strBoundary
248 .setRequestHeader "Content-Type", "multipart/form-data; boundary=" & Mid(strBoundary, 3)
250 .setRequestHeader "Authorization", "Bearer " & RingCentral.AccessToken
252 .send params & sPostData
260 If Ok(.status) Then
262 strResponse = .responseText
264 CreateFaxMessage = True
Else
266 MsgBox .statusText & " (" & .status & ")"
End If
End With
Exit Function
End Function

Access Denied Query XML SOAP Sharepoint

The code worked very well, but these last days just stopped to work.
The .responseText is now:
Access is denied. (Exception from HRESULT: 0x80070005
(E_ACCESSDENIED))"
I tried with and without the line: objXMLHTTP.setRequestHeader "Authorization" And got the same Error.
With and without User and Password at line objXMLHTTP.Open, and still the same problem, Access Denied.
Can you guys help me please?
Sub selectSharepoint()
Dim objXMLHTTP As MSXML2.XMLHTTP
Dim strBatchXml As String
Dim strSoapBody As String
UserName = "john#email.com"
Password = "123456"
Set objXMLHTTP = New MSXML2.XMLHTTP
objXMLHTTP.Open "POST", "https://ts.sharepoint.com/sites/2018_teste/_vti_bin/lists.asmx", False, UserName, Password
'objXMLHTTP.Open "POST", "https://ts.sharepoint.com/sites/2018_teste/_vti_bin/lists.asmx", False 'This way worked the same, and got the same error.
objXMLHTTP.setRequestHeader "Content-Type", "text/xml; charset=UTF-8"
objXMLHTTP.setRequestHeader "Content-Length", "length"
'objXMLHTTP.setRequestHeader "Authorization", "Basic " + Base64Encode(UserName & ":" & Password) 'makes no effect, with or without Base64Encode
objXMLHTTP.setRequestHeader "SOAPAction", "http://schemas.microsoft.com/sharepoint/soap/GetListItems"
strSoapBody = "<?xml version='1.0' encoding='utf-8'?>" & _
" <soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>" & _
" <soap:Body>" & _
" <GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'>" & _
" <listName>AllNames</listName>" & _
" <query>" & _
" <Query xmlns=''>" & _
" <Where>" & _
" <Eq>" & _
" <FieldRef Name='Name' />" & _
" <Value Type='Text'>Cloe</Value>" & _
" </Eq>" & _
" </Where>" & _
" <OrderBy>" & _
" <FieldRef Name='ID' />" & _
" </OrderBy>" & _
" </Query>" & _
" </query>"
strSoapBody = strSoapBody & _
" <rowLimit>1</rowLimit>" & _
" <viewFields><ViewFields>" & _
" <FieldRef xsi:type='s:string' Name='Name'></FieldRef>" & _
" </ViewFields></viewFields>" & _
" </GetListItems>" & _
" </soap:Body>" & _
" </soap:Envelope>"
objXMLHTTP.send strSoapBody
If objXMLHTTP.Status <> 200 Then
MsgBox ("Error! " & Chr(10) & objXMLHTTP.responseText)
End
Else
tudo = objXMLHTTP.responseText
End If
End Sub
MsgBox Error:
MsgBox Error