adyen 1.4.1 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +17 -13
- data/Gemfile +4 -0
- data/README.rdoc +1 -1
- data/adyen.gemspec +4 -15
- data/lib/adyen.rb +4 -0
- data/lib/adyen/api.rb +8 -6
- data/lib/adyen/api/cacert.pem +369 -260
- data/lib/adyen/api/payment_service.rb +43 -7
- data/lib/adyen/api/simple_soap_client.rb +8 -8
- data/lib/adyen/api/templates/payment_service.rb +51 -40
- data/lib/adyen/api/test_helpers.rb +49 -49
- data/lib/adyen/api/xml_querier.rb +10 -2
- data/lib/adyen/encoding.rb +2 -2
- data/lib/adyen/form.rb +32 -0
- data/lib/adyen/version.rb +1 -1
- data/spec/api/api_spec.rb +6 -6
- data/spec/api/payment_service_spec.rb +24 -6
- data/spec/api/recurring_service_spec.rb +2 -2
- data/spec/api/response_spec.rb +1 -1
- data/spec/api/simple_soap_client_spec.rb +1 -1
- data/spec/api/spec_helper.rb +6 -2
- data/spec/form_spec.rb +58 -7
- data/spec/functional/api_spec.rb +36 -32
- data/spec/functional/initializer.rb.ci +3 -0
- data/spec/functional/initializer.rb.sample +3 -3
- data/spec/spec_helper.rb +0 -2
- metadata +11 -9
@@ -98,15 +98,16 @@ module Adyen
|
|
98
98
|
|
99
99
|
def authorise_one_click_payment_request_body
|
100
100
|
validate_parameters!(:recurring_detail_reference,
|
101
|
-
:shopper => [:email, :reference]
|
102
|
-
|
103
|
-
content
|
101
|
+
:shopper => [:email, :reference])
|
102
|
+
content = one_click_card_partial
|
103
|
+
content << ONE_CLICK_PAYMENT_BODY_PARTIAL % [@params[:recurring_detail_reference]]
|
104
104
|
payment_request_body(content)
|
105
105
|
end
|
106
106
|
|
107
107
|
def payment_request_body(content)
|
108
108
|
validate_parameters!(:merchant_account, :reference, :amount => [:currency, :value])
|
109
109
|
content << amount_partial
|
110
|
+
content << installments_partial if @params[:installments]
|
110
111
|
content << shopper_partial if @params[:shopper]
|
111
112
|
content << fraud_offset_partial if @params[:fraud_offset]
|
112
113
|
LAYOUT % [@params[:merchant_account], @params[:reference], content]
|
@@ -139,8 +140,18 @@ module Adyen
|
|
139
140
|
AMOUNT_PARTIAL % @params[:amount].values_at(:currency, :value)
|
140
141
|
end
|
141
142
|
|
143
|
+
def one_click_card_partial
|
144
|
+
if @params[:card] && @params[:card][:encrypted] && @params[:card][:encrypted][:json]
|
145
|
+
ENCRYPTED_CARD_PARTIAL % [@params[:card][:encrypted][:json]]
|
146
|
+
else
|
147
|
+
validate_parameters!(:card => [:cvc])
|
148
|
+
card = @params[:card].values_at(:cvc)
|
149
|
+
ONE_CLICK_CARD_PARTIAL % card
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
142
153
|
def card_partial
|
143
|
-
if @params[:card]
|
154
|
+
if @params[:card] && @params[:card][:encrypted] && @params[:card][:encrypted][:json]
|
144
155
|
ENCRYPTED_CARD_PARTIAL % [@params[:card][:encrypted][:json]]
|
145
156
|
else
|
146
157
|
validate_parameters!(:card => [:holder_name, :number, :cvc, :expiry_year, :expiry_month])
|
@@ -150,15 +161,21 @@ module Adyen
|
|
150
161
|
end
|
151
162
|
end
|
152
163
|
|
164
|
+
def installments_partial
|
165
|
+
if @params[:installments] && @params[:installments][:value]
|
166
|
+
INSTALLMENTS_PARTIAL % @params[:installments].values_at(:value)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
153
170
|
def shopper_partial
|
154
171
|
@params[:shopper].map { |k, v| SHOPPER_PARTIALS[k] % v }.join("\n")
|
155
172
|
end
|
156
|
-
|
173
|
+
|
157
174
|
def fraud_offset_partial
|
158
175
|
validate_parameters!(:fraud_offset)
|
159
176
|
FRAUD_OFFSET_PARTIAL % @params[:fraud_offset]
|
160
177
|
end
|
161
|
-
|
178
|
+
|
162
179
|
class AuthorisationResponse < Response
|
163
180
|
ERRORS = {
|
164
181
|
"validation 101 Invalid card number" => [:number, 'is not a valid creditcard number'],
|
@@ -171,7 +188,8 @@ module Adyen
|
|
171
188
|
AUTHORISED = 'Authorised'
|
172
189
|
REFUSED = 'Refused'
|
173
190
|
|
174
|
-
response_attrs :result_code, :auth_code, :refusal_reason, :psp_reference
|
191
|
+
response_attrs :result_code, :auth_code, :refusal_reason, :psp_reference,
|
192
|
+
:additional_data
|
175
193
|
|
176
194
|
def success?
|
177
195
|
super && params[:result_code] == AUTHORISED
|
@@ -217,10 +235,28 @@ module Adyen
|
|
217
235
|
:psp_reference => result.text('./payment:pspReference'),
|
218
236
|
:result_code => result.text('./payment:resultCode'),
|
219
237
|
:auth_code => result.text('./payment:authCode'),
|
238
|
+
:additional_data => parse_additional_data(result.xpath('.//payment:additionalData')),
|
220
239
|
:refusal_reason => (invalid_request? ? fault_message : result.text('./payment:refusalReason'))
|
221
240
|
}
|
222
241
|
end
|
223
242
|
end
|
243
|
+
|
244
|
+
private
|
245
|
+
def parse_additional_data(xpath)
|
246
|
+
if xpath.empty?
|
247
|
+
{}
|
248
|
+
else
|
249
|
+
results = {}
|
250
|
+
|
251
|
+
xpath.map do |node|
|
252
|
+
key = node.text('./payment:entry/payment:key')
|
253
|
+
value = node.text('./payment:entry/payment:value')
|
254
|
+
results[key] = value unless key.empty?
|
255
|
+
end
|
256
|
+
|
257
|
+
results
|
258
|
+
end
|
259
|
+
end
|
224
260
|
end
|
225
261
|
|
226
262
|
class ModificationResponse < Response
|
@@ -8,14 +8,14 @@ module Adyen
|
|
8
8
|
# The base class of the API classes that map to Adyen SOAP services.
|
9
9
|
class SimpleSOAPClient
|
10
10
|
# @private
|
11
|
-
ENVELOPE =
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
</soap:Envelope>
|
18
|
-
|
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
19
|
|
20
20
|
# A CA file used to verify certificates when connecting to Adyen.
|
21
21
|
#
|
@@ -5,24 +5,24 @@ module Adyen
|
|
5
5
|
private
|
6
6
|
|
7
7
|
def modification_request(method, body = nil)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
17
|
end
|
18
18
|
|
19
19
|
def modification_request_with_amount(method)
|
20
|
-
modification_request(method,
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -36,26 +36,26 @@ EOS
|
|
36
36
|
CANCEL_OR_REFUND_LAYOUT = modification_request(:cancelOrRefund)
|
37
37
|
|
38
38
|
# @private
|
39
|
-
LAYOUT =
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
%s
|
45
|
-
|
46
|
-
|
47
|
-
|
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
48
|
|
49
49
|
# @private
|
50
|
-
AMOUNT_PARTIAL =
|
50
|
+
AMOUNT_PARTIAL = <<-EOXML
|
51
51
|
<payment:amount>
|
52
52
|
<common:currency>%s</common:currency>
|
53
53
|
<common:value>%s</common:value>
|
54
54
|
</payment:amount>
|
55
|
-
|
55
|
+
EOXML
|
56
56
|
|
57
57
|
# @private
|
58
|
-
CARD_PARTIAL =
|
58
|
+
CARD_PARTIAL = <<-EOXML
|
59
59
|
<payment:card>
|
60
60
|
<payment:holderName>%s</payment:holderName>
|
61
61
|
<payment:number>%s</payment:number>
|
@@ -63,10 +63,24 @@ EOS
|
|
63
63
|
<payment:expiryYear>%s</payment:expiryYear>
|
64
64
|
<payment:expiryMonth>%02d</payment:expiryMonth>
|
65
65
|
</payment:card>
|
66
|
-
|
66
|
+
EOXML
|
67
|
+
|
68
|
+
# @private
|
69
|
+
ONE_CLICK_CARD_PARTIAL = <<-EOXML
|
70
|
+
<payment:card>
|
71
|
+
<payment:cvc>%s</payment:cvc>
|
72
|
+
</payment:card>
|
73
|
+
EOXML
|
67
74
|
|
68
75
|
# @private
|
69
|
-
|
76
|
+
INSTALLMENTS_PARTIAL = <<-EOXML
|
77
|
+
<payment:installments>
|
78
|
+
<common:value>%s</common:value>
|
79
|
+
</payment:installments>
|
80
|
+
EOXML
|
81
|
+
|
82
|
+
# @private
|
83
|
+
ENCRYPTED_CARD_PARTIAL = <<-EOXML
|
70
84
|
<additionalAmount xmlns="http://payment.services.adyen.com" xsi:nil="true" />
|
71
85
|
<additionalData xmlns="http://payment.services.adyen.com">
|
72
86
|
<entry>
|
@@ -74,34 +88,31 @@ EOS
|
|
74
88
|
<value xsi:type="xsd:string">%s</value>
|
75
89
|
</entry>
|
76
90
|
</additionalData>
|
77
|
-
|
91
|
+
EOXML
|
78
92
|
|
79
93
|
# @private
|
80
|
-
ENABLE_RECURRING_CONTRACTS_PARTIAL =
|
94
|
+
ENABLE_RECURRING_CONTRACTS_PARTIAL = <<-EOXML
|
81
95
|
<payment:recurring>
|
82
96
|
<payment:contract>RECURRING,ONECLICK</payment:contract>
|
83
97
|
</payment:recurring>
|
84
|
-
|
98
|
+
EOXML
|
85
99
|
|
86
100
|
# @private
|
87
|
-
RECURRING_PAYMENT_BODY_PARTIAL =
|
101
|
+
RECURRING_PAYMENT_BODY_PARTIAL = <<-EOXML
|
88
102
|
<payment:recurring>
|
89
103
|
<payment:contract>RECURRING</payment:contract>
|
90
104
|
</payment:recurring>
|
91
105
|
<payment:selectedRecurringDetailReference>%s</payment:selectedRecurringDetailReference>
|
92
106
|
<payment:shopperInteraction>ContAuth</payment:shopperInteraction>
|
93
|
-
|
107
|
+
EOXML
|
94
108
|
|
95
109
|
# @private
|
96
|
-
ONE_CLICK_PAYMENT_BODY_PARTIAL =
|
110
|
+
ONE_CLICK_PAYMENT_BODY_PARTIAL = <<-EOXML
|
97
111
|
<payment:recurring>
|
98
112
|
<payment:contract>ONECLICK</payment:contract>
|
99
113
|
</payment:recurring>
|
100
114
|
<payment:selectedRecurringDetailReference>%s</payment:selectedRecurringDetailReference>
|
101
|
-
|
102
|
-
<payment:cvc>%s</payment:cvc>
|
103
|
-
</payment:card>
|
104
|
-
EOS
|
115
|
+
EOXML
|
105
116
|
|
106
117
|
# @private
|
107
118
|
SHOPPER_PARTIALS = {
|
@@ -110,7 +121,7 @@ EOS
|
|
110
121
|
:ip => ' <payment:shopperIP>%s</payment:shopperIP>',
|
111
122
|
:statement => ' <payment:shopperStatement>%s</payment:shopperStatement>',
|
112
123
|
}
|
113
|
-
|
124
|
+
|
114
125
|
# @private
|
115
126
|
FRAUD_OFFSET_PARTIAL = '<payment:fraudOffset>%s</payment:fraudOffset>'
|
116
127
|
end
|
@@ -8,48 +8,48 @@ module Adyen
|
|
8
8
|
#
|
9
9
|
# This module extends the {PaymentService} class and thus these methods are callable on it.
|
10
10
|
module TestHelpers
|
11
|
-
AUTHORISE_RESPONSE = SimpleSOAPClient::ENVELOPE %
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
28
|
|
29
|
-
AUTHORISATION_REFUSED_RESPONSE = SimpleSOAPClient::ENVELOPE %
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
46
|
|
47
|
-
AUTHORISATION_REQUEST_INVALID_RESPONSE = SimpleSOAPClient::ENVELOPE %
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
53
|
|
54
54
|
# @return [AuthorisationResponse] A authorisation succeeded response instance.
|
55
55
|
def success_stub
|
@@ -104,15 +104,15 @@ EOS
|
|
104
104
|
#
|
105
105
|
# This module extends the {RecurringService} class and thus these methods are callable on it.
|
106
106
|
module TestHelpers
|
107
|
-
DISABLE_RESPONSE = SimpleSOAPClient::ENVELOPE %
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
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
116
|
|
117
117
|
# @return [DisableResponse] A ‘disable succeeded’ response instance.
|
118
118
|
def disabled_stub
|
@@ -31,6 +31,10 @@ module Adyen
|
|
31
31
|
def perform_xpath(query, root_node)
|
32
32
|
root_node.xpath(query, NS)
|
33
33
|
end
|
34
|
+
|
35
|
+
def stringify_nodeset(nodeset)
|
36
|
+
nodeset.to_xml(encoding: 'UTF-8')
|
37
|
+
end
|
34
38
|
end
|
35
39
|
|
36
40
|
class REXMLBackend
|
@@ -48,7 +52,11 @@ module Adyen
|
|
48
52
|
|
49
53
|
def perform_xpath(query, root_node)
|
50
54
|
REXML::XPath.match(root_node, query, NS)
|
51
|
-
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def stringify_nodeset(nodeset)
|
58
|
+
nodeset.map { |n| n.to_s }.join("")
|
59
|
+
end
|
52
60
|
end
|
53
61
|
|
54
62
|
# @return A backend to handle XML parsing.
|
@@ -116,7 +124,7 @@ module Adyen
|
|
116
124
|
|
117
125
|
# @return [String] A string representation of this node.
|
118
126
|
def to_s
|
119
|
-
|
127
|
+
backend.stringify_nodeset(@node)
|
120
128
|
end
|
121
129
|
|
122
130
|
# @yield [XMLQuerier] A member of this node set, ready to be queried.
|
data/lib/adyen/encoding.rb
CHANGED
@@ -7,7 +7,7 @@ module Adyen
|
|
7
7
|
module Encoding
|
8
8
|
def self.hmac_base64(hmac_key, message)
|
9
9
|
digest = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), hmac_key, message)
|
10
|
-
Base64.
|
10
|
+
Base64.strict_encode64(digest).strip
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.gzip_base64(message)
|
@@ -15,7 +15,7 @@ module Adyen
|
|
15
15
|
gz = Zlib::GzipWriter.new(sio)
|
16
16
|
gz.write(message)
|
17
17
|
gz.close
|
18
|
-
Base64.
|
18
|
+
Base64.strict_encode64(sio.string)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
data/lib/adyen/form.rb
CHANGED
@@ -119,6 +119,10 @@ module Adyen
|
|
119
119
|
parameters[:billing_address_sig] = calculate_billing_address_signature(parameters, shared_secret)
|
120
120
|
end
|
121
121
|
|
122
|
+
if parameters[:shopper]
|
123
|
+
parameters[:shopper_sig] = calculate_shopper_signature(parameters, shared_secret)
|
124
|
+
end
|
125
|
+
|
122
126
|
return parameters
|
123
127
|
end
|
124
128
|
|
@@ -165,6 +169,20 @@ module Adyen
|
|
165
169
|
}.join('&')
|
166
170
|
end
|
167
171
|
|
172
|
+
# @see Adyen::Form.redirect_url
|
173
|
+
#
|
174
|
+
# Returns an absolute URL very similar to the one returned by Adyen::Form.redirect_url
|
175
|
+
# except that it uses the directory.shtml call which returns a list of all available
|
176
|
+
# payment methods
|
177
|
+
#
|
178
|
+
# @param [Hash] parameters The payment parameters to include in the payment request.
|
179
|
+
# @return [String] An absolute URL to redirect to the Adyen payment system.
|
180
|
+
def payment_methods_url(parameters = {})
|
181
|
+
url(nil, :directory) + '?' + flat_payment_parameters(parameters).map { |(k, v)|
|
182
|
+
"#{k}=#{CGI.escape(v)}"
|
183
|
+
}.join('&')
|
184
|
+
end
|
185
|
+
|
168
186
|
# Returns a HTML snippet of hidden INPUT tags with the provided payment parameters.
|
169
187
|
# The snippet can be included in a payment form that POSTs to the Adyen payment system.
|
170
188
|
#
|
@@ -266,6 +284,20 @@ module Adyen
|
|
266
284
|
Adyen::Encoding.hmac_base64(shared_secret, calculate_billing_address_signature_string(parameters[:billing_address]))
|
267
285
|
end
|
268
286
|
|
287
|
+
# shopperSig: shopper.firstName + shopper.infix + shopper.lastName + shopper.gender + shopper.dateOfBirthDayOfMonth + shopper.dateOfBirthMonth + shopper.dateOfBirthYear + shopper.telephoneNumber
|
288
|
+
# (Note that you can send only shopper.firstName and shopper.lastName if you like. Do NOT include shopperSocialSecurityNumber in the shopperSig!)
|
289
|
+
def calculate_shopper_signature_string(parameters)
|
290
|
+
%w(first_name infix last_name gender date_of_birth_day_of_month date_of_birth_month date_of_birth_year telephone_number).map do |key|
|
291
|
+
parameters[key.to_sym]
|
292
|
+
end.join
|
293
|
+
end
|
294
|
+
|
295
|
+
def calculate_shopper_signature(parameters, shared_secret = nil)
|
296
|
+
shared_secret ||= parameters.delete(:shared_secret)
|
297
|
+
raise ArgumentError, "Cannot calculate shopper request signature with empty shared_secret" if shared_secret.to_s.empty?
|
298
|
+
Adyen::Encoding.hmac_base64(shared_secret, calculate_shopper_signature_string(parameters[:shopper]))
|
299
|
+
end
|
300
|
+
|
269
301
|
######################################################
|
270
302
|
# REDIRECT SIGNATURE CHECKING
|
271
303
|
######################################################
|