Getting Myob AccountRight API Access token error - access-token

I am trying to get access token from MYOB. The POST call i make returns a "400 Bad Request error"
i'm using "axios" to make the POST call
i already got the Access code which i use in the data i'm sending in the POST call
here is my code
const config= { headers:{'Content-Type':"application/x-www-form-urlencoded"}}
const data={
client_id:"xxxxxxxxxxxxxxxxxxxxxxx",
client_secret:"xxxxxxxxxxxxxxxxxxxxx",
scope:"CompanyFile",
code: code,
redirect_uri:"http%3A%2F%2Flocalhost%3A30002Fcallback",
grant_type : "authorization_code"
}
axios.post("https://secure.myob.com/oauth2/v1/authorize", data, config)
.then((res) =>{
console.log ("response ...............", res
}
)
.catch((error) => {
console.error("Error here is ........",error)
}
)

Axios will, by default, attempt to POST your data fields as JSON which is not correct.
Instead, you want to url encode them and post the url-encoded string in the HTTP body. See the 'example call' in the docs.
There's a good example of how to url encode w/ axios here.
I also note that your redirect_uri field is already url encoded, so attempting to simply encode it a second time means you'll end up with something like http%253A%252F%252Flocalhost which is not correct. Double check your URL encoding against the example call to make sure you're not accidentally encoding certain fields twice. From memory the access code is already encoded appropriately so you might need to fiddle with decoding it before re-encoding it to get it working.

Related

Capture raw axios request from AWS Lambda

I have code that calls a vendor API to do a formdata upload of a file by axios from inside an AWS Lambda. The call returns a 400 error. If I run the code locally using the same node version v14 it works. I want to capture both raw requests and compare them for differences. How do I capture both raw requests? I've tried using ngrok and pipedream but they don't show the raw but decode the request and the file.
let response = null;
try {
const newFile = fs.createReadStream(doc);
const formData = new FormData();
formData.append("file", newFile);
formData.append("url", url);
const headers = {
Authorization: "Bearer " + token,
...formData.getHeaders(),
};
console.log("Headers: ", headers);
response = await axios.post(`${APIBASE}/file/FileUpload`, formData, {
headers,
});
console.log("file upload response", response);
} catch (err) {
console.log("fileupload error at API", err);
}
You might be able to just use a custom request interceptor and interrogate at the requests that way.
https://axios-http.com/docs/interceptors
You're not able to capture the request on the network level, as this is totally controlled by AWS. Maybe there's a way to do this when running in a VPC, but I don't think so.
You could simply use a tool such as axios debug logger to print out all of the request and response contents (including headers etc) before the request is made/after the response has arrived. This might provide some more information as to where things are going wrong.
As to the cause of the problem, it is difficult to help you there since you haven't shared the error message nor do we know anything about the API you're trying to call.
There are multiple ways to debug
axios debug logger .
AWS cloud watch where you can see all the logs. you can capture the request
and response.
Use postman to call the prod lambda endpoint and verify the response.

Power Query call to google.webmaster.api , Post, request problem

I call the google.webmasters.api via Power-Query(M) and managed to configure the oath2 and made my first successfull call to get & list.
Now i try to call the /searchAnalytics/query? which is working only with Post.
This always responds in a 400 error. Formating of the Query or the Url is not working correctly.
Here some additional Infomations:
Power Query - Reference
Google Webmaster Api - Reference
PowerBi Community
format Date different:
body = "{ ""startDate"": ""2019-01-01"", ""endDate"": ""2019-02-02"" }",
to
body = "{ ""startDate"": ""2019/01/01"", ""endDate"": ""2019/02/02"" }",
let
body = "{ ""startDate"": ""2019-01-01"", ""endDate"": ""2019-02-02"" }",
AccessTokenList = List.Buffer(api_token),
access_token = AccessTokenList{0},
AuthKey = "Bearer " & access_token,
url = "https://www.googleapis.com/webmasters/v3/sites/https%3A%2F%2Fxxxxxxxxx.xxx/searchAnalytics/query?",
Response = Web.Contents(url, [Headers=[Authorization=AuthKey, ContentType="application/json", Accept="application/json"], Content=Text.ToBinary(body) ]),
JsonResponse = Json.Document(Response)
in
Response
getting a 400 and is shows as 400 call in Gooogle-Api Overview
Any Ideas whats wrong?
Thx
Ensure request headers are valid. Server expects Content-Type header, not ContentType.
The documentation (https://developers.google.com/webmaster-tools/search-console-api-original/v3/searchanalytics/query#try-it) suggest requests should be something like:
POST https://www.googleapis.com/webmasters/v3/sites/[SITEURL]/searchAnalytics/query HTTP/1.1
Authorization: Bearer [YOUR_ACCESS_TOKEN]
Accept: application/json
Content-Type: application/json
{}
So seems like main takeaways are:
HTTP POST method must be used
Web.Contents documentation (https://learn.microsoft.com/en-us/powerquery-m/web-contents) suggests including the Content field in the options record to change request from GET to POST.
URL must be valid
You haven't provided your actual URL, so you'll have to validate it for yourself. I would get rid of the trailing ? in your url (as you aren't including a query string -- and even if you were, you should pass them to the Query field of the options record instead of building the query string yourself).
Headers (Authorization, Accept, Content-Type) should be valid/present.
Build your headers in a separation expression. Then pass that expression to the Headers field of the options record. This gives you the chance to review/inspect your headers (to ensure they are as intended).
Body should contain valid JSON to pass to the API method.
Creating valid JSON via manual string concatenation is liable to error. Using Json.FromValue (https://learn.microsoft.com/en-us/powerquery-m/json-fromvalue) seems a better approach.
All in all, your M code might look something like:
let
// Some other code is needed here, in which you define the expression api_token
AccessTokenList = List.Buffer(api_token),
access_token = AccessTokenList{0},
AuthKey = "Bearer " & access_token,
requestHeaders = [Authorization = AuthKey, #"Content-Type" = "application/json", Accept = "application/json"],
parametersToPost = [startDate = "2019-01-01", endDate = "2019-02-02"], // Can include other parameters here e.g. dimensions, as mentioned in Search Console API documentaton.
jsonToPost = Json.FromValue(parametersToPost, TextEncoding.Utf8), // Second argument not required (as is default), but just be explicit until you've got everything working.
url = "https://www.googleapis.com/webmasters/v3/sites/https%3A%2F%2Fxxxxxxxxx.xxx/searchAnalytics/query", // Uri.EscapeDataString function can be use for URL encoding
response = Web.Contents(url, [Headers=requestHeaders, Content=jsonToPost])
in
response
Untested (as I don't have an account or API credentials).

Axios AJAX call nulls parameter

I use Vuejs to create my frontend for my project.
At the creation of one component ('TimeCapsy.vue'), I make an AJAX call to my backend like this:
created: function () {
if (verify.verify_login()) {
let token = this.$cookies.get('jwt_us_cas');
let params = {'jwt': token};
console.log(params);
axios({
method: 'post',
url: dev.HOST+'getuserinfoobject',
params: queryString.stringify(params)
})
.then(response => {
console.log(response.data)
})
}
}
As you can see I use the
this.$cookies.get('jwt_us_cas');
to get the a json web token, that I set on the client at the login.
I use the queryString Library to stringify my parameters for my request.
I also tried it without the queryString.stringify(params) call, but I get the same error, e.g. the parameter still turns into null.
When I look at the console log, where I check the params variable, I get this output:
{jwt: "my token comes here"}
So I can see, that it gets the correct value from the cookie.
But when I check the answer from my backend (PHP), I get this error:
Undefined index: jwt in <b>D:\casb\public\index.php</b> on line <b>52</b>
Of course I know that it means, that jwt is null, but I can't understand why.
As I said, right before I make the call I check the params and it shows the token.
I checked the endpoint with Postman and the token as the jwt parameter and it returned a successfull call with the correct answer.
A correct answer is basically just a nested object with some information in it.
My PHP endpoint is pretty basic too:
Router::add('/getuserinfoobject', function () {
$response['response'] = User::getUserInfoObject($_POST['jwt']);
echo json_encode($response);
}, 'post');
So I guess that right before or in my call it nulls my parameter. But I can't understand how, since I make a lot of requests and never had this problem.
From axios docs
params are the URL parameters to be sent with the request
Which means, you should get the value with PHP $_GET.
Or $_REQUEST (which stores both $_GET, $_POST. Also $_COOKIE).
The other hand, you can use data key as docs says
data is the data to be sent as the request body
Only applicable for request methods PUT, POST, and PATCH
So the value would be available in $_POST
axios({
method: 'post',
url: dev.HOST+'getuserinfoobject',
data: {
jwt: token
}
})

How can I return a response to an AngularJS $http POST to Sinatra?

I am able to successfully POST from AngularJS to my Sinatra route such that I get a "200" Status.
When I inspect in Chrome, I see the request payload as follows:
{"input":"testing"}
But response is empty.
Here is how I am POST-ing:
$http({
method: "POST",
url: "http://floating-beyond-3787.herokuapp.com/angular",
/*url: "https://worker-aws-us-east-1.iron.io/2/projects/542c8609827e3f0005000123/tasks/webhook?code_name=botweb&oauth=LOo5Nc0x0e2GJ838_nbKoheXqM0",*/
data: {input: $scope.newChat}
})
.success(function (data)
{
// $scope.chats.push(data);
$scope.chats.push($scope.newChat)
// if successful then get the value from the cache?
})
.error(function (data)
{
$scope.errors.push(data);
});
};
$scope.newChat = null
Chrome under Request Payload shows it properly -- as above.
When I check the logs in Heroku where I run my Sinatra app, I can't tell if I am properly processing the request payload. And I'm definitely not getting anything in the Response:
post '/angular' do
puts "params: #{params}"
puts params[:input]
puts #json = JSON.parse(request.body.read)
return RestClient.post 'https://worker.io' {:send => params[:input]}
end
My expectation is:
The Sinatra app can receive the payload :input
It can successfully post to my worker on iron.io
It can return something back in the Response to Angular JS along with Success.
Is this possible and if so, how?
Possibly you are running into a case where the request.body has already been read further up the chain before hitting your route.
Try the following
request.body.rewind
request_payload = JSON.parse request.body.read
This is a fairly common issue encountered in Sinatra so if this addresses your issue you may want to put it in a before filter.
before do
request.body.rewind
#request_payload = JSON.parse request.body.read
end
Also the following will not work with a JSON payload.
params[:input]
The params[:field] style works if the Content-Type is application/x-www-form-urlencoded to allow accessing form data in a traditional web application style. It also works to pull params off a parameterized route; something like the following.
post '/angular/:data'
puts params[:data]
# Do whatever processing you need in here
# assume you created a no_errors var to track problems with the
# post
if no_errors
body(json({key: val, key2: val2, keyetc: valetc}))
status 200
else
body(({oh_snap: "An error has occurred!"}).to_json) # json(hash) or hash.to_json should both work here.
status 400 # Replace with your appropriate 4XX error here...
end
end
Something I did recently was to use this last style post 'myroute/:myparam and then Base64 encode a JSON payload on the client side and send it in the URL :myparam slot. This is a bit of a hack and is not something I would recommend as a general practice. I had a client application that could not properly encode the JSON data + headers into the request body; so this was a viable workaround.

How to set the body of a POST request using Ruby Mechanize?

How can you set the body of a POST request using the Ruby Mechanize gem. I know you can do
mechanize.post(url, query, headers)
but I want to set the body of the POST request with a JSON string. Is that possible? So, similar to something like this with jQuery:
$.ajax({
type: 'POST',
url: 'myurl',
data: "{'key1':'value1','key2':'value2'}",
...
});
I don't really like the answer you linked to in your comment because it employs to_json() which is a rails method, and the tags for your question do not indicate that your question pertains to rails. In any case, I think the answer needs some discussion.
Here is the mechanize method:
Mechanize#post(url, query, headers)
...and your stated goal is:
I want to set the body of the POST request
Mechanize#post() allows you to set the body of the request to anything you want, but you also have to consider the question:
What is the server side expecting?
You gave an example of a jquery ajax() request for what you want to do. jquery uses the following default Content-Type header when sending an ajax() request:
application/x-www-form-urlencoded; charset=UTF-8
That tells the server that the body of the post request is going to be written in a specific secret code. Well, it's not much of a secret; it looks like this:
name1=val1&name2=val2
That secret code's name is x-www-form-urlencoded. Because the server is given the name of the secret code in the Content-Type header, the server knows how to read the body of the post request.
In the Mechanize#post() method, the second parameter is 'query', and the mechanize docs say this about the query argument:
The query is specified by either a string, or
a list of key-value pairs represented by a hash, or
an array of arrays.
http://rubydoc.info/gems/mechanize/Mechanize#post-instance_method
If you want to use the secret code named x-www-form-urlencoded in the body of your Mechanize#post() request, then you can provide a Hash with name/value pairs, e.g.
my_hash = {
'data' => '{"key1":"value1","key2":"value2"}'
}
Then you call Mechanize#post() like this:
my_agent.post(
'http://target_site.com',
my_hash,
{'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8'},
)
Then Mechanize will convert the 'query' Hash into a String using the secret code named x-www-form-urlencoded and insert the string into the body of the post request. On the server side, the application that receives the post request can retrieve the json string doing something like this:
json_str = post_variables['data']
You should be aware that there are other secret codes that can be used for the body of a post request. One of them is called json, which is a string formatted using javascript syntax, for example:
'{
"id": 1,
"name": "A green door",
"price": 12.50,
"tags": ["home", "green"]
}'
Note how there are no '=' signs or '&' symbols in the json format--as there are with the x-www-form-urlencoded format, so the json secret code is much different from the x-www-form-urlencoded secret code.
If you want to use the json secret code in the body of your post request, you need to change two things when you call Mechanize#post(url, query, headers):
Provide a String for the 'query' argument.
Tell the server that the body of the post request uses the json secret code.
Like this:
json_str = '{"key1":"value1","key2":"value2"}'
my_agent.post(
'http://target_site.com',
json_str,
{'Content-Type' => 'application/json'},
)
When you pass a String argument for the query parameter, Mechanize doesn't do any processing of the String before inserting the String into the body of the post request. On the server side, the application that receives the post request can retrieve the json string by doing something like this:
json_str = request.body.read
#Then probably:
hash = JSON.parse(json_str)
The one hitch is that the server can ignore the Content-Type header and try to read the body of the post request using a secret code that it has already decided upon. If the body of your post request is not written in the secret code that the server expects, then you will get an error.
Note that the 'data' string you posted isn't valid json because it uses single quotes around the properties and values.

Resources