mastercard_api_core 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 +7 -0
- data/lib/mastercard/core/config.rb +84 -0
- data/lib/mastercard/core/constants.rb +36 -0
- data/lib/mastercard/core/controller.rb +325 -0
- data/lib/mastercard/core/exceptions.rb +325 -0
- data/lib/mastercard/core/model.rb +467 -0
- data/lib/mastercard/core/util.rb +141 -0
- data/lib/mastercard/security/authentication.rb +36 -0
- data/lib/mastercard/security/oauth.rb +211 -0
- data/lib/mastercard/security/util.rb +46 -0
- data/lib/mastercard_api_core.rb +29 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 11df59f25e79aa759a551ecfc4aa6e1425b9cd88
|
4
|
+
data.tar.gz: 3eef3a4fc2104ddbce60f346e75f905571d7c9a7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1d11fde3322e775985c14aa7bb7c98a9e5124b8d9471e41cd032f60c8da2105999c3b7519a09317d16150d9a7bd07ad74358222585b1fa0e0f4fb4cd7302a2c9
|
7
|
+
data.tar.gz: c198b9395316e85b110661ff1fb82e091fefb8414189dae3911e1ecbcc4973fd5aa51c2d852a4dc78ad2d05bbe488e433e4f51b59a7b411619d9a9f62e013666
|
@@ -0,0 +1,84 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2016 MasterCard International Incorporated
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification, are
|
6
|
+
# permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list of
|
9
|
+
# conditions and the following disclaimer.
|
10
|
+
# Redistributions in binary form must reproduce the above copyright notice, this list of
|
11
|
+
# conditions and the following disclaimer in the documentation and/or other materials
|
12
|
+
# provided with the distribution.
|
13
|
+
# Neither the name of the MasterCard International Incorporated nor the names of its
|
14
|
+
# contributors may be used to endorse or promote products derived from this software
|
15
|
+
# without specific prior written permission.
|
16
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
17
|
+
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
18
|
+
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
19
|
+
# SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
20
|
+
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
21
|
+
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
22
|
+
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
23
|
+
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
24
|
+
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
25
|
+
# SUCH DAMAGE.
|
26
|
+
#
|
27
|
+
require "mastercard/core/constants"
|
28
|
+
|
29
|
+
module MasterCard
|
30
|
+
module Core
|
31
|
+
class Config
|
32
|
+
|
33
|
+
private
|
34
|
+
@@sandbox = true
|
35
|
+
@@debug = false
|
36
|
+
@@authentication = nil
|
37
|
+
@@localhost = false
|
38
|
+
|
39
|
+
public
|
40
|
+
def self.setDebug(debug)
|
41
|
+
@@debug = debug
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.isDebug()
|
45
|
+
return @@debug
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.setSandbox(sandbox)
|
49
|
+
@@sandbox = sandbox
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.isSandbox()
|
53
|
+
return @@sandbox
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.setLocal(local)
|
57
|
+
@@localhost = local
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.isLocal
|
61
|
+
return @@localhost
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.setAuthentication(auth)
|
65
|
+
@@authentication = auth
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.getAuthentication
|
69
|
+
return @@authentication
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.getAPIBaseURL
|
73
|
+
|
74
|
+
if @@localhost
|
75
|
+
return Constants::API_BASE_LOCALHOST_URL
|
76
|
+
elsif @@sandbox
|
77
|
+
return Constants::API_BASE_SANDBOX_URL
|
78
|
+
end
|
79
|
+
|
80
|
+
return Constants::API_BASE_LIVE_URL
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2016 MasterCard International Incorporated
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification, are
|
6
|
+
# permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list of
|
9
|
+
# conditions and the following disclaimer.
|
10
|
+
# Redistributions in binary form must reproduce the above copyright notice, this list of
|
11
|
+
# conditions and the following disclaimer in the documentation and/or other materials
|
12
|
+
# provided with the distribution.
|
13
|
+
# Neither the name of the MasterCard International Incorporated nor the names of its
|
14
|
+
# contributors may be used to endorse or promote products derived from this software
|
15
|
+
# without specific prior written permission.
|
16
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
17
|
+
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
18
|
+
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
19
|
+
# SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
20
|
+
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
21
|
+
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
22
|
+
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
23
|
+
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
24
|
+
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
25
|
+
# SUCH DAMAGE.
|
26
|
+
#
|
27
|
+
module MasterCard
|
28
|
+
module Core
|
29
|
+
module Constants
|
30
|
+
VERSION = "1.0.0"
|
31
|
+
API_BASE_LOCALHOST_URL = "http://localhost:8080"
|
32
|
+
API_BASE_LIVE_URL = "https://api.mastercard.com"
|
33
|
+
API_BASE_SANDBOX_URL = "https://sandbox.api.mastercard.com"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,325 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2016 MasterCard International Incorporated
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification, are
|
6
|
+
# permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list of
|
9
|
+
# conditions and the following disclaimer.
|
10
|
+
# Redistributions in binary form must reproduce the above copyright notice, this list of
|
11
|
+
# conditions and the following disclaimer in the documentation and/or other materials
|
12
|
+
# provided with the distribution.
|
13
|
+
# Neither the name of the MasterCard International Incorporated nor the names of its
|
14
|
+
# contributors may be used to endorse or promote products derived from this software
|
15
|
+
# without specific prior written permission.
|
16
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
17
|
+
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
18
|
+
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
19
|
+
# SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
20
|
+
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
21
|
+
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
22
|
+
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
23
|
+
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
24
|
+
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
25
|
+
# SUCH DAMAGE.
|
26
|
+
#
|
27
|
+
require 'mastercard/core/config'
|
28
|
+
require 'mastercard/core/exceptions'
|
29
|
+
require 'mastercard/core/util'
|
30
|
+
require 'mastercard/security/authentication'
|
31
|
+
require 'net/http'
|
32
|
+
require 'json'
|
33
|
+
|
34
|
+
module MasterCard
|
35
|
+
module Core
|
36
|
+
module Controller
|
37
|
+
class APIController
|
38
|
+
include MasterCard::Core
|
39
|
+
include MasterCard::Core::Exceptions
|
40
|
+
include MasterCard::Security
|
41
|
+
|
42
|
+
ACTION_CREATE = "CREATE"
|
43
|
+
ACTION_DELETE = "DELETE"
|
44
|
+
ACTION_UPDATE = "UPDATE"
|
45
|
+
ACTION_READ = "READ"
|
46
|
+
ACTION_LIST = "LIST"
|
47
|
+
ACTION_QUERY = "QUERY"
|
48
|
+
|
49
|
+
KEY_ID = "id"
|
50
|
+
KEY_FORMAT = "Format"
|
51
|
+
KEY_ACCEPT = "Accept"
|
52
|
+
KEY_USER_AGENT = "User-Agent"
|
53
|
+
KEY_CONTENT_TYPE = "Content-Type"
|
54
|
+
APPLICATION_JSON = "application/json"
|
55
|
+
RUBY_SDK = "Ruby_SDK"
|
56
|
+
JSON_STR = "JSON"
|
57
|
+
|
58
|
+
|
59
|
+
def initialize(version=nil)
|
60
|
+
#Set the parameters
|
61
|
+
@baseURL = Config.getAPIBaseURL()
|
62
|
+
|
63
|
+
@baseURL = removeForwardSlashFromTail(@baseURL)
|
64
|
+
|
65
|
+
#Verify if the URL is correct
|
66
|
+
unless Util.validateURL(@baseURL)
|
67
|
+
raise APIException.new "URL: '" + @baseURL + "' is not a valid url"
|
68
|
+
end
|
69
|
+
|
70
|
+
#Set the version
|
71
|
+
unless version.nil?
|
72
|
+
@version = version
|
73
|
+
else
|
74
|
+
@version = Constants::VERSION
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
def execute(action,resourcePath,headerKey,queryKey,input)
|
80
|
+
|
81
|
+
#Check preconditions for execute
|
82
|
+
preCheck()
|
83
|
+
|
84
|
+
#Separate the headers from the inputMap
|
85
|
+
headers = Util.subMap(input,headerKey)
|
86
|
+
|
87
|
+
#Separate the query from the inputMap
|
88
|
+
queryParams = Util.subMap(input,queryKey)
|
89
|
+
|
90
|
+
#Get the resourcePath containing values from input
|
91
|
+
resourcePath = getFullResourcePath(action,resourcePath,input)
|
92
|
+
|
93
|
+
#Get the path parameters
|
94
|
+
pathParams = getPathParams(action,queryParams,input)
|
95
|
+
#Get the body
|
96
|
+
body = getBody(action,input)
|
97
|
+
|
98
|
+
#Get the request Object
|
99
|
+
request = getRequestObject(resourcePath,action,pathParams,body)
|
100
|
+
|
101
|
+
#Add headers to request
|
102
|
+
headers.each do |key,value|
|
103
|
+
request.add_field(key,value)
|
104
|
+
end
|
105
|
+
|
106
|
+
fullUrl = @baseURL+resourcePath
|
107
|
+
#Sign and get back the request
|
108
|
+
request = Config.getAuthentication().signRequest(fullUrl,request,request.method,body,pathParams)
|
109
|
+
|
110
|
+
uri = URI.parse(@baseURL)
|
111
|
+
#Get the http object
|
112
|
+
http = getHTTPObject(uri)
|
113
|
+
|
114
|
+
if Config.isDebug
|
115
|
+
puts "---- Request ----"
|
116
|
+
puts ""
|
117
|
+
puts "URL"
|
118
|
+
puts @baseURL+request.path
|
119
|
+
puts ""
|
120
|
+
puts "Headers"
|
121
|
+
request.each_header do |header_name, header_value|
|
122
|
+
puts "#{header_name} : #{header_value}"
|
123
|
+
end
|
124
|
+
puts ""
|
125
|
+
puts "Body"
|
126
|
+
puts request.body
|
127
|
+
end
|
128
|
+
|
129
|
+
begin
|
130
|
+
response = http.request(request)
|
131
|
+
|
132
|
+
if Config.isDebug
|
133
|
+
puts "---- Response ----"
|
134
|
+
puts ""
|
135
|
+
puts "Status Code"
|
136
|
+
puts response.code
|
137
|
+
puts ""
|
138
|
+
puts "Headers"
|
139
|
+
response.each_header do |header_name, header_value|
|
140
|
+
puts "#{header_name} : #{header_value}"
|
141
|
+
end
|
142
|
+
puts ""
|
143
|
+
puts "Body"
|
144
|
+
puts response.body
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
return handleResponse(response,response.body)
|
149
|
+
rescue Errno::ECONNREFUSED
|
150
|
+
raise APIException.new ("Connection to server could not be established.")
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
|
160
|
+
def handleResponse(response,content)
|
161
|
+
#Handles the exception and response
|
162
|
+
status = response.code.to_i
|
163
|
+
|
164
|
+
if content
|
165
|
+
begin
|
166
|
+
content = JSON.load content
|
167
|
+
rescue JSON::ParserError
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
if 200 <= status && status <= 299
|
172
|
+
return content
|
173
|
+
elsif 300 <= status && status <= 399
|
174
|
+
raise InvalidRequestException.new("Unexpected response code returned from the API causing redirect",status,content)
|
175
|
+
elsif status == 400
|
176
|
+
raise InvalidRequestException.new("Bad request",status,content)
|
177
|
+
elsif status == 401
|
178
|
+
raise APIException.new("You are not authorized to make this request",status,content)
|
179
|
+
elsif status == 403
|
180
|
+
raise APIException.new("You are not authorized to make this request",status,content)
|
181
|
+
elsif status == 404
|
182
|
+
raise ObjectNotFoundException.new("Object not found",status,content)
|
183
|
+
elsif status == 405
|
184
|
+
raise APIException.new("Operation not allowed",status,content)
|
185
|
+
else
|
186
|
+
raise SystemException.new("Internal Server Error",status,content)
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
def getBody(action,input)
|
192
|
+
#Returns the body hash depending on action
|
193
|
+
body = nil
|
194
|
+
case action.upcase
|
195
|
+
when ACTION_CREATE, ACTION_UPDATE
|
196
|
+
unless input.nil?
|
197
|
+
body = input
|
198
|
+
end
|
199
|
+
end
|
200
|
+
return body
|
201
|
+
end
|
202
|
+
|
203
|
+
def getPathParams(action,queryParams,input)
|
204
|
+
#Returns the path params based on action
|
205
|
+
pathParams = {KEY_FORMAT => JSON_STR}
|
206
|
+
case action.upcase
|
207
|
+
when ACTION_LIST, ACTION_READ, ACTION_QUERY, ACTION_DELETE
|
208
|
+
unless input.nil?
|
209
|
+
pathParams = pathParams.merge(input)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
#merge the queryParams
|
214
|
+
pathParams = pathParams.merge(queryParams)
|
215
|
+
|
216
|
+
return pathParams
|
217
|
+
end
|
218
|
+
|
219
|
+
def getHTTPObject(uri)
|
220
|
+
#Returns the HTTP Object
|
221
|
+
http = Net::HTTP.new(uri.host,uri.port)
|
222
|
+
|
223
|
+
unless Config.isLocal()
|
224
|
+
http.use_ssl = true
|
225
|
+
end
|
226
|
+
|
227
|
+
return http
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
def encode_path_params(path, params)
|
232
|
+
#Encode and join the params
|
233
|
+
encoded = URI.encode_www_form(params)
|
234
|
+
[path, encoded].join("?")
|
235
|
+
end
|
236
|
+
|
237
|
+
def getRequestObject(path,action,pathParams,body)
|
238
|
+
#Retuns the request object based on action
|
239
|
+
case action.upcase
|
240
|
+
when ACTION_LIST, ACTION_READ, ACTION_QUERY
|
241
|
+
verb = Net::HTTP::Get
|
242
|
+
|
243
|
+
when ACTION_CREATE
|
244
|
+
verb = Net::HTTP::Post
|
245
|
+
|
246
|
+
when ACTION_DELETE
|
247
|
+
verb = Net::HTTP::Delete
|
248
|
+
|
249
|
+
when ACTION_UPDATE
|
250
|
+
verb = Net::HTTP::Put
|
251
|
+
else
|
252
|
+
raise APIException.new "Invalid action #{action}"
|
253
|
+
end
|
254
|
+
|
255
|
+
#add url parameters to path
|
256
|
+
path = encode_path_params(path,pathParams)
|
257
|
+
|
258
|
+
req = verb.new(path)
|
259
|
+
|
260
|
+
#Add default headers
|
261
|
+
req.add_field(KEY_ACCEPT,APPLICATION_JSON)
|
262
|
+
req.add_field(KEY_CONTENT_TYPE,APPLICATION_JSON)
|
263
|
+
req.add_field(KEY_USER_AGENT,RUBY_SDK+"/"+@version)
|
264
|
+
|
265
|
+
#Add body
|
266
|
+
|
267
|
+
unless body.nil?
|
268
|
+
req.body = body.to_json
|
269
|
+
end
|
270
|
+
|
271
|
+
return req
|
272
|
+
|
273
|
+
|
274
|
+
end
|
275
|
+
|
276
|
+
def preCheck()
|
277
|
+
#check if execute can be done
|
278
|
+
auth = Config.getAuthentication()
|
279
|
+
|
280
|
+
unless (auth.nil? || auth.is_a?(Authentication))
|
281
|
+
raise APIException.new "No or incorrect authentication has been configured"
|
282
|
+
end
|
283
|
+
|
284
|
+
end
|
285
|
+
|
286
|
+
def removeForwardSlashFromTail(text)
|
287
|
+
#
|
288
|
+
#Removes the trailing / from url if any and returns the url
|
289
|
+
|
290
|
+
if text.end_with? "/"
|
291
|
+
return text[0...-1]
|
292
|
+
end
|
293
|
+
|
294
|
+
return text
|
295
|
+
|
296
|
+
end
|
297
|
+
|
298
|
+
def getFullResourcePath(action,resourcePath,inputMap)
|
299
|
+
#
|
300
|
+
#Forms the complete URL by combining baseURL and replaced path variables in resourcePath from inputMap
|
301
|
+
|
302
|
+
|
303
|
+
#Remove the Trailing slash from the resource path
|
304
|
+
resourcePath = removeForwardSlashFromTail(resourcePath)
|
305
|
+
|
306
|
+
#Replace the path variables
|
307
|
+
resourcePath = Util.getReplacedPath(resourcePath,inputMap)
|
308
|
+
|
309
|
+
#This step is if id is in inputMap but was not specified in URL as /{id}
|
310
|
+
#If the action is read,update or delete we add this id
|
311
|
+
if inputMap.has_key?(KEY_ID)
|
312
|
+
if [ACTION_READ,ACTION_UPDATE,ACTION_DELETE].include? action.upcase
|
313
|
+
resourcePath += "/"+inputMap[KEY_ID].to_s
|
314
|
+
inputMap.delete(KEY_ID) #Remove from input path otherwise this would get add in query params as well
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
return resourcePath
|
319
|
+
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|