adyen_jpiqueras 2.3.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 +7 -0
- data/.gitignore +14 -0
- data/.travis.yml +30 -0
- data/CHANGELOG.md +128 -0
- data/CONTRIBUTING.md +85 -0
- data/Gemfile +11 -0
- data/LICENSE +21 -0
- data/README.md +31 -0
- data/Rakefile +54 -0
- data/adyen_jpiqueras.gemspec +44 -0
- data/config.ru +5 -0
- data/lib/adyen.rb +16 -0
- data/lib/adyen/api.rb +424 -0
- data/lib/adyen/api/cacert.pem +3894 -0
- data/lib/adyen/api/payment_service.rb +374 -0
- data/lib/adyen/api/recurring_service.rb +188 -0
- data/lib/adyen/api/response.rb +61 -0
- data/lib/adyen/api/simple_soap_client.rb +134 -0
- data/lib/adyen/api/templates/payment_service.rb +159 -0
- data/lib/adyen/api/templates/recurring_service.rb +71 -0
- data/lib/adyen/api/test_helpers.rb +133 -0
- data/lib/adyen/api/xml_querier.rb +137 -0
- data/lib/adyen/base.rb +17 -0
- data/lib/adyen/configuration.rb +179 -0
- data/lib/adyen/form.rb +419 -0
- data/lib/adyen/hpp.rb +27 -0
- data/lib/adyen/hpp/request.rb +192 -0
- data/lib/adyen/hpp/response.rb +52 -0
- data/lib/adyen/hpp/signature.rb +34 -0
- data/lib/adyen/matchers.rb +92 -0
- data/lib/adyen/notification_generator.rb +30 -0
- data/lib/adyen/railtie.rb +13 -0
- data/lib/adyen/rest.rb +67 -0
- data/lib/adyen/rest/authorise_payment.rb +234 -0
- data/lib/adyen/rest/authorise_recurring_payment.rb +46 -0
- data/lib/adyen/rest/client.rb +127 -0
- data/lib/adyen/rest/errors.rb +33 -0
- data/lib/adyen/rest/modify_payment.rb +89 -0
- data/lib/adyen/rest/payout.rb +89 -0
- data/lib/adyen/rest/request.rb +104 -0
- data/lib/adyen/rest/response.rb +80 -0
- data/lib/adyen/rest/signature.rb +27 -0
- data/lib/adyen/signature.rb +76 -0
- data/lib/adyen/templates/notification_migration.rb +29 -0
- data/lib/adyen/templates/notification_model.rb +69 -0
- data/lib/adyen/util.rb +147 -0
- data/lib/adyen/version.rb +5 -0
- data/spec/api/api_spec.rb +231 -0
- data/spec/api/payment_service_spec.rb +505 -0
- data/spec/api/recurring_service_spec.rb +236 -0
- data/spec/api/response_spec.rb +59 -0
- data/spec/api/simple_soap_client_spec.rb +133 -0
- data/spec/api/spec_helper.rb +463 -0
- data/spec/api/test_helpers_spec.rb +84 -0
- data/spec/functional/api_spec.rb +117 -0
- data/spec/functional/initializer.rb.ci +3 -0
- data/spec/functional/initializer.rb.sample +3 -0
- data/spec/spec_helper.rb +8 -0
- data/test/form_test.rb +303 -0
- data/test/functional/payment_authorisation_api_test.rb +107 -0
- data/test/functional/payment_modification_api_test.rb +58 -0
- data/test/functional/payout_api_test.rb +93 -0
- data/test/helpers/capybara.rb +12 -0
- data/test/helpers/configure_adyen.rb +6 -0
- data/test/helpers/example_server.rb +136 -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 +20 -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/hpp/signature_test.rb +37 -0
- data/test/hpp_test.rb +250 -0
- data/test/integration/hpp_integration_test.rb +52 -0
- data/test/integration/payment_using_3d_secure_integration_test.rb +41 -0
- data/test/integration/payment_with_client_side_encryption_integration_test.rb +26 -0
- data/test/rest/signature_test.rb +36 -0
- data/test/rest_list_recurring_details_response_test.rb +22 -0
- data/test/rest_request_test.rb +43 -0
- data/test/rest_response_test.rb +19 -0
- data/test/signature_test.rb +76 -0
- data/test/test_helper.rb +45 -0
- data/test/util_test.rb +78 -0
- data/yard_extensions.rb +16 -0
- metadata +308 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
module Adyen
|
2
|
+
module API
|
3
|
+
# The base class of all responses returned by API calls to Adyen.
|
4
|
+
class Response
|
5
|
+
# Defines shortcut accessor methods, to {Response#params}, for the given parameters.
|
6
|
+
def self.response_attrs(*attrs)
|
7
|
+
attrs.each do |attr|
|
8
|
+
define_method(attr) { params[attr] }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Net::HTTPResponse] The response object returned by Net::HTTP.
|
13
|
+
attr_reader :http_response
|
14
|
+
|
15
|
+
# @param [Net::HTTPResponse] http_response The response object returned by Net::HTTP.
|
16
|
+
def initialize(http_response)
|
17
|
+
@http_response = http_response
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [String] The raw body of the response object.
|
21
|
+
def body
|
22
|
+
@http_response.body
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Boolean] Whether or not the request was successful.
|
26
|
+
def success?
|
27
|
+
!http_failure?
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [Boolean] Whether or not the HTTP request was a success.
|
31
|
+
def http_failure?
|
32
|
+
!@http_response.is_a?(Net::HTTPSuccess)
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Boolean] Whether or not the SOAP request itself was a success.
|
36
|
+
# Adyen returns a 500 status code for e.g. failed CC validation and in this case, we don't
|
37
|
+
# want to throw a server error but rather treat it as something normal.
|
38
|
+
def server_error?
|
39
|
+
@http_response.is_a?(Net::HTTPServerError) && fault_message.nil?
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [XMLQuerier] The response body wrapped in a XMLQuerier.
|
43
|
+
def xml_querier
|
44
|
+
@xml_querier ||= XMLQuerier.xml(@http_response.body)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [Hash] Subclasses return the parsed response body.
|
48
|
+
def params
|
49
|
+
raise "The Adyen::API::Response#params method should be overridden in a subclass."
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [String,nil] The SOAP failure message, if there is one.
|
53
|
+
def fault_message
|
54
|
+
@fault_message ||= begin
|
55
|
+
message = xml_querier.text('//soap:Fault/faultstring')
|
56
|
+
message unless message.empty?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'net/https'
|
2
|
+
|
3
|
+
require 'adyen/api/response'
|
4
|
+
require 'adyen/api/xml_querier'
|
5
|
+
|
6
|
+
module Adyen
|
7
|
+
module API
|
8
|
+
# The base class of the API classes that map to Adyen SOAP services.
|
9
|
+
class SimpleSOAPClient
|
10
|
+
# @private
|
11
|
+
ENVELOPE = <<-EOXML.strip.freeze
|
12
|
+
<?xml version="1.0"?>
|
13
|
+
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
14
|
+
<soap:Body>
|
15
|
+
%s
|
16
|
+
</soap:Body>
|
17
|
+
</soap:Envelope>
|
18
|
+
EOXML
|
19
|
+
|
20
|
+
# A CA file used to verify certificates when connecting to Adyen.
|
21
|
+
#
|
22
|
+
# @see http://curl.haxx.se/ca/cacert.pem
|
23
|
+
CACERT = File.expand_path('../cacert.pem', __FILE__)
|
24
|
+
|
25
|
+
class StandardError < ::StandardError
|
26
|
+
def initialize(response, action, endpoint)
|
27
|
+
@response, @action, @endpoint = response, action, endpoint
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def message_prefix
|
33
|
+
%{[#{@response.http_response.code} #{@response.http_response.message}] A %s error occurred while calling SOAP action `#{@action}' on endpoint `#{@endpoint}'.}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class ClientError < StandardError
|
38
|
+
def message
|
39
|
+
"#{message_prefix % "client"} Fault message: #{@response.fault_message}."
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class ServerError < StandardError
|
44
|
+
def message
|
45
|
+
message_prefix % 'server'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class << self
|
50
|
+
# When a response instance has been assigned, the subsequent call to
|
51
|
+
# {SimpleSOAPClient#call_webservice_action} will not make a remote call, but simply return
|
52
|
+
# the stubbed response instance. This is obviously meant for making payments from tests.
|
53
|
+
#
|
54
|
+
# @see PaymentService::TestHelpers
|
55
|
+
# @see RecurringService::TestHelpers
|
56
|
+
#
|
57
|
+
# @return [Response] The stubbed Response subclass instance.
|
58
|
+
attr_accessor :stubbed_response
|
59
|
+
|
60
|
+
# @return [URI] A URI based on the ENDPOINT_URI constant defined on subclasses, where
|
61
|
+
# the environment type has been interpolated. E.g. Test environment.
|
62
|
+
def endpoint
|
63
|
+
@endpoint ||= URI.parse(const_get('ENDPOINT_URI') % Adyen.configuration.environment)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# @return [Hash] A hash of key-value pairs required for the action that is to be called.
|
68
|
+
attr_reader :params
|
69
|
+
|
70
|
+
# @param [Hash] params A hash of key-value pairs required for the action that is to be called.
|
71
|
+
# These are merged with the Adyen::API.default_params.
|
72
|
+
def initialize(params = {})
|
73
|
+
@params = Adyen.configuration.default_api_params.merge(params)
|
74
|
+
end
|
75
|
+
|
76
|
+
def validate_parameter_value!(param, value)
|
77
|
+
if value.nil? || value =~ /^\s*$/
|
78
|
+
raise ArgumentError, "The required parameter `:#{param}' is missing."
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def validate_parameters!(*params)
|
83
|
+
params.each do |param|
|
84
|
+
case param
|
85
|
+
when Symbol
|
86
|
+
validate_parameter_value!(param, @params[param])
|
87
|
+
when Hash
|
88
|
+
param.each do |name, attrs|
|
89
|
+
validate_parameter_value!(name, @params[name])
|
90
|
+
attrs.each { |attr| validate_parameter_value!("#{name} => :#{attr}", @params[name][attr]) }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# This method wraps the given XML +data+ in a SOAP envelope and posts it to +action+ on the
|
97
|
+
# +endpoint+ defined for the subclass.
|
98
|
+
#
|
99
|
+
# The result is a response object, with XMLQuerier, ready to be queried.
|
100
|
+
#
|
101
|
+
# If a {stubbed_response} has been set, then said response is returned and no actual remote
|
102
|
+
# calls are made.
|
103
|
+
#
|
104
|
+
# @param [String] action The remote action to call.
|
105
|
+
# @param [String] data The XML data to post to the remote action.
|
106
|
+
# @param [Response] response_class The Response subclass used to wrap the response from Adyen.
|
107
|
+
def call_webservice_action(action, data, response_class)
|
108
|
+
if response = self.class.stubbed_response
|
109
|
+
self.class.stubbed_response = nil
|
110
|
+
response
|
111
|
+
else
|
112
|
+
endpoint = self.class.endpoint
|
113
|
+
|
114
|
+
post = Net::HTTP::Post.new(endpoint.path, 'Accept' => 'text/xml', 'Content-Type' => 'text/xml; charset=utf-8', 'SOAPAction' => action)
|
115
|
+
post.basic_auth(Adyen.configuration.api_username, Adyen.configuration.api_password)
|
116
|
+
post.body = ENVELOPE % data
|
117
|
+
|
118
|
+
request = Net::HTTP.new(endpoint.host, endpoint.port)
|
119
|
+
request.use_ssl = true
|
120
|
+
request.ca_file = CACERT
|
121
|
+
request.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
122
|
+
|
123
|
+
request.start do |http|
|
124
|
+
http_response = http.request(post)
|
125
|
+
response = response_class.new(http_response)
|
126
|
+
raise ClientError.new(response, action, endpoint) if http_response.is_a?(Net::HTTPClientError)
|
127
|
+
raise ServerError.new(response, action, endpoint) if response.server_error?
|
128
|
+
response
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
module Adyen
|
2
|
+
module API
|
3
|
+
class PaymentService < SimpleSOAPClient
|
4
|
+
class << self
|
5
|
+
private
|
6
|
+
|
7
|
+
def modification_request(method, body = nil)
|
8
|
+
<<-EOXML
|
9
|
+
<payment:#{method} xmlns:payment="http://payment.services.adyen.com" xmlns:recurring="http://recurring.services.adyen.com" xmlns:common="http://common.services.adyen.com">
|
10
|
+
<payment:modificationRequest>
|
11
|
+
<payment:merchantAccount>%s</payment:merchantAccount>
|
12
|
+
<payment:originalReference>%s</payment:originalReference>
|
13
|
+
#{body}
|
14
|
+
</payment:modificationRequest>
|
15
|
+
</payment:#{method}>
|
16
|
+
EOXML
|
17
|
+
end
|
18
|
+
|
19
|
+
def modification_request_with_amount(method)
|
20
|
+
modification_request(method, <<-EOXML)
|
21
|
+
<payment:modificationAmount>
|
22
|
+
<common:currency>%s</common:currency>
|
23
|
+
<common:value>%s</common:value>
|
24
|
+
</payment:modificationAmount>
|
25
|
+
EOXML
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# @private
|
30
|
+
CAPTURE_LAYOUT = modification_request_with_amount(:capture)
|
31
|
+
# @private
|
32
|
+
REFUND_LAYOUT = modification_request_with_amount(:refund)
|
33
|
+
# @private
|
34
|
+
CANCEL_LAYOUT = modification_request(:cancel)
|
35
|
+
# @private
|
36
|
+
CANCEL_OR_REFUND_LAYOUT = modification_request(:cancelOrRefund)
|
37
|
+
|
38
|
+
# @private
|
39
|
+
LAYOUT = <<-EOXML
|
40
|
+
<payment:authorise xmlns:payment="http://payment.services.adyen.com" xmlns:recurring="http://recurring.services.adyen.com" xmlns:common="http://common.services.adyen.com">
|
41
|
+
<payment:paymentRequest>
|
42
|
+
<payment:merchantAccount>%s</payment:merchantAccount>
|
43
|
+
<payment:reference>%s</payment:reference>
|
44
|
+
%s
|
45
|
+
</payment:paymentRequest>
|
46
|
+
</payment:authorise>
|
47
|
+
EOXML
|
48
|
+
|
49
|
+
# @private
|
50
|
+
AMOUNT_PARTIAL = <<-EOXML
|
51
|
+
<payment:amount>
|
52
|
+
<common:currency>%s</common:currency>
|
53
|
+
<common:value>%s</common:value>
|
54
|
+
</payment:amount>
|
55
|
+
EOXML
|
56
|
+
|
57
|
+
# @private
|
58
|
+
CARD_PARTIAL = <<-EOXML
|
59
|
+
<payment:card>
|
60
|
+
<payment:holderName>%s</payment:holderName>
|
61
|
+
<payment:number>%s</payment:number>
|
62
|
+
<payment:expiryYear>%s</payment:expiryYear>
|
63
|
+
<payment:expiryMonth>%02d</payment:expiryMonth>
|
64
|
+
%s
|
65
|
+
</payment:card>
|
66
|
+
EOXML
|
67
|
+
|
68
|
+
# @private
|
69
|
+
CARD_CVC_PARTIAL = <<-EOXML
|
70
|
+
<payment:cvc>%s</payment:cvc>
|
71
|
+
EOXML
|
72
|
+
|
73
|
+
# @private
|
74
|
+
ONE_CLICK_CARD_PARTIAL = <<-EOXML
|
75
|
+
<payment:card>
|
76
|
+
<payment:cvc>%s</payment:cvc>
|
77
|
+
</payment:card>
|
78
|
+
EOXML
|
79
|
+
|
80
|
+
# @private
|
81
|
+
INSTALLMENTS_PARTIAL = <<-EOXML
|
82
|
+
<payment:installments>
|
83
|
+
<common:value>%s</common:value>
|
84
|
+
</payment:installments>
|
85
|
+
EOXML
|
86
|
+
|
87
|
+
SOCIAL_SECURITY_NUMBER_PARTIAL = <<-EOXML
|
88
|
+
<payment:socialSecurityNumber>%s</payment:socialSecurityNumber>
|
89
|
+
EOXML
|
90
|
+
|
91
|
+
# @private
|
92
|
+
DELIVERY_DATE_PARTIAL = <<-EOXML
|
93
|
+
<deliveryDate xmlns="http://payment.services.adyen.com">%s</deliveryDate>
|
94
|
+
EOXML
|
95
|
+
|
96
|
+
# @private
|
97
|
+
SELECTED_BRAND_PARTIAL = <<-EOXML
|
98
|
+
<payment:selectedBrand>%s</payment:selectedBrand>
|
99
|
+
EOXML
|
100
|
+
|
101
|
+
# @private
|
102
|
+
SHOPPER_NAME_PARTIAL = <<-EOXML
|
103
|
+
<payment:shopperName>
|
104
|
+
<common:firstName>%s</common:firstName>
|
105
|
+
<common:lastName>%s</common:lastName>
|
106
|
+
</payment:shopperName>
|
107
|
+
EOXML
|
108
|
+
|
109
|
+
# @private
|
110
|
+
ENCRYPTED_CARD_PARTIAL = <<-EOXML
|
111
|
+
<additionalAmount xmlns="http://payment.services.adyen.com" xsi:nil="true" />
|
112
|
+
<additionalData xmlns="http://payment.services.adyen.com">
|
113
|
+
<entry>
|
114
|
+
<key xsi:type="xsd:string">card.encrypted.json</key>
|
115
|
+
<value xsi:type="xsd:string">%s</value>
|
116
|
+
</entry>
|
117
|
+
</additionalData>
|
118
|
+
EOXML
|
119
|
+
|
120
|
+
# @private
|
121
|
+
ENABLE_RECURRING_CONTRACTS_PARTIAL = <<-EOXML
|
122
|
+
<payment:recurring>
|
123
|
+
<payment:contract>RECURRING,ONECLICK</payment:contract>
|
124
|
+
</payment:recurring>
|
125
|
+
EOXML
|
126
|
+
|
127
|
+
# @private
|
128
|
+
RECURRING_PAYMENT_BODY_PARTIAL = <<-EOXML
|
129
|
+
<payment:recurring>
|
130
|
+
<payment:contract>RECURRING</payment:contract>
|
131
|
+
</payment:recurring>
|
132
|
+
<payment:selectedRecurringDetailReference>%s</payment:selectedRecurringDetailReference>
|
133
|
+
<payment:shopperInteraction>ContAuth</payment:shopperInteraction>
|
134
|
+
EOXML
|
135
|
+
|
136
|
+
# @private
|
137
|
+
ONE_CLICK_PAYMENT_BODY_PARTIAL = <<-EOXML
|
138
|
+
<payment:recurring>
|
139
|
+
<payment:contract>ONECLICK</payment:contract>
|
140
|
+
</payment:recurring>
|
141
|
+
<payment:selectedRecurringDetailReference>%s</payment:selectedRecurringDetailReference>
|
142
|
+
EOXML
|
143
|
+
|
144
|
+
# @private
|
145
|
+
SHOPPER_PARTIALS = {
|
146
|
+
:reference => ' <payment:shopperReference>%s</payment:shopperReference>',
|
147
|
+
:email => ' <payment:shopperEmail>%s</payment:shopperEmail>',
|
148
|
+
:ip => ' <payment:shopperIP>%s</payment:shopperIP>',
|
149
|
+
:statement => ' <payment:shopperStatement>%s</payment:shopperStatement>',
|
150
|
+
}
|
151
|
+
|
152
|
+
# @private
|
153
|
+
FRAUD_OFFSET_PARTIAL = '<payment:fraudOffset>%s</payment:fraudOffset>'
|
154
|
+
|
155
|
+
# @private
|
156
|
+
CAPTURE_DELAY_PARTIAL = '<payment:captureDelayHours>%s</payment:captureDelayHours>'
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Adyen
|
2
|
+
module API
|
3
|
+
class RecurringService < SimpleSOAPClient
|
4
|
+
# @private
|
5
|
+
LIST_LAYOUT = <<EOS
|
6
|
+
<recurring:listRecurringDetails xmlns:payment="http://payment.services.adyen.com" xmlns:recurring="http://recurring.services.adyen.com">
|
7
|
+
<recurring:request>
|
8
|
+
<recurring:recurring>
|
9
|
+
<payment:contract>RECURRING</payment:contract>
|
10
|
+
</recurring:recurring>
|
11
|
+
<recurring:merchantAccount>%s</recurring:merchantAccount>
|
12
|
+
<recurring:shopperReference>%s</recurring:shopperReference>
|
13
|
+
</recurring:request>
|
14
|
+
</recurring:listRecurringDetails>
|
15
|
+
EOS
|
16
|
+
|
17
|
+
# @private
|
18
|
+
DISABLE_LAYOUT = <<EOS
|
19
|
+
<recurring:disable xmlns:recurring="http://recurring.services.adyen.com">
|
20
|
+
<recurring:request>
|
21
|
+
<recurring:merchantAccount>%s</recurring:merchantAccount>
|
22
|
+
<recurring:shopperReference>%s</recurring:shopperReference>
|
23
|
+
%s
|
24
|
+
</recurring:request>
|
25
|
+
</recurring:disable>
|
26
|
+
EOS
|
27
|
+
|
28
|
+
# @private
|
29
|
+
RECURRING_DETAIL_PARTIAL = <<EOS
|
30
|
+
<recurring:recurringDetailReference>%s</recurring:recurringDetailReference>
|
31
|
+
EOS
|
32
|
+
|
33
|
+
STORE_TOKEN_LAYOUT = <<EOS
|
34
|
+
<recurring:storeToken xmlns:recurring="http://recurring.services.adyen.com" xmlns:payment="http://payment.services.adyen.com">
|
35
|
+
<recurring:request>
|
36
|
+
<recurring:recurring>
|
37
|
+
<payment:contract>RECURRING</payment:contract>
|
38
|
+
</recurring:recurring>
|
39
|
+
<recurring:merchantAccount>%s</recurring:merchantAccount>
|
40
|
+
<recurring:shopperReference>%s</recurring:shopperReference>
|
41
|
+
<recurring:shopperEmail>%s</recurring:shopperEmail>
|
42
|
+
%s
|
43
|
+
</recurring:request>
|
44
|
+
</recurring:storeToken>
|
45
|
+
EOS
|
46
|
+
|
47
|
+
# @private
|
48
|
+
CARD_PARTIAL = <<EOS
|
49
|
+
<recurring:card>
|
50
|
+
<payment:holderName>%s</payment:holderName>
|
51
|
+
<payment:number>%s</payment:number>
|
52
|
+
<payment:cvc>%s</payment:cvc>
|
53
|
+
<payment:expiryYear>%s</payment:expiryYear>
|
54
|
+
<payment:expiryMonth>%02d</payment:expiryMonth>
|
55
|
+
</recurring:card>
|
56
|
+
EOS
|
57
|
+
# Electronic bank debit in Germany. Semi real-time payment method.
|
58
|
+
# @private
|
59
|
+
ELV_PARTIAL = <<EOS
|
60
|
+
<recurring:elv>
|
61
|
+
<payment:bankLocation>%s</payment:bankLocation>
|
62
|
+
<payment:bankName>%s</payment:bankName>
|
63
|
+
<payment:bankLocationId>%s</payment:bankLocationId>
|
64
|
+
<payment:accountHolderName>%s</payment:accountHolderName>
|
65
|
+
<payment:bankAccountNumber>%02d</payment:bankAccountNumber>
|
66
|
+
</recurring:elv>
|
67
|
+
EOS
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'adyen/api/payment_service'
|
2
|
+
|
3
|
+
module Adyen
|
4
|
+
module API
|
5
|
+
class PaymentService < SimpleSOAPClient
|
6
|
+
# A collection of test helpers that create and assign stubbed response instances for a
|
7
|
+
# subsequent remote call.
|
8
|
+
#
|
9
|
+
# This module extends the {PaymentService} class and thus these methods are callable on it.
|
10
|
+
module TestHelpers
|
11
|
+
AUTHORISE_RESPONSE = SimpleSOAPClient::ENVELOPE % <<-EOXML
|
12
|
+
<ns1:authoriseResponse xmlns:ns1="http://payment.services.adyen.com">
|
13
|
+
<ns1:paymentResult>
|
14
|
+
<additionalData xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
|
15
|
+
<authCode xmlns="http://payment.services.adyen.com">1234</authCode>
|
16
|
+
<dccAmount xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
|
17
|
+
<dccSignature xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
|
18
|
+
<fraudResult xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
|
19
|
+
<issuerUrl xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
|
20
|
+
<md xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
|
21
|
+
<paRequest xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
|
22
|
+
<pspReference xmlns="http://payment.services.adyen.com">9876543210987654</pspReference>
|
23
|
+
<refusalReason xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
|
24
|
+
<resultCode xmlns="http://payment.services.adyen.com">Authorised</resultCode>
|
25
|
+
</ns1:paymentResult>
|
26
|
+
</ns1:authoriseResponse>
|
27
|
+
EOXML
|
28
|
+
|
29
|
+
AUTHORISATION_REFUSED_RESPONSE = SimpleSOAPClient::ENVELOPE % <<-EOXML
|
30
|
+
<ns1:authoriseResponse xmlns:ns1="http://payment.services.adyen.com">
|
31
|
+
<ns1:paymentResult>
|
32
|
+
<additionalData xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
|
33
|
+
<authCode xmlns="http://payment.services.adyen.com">1234</authCode>
|
34
|
+
<dccAmount xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
|
35
|
+
<dccSignature xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
|
36
|
+
<fraudResult xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
|
37
|
+
<issuerUrl xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
|
38
|
+
<md xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
|
39
|
+
<paRequest xmlns="http://payment.services.adyen.com" xsi:nil="true"/>
|
40
|
+
<pspReference xmlns="http://payment.services.adyen.com">9876543210987654</pspReference>
|
41
|
+
<refusalReason xmlns="http://payment.services.adyen.com">You need to actually own money.</refusalReason>
|
42
|
+
<resultCode xmlns="http://payment.services.adyen.com">Refused</resultCode>
|
43
|
+
</ns1:paymentResult>
|
44
|
+
</ns1:authoriseResponse>
|
45
|
+
EOXML
|
46
|
+
|
47
|
+
AUTHORISATION_REQUEST_INVALID_RESPONSE = SimpleSOAPClient::ENVELOPE % <<-EOXML
|
48
|
+
<soap:Fault>
|
49
|
+
<faultcode>soap:Server</faultcode>
|
50
|
+
<faultstring>validation 101 Invalid card number</faultstring>
|
51
|
+
</soap:Fault>
|
52
|
+
EOXML
|
53
|
+
|
54
|
+
# @return [AuthorisationResponse] A authorisation succeeded response instance.
|
55
|
+
def success_stub
|
56
|
+
http_response = Net::HTTPOK.new('1.1', '200', 'OK')
|
57
|
+
def http_response.body; AUTHORISE_RESPONSE; end
|
58
|
+
PaymentService::AuthorisationResponse.new(http_response)
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [AuthorisationResponse] An authorisation refused response instance.
|
62
|
+
def refused_stub
|
63
|
+
http_response = Net::HTTPOK.new('1.1', '200', 'OK')
|
64
|
+
def http_response.body; AUTHORISATION_REFUSED_RESPONSE; end
|
65
|
+
PaymentService::AuthorisationResponse.new(http_response)
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [AuthorisationResponse] An ‘invalid request’ response instance.
|
69
|
+
def invalid_stub
|
70
|
+
http_response = Net::HTTPOK.new('1.1', '200', 'OK')
|
71
|
+
def http_response.body; AUTHORISATION_REQUEST_INVALID_RESPONSE; end
|
72
|
+
PaymentService::AuthorisationResponse.new(http_response)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Assigns a {#success_stub}, meaning the subsequent authoristaion request will be authorised.
|
76
|
+
#
|
77
|
+
# @return [AuthorisationResponse] A authorisation succeeded response instance.
|
78
|
+
def stub_success!
|
79
|
+
@stubbed_response = success_stub
|
80
|
+
end
|
81
|
+
|
82
|
+
# Assigns a {#refused_stub}, meaning the subsequent authoristaion request will be refused.
|
83
|
+
#
|
84
|
+
# @return [AuthorisationResponse] An authorisation refused response instance.
|
85
|
+
def stub_refused!
|
86
|
+
@stubbed_response = refused_stub
|
87
|
+
end
|
88
|
+
|
89
|
+
# Assigns a {#invalid_stub}, meaning the subsequent authoristaion request will be refused,
|
90
|
+
# because the request was invalid.
|
91
|
+
#
|
92
|
+
# @return [AuthorisationResponse] An ‘invalid request’ response instance.
|
93
|
+
def stub_invalid!
|
94
|
+
@stubbed_response = invalid_stub
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
extend TestHelpers
|
99
|
+
end
|
100
|
+
|
101
|
+
class RecurringService < SimpleSOAPClient
|
102
|
+
# A collection of test helpers that create and assign stubbed response instances for a
|
103
|
+
# subsequent remote call.
|
104
|
+
#
|
105
|
+
# This module extends the {RecurringService} class and thus these methods are callable on it.
|
106
|
+
module TestHelpers
|
107
|
+
DISABLE_RESPONSE = SimpleSOAPClient::ENVELOPE % <<-EOXML
|
108
|
+
<ns1:disableResponse xmlns:ns1="http://recurring.services.adyen.com">
|
109
|
+
<ns1:result>
|
110
|
+
<response xmlns="http://recurring.services.adyen.com">
|
111
|
+
%s
|
112
|
+
</response>
|
113
|
+
</ns1:result>
|
114
|
+
</ns1:disableResponse>
|
115
|
+
EOXML
|
116
|
+
|
117
|
+
# @return [DisableResponse] A ‘disable succeeded’ response instance.
|
118
|
+
def disabled_stub
|
119
|
+
http_response = Net::HTTPOK.new('1.1', '200', 'OK')
|
120
|
+
def http_response.body; DISABLE_RESPONSE % DisableResponse::DISABLED_RESPONSES.first; end
|
121
|
+
RecurringService::DisableResponse.new(http_response)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Assigns a {#disabled_stub}, meaning the subsequent disable request will be successful.
|
125
|
+
def stub_disabled!
|
126
|
+
@stubbed_response = disabled_stub
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
extend TestHelpers
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|