sepafm 1.1.5 → 1.1.6
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 +3 -0
- data/lib/sepa/application_request.rb +17 -8
- data/lib/sepa/attribute_checks.rb +23 -26
- data/lib/sepa/banks/danske/danske_response.rb +29 -41
- data/lib/sepa/banks/danske/soap_danske.rb +30 -23
- data/lib/sepa/client.rb +8 -11
- data/lib/sepa/response.rb +13 -23
- data/lib/sepa/utilities.rb +2 -6
- data/lib/sepa/version.rb +1 -1
- data/lib/sepa/xml_schemas/danske_pki.xsd +1 -1
- data/lib/sepa/xml_templates/application_request/danske/renew_certificate.xml +33 -0
- data/lib/sepa/xml_templates/soap/danske/renew_certificate.xml +17 -0
- data/readme.md +3 -3
- data/sepafm.gemspec +4 -4
- data/test/custom_assertions.rb +21 -0
- data/test/sepa/banks/danske/danske_cert_soap_builder_test.rb +1 -5
- data/test/sepa/banks/danske/danske_certificate_application_request_test.rb +6 -8
- data/test/sepa/banks/danske/danske_generic_soap_builder_test.rb +7 -23
- data/test/sepa/banks/danske/danske_get_bank_cert_test.rb +3 -13
- data/test/sepa/banks/danske/danske_renew_cert_application_request_test.rb +32 -0
- data/test/sepa/banks/danske/danske_renew_cert_request_soap_builder_test.rb +41 -0
- data/test/sepa/banks/nordea/nordea_application_request_test.rb +4 -16
- data/test/sepa/banks/nordea/nordea_cert_application_request_test.rb +1 -5
- data/test/sepa/banks/nordea/nordea_cert_request_soap_builder_test.rb +1 -4
- data/test/sepa/banks/nordea/nordea_generic_soap_builder_test.rb +7 -23
- data/test/sepa/banks/nordea/nordea_renew_cert_application_request_test.rb +1 -10
- data/test/sepa/banks/nordea/nordea_renew_cert_request_soap_builder_test.rb +1 -10
- data/test/sepa/banks/op/op_application_request_test.rb +3 -30
- data/test/sepa/banks/op/op_cert_application_request_test.rb +1 -10
- data/test/sepa/banks/op/op_cert_request_soap_builder_test.rb +1 -10
- data/test/sepa/banks/op/op_generic_soap_builder_test.rb +2 -20
- data/test/sepa/client_test.rb +42 -66
- data/test/sepa/fixtures.rb +72 -23
- data/test/sepa/sepa_test.rb +1 -1
- data/test_client/test_client.rb +23 -18
- metadata +16 -19
- data/.travis.yml +0 -16
- data/test/sepa/banks/danske/keys/danske_encryption.crt +0 -24
- data/test/sepa/banks/danske/keys/encryption_pkcs.csr +0 -0
- data/test/sepa/banks/danske/keys/signing_pkcs.csr +0 -0
- data/test/sepa/banks/danske/keys/signing_private_key.pem +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c038dcb77ca225b13580f7f01c23ecf58fc00e23
|
4
|
+
data.tar.gz: aa11761b080c92183b185d997bb5c7e509e88171
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea3ae75974fbbb309e959796d709dbf50209f03e8fe5d2b5d47b4028c08cd9dbecbeb2e0f835b84792ee5d71f43e16aae94b7ac69dbb09122c990cff6016435d
|
7
|
+
data.tar.gz: ad964633e3b736ade71ee6a64222311167a47f5f0b7d5406ac06b1f0bfd3012a232e782e798d86d6fe9e14c30afa9f1df549ccc2a1310054735daed5e71ebe3b
|
data/.rubocop.yml
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module Sepa
|
2
|
-
|
3
2
|
# Contains functionality to build the application request
|
4
3
|
#
|
5
4
|
# @todo Add return values for content modifying methods to signal whether they succeeded or not
|
@@ -22,7 +21,7 @@ module Sepa
|
|
22
21
|
instance_variable_set("@#{key}", value)
|
23
22
|
end
|
24
23
|
|
25
|
-
@application_request = load_body_template
|
24
|
+
@application_request = load_body_template(AR_TEMPLATE_PATH)
|
26
25
|
end
|
27
26
|
|
28
27
|
# Sets the nodes in the application request, processes signature and then returns the
|
@@ -129,10 +128,21 @@ module Sepa
|
|
129
128
|
set_node "Content", format_cert_request(@signing_csr)
|
130
129
|
end
|
131
130
|
|
132
|
-
# Sets nodes' contents for
|
131
|
+
# Sets nodes' contents for renew certificate request
|
133
132
|
def set_renew_certificate_nodes
|
134
|
-
|
135
|
-
|
133
|
+
case @bank
|
134
|
+
when :nordea, :op
|
135
|
+
set_node "Service", "service" if @bank == :nordea
|
136
|
+
set_node "Content", format_cert_request(@signing_csr)
|
137
|
+
when :danske
|
138
|
+
@environment = 'customertest' if @environment == :test
|
139
|
+
|
140
|
+
set_node 'tns|CustomerId', @customer_id
|
141
|
+
set_node 'tns|EncryptionCertPKCS10', format_cert_request(@encryption_csr)
|
142
|
+
set_node 'tns|SigningCertPKCS10', format_cert_request(@signing_csr)
|
143
|
+
set_node 'tns|Timestamp', iso_time
|
144
|
+
set_node 'tns|Environment', @environment
|
145
|
+
end
|
136
146
|
end
|
137
147
|
|
138
148
|
# Sets nodes' contents for OP's get service certificates request
|
@@ -161,8 +171,8 @@ module Sepa
|
|
161
171
|
# Sets contents for nodes that are common to all requests except when {#command} is
|
162
172
|
# `:get_bank_certificate` or `:create_certificate`. {#environment} is upcased here.
|
163
173
|
def set_common_nodes
|
164
|
-
return if @command
|
165
|
-
return if @command == :
|
174
|
+
return if [:get_bank_certificate, :create_certificate].include?(@command)
|
175
|
+
return if @bank == :danske && @command == :renew_certificate
|
166
176
|
|
167
177
|
set_node('Environment', @environment.to_s.upcase)
|
168
178
|
set_node("CustomerId", @customer_id)
|
@@ -256,6 +266,5 @@ module Sepa
|
|
256
266
|
target_id.content = @target_id
|
257
267
|
@application_request.at(node).add_next_sibling target_id
|
258
268
|
end
|
259
|
-
|
260
269
|
end
|
261
270
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
module Sepa
|
2
|
-
|
3
2
|
# Contains functionality to check the attributes passed to {Client}. Uses
|
4
3
|
# ActiveModel::Validations for the actual validation.
|
5
4
|
module AttributeChecks
|
@@ -11,25 +10,24 @@ module Sepa
|
|
11
10
|
def allowed_commands
|
12
11
|
case bank
|
13
12
|
when :nordea
|
14
|
-
|
15
|
-
|
16
|
-
get_certificate
|
17
|
-
renew_certificate
|
18
|
-
|
13
|
+
[
|
14
|
+
STANDARD_COMMANDS,
|
15
|
+
:get_certificate,
|
16
|
+
:renew_certificate
|
17
|
+
].flatten
|
19
18
|
when :danske
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
[
|
20
|
+
STANDARD_COMMANDS - [:get_user_info],
|
21
|
+
:create_certificate,
|
22
|
+
:get_bank_certificate,
|
23
|
+
:renew_certificate,
|
24
|
+
].flatten
|
26
25
|
when :op
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
)
|
26
|
+
[
|
27
|
+
STANDARD_COMMANDS - [:get_user_info],
|
28
|
+
:get_certificate,
|
29
|
+
:get_service_certificates,
|
30
|
+
].flatten
|
33
31
|
else
|
34
32
|
[]
|
35
33
|
end
|
@@ -64,20 +62,19 @@ module Sepa
|
|
64
62
|
|
65
63
|
# Checks that signing certificate signing request can be initialized properly.
|
66
64
|
def check_signing_csr
|
67
|
-
return unless [:get_certificate, :create_certificate].include? command
|
65
|
+
return unless [:get_certificate, :create_certificate, :renew_certificate].include? command
|
66
|
+
return if cert_request_valid?(signing_csr)
|
68
67
|
|
69
|
-
|
70
|
-
errors.add(:signing_csr, SIGNING_CERT_REQUEST_ERROR_MESSAGE)
|
71
|
-
end
|
68
|
+
errors.add(:signing_csr, SIGNING_CERT_REQUEST_ERROR_MESSAGE)
|
72
69
|
end
|
73
70
|
|
74
71
|
# Checks that encryption certificate signing request can be initialized properly.
|
75
72
|
def check_encryption_cert_request
|
76
|
-
return unless
|
73
|
+
return unless bank == :danske
|
74
|
+
return unless [:create_certificate, :renew_certificate].include? command
|
75
|
+
return if cert_request_valid?(encryption_csr)
|
77
76
|
|
78
|
-
|
79
|
-
errors.add(:encryption_csr, ENCRYPTION_CERT_REQUEST_ERROR_MESSAGE)
|
80
|
-
end
|
77
|
+
errors.add(:encryption_csr, ENCRYPTION_CERT_REQUEST_ERROR_MESSAGE)
|
81
78
|
end
|
82
79
|
|
83
80
|
# Checks that {Client#file_type} is proper
|
@@ -1,9 +1,7 @@
|
|
1
1
|
module Sepa
|
2
|
-
|
3
2
|
# Handles Danske Bank specific {Response} functionality. Mainly decryption and certificate
|
4
3
|
# specific stuff.
|
5
4
|
class DanskeResponse < Response
|
6
|
-
|
7
5
|
validate :valid_get_bank_certificate_response
|
8
6
|
validate :can_be_decrypted_with_given_key
|
9
7
|
|
@@ -47,63 +45,59 @@ module Sepa
|
|
47
45
|
end
|
48
46
|
|
49
47
|
# Returns own encryption certificate which has been signed by the bank. Only present in
|
50
|
-
# `:create_certificate` responses
|
48
|
+
# `:create_certificate` & `:renew_certificate` responses
|
51
49
|
#
|
52
|
-
# @return [OpenSSL::X509::Certificate] if {#command} is `:create_certificate`
|
50
|
+
# @return [OpenSSL::X509::Certificate] if {#command} is `:create_certificate` or `:renew_certificate`
|
53
51
|
# @return [nil] if command is any other
|
54
52
|
def own_encryption_certificate
|
55
|
-
return unless @command
|
53
|
+
return unless [:create_certificate, :renew_certificate].include?(@command)
|
56
54
|
|
57
55
|
@own_encryption_certificate ||= extract_cert(doc, 'EncryptionCert', DANSKE_PKI)
|
58
56
|
end
|
59
57
|
|
60
58
|
# Returns own signing certificate which has been signed by the bank. Is used to sign requests
|
61
|
-
# sent to the bank. Is only present in `:create_certificate` responses.
|
59
|
+
# sent to the bank. Is only present in `:create_certificate` & `:renew_certificate` responses.
|
62
60
|
#
|
63
|
-
# @return [OpenSSL::X509::Certificate] if {#command} is `:create_certificate`
|
61
|
+
# @return [OpenSSL::X509::Certificate] if {#command} is `:create_certificate` or `:renew_certificate`
|
64
62
|
# @return [nil] if command is any other
|
65
63
|
def own_signing_certificate
|
66
|
-
return unless @command
|
64
|
+
return unless [:create_certificate, :renew_certificate].include?(@command)
|
67
65
|
|
68
66
|
@own_signing_certificate ||= extract_cert(doc, 'SigningCert', DANSKE_PKI)
|
69
67
|
end
|
70
68
|
|
71
69
|
# Returns the CA certificate that has been used to sign own signing and encryption certificates.
|
72
|
-
# Only present in `:create_certificate` responses
|
70
|
+
# Only present in `:create_certificate` & `:renew_certificate` responses
|
73
71
|
#
|
74
|
-
# @return [OpenSSL::X509::Certificate] if {#command} is `:create_certificate`
|
72
|
+
# @return [OpenSSL::X509::Certificate] if {#command} is `:create_certificate` or `:renew_certificate`
|
75
73
|
# @return [nil] if command is any other
|
76
74
|
def ca_certificate
|
77
|
-
return unless @command
|
75
|
+
return unless [:create_certificate, :renew_certificate].include?(@command)
|
78
76
|
|
79
77
|
@ca_certificate ||= extract_cert(doc, 'CACert', DANSKE_PKI)
|
80
78
|
end
|
81
79
|
|
82
80
|
# Extract certificate that has been used to sign the response. This overrides
|
83
|
-
# {Response#certificate} method with specific functionality for `:get_bank_certificate
|
84
|
-
# `:create_certificate` commands. Otherwise just calls {Response#certificate}
|
81
|
+
# {Response#certificate} method with specific functionality for `:get_bank_certificate`,
|
82
|
+
# `:create_certificate` & `:renew_certificate` commands. Otherwise just calls {Response#certificate}
|
85
83
|
#
|
86
84
|
# @return [OpenSSL::X509::Certificate]
|
87
85
|
# @raise [OpenSSL::X509::CertificateError] if certificate cannot be processed
|
88
86
|
def certificate
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
end
|
93
|
-
else
|
94
|
-
super
|
95
|
-
end
|
87
|
+
return super unless [:get_bank_certificate, :create_certificate, :renew_certificate].include? @command
|
88
|
+
|
89
|
+
@certificate ||= extract_cert(doc, 'X509Certificate', DSIG)
|
96
90
|
end
|
97
91
|
|
98
92
|
# Extract response code from the response. Overrides super method when {#command} is
|
99
|
-
# `:get_bank_certificate` or `:
|
93
|
+
# `:get_bank_certificate`, `:create_certificate` or `:renew_certificate` because response code node is named
|
100
94
|
# differently in those responses.
|
101
95
|
#
|
102
96
|
# @return [String] if response code is found
|
103
97
|
# @return [nil] if response code cannot be found
|
104
98
|
# @see Response#response_code
|
105
99
|
def response_code
|
106
|
-
return super unless [:get_bank_certificate, :create_certificate].include? @command
|
100
|
+
return super unless [:get_bank_certificate, :create_certificate, :renew_certificate].include? @command
|
107
101
|
|
108
102
|
node = doc.at('xmlns|ReturnCode', xmlns: DANSKE_PKI)
|
109
103
|
node = doc.at('xmlns|ReturnCode', xmlns: DANSKE_PKIF) unless node
|
@@ -112,17 +106,14 @@ module Sepa
|
|
112
106
|
end
|
113
107
|
|
114
108
|
# Extract response text from the response. Overrides super method when {#command} is
|
115
|
-
# `:get_bank_certificate` or `:
|
109
|
+
# `:get_bank_certificate`, `:create_certificate` or `:renew_certificate` because response text node is named
|
116
110
|
# differently in those responses.
|
117
111
|
#
|
118
112
|
# @return [String] if response text is found
|
119
113
|
# @return [nil] if response text cannot be found
|
120
114
|
# @see Response#response_text
|
121
115
|
def response_text
|
122
|
-
return super unless
|
123
|
-
create_certificate
|
124
|
-
get_bank_certificate
|
125
|
-
).include? @command
|
116
|
+
return super unless [:get_bank_certificate, :create_certificate, :renew_certificate].include? @command
|
126
117
|
|
127
118
|
node = doc.at('xmlns|ReturnText', xmlns: DANSKE_PKI)
|
128
119
|
node = doc.at('xmlns|ReturnText', xmlns: DANSKE_PKIF) unless node
|
@@ -145,7 +136,7 @@ module Sepa
|
|
145
136
|
private
|
146
137
|
|
147
138
|
# Finds a node by its reference URI from Danske Bank's certificate responses. If {#command} is
|
148
|
-
# other than `:get_bank_certificate` or `:
|
139
|
+
# other than `:get_bank_certificate`, `:create_certificate` or `:renew_certificate` returns super. This method is
|
149
140
|
# needed because Danske Bank uses a different way to reference nodes in their certificate
|
150
141
|
# responses.
|
151
142
|
#
|
@@ -153,7 +144,7 @@ module Sepa
|
|
153
144
|
# @return [Nokogiri::XML::Node] node with signature removed from its document since signature
|
154
145
|
# has to be removed for canonicalization and hash calculation
|
155
146
|
def find_node_by_uri(uri)
|
156
|
-
return super unless [:get_bank_certificate, :create_certificate].include? @command
|
147
|
+
return super unless [:get_bank_certificate, :create_certificate, :renew_certificate].include? @command
|
157
148
|
|
158
149
|
doc_without_signature = doc.dup
|
159
150
|
doc_without_signature.at('xmlns|Signature', xmlns: DSIG).remove
|
@@ -173,11 +164,11 @@ module Sepa
|
|
173
164
|
key = decrypt_embedded_key
|
174
165
|
|
175
166
|
encypted_data = encrypted_application_response
|
176
|
-
|
177
|
-
|
167
|
+
.css('CipherValue', 'xmlns' => XMLENC)[1]
|
168
|
+
.content
|
178
169
|
|
179
170
|
encypted_data = decode encypted_data
|
180
|
-
iv
|
171
|
+
iv = encypted_data[0, 8]
|
181
172
|
encypted_data = encypted_data[8, encypted_data.length]
|
182
173
|
|
183
174
|
decipher = OpenSSL::Cipher.new('DES-EDE3-CBC')
|
@@ -192,10 +183,9 @@ module Sepa
|
|
192
183
|
# from the bank.
|
193
184
|
def valid_get_bank_certificate_response
|
194
185
|
return unless @command == :get_bank_certificate
|
186
|
+
return unless doc.at('xmlns|PKIFactoryServiceFault', xmlns: DANSKE_PKIF)
|
195
187
|
|
196
|
-
|
197
|
-
errors.add(:base, "Did not get a proper response when trying to get bank's certificates")
|
198
|
-
end
|
188
|
+
errors.add(:base, "Did not get a proper response when trying to get bank's certificates")
|
199
189
|
end
|
200
190
|
|
201
191
|
# Extracts the encrypted application response from the response and returns it as a nokogiri
|
@@ -206,19 +196,18 @@ module Sepa
|
|
206
196
|
def encrypted_application_response
|
207
197
|
@encrypted_application_response ||= begin
|
208
198
|
encrypted_application_response = extract_application_response(BXD)
|
209
|
-
xml_doc
|
199
|
+
xml_doc(encrypted_application_response)
|
210
200
|
end
|
211
201
|
end
|
212
202
|
|
213
203
|
# Validates that the encrypted key in the response can be decrypted with the private key given
|
214
204
|
# to the response in the parameters. Response is invalid if this cannot be done.
|
215
205
|
def can_be_decrypted_with_given_key
|
216
|
-
return if [:get_bank_certificate, :create_certificate].include? @command
|
206
|
+
return if [:get_bank_certificate, :create_certificate, :renew_certificate].include? @command
|
217
207
|
return unless encrypted_application_response.css('CipherValue', 'xmlns' => XMLENC)[0]
|
208
|
+
return if decrypt_embedded_key
|
218
209
|
|
219
|
-
|
220
|
-
errors.add(:encryption_private_key, DECRYPTION_ERROR_MESSAGE)
|
221
|
-
end
|
210
|
+
errors.add(:encryption_private_key, DECRYPTION_ERROR_MESSAGE)
|
222
211
|
end
|
223
212
|
|
224
213
|
# Decrypts (assymetrically) the symmetric encryption key embedded in the response with the
|
@@ -235,6 +224,5 @@ module Sepa
|
|
235
224
|
rescue OpenSSL::PKey::RSAError
|
236
225
|
nil
|
237
226
|
end
|
238
|
-
|
239
227
|
end
|
240
228
|
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
module Sepa
|
2
|
-
|
3
2
|
# Contains Danske Bank specific soap building functionality
|
4
3
|
module DanskeSoapRequest
|
5
|
-
|
6
4
|
private
|
7
5
|
|
8
6
|
# Determines which kind of request to build depending on command. Certificate requests differ
|
@@ -13,11 +11,13 @@ module Sepa
|
|
13
11
|
def find_correct_build
|
14
12
|
case @command
|
15
13
|
when :create_certificate
|
16
|
-
|
14
|
+
build_create_certificate_request
|
17
15
|
when :upload_file, :download_file, :get_user_info, :download_file_list
|
18
16
|
build_danske_generic_request
|
19
17
|
when :get_bank_certificate
|
20
18
|
build_get_bank_certificate_request
|
19
|
+
when :renew_certificate
|
20
|
+
build_renew_certificate_request
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -85,16 +85,16 @@ module Sepa
|
|
85
85
|
ar
|
86
86
|
end
|
87
87
|
|
88
|
-
# Sets contents for
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
set_node
|
93
|
-
set_node
|
94
|
-
set_node
|
95
|
-
set_node
|
96
|
-
set_node
|
97
|
-
set_node
|
88
|
+
# Sets contents for certificate requests.
|
89
|
+
def set_cert_contents
|
90
|
+
@environment = :customertest if @environment == :test
|
91
|
+
|
92
|
+
set_node @template, 'pkif|SenderId', @customer_id
|
93
|
+
set_node @template, 'pkif|CustomerId', @customer_id
|
94
|
+
set_node @template, 'pkif|RequestId', request_id
|
95
|
+
set_node @template, 'pkif|Timestamp', iso_time
|
96
|
+
set_node @template, 'pkif|InterfaceVersion', 1
|
97
|
+
set_node @template, 'pkif|Environment', @environment
|
98
98
|
end
|
99
99
|
|
100
100
|
# Sets contents for get bank certificate requests
|
@@ -130,12 +130,9 @@ module Sepa
|
|
130
130
|
# if set to `:test`. This request is encrypted but not signed.
|
131
131
|
#
|
132
132
|
# @return [Nokogiri::XML] the complete soap
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
set_create_cert_contents
|
137
|
-
encrypted_request = encrypt_application_request
|
138
|
-
add_encrypted_request_to_soap(encrypted_request)
|
133
|
+
def build_create_certificate_request
|
134
|
+
set_cert_contents
|
135
|
+
add_encrypted_request_to_soap(encrypt_application_request)
|
139
136
|
end
|
140
137
|
|
141
138
|
# Builds get bank certificate request soap. This request is neither signed nor encrypted.
|
@@ -146,16 +143,27 @@ module Sepa
|
|
146
143
|
add_bank_certificate_body_to_soap
|
147
144
|
end
|
148
145
|
|
146
|
+
# Builds Danske Bank's renew certificate request soap. Environment is set to `:customertest`
|
147
|
+
# if set to `:test`. This request is encrypted and signed
|
148
|
+
#
|
149
|
+
# @return [Nokogiri::XML] the complete soap
|
150
|
+
def build_renew_certificate_request
|
151
|
+
set_cert_contents
|
152
|
+
add_encrypted_request_to_soap(encrypt_application_request, parent_node: 'pkif|RenewCertificateIn')
|
153
|
+
process_header
|
154
|
+
add_body_to_header
|
155
|
+
end
|
156
|
+
|
149
157
|
# Adds encrypted application request xml structure to the soap. This method is used when
|
150
|
-
# building create certificate requests and the encrypted application request xml structure
|
158
|
+
# building create & renew certificate requests and the encrypted application request xml structure
|
151
159
|
# will not be base64 encoded.
|
152
160
|
#
|
153
161
|
# @param encrypted_request [Nokogiri::XML] the encrypted application request xml structure
|
154
162
|
# @return [Nokogiri::XML] the soap with the encrypted application request added to it
|
155
|
-
def add_encrypted_request_to_soap(encrypted_request)
|
163
|
+
def add_encrypted_request_to_soap(encrypted_request, parent_node: 'pkif|CreateCertificateIn')
|
156
164
|
encrypted_request = Nokogiri::XML(encrypted_request.to_xml)
|
157
165
|
encrypted_request = encrypted_request.root
|
158
|
-
@template.at_css(
|
166
|
+
@template.at_css(parent_node).add_child(encrypted_request)
|
159
167
|
|
160
168
|
@template
|
161
169
|
end
|
@@ -199,6 +207,5 @@ module Sepa
|
|
199
207
|
end
|
200
208
|
|
201
209
|
def set_application_request; end
|
202
|
-
|
203
210
|
end
|
204
211
|
end
|
data/lib/sepa/client.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# Main module for this gem
|
2
2
|
module Sepa
|
3
|
-
|
4
3
|
# Handles parameter validation, key initialization, {SoapBuilder} initialization, communicating
|
5
4
|
# with the bank and {Response} initialization.
|
6
5
|
class Client
|
@@ -9,7 +8,6 @@ module Sepa
|
|
9
8
|
include ErrorMessages
|
10
9
|
include AttributeChecks
|
11
10
|
|
12
|
-
|
13
11
|
# The bank that is used in this client. One of {BANKS}.
|
14
12
|
#
|
15
13
|
# @return [Symbol]
|
@@ -169,18 +167,18 @@ module Sepa
|
|
169
167
|
danske
|
170
168
|
nordea
|
171
169
|
op
|
172
|
-
)
|
170
|
+
).freeze
|
173
171
|
|
174
172
|
# Languages that are currently supported by the gem
|
175
|
-
LANGUAGES =
|
173
|
+
LANGUAGES = %w(FI SE EN).freeze
|
176
174
|
|
177
175
|
# Environments that are currently supported by the gem
|
178
|
-
ENVIRONMENTS = [:production, :test]
|
176
|
+
ENVIRONMENTS = [:production, :test].freeze
|
179
177
|
|
180
178
|
# Statuses that can be given to download file list command. When NEW is given, only those files
|
181
179
|
# that have not yet been downloaded will be listed. DOWNLOADED will list only downloaded files
|
182
180
|
# and ALL will list every file
|
183
|
-
STATUSES =
|
181
|
+
STATUSES = %w(NEW DOWNLOADED ALL).freeze
|
184
182
|
|
185
183
|
validates :bank, inclusion: { in: BANKS }
|
186
184
|
validates :language, inclusion: { in: LANGUAGES }, allow_nil: true
|
@@ -205,10 +203,10 @@ module Sepa
|
|
205
203
|
#
|
206
204
|
# @param hash [Hash] All the attributes of the client can be given to the construcor in a hash
|
207
205
|
def initialize(hash = {})
|
208
|
-
|
206
|
+
attributes(hash)
|
209
207
|
self.environment ||= :production
|
210
|
-
self.language
|
211
|
-
self.status
|
208
|
+
self.language ||= 'EN'
|
209
|
+
self.status ||= 'NEW'
|
212
210
|
end
|
213
211
|
|
214
212
|
def bank=(value)
|
@@ -330,8 +328,7 @@ module Sepa
|
|
330
328
|
end
|
331
329
|
|
332
330
|
def soap_command
|
333
|
-
|
334
|
-
when :renew_certificate
|
331
|
+
if @command == :renew_certificate && [:nordea, :op].include?(@bank)
|
335
332
|
:get_certificate
|
336
333
|
else
|
337
334
|
@command
|
data/lib/sepa/response.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module Sepa
|
2
|
-
|
3
2
|
# Handles soap responses got back from the bank. Bank specific functionality is defined in
|
4
3
|
# subclasses. Handles i.e. logic to make sure the response's integrity has not been compromised
|
5
4
|
# and has methods to extract content from the response.
|
@@ -276,9 +275,10 @@ module Sepa
|
|
276
275
|
# @return [nil] if application response cannot be found
|
277
276
|
def extract_application_response(namespace)
|
278
277
|
ar_node = doc.at('xmlns|ApplicationResponse', xmlns: namespace)
|
279
|
-
|
280
|
-
|
281
|
-
|
278
|
+
|
279
|
+
return unless ar_node
|
280
|
+
|
281
|
+
decode(ar_node.content)
|
282
282
|
end
|
283
283
|
|
284
284
|
# Handles errors that have been passed from client
|
@@ -297,43 +297,34 @@ module Sepa
|
|
297
297
|
|
298
298
|
# Validates response code in response. "00" and "24" are currently considered valid.
|
299
299
|
def validate_response_code
|
300
|
-
|
301
|
-
|
302
|
-
|
300
|
+
return if %w(00 24).include? response_code
|
301
|
+
|
302
|
+
errors.add(:base, response_code: response_code, response_text: response_text)
|
303
303
|
end
|
304
304
|
|
305
305
|
# Validates hashes in the response. {#hashes_match?} must return true for validation to pass.
|
306
306
|
# Is not run if {#error} is present or response code is not ok.
|
307
307
|
def validate_hashes
|
308
|
-
return if @error
|
309
|
-
return unless response_code_is_ok?
|
308
|
+
return if @error || !response_code_is_ok? || hashes_match?
|
310
309
|
|
311
|
-
|
312
|
-
errors.add(:base, HASH_ERROR_MESSAGE)
|
313
|
-
end
|
310
|
+
errors.add(:base, HASH_ERROR_MESSAGE)
|
314
311
|
end
|
315
312
|
|
316
313
|
# Validate signature in the response. Validation is not run if {#error} is present or response
|
317
314
|
# is not ok.
|
318
315
|
def verify_signature
|
319
|
-
return if @error
|
320
|
-
return unless response_code_is_ok?
|
316
|
+
return if @error || !response_code_is_ok? || signature_is_valid?
|
321
317
|
|
322
|
-
|
323
|
-
errors.add(:base, SIGNATURE_ERROR_MESSAGE)
|
324
|
-
end
|
318
|
+
errors.add(:base, SIGNATURE_ERROR_MESSAGE)
|
325
319
|
end
|
326
320
|
|
327
321
|
# Validates certificate in the soap. The certificate must be present and signed by the bank's
|
328
322
|
# root certificate for the validation to pass. Is not run if {#error} is present or response
|
329
323
|
# code is not ok.
|
330
324
|
def verify_certificate
|
331
|
-
return if @error
|
332
|
-
return unless response_code_is_ok?
|
325
|
+
return if @error || !response_code_is_ok? || certificate_is_trusted?
|
333
326
|
|
334
|
-
|
335
|
-
errors.add(:base, 'The certificate in the response is not trusted')
|
336
|
-
end
|
327
|
+
errors.add(:base, 'The certificate in the response is not trusted')
|
337
328
|
end
|
338
329
|
|
339
330
|
# Checks whether response code in the response is ok. Response code is considered ok if it is
|
@@ -346,6 +337,5 @@ module Sepa
|
|
346
337
|
|
347
338
|
false
|
348
339
|
end
|
349
|
-
|
350
340
|
end
|
351
341
|
end
|
data/lib/sepa/utilities.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
module Sepa
|
2
|
-
|
3
2
|
# Contains utility methods that are used in this gem.
|
4
3
|
module Utilities
|
5
|
-
|
6
4
|
# Calculates a SHA1 digest for a given node. Before the calculation, the node is canonicalized
|
7
5
|
# exclusively.
|
8
6
|
#
|
@@ -11,7 +9,7 @@ module Sepa
|
|
11
9
|
def calculate_digest(node)
|
12
10
|
sha1 = OpenSSL::Digest::SHA1.new
|
13
11
|
|
14
|
-
canon_node = canonicalize_exclusively
|
12
|
+
canon_node = canonicalize_exclusively(node)
|
15
13
|
|
16
14
|
encode(sha1.digest(canon_node)).gsub(/\s+/, "")
|
17
15
|
end
|
@@ -189,9 +187,7 @@ module Sepa
|
|
189
187
|
# @param value [Nokogiri::XML::Node, #canonicalize] the node to be canonicalized
|
190
188
|
# @return [String] the canonicalized node
|
191
189
|
def canonicalize_exclusively(value)
|
192
|
-
value.canonicalize(
|
193
|
-
inclusive_namespaces = nil,
|
194
|
-
with_comments = false)
|
190
|
+
value.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
|
195
191
|
end
|
196
192
|
|
197
193
|
# Creates a new OpenSSL X509 certificate from a string
|
data/lib/sepa/version.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
2
2
|
<!-- edited with XMLSpy v2009 sp1 (http://www.altova.com) by Danske Bank (Danske Bank A/S) -->
|
3
3
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:tns="http://danskebank.dk/PKI/PKIFactoryService/elements" xmlns:xml="http://www.w3.org/XML/1998/namespace" targetNamespace="http://danskebank.dk/PKI/PKIFactoryService/elements" elementFormDefault="qualified" attributeFormDefault="unqualified">
|
4
|
-
<xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="
|
4
|
+
<xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsig-core-schema.xsd"/>
|
5
5
|
<!--xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="store:///schemas/xmldsig-core-schema.xsd"/-->
|
6
6
|
<xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml_id.xsd"/>
|
7
7
|
<!-- SHARED TYPES SECTION -->
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<tns:RenewCertificateRequest xmlns:pkif="http://danskebank.dk/PKI/PKIFactoryService"
|
2
|
+
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
|
3
|
+
xmlns:xe="http://www.w3.org/2001/04/xmlenc#"
|
4
|
+
xmlns:xd="http://www.w3.org/2000/09/xmldsig#"
|
5
|
+
xmlns:tns="http://danskebank.dk/PKI/PKIFactoryService/elements">
|
6
|
+
<tns:CustomerId/>
|
7
|
+
<tns:KeyGeneratorType>software</tns:KeyGeneratorType>
|
8
|
+
<tns:EncryptionCertPKCS10/>
|
9
|
+
<tns:SigningCertPKCS10/>
|
10
|
+
<tns:Timestamp/>
|
11
|
+
<tns:RequestId/>
|
12
|
+
<tns:Environment/>
|
13
|
+
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
|
14
|
+
<SignedInfo>
|
15
|
+
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
|
16
|
+
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
|
17
|
+
<Reference URI="">
|
18
|
+
<Transforms>
|
19
|
+
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
|
20
|
+
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
|
21
|
+
</Transforms>
|
22
|
+
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
|
23
|
+
<DigestValue/>
|
24
|
+
</Reference>
|
25
|
+
</SignedInfo>
|
26
|
+
<SignatureValue/>
|
27
|
+
<KeyInfo>
|
28
|
+
<X509Data>
|
29
|
+
<X509Certificate/>
|
30
|
+
</X509Data>
|
31
|
+
</KeyInfo>
|
32
|
+
</Signature>
|
33
|
+
</tns:RenewCertificateRequest>
|