diff --git a/.gitignore b/.gitignore index f356293..e937057 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ logs results npm-debug.log + +node_modules/ +test/ \ No newline at end of file diff --git a/README.md b/README.md index 24c7bf0..33f2daa 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,64 @@ -[![NPM](https://nodei.co/npm/yfb-expedia.png)](https://nodei.co/npm/yfb-expedia/) +[![NPM](https://nodei.co/npm/node-expedia-api.png)](https://nodei.co/npm/node-expedia-api/) This module is a fork of [expedia](https://www.npmjs.com/package/expedia) module that is not maintained anymore. -## Expedia API +# Expedia API -Small client interface for the [Expedia EAN api](http://developer.ean.com/). Provides an interface for the following methods: -- **Hotel List** Retrieve a list of hotels by location or a list of specific hotel ids -- **Hotel Information** Retrieve detailed information about a hotel from a hotel id -- **Room Availability** Retrieve all available rooms for a specific hotel that accommodate the provided guest count and any other criteria. -- **Room Images** Retrieve a list of room images for a specific hotelId organized by room type -- **Payment Types** Retrieve credit card types compatible with current request settings -- **Book Reservation** Request a reservation for the specified room(s). -- **Itinerary Request** Retrieve an existing itinerary's status and details, confirm the status of a previously requested booking, or retrieve a list of itineraries from a specified date span. -- **Cancel Reservation** Cancel an existing reservation for a single room. -- **Ping Request** Send a ping request to expedia API servers to determine if service is available in the event of a suspected outage or ISP issue, or to obtain EAN's Unix server time when troubleshooting issues with signature authentication. -- **Geo Functions** Obtain location data such as a specific destinationId, latitude/longitude coordinates, and the number of active properties available within the location. +Small client interface for the [Expedia EAN api](http://developer.ean.com/).
+Provides an interface for the following methods: -## Installation +- **Hotel List** Retrieve a list of hotels by location or a list of specific hotel ids +- **Hotel Information** Retrieve detailed information about a hotel from a hotel id +- **Room Availability** Retrieve all available rooms for a specific hotel that accommodate the provided guest count and any other criteria. +- **Room Images** Retrieve a list of room images for a specific hotelId organized by room type +- **Payment Types** Retrieve credit card types compatible with current request settings +- **Book Reservation** Request a reservation for the specified room(s). +- **Itinerary Request** Retrieve an existing itinerary's status and details, confirm the status of a previously requested booking, or retrieve a list of itineraries from a specified date span. +- **Cancel Reservation** Cancel an existing reservation for a single room. +- **Ping Request** Send a ping request to expedia API servers to determine if service is available in the event of a suspected outage or ISP issue, or to obtain EAN's Unix server time when troubleshooting issues with signature authentication. +- **Geo Functions** Obtain location data such as a specific destinationId, latitude/longitude coordinates, and the number of active properties available within the location. -Install with npm: -```npm install yfb-expedia``` +# Installation -## Initialization +Install with npm: -Usage requires an Expedia Api key and CID. For development use you can use the CID 55505. You can obtain your api key from the [Expedia EAN api documentation](http://developer.ean.com/). +``` +npm install --save node-expedia-api +``` + +# Initialization + +Usage requires an Expedia Api key and CID. For development use you can use the CID 55505\. You can obtain your api key from the [Expedia EAN api documentation](http://developer.ean.com/). ```javascript - var options = { - cid : "YOUR CID", - apiKey : "YOUR EAN API KEY", - locale : "en_US", // optional defaults to en_US - currencyCode :"USD" // optional defaults to USD +var options = { + cid: 'YOUR CID', + apiKey: 'YOUR EAN API KEY', + secret: 'YOUR SECRET', + locale: 'en_US', // optional defaults to en_US + currencyCode: 'USD' // optional defaults to USD }; -var expedia = require("expedia")(options, sendAsREST); +var expedia = require("expedia")(options); ``` -sendAsREST parameter allows you to choose if you want to send your data in XML or REST format (forgetting the param sets format to XML). -Note that usage of XML is going to be deprecated by Expedia. -## Usage +# Usage -Expedia requires that you pass in a customer ip, unique session identifier, and browser agent. The remaining parameters are defined in the [Expedia EAN api documentation](http://developer.ean.com/). Please see the example directory for more options. +Expedia requires that you pass in a customer ip, unique session identifier, and browser agent. The remaining parameters are defined in the [Expedia EAN api documentation](http://developer.ean.com/). Please see the example directory for more options. ```javascript var options = { - "customerSessionId" : "thisisauniqueID", - "customerIpAddress" : "127.0.0.1", - "customerUserAgent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", - "LocationInfoRequest": { - "locale": "en_US", - "destinationString": "Seattle, WA" - } + customerSessionId: 'thisisauniqueID', + customerIpAddress: '127.0.0.1', + customerUserAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)', + city: 'Bellevue', + stateProvinceCode: 'WA', + countryCode: 'US', + postalCode: '98004' }; -expedia.geoSearch(options, function(err, res){ - if(err)throw new Error(err); +expedia.geoSearch(options, function(err, res) { + if (err) { throw new Error(err); } console.log(res); }); ``` diff --git a/examples/geo-search.js b/examples/geo-search.js index 36adfbf..d55c8cd 100644 --- a/examples/geo-search.js +++ b/examples/geo-search.js @@ -1,19 +1,19 @@ -var expedia = require("../lib/expedia")({apiKey:"cbrzfta369qwyrm9t5b8y8kf",cid:"55505"}); +var expedia = require("../lib/expedia")({ + apiKey: "cbrzfta369qwyrm9t5b8y8kf", + cid: "55505" +}); // Takes a search string as an argument, and returns location information available for performing a hotel search // a complete list of options is available at http://developer.ean.com/docs/geo-functions/ var options = { - "customerSessionId" : "thisisauniqueID", - "customerIpAddress" : "127.0.0.1", - "customerUserAgent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", - "LocationInfoRequest": { + "customerSessionId": "thisisauniqueID", + "customerIpAddress": "127.0.0.1", + "customerUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", "locale": "en_US", "destinationString": "Seattle, WA" - } }; -expedia.geoSearch(options, function(err, res){ - if(err)throw new Error(err); +expedia.geoSearch(options, function(err, res) { + if (err) throw new Error(err); console.log(res); }); - diff --git a/examples/hotel-accepted-payments.js b/examples/hotel-accepted-payments.js index da4d3cd..02fd2ea 100644 --- a/examples/hotel-accepted-payments.js +++ b/examples/hotel-accepted-payments.js @@ -1,19 +1,19 @@ -var expedia = require("../lib/expedia")({apiKey:"cbrzfta369qwyrm9t5b8y8kf",cid:"55505"}); +var expedia = require("../lib/expedia")({ + apiKey: "cbrzfta369qwyrm9t5b8y8kf", + cid: "55505" +}); -// a complete list of options is available at http://developer.ean.com/docs/payment-types/ +// a complete list of options is available at http://developer.ean.com/docs/payment-types/ var options = { - "customerSessionId" : "thisisauniqueID", - "customerIpAddress" : "127.0.0.1", - "customerUserAgent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", - "HotelPaymentRequest": { + "customerSessionId": "thisisauniqueID", + "customerIpAddress": "127.0.0.1", + "customerUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", "hotelId": "122212", "supplierType": "E", "rateType": "MerchantStandard" - } }; -expedia.hotels.acceptedPayments(options, function(err, res){ - if(err)throw new Error(err); +expedia.hotels.acceptedPayments(options, function(err, res) { + if (err) throw new Error(err); console.log(res); }); - diff --git a/examples/hotel-availability.js b/examples/hotel-availability.js index 6279ca8..94d9665 100644 --- a/examples/hotel-availability.js +++ b/examples/hotel-availability.js @@ -1,23 +1,25 @@ -var expedia = require("../lib/expedia")({apiKey:"cbrzfta369qwyrm9t5b8y8kf",cid:"55505"}); +var expedia = require("../lib/expedia")({ + apiKey: "cbrzfta369qwyrm9t5b8y8kf", + cid: "55505" +}); // a complete list of options is available at http://developer.ean.com/docs/room-avail/ var options = { - "customerSessionId" : "thisisauniqueID", - "customerIpAddress" : "127.0.0.1", - "customerUserAgent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", - "HotelRoomAvailabilityRequest": { + "customerSessionId": "thisisauniqueID", + "customerIpAddress": "127.0.0.1", + "customerUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", "hotelId": "106347", "arrivalDate": "9/30/2013", "departureDate": "10/2/2013", "includeDetails": "true", "RoomGroup": { - "Room": { "numberOfAdults": "2" } + "Room": { + "numberOfAdults": "2" + } } - } }; -expedia.hotels.availability(options, function(err, res){ - if(err)throw new Error(err); +expedia.hotels.availability(options, function(err, res) { + if (err) throw new Error(err); console.log(res); }); - diff --git a/examples/hotel-info.js b/examples/hotel-info.js index ac89454..d107f71 100644 --- a/examples/hotel-info.js +++ b/examples/hotel-info.js @@ -1,18 +1,18 @@ -var expedia = require("../lib/expedia")({apiKey:"cbrzfta369qwyrm9t5b8y8kf",cid:"55505"}); +var expedia = require("../lib/expedia")({ + apiKey: "cbrzfta369qwyrm9t5b8y8kf", + cid: "55505" +}); // a complete list of options is available at http://developer.ean.com/docs/hotel-info/ var options = { - "customerSessionId" : "thisisauniqueID", - "customerIpAddress" : "127.0.0.1", - "customerUserAgent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", - "HotelInformationRequest": { + "customerSessionId": "thisisauniqueID", + "customerIpAddress": "127.0.0.1", + "customerUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", "hotelId": "122212", "options": "0" - } }; -expedia.hotels.info(options, function(err, res){ - if(err)throw new Error(err); +expedia.hotels.info(options, function(err, res) { + if (err) throw new Error(err); console.log(res); }); - diff --git a/examples/hotel-list.js b/examples/hotel-list.js index fd286db..4fa0fe0 100644 --- a/examples/hotel-list.js +++ b/examples/hotel-list.js @@ -1,25 +1,27 @@ -var expedia = require("../lib/expedia")({apiKey:"cbrzfta369qwyrm9t5b8y8kf",cid:"55505"}); +var expedia = require("../lib/expedia")({ + apiKey: "cbrzfta369qwyrm9t5b8y8kf", + cid: "55505" +}); // a complete list of options is available at http://developer.ean.com/docs/hotel-list/ var options = { - "customerSessionId" : "thisisauniqueID", - "customerIpAddress" : "127.0.0.1", - "customerUserAgent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", - "HotelListRequest": { + "customerSessionId": "thisisauniqueID", + "customerIpAddress": "127.0.0.1", + "customerUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", "city": "Seattle", "stateProvinceCode": "WA", "countryCode": "US", "arrivalDate": "9/30/2013", "departureDate": "10/2/2013", "RoomGroup": { - "Room": { "numberOfAdults": "2" } + "Room": { + "numberOfAdults": "2" + } }, "numberOfResults": "25" - } } -expedia.hotels.list(options, function(err, res){ - if(err)throw new Error(err); +expedia.hotels.list(options, function(err, res) { + if (err) throw new Error(err); console.log(res); }); - diff --git a/examples/hotel-room-images.js b/examples/hotel-room-images.js index 99fd924..3ff8450 100644 --- a/examples/hotel-room-images.js +++ b/examples/hotel-room-images.js @@ -1,17 +1,19 @@ -var expedia = require("../lib/expedia")({apiKey:"cbrzfta369qwyrm9t5b8y8kf",cid:"55505"}); +var expedia = require("../lib/expedia")({ + apiKey: "cbrzfta369qwyrm9t5b8y8kf", + cid: "55505" +}); // a complete list of options is available at http://developer.ean.com/docs/room-images/ var options = { - "customerSessionId" : "thisisauniqueID", - "customerIpAddress" : "127.0.0.1", - "customerUserAgent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", - "HotelRoomImagesRequest": { - "hotelId": "106347", - } + "customerSessionId": "thisisauniqueID", + "customerIpAddress": "127.0.0.1", + "customerUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", + "HotelRoomImagesRequest": { + "hotelId": "106347", + } }; -expedia.hotels.roomImages(options, function(err, res){ - if(err)throw new Error(err); +expedia.hotels.roomImages(options, function(err, res) { + if (err) throw new Error(err); console.log(res); }); - diff --git a/examples/ping.js b/examples/ping.js index 6b1251c..e91f287 100644 --- a/examples/ping.js +++ b/examples/ping.js @@ -1,15 +1,19 @@ -var expedia = require("../lib/expedia")({apiKey:"cbrzfta369qwyrm9t5b8y8kf",cid:"55505"}); +var expedia = require("../lib/expedia")({ + apiKey: "cbrzfta369qwyrm9t5b8y8kf", + cid: "55505" +}); // Simple echo server, response should match input var options = { - "customerSessionId" : "thisisauniqueID", - "customerIpAddress" : "127.0.0.1", - "customerUserAgent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", - "PingRequest": { "echo": "This message should be echoed back to you." } + "customerSessionId": "thisisauniqueID", + "customerIpAddress": "127.0.0.1", + "customerUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", + "PingRequest": { + "echo": "This message should be echoed back to you." + } }; -expedia.ping(options, function(err, res){ - if(err)throw new Error(err); +expedia.ping(options, function(err, res) { + if (err) throw new Error(err); console.log(res); }); - diff --git a/examples/reservation-book.js b/examples/reservation-book.js index 279bf7e..2c3b268 100644 --- a/examples/reservation-book.js +++ b/examples/reservation-book.js @@ -1,52 +1,52 @@ -var expedia = require("../lib/expedia")({apiKey:"cbrzfta369qwyrm9t5b8y8kf",cid:"55505"}); +var expedia = require("../lib/expedia")({ + apiKey: "cbrzfta369qwyrm9t5b8y8kf", + cid: "55505" +}); // a complete list of options is available at http://developer.ean.com/docs/book-reservation/ var options = { - "customerSessionId" : "thisisauniqueID", - "customerIpAddress" : "127.0.0.1", - "customerUserAgent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", - "HotelRoomReservationRequest": { - "hotelId": "106347", - "arrivalDate": "9/30/2013", - "departureDate": "10/2/2013", + "customerSessionId": "0ABAAC0E-B501-FF91-5952-099A2F397163", + "customerIpAddress": "188.163.105.77", + "customerUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", + "hotelId": 106347, + "arrivalDate": "02/03/2017", + "departureDate": "02/05/2017", "supplierType": "E", "rateKey": "af00b688-acf4-409e-8bdc-fcfc3d1cb80c", "roomTypeCode": "198058", "rateCode": "484072", "chargeableRate": "231.18", - "RoomGroup": { - "Room": { - "numberOfAdults": "2", + // "RoomGroup": { + // "Room": { + "room1": 2, + "room1firstName": "test", + "room1lastName": "tester", + "room1bedTypeId": "23", + "room1smokingPreference": "NS", + // } + // }, + // "ReservationInfo": { + "email": "test@travelnow.com", "firstName": "test", "lastName": "tester", - "bedTypeId": "23", - "smokingPreference": "NS" - } - }, - "ReservationInfo": { - "email": "test@travelnow.com", - "firstName": "test", - "lastName": "tester", - "homePhone": "2145370159", - "workPhone": "2145370159", - "creditCardType": "CA", - "creditCardNumber": "5401999999999999", - "creditCardIdentifier": "123", - "creditCardExpirationMonth": "11", - "creditCardExpirationYear": "2015" - }, - "AddressInfo": { - "address1": "travelnow", - "city": "Seattle", - "stateProvinceCode": "WA", - "countryCode": "US", - "postalCode": "98004" - } - } + "homePhone": "2145370159", + "workPhone": "2145370159", + "creditCardType": "CA", + "creditCardNumber": "5401999999999999", + "creditCardIdentifier": "123", + "creditCardExpirationMonth": "11", + "creditCardExpirationYear": "2019", + // }, + // "AddressInfo": { + "address1": "travelnow", + "city": "Seattle", + "stateProvinceCode": "WA", + "countryCode": "US", + "postalCode": "98004" + // } }; -expedia.reservation.book(options, function(err, res){ - if(err)throw new Error(err); +expedia.reservation.book(options, function(err, res) { + if (err) throw new Error(err); console.log(res); }); - diff --git a/examples/reservation-cancel.js b/examples/reservation-cancel.js index c099331..dcc96af 100644 --- a/examples/reservation-cancel.js +++ b/examples/reservation-cancel.js @@ -1,20 +1,20 @@ -var expedia = require("../lib/expedia")({apiKey:"cbrzfta369qwyrm9t5b8y8kf",cid:"55505"}); +var expedia = require("../lib/expedia")({ + apiKey: "cbrzfta369qwyrm9t5b8y8kf", + cid: "55505" +}); // a complete list of options is available at http://developer.ean.com/docs/cancel-reservation/ var options = { - "customerSessionId" : "thisisauniqueID", - "customerIpAddress" : "127.0.0.1", - "customerUserAgent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", - "HotelRoomCancellationRequest": { + "customerSessionId": "thisisauniqueID", + "customerIpAddress": "127.0.0.1", + "customerUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", "itineraryId": "1234", "email": "test@travelnow.com", "reason": "COP", "confirmationNumber": "1234" - } }; -expedia.reservation.cancel(options, function(err, res){ - if(err)throw new Error(err); +expedia.reservation.cancel(options, function(err, res) { + if (err) throw new Error(err); console.log(res); }); - diff --git a/examples/reservation-get.js b/examples/reservation-get.js index b375901..2703370 100644 --- a/examples/reservation-get.js +++ b/examples/reservation-get.js @@ -1,18 +1,18 @@ -var expedia = require("../lib/expedia")({apiKey:"cbrzfta369qwyrm9t5b8y8kf",cid:"55505"}); +var expedia = require("../lib/expedia")({ + apiKey: "cbrzfta369qwyrm9t5b8y8kf", + cid: "55505" +}); // a complete list of options is available at http://developer.ean.com/docs/request-itinerary/ var options = { - "customerSessionId" : "thisisauniqueID", - "customerIpAddress" : "127.0.0.1", - "customerUserAgent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", - "HotelItineraryRequest": { + "customerSessionId": "thisisauniqueID", + "customerIpAddress": "127.0.0.1", + "customerUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko)", "itineraryId": "1234", "email": "test@travelnow.com" - } }; -expedia.reservation.get(options, function(err, res){ - if(err)throw new Error(err); +expedia.reservation.get(options, function(err, res) { + if (err) throw new Error(err); console.log(res); }); - diff --git a/lib/expedia.js b/lib/expedia.js index d4c3e65..7ae4107 100644 --- a/lib/expedia.js +++ b/lib/expedia.js @@ -1,174 +1,194 @@ /** -* Author : Shiem Edelbrock -* License: Released under the WTFPL license - http://sam.zoy.org/wtfpl/ -**/ + * Author : Shiem Edelbrock + * License: Released under the WTFPL license - http://sam.zoy.org/wtfpl/ + **/ var querystring = require('querystring'); -var parser = require('jstoxml'); -var request = require('request'); +var request = require('request-promise'); var color = require('cli-color'); +var crypto = require('crypto'); +var _ = require('lodash'); + +module.exports = function(options) { -module.exports = function (options, sendAsREST) { - // development and production ean endpoints var generalBaseUrl = "http://api.ean.com/ean-services/rs/hotel/v3/"; var bookingBaseUrl = "https://book.api.ean.com/ean-services/rs/hotel/v3/"; - var sendAsREST = sendAsREST || false; + var secret = options.secret || null; var defaults = { - cid : null, - apiKey : null, - locale : "en_US", - currencyCode :"USD" + cid: null, + minorRev: "99", + apiKey: null, + locale: "en_US", + currencyCode: "USD" }; - options = _extend(defaults, options); + options = _.assign(defaults, _.omit(options, 'secret')); - if(options.apiKey === null) throw new Error("Api Key is required"); - if(options.cid === null) throw new Error("CID is required"); - if(options.cid == 55505) console.log(color.red.bold.underline("|WARNING|") + color.red.bold(" CID 55505 is for development only, for production you must use another value")); - // add a callable endpoint to help us build the URL - var endpoint = function (endpoint, type){ - var baseUrl = (type == "booking") ? bookingBaseUrl : generalBaseUrl; - return baseUrl + endpoint + "?" + querystring.stringify(options) + "&"; - }; + if (options.apiKey === null) throw new Error("Api Key is required"); + if (options.cid === null) throw new Error("CID is required"); + if (options.cid == 55505) console.log(color.red.bold.underline("|WARNING|") + color.red.bold(" CID 55505 is for development only, for production you must use another value")); + if (options.secret === null) { + throw new Error('Secret is required'); + } - // Simple extend for our defaults - function _extend(settings1,settings2){ - var newSettings = {}; - for (var name in settings1) { newSettings[name] = settings1[name]; } - for (var name in settings2) { newSettings[name] = settings2[name]; } + // add a callable endpoint to help us build the URL + var endpoint = function(endpoint, type) { + var baseUrl = (type == "booking") ? bookingBaseUrl : generalBaseUrl, + timestamp = Math.floor(Date.now() / 1000), + sig = '&sig=' + crypto.createHash('md5').update(options.apiKey + secret + timestamp).digest('hex'); - return newSettings; - } + return baseUrl + endpoint + "?" + querystring.stringify(options) + sig; + }; - // Normalize nested json to xml and then querystring it - function _normalizeParameters(parameters, request){ - if(typeof parameters !== 'object'){ + function _normalizeParameters(parameters) { + if (typeof parameters !== 'object') { throw new Error("Parameters must be passed in as an object"); } - // Extract customer from request object - var customer = { - customerSessionId : parameters.customerSessionId, - customerIpAddress : parameters.customerIpAddress, - customerUserAgent : parameters.customerUserAgent - }; - delete(parameters.customerSessionId); - delete(parameters.customerIpAddress); - delete(parameters.customerUserAgent); - - customer = querystring.stringify(customer); - - var paramsAsString = customer +"&json&"; - if (sendAsREST){ - paramsAsString += querystring.stringify(parameters); - } - else { - paramsAsString += querystring.stringify({"xml" : parser.toXML(parameters)}); - } - return paramsAsString; + return querystring.stringify(parameters); } // Check to make sure default parameters are set - function _checkParameters(params){ - if(typeof params !== 'object') throw new Error("Parameters must be passed in as an object"); - if(!params.customerIpAddress) throw new Error("Customer ip address must be sent in as customerIpAddress"); - if(!params.customerUserAgent) throw new Error("Customer user agent string address must be sent in as customerUserAgent"); + function _checkParameters(params) { + if (typeof params !== 'object') throw new Error("Parameters must be passed in as an object"); + if (!params.customerIpAddress) throw new Error("Customer ip address must be sent in as customerIpAddress"); + if (!params.customerUserAgent) throw new Error("Customer user agent string address must be sent in as customerUserAgent"); } - function _handleResponse(response, cb){ + function _handleResponse(response) { var result; - try{ - result = JSON.parse(response); - } - catch (error){ - cb({error:"Error trying to parse response", details:{error:error, response:response}}); - } - if(result && result.EanWsError){ - cb({error:result.EanWsError.verboseMessage, details:result.EanWsError}); - } - else{ - cb(null, result); + + try { + result = response.HotelRoomReservationResponse; + + if (result && result.EanWsError) { + let error = { + error: result.EanWsError.verboseMessage, + details: result.EanWsError + }; + + return error; + } else { + return result; + } + + } catch (e) { + let error = { + error: 'Error trying to parse response', + details: { + error: e, + response: response + } + }; + + return error; } + + } - function _get(method, parameters, cb, type){ - var url = endpoint(method, type) + _normalizeParameters(parameters); - request.get(url, function (error, response, body) { - if (!error && response.statusCode == 200) { - _handleResponse(body, cb); - } - else if(error){ - cb({error:"http request error", details : error}); - } - else{ - cb({error:"http request error", details :{response : response,body : body}}); - } - }); + function _get(method, parameters, cb, type) { + var url = endpoint(method, type) + _normalizeParameters(parameters), + fn = request({ + uri: url, + json: true + }); + + if (typeof cb === 'function') { + fn.then(function(response) { + cb(null, response); + }).catch(function(error) { + cb({ + error: "http request error", + details: error + }); + }); + } else { + return fn; + } } - function _post(method, parameters, cb, type){ - var url = endpoint(method, type) + _normalizeParameters(parameters); - request.post(url, function (error, response, body) { - if (!error && response.statusCode == 200) { - _handleResponse(body, cb); - } - else if(error){ - cb({error:"http request error", details : error}); - } - else{ - cb({error:"http request error", details :{response : response,body : body}}); - } - }); + function _post(method, parameters, cb, type) { + var url = endpoint(method, type); + + var body = _.assign(options, parameters); + + var fn = request({ + method: 'POST', + uri: url, + json: true, + body: _normalizeParameters(body), + headers: { + 'content-type': 'application/x-www-form-urlencoded' // Set automatically + } + }); + + fn + .then(body => { + let response = _handleResponse(body); + + if (response.error) { + cb(response); + } else { + cb(null, response); + } + + }) + .catch(err => err); } return { // Utility functions - ping : function(params, cb){ + ping: function(params, cb) { _checkParameters(params); - _get("ping", params, cb, "general"); + return _get("ping", params, cb, "general"); }, - geoSearch : function(params, cb){ + geoSearch: function(params, cb) { _checkParameters(params); - _get("geoSearch", params, cb, "general"); + return _get("geoSearch", params, cb, "general"); + }, + optionsChange: function(nOpt) { + options = _.assign(options, nOpt); + return options; }, // Hotel specific methods - hotels:{ - list : function(params, cb){ + hotels: { + list: function(params, cb) { _checkParameters(params); - _get("list", params, cb, "general"); + return _get("list", params, cb, "general"); }, - info : function(params, cb){ + info: function(params, cb) { _checkParameters(params); - _get("info", params, cb, "general"); + return _get("info", params, cb, "general"); }, - availability : function(params, cb){ + availability: function(params, cb) { _checkParameters(params); - _get("avail", params, cb, "general"); + return _get("avail", params, cb, "general"); }, - roomImages : function(params, cb){ + roomImages: function(params, cb) { _checkParameters(params); - _get("roomImages", params, cb, "general"); + return _get("roomImages", params, cb, "general"); }, - acceptedPayments : function(params, cb){ + acceptedPayments: function(params, cb) { _checkParameters(params); - _get("paymentInfo", params, cb, "general"); + return _get("paymentInfo", params, cb, "general"); } }, // Reservation/Itinerary specific methods - reservation:{ - book : function(params, cb){ - _checkParameters(params); + reservation: { + book: function(params, cb) { + //_checkParameters(params); _post("res", params, cb, "booking"); }, - get : function(params, cb){ + get: function(params, cb) { _checkParameters(params); - _get("itin", params, cb, "general"); + return _get("itin", params, cb, "general"); }, - cancel : function(params, cb){ + cancel: function(params, cb) { _checkParameters(params); - _get("cancel", params, cb, "general"); + return _get("cancel", params, cb, "general"); } } }; -}; +}; \ No newline at end of file diff --git a/package.json b/package.json index e9c3e94..83549ed 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,20 @@ { - "name": "yfb-expedia", - "version": "1.0.1", + "name": "node-expedia-api", + "version": "1.0.5", "description": "simple wrapper around the expedia EAN api", "main": "lib/expedia.js", "repository": { "type": "git", - "url": "https://github.com/chris-verclytte/node-expedia-api.git" + "url": "https://github.com/startsat60/node-expedia-api.git.git" }, - "url": "https://github.com/chris-verclytte/node-expedia-api", + "url": "https://github.com/startsat60/node-expedia-api", "author": "Christophe Verclytte ", - "contributors": "Shiem Edelbrock", + "contributors": "Shiem Edelbrock, Emanuele Tonello", "license": "WTFPL", "dependencies": { - "cli-color": "~0.2.2", - "request": "~2.27.0", - "jstoxml": "~0.2.2" + "cli-color": "^1.1.0", + "lodash": "^4.11.2", + "request-promise": "^4.1.1", }, "engines": { "node": "*"