ytlabs_api_client 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f30bcad7ecac2a4ebf8c127f56f8d6da4cfa1437
4
+ data.tar.gz: a3fb99eb663787a7eb06ff638265766a5e613ead
5
+ SHA512:
6
+ metadata.gz: c679f3ecd6b371a0eefdf26e877679b4c28a645ca35f072045dd6efcfe678e272d5b2d579646b650b2105ab09664458ff3da8b2c456d42c3b81468a863d2a5ca
7
+ data.tar.gz: 2e6d1c071b7d1012c333ae2d3d70ee5e752dfbcb99cf86433a9a96787da8f5998ce5e1103865aebbdee90d7d1bd118696681d8eff79484457e0b5703f29eb982
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'activemodel'
4
+ gem 'httparty'
5
+
6
+ group :test, :development do
7
+ gem 'rspec'
8
+ gem 'pry'
9
+ gem 'webmock'
10
+ end
data/README.md ADDED
@@ -0,0 +1,203 @@
1
+ YTLabs API Client
2
+ ===================
3
+
4
+ A Ruby wrapper packaged as a Gem enabling Ruby calls to the Yello Travel Labs API which provides endpoints to search & book their inventory of Korea based rental properties. Visit Yello Travel Labs at [http://www.ytlabs.co.kr/](http://www.ytlabs.co.kr/). You will need an access token.
5
+
6
+ The YTLabs API uses camelCase params, however as this is a Ruby wrapper I have followed the Ruby convention of using underscore_case parameter naming, with the exception of `client.post_reservation_confirmation`. The belows README (and also the comments above the definition of each method) documents all required and optional parameter formats.
7
+
8
+ A work in progress as of July 2016, hence currently calling staging url.
9
+
10
+ ### Requirements:
11
+
12
+ httparty [github.com/jnunemaker/httparty](http://www.github.com/jnunemaker/httparty)
13
+
14
+ ===================
15
+
16
+ ### Install:
17
+
18
+ ```
19
+ gem install 'ytlabs_api_client'
20
+ ```
21
+
22
+ ===================
23
+
24
+ ### Usage:
25
+
26
+ ```
27
+ client = YTLabsApi::Client.new(token, :json)
28
+ ```
29
+
30
+ ===================
31
+
32
+ ### Endpoints covered:
33
+
34
+ #### GET Requests
35
+
36
+ #### get_properties: "GET /properties/"
37
+ ```
38
+ Use this resource to get a response a list of properties in the YTLabs API.
39
+
40
+ - Required => updated_at Date at which data starts being returned. (YYYY-MM-
41
+ - Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN,
42
+ - Optional => offset default: 0 Data offset (default 0)
43
+ - Optional => limit default: 30 Amount of requested properties (default 30)
44
+ - Optional => active default: 1 To filter by only active properties. 0 returns all. 1 returns Active o
45
+
46
+ When parameter 'limit=0&updatedAt=1970-01-01' is specified in request, all of the properties' information is
47
+ returned. It is recommended only for the first ever call made to retrieve all information.
48
+
49
+ Usage: get_property(params)
50
+ Example usage: client.get_properties(:updated_at => "1970-01-01", :limit => 3)
51
+ ```
52
+ ===================
53
+
54
+ #### get_property: "GET /properties/{propertyID}/"
55
+ ```
56
+ Use this resource with a property_identifier (e.g. "w_w0307279") to get the property's information.
57
+
58
+ - Required => property_identifier The unique property identifier/hash (e.g. w_w0307279)
59
+ - Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN, ja-JP)
60
+
61
+ Usage: get_property(property_identifier, params=nil)
62
+ Example usage: client.get_property("w_w0307279", :i18n => "en-US")
63
+ ```
64
+ ===================
65
+
66
+ #### get_availability: "GET /available/{propertyID}"
67
+ ```
68
+ Use this resource with a property_identifier (e.g. "w_w0307279") & a stay start_date to obtain rates & availability.
69
+
70
+ Required => property_identifier The unique property identifier/hash (e.g. w_w0307279)
71
+ Required => start_date YYYY-MM-DD (ex: 2016-02-01). Stay start date.
72
+ Optional => end_date default: (start_date + 1 day) YYYY-MM-DD (ex: 2016-02-05). Stay end date. If empty, defaults to start_date + 1 day.
73
+
74
+ Usage: get_availability(property_identifier, start_date, end_date=nil)
75
+ Example usage: client.get_availability("w_w0307279_R01", "2016-07-01", "2016-07-10")
76
+ ```
77
+ ===================
78
+
79
+ #### get_provinces: "GET /provincecode/"
80
+ ```
81
+ Returns a list with code or name of province.
82
+ - Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN, ja-JP)
83
+
84
+ Example usage: client.get_provinces
85
+ ```
86
+ ===================
87
+
88
+ #### get_cities: "GET /citycode/"
89
+ ```
90
+ Returns a list with code or name of cities.
91
+ - Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN, ja-JP)
92
+
93
+ Example usage: client.get_cities
94
+ ```
95
+ ===================
96
+
97
+ #### get_extra_service_codes: "GET /extraservicecode/"
98
+ ```
99
+ Returns a list mapping the codes and names of extra services.
100
+ - Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN, ja-JP)
101
+
102
+ Example usage: client.get_extra_service_codes
103
+ ```
104
+ ===================
105
+
106
+ #### get_theme_codes: "GET /themecode/"
107
+ ```
108
+ Returns a list mapping the code and name of themes.
109
+ - Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN, ja-JP)
110
+
111
+ Example usage: client.get_theme_codes
112
+ ```
113
+ ===================
114
+
115
+ #### get_reservations: "GET /reservation/information"
116
+ ```
117
+ 1. Use this resource with a set of dates to retrieve a collection of reservations between the given dates
118
+ 2. Use this resource with a reservation identifier(hash) + the start date to retrieve a collection of one reservation.
119
+
120
+ - Required => start_date YYYY-MM-DD (ex: 2016-02-01). Search by start date.
121
+ - Required => end_date YYYY-MM-DD (ex: 2016-02-05). Search by end date.
122
+ - Optional => reservation_identifier The unique property identifier/hash (e.g. w_w03072)
123
+
124
+ Example usage: client.get_reservations("2016-07-01", "2016-07-10", "w_w0307279_R01")
125
+ ```
126
+ ===================
127
+
128
+ #### get_room_types: "GET /roomtypes/"
129
+ ```
130
+ Use this resource to obtain a list of all room types.
131
+ - Required => updated_at Date at which data starts being returned. (YYYY-MM-
132
+ - Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN, ja-
133
+ - Optional => offset default: 0 Data offset (default 0)
134
+ - Optional => limit default: 30 Amount of requested room type (default 30)
135
+ - Optional => active default: 1 To filter by only active room type. 0 returns all. 1 returns Active o
136
+
137
+ Example usage: client.get_room_types(:updated_at => "1970-01-01", :limit => 1)
138
+ ```
139
+ ===================
140
+
141
+ #### get_property_room_types: "GET /properties/{propertyID}/roomtypes/"
142
+ ```
143
+ Using a specific propertyID, get all roomtypes' information of the property.
144
+
145
+ - Required => property_identifier Date at which data starts being returned. (YYYY-MM-
146
+ - Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN, ja
147
+
148
+ Example usage: client.get_property_room_types("w_w0307279", :i81n => "en-US")
149
+ ```
150
+ ===================
151
+
152
+ #### get_cancellation_charge: "GET /reservation/cancelcharge/"
153
+ ```
154
+ Using a reservation number get the cancellation fee payable. If a reservation is cancelled within 7 days of the check in day, a cancellation fee will be charged.
155
+
156
+ - Required => reservation_number Unique reservation number
157
+
158
+ Example usage: client.get_cancellation_charge("w_WP20160705145532ECD5")
159
+ ```
160
+
161
+ #### POST Requests
162
+
163
+ #### post_reservation_request(property_identifier, start_date, end_date): "POST /reservation/holding/"
164
+ ```
165
+ Before making a reservation, the room must be held - to prevent double booking.
166
+
167
+ Example usage: client.post_reservation_request("w_w0814002_R01", "2016-07-01", "2016-07-10")
168
+ ```
169
+ ===================
170
+
171
+
172
+ #### post_reservation_confirmation: "POST /reservation/confirm"
173
+ ```
174
+ Confirm a booking.
175
+
176
+ Format expected (Ruby Hash):
177
+
178
+ request_body = {
179
+ "reservationNo" => "w_WP20160718164753DE39",
180
+ "roomtypeCode" => "w_w0814002_R01",
181
+ "checkInDate" => "2016-07-01",
182
+ "checkOutDate" => "2016-07-10",
183
+ "guestName" => "Bob",
184
+ "guestCount" => 4,
185
+ "adultCount" => 2,
186
+ "childrenCount" => 2,
187
+ "paidPrice" => 2000.0,
188
+ "sellingPrice" => 2000.0,
189
+ "commissionPrice" => 200.0,
190
+ "currency" => "KRW"
191
+ }
192
+
193
+ Example usage: client.post_reservation_confirmation(request_body)
194
+ ```
195
+ ===================
196
+
197
+ #### post_cancellation_request(reservation_number, paid_price, commission_price, currency) "POST /reservation/cancel"
198
+
199
+ ```
200
+ Cancel a booking.
201
+
202
+ Example usage: client.post_cancellation_request("w_WP20160718164753DE39", 2000.0, 200.0, "KRW")
203
+ ```
data/lib/ytlabs_api.rb ADDED
@@ -0,0 +1,35 @@
1
+ require 'json'
2
+ require 'yaml'
3
+ require 'httparty'
4
+ require 'active_support/inflector'
5
+
6
+ require_relative 'ytlabs_api/client'
7
+
8
+ ## Exceptions
9
+ module YTLabsApi
10
+
11
+ #To be implemented in the Client.
12
+ class NetworkError < StandardError
13
+ def initialize(status, body)
14
+ super("Error. HTTP status: #{status}. Response body: #{body}")
15
+ end
16
+ end
17
+
18
+ class InvalidAccessToken < StandardError
19
+ def initialize
20
+ super("Your access token is not valid. It must be 36 characters long.")
21
+ end
22
+ end
23
+
24
+ class InvalidContentType < StandardError
25
+ def initialize
26
+ super("Your content type is invalid. 'json' or 'xml' are the 2 valid options")
27
+ end
28
+ end
29
+
30
+ class EndPointNotSupported < StandardError
31
+ def initialize
32
+ super("This endpoint is not supported: Try one of these: #{Client::END_POINTS.keys}")
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,34 @@
1
+ module YTLabsApi
2
+ module Availability
3
+
4
+ # GET /available/
5
+ # Use this resource with a property_identifier (e.g. "w_w0307279") & a stay start_date to obtain rates & availability.
6
+ #
7
+ # Parameters:
8
+ #
9
+ # Required => property_identifier The unique property identifier/hash (e.g. w_w0307279)
10
+ # Required => start_date YYYY-MM-DD (ex: 2016-02-01). Stay start date.
11
+ #
12
+ # Optional => end_date default: start_date + 1 day YYYY-MM-DD (ex: 2016-02-05). Stay end date. If empty, defaults to start_date + 1 day.
13
+ #
14
+ # Example Request: https://api.ytlabs.co.kr/stage/v1/available?roomCode=w_w0307279_R01&searchStartDate=2016-07-01&searchEndDate=2016-07-10
15
+ #
16
+ # Example usage: client.get_availability("w_w0307279_R01", "2016-12-01", "2016-12-10")
17
+
18
+ def get_availability(property_identifier, start_date, end_date=nil)
19
+ params = {
20
+ :roomCode => "#{property_identifier}",
21
+ :searchStartDate => "#{start_date}"
22
+ }
23
+
24
+ params.merge!(:searchEndDate => "#{end_date}") if end_date
25
+
26
+ response = HTTParty.get(
27
+ "#{build_url(__method__.to_s)}?#{transform_params!(params)}",
28
+ headers: { "Authorization" => token.to_s, "Content-Type" => "#{content_type}" }
29
+ )
30
+
31
+ prepare_response(response)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,107 @@
1
+ module YTLabsApi
2
+ module Booking
3
+
4
+ # POST /reservation/holding/
5
+ # Before making a reservation, the room must be held - to prevent double booking.
6
+ # Other customers cannot make a reservation until the holding status has ended.
7
+ # If 'pending' is returned in the response, the user can request Reservation Confirm.
8
+
9
+ # Format expected (JSON content type):
10
+ #
11
+ # {
12
+ # "roomCode" : "w_w0814002_R01",
13
+ # "checkInDate" : "2016-09-15",
14
+ # "checkOutDate" : "2016-09-16"
15
+ # }
16
+
17
+ def post_reservation_request(property_identifier, start_date, end_date)
18
+ request_body = {
19
+ :roomCode => "#{property_identifier}",
20
+ :checkInDate => "#{start_date}",
21
+ :checkOutDate => "#{end_date}"
22
+ }.to_json
23
+
24
+ response = HTTParty.post(
25
+ "#{build_url(__method__.to_s)}",
26
+ body: request_body,
27
+ headers: { "Authorization" => token.to_s, "Content-Type" => "#{content_type}" }
28
+ )
29
+
30
+ prepare_response(response)
31
+ end
32
+
33
+ # _________________________________________________________________________________________ #
34
+
35
+ # POST /reservation/confirm/
36
+ # The user must have a valid reservation number that will have been returned by making a successful 'reservation request'.
37
+ #
38
+ # Note that this method accepts a body with keys specified in camelcase.
39
+
40
+ # Format expected (JSON content type):
41
+ #
42
+ # {
43
+ # *** Required ***
44
+ # "reservationNo" : "w_WP000000000000000",
45
+ # "roomtypeCode" : "w_w0814002_R01",
46
+ # "checkInDate" : "2016-09-15",
47
+ # "checkOutDate" : "2016-09-16",
48
+ # "guestName" : "Lucy",
49
+ # "guestCount" : 3,
50
+ # "adultCount" : 2,
51
+ # "childrenCount" : 1,
52
+ # "paidPrice" : 2000.0,
53
+ # "sellingPrice" : 2000.0,
54
+ # "commissionPrice" : 200.0,
55
+ # "currency" : "KRW",
56
+ #
57
+ # *** Optional ***
58
+ # "guestPhone" : "010-0000-0000",
59
+ # "guestEmail" : "aaa@mail.com",
60
+ # "guestNationality" : "Korea"
61
+ # }
62
+
63
+ def post_reservation_confirmation(request_body={})
64
+ response = HTTParty.post(
65
+ "#{build_url(__method__.to_s)}",
66
+ body: request_body.to_json,
67
+ headers: { "Authorization" => token.to_s, "Content-Type" => "#{content_type}" }
68
+ )
69
+
70
+ prepare_response(response)
71
+ end
72
+
73
+ # _________________________________________________________________________________________ #
74
+
75
+ # GET /reservation/information
76
+
77
+ # Use this resource with a set of dates to retrieve a collection of reservations between the given dates
78
+ # OR
79
+ # Use this resource with a reservation identifier(hash) + the start date to retrieve a collection of one reservation.
80
+ #
81
+ # Parameters:
82
+ #
83
+ # Required => start_date YYYY-MM-DD (ex: 2016-02-01). Search by start date.
84
+ # Required => end_date YYYY-MM-DD (ex: 2016-02-05). Search by end date.
85
+ # Optional => reservation_identifier The unique property identifier/hash (e.g. w_w0307279)
86
+ #
87
+ # Example Request: https://api.ytlabs.co.kr/stage/v1/reservation/information?searchStartDate=2016-07-01&searchEndDate=2016-07-10&reservationNo=
88
+ #
89
+ # Example usage: client.get_reservations("2016-07-01", "2016-07-10", "w_w0307279_R01")
90
+
91
+ def get_reservations(start_date, end_date, reservation_identifier=nil)
92
+ params = {
93
+ :searchStartDate => "#{start_date}",
94
+ :searchEndDate => "#{end_date}"
95
+ }
96
+
97
+ params.merge!( :reservationNo => "#{reservation_identifier}" ) if reservation_identifier
98
+
99
+ response = HTTParty.get(
100
+ "#{build_url(__method__.to_s)}?#{transform_params!(params)}",
101
+ headers: { "Authorization" => token.to_s, "Content-Type" => "#{content_type}" }
102
+ )
103
+
104
+ prepare_response(response)
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,55 @@
1
+ module YTLabsApi
2
+ module Cancellation
3
+
4
+ # POST /reservation/cancel/
5
+ #
6
+ # If a reservation is canceled by the guest, the partner should request /reservation/cancel/
7
+ # If a real reservation is not completed within 10 minutes after ReservationHolding, Partner should also request /reservation/cancel/
8
+ #
9
+ # {
10
+ # "reservationNo" : "w_WP0000000000000000",
11
+ # "refundPaidPrice" : 2000.0,
12
+ # "refundCommissionPrice" : 200.0,
13
+ # "currency" : "KRW"
14
+ # }
15
+
16
+ def post_cancellation_request(reservation_number, paid_price, commission_price, currency)
17
+ request_body = {
18
+ :reservationNo => "#{reservation_number}",
19
+ :refundPaidPrice => "#{paid_price}",
20
+ :refundCommissionPrice => "#{commission_price}",
21
+ :currency => "#{currency}"
22
+ }.to_json
23
+
24
+ response = HTTParty.post(
25
+ "#{build_url(__method__.to_s)}",
26
+ body: request_body,
27
+ headers: { "Authorization" => token.to_s, "Content-Type" => "#{content_type}" }
28
+ )
29
+
30
+ prepare_response(response)
31
+ end
32
+
33
+ # GET /reservation/cancelcharge/
34
+ # Using a reservation number get the cancellation fee payable.
35
+ #
36
+ # If a reservation is cancelled within 7 days of the check in day, a cancellation fee will be charged.
37
+
38
+ # Parameters:
39
+ #
40
+ # Required => reseveration_number Unique reservation number - provided when booking was made.
41
+ #
42
+ # Example Request: https://api.ytlabs.co.kr/stage/v1/reservation/cancelcharge?reservationNo=w_WP20160705145532ECD5
43
+ #
44
+ # Example usage: client.get_cancellation_charge("w_WP20160705145532ECD5")
45
+ def get_cancellation_charge(reservation_number)
46
+ response = HTTParty.get(
47
+ "#{build_url(__method__.to_s)}?reservationNo=#{reservation_number}",
48
+ headers: { "Authorization" => token.to_s, "Content-Type" => "#{content_type}" }
49
+ )
50
+
51
+ prepare_response(response)
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,129 @@
1
+ # +YTLabsApi::Client+ - entry class to the API client.
2
+ #
3
+ # Proposed usage:
4
+ # => client = YTLabsApi::Client.new("your_token", :json)
5
+ # => client.get_properties(params_hash)
6
+
7
+ require_relative 'availability'
8
+ require_relative 'booking'
9
+ require_relative 'property'
10
+ require_relative 'supplementary_information'
11
+ require_relative 'cancellation'
12
+ require_relative 'room_type'
13
+
14
+
15
+ module YTLabsApi
16
+ class Client
17
+ include HTTParty
18
+
19
+ include YTLabsApi::Availability
20
+ include YTLabsApi::Booking
21
+ include YTLabsApi::Cancellation
22
+ include YTLabsApi::Property
23
+ include YTLabsApi::RoomType
24
+ include YTLabsApi::SupplementaryInformation
25
+
26
+ END_POINTS = YAML::load(File.open(File.join('lib', 'ytlabs_api', 'end_points.yml')))
27
+ URL = "https://api.ytlabs.co.kr/stage/v1"
28
+ VALID_CONTENT_TYPES = [:json, :xml].freeze
29
+
30
+ format :json
31
+ default_timeout 1 #Hard timeout after 1 second.
32
+
33
+ attr_reader :token, :content_type, :base_url, :errors
34
+
35
+ def initialize(token, content_type=nil)
36
+ @token = token
37
+ @content_type = "application/#{content_type.to_s}" || "application/json"
38
+ @base_url = URL
39
+ @errors = []
40
+
41
+ raise InvalidAccessToken unless valid_token?(token)
42
+ raise InvalidContentType unless valid_content_type?(content_type)
43
+ end
44
+
45
+
46
+ # HTTParty will raise Net::OpenTimeout if it can't connect to the server.
47
+ # It will raise Net::ReadTimeout if reading the response from the server times out.
48
+ # Handle these exceptions to return a empty hash, and set the timeout to 1 second.
49
+ # Wrap any calls made using HTTParty in a handle_timeouts block
50
+
51
+ # handle_timeouts do
52
+ # your HTTParty call.
53
+ # end
54
+
55
+ # TODO
56
+ # def handle_timeouts
57
+ # begin
58
+ # yield
59
+ # rescue Net::OpenTimeout, Net::ReadTimeout
60
+ # {}
61
+ # end
62
+ # end
63
+
64
+ # Since the only public methods this client supports are calls to the specified endpoints,
65
+ # which are implemented - we will raise a more specific error here.
66
+ def method_missing(method, *args, &block)
67
+ raise EndPointNotSupported
68
+ end
69
+
70
+ private
71
+
72
+ ## Transforms {:a => 2, :b => 2} to "a=2&b=2"
73
+ def transform_params!(params)
74
+ URI.encode_www_form(params) if params
75
+ end
76
+
77
+
78
+ ## Accepts underscored variables/params & converts them to camelCase as required by the YTLabs API.
79
+ ## The intention is to 'Rubify' the wrapper allowing underscore_style_variable_naming.
80
+ ## Example:
81
+ ## camelize_params_keys!({:room_code=>"123", :search_start_date=>"456"})
82
+ ## => {"roomCode"=>"123", "searchStartDate"=>"456"}
83
+ def camelize_params_keys!(params_hash)
84
+ return unless params_hash
85
+
86
+ params_hash.keys.each do |key|
87
+ value = params_hash.delete(key)
88
+ new_key = key.to_s.camelize(:lower)
89
+ params_hash[new_key] = value
90
+ end
91
+ params_hash
92
+ end
93
+
94
+ ## Builds endpoint URL dynamically.
95
+ def build_url(action, identifier=nil)
96
+ end_point = END_POINTS[action]
97
+
98
+ if identifier
99
+ url = "#{base_url}/#{end_point}/#{identifier}"
100
+ else
101
+ url = "#{base_url}/#{end_point}"
102
+ end
103
+ url
104
+ end
105
+
106
+ # The responses from the API are somewhat misleading. Calls that one might expect to 404 seem to return 403 Forbidden
107
+ # with "message"=>"Authorization header requires 'Credential' parameter. Consider how to provide more helpful messages.
108
+ def prepare_response(response)
109
+ if response.parsed_response["status"] == (200..206)
110
+ parse_successful_response(response)
111
+ else
112
+ # Temporary
113
+ JSON.parse(response.body)
114
+ end
115
+ end
116
+
117
+ def parse_successful_response(response)
118
+ JSON.parse(response.body)
119
+ end
120
+
121
+ def valid_token?(token)
122
+ token.size == 36
123
+ end
124
+
125
+ def valid_content_type?(content_type)
126
+ VALID_CONTENT_TYPES.include?(content_type)
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,26 @@
1
+ # Define each endpoint here +end_points.yml+ to map a method name to
2
+ # an endpoint that it will call on the API.
3
+
4
+ # GET Requests
5
+ get_properties: "properties"
6
+ get_property: "properties"
7
+ get_availability: "available"
8
+
9
+ get_provinces: "provincecode"
10
+ get_cities: "citycode"
11
+ get_extra_service_codes: "extraservicecode"
12
+ get_theme_codes: "themecode"
13
+
14
+ get_reservations: "reservation/information"
15
+
16
+ get_room_types: "roomtypes"
17
+ get_property_room_types: "properties"
18
+
19
+ get_cancellation_charge: "reservation/cancelcharge"
20
+
21
+
22
+ # POST Requests
23
+ post_reservation_request: "reservation/holding"
24
+ post_reservation_confirmation: "reservation/confirm"
25
+
26
+ post_cancellation_request: "reservation/cancel"
@@ -0,0 +1,61 @@
1
+ module YTLabsApi
2
+ module Property
3
+
4
+ # GET /properties/
5
+ # Use this resource to get a response a list of properties in the YTLabs API.
6
+ #
7
+ # Parameters:
8
+ #
9
+ # Required => updated_at Date at which data starts being returned. (YYYY-MM-DD).
10
+ #
11
+ # Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN, ja-JP)
12
+ # Optional => offset default: 0 Data offset (default 0)
13
+ # Optional => limit default: 30 Amount of requested properties (default 30)
14
+ # Optional => active default: 1 To filter by only active properties. 0 returns all. 1 returns Active only.
15
+ #
16
+ # When parameter 'limit=0&updatedAt=1970-01-01' is specified in request, all of the properties' information is
17
+ # returned. It is recommended only for the first time
18
+ #
19
+ # Example Request: https://api.ytlabs.co.kr/stage/v1/properties?i18n=en-US&offset=0&limit=30&active=1&updatedAt=2016-05-24
20
+ #
21
+ # Example usage: client.get_properties(:updated_at => "1970-01-01", :limit => 3)
22
+
23
+ def get_properties(params)
24
+ camelize_params_keys!(params)
25
+
26
+ response = HTTParty.get(
27
+ "#{build_url(__method__.to_s)}?#{transform_params!(params)}",
28
+ headers: { "Authorization" => token.to_s, "Content-Type" => "#{content_type}" }
29
+ )
30
+
31
+ prepare_response(response)
32
+ end
33
+
34
+
35
+ # _________________________________________________________________________________________ #
36
+
37
+ # GET /properties/{propertyID}/
38
+ # Use this resource with a property_identifier (e.g. "w_w0307279") to get the property's information.
39
+ #
40
+ # Parameters:
41
+ #
42
+ # Required => property_identifier The unique property identifier/hash (e.g. w_w0307279)
43
+ #
44
+ # Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN, ja-JP)
45
+ #
46
+ # Example Request: https://api.ytlabs.co.kr/stage/v1/properties/w_w0307279?i18n=en-US
47
+ #
48
+ # Example usage: client.get_property("w_w0307279", :i18n => "en-US")
49
+
50
+ def get_property(property_identifier, params=nil)
51
+ camelize_params_keys!(params)
52
+
53
+ response = HTTParty.get(
54
+ "#{build_url(__method__.to_s, property_identifier)}?#{transform_params!(params)}",
55
+ headers: { "Authorization" => token.to_s, "Content-Type" => "#{content_type}" }
56
+ )
57
+
58
+ prepare_response(response)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,59 @@
1
+ module YTLabsApi
2
+ module RoomType
3
+
4
+ # GET /roomtypes/
5
+ # Obtain a list of all room types.
6
+
7
+ # Parameters:
8
+ #
9
+ # Required => updated_at Date at which data starts being returned. (YYYY-MM-DD).
10
+ #
11
+ # Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN, ja-JP)
12
+ # Optional => offset default: 0 Data offset (default 0)
13
+ # Optional => limit default: 30 Amount of requested room type (default 30)
14
+ # Optional => active default: 1 To filter by only active room type. 0 returns all. 1 returns Active only.
15
+ #
16
+ # When parameter 'updatedAt' is specified in request, only updated information is returned.
17
+ #
18
+ # Example Request: https://api.ytlabs.co.kr/stage/v1/roomtypes?i18n=en-US&offset=0&limit=30&active=1&updatedAt=2016-05-24
19
+ #
20
+ # Example usage: client.get_room_types(:updated_at => "1970-01-01", :limit => 1)
21
+
22
+ def get_room_types(params=nil)
23
+ camelize_params_keys!(params)
24
+
25
+ response = HTTParty.get(
26
+ "#{build_url(__method__.to_s)}?#{transform_params!(params)}",
27
+ headers: { "Authorization" => token.to_s, "Content-Type" => "#{content_type}" }
28
+ )
29
+
30
+ prepare_response(response)
31
+ end
32
+
33
+
34
+ # GET /properties/{propertyID}/roomtypes/
35
+ # Using a specific propertyID, get all roomtypes' information of the property.
36
+
37
+ # Parameters:
38
+ #
39
+ # Required => property_identifier Date at which data starts being returned. (YYYY-MM-DD).
40
+ #
41
+ # Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN, ja-JP)
42
+ #
43
+ # Example Request: https://api.ytlabs.co.kr/stage/v1/properties/w_w0307279/roomtypes?i18n=en-US
44
+ #
45
+ # Example usage: client.get_property_room_types("w_w0307279", :i81n => "en-US")
46
+
47
+ def get_property_room_types(property_identifier, params=nil)
48
+ camelize_params_keys!(params)
49
+
50
+ response = HTTParty.get(
51
+ "#{build_url(__method__.to_s, property_identifier)}/roomtypes?#{transform_params!(params)}",
52
+ headers: { "Authorization" => token.to_s, "Content-Type" => "#{content_type}" }
53
+ )
54
+
55
+ prepare_response(response)
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,63 @@
1
+ module YTLabsApi
2
+ module SupplementaryInformation
3
+
4
+ # GET /provincecode/
5
+ # Returns a list with code or name of province.
6
+ # Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN, ja-JP)
7
+
8
+ def get_provinces(i18n="ko-KR")
9
+ response = HTTParty.get(
10
+ "#{build_url(__method__.to_s)}?i18n=#{i18n}",
11
+ headers: { "Authorization" => token.to_s, "Content-Type" => "#{content_type}" }
12
+ )
13
+
14
+ prepare_response(response)
15
+ end
16
+
17
+ # _________________________________________________________________________________________ #
18
+
19
+ # GET /citycode/
20
+ # Returns a list with code or name of cities.
21
+ # Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN, ja-JP)
22
+
23
+ def get_cities(i18n="ko-KR")
24
+ response = HTTParty.get(
25
+ "#{build_url(__method__.to_s)}?i18n=#{i18n}",
26
+ headers: { "Authorization" => token.to_s, "Content-Type" => "#{content_type}" }
27
+ )
28
+
29
+ prepare_response(response)
30
+ end
31
+
32
+ # _________________________________________________________________________________________ #
33
+
34
+ # GET /extraservicecode/
35
+ # Returns a list mapping the codes and names of extra services.
36
+ # Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN, ja-JP)
37
+
38
+ def get_extra_service_codes(i18n="ko-KR")
39
+ response = HTTParty.get(
40
+ "#{build_url(__method__.to_s)}?i18n=#{i18n}",
41
+ headers: { "Authorization" => token.to_s, "Content-Type" => "#{content_type}" }
42
+ )
43
+
44
+ prepare_response(response)
45
+ end
46
+
47
+ # _________________________________________________________________________________________ #
48
+
49
+ # GET /themecode/
50
+ # Returns a list mapping the code and name of themes.
51
+ # Optional => i18n default: "ko-KR" Return text in other lanaguages(ko-KR, en-US, zh-CN, ja-JP)
52
+
53
+ def get_theme_codes(i18n="ko-KR")
54
+ response = HTTParty.get(
55
+ "#{build_url(__method__.to_s)}?i18n=#{i18n}",
56
+ headers: { "Authorization" => token.to_s, "Content-Type" => "#{content_type}" }
57
+ )
58
+
59
+ prepare_response(response)
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,3 @@
1
+ module YTLabsApi
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,6 @@
1
+ require "ytlabs_api"
2
+ require "webmock/rspec"
3
+
4
+ # Disable all net connections except localhost.
5
+ # Override this in a specific spec with ++WebMock.allow_net_connect!++
6
+ WebMock.disable_net_connect!(:allow_localhost => true)
@@ -0,0 +1,163 @@
1
+ require 'spec_helper'
2
+
3
+ describe YTLabsApi::Client do
4
+ ## Generates a 36 char length token.
5
+ let(:token) { SecureRandom.hex(18) }
6
+ let(:content_type) { :json }
7
+ let(:client) { described_class.new(token, content_type) }
8
+
9
+ describe "Client" do
10
+ it "instantiates a new client object" do
11
+ expect(client).to be_a (YTLabsApi::Client)
12
+ end
13
+
14
+ context "token" do
15
+ it "raises an error if a token is not valid" do
16
+ error_message = "Your access token is not valid. It must be 36 characters long."
17
+ bad_token = "123"
18
+ expect { described_class.new(bad_token) }.to raise_error (error_message)
19
+ end
20
+ end
21
+
22
+ context "content_type" do
23
+ it "accepts json" do
24
+ client = described_class.new(token, :json)
25
+ expect(client.content_type).to eq "application/json"
26
+ end
27
+
28
+ it "accepts xml" do
29
+ client = described_class.new(token, :xml)
30
+ expect(client.content_type).to eq "application/xml"
31
+ end
32
+
33
+ it "does not content types other than json or xml" do
34
+ error_message = "Your content type is invalid. 'json' or 'xml' are the 2 valid options"
35
+ expect { described_class.new(token, :html) }.to raise_error (error_message)
36
+ end
37
+ end
38
+
39
+ context "invalid/not implemented method/endpoint called" do
40
+ it "raises when invalid endpoint is called" do
41
+ error_message = 'This endpoint is not supported: Try one of these: ["get_properties", "get_property", "get_availability", "get_provinces", "get_cities", "get_extra_service_codes", "get_theme_codes", "get_reservations", "get_room_types", "get_property_room_types", "get_cancellation_charge", "post_reservation_request", "post_reservation_confirmation", "post_cancellation_request"]'
42
+ expect { client.bob }.to raise_error.with_message (error_message)
43
+ end
44
+ end
45
+ end
46
+
47
+ describe "base_url" do
48
+ it "responds with the base url" do
49
+ expect(client).to respond_to (:base_url)
50
+ expect(client.base_url).to eq ("https://api.ytlabs.co.kr/stage/v1")
51
+ end
52
+ end
53
+
54
+ context "properties" do
55
+ describe "#get_property" do
56
+ context "with an invalid access token" do
57
+ it "returns an Unauthorized response" do
58
+ WebMock.allow_net_connect!
59
+ expect(client.get_property("w_w0307360")).to include ( {"message"=>"Unauthorized"} )
60
+ end
61
+ end
62
+
63
+ context "with a valid access token" do
64
+ before do
65
+ response = '[{ "property": "a property for you" }]'
66
+ stub_request(:any, "https://api.ytlabs.co.kr/stage/v1/properties").to_return(:body => response, :status => 200, :headers => {})
67
+ end
68
+
69
+ it "returns a property within a parsed response" do
70
+ client = YTLabsApi::Client.new(token, :json)
71
+ response = client.get_property("w_w0307360")
72
+ expect(response).to eq response
73
+ end
74
+ end
75
+ end
76
+
77
+ describe "#get_properties" do
78
+ context "with an invalid access token" do
79
+ it "returns an Unauthorized response" do
80
+ WebMock.allow_net_connect!
81
+ expect(client.get_properties(:updated_at => "1970-01-01", :limit => 3)).to include ( {"message"=>"Unauthorized"} )
82
+ end
83
+ end
84
+
85
+ context "with a valid access token" do
86
+ before do
87
+ response = '[{ "property": "a property for you" }, { "property_2": "another property for you" }]'
88
+ url = "https://api.ytlabs.co.kr/stage/v1/properties?i18n=en-US&offset=0&limit=2&active=1&updatedAt=2016-05-24"
89
+ stub_request(:any, url).to_return(:body => response, :status => 200, :headers => {})
90
+ end
91
+
92
+ it "returns 2 properties within a parsed response" do
93
+ client = YTLabsApi::Client.new(token, :json)
94
+ response = client.get_properties(updated_at: Date.today)
95
+ expect(response).to eq response
96
+ end
97
+ end
98
+ end
99
+
100
+ describe "#get_room_types" do
101
+ before do
102
+ response = '[{ "room_type": "a room_type for you" }, { "room_type_2": "another room_type for you" }]'
103
+ url = "https://api.ytlabs.co.kr/stage/v1/roomtypes?i18n=en-US&offset=0&limit=30&active=1&updatedAt=2016-05-24"
104
+ stub_request(:any, url).to_return(:body => response, :status => 200, :headers => {})
105
+ end
106
+
107
+ it "returns 2 room_types within a parsed response" do
108
+ client = YTLabsApi::Client.new(token, :json)
109
+ response = client.get_room_types
110
+ expect(response).to eq response
111
+ end
112
+ end
113
+ end
114
+
115
+ context "supplementary_information" do
116
+ describe "#get_provinces" do
117
+ before do
118
+ response = '[{ "province_one": "great place", "province_two": "an ever better place" }]'
119
+ stub_request(:any, "https://api.ytlabs.co.kr/stage/v1/provincecode").to_return(:body => response, :status => 200, :headers => {})
120
+ end
121
+
122
+ it "returns a property within a parsed response" do
123
+ client = YTLabsApi::Client.new(token, :json)
124
+ response = client.get_provinces
125
+ expect(response).to eq response
126
+ end
127
+ end
128
+ end
129
+
130
+ private
131
+
132
+ describe "#build_url" do
133
+ context "without identifier (i.e. a room hash/id)" do
134
+ it "builds the endpoint URL correctly" do
135
+ stub_const("YTLabs::CLient::END_POINTS", { get_properties: "properties" } )
136
+ action = "get_properties"
137
+ expect(client.send(:build_url, action)).to eq "https://api.ytlabs.co.kr/stage/v1/properties"
138
+ end
139
+ end
140
+
141
+ context "with an identifier (i.e. a room hash/id)" do
142
+ it "builds the endpoint URL correctly" do
143
+ stub_const("YTLabsApi::CLient::END_POINTS", { get_properties: "properties" } )
144
+ action = "get_properties"
145
+ identifier = "123"
146
+ expect(client.send(:build_url, action, identifier)).to eq "https://api.ytlabs.co.kr/stage/v1/properties/123"
147
+ end
148
+ end
149
+ end
150
+
151
+ describe "#camelize_params_keys!(params_hash)" do
152
+ it "modifies a Rubified set of params keys correctly" do
153
+ params_hash = { :room_code => "123", :search_start_date => "456" }
154
+ expect(client.send(:camelize_params_keys!, params_hash)).to eq ({"roomCode"=> "123", "searchStartDate"=> "456"})
155
+ end
156
+
157
+ it "it does not modify keys that are already camelized" do
158
+ params_hash = { :roomCode => "123", :searchStartDate => "456" }
159
+ expect(client.send(:camelize_params_keys!, params_hash)).to eq ({"roomCode"=> "123", "searchStartDate"=> "456"})
160
+ end
161
+ end
162
+
163
+ end
@@ -0,0 +1,9 @@
1
+ require "spec_helper"
2
+
3
+ describe "roomallo API" do
4
+ let(:ytlabs_api) { YTLabsApi }
5
+
6
+ it "is a module" do
7
+ expect( ytlabs_api ).to be_a( Module )
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ytlabs_api_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ben Hawker
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-07-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: Ruby wrapper enabling authenticated calls to the YT Labs API
28
+ email: ben.c.hawker@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - Gemfile
34
+ - README.md
35
+ - lib/ytlabs_api.rb
36
+ - lib/ytlabs_api/availability.rb
37
+ - lib/ytlabs_api/booking.rb
38
+ - lib/ytlabs_api/cancellation.rb
39
+ - lib/ytlabs_api/client.rb
40
+ - lib/ytlabs_api/end_points.yml
41
+ - lib/ytlabs_api/property.rb
42
+ - lib/ytlabs_api/room_type.rb
43
+ - lib/ytlabs_api/supplementary_information.rb
44
+ - lib/ytlabs_api/version.rb
45
+ - spec/spec_helper.rb
46
+ - spec/ytlabs_api/client_spec.rb
47
+ - spec/ytlabs_api_spec.rb
48
+ homepage:
49
+ licenses:
50
+ - MIT
51
+ metadata: {}
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 2.4.6
69
+ signing_key:
70
+ specification_version: 4
71
+ summary: YT Labs API Ruby Client
72
+ test_files: []