How to make api requests to sabre / travel api (node js app)? - javascript

I am using the travel api from sabre and cannot make any http requests to any endpoint but 1. I don't understand what I am doing wrong. Im also not sure if I need a token since its just a test developer account and as I understand,I wouldn't need to require token?! if anyone has some experience with the saber api or api requests (maybe my code is wrong for other reasons) any help would be super much appreciated!! Thanks!!
Ps. I am using nodejs.
Api code that works:
var router = require('express').Router();
var SabreDevStudio = require('sabre-dev-studio');
var sabre_dev_studio = new SabreDevStudio({
client_id: 'V1:xxx',
client_secret: 'xxx',
uri: 'https://api.test.sabre.com'
});
var options = {};
router.get('/allcities', function (req, res) {
sabre_dev_studio.get('/v1/lists/supported/shop/themes', options, function (err, data) {
if (err) {
res.status(200).send(err);
} else {
res.status(200).send(data);
}
});
});
Api call (below) to get the lowest fares of picked destination doesn't work. In sabre's documentation I find this:
GET https://api.havail.sabre.com/v1/shop/flights/cheapest/fares/DFW HTTP/1.1
documentation: https://developer.sabre.com/docs/rest_apis/air/search/flights_to/
router.get('/lowestFare', function(req,res){
sabre_dev_studio.get('/v1/shop/flights/cheapest/fares/DFW HTTP/1.1', options, function(err, data){
if (err){
res.status(200).send(err);
}
else{
res.status(200).send(data);
}
})
})
What am I doing wrong?
Thanks!

In order to send requests to SOAP or HTTP sabre API's you need to have spoken to a Sabre account manager and/or signed a contract with Sabre. They will inform you which environments you have access and to which Sabre APIs you have access.
I presume you are only interested in the REST API's, namely the HTTP REST API 'Bargain Finder Max (BFM)', which is sabre's best-in-class low fare search product, used to search for the lowest available priced itineraries based upon a specific date. The 'Bargain Finder Max (BFM)' requires activation, documentation advises you to contact your Sabre Account Representative for assistance.
Firstly click here to obtain API key for test purposes. Register an account.
Obtain your personal 'key' and 'shared secret' after registration.
Click here for the test environment to get familiar with the REST API's.
The cheapest air search endpoint is part of the 'Air Search' HTTP REST API. This is an endpoint which supports HTTP GET requests to find the 20 lowest published fares available for a given destination (destination required; the destination parameter is a 3-letter IATA airport code or city code of the arrival airport e.g. LAX - Los Angeles). Also you submit a pointofsalecountry parameter which is just a 2-letter country code of the point of sale e.g. US.
Using the API explorer invoke a HTTP GET request to the following URI:
https://api.test.sabre.com/v1/shop/flights/cheapest/fares/LAX?pointofsalecountry=US
In terms of your Express.js JavaScript code, you've setup a middleware callback function for GET requests to '/lowestFare' which in turn seems to send a HTTP GET request to the following URL: '/v1/shop/flights/cheapest/fares/DFW HTTP/1.1' this is not a valid URL and doesn't seem to have any query string or request data / options sent with it.
See this GitHub repository with a complete examples for consuming sabre REST API's with Node.js. The readme file here also states: 'Please register at https://developer.sabre.com contact Sabre in order to obtain your own credentials.'

Related

How to verify PayPal Webhooks in node.js?

I found some old answers dealing with PHP and this code example, but I am not sure whether this is outdated now since the repo is archived and I know that generally PayPal moved to an approach that just uses the REST API.
I would love if somebody could give an update here on whats the latest recommendation is and whether the code here from 2015 is outdated now.
/* Copyright 2015-2016 PayPal, Inc. */
"use strict";
var paypal = require('../../../');
require('../../configure');
// Sends the webhook event data to PayPal to verify the webhook event signature is correct and
// the event data came from PayPal.
// Note this sample is only for illustrative purposes. You must have a valid webhook configured with your
// client ID and secret. This sample may not work due to other tests deleting and creating webhooks.
// Normally, you would pass all the HTTP request headers sent in the Webhook Event, but creating a
// JSON object here for the sample.
var certURL = "https://api.sandbox.paypal.com/v1/notifications/certs/CERT-360caa42-fca2a594-a5cafa77";
var transmissionId = "103e3700-8b0c-11e6-8695-6b62a8a99ac4";
var transmissionSignature = "t8hlRk64rpEImZMKqgtp5dlWaT1W8ed/mf8Msos341QInVn3BMQubjAhM/cKiSJtW07VwJvSX7X4+YUmHBrm5BQ+CEkClke4Yf4ouhCK6GWsfs0J8cKkmjI0XxfJpPLgjROEWY3MXorwCtbvrEo5vrRI2+TyLkquBKAlM95LbNWG43lxMu0LHzsSRUBDdt5IP1b2CKqbcEJKGrC78iw+fJEQGagkJAiv3Qvpw8F/8q7FCQAZ3c81mzTvP4ZH3Xk2/nNznEA7eMi3u1EjSpTmLfAb423ytX37Ts0QpmPNgxJe8wnMB/+fvt4xjYH6KNe+bIcYU30hUIe9O8c9UFwKuQ==";
var transmissionTimestamp = "2016-10-05T14:57:40Z";
var headers = {
'paypal-auth-algo': 'SHA256withRSA',
'paypal-cert-url': certURL,
'paypal-transmission-id': transmissionId,
'paypal-transmission-sig': transmissionSignature,
'paypal-transmission-time': transmissionTimestamp
};
// The eventBody parameter is the entire webhook event body.
var eventBody = '{"id":"WH-82L71649W50323023-5WC64761VS637831A","event_version":"1.0","create_time":"2016-10-05T14:57:40Z","resource_type":"sale","event_type":"PAYMENT.SALE.COMPLETED","summary":"Payment completed for $ 6.01 USD","resource":{"id":"8RS6210148826604N","state":"completed","amount":{"total":"6.01","currency":"USD","details":{"subtotal":"3.00","tax":"0.01","shipping":"1.00","handling_fee":"2.00","shipping_discount":"3.00"}},"payment_mode":"INSTANT_TRANSFER","protection_eligibility":"ELIGIBLE","protection_eligibility_type":"ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE","transaction_fee":{"value":"0.47","currency":"USD"},"invoice_number":"","custom":"Hello World!","parent_payment":"PAY-11X29866PC6848407K72RIQA","create_time":"2016-10-05T14:57:18Z","update_time":"2016-10-05T14:57:26Z","links":[{"href":"https://api.sandbox.paypal.com/v1/payments/sale/8RS6210148826604N","rel":"self","method":"GET"},{"href":"https://api.sandbox.paypal.com/v1/payments/sale/8RS6210148826604N/refund","rel":"refund","method":"POST"},{"href":"https://api.sandbox.paypal.com/v1/payments/payment/PAY-11X29866PC6848407K72RIQA","rel":"parent_payment","method":"GET"}]},"links":[{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-82L71649W50323023-5WC64761VS637831A","rel":"self","method":"GET"},{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-82L71649W50323023-5WC64761VS637831A/resend","rel":"resend","method":"POST"}]}';
// The webhookId is the ID of the configured webhook (can find this in the PayPal Developer Dashboard or
// by doing a paypal.webhook.list()
var webhookId = "3TR748995U920805P";
paypal.notification.webhookEvent.verify(headers, eventBody, webhookId, function (error, response) {
if (error) {
console.log(error);
throw error;
} else {
console.log(response);
// Verification status must be SUCCESS
if (response.verification_status === "SUCCESS") {
console.log("It was a success.");
} else {
console.log("It was a failed verification");
}
}
});
Those SDKs are abstractions for the REST API but are no longer being maintained, so it is best not to use them.
There are two possible ways to verify Webhooks
Posting the message back to PayPal with the verify webhook sygnature REST API call. You'll need to use a client_id and secret get an access token first, same as all other REST API calls.
Verifying the cryptographic signature yourself (Java pseudocode here).
For either method, the "webhookId" -- as opposed to each webhook event id -- is 17 alphadigits and for security (anti-spoof) reasons not part of the Webhook message itself (you get it when registering for webhooks or reviewing existing subscribed hooks in the REST app config)
As it can sometimes be a point of confusion, it's worth mentioning that verifying webhooks is for your own information -- to confirm the message did in fact originate from PayPal, and not some other (malicious) actor.
But for PayPal itself to consider the webhook message successfully delivered (and not keep retrying), all that needs to happen is for the listener URL it's posted to to respond with an HTTP 200 OK status. That concludes the webhook message delivery.

Instagram follower count endpoint in 2020

I have been struggling with the Instagram APIs and can't find a solution to fetch the follower count a user on Instagram. I too have APIs where I fetch user's media and username using Instagram basic display Graph API, but I can see nowhere how to get the follower count.
I tried the https://www.instagram.com/<username>/?__a=1 url as well but it worked on my local system but when I pushed this on server it stopped working after a while, similarly I also tried
request.get(url, function(err, response, body){
if(response.body.indexOf(("meta property=\"og:description\" content=\"")) != -1){
console.log("followers:", response.body.split("meta property=\"og:description\" content=\"")[1].split("Followers")[0])
}
});
This didn't work either on my server.
This will give you the followers count from the endpoint you have mentioned.
const axios = require('axios').default;
axios.get("https://www.instagram.com/username/?__a=1")
.then(res=>{
console.log("res="+JSON.stringify(res.data.graphql.user.edge_followed_by.count));
})
.catch(err=>{
console.log("error:\n"+err);
})
.finally(()=>
console.log("end"));
Check out this website to learn how to make request with axios
Here we make a simple get request to the server and it return an Object (res.data). We then simply access the required data.

Update activity from browser in GetStream io

I'm trying to integrate getstream.io into our framework to deliver activities to subscribers and also allow clients to filter activities. GetStream doesn't allow filter on activities, So I had to create new group and link the activities through to property. Is this the proper way to do filter?
We need to allow clients to update the activity with bookmarks/comments from browser. I'm having issue here.
var activity = {
actor: 'org_1:user_1',
verb: 'start',
object: 'site',
time: '2018-04-18T11:19:04.263000',
foreign_id: 'site_id:1',
comment: 'start properly'
}
client.updateActivities([activity]).then(
function(res) {
console.log('res:',res)
},
function(err) {
console.log('err:',err)
}
);
The code gives following error in browser but works when executed from the node.js server
getstream.js:2107 Uncaught TypeError: jwt.sign is not a function
at Object.exports.JWTScopeToken (getstream.js:2107)
at StreamClient.updateActivities (getstream.js:816)
at <anonymous>:8:8
I pass the feed token that is generated in the node.js server to client to make connection to the feed group.
Should I add JWT to the updateActivities request, If so what should the payload contain and how do I add a token to the request?
True. JWT is only included as a back-end dependency and not compiled in your front-end assets, probably.
Updating activities is not an operation to be done on the front-end side of your application. The only recommended operation on the front-end is getting more activities with a read-only token and client.feed(...).getActivities().
Cheers

Unable to query Google Search Console API using a Service Account

I need to retrieve some data from Google Search Console (Webmaster Tools) using a service account.
So far I've been able to retrieve an access_token for the service account which I need to append to the url of the request. The problem is that I can't find a way to do so, this is the code i'm using:
function retrieveSearchesByQuery(token)
{
gapi.client.webmasters.searchanalytics.query(
{
'access_token': token,
'siteUrl': 'http://www.WEBSITE.com',
'fields': 'responseAggregationType,rows',
'resource': {
'startDate': formatDate(cSDate),
'endDate': formatDate(cEDate),
'dimensions': [
'date'
]
}
})
.then(function(response) {
console.log(response);
})
.then(null, function(err) {
console.log(err);
});
}
This is the url called by the function:
https://content.googleapis.com/webmasters/v3/sites/http%3A%2F%2Fwww.WEBSITE.com/searchAnalytics/query?fields=responseAggregationType%2Crows&alt=json"
Instead it should be something like this:
https://content.googleapis.com/webmasters/v3/sites/http%3A%2F%2Fwww.WEBSITE.com/searchAnalytics/query?fields=responseAggregationType%2Crows&alt=json&access_token=XXX"
The gapi.client.webmasters.searchanalytics.query doesn't recognize 'access_token' as a valid key thus it doesn't append it to the url and that's why I get a 401 Unauthorized as response.
If I use 'key' instead of 'access_token' the parameter gets appended to the url but 'key' is used for OAuth2 authentication so the service account token I pass is not valid.
Does anyone have a solution or a workaround for this?
If your application requests private data, the request must be authorized by an authenticated user who has access to that data. As specified in the documentation of the Search Console API, your application must use OAuth 2.0 to authorize requests. No other authorization protocols are supported.
If you application is correctly configured, when using the Google API, an authenticated request looks exactly like an unauthenticated request. As stated in the documentation, if the application has received an OAuth 2.0 token, the JavaScript client library includes it in the request automatically.
You're mentioning that you have retrieved an access_token, if correctly received, the API client will automatically send this token for you, you don't have to append it yourself.
A very basic workflow to authenticate and once authenticated, send a request would looks like the following code. The Search Console API can use the following scopes: https://www.googleapis.com/auth/webmasters and https://www.googleapis.com/auth/webmasters.readonly.
var clientId = 'YOUR CLIENT ID';
var apiKey = 'YOUR API KEY';
var scopes = 'https://www.googleapis.com/auth/webmasters';
function auth() {
// Set the API key.
gapi.client.setApiKey(apiKey);
// Start the auth process using our client ID & the required scopes.
gapi.auth2.init({
client_id: clientId,
scope: scopes
})
.then(function () {
// We're authenticated, let's go...
// Load the webmasters API, then query the API
gapi.client.load('webmasters', 'v3')
.then(retrieveSearchesByQuery);
});
}
// Load the API client and auth library
gapi.load('client:auth2', auth);
At this point, your retrieveSearchesByQuery function will need to be modified since it doesn't need to get a token by argument anymore in order to pass it in the query. The JavaScript client library should include it in the request automatically.
You can also use the API Explorer to check what parameters are supported for a specific query and check the associated request.
If you need to use an externally generated access token, which should be the case with a Service Account, you need to use the gapi.auth.setToken method to sets the OAuth 2.0 token object yourself for the application:
gapi.auth.setToken(token_Object);

Nodejs, Express. Is there a way to store/get what POST params are required in an endpoint to show to the client?

I'm writing some test page to debug my API and expose it neatly.
Using Express app.routes I can get a neat list of all the endpoints my application implements, so I can show to the users the list of possible POST requests.
However, most of them require some POST parameters, which the server obtains from the requests in this way, for example (/api/ping requires a "ping" POST parameter):
app.post("/api/ping", function(req, res) //
{
var ping = req.param('ping');
if( ping ) {
res.out.message = "Pong";
} else {
res.out.message = "Ping missing";
}
return exports.respond(res);
});
I noticed that app.routes has a "keys" and a "params" keys in the endpoints list, but I think this seems to be used only for parameters that are in the path (for example "userid" as parameter when someone requests for the "/user/:userid" path). I believe express calls these stored parameters "pre-conditions".
Is there any way to add preconditions like these to express app for POST parameters so that they are also shown in the app.routes object and I can display neatly which parameters are required for which endpoint?

Categories