MS Access API Request - vba

This is my first post here though have been using the great advice/solutions here for years so am very grateful. But this one, I can't find solution for.
I have an MS access front end/back end in use for various office admin tasks and records. Much of the data my office works with on a daily basis is cloud based. However API access is provided with app key and secret key. I have no issues using the API explorer with these keys, but can't get anything through code (VBA). I keep reading it is perfectly possible to do this with VBA which is why I kept trying different solutions, but now need help. (I have replaced URL and keys etc)
Dim myObj As New MSXML2.XMLHTTP60
Dim url, endPoint, params, tickers, appKey, secretKey As String
url = "theURL.com"
endPoint = "theEndPoint"
params = "id="
tickers = "1"
appKey = "12345678"
secretKey = "12345678"
myObj.Open "GET", url, False
myObj.setRequestHeader "Content-Type", "application/json"
myObj.setRequestHeader "app-key", appKey
myObj.setRequestHeader "secret-key", secretKey
myObj.send
This returns "App Key is required." I have tried various solutions including converting keys to Base64, putting the keys within the Open request, sending the keys as part of the send request etc. Always get "App Key is required" when reading response. I know in this code I have't actually requested anything but that returns same message when I do. I just wanted to keep what I posted simple.
Any help at all is greatly appreciated as this would allow great deal of automation for our office.
Thanks
James

Related

Unable to connect to HateBase API

I'm failing to connect to HateBase API. I have broken down the code here to make the debugging easier:
key ='blah blah'
base_url = 'https://api.hatebase.org'
url = "https://api.hatebase.org/4-4/authenticate"
payload = "api_key=" + key
response = requests.post(url, data=payload, headers=headers)
token = response.json()
print(token)
output:
{'datetime': '2022-03-02 18:32:13',
'errors': {'8752': 'The version of the API is now retired; please update your queries to resume accessing the API'},
'important': "Your use of the HateBase API acknowledges your consent with Hatebase's Terms of Use (available online at hatebase.org) and PROHIBITS REDISTRIBUTION of this data for any purpose, including but not limited to republication in any form, such as in PUBLIC CODE REPOSITORIES.",
'query': {'api_key': 'blah blah'},
'version': '4.4'}
I'm not sure if there is a problem with HateBase API itself... Alternatively, I'd be thankful if anyone knows a source that has already collected all HateBase Vocabulary.
Apparently Hatebase is no longer being actively maintained, so they retired the Hatebase API. I sent them an email about it and they suggested I try Weaponized Word instead.
"A good alternative is The Weaponized Word, a new project which is
very similar to Hatebase: it's free for eligible academic researchers,
and has a multilingual lexicon, an API and a built-in natural language
parser. At this time, language coverage on The Weaponized Word is
roughly twice the size of Hatebase's lexicon."
That was very frustrating for me as well, because I last used the API end of 2021 so I was not sure what was happening. I haven't tried the new tool yet, but I'm happy that at least they offer an alternative :)

How to Emulate a POST Request from PostMan - For a series of Integration Tests in a WebAPI Development

I am using PostMan as part of the testing regime for a WebAPI service development that I am working on. In order for external parties to gain access to our WebAPI service they first need to obtain an access token.
The POST request returns some JSON containing the required access token:
{
"access_token": "anencryptedaccesstoken",
"scope": "am_application_scope default",
"token_type": "Bearer",
"expires_in": 3218
}
I am putting together a series of integration tests which need to emulate the POST calls from POSTMAN. I am currently using System.Net.WebClient to achieve this. I am not sure what I need to do in order to achieve my goal. Here is a function that I am using to try and obtain the access token:
Public Shared Function GetAccessToken(ByVal endpoint As String, wc As WebClient) As String
Dim result As String = ""
Dim data As Byte() = Nothing
'Header information
wc.Headers.Add("Authorization", "Basic <alongencryptedstring>")
wc.Headers.Add("Content_Type", "application/x-www-form-urlencoded")
result = wc.UploadString(endpoint, "POST", "")
Return result
End Function
The 'Body' tab in PostMan contains the following entries:
grant_type - client_credentials
Content_Type - application%2Fx-www-form-urlencoded
In this instance as far as I am aware there is no 'data' element to the PostMan request hence the empty string in my use of UploadString. The function returns the following error:
"The remote server returned an error: (415) Unsupported Media Type."
I am new to web app development so please bear with me, I am finding it difficult to phrase what I think are meaningful question in the context of this post, I hope however that I have ssupplied sufficient information to convey the gist of my problem and for someone to be able to respond appropriately.
Kind Regards
Paul.

Format this GET request in VB.NET code behind?

I am trying a "GET" method to request a count of activities from the Accelo API here:
https://api.accelo.com/docs/?http#count-activities
And although i've used a very similar POST method to successfully get the access token using an authentication method, I cannot for the life of me figure out how to get the count of activities. The API says to use "GET" and past the access token as "bearer..." and I've also tried doing a post and getting the stream first, tried sending in some data and accessing the "list activities" endpoint instead...nothing is working. everything I do returns the error "400. Bad Request."
I've tried passing data in a query string format directly in the URI, and tried passing no data since its a GET function. It looks to me like I'm following the API exactly.
Dim data2 = Nothing ' Encoding.UTF8.GetBytes(jsonstring)
Dim _list = GetListOfActivities(New Uri("https://example.api.accelo.com/api/v0/activities/count.xml"), data2, _AccessToken)
Dim reqa As WebRequest = WebRequest.Create(uri)
' reqa.Method = "GET"
reqa.Headers.Add("GET", "/api/v0/activities/count.xml HTTP/1.1")
reqa.Headers.Add("Authorization", "Bearer " & _AccessToken)
reqa.ContentType = "application/x-www-form-urlencoded"
'reqa.ContentLength = jsonDataBytes.Length
' Dim streama = reqa.GetRequestStream()
' streama.Write(jsonDataBytes, 0, jsonDataBytes.Length)
'streama.Close()
Dim responsea As WebResponse = reqa.GetResponse()
Console.WriteLine((CType(responsea, HttpWebResponse)).StatusDescription)
I must be formatting the request wrong - please help?
My problem turned out to be something stupid, and literally beyond the scope of what I posted here. I had specified a "scope" in my initial request to get the access token that was set to read-only "staff" data (I had copied-and-pasted their example online into my code, for other parameters like grant type, and I brought the scope along with it), and in this scenario here I was trying to access "activities" data and not "staff" data. I would have thought I'd get a permissions-related error, instead of "bad request" which confused me, but anyway it works now.
The above code - actually with this line:
reqa.Method = "GET"
instead of this line:
reqa.Headers.Add("GET", "/api/v0/activities/count.xml HTTP/1.1")
Works just fine since I changed my scope to read(all) in my initial web method getting the access token.

Google Apps Script login to website with HTTP request

I have a spreadsheet on my Google Drive and I want to download a CSV from another website and put it into my spreadsheet. The problem is that I have to login to the website first, so I need to use some HTTP request to do that.
I have found this site and this. If either of these sites has the answer on it, then I clearly don't understand them enough to figure it out. Could someone help me figure this out? I feel that the second site is especially close to what I need, but I don't understand what it is doing.
To clarify again, I want to login with an HTTP request and then make a call to the same website with a different URL that is the call to get the CSV file.
I have done a lot of this in the past month so I should be able to help you, we are trying to emulate the browsers behaviour here so first you need to use chrome's developer tools(or something similar) and note down the exact things the browser does like the form values posted, the url that is called and so on. The following example shows the general techinique to be used:
The first step is to login to the website and get the session cookie:
var payload =
{
"user_session[email]" : "username",
"user_session[password]" : "password",
};// The actual values of the post variables (like user_session[email]) depends on the site so u need to get it either from the html of the login page or using the developer tools I mentioned.
var options =
{
"method" : "post",
"payload" : payload,
"followRedirects" : false
};
var login = UrlFetchApp.fetch("https://www.website.com/login" , options);
var sessionDetails = login.getAllHeaders()['Set-Cookie'];
We have logged into the website (In order to confirm just log the sessionDetails and match it with the cookies set by chrome). The next step is purely dependent on the website so I will give u a general example
var downloadPayload =
{
"__EVENTTARGET" : 'ctl00$ActionsPlaceHolder$exportDownloadLink1',
};// This is just an example it may or may not be needed, if needed u need to trace the values from the developer tools.
var downloadCsv = UrlFetchApp.fetch("https://www.website.com/",
{"headers" : {"Cookie" : sessionDetails},
"method" : "post",
"payload" : downloadPayload,
});
Logger.log(downloadCsv.getContentText())
The file should now be logged, you can then parse the csv using hte GAS inbuilt function and dump the data in the spreadsheet.
A few points to note:
I have assumed that all form post values are static and can be
hardcoded, in case this is not true then let me know I will give you
a function that can extract values from the html.
Some websites require the browser to send a token value(the value will be present in the html) along with the credentials. In this case you need to extract the values and then post it.

Authenticate in Xero from Salesforce

I'm new to Oauth and I stack on getting oauth_access_token to work with Xero. Web Service authentication doesn't work for me.
Xero returns the following error message "oauth_problem=signature_invalid&oauth_problem_advice=Failed to validate signature".
The generated signature is incorrect, but what is right way to generate it?
Here is APEX code which generates Endpoint. What is wrong?
Http h = new Http();
String consumer_key='XXX';
Long tmp=(System.now().getTime()/1000);
Blob isItCorrect = Crypto.generateMac('HMacSHA1', Blob.valueOf('https://api.xero.com/api.xro/2.0'), Blob.valueOf(consumer_key));
String signature= EncodingUtil.urlEncode(EncodingUtil.base64Encode(isItCorrect), 'UTF-8');
// Try to get access token
HttpRequest req = new HttpRequest();
req.setEndpoint('https://api.xero.com/oauth/RequestToken?oauth_consumer_key='+consumer_key+
'&oauth_signature_method=RSA-SHA1'+
'&oauth_signature='+signature+
'&oauth_timestamp='+tmp+ '&oauth_nonce='+tmp+'&oauth_version=1.0&scope=https%3A%2F%2Fapi.xero.com%2Fapi.xro%2F2.0');
req.setMethod('GET');
// Send the request, and return a response
HttpResponse res = h.send(req);
System.debug('~~~ '+res.getBody());
It generates following Endpoint:
Endpoint=https://api.xero.com/oauth/RequestToken?oauth_consumer_key=ICSP7Y5K2TG7RIIC6Y7R7KLC1AHWYC&oauth_signature_method=RSA-SHA1&oauth_signature=gWP02y2EIatw4xilTvd5Iq3e0%2Fw%3D&oauth_timestamp=1372123781&oauth_nonce=1372123781&oauth_version=1.0&scope=https%3A%2F%2Fapi.xero.com%2Fapi.xro%2F2.0
Just as an aside: I've never worked with salesforce so I'm not sure if there's a better
way to leverage existing oauth work on the platform, it's very rare
now to have to write all the oauth signature stuff yourself and it's
easy to make a mistake but here goes]
I think your signature base string is incorrect.
As far as I can tell you're just performing HMAC-SHA1 over https://api.xero.com/api.xro/2.0
if you read the OAuth Spec here: http://oauth.net/core/1.0/#anchor14 you need to construct the following base string (based on the request above)
GET&https%3A%2F%2Fapi.xero.com%2Foauth%2Frequesttoken&oauth_consumer_key%3DCONSUMER_KEY%26oauth_nonce (etc etc, just append all your query parameters apart from oauth_consumer as url encoded key=value pairs, in alphabetical order)
and then you need to create the hash with the key CONSUMER_KEY&CONSUMER_SECRET (both CONSUMER_KEY and CONSUMER_SECRET should be parameter encoded as per the OAuth Spec)
That should give you a valid signature..
Edit: I found this library which might be of help: https://code.google.com/p/sfdc-oauth-playground/