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.
Files changed (58) hide show
  1. checksums.yaml +15 -0
  2. data/.travis.yml +3 -0
  3. data/Gemfile +4 -0
  4. data/README.md +51 -0
  5. data/Rakefile +40 -0
  6. data/agms.gemspec +29 -0
  7. data/bin/console +14 -0
  8. data/bin/setup +7 -0
  9. data/example/hpp.rb +18 -0
  10. data/example/invoicing.rb +23 -0
  11. data/example/recurring.rb +23 -0
  12. data/example/report.rb +16 -0
  13. data/example/safe.rb +17 -0
  14. data/example/transaction.rb +17 -0
  15. data/init.yml +9 -0
  16. data/lib/agms.rb +59 -0
  17. data/lib/agms/agms.rb +109 -0
  18. data/lib/agms/configuration.rb +71 -0
  19. data/lib/agms/connect.rb +176 -0
  20. data/lib/agms/error/agms_error.rb +9 -0
  21. data/lib/agms/error/authentication_error.rb +7 -0
  22. data/lib/agms/error/authorization_error.rb +7 -0
  23. data/lib/agms/error/client_error_error.rb +7 -0
  24. data/lib/agms/error/configuation_error.rb +7 -0
  25. data/lib/agms/error/down_for_maintenance_error.rb +7 -0
  26. data/lib/agms/error/forged_query_String_error.rb +7 -0
  27. data/lib/agms/error/invalid_parameter_error.rb +7 -0
  28. data/lib/agms/error/invalid_request_error.rb +7 -0
  29. data/lib/agms/error/invalid_signature_error.rb +7 -0
  30. data/lib/agms/error/not_found_error.rb +7 -0
  31. data/lib/agms/error/request_validation_error.rb +7 -0
  32. data/lib/agms/error/response_error.rb +7 -0
  33. data/lib/agms/error/server_error_error.rb +7 -0
  34. data/lib/agms/error/ssl_certificate_error.rb +7 -0
  35. data/lib/agms/error/unexpected_error.rb +7 -0
  36. data/lib/agms/error/upgrade_required_error.rb +7 -0
  37. data/lib/agms/hpp.rb +65 -0
  38. data/lib/agms/invoicing.rb +63 -0
  39. data/lib/agms/recurring.rb +76 -0
  40. data/lib/agms/report.rb +53 -0
  41. data/lib/agms/request/hpp_request.rb +181 -0
  42. data/lib/agms/request/invoicing_request.rb +8 -0
  43. data/lib/agms/request/recurring_request.rb +115 -0
  44. data/lib/agms/request/report_request.rb +106 -0
  45. data/lib/agms/request/request.rb +455 -0
  46. data/lib/agms/request/safe_request.rb +211 -0
  47. data/lib/agms/request/transaction_request.rb +217 -0
  48. data/lib/agms/response/hpp_response.rb +39 -0
  49. data/lib/agms/response/invoicing_response.rb +10 -0
  50. data/lib/agms/response/recurring_response.rb +28 -0
  51. data/lib/agms/response/report_response.rb +141 -0
  52. data/lib/agms/response/response.rb +48 -0
  53. data/lib/agms/response/safe_response.rb +51 -0
  54. data/lib/agms/response/transaction_response.rb +50 -0
  55. data/lib/agms/safe.rb +66 -0
  56. data/lib/agms/transaction.rb +37 -0
  57. data/lib/agms/version.rb +3 -0
  58. 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
@@ -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
@@ -0,0 +1,9 @@
1
+ module Agms
2
+ class AgmsError < StandardError
3
+ attr_accessor :object
4
+ def initialize(message = nil, object = nil)
5
+ super(message)
6
+ self.object = object
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class AuthenticationError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class AuthorizationError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class ClientErrorError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class ConfigurationError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class DownForMaintenanceError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class ForgedQueryStringError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class InvalidParameterError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class InvalidRequestError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class InvalidSignatureError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class NotFoundError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class RequestValidationError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class ResponseError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class ServerErrorError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class SSLCertificateError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class UnexpectedError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agms
2
+ class UpgradeRequiredError < AgmsError
3
+ def initialize(message, object)
4
+ super(message, object)
5
+ end
6
+ end
7
+ end
@@ -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