agms 0.1.0
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 +15 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/README.md +51 -0
- data/Rakefile +40 -0
- data/agms.gemspec +29 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/example/hpp.rb +18 -0
- data/example/invoicing.rb +23 -0
- data/example/recurring.rb +23 -0
- data/example/report.rb +16 -0
- data/example/safe.rb +17 -0
- data/example/transaction.rb +17 -0
- data/init.yml +9 -0
- data/lib/agms.rb +59 -0
- data/lib/agms/agms.rb +109 -0
- data/lib/agms/configuration.rb +71 -0
- data/lib/agms/connect.rb +176 -0
- data/lib/agms/error/agms_error.rb +9 -0
- data/lib/agms/error/authentication_error.rb +7 -0
- data/lib/agms/error/authorization_error.rb +7 -0
- data/lib/agms/error/client_error_error.rb +7 -0
- data/lib/agms/error/configuation_error.rb +7 -0
- data/lib/agms/error/down_for_maintenance_error.rb +7 -0
- data/lib/agms/error/forged_query_String_error.rb +7 -0
- data/lib/agms/error/invalid_parameter_error.rb +7 -0
- data/lib/agms/error/invalid_request_error.rb +7 -0
- data/lib/agms/error/invalid_signature_error.rb +7 -0
- data/lib/agms/error/not_found_error.rb +7 -0
- data/lib/agms/error/request_validation_error.rb +7 -0
- data/lib/agms/error/response_error.rb +7 -0
- data/lib/agms/error/server_error_error.rb +7 -0
- data/lib/agms/error/ssl_certificate_error.rb +7 -0
- data/lib/agms/error/unexpected_error.rb +7 -0
- data/lib/agms/error/upgrade_required_error.rb +7 -0
- data/lib/agms/hpp.rb +65 -0
- data/lib/agms/invoicing.rb +63 -0
- data/lib/agms/recurring.rb +76 -0
- data/lib/agms/report.rb +53 -0
- data/lib/agms/request/hpp_request.rb +181 -0
- data/lib/agms/request/invoicing_request.rb +8 -0
- data/lib/agms/request/recurring_request.rb +115 -0
- data/lib/agms/request/report_request.rb +106 -0
- data/lib/agms/request/request.rb +455 -0
- data/lib/agms/request/safe_request.rb +211 -0
- data/lib/agms/request/transaction_request.rb +217 -0
- data/lib/agms/response/hpp_response.rb +39 -0
- data/lib/agms/response/invoicing_response.rb +10 -0
- data/lib/agms/response/recurring_response.rb +28 -0
- data/lib/agms/response/report_response.rb +141 -0
- data/lib/agms/response/response.rb +48 -0
- data/lib/agms/response/safe_response.rb +51 -0
- data/lib/agms/response/transaction_response.rb +50 -0
- data/lib/agms/safe.rb +66 -0
- data/lib/agms/transaction.rb +37 -0
- data/lib/agms/version.rb +3 -0
- metadata +156 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
module Agms
|
3
|
+
class Configuration
|
4
|
+
# A class representing the configuration of AGMS Gateway
|
5
|
+
|
6
|
+
# Attribute accessor for the class method
|
7
|
+
class << self
|
8
|
+
attr_accessor :server
|
9
|
+
attr_accessor :port
|
10
|
+
attr_accessor :use_unsafe_ssl
|
11
|
+
attr_accessor :gateway_username
|
12
|
+
attr_accessor :gateway_password
|
13
|
+
attr_accessor :gateway_account
|
14
|
+
attr_accessor :gateway_api_key
|
15
|
+
attr_accessor :gateway_max_amount
|
16
|
+
attr_accessor :gateway_min_amount
|
17
|
+
attr_accessor :verbose
|
18
|
+
attr_accessor :hpp_template
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def self.init(init_file)
|
23
|
+
Configuration.server = 'gateway.agms.com'
|
24
|
+
Configuration.port = '443'
|
25
|
+
Configuration.use_unsafe_ssl = false
|
26
|
+
|
27
|
+
config = YAML::load_file(init_file)
|
28
|
+
Configuration.gateway_username = config['username']
|
29
|
+
Configuration.gateway_password = config['password']
|
30
|
+
Configuration.gateway_account = config['account']
|
31
|
+
Configuration.gateway_api_key = config['api_key']
|
32
|
+
Configuration.gateway_max_amount = config['max_amount']
|
33
|
+
Configuration.gateway_min_amount = config['min_amount']
|
34
|
+
if config['verbose']
|
35
|
+
Configuration.verbose = config['verbose']
|
36
|
+
end
|
37
|
+
if config['hpp_template']
|
38
|
+
Configuration.hpp_template = config['hpp_template']
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.configure(gateway_username, gateway_password, gateway_account=nil, gateway_api_key=nil)
|
43
|
+
Configuration.server = 'gateway.agms.com'
|
44
|
+
Configuration.port = '443'
|
45
|
+
Configuration.use_unsafe_ssl = false
|
46
|
+
|
47
|
+
Configuration.gateway_username = gateway_username
|
48
|
+
Configuration.gateway_password = gateway_password
|
49
|
+
Configuration.gateway_account = gateway_account
|
50
|
+
Configuration.gateway_api_key = gateway_api_key
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.instantiate()
|
54
|
+
return Configuration.new(
|
55
|
+
gateway_username = Configuration.gateway_username,
|
56
|
+
gateway_password = Configuration.gateway_password,
|
57
|
+
gateway_account = Configuration.gateway_account,
|
58
|
+
gateway_api_key = Configuration.gateway_api_key,
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
def initialize(gateway_username, gateway_password, gateway_account=nil, gateway_api_key=nil)
|
63
|
+
# TODO Add default value for max_amount and min_amount
|
64
|
+
@@gateway_username = gateway_username
|
65
|
+
@@gateway_password = gateway_password
|
66
|
+
@@gateway_account = gateway_account
|
67
|
+
@@gateway_api_key = gateway_api_key
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
data/lib/agms/connect.rb
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
module Agms
|
2
|
+
class Connect
|
3
|
+
|
4
|
+
def self.is_exception_status(status)
|
5
|
+
if [200, 201, 422].include?(status)
|
6
|
+
return true
|
7
|
+
else
|
8
|
+
return false
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.raise_exception_for_status(status, message=nil)
|
13
|
+
case status.to_i
|
14
|
+
when 401
|
15
|
+
raise AuthenticationError
|
16
|
+
when 403
|
17
|
+
raise AuthorizationError, message
|
18
|
+
when 404
|
19
|
+
raise NotFoundError
|
20
|
+
when 426
|
21
|
+
raise UpgradeRequiredError
|
22
|
+
when 500
|
23
|
+
raise ServerError
|
24
|
+
when 503
|
25
|
+
raise DownForMaintenanceError
|
26
|
+
else
|
27
|
+
raise UnexpectedError, "Unexpected HTTP_RESPONSE #{status.to_i}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(config)
|
32
|
+
@config = config
|
33
|
+
end
|
34
|
+
|
35
|
+
def connect(url, request, request_method, response_object)
|
36
|
+
headers = _buildHeaders(request_method)
|
37
|
+
request_body = _buildRequest(request, request_method)
|
38
|
+
response_body = post(url, headers, request_body)
|
39
|
+
return _parseResponse(response_body, request_method)
|
40
|
+
end
|
41
|
+
|
42
|
+
def post(url, headers = nil, body = nil)
|
43
|
+
return _http_do(Net::HTTP::Post, url, headers, body)
|
44
|
+
end
|
45
|
+
|
46
|
+
def delete(url, headers = nil, body = nil)
|
47
|
+
return _http_do(Net::HTTP::Delete, url, headers, body)
|
48
|
+
end
|
49
|
+
|
50
|
+
def get(url, headers = nil, body = nil)
|
51
|
+
return _http_do Net::HTTP::Get, url, headers, body
|
52
|
+
end
|
53
|
+
|
54
|
+
def put(url, headers = nil, body = nil)
|
55
|
+
return _http_do Net::HTTP::Put, url, headers, body
|
56
|
+
end
|
57
|
+
|
58
|
+
def _http_do(http_verb, url, headers = nil, body = nil)
|
59
|
+
connection = Net::HTTP.new(Configuration.server, Configuration.port)
|
60
|
+
connection.open_timeout = 60
|
61
|
+
connection.read_timeout = 60
|
62
|
+
|
63
|
+
connection.use_ssl = true
|
64
|
+
connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
65
|
+
|
66
|
+
# connection.ca_file = @config.ca_file
|
67
|
+
connection.verify_callback = proc { |preverify_ok, ssl_context| _verify_ssl_certificate(preverify_ok, ssl_context) }
|
68
|
+
|
69
|
+
# Debug connection
|
70
|
+
if Configuration.verbose
|
71
|
+
connection.set_debug_output($stdout)
|
72
|
+
end
|
73
|
+
|
74
|
+
connection.start do |http|
|
75
|
+
request = http_verb.new(url)
|
76
|
+
|
77
|
+
if headers
|
78
|
+
headers.each do |key, value|
|
79
|
+
request[key] = value
|
80
|
+
end
|
81
|
+
end
|
82
|
+
if body
|
83
|
+
request.body = body
|
84
|
+
end
|
85
|
+
|
86
|
+
response = http.request(request)
|
87
|
+
if response.code.to_i == 200 || response.code.to_i == 201 || response.code.to_i == 422
|
88
|
+
return response.body
|
89
|
+
else
|
90
|
+
Connect.raise_exception_for_status(response.code)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
rescue OpenSSL::SSL::SSLError
|
94
|
+
raise SSLCertificateError
|
95
|
+
end
|
96
|
+
|
97
|
+
# Build Header
|
98
|
+
def _buildHeaders(request_method)
|
99
|
+
return {
|
100
|
+
'Accept' => 'application/xml',
|
101
|
+
'Content-type' => 'text/xml; charset=utf-8',
|
102
|
+
'User-Agent' => '(Agms Ruby ' + Agms.getLibraryVersion() + ')',
|
103
|
+
'X-ApiVersion' => Agms.getAPIVersion(),
|
104
|
+
'SOAPAction' => 'https://gateway.agms.com/roxapi/' + request_method
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
# Build Request
|
109
|
+
def _buildRequest(request, request_method)
|
110
|
+
header = '<soap:Envelope
|
111
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
112
|
+
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
113
|
+
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
|
114
|
+
<soap:Body>'
|
115
|
+
|
116
|
+
header_line = '<' + request_method + ' xmlns="https://gateway.agms.com/roxapi/">'
|
117
|
+
body = _hashToXml(request)
|
118
|
+
footer_line = '</' + request_method + '>'
|
119
|
+
footer = '</soap:Body></soap:Envelope>'
|
120
|
+
return header + header_line + body + footer_line + footer
|
121
|
+
end
|
122
|
+
|
123
|
+
# Build xml from Hash
|
124
|
+
def _hashToXml(request)
|
125
|
+
data = ''
|
126
|
+
request.each do |key, value|
|
127
|
+
if value != ''
|
128
|
+
# Open Tag
|
129
|
+
data = data + "<#{key}>"
|
130
|
+
# Check whether value is still a hash
|
131
|
+
if value.class == Hash
|
132
|
+
value = _hashToXml(value)
|
133
|
+
end
|
134
|
+
# Add data
|
135
|
+
data = data + "#{value}"
|
136
|
+
# Close Tag
|
137
|
+
data = data + "</#{key}>"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
return data
|
141
|
+
end
|
142
|
+
|
143
|
+
def _verify_ssl_certificate(preverify_ok, ssl_context)
|
144
|
+
if preverify_ok != true || ssl_context.error != 0
|
145
|
+
err_msg = "SSL Verification failed -- Preverify: #{preverify_ok}, Error: #{ssl_context.error_string} (#{ssl_context.error})"
|
146
|
+
@config.logger.error err_msg
|
147
|
+
false
|
148
|
+
else
|
149
|
+
true
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Parse the response received from gateway
|
154
|
+
def _parseResponse(xml, request_method)
|
155
|
+
# Parse the response body
|
156
|
+
doc = Nokogiri::XML(xml)
|
157
|
+
# Remove the namespaces
|
158
|
+
doc.remove_namespaces!
|
159
|
+
response = {}
|
160
|
+
# Extract the response data from the #{request_method}Result node
|
161
|
+
if request_method != 'ReturnHostedPaymentSetup'
|
162
|
+
doc.xpath("//#{request_method}Result//*").each do |node|
|
163
|
+
response[node.name] = node.children.text
|
164
|
+
end
|
165
|
+
else
|
166
|
+
doc.xpath("//#{request_method}Response//*").each do |node|
|
167
|
+
response = node.children.text
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
return response
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
end
|
176
|
+
end
|
data/lib/agms/hpp.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
module Agms
|
2
|
+
class HPP < Agms
|
3
|
+
# A class representing AGMS HPP objects.
|
4
|
+
|
5
|
+
alias AgmsResetParameters resetParameters
|
6
|
+
alias AgmsSetParameter setParameter
|
7
|
+
alias AgmsDoConnect doConnect
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
super()
|
11
|
+
@api_url = 'https://gateway.agms.com/roxapi/AGMS_HostedPayment.asmx'
|
12
|
+
@requestObject = 'HPPRequest'
|
13
|
+
@responseObject = 'HPPResponse'
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Object]
|
17
|
+
def generate(params)
|
18
|
+
@op = 'ReturnHostedPaymentSetup'
|
19
|
+
AgmsResetParameters()
|
20
|
+
params.each do |param, config|
|
21
|
+
AgmsSetParameter(param, config)
|
22
|
+
end
|
23
|
+
self.execute()
|
24
|
+
return @response.toArray()
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [String]
|
28
|
+
def getHash
|
29
|
+
return @hash
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [String]
|
33
|
+
def getLink
|
34
|
+
if not @hash
|
35
|
+
raise UnexpectedError, 'Requested HPP link but no hash generated in HPP.'
|
36
|
+
else
|
37
|
+
format_field = @request.getField(:HPPFormat)
|
38
|
+
if format_field[:value]
|
39
|
+
if format_field[:value] == '1'
|
40
|
+
return "https://gateway.agms.com/HostedPaymentForm/HostedPaymentPage.aspx?hash=#{@hash}"
|
41
|
+
else
|
42
|
+
return "https://gateway.agms.com/HostedPaymentForm/HostedPaymentPage2.aspx?hash=#{@hash}"
|
43
|
+
end
|
44
|
+
else
|
45
|
+
if @@Configuration.Hpp_Template == 'TEMPLATE_1'
|
46
|
+
return "https://gateway.agms.com/HostedPaymentForm/HostedPaymentPage.aspx?hash=#{@hash}"
|
47
|
+
else
|
48
|
+
return "https://gateway.agms.com/HostedPaymentForm/HostedPaymentPage2.aspx?hash=#{@hash}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
def execute
|
56
|
+
if @op == 'ReturnHostedPaymentSetup'
|
57
|
+
AgmsDoConnect('ReturnHostedPaymentSetup', @responseObject)
|
58
|
+
@hash = @response.getHash
|
59
|
+
else
|
60
|
+
raise InvalidRequestError, "Invalid request to Transaction API #{@op}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|