adyen 1.6.0 → 2.0.0.pre1
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 +4 -4
- data/.travis.yml +2 -0
- data/CHANGELOG.md +116 -0
- data/CONTRIBUTING.md +84 -0
- data/Gemfile +1 -1
- data/README.md +33 -0
- data/Rakefile +19 -4
- data/adyen.gemspec +7 -5
- data/config.ru +5 -0
- data/lib/adyen.rb +2 -2
- data/lib/adyen/configuration.rb +6 -0
- data/lib/adyen/form.rb +13 -48
- data/lib/adyen/matchers.rb +1 -1
- data/lib/adyen/rest.rb +53 -0
- data/lib/adyen/rest/authorise_payment.rb +148 -0
- data/lib/adyen/rest/client.rb +110 -0
- data/lib/adyen/rest/errors.rb +33 -0
- data/lib/adyen/rest/modify_payment.rb +97 -0
- data/lib/adyen/rest/request.rb +107 -0
- data/lib/adyen/rest/response.rb +59 -0
- data/lib/adyen/util.rb +147 -0
- data/lib/adyen/version.rb +1 -1
- data/test/form_test.rb +17 -10
- data/test/functional/payment_authorisation_api_test.rb +54 -0
- data/test/functional/payment_modification_api_test.rb +57 -0
- data/test/helpers/configure_adyen.rb +5 -0
- data/test/helpers/example_server.rb +105 -0
- data/test/helpers/public/adyen.encrypt.js +679 -0
- data/test/helpers/public/adyen.encrypt.min.js +14 -0
- data/test/helpers/test_cards.rb +20 -0
- data/test/helpers/views/authorized.erb +7 -0
- data/test/helpers/views/hpp.erb +19 -0
- data/test/helpers/views/index.erb +6 -0
- data/test/helpers/views/pay.erb +36 -0
- data/test/helpers/views/redirect_shopper.erb +18 -0
- data/test/integration/hpp_integration_test.rb +52 -0
- data/test/integration/payment_using_3d_secure_integration_test.rb +40 -0
- data/test/integration/payment_with_client_side_encryption_integration_test.rb +26 -0
- data/test/rest_request_test.rb +50 -0
- data/test/rest_response_test.rb +18 -0
- data/test/test_helper.rb +32 -0
- data/test/util_test.rb +77 -0
- metadata +89 -16
- data/README.rdoc +0 -50
- data/lib/adyen/encoding.rb +0 -21
- data/lib/adyen/formatter.rb +0 -33
- data/test/adyen_test.rb +0 -31
@@ -0,0 +1,107 @@
|
|
1
|
+
module Adyen
|
2
|
+
module REST
|
3
|
+
|
4
|
+
# The request object models an API request to be sent to Adyen's webservice.
|
5
|
+
#
|
6
|
+
# Some API calls may use a subclass to model their request.
|
7
|
+
#
|
8
|
+
# @!attribute prefix [r]
|
9
|
+
# The prefix to use for every request attribute (except action)
|
10
|
+
# @return [String]
|
11
|
+
# @!attribute form_data [r]
|
12
|
+
# The attributes to include in the API request as form data.
|
13
|
+
# @return [Hash<String, String>] A dictionary of key value pairs
|
14
|
+
# @!required_attributes [r]
|
15
|
+
# The list of required attributes that should show up in the request.
|
16
|
+
# {#validate!} will fail if any of these attributes is missing or empty.
|
17
|
+
# @return [Array<String>]
|
18
|
+
# @!attribute response_class [rw]
|
19
|
+
# The response class to use to wrap the HTTP response to this request.
|
20
|
+
# @return [Class]
|
21
|
+
# @!attribute response_options [rw]
|
22
|
+
# The options to send to the response class initializer.
|
23
|
+
# @return [Hash]
|
24
|
+
#
|
25
|
+
# @see Adyen::REST::Client
|
26
|
+
# @see Adyen::REST::Response
|
27
|
+
class Request
|
28
|
+
attr_reader :prefix, :form_data, :required_attributes
|
29
|
+
attr_accessor :response_class, :response_options
|
30
|
+
|
31
|
+
def initialize(action, attributes, options = {})
|
32
|
+
@prefix = options[:prefix]
|
33
|
+
@form_data = generate_form_data(action, attributes)
|
34
|
+
|
35
|
+
@response_class = options[:response_class] || Adyen::REST::Response
|
36
|
+
@response_options = options[:response_options] || {}
|
37
|
+
|
38
|
+
@required_attributes = ['action']
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns the request's action
|
42
|
+
# @return [String]
|
43
|
+
def action
|
44
|
+
form_data['action']
|
45
|
+
end
|
46
|
+
|
47
|
+
# Retrieves an attribute from the request
|
48
|
+
def [](attribute)
|
49
|
+
form_data[canonical_name(attribute)]
|
50
|
+
end
|
51
|
+
|
52
|
+
# Sets an attribute on the request
|
53
|
+
def []=(attribute, value)
|
54
|
+
form_data.merge!(flatten_attributes(attribute => value))
|
55
|
+
value
|
56
|
+
end
|
57
|
+
|
58
|
+
def merchant_account=(value)
|
59
|
+
self[:merchant_account] = value
|
60
|
+
end
|
61
|
+
|
62
|
+
# Runs validations on the request before it is sent.
|
63
|
+
# @return [void]
|
64
|
+
# @raises [Adyen::REST::RequestValidationFailed]
|
65
|
+
def validate!
|
66
|
+
required_attributes.each do |attribute|
|
67
|
+
if form_data[attribute].nil? || form_data[attribute].empty?
|
68
|
+
raise Adyen::REST::RequestValidationFailed, "#{attribute} is empty, but required!"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Builds a Adyen::REST::Response instnace for a given Net::HTTP response.
|
74
|
+
# @param http_response [Net::HTTPResponse] The HTTP response return for this request.
|
75
|
+
# @return [Adyen::REST::Response] An instance of {Adyen::REST::Response}, or a subclass.
|
76
|
+
def build_response(http_response)
|
77
|
+
response_class.new(http_response, response_options)
|
78
|
+
end
|
79
|
+
|
80
|
+
protected
|
81
|
+
|
82
|
+
def canonical_name(name)
|
83
|
+
Adyen::Util.camelize(apply_prefix(name))
|
84
|
+
end
|
85
|
+
|
86
|
+
def apply_prefix(name)
|
87
|
+
prefix ? name.to_s.sub(/\A(?!#{Regexp.quote(prefix)}\.)/, "#{prefix}.") : name.to_s
|
88
|
+
end
|
89
|
+
|
90
|
+
# Flattens the {#attributes} hash and converts all the keys to camelcase.
|
91
|
+
# @return [Hash] A potentially nested hash of attributes.
|
92
|
+
# @return [Hash<String, String>] A dictionary of API request attributes that
|
93
|
+
# can be included in an HTTP request as form data.
|
94
|
+
def flatten_attributes(attributes)
|
95
|
+
if prefix
|
96
|
+
Adyen::Util.flatten(prefix => attributes)
|
97
|
+
else
|
98
|
+
Adyen::Util.flatten(attributes)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def generate_form_data(action, attributes)
|
103
|
+
flatten_attributes(attributes).merge('action' => action.to_s)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Adyen
|
2
|
+
module REST
|
3
|
+
|
4
|
+
# The Response class models the HTTP response that is the result of a
|
5
|
+
# API call to Adyen's REST webservice.
|
6
|
+
#
|
7
|
+
# Some API calls may respond with an instance of a subclass, to make
|
8
|
+
# dealing with the response easier.
|
9
|
+
#
|
10
|
+
# @!attribute http_response [r]
|
11
|
+
# The underlying net/http response.
|
12
|
+
# @return [Net::HTTPResponse]
|
13
|
+
# @!attribute prefix [r]
|
14
|
+
# The prefix to use when reading attributes from the response
|
15
|
+
# @return [String]
|
16
|
+
#
|
17
|
+
# @see Adyen::REST::Client
|
18
|
+
# @see Adyen::REST::Request
|
19
|
+
class Response
|
20
|
+
attr_reader :http_response, :prefix, :attributes
|
21
|
+
|
22
|
+
def initialize(http_response, options = {})
|
23
|
+
@http_response = http_response
|
24
|
+
@prefix = options.key?(:prefix) ? options[:prefix].to_s : nil
|
25
|
+
@attributes = parse_response_attributes
|
26
|
+
end
|
27
|
+
|
28
|
+
# Looks up an attribute in the response.
|
29
|
+
# @return [String, nil] The value of the attribute if it was included in the response.
|
30
|
+
def [](name)
|
31
|
+
attributes[canonical_name(name)]
|
32
|
+
end
|
33
|
+
|
34
|
+
def has_attribute?(name)
|
35
|
+
attributes.has_key?(canonical_name(name))
|
36
|
+
end
|
37
|
+
|
38
|
+
def psp_reference
|
39
|
+
Integer(self[:psp_reference])
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def canonical_name(name)
|
45
|
+
Adyen::Util.camelize(apply_prefix(name))
|
46
|
+
end
|
47
|
+
|
48
|
+
def apply_prefix(name)
|
49
|
+
prefix ? name.to_s.sub(/\A(?!#{Regexp.quote(prefix)}\.)/, "#{prefix}.") : name.to_s
|
50
|
+
end
|
51
|
+
|
52
|
+
def parse_response_attributes
|
53
|
+
attributes = CGI.parse(http_response.body)
|
54
|
+
attributes.each { |key, values| attributes[key] = values.first }
|
55
|
+
attributes
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/adyen/util.rb
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'openssl'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
module Adyen
|
6
|
+
module Util
|
7
|
+
extend self
|
8
|
+
|
9
|
+
# Returns a valid Adyen string representation for a date
|
10
|
+
def format_date(date)
|
11
|
+
case date
|
12
|
+
when Date, DateTime, Time
|
13
|
+
date.strftime('%Y-%m-%d')
|
14
|
+
when String
|
15
|
+
raise ArgumentError, "Invalid date notation: #{date.inspect}!" unless /^\d{4}-\d{2}-\d{2}$/ =~ date
|
16
|
+
date
|
17
|
+
else
|
18
|
+
raise ArgumentError, "Cannot convert #{date.inspect} to date!"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns a valid Adyen string representation for a timestamp
|
23
|
+
def format_timestamp(time)
|
24
|
+
case time
|
25
|
+
when Date, DateTime, Time
|
26
|
+
time.strftime('%Y-%m-%dT%H:%M:%SZ')
|
27
|
+
when String
|
28
|
+
raise ArgumentError, "Invalid timestamp notation: #{time.inspect}!" unless /^\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}Z$/ =~ time
|
29
|
+
time
|
30
|
+
else
|
31
|
+
raise ArgumentError, "Cannot convert #{time.inspect} to timestamp!"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns a base64-encoded signature for a message
|
36
|
+
# @param [String] hmac_key The secret key to use for the HMAC signature.
|
37
|
+
# @param [String] message The message to sign.
|
38
|
+
# @return [String] The signature, base64-encoded.
|
39
|
+
def hmac_base64(hmac_key, message)
|
40
|
+
digest = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), hmac_key, message)
|
41
|
+
Base64.strict_encode64(digest).strip
|
42
|
+
end
|
43
|
+
|
44
|
+
# Retuns a message gzip-compressed and base64-encoded.
|
45
|
+
# @param [String] message The message to compress and encode.
|
46
|
+
# @return [String] The compressed and encoded version of the message
|
47
|
+
def gzip_base64(message)
|
48
|
+
sio = StringIO.new
|
49
|
+
gz = Zlib::GzipWriter.new(sio)
|
50
|
+
gz.write(message)
|
51
|
+
gz.close
|
52
|
+
Base64.strict_encode64(sio.string)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the camelized version of a string.
|
56
|
+
# @param [:to_s] identifier The identifier to turn to camelcase.
|
57
|
+
# @return [String] The camelcase version of the identifier provided.
|
58
|
+
def camelize(identifier)
|
59
|
+
CAMELCASE_EXCEPTIONS[identifier.to_s] || identifier.to_s.gsub(/_+(.)/) { $1.upcase }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the underscore version of a string.
|
63
|
+
# @param [:to_s] identifier The identifier to turn to underscore notation.
|
64
|
+
# @return [String] The underscore version of the identifier provided.
|
65
|
+
def underscore(identifier)
|
66
|
+
UNDERSCORE_EXCEPTIONS[identifier.to_s] || identifier.to_s
|
67
|
+
.gsub(/([A-Z]{2,})([A-Z])/) { "#{$1.downcase}#{$2}" }
|
68
|
+
.gsub(/(?!\A)([A-Z][a-z]*)/, '_\1')
|
69
|
+
.downcase
|
70
|
+
end
|
71
|
+
|
72
|
+
# Transforms the nested parameters Hash into a 'flat' Hash which is understood by adyen. This is:
|
73
|
+
# * all keys are camelized
|
74
|
+
# * all keys are stringified
|
75
|
+
# * nested hash is flattened, keys are prefixed with root key
|
76
|
+
#
|
77
|
+
# @example
|
78
|
+
# flatten {:billing_address => { :street => 'My Street'}}
|
79
|
+
#
|
80
|
+
# # resolves in:
|
81
|
+
# {'billingAddress.street' => 'My Street'}
|
82
|
+
#
|
83
|
+
# @param [Hash] nested_hash The nested hash to transform
|
84
|
+
# @param [String] prefix The prefix to add to the key
|
85
|
+
# @param [Hash] return_hash The new hash which is retruned (needed for recursive calls)
|
86
|
+
# @return [Hash] The return hash filled with camelized and prefixed key, stringified value
|
87
|
+
def flatten(nested_hash, prefix = "", return_hash = {})
|
88
|
+
nested_hash ||= {}
|
89
|
+
nested_hash.inject(return_hash) do |hash, (key, value)|
|
90
|
+
key = "#{prefix}#{camelize(key)}"
|
91
|
+
if value.is_a?(Hash)
|
92
|
+
flatten(value, "#{key}.", return_hash)
|
93
|
+
else
|
94
|
+
hash[key] = value.to_s
|
95
|
+
end
|
96
|
+
hash
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Transforms a flat hash into a nested hash structure.
|
101
|
+
# * all keys are underscored
|
102
|
+
# * all keys are stringified
|
103
|
+
# * flattened hash is deflattened, using . as namespace separator
|
104
|
+
#
|
105
|
+
# @example
|
106
|
+
# deflatten {'billingAddress.street' => 'My Street'}
|
107
|
+
#
|
108
|
+
# # resolves in:
|
109
|
+
# {'billing_address' => { 'street' => 'My Street'}}
|
110
|
+
#
|
111
|
+
# @param [Hash] flattened_hash The flat hash to transform
|
112
|
+
# @param [Hash] return_hash The new hash which will be returned (needed for recursive calls)
|
113
|
+
# @return [Hash] A nested hash structure, using strings as key.
|
114
|
+
def deflatten(flattened_hash, return_hash = {})
|
115
|
+
return return_hash if flattened_hash.nil?
|
116
|
+
flattened_hash.each do |key, value|
|
117
|
+
deflatten_pair(key, value, return_hash)
|
118
|
+
end
|
119
|
+
return_hash
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def deflatten_pair(key, value, return_hash)
|
125
|
+
head, rest = key.split('.', 2)
|
126
|
+
key = underscore(head)
|
127
|
+
if rest.nil?
|
128
|
+
raise ArgumentError, "Duplicate key in flattened hash." if return_hash.key?(key)
|
129
|
+
return_hash[key] = value
|
130
|
+
else
|
131
|
+
return_hash[key] ||= {}
|
132
|
+
raise ArgumentError, "Key nesting conflict in flattened hash." unless return_hash[key].is_a?(Hash)
|
133
|
+
deflatten_pair(rest, value, return_hash[key])
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# This hash contains exceptions to the standard underscore to camelcase conversion rules.
|
138
|
+
CAMELCASE_EXCEPTIONS = {
|
139
|
+
'shopper_ip' => 'shopperIP'
|
140
|
+
}
|
141
|
+
|
142
|
+
# This hash contains exceptions to the standard camelcase to underscore conversion rules.
|
143
|
+
UNDERSCORE_EXCEPTIONS = CAMELCASE_EXCEPTIONS.invert
|
144
|
+
|
145
|
+
private_constant :CAMELCASE_EXCEPTIONS, :UNDERSCORE_EXCEPTIONS
|
146
|
+
end
|
147
|
+
end
|
data/lib/adyen/version.rb
CHANGED
data/test/form_test.rb
CHANGED
@@ -29,7 +29,7 @@ class FormTest < Minitest::Test
|
|
29
29
|
:state_or_province => 'Berlin',
|
30
30
|
:country => 'Germany',
|
31
31
|
},
|
32
|
-
|
32
|
+
:shopper => {
|
33
33
|
:telephone_number => '1234512345',
|
34
34
|
:first_name => 'John',
|
35
35
|
:last_name => 'Doe',
|
@@ -90,7 +90,7 @@ class FormTest < Minitest::Test
|
|
90
90
|
|
91
91
|
params = CGI.parse(redirect_uri.query)
|
92
92
|
attributes.each do |key, value|
|
93
|
-
assert_equal value.to_s, params[Adyen::
|
93
|
+
assert_equal value.to_s, params[Adyen::Util.camelize(key).to_s].first
|
94
94
|
end
|
95
95
|
|
96
96
|
assert params.key?('merchantSig'), "Expected a merchantSig parameter to be set"
|
@@ -107,7 +107,7 @@ class FormTest < Minitest::Test
|
|
107
107
|
|
108
108
|
params = CGI.parse(redirect_uri.query)
|
109
109
|
attributes.each do |key, value|
|
110
|
-
assert_equal value.to_s, params[Adyen::
|
110
|
+
assert_equal value.to_s, params[Adyen::Util.camelize(key).to_s].first
|
111
111
|
end
|
112
112
|
|
113
113
|
assert params.key?('merchantSig'), "Expected a merchantSig parameter to be set"
|
@@ -158,9 +158,9 @@ class FormTest < Minitest::Test
|
|
158
158
|
|
159
159
|
def test_redirect_signature_check
|
160
160
|
params = {
|
161
|
-
|
162
|
-
|
163
|
-
|
161
|
+
'authResult' => 'AUTHORISED', 'pspReference' => '1211992213193029',
|
162
|
+
'merchantReference' => 'Internet Order 12345', 'skinCode' => '4aD37dJA',
|
163
|
+
'merchantSig' => 'ytt3QxWoEhAskUzUne0P5VA9lPw='
|
164
164
|
}
|
165
165
|
|
166
166
|
assert_equal params[:merchantSig], Adyen::Form.redirect_signature(params)
|
@@ -179,10 +179,17 @@ class FormTest < Minitest::Test
|
|
179
179
|
assert_raises(ArgumentError) { Adyen::Form.redirect_signature_check(params.delete(:skinCode)) }
|
180
180
|
end
|
181
181
|
|
182
|
-
def
|
183
|
-
|
184
|
-
|
185
|
-
|
182
|
+
def test_redirect_signature_check
|
183
|
+
Adyen.configuration.register_form_skin(:testing, 'tifSfXeX', 'testing123', :merchant_account => 'VanBergenORG')
|
184
|
+
|
185
|
+
# http://example.com/result?merchantReference=HPP+test+order+%25231&skinCode=tifSfXeX&shopperLocale=en_GB&paymentMethod=visa&authResult=AUTHORISED&pspReference=8814131153369759&merchantSig=il8cjgOiG4N9l2PlSf6h4EVQ6hk%253D
|
186
|
+
params = {
|
187
|
+
"merchantReference"=>CGI.unescape("HPP test order %231"), "skinCode"=>"tifSfXeX",
|
188
|
+
"shopperLocale"=>"en_GB", "paymentMethod"=>"visa", "authResult"=>"AUTHORISED",
|
189
|
+
"pspReference"=>"8814131148758652", "merchantSig"=> CGI.unescape("q8J9P%2Fp%2FYsbnnFn%2F83TFsv7Hais%3D")
|
190
|
+
}
|
191
|
+
|
192
|
+
assert_equal params['merchantSig'], Adyen::Form.redirect_signature(params)
|
186
193
|
end
|
187
194
|
|
188
195
|
def test_hidden_payment_form_fields
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class PaymentAuthorisationAPITest < Minitest::Test
|
4
|
+
def setup
|
5
|
+
@client = Adyen::REST.client
|
6
|
+
end
|
7
|
+
|
8
|
+
def teardown
|
9
|
+
@client.close
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_payment_api_request
|
13
|
+
response = @client.authorise_payment(
|
14
|
+
merchant_account: 'VanBergenORG',
|
15
|
+
amount: { currency: 'EUR', value: 1234 },
|
16
|
+
reference: 'Test order #1',
|
17
|
+
card: Adyen::TestCards::VISA
|
18
|
+
)
|
19
|
+
|
20
|
+
assert response.authorised?
|
21
|
+
assert response.psp_reference
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_refused_payment_api_request
|
25
|
+
response = @client.authorise_payment(
|
26
|
+
merchant_account: 'VanBergenORG',
|
27
|
+
amount: { currency: 'EUR', value: 1234 },
|
28
|
+
reference: 'Test order #1',
|
29
|
+
card: Adyen::TestCards::VISA.merge(cvc: '123')
|
30
|
+
)
|
31
|
+
|
32
|
+
assert response.refused?
|
33
|
+
assert response.psp_reference
|
34
|
+
assert response.has_attribute?(:refusal_reason)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_payment_with_3d_secure_api_request
|
38
|
+
response = @client.authorise_payment(
|
39
|
+
merchant_account: 'VanBergenORG',
|
40
|
+
amount: { currency: 'EUR', value: 1234 },
|
41
|
+
reference: 'Test order #1',
|
42
|
+
card: Adyen::TestCards::MASTERCARD_3DSECURE,
|
43
|
+
browser_info: {
|
44
|
+
acceptHeader: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
45
|
+
userAgent: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008052912 Firefox/3.0"
|
46
|
+
}
|
47
|
+
)
|
48
|
+
|
49
|
+
assert response.redirect_shopper?
|
50
|
+
assert response.psp_reference
|
51
|
+
assert response.has_attribute?(:md)
|
52
|
+
assert_equal "https://test.adyen.com/hpp/3d/validate.shtml", response['issuer_url']
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class PaymentModificationAPITest < Minitest::Test
|
4
|
+
def setup
|
5
|
+
@client = Adyen::REST.client
|
6
|
+
end
|
7
|
+
|
8
|
+
def teardown
|
9
|
+
@client.close
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_capture_payment_api_request
|
13
|
+
response = @client.capture_payment(
|
14
|
+
merchant_account: 'VanBergenORG',
|
15
|
+
modification_amount: { currency: 'EUR', value: 1234 },
|
16
|
+
reference: "functional test for cancellation",
|
17
|
+
original_reference: 7913939284323855
|
18
|
+
)
|
19
|
+
|
20
|
+
assert response.received?
|
21
|
+
assert response.psp_reference
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_cancel_payment_api_request
|
25
|
+
response = @client.cancel_payment(
|
26
|
+
merchant_account: 'VanBergenORG',
|
27
|
+
reference: "functional test for cancellation",
|
28
|
+
original_reference: 7913939284323855
|
29
|
+
)
|
30
|
+
|
31
|
+
assert response.received?
|
32
|
+
assert response.psp_reference
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_refund_payment_api_request
|
36
|
+
response = @client.refund_payment(
|
37
|
+
merchant_account: 'VanBergenORG',
|
38
|
+
modification_amount: { currency: 'EUR', value: 1234 },
|
39
|
+
reference: "functional test for cancellation",
|
40
|
+
original_reference: 7913939284323855
|
41
|
+
)
|
42
|
+
|
43
|
+
assert response.received?
|
44
|
+
assert response.psp_reference
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_cancel_or_refund_payment_api_request
|
48
|
+
response = @client.cancel_or_refund_payment(
|
49
|
+
merchant_account: 'VanBergenORG',
|
50
|
+
reference: "functional test for cancellation",
|
51
|
+
original_reference: 7913939284323855
|
52
|
+
)
|
53
|
+
|
54
|
+
assert response.received?
|
55
|
+
assert response.psp_reference
|
56
|
+
end
|
57
|
+
end
|