Using Postman I am able to successfully connect to my login server and receive an access token.
I would like to replicate this call within my CN1 code
This is my postman script:
cURL
curl --location --request POST 'https://myloginserver.com/accounts/login' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=myusername' \
--data-urlencode 'password=mypassword'
Java
Unirest.setTimeouts(0, 0);
HttpResponse<String> response = Unirest.post("https://myloginserver/accounts/login")
.header("Content-Type", "application/x-www-form-urlencoded")
.field("username", "myusername")
.field("password", "mypassword")
.asString();
And this is my CN1 code
ConnectionRequest getTokenConnReq = null;
try {
getTokenConnReq = new ConnectionRequest("https://myloginserver.com/accounts/login");
getTokenConnReq.setPost(true);
getTokenConnReq.addRequestHeader("Content-Type","application/x-www-form-urlencoded");
getTokenConnReq.setHttpMethod("POST");
getTokenConnReq.setRequestBody("username=myusername&password=mypassword");
getTokenConnReq.setFailSilently(true);
getTokenConnReq.setCookiesEnabled(false);
NetworkManager.getInstance().addToQueueAndWait(getTokenConnReq);
result = new JSONParser().parseJSON(new InputStreamReader(new ByteArrayInputStream(getTokenConnReq.getResponseData()), DocumentInfo.ENCODING_UTF8));
return result;
} catch (Exception err22) {
System.err.println(err22);
return null;
}
Unfortunately my responses vary from the 300's to the 400's depending on how I tweak the code.
Please advise how I get this working in CN1?
(I think that it may have something to do with Cookies as I do see Postman adding cookies to the call in the background)
Any help will be appreciated.
Thanks
I would suggest using the Rest API which is much easier to use for these sort of calls:
Rest.post("https://myloginserver.com/accounts/login")
.contentType("application/x-www-form-urlencoded")
.queryParam("username", username)
.queryParam("password", password)
.fetchAsJsonMap(result -> {
Map parsedJson = result.getResponseData();
// key/value pairs from the resulting JSON
});
Related
I am trying to make a call to the Petfinder API from codename one. It requires oAuth authorization. Right now I am able to get access to the API from terminal, but I do not know how to call it from codename one which uses Java. Right now I'm able to pull data from APIs that don't need oAuth but need a key.
From terminal it looks like this:
curl -d "grant_type=client_credentials&client_id={CLIENT-ID}&client_secret={CLIENT-SECRET}" https://api.petfinder.com/v2/oauth2/token
{"token_type": "Bearer","expires_in": 3600,"access_token": "{my access token}"
}
curl -H "Authorization: Bearer {my access token}" GET https://api.petfinder.com/v2/animals?type=dog&page=2
You can use something like this. I haven't tested it though so debugging will be required:
Rest.post("https://api.petfinder.com/v2/oauth2/token").
queryParam("grant_type", "client_credentials").
queryParam("client_id", clientId).
queryParam("client_secret", clientSecret).
fetchAsJsonMap(response -> {
// data is already parsed to Map here
if(response.getResponseData() != null) {
accessToken = (String)response.getResponseData().get("access_token");
// set the auth header for all future requests in this session
addDefaultHeader("Authorization", "Bearer " + accessToken);
}
});
Notice that the code assumes a static import of the CN class exists. You could also store the token into Prefrences and load it dynamically/set it globally as I did here which is the more complete example.
Im trying to write a code that checks for twitch channels if they exist or not, i tried using request but the statusCode its allways 200
request(`https://www.twitch.tv/${args[1]}`, function(error, response, body){
console.log('statusCode', response.statusCode)
edit: tried using twith api kraken but doesn't seem to work, if i use existing channels its the same response.
request('https://api.twitch.tv/kraken/channels/' + args[1], function(channel, response) {
console.log(channel)
if (channel == null) {
return console.log("doesnt exists")
} else {
return console.log("Exists")
}
The status code of an HTML request is the status code of the request, not what was requested. 200 means that the request went through fine without problems.
You could either look through the response and body of the request or try the Kraken, which I'm not very familiar with. Have you looked through the docs?
The docs about this part use this syntax:
curl -H 'Accept: application/vnd.twitchtv.v5+json' \
-H 'Client-ID: uo6dggojyb8d6soh92zknwmi5ej1q2' \
-X GET 'https://api.twitch.tv/kraken/channels/44322889'
Your syntax probably works fine. The issue is probably that the response isn't null, but rather something like an empty object.
What response ARE you getting? What is your console output if you use console.log(channel);
console.log(response);
I hope I could help a bit.
With Solr 6.3.0, in cloud mode, and 3 external zookeepers as cluster, and use solrJ as client.
A: Without authentication
Before enabling authentication, I use following code to add/update document:
CloudSolrClient client = cloudClientBuilder.build();
UpdateResponse resp = client.add(doc, 5000);
client.commit();
client.close();
return resp;
It works well, the new document is in searching result immediately.
B: With authentication enabled
Then I enabled basic authentication plugin and rule-based authorization plugin (and SSL if that matters).
In order to set credential information, the code is refactored as following:
// create request,
UpdateRequest req = new UpdateRequest();
// add doc to request,
req.add(doc, 5000);
// set credential,
req.setBasicAuthCredentials(user, password);
// create client,
CloudSolrClient client = cloudClientBuilder.build();
client.setDefaultCollection(ConfigUtil.getProp(ConfigUtil.KEY_SOLR_CORE));
// do request & get response,
UpdateResponse resp = req.process(client);
client.commit();
client.close();
Then it will get error similar as this:
Error 401 require authentication, require authentication.
When debugging, the error occurs at line client.commit();.
Try with curl
I use curl to make an update:
curl -k --user solr:password "https://localhost:8983/solr/corexxx/update?wt=json&indent=true&commit=true" -d '[{"id":"20041", "name":"xxx 41", "location":"xxx", "description":"xxx"}]'
It committed successfully ! And, the updates are visible in searching result immediately.
My guess
Since curl works well, I guess solr cloud itself works fine.
Thus the issue is due to the code from B which is based on SolrJ.
Questions:
Why code B get HTTP 401 error? How can I fix it?
Could I use code from A, and still able to provide credential information,if yes, then how?
Thanks.
You should change client.commit() for req.commit(client, ConfigUtil.getProp(ConfigUtil.KEY_SOLR_CORE)), the credentials are setted in the UpdateRequest.
It worked like this:
SolrClient client = new HttpSolrClient.Builder(urlString).build();
UpdateRequest up = new UpdateRequest();
up.setBasicAuthCredentials(user, pass);
up.add(doc1);
up.process(client, core);
up.commit(client, core);
client.close();
I am new in quickbooks API implementation, I am always getting one error No apptoken detected; errorCode=003102; statusCode=401 when I am doing API call for customer add etc.
I am giving my steps, please look over that.
My sandbox info like that
Consumer Key: qyprdffbBBInX4a82jG73Mreyy96tC
Consumer Secret: IgpJzJrYvb9FmmdB7A0ECDGHG62Cp7dqVWjfMTvU
Access Token: qyprdlo3WrK0KhGZMTeA857AuKiVy2eaAmpXsRvG3jycYaMQ
Access Token Secret: TdPGpcUI8AiAdWFiCyb8jAAygH16bzU7VRGaspx4
I am Using PHP.
First I have generated oauth_signature.
$URL =
rawurlencode('https://sandbox-quickbooks.api.intuit.com/v3/company/408554291/customer');
$method = 'POST'; $parameter =
rawurlencode('oauth_consumer_key=qyprdffbBBInX4a82jG73Mreyy96tC&oauth_nonce=BlyqIBbv3R4T0P4qglAv1RjoYisMZk1449659733&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1449659733&oauth_token=qyprdlo3WrK0KhGZMTeA857AuKiVy2eaAmpXsRvG3jycYaMQ&oauth_version=1.0');
$ukey =
rawurlencode('IgpJzJrYvb9FmmdB7A0ECDGHG62Cp7dqVWjfMTvU').'&'.rawurlencode('TdPGpcUI8AiAdWFiCyb8jAAygH16bzU7VRGaspx4');
$hasmac = hash_hmac("sha1", $BaseURL,$ukey,1);
and My oauth_signature is jZ8JhECy/e0kpPbUdZp/o/EUC7U=
When i call API with this oauth_signature, i am getting Error 'No apptoken detected; errorCode=003102; statusCode=401'
My CURL call like this
curl -X POST -H 'Content-Type: application/json, Authorization: OAuth
oauth_token=qyprdlo3WrK0KhGZMTeA857AuKiVy2eaAmpXsRvG3jycYaMQ,oauth_consumer_key=qyprdffbBBInX4a82jG73Mreyy96tC,oauth_signature_method=HMAC-SHA1,oauth_timestamp=1449659733,oauth_version=1.0,oauth_nonce=BlyqIBbv3R4T0P4qglAv1RjoYisMZk1449659733,oauth_signature=jZ8JhECy/e0kpPbUdZp/o/EUC7U='
-d '{"data": [{"BillAddr":{"Line1":"86 A Topsia","City":"Kolkata","Country":"India","CountrySubDivisionCode":"WB","PostalCode":"700102"},"Title":"Mr.","GivenName":"ApurbaK","MiddleName":"Kumar","FamilyName":"ApurbaK","PrimaryPhone":{"FreeFormNumber":"564545465"},"PrimaryEmailAddr":{"Address":"apurbahazra12#navsoft.in"}}]}'
'https://sandbox-quickbooks.api.intuit.com/v3/company/408554291/customer'
Please look over that.
Thanks,
Apurba
Firstly, you don't want to be doing this yourself -- use a library. OAuth is complex, and implementing it yourself is going to be a hairy process, rife with errors.
Go grab a library:
https://github.com/consolibyte/quickbooks-php
Follow the quick-start guide linked there, and benefit from the examples:
https://github.com/consolibyte/quickbooks-php/tree/master/docs/partner_platform/example_app_ipp_v3
With that said, if you do decide to write it yourself, make sure you follow the OAuth spec:
https://www.rfc-editor.org/rfc/rfc5849
So far, the issues I immediately see with your implementation are:
You can't hard-code the timestamp like this: &oauth_timestamp=1449659733 The timestamp should be ever-changing, and set to the currenty timestamp.
You can't hard-code a nonce like this: &oauth_nonce=BlyqIBbv3R4T0P4qglAv1RjoYisMZk1449659733 The nonce has to change with every single request so this is going to fail after your first request.
You haven't normalized your request parameters / sorted them, per the spec.
This is the incorrect way to specify multiple headers with cURL: -H 'Content-Type: application/json, Authorization: OAuth .... Please see the cURL docs: http://curl.haxx.se/docs/manpage.html#-H
In the code you posted, you haven't actually set $BaseURL anywhere, so right now you're signing an empty string (unless you forgot to paste some code somewhere?)
What is $ukey set to? It doesn't appear to be defined in your code anywhere (did you forget to paste some code in?)
I need to get the last 100 messages in the INBOX (headers only). For that I'm currently using the IMAP extension to search and then fetch the messages. This is done with two requests (SEARCH and then UID FETCH).
What's the Gmail API equivalent to fetching multiple messages in one request?
All I could find is a batch API, which seems way more cumbersome (composing a long list of messages:get requests wrapped in plain HTTP code).
It's pretty much the same in the Gmail API as in IMAP. Two requests: first is messages.list to get the message ids. Then a (batched) message.get to retrieve the ones you want. Depending on what language you're using the client libraries may help with the batch request construction.
A batch request is a single standard HTTP request containing multiple Google Cloud Storage JSON API calls, using the multipart/mixed content type. Within that main HTTP request, each of the parts contains a nested HTTP request.
From: https://developers.google.com/storage/docs/json_api/v1/how-tos/batch
It's really not that hard, took me about an hour to figure it out in python even without the python client libraries (just using httplib and mimelib).
Here's a partial code snippet of doing it, again with direct python. Hopefully it makes it clear that's there's not too much involved:
msg_ids = [msg['id'] for msg in body['messages']]
headers['Content-Type'] = 'multipart/mixed; boundary=%s' % self.BOUNDARY
post_body = []
for msg_id in msg_ids:
post_body.append(
"--%s\n"
"Content-Type: application/http\n\n"
"GET /gmail/v1/users/me/messages/%s?format=raw\n"
% (self.BOUNDARY, msg_id))
post_body.append("--%s--\n" % self.BOUNDARY)
post = '\n'.join(post_body)
(headers, body) = _conn.request(
SERVER_URL + '/batch',
method='POST', body=post, headers=headers)
Great reply!
If somebody wants to use a raw function in php to make batch requests for fetching emails corresponding to message ids, please feel free to use mine.
function perform_batch_operation($auth_token, $gmail_api_key, $email_id, $message_ids, $BOUNDARY = "gmail_data_boundary"){
$post_body = "";
foreach ($message_ids as $message_id) {
$post_body .= "--$BOUNDARY\n";
$post_body .= "Content-Type: application/http\n\n";
$post_body .= 'GET https://www.googleapis.com/gmail/v1/users/'.$email_id.
'/messages/'.$message_id.'?metadataHeaders=From&metadataHeaders=Date&format=metadata&key='.urlencode($gmail_api_key)."\n\n";
}
$post_body .= "--$BOUNDARY--\n";
$headers = [ 'Content-type: multipart/mixed; boundary='.$BOUNDARY, 'Authorization: OAuth '.$auth_token ];
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL, 'https://www.googleapis.com/batch' );
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl,CURLOPT_CONNECTTIMEOUT , 60 ) ;
curl_setopt($curl, CURLOPT_TIMEOUT, 60 ) ;
curl_setopt($curl,CURLOPT_POSTFIELDS , $post_body);
curl_setopt($curl, CURLOPT_RETURNTRANSFER,TRUE);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,0);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
$tmp_response = curl_exec($curl);
curl_close($curl);
return $tmp_response;
}
FYI the above function gets just the headers for the emails, in particular the From and Date fields, please adjust according to the api documentation https://developers.google.com/gmail/api/v1/reference/users/messages/get
In addition to MaK you can perform multiple batch requests using the google-api-php-client and Google_Http_Batch()
$optParams = [];
$optParams['maxResults'] = 5;
$optParams['labelIds'] = 'INBOX'; // Only show messages in Inbox
$optParams['q'] = 'subject:hello'; // search for hello in subject
$messages = $service->users_messages->listUsersMessages($email_id,$optParams);
$list = $messages->getMessages();
$client->setUseBatch(true);
$batch = new Google_Http_Batch($client);
foreach($list as $message_data){
$message_id = $message_data->getId();
$optParams = array('format' => 'full');
$request = $service->users_messages->get($email_id,$message_id,$optParams);
$batch->add($request, $message_id);
}
$results = $batch->execute();
here is the python version, using the official google api client. Note that I did not use the callback here, because I need to handle the responses in a synchronous way.
from apiclient.http import BatchHttpRequest
import json
batch = BatchHttpRequest()
#assume we got messages from Gmail query API
for message in messages:
batch.add(service.users().messages().get(userId='me', id=message['id'],
format='raw'))
batch.execute()
for request_id in batch._order:
resp, content = batch._responses[request_id]
message = json.loads(content)
#handle your message here, like a regular email object
solution from Walty Yeung is worked partially for my use case.
if you guys tried the code and nothing happens use this batch
batch = service.new_batch_http_request()