sepafm 1.1.8 → 1.1.9
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/.rubocop.yml +8 -6
- data/Rakefile +1 -1
- data/lib/sepa/application_request.rb +12 -18
- data/lib/sepa/application_response.rb +0 -2
- data/lib/sepa/attribute_checks.rb +33 -28
- data/lib/sepa/banks/danske/danske_response.rb +9 -25
- data/lib/sepa/banks/danske/soap_danske.rb +1 -1
- data/lib/sepa/banks/nordea/nordea_response.rb +2 -16
- data/lib/sepa/banks/op/op_response.rb +5 -23
- data/lib/sepa/banks/samlink/samlink_response.rb +35 -0
- data/lib/sepa/banks/samlink/soap_samlink.rb +14 -0
- data/lib/sepa/certificates/samlink_certificate.pem +29 -0
- data/lib/sepa/certificates/samlink_root_certificate.pem +32 -0
- data/lib/sepa/client.rb +35 -8
- data/lib/sepa/error_messages.rb +16 -18
- data/lib/sepa/response.rb +7 -11
- data/lib/sepa/soap_builder.rb +7 -17
- data/lib/sepa/utilities.rb +4 -5
- data/lib/sepa/version.rb +1 -1
- data/lib/sepa/wsdl/wsdl_samlink_cert_production.xml +82 -0
- data/lib/sepa/wsdl/wsdl_samlink_cert_test.xml +82 -0
- data/lib/sepa/wsdl/wsdl_samlink_production.xml +160 -0
- data/lib/sepa/wsdl/wsdl_samlink_test.xml +160 -0
- data/lib/sepa/xml_schemas/samlink/CertApplicationRequest.xsd +105 -0
- data/lib/sepa/xml_schemas/samlink/CertApplicationResponse.xsd +88 -0
- data/lib/sepa/xml_templates/application_request/download_file.xml +0 -1
- data/lib/sepa/xml_templates/application_request/download_file_list.xml +0 -1
- data/lib/sepa/xml_templates/application_request/samlink/get_certificate.xml +12 -0
- data/lib/sepa/xml_templates/application_request/samlink/renew_certificate.xml +29 -0
- data/lib/sepa/xml_templates/soap/samlink/get_certificate.xml +14 -0
- data/lib/sepa/xml_templates/soap/samlink/renew_certificate.xml +14 -0
- data/lib/sepafm.rb +43 -31
- data/readme.md +1 -0
- data/sepafm.gemspec +2 -2
- data/test/custom_assertions.rb +30 -28
- data/test/sepa/banks/danske/danske_cert_response_test.rb +13 -10
- data/test/sepa/banks/danske/danske_generic_soap_builder_test.rb +9 -31
- data/test/sepa/banks/danske/danske_get_bank_cert_test.rb +4 -5
- data/test/sepa/banks/danske/danske_response_test.rb +2 -3
- data/test/sepa/banks/danske/responses/create_cert_corrupted.xml +15 -0
- data/test/sepa/banks/nordea/nordea_application_request_test.rb +4 -6
- data/test/sepa/banks/nordea/nordea_application_response_test.rb +14 -15
- data/test/sepa/banks/nordea/nordea_cert_request_soap_builder_test.rb +1 -3
- data/test/sepa/banks/nordea/nordea_generic_soap_builder_test.rb +6 -16
- data/test/sepa/banks/nordea/nordea_response_test.rb +11 -11
- data/test/sepa/banks/op/op_cert_application_request_test.rb +1 -1
- data/test/sepa/banks/op/op_cert_request_soap_builder_test.rb +0 -1
- data/test/sepa/banks/op/op_response_test.rb +2 -2
- data/test/sepa/banks/samlink/responses/dfl.xml +21 -0
- data/test/sepa/banks/samlink/responses/gc_error_30.xml +21 -0
- data/test/sepa/banks/samlink/responses/rc.xml +21 -0
- data/test/sepa/banks/samlink/samlink_application_request_test.rb +36 -0
- data/test/sepa/banks/samlink/samlink_cert_application_request_test.rb +13 -0
- data/test/sepa/banks/samlink/samlink_cert_request_soap_builder_test.rb +13 -0
- data/test/sepa/banks/samlink/samlink_generic_soap_builder_test.rb +34 -0
- data/test/sepa/banks/samlink/samlink_renew_cert_application_request_test.rb +36 -0
- data/test/sepa/banks/samlink/samlink_renew_cert_request_soap_builder_test.rb +26 -0
- data/test/sepa/banks/samlink/samlink_response_test.rb +71 -0
- data/test/sepa/client_test.rb +32 -6
- data/test/sepa/fixtures.rb +169 -7
- data/test/sepa/sepa_test.rb +1 -1
- data/test/test_helper.rb +8 -7
- data/test_client/data/certs_example.rb +9 -9
- data/test_client/data/params_example.rb +18 -19
- data/test_client/test_client.rb +6 -0
- metadata +41 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d7953437ff7a58f58b2f7df4b1e9541ceb409000
|
|
4
|
+
data.tar.gz: ac839e70c1644adb076586e5ac98fa78779fd8a3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8c8b5f59d6bac6b85f71d893039f1ffe707c78258c1f65546c7b64c650f27bc7b389196ae62513b0c0e933c20ec488370b7aa220c5b3297375b602d07aada7f0
|
|
7
|
+
data.tar.gz: ed2acb7fa7b253c93cd36be5eca1750e40e709b43914baa876ee68b5bea5a242ac3d46b12672a4659301b554afe276ea374dc45e7a7667bd18cfe26d61f5f11e
|
data/.rubocop.yml
CHANGED
|
@@ -5,7 +5,7 @@ Metrics/AbcSize:
|
|
|
5
5
|
Max: 37
|
|
6
6
|
|
|
7
7
|
Metrics/ClassLength:
|
|
8
|
-
Max:
|
|
8
|
+
Max: 350
|
|
9
9
|
|
|
10
10
|
Metrics/CyclomaticComplexity:
|
|
11
11
|
Max: 8
|
|
@@ -17,7 +17,7 @@ Metrics/MethodLength:
|
|
|
17
17
|
Max: 69
|
|
18
18
|
|
|
19
19
|
Metrics/ModuleLength:
|
|
20
|
-
Max:
|
|
20
|
+
Max: 150
|
|
21
21
|
|
|
22
22
|
Style/Documentation:
|
|
23
23
|
Exclude:
|
|
@@ -25,11 +25,13 @@ Style/Documentation:
|
|
|
25
25
|
- 'test/**/*'
|
|
26
26
|
|
|
27
27
|
Style/IndentationConsistency:
|
|
28
|
-
|
|
28
|
+
EnforcedStyle: rails
|
|
29
29
|
|
|
30
30
|
Style/StringLiterals:
|
|
31
|
-
|
|
32
|
-
ConsistentQuotesInMultiline: true
|
|
31
|
+
Enabled: false
|
|
33
32
|
|
|
34
33
|
Style/TrailingCommaInLiteral:
|
|
35
|
-
|
|
34
|
+
EnforcedStyleForMultiline: comma
|
|
35
|
+
|
|
36
|
+
Style/TrailingCommaInArguments:
|
|
37
|
+
EnforcedStyleForMultiline: comma
|
data/Rakefile
CHANGED
|
@@ -74,7 +74,7 @@ module Sepa
|
|
|
74
74
|
# @example Example input and output
|
|
75
75
|
# :get_user_info --> GetUserInfo
|
|
76
76
|
def pretty_command
|
|
77
|
-
@command.to_s.split(/[\W_]/).map
|
|
77
|
+
@command.to_s.split(/[\W_]/).map(&:capitalize).join
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
# Determines which content setting method to call depending on {#command}
|
|
@@ -86,8 +86,8 @@ module Sepa
|
|
|
86
86
|
|
|
87
87
|
# Sets nodes' values for download file request
|
|
88
88
|
def set_download_file_nodes
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
add_node_after('FileReferences', 'TargetId', content: @target_id) if @bank == :nordea
|
|
90
|
+
add_node_after('Timestamp', 'Status', content: @status) if @status.present?
|
|
91
91
|
add_node_to_root 'FileType', content: @file_type if @file_type.present?
|
|
92
92
|
set_node("FileReference", @file_reference)
|
|
93
93
|
end
|
|
@@ -110,20 +110,20 @@ module Sepa
|
|
|
110
110
|
def set_upload_file_nodes
|
|
111
111
|
set_node_b("Content", @content)
|
|
112
112
|
set_node("FileType", @file_type)
|
|
113
|
-
|
|
113
|
+
add_node_after('Environment', 'TargetId', content: @target_id) if @bank == :nordea
|
|
114
114
|
end
|
|
115
115
|
|
|
116
116
|
# Sets nodes' contents for download file list request
|
|
117
117
|
def set_download_file_list_nodes
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
add_node_after('Environment', 'TargetId', content: @target_id) if @bank == :nordea
|
|
119
|
+
add_node_after('Timestamp', 'Status', content: @status) if @status.present?
|
|
120
120
|
add_node_to_root 'FileType', content: @file_type if @file_type.present?
|
|
121
121
|
end
|
|
122
122
|
|
|
123
123
|
# Sets nodes' contents for Nordea's and OP's get certificate request
|
|
124
124
|
def set_get_certificate_nodes
|
|
125
125
|
set_node "Service", "MATU" if @bank == :op
|
|
126
|
-
set_node "TransferKey", @pin if @bank
|
|
126
|
+
set_node "TransferKey", @pin if [:op, :samlink].include?(@bank)
|
|
127
127
|
set_node "HMAC", hmac(@pin, csr_to_binary(@signing_csr)) if @bank == :nordea
|
|
128
128
|
set_node "Content", format_cert_request(@signing_csr)
|
|
129
129
|
end
|
|
@@ -131,7 +131,7 @@ module Sepa
|
|
|
131
131
|
# Sets nodes' contents for renew certificate request
|
|
132
132
|
def set_renew_certificate_nodes
|
|
133
133
|
case @bank
|
|
134
|
-
when :nordea, :op
|
|
134
|
+
when :nordea, :op, :samlink
|
|
135
135
|
set_node "Service", "service" if @bank == :nordea
|
|
136
136
|
set_node "Content", format_cert_request(@signing_csr)
|
|
137
137
|
when :danske
|
|
@@ -255,16 +255,10 @@ module Sepa
|
|
|
255
255
|
add_value_to_signature('X509Certificate', format_cert(@own_signing_certificate))
|
|
256
256
|
end
|
|
257
257
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
def add_target_id_after(node)
|
|
263
|
-
return unless @bank == :nordea
|
|
264
|
-
|
|
265
|
-
target_id = Nokogiri::XML::Node.new 'TargetId', @application_request
|
|
266
|
-
target_id.content = @target_id
|
|
267
|
-
@application_request.at(node).add_next_sibling target_id
|
|
258
|
+
def add_node_after(node, new_node, content:)
|
|
259
|
+
new_node = Nokogiri::XML::Node.new(new_node, @application_request)
|
|
260
|
+
new_node.content = content
|
|
261
|
+
@application_request.at(node).add_next_sibling(new_node)
|
|
268
262
|
end
|
|
269
263
|
|
|
270
264
|
def canonicalization_mode
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
module Sepa
|
|
2
|
-
|
|
3
2
|
# Contains functionality for the application response embedded in {Response}
|
|
4
3
|
# @todo Use functionality from this class more when validating response
|
|
5
4
|
class ApplicationResponse
|
|
@@ -96,6 +95,5 @@ module Sepa
|
|
|
96
95
|
def response_must_validate_against_schema
|
|
97
96
|
check_validity_against_schema(doc, 'application_response.xsd')
|
|
98
97
|
end
|
|
99
|
-
|
|
100
98
|
end
|
|
101
99
|
end
|
|
@@ -13,7 +13,7 @@ module Sepa
|
|
|
13
13
|
[
|
|
14
14
|
STANDARD_COMMANDS,
|
|
15
15
|
:get_certificate,
|
|
16
|
-
:renew_certificate
|
|
16
|
+
:renew_certificate,
|
|
17
17
|
].flatten
|
|
18
18
|
when :danske
|
|
19
19
|
[
|
|
@@ -28,6 +28,12 @@ module Sepa
|
|
|
28
28
|
:get_certificate,
|
|
29
29
|
:get_service_certificates,
|
|
30
30
|
].flatten
|
|
31
|
+
when :samlink
|
|
32
|
+
[
|
|
33
|
+
STANDARD_COMMANDS - [:get_user_info],
|
|
34
|
+
:get_certificate,
|
|
35
|
+
:renew_certificate,
|
|
36
|
+
].flatten
|
|
31
37
|
else
|
|
32
38
|
[]
|
|
33
39
|
end
|
|
@@ -53,11 +59,9 @@ module Sepa
|
|
|
53
59
|
errors.add(:signing_private_key, "Invalid signing private key")
|
|
54
60
|
end
|
|
55
61
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
errors.add(:own_signing_certificate, "Invalid signing certificate")
|
|
60
|
-
end
|
|
62
|
+
x509_certificate own_signing_certificate
|
|
63
|
+
rescue
|
|
64
|
+
errors.add(:own_signing_certificate, "Invalid signing certificate")
|
|
61
65
|
end
|
|
62
66
|
|
|
63
67
|
# Checks that signing certificate signing request can be initialized properly.
|
|
@@ -82,8 +86,7 @@ module Sepa
|
|
|
82
86
|
if file_type.present?
|
|
83
87
|
valid = file_type.size < 35
|
|
84
88
|
else
|
|
85
|
-
return if bank == :op && %i(download_file
|
|
86
|
-
download_file_list).include?(command)
|
|
89
|
+
return if bank == :op && %i(download_file download_file_list).include?(command)
|
|
87
90
|
|
|
88
91
|
valid = !(%i(
|
|
89
92
|
download_file
|
|
@@ -97,17 +100,21 @@ module Sepa
|
|
|
97
100
|
|
|
98
101
|
# Checks that {Client#target_id} is valid.
|
|
99
102
|
def check_target_id
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
103
|
+
exclude_commands = [
|
|
104
|
+
:create_certificate,
|
|
105
|
+
:get_bank_certificate,
|
|
106
|
+
:get_certificate,
|
|
107
|
+
:get_user_info,
|
|
108
|
+
:renew_certificate,
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
exclude_banks = [
|
|
112
|
+
:danske,
|
|
113
|
+
:op,
|
|
114
|
+
:samlink,
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
return if exclude_commands.include?(command) || exclude_banks.include?(bank)
|
|
111
118
|
|
|
112
119
|
check_presence_and_length(:target_id, 80, TARGET_ID_ERROR_MESSAGE)
|
|
113
120
|
end
|
|
@@ -122,7 +129,7 @@ module Sepa
|
|
|
122
129
|
check &&= send(attribute)
|
|
123
130
|
check &&= send(attribute).respond_to? :size
|
|
124
131
|
check &&= send(attribute).size < length
|
|
125
|
-
check &&= send(attribute).
|
|
132
|
+
check &&= !send(attribute).empty?
|
|
126
133
|
|
|
127
134
|
errors.add(attribute, error_message) unless check
|
|
128
135
|
end
|
|
@@ -135,7 +142,7 @@ module Sepa
|
|
|
135
142
|
check = true
|
|
136
143
|
check &&= content
|
|
137
144
|
check &&= content.respond_to? :length
|
|
138
|
-
check &&= content.
|
|
145
|
+
check &&= !content.empty?
|
|
139
146
|
|
|
140
147
|
errors.add(:content, CONTENT_ERROR_MESSAGE) unless check
|
|
141
148
|
end
|
|
@@ -151,10 +158,9 @@ module Sepa
|
|
|
151
158
|
# {Client#command} is `:get_bank_certificate`.
|
|
152
159
|
def check_environment
|
|
153
160
|
return if command == :get_bank_certificate
|
|
161
|
+
return if Client::ENVIRONMENTS.include?(environment)
|
|
154
162
|
|
|
155
|
-
|
|
156
|
-
errors.add(:environment, ENVIRONMENT_ERROR_MESSAGE)
|
|
157
|
-
end
|
|
163
|
+
errors.add(:environment, ENVIRONMENT_ERROR_MESSAGE)
|
|
158
164
|
end
|
|
159
165
|
|
|
160
166
|
# Checks that {Client#customer_id} is valid
|
|
@@ -182,11 +188,11 @@ module Sepa
|
|
|
182
188
|
|
|
183
189
|
# Checks that {Client#status} is included in {Client::STATUSES}.
|
|
184
190
|
def check_status
|
|
191
|
+
return if bank == :samlink && command != :download_file_list
|
|
185
192
|
return unless [:download_file_list, :download_file].include? command
|
|
193
|
+
return if status && Client::STATUSES.include?(status)
|
|
186
194
|
|
|
187
|
-
|
|
188
|
-
errors.add :status, STATUS_ERROR_MESSAGE
|
|
189
|
-
end
|
|
195
|
+
errors.add :status, STATUS_ERROR_MESSAGE
|
|
190
196
|
end
|
|
191
197
|
|
|
192
198
|
# Checks presence and length of {Client#file_reference} if {Client#command} is `:download_file`
|
|
@@ -208,6 +214,5 @@ module Sepa
|
|
|
208
214
|
rescue
|
|
209
215
|
errors.add :encryption_private_key, ENCRYPTION_PRIVATE_KEY_ERROR_MESSAGE
|
|
210
216
|
end
|
|
211
|
-
|
|
212
217
|
end
|
|
213
218
|
end
|
|
@@ -2,6 +2,8 @@ module Sepa
|
|
|
2
2
|
# Handles Danske Bank specific {Response} functionality. Mainly decryption and certificate
|
|
3
3
|
# specific stuff.
|
|
4
4
|
class DanskeResponse < Response
|
|
5
|
+
CERTIFICATE_COMMANDS = [:get_bank_certificate, :create_certificate, :renew_certificate].freeze
|
|
6
|
+
|
|
5
7
|
validate :valid_get_bank_certificate_response
|
|
6
8
|
validate :can_be_decrypted_with_given_key
|
|
7
9
|
|
|
@@ -84,41 +86,23 @@ module Sepa
|
|
|
84
86
|
# @return [OpenSSL::X509::Certificate]
|
|
85
87
|
# @raise [OpenSSL::X509::CertificateError] if certificate cannot be processed
|
|
86
88
|
def certificate
|
|
87
|
-
return super unless
|
|
89
|
+
return super unless CERTIFICATE_COMMANDS.include? @command
|
|
88
90
|
|
|
89
91
|
@certificate ||= extract_cert(doc, 'X509Certificate', DSIG)
|
|
90
92
|
end
|
|
91
93
|
|
|
92
|
-
# Extract response code from the response. Overrides super method when {#command} is
|
|
93
|
-
# `:get_bank_certificate`, `:create_certificate` or `:renew_certificate` because response code node is named
|
|
94
|
-
# differently in those responses.
|
|
95
|
-
#
|
|
96
|
-
# @return [String] if response code is found
|
|
97
|
-
# @return [nil] if response code cannot be found
|
|
98
94
|
# @see Response#response_code
|
|
99
95
|
def response_code
|
|
100
|
-
return super unless
|
|
101
|
-
|
|
102
|
-
node = doc.at('xmlns|ReturnCode', xmlns: DANSKE_PKI)
|
|
103
|
-
node = doc.at('xmlns|ReturnCode', xmlns: DANSKE_PKIF) unless node
|
|
96
|
+
return super unless CERTIFICATE_COMMANDS.include? @command
|
|
104
97
|
|
|
105
|
-
|
|
98
|
+
super(namespace: DANSKE_PKI, node_name: 'ReturnCode') || super(namespace: DANSKE_PKIF, node_name: 'ReturnCode')
|
|
106
99
|
end
|
|
107
100
|
|
|
108
|
-
# Extract response text from the response. Overrides super method when {#command} is
|
|
109
|
-
# `:get_bank_certificate`, `:create_certificate` or `:renew_certificate` because response text node is named
|
|
110
|
-
# differently in those responses.
|
|
111
|
-
#
|
|
112
|
-
# @return [String] if response text is found
|
|
113
|
-
# @return [nil] if response text cannot be found
|
|
114
101
|
# @see Response#response_text
|
|
115
102
|
def response_text
|
|
116
|
-
return super unless
|
|
117
|
-
|
|
118
|
-
node = doc.at('xmlns|ReturnText', xmlns: DANSKE_PKI)
|
|
119
|
-
node = doc.at('xmlns|ReturnText', xmlns: DANSKE_PKIF) unless node
|
|
103
|
+
return super unless CERTIFICATE_COMMANDS.include? @command
|
|
120
104
|
|
|
121
|
-
|
|
105
|
+
super(namespace: DANSKE_PKI, node_name: 'ReturnText') || super(namespace: DANSKE_PKIF, node_name: 'ReturnText')
|
|
122
106
|
end
|
|
123
107
|
|
|
124
108
|
# Checks whether certificate embedded in the response has been signed with the bank's root
|
|
@@ -144,7 +128,7 @@ module Sepa
|
|
|
144
128
|
# @return [Nokogiri::XML::Node] node with signature removed from its document since signature
|
|
145
129
|
# has to be removed for canonicalization and hash calculation
|
|
146
130
|
def find_node_by_uri(uri)
|
|
147
|
-
return super unless
|
|
131
|
+
return super unless CERTIFICATE_COMMANDS.include? @command
|
|
148
132
|
|
|
149
133
|
doc_without_signature = doc.dup
|
|
150
134
|
doc_without_signature.at('xmlns|Signature', xmlns: DSIG).remove
|
|
@@ -203,7 +187,7 @@ module Sepa
|
|
|
203
187
|
# Validates that the encrypted key in the response can be decrypted with the private key given
|
|
204
188
|
# to the response in the parameters. Response is invalid if this cannot be done.
|
|
205
189
|
def can_be_decrypted_with_given_key
|
|
206
|
-
return if
|
|
190
|
+
return if CERTIFICATE_COMMANDS.include? @command
|
|
207
191
|
return unless encrypted_application_response.css('CipherValue', 'xmlns' => XMLENC)[0]
|
|
208
192
|
return if decrypt_embedded_key
|
|
209
193
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
module Sepa
|
|
2
|
-
|
|
3
2
|
# Handles Nordea specific response logic. Mainly certificate specific stuff.
|
|
4
3
|
class NordeaResponse < Response
|
|
5
4
|
include Utilities
|
|
@@ -20,30 +19,18 @@ module Sepa
|
|
|
20
19
|
cert.to_s
|
|
21
20
|
end
|
|
22
21
|
|
|
23
|
-
# Returns the response code in the response. Overrides {Response#response_code} if {#command} is
|
|
24
|
-
# `:get_certificate`, because the namespace is different with that command.
|
|
25
|
-
#
|
|
26
|
-
# @return [String] response code if it is found
|
|
27
|
-
# @return [nil] if response code cannot be found
|
|
28
22
|
# @see Response#response_code
|
|
29
23
|
def response_code
|
|
30
24
|
return super unless [:get_certificate, :renew_certificate].include? command
|
|
31
25
|
|
|
32
|
-
|
|
33
|
-
node.content if node
|
|
26
|
+
super(namespace: NORDEA_PKI)
|
|
34
27
|
end
|
|
35
28
|
|
|
36
|
-
# Returns the response text in the response. Overrides {Response#response_text} if {#command} is
|
|
37
|
-
# `:get_certificate`, because the namespace is different with that command.
|
|
38
|
-
#
|
|
39
|
-
# @return [String] response text if it is found
|
|
40
|
-
# @return [nil] if response text cannot be found
|
|
41
29
|
# @see Response#response_text
|
|
42
30
|
def response_text
|
|
43
31
|
return super unless [:get_certificate, :renew_certificate].include? command
|
|
44
32
|
|
|
45
|
-
|
|
46
|
-
node.content if node
|
|
33
|
+
super(namespace: NORDEA_PKI)
|
|
47
34
|
end
|
|
48
35
|
|
|
49
36
|
# Checks whether the certificate embedded in the response soap has been signed with Nordea's
|
|
@@ -55,6 +42,5 @@ module Sepa
|
|
|
55
42
|
def certificate_is_trusted?
|
|
56
43
|
verify_certificate_against_root_certificate(certificate, NORDEA_ROOT_CERTIFICATE)
|
|
57
44
|
end
|
|
58
|
-
|
|
59
45
|
end
|
|
60
46
|
end
|
|
@@ -6,7 +6,7 @@ module Sepa
|
|
|
6
6
|
BYPASS_COMMANDS = %i(
|
|
7
7
|
get_certificate
|
|
8
8
|
get_service_certificates
|
|
9
|
-
)
|
|
9
|
+
).freeze
|
|
10
10
|
|
|
11
11
|
# Extracts own signing certificate from the response.
|
|
12
12
|
#
|
|
@@ -24,36 +24,18 @@ module Sepa
|
|
|
24
24
|
cert.to_s
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
# Returns the response code in the response. Overrides {Response#response_code} if {#command} is
|
|
28
|
-
# `:get_certificate`, because the namespace is different with that command.
|
|
29
|
-
#
|
|
30
|
-
# @return [String] response code if it is found
|
|
31
|
-
# @return [nil] if response code cannot be found
|
|
32
27
|
# @see Response#response_code
|
|
33
28
|
def response_code
|
|
34
|
-
return super unless
|
|
35
|
-
get_certificate
|
|
36
|
-
get_service_certificates
|
|
37
|
-
).include? command
|
|
29
|
+
return super unless [:get_certificate, :get_service_certificates].include? command
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
node.content if node
|
|
31
|
+
super(namespace: OP_PKI)
|
|
41
32
|
end
|
|
42
33
|
|
|
43
|
-
# Returns the response text in the response. Overrides {Response#response_text} if {#command} is
|
|
44
|
-
# `:get_certificate`, because the namespace is different with that command.
|
|
45
|
-
#
|
|
46
|
-
# @return [String] response text if it is found
|
|
47
|
-
# @return [nil] if response text cannot be found
|
|
48
34
|
# @see Response#response_text
|
|
49
35
|
def response_text
|
|
50
|
-
return super unless
|
|
51
|
-
get_certificate
|
|
52
|
-
get_service_certificates
|
|
53
|
-
).include? command
|
|
36
|
+
return super unless [:get_certificate, :get_service_certificates].include? command
|
|
54
37
|
|
|
55
|
-
|
|
56
|
-
node.content if node
|
|
38
|
+
super(namespace: OP_PKI)
|
|
57
39
|
end
|
|
58
40
|
|
|
59
41
|
# Checks whether the certificate embedded in the response soap has been signed with OP's
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Sepa
|
|
2
|
+
# Handles Samlink specific response logic. Mainly certificate specific stuff.
|
|
3
|
+
class SamlinkResponse < Response
|
|
4
|
+
# @see Response#response_code
|
|
5
|
+
def response_code
|
|
6
|
+
[:get_certificate, :renew_certificate].include?(command) ? super(namespace: SAMLINK_PKI) : super
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# @see Response#response_code
|
|
10
|
+
def response_text
|
|
11
|
+
[:get_certificate, :renew_certificate].include?(command) ? super(namespace: SAMLINK_PKI) : super
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def application_response
|
|
15
|
+
[:get_certificate, :renew_certificate].include?(command) ? super(namespace: SAMLINK_PKI) : super
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def own_signing_certificate
|
|
19
|
+
(node = Nokogiri::XML(application_response).at('xmlns|Certificate > xmlns|Certificate', xmlns: OP_XML_DATA)) &&
|
|
20
|
+
(content = node.content) &&
|
|
21
|
+
x509_certificate(decode(content)).to_s
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def certificate_is_trusted?
|
|
25
|
+
case environment
|
|
26
|
+
when :production
|
|
27
|
+
# Samlink doesn't provide a CA certificate for production environment and that's why we check that the
|
|
28
|
+
# certificate provided is equal to the known trusted certificate.
|
|
29
|
+
certificate.to_s == SAMLINK_CERTIFICATE.to_s
|
|
30
|
+
when :test
|
|
31
|
+
verify_certificate_against_root_certificate(certificate, SAMLINK_ROOT_CERTIFICATE)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIE6TCCAtGgAwIBAgIQA3WFy1naV3PkFL0hKYOZ3TANBgkqhkiG9w0BAQsFADA9
|
|
3
|
+
MQswCQYDVQQGEwJGSTEQMA4GA1UECgwHU2FtbGluazEcMBoGA1UEAwwTU2FtbGlu
|
|
4
|
+
ayBDdXN0b21lciBDQTAeFw0xNDA5MjQwODI0MjJaFw0xNzA5MjMwODI0MjJaMFYx
|
|
5
|
+
CzAJBgNVBAYTAkZJMSEwHwYDVQQKDBhBaW5laXN0b3BhbHZlbHV0LVNhbWxpbmsx
|
|
6
|
+
ETAPBgNVBAMMCFNFUEFXRUJTMREwDwYDVQQEDAgwMDAwMDAwMTCCASIwDQYJKoZI
|
|
7
|
+
hvcNAQEBBQADggEPADCCAQoCggEBANpDNrC4C+2vUuDvDYpvRn14AWW48JlOC8M/
|
|
8
|
+
w5k5/fu8B+sV70qt/no3JKBKNvNpqDr34hILBtCc3TppGDz+Uv/W347Q/N42B1Z9
|
|
9
|
+
8cAKMEkoKvLcQVotlLSzxXeG5nhsZKw79uiyNx8VePHnnPVjjH1+daOG0xEPZqcL
|
|
10
|
+
XqtJh2dI9OjHs+HWkgy8Eudv0GrO0g5ArrEN1sfNfp9WdhZ7nzHtYcIYVApZB9oV
|
|
11
|
+
MpBkWXBAV3XZNbu+3gHbAs7JNi+c90MOmuhlzUIF6DNUU0ahrTQR55LynkGVuY/v
|
|
12
|
+
jlQvIdzD71bC3MoNZ1yJgoWDi1DjakkdSijiH2lLJtYlKQ/VTVcCAwEAAaOByzCB
|
|
13
|
+
yDAfBgNVHSMEGDAWgBTKgDgzk4pjBJGNBWlWaEI15cf/vDB2BgNVHR8EbzBtMGug
|
|
14
|
+
aaBnhmVsZGFwOi8vMTk0LjI1Mi4xMjQuMjQxOjM4OS9jbj1TYW1saW5rJTIwQ3Vz
|
|
15
|
+
dG9tZXIlMjBDQSxvPVNhbWxpbmssYz1maT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25s
|
|
16
|
+
aXN0O2JpbmFyeTAOBgNVHQ8BAf8EBAMCBPAwHQYDVR0OBBYEFEAoDpdUQbW9K35l
|
|
17
|
+
2K3ywgNemLeWMA0GCSqGSIb3DQEBCwUAA4ICAQBr0+3BfuQacQ9esTZpny08lagu
|
|
18
|
+
FMttI47i8AUwkJkKnvhROysBke77UoO6jyHDxskFOHd9yZdnPfzpJ6AVXzqwUxdL
|
|
19
|
+
Uakk38Wk8ODAyF6leRuy+I/biO+jRa52C0Ai4+XF5VNa1UUrsvjYJl6BqKJmI8aO
|
|
20
|
+
34ArzOcFocUF9UBQNC/eqL/AIx8mp5HC6fWA58kvWwiwdC5CQILbMMADpDjmEpkg
|
|
21
|
+
2ueBsLudrxXw1uNktY2wUv95KcfmlqdeAPkb0ra5x7p5SM1bJYFh8MMpm9BwnJ3a
|
|
22
|
+
q/l1+qFMmL0GCcevNQP5Dp3Vkrsf601aQcYyaptHMfiv6ryLfVq3487gUPNPUwWn
|
|
23
|
+
x24K1A5j1aQBmF8TLZl8MRkDeeEIwbXJxgoZZXAJSO2Yf/JO/vPCalBJflosiNgg
|
|
24
|
+
o9oxE8LCjqbJ26HeiNoeNUC1cnv15yhb6O+eSgZbkAYfuKgLWeOele3oC2QWqqT7
|
|
25
|
+
TSHaEipRz3TifdzpzKuXRvQaPv6lra28nbyc+OeJlnr/A7ZH3VF6OkasAoIC5wmU
|
|
26
|
+
tJgcQW5eD5jmaQZYktZljNWKXEm6tXmXOnDoRib0yzqUA9s6ReD7sBHBUaTDZFfy
|
|
27
|
+
/qrAHfYk4Pe/9seeBmbTnkdi5VnoNQT70boqaVsa/OK8eE2EWjTYs++ocfWaGSpN
|
|
28
|
+
pUI4al2qFueN8ji+nw==
|
|
29
|
+
-----END CERTIFICATE-----
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIFgjCCA2qgAwIBAgIQMEFUVTYB8PwGq4Ak5dfC5TANBgkqhkiG9w0BAQsFADBJ
|
|
3
|
+
MQswCQYDVQQGEwJGSTEQMA4GA1UECgwHU2FtbGluazEoMCYGA1UEAwwfU2FtbGlu
|
|
4
|
+
ayBTeXN0ZW0gVGVzdCBDdXN0b21lciBDQTAeFw0wOTA2MDQxMjU3MTNaFw0zNDA2
|
|
5
|
+
MDQxMjU3MTNaMEkxCzAJBgNVBAYTAkZJMRAwDgYDVQQKDAdTYW1saW5rMSgwJgYD
|
|
6
|
+
VQQDDB9TYW1saW5rIFN5c3RlbSBUZXN0IEN1c3RvbWVyIENBMIICIjANBgkqhkiG
|
|
7
|
+
9w0BAQEFAAOCAg8AMIICCgKCAgEAxNegF+36GmNnZJGvGZaZNvMufcpnpSMXtsFC
|
|
8
|
+
6epS+nG9M+KtdcUXGy2W58n0skLmF/lg+IiiK6OyLl621KfpUu2rKQ5TKuTazhW7
|
|
9
|
+
JX3Ha/4Dwa1OJtnfUlWiE94SEJwLspcOI3svSuv7IwEs3brnoNji0+V1qbr3/C2s
|
|
10
|
+
y4x/NQcColsvwMwMUNTuUGxk/I3s/yobUrBTDX3dw2ENhVvTQjnnnhUEsr8f4Hvg
|
|
11
|
+
ouVQTkutLDlB4e/ugYe3cFPDomy5gg8JgDqE+EvrNFRxD7v5Gnwau4jVH2hkB/wC
|
|
12
|
+
2/QAvV8bpBhKOSVUZN7mPIIg6HiCqJd/R6Qd+Hyh9DaTxXUFLPIQs1M352sZRYMJ
|
|
13
|
+
lnwYQCnH/krA7K0rlEjOiiAtlZPeayxatctRFVQyMfzaTzKL7+1jVEcexVDM8aIv
|
|
14
|
+
76Br4cPF2ymF9QGSp9noRozX44yVjNSXqHysjIpUrRG9sQcyraP7+FGfKx3PkihB
|
|
15
|
+
nO9aHplcUIXNldbXu+vobayBHRi5VimV21u7R1DCxbZhfeyxHdlN4/G0Qo4aOLNw
|
|
16
|
+
5Z7ncWwVbTxN14/xHAP14VK4toytsqJ2EhtxVXNEBXgJT2NOimPMbtouRjbgnrmp
|
|
17
|
+
Rb85x9YnCSQhs/Kkh7R5ay7lMa0yS6WeP1G6xXfQ8WOkUkYb+npH5NCtFb47xlgy
|
|
18
|
+
pY1/RxcCAwEAAaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8C
|
|
19
|
+
AQAwHQYDVR0OBBYEFAKqDJ696UiBJwgo5ujeFPcVjLm2MB8GA1UdIwQYMBaAFAKq
|
|
20
|
+
DJ696UiBJwgo5ujeFPcVjLm2MA0GCSqGSIb3DQEBCwUAA4ICAQCZ8hOaNfX7LjCO
|
|
21
|
+
R2uPJ89z28tLq4rEX7s+ntTVAtjx78q3x8Pk+DWopucjtqpBBgjSxI6Y3ZDyW4SS
|
|
22
|
+
BWLs9tz+CKbPUkFKOE0/vPbdsFBA1miJrwt8VgzndGb9T+GLAM91d+wXJqccTlmH
|
|
23
|
+
2ERx8lAJSFThO0Dr+WK+N9UFfEviovlnq6ZRGd4X2mk3l/yQ9VDuDNGhb2vH8/Z8
|
|
24
|
+
89deMvP3v9DNm4WiHvKtJ7cdEhiH90SUICKnRRGwu3353QcnGMUfNhqQCnSVGjhN
|
|
25
|
+
EiWukxNF2t5DhDw066wjjxFD5WBG7na5AEzJzW9yn3N4FPNENgege2p7wkyJ4W2/
|
|
26
|
+
qDymuRB26LpfRbzAJ7TdzZM7EeBI2DkXT2mR4/5NQ/TAcPqG2GIDuMuOAvsD7piX
|
|
27
|
+
4tWZDT0phBwQy/EXmCBRwta2w/AcQsrZqUkTD0jJSAJ/rpyatYQz/3y8lLcEz5Do
|
|
28
|
+
ZMFk1a4nYGoyP9O5c04amfdSvhyrjzB0XETnoaQoJPxmpDSmNWmOA6sFL9tMF2ec
|
|
29
|
+
B1Z2ad8VaUJ8Ssyz0uKRZPhbjj7t/nYvR6sz+lIQkISWkdjKUINWaA0Y/qt+rAQr
|
|
30
|
+
c9WTZ8meh1VD8bXn4RRR3KxoFgBqSfz3b4U6gt2M0E/1r8moQXzc7MDeFD3AQVvm
|
|
31
|
+
yMgRk0vap01P6bNkJgj/PrkOw/ECDQ==
|
|
32
|
+
-----END CERTIFICATE-----
|
data/lib/sepa/client.rb
CHANGED
|
@@ -162,11 +162,27 @@ module Sepa
|
|
|
162
162
|
# @see #signing_csr The format is the same as in signing csr
|
|
163
163
|
attr_accessor :encryption_csr
|
|
164
164
|
|
|
165
|
+
# Options to be passed directly to the underlying savon client. Format is as follows:
|
|
166
|
+
# {
|
|
167
|
+
# globals: {
|
|
168
|
+
# ssl_verify_mode: :none,
|
|
169
|
+
# ...,
|
|
170
|
+
# },
|
|
171
|
+
# locals: {
|
|
172
|
+
# xml: "<envelope></envelope>",
|
|
173
|
+
# ...,
|
|
174
|
+
# },
|
|
175
|
+
# }
|
|
176
|
+
#
|
|
177
|
+
# @return [Hash]
|
|
178
|
+
attr_accessor :savon_options
|
|
179
|
+
|
|
165
180
|
# The list of banks that are currently supported by this gem
|
|
166
181
|
BANKS = %i(
|
|
167
182
|
danske
|
|
168
183
|
nordea
|
|
169
184
|
op
|
|
185
|
+
samlink
|
|
170
186
|
).freeze
|
|
171
187
|
|
|
172
188
|
# Languages that are currently supported by the gem
|
|
@@ -204,9 +220,13 @@ module Sepa
|
|
|
204
220
|
# @param hash [Hash] All the attributes of the client can be given to the construcor in a hash
|
|
205
221
|
def initialize(hash = {})
|
|
206
222
|
attributes(hash)
|
|
207
|
-
self.environment
|
|
208
|
-
self.language
|
|
209
|
-
self.status
|
|
223
|
+
self.environment ||= :production
|
|
224
|
+
self.language ||= 'EN'
|
|
225
|
+
self.status ||= 'NEW'
|
|
226
|
+
self.savon_options ||= {
|
|
227
|
+
globals: {},
|
|
228
|
+
locals: {},
|
|
229
|
+
}
|
|
210
230
|
end
|
|
211
231
|
|
|
212
232
|
def bank=(value)
|
|
@@ -249,12 +269,11 @@ module Sepa
|
|
|
249
269
|
def send_request
|
|
250
270
|
raise ArgumentError, errors.messages unless valid?
|
|
251
271
|
|
|
252
|
-
|
|
253
|
-
client = Savon.client(wsdl: wsdl)
|
|
272
|
+
client = Savon.client(savon_globals)
|
|
254
273
|
|
|
255
274
|
begin
|
|
256
275
|
error = nil
|
|
257
|
-
response = client.call(soap_command,
|
|
276
|
+
response = client.call(soap_command, savon_locals)
|
|
258
277
|
response &&= response.to_xml
|
|
259
278
|
rescue Savon::Error => e
|
|
260
279
|
response = nil
|
|
@@ -318,7 +337,7 @@ module Sepa
|
|
|
318
337
|
command: command,
|
|
319
338
|
environment: environment,
|
|
320
339
|
error: error,
|
|
321
|
-
response: response
|
|
340
|
+
response: response,
|
|
322
341
|
}
|
|
323
342
|
if encryption_private_key && !encryption_private_key.empty?
|
|
324
343
|
options[:encryption_private_key] = rsa_key(encryption_private_key)
|
|
@@ -328,11 +347,19 @@ module Sepa
|
|
|
328
347
|
end
|
|
329
348
|
|
|
330
349
|
def soap_command
|
|
331
|
-
if @command == :renew_certificate && [:nordea, :op].include?(@bank)
|
|
350
|
+
if @command == :renew_certificate && [:nordea, :op, :samlink].include?(@bank)
|
|
332
351
|
:get_certificate
|
|
333
352
|
else
|
|
334
353
|
@command
|
|
335
354
|
end
|
|
336
355
|
end
|
|
356
|
+
|
|
357
|
+
def savon_globals
|
|
358
|
+
{ wsdl: wsdl }.merge(savon_options[:globals] || {})
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
def savon_locals
|
|
362
|
+
{ xml: SoapBuilder.new(create_hash).to_xml }.merge(savon_options[:locals] || {})
|
|
363
|
+
end
|
|
337
364
|
end
|
|
338
365
|
end
|