sepafm 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sepa/application_request.rb +29 -13
- data/lib/sepa/attribute_checks.rb +29 -29
- data/lib/sepa/banks/danske/danske_response.rb +49 -10
- data/lib/sepa/banks/danske/soap_danske.rb +7 -6
- data/lib/sepa/banks/nordea/nordea_response.rb +2 -4
- data/lib/sepa/client.rb +31 -11
- data/lib/sepa/error_messages.rb +2 -1
- data/lib/sepa/response.rb +18 -3
- data/lib/sepa/soap_builder.rb +52 -21
- data/lib/sepa/utilities.rb +4 -0
- data/lib/sepa/version.rb +1 -1
- data/lib/sepa/wsdl/wsdl_danske.xml +1 -1
- 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/upload_file.xml +0 -1
- data/lib/sepa/xml_templates/soap/download_file_list.xml +1 -1
- data/lib/sepa/xml_templates/soap/header.xml +6 -5
- data/lib/sepafm.rb +1 -0
- data/readme.md +3 -5
- data/sepafm.gemspec +5 -5
- data/test/sepa/banks/danske/danske_cert_response_test.rb +6 -6
- data/test/sepa/banks/danske/danske_cert_soap_builder_test.rb +16 -17
- data/test/sepa/banks/danske/danske_certificate_application_request_test.rb +16 -0
- data/test/sepa/banks/danske/danske_generic_soap_builder_test.rb +39 -43
- data/test/sepa/banks/nordea/nordea_application_request_test.rb +38 -18
- data/test/sepa/banks/nordea/nordea_cert_application_request_test.rb +12 -11
- data/test/sepa/banks/nordea/nordea_cert_request_soap_builder_test.rb +10 -10
- data/test/sepa/banks/nordea/nordea_generic_soap_builder_test.rb +14 -18
- data/test/sepa/banks/nordea/nordea_response_test.rb +1 -1
- data/test/sepa/client_test.rb +38 -25
- data/test/sepa/fixtures.rb +52 -22
- data/test/sepa/sepa_test.rb +1 -1
- metadata +27 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef6bfed9365908016a49c134f04b31270f2cd7c0
|
4
|
+
data.tar.gz: fad409e18066c845c6cc8c267d1d6f328c365f6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0caa72426efa99e3baf93ad1cbdeb08ae742a99001de93068d48a8405a406eb3fb07eeb5ae69aa3b582f1af7c6a53f2a1153eca7d1c5b4b68c0798a217a4c082
|
7
|
+
data.tar.gz: 05e7942b179477e1742190c6160bf6270b8770fe1ee3e78ac5be7926d2d39464dc87b3b0ea570cb03d60653d19f4cd2b2593c31001f6be94de00f9ab7e14acf0
|
@@ -58,12 +58,17 @@ module Sepa
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def set_download_file_nodes
|
61
|
-
|
61
|
+
add_target_id_after 'FileReferences'
|
62
|
+
set_node("Status", @status)
|
63
|
+
set_node("FileType", @file_type)
|
62
64
|
set_node("FileReference", @file_reference)
|
63
65
|
end
|
64
66
|
|
65
67
|
def set_get_bank_certificate_nodes
|
66
|
-
|
68
|
+
raise 'OnlyWorksWithDanske' if @bank != :danske
|
69
|
+
|
70
|
+
# Root Cert Serial Hardcoded to Danske
|
71
|
+
set_node("elem|BankRootCertificateSerialNo", '1111110002')
|
67
72
|
set_node("elem|Timestamp", iso_time)
|
68
73
|
set_node("elem|RequestId", @request_id)
|
69
74
|
end
|
@@ -71,29 +76,32 @@ module Sepa
|
|
71
76
|
def set_upload_file_nodes
|
72
77
|
set_node_b("Content", @content)
|
73
78
|
set_node("FileType", @file_type)
|
74
|
-
|
79
|
+
add_target_id_after 'Environment'
|
75
80
|
end
|
76
81
|
|
77
82
|
def set_download_file_list_nodes
|
83
|
+
add_target_id_after 'Environment'
|
78
84
|
set_node("Status", @status)
|
79
|
-
set_node("TargetId", @target_id)
|
80
85
|
set_node("FileType", @file_type)
|
81
86
|
end
|
82
87
|
|
83
88
|
def set_get_certificate_nodes
|
84
|
-
set_node("Service",
|
85
|
-
set_node("Content", format_cert_request(@
|
86
|
-
set_node("HMAC", hmac(@pin, csr_to_binary(@
|
89
|
+
set_node("Service", '')
|
90
|
+
set_node("Content", format_cert_request(@signing_csr))
|
91
|
+
set_node("HMAC", hmac(@pin, csr_to_binary(@signing_csr)))
|
87
92
|
end
|
88
93
|
|
89
94
|
def set_create_certificate_nodes
|
90
95
|
set_node("tns|CustomerId", @customer_id)
|
91
|
-
set_node("tns|KeyGeneratorType",
|
92
|
-
set_node("tns|EncryptionCertPKCS10", format_cert_request(@
|
93
|
-
set_node("tns|SigningCertPKCS10", format_cert_request(@
|
96
|
+
set_node("tns|KeyGeneratorType", 'software')
|
97
|
+
set_node("tns|EncryptionCertPKCS10", format_cert_request(@encryption_csr))
|
98
|
+
set_node("tns|SigningCertPKCS10", format_cert_request(@signing_csr))
|
94
99
|
set_node("tns|Timestamp", iso_time)
|
95
100
|
set_node("tns|RequestId", @request_id)
|
101
|
+
|
102
|
+
@environment = 'customertest' if @environment == :test
|
96
103
|
set_node("tns|Environment", @environment)
|
104
|
+
|
97
105
|
set_node("tns|PIN", @pin)
|
98
106
|
end
|
99
107
|
|
@@ -101,9 +109,9 @@ module Sepa
|
|
101
109
|
return if @command == :get_bank_certificate
|
102
110
|
return if @command == :create_certificate
|
103
111
|
|
112
|
+
set_node('Environment', @environment.to_s.upcase)
|
104
113
|
set_node("CustomerId", @customer_id)
|
105
114
|
set_node("Timestamp", iso_time)
|
106
|
-
set_node("Environment", @environment)
|
107
115
|
set_node("SoftwareId", "Sepa Transfer Library version #{VERSION}")
|
108
116
|
set_node("Command", pretty_command)
|
109
117
|
end
|
@@ -131,7 +139,7 @@ module Sepa
|
|
131
139
|
sha1 = OpenSSL::Digest::SHA1.new
|
132
140
|
dsig = 'http://www.w3.org/2000/09/xmldsig#'
|
133
141
|
node = @application_request.at_css("dsig|SignedInfo", 'dsig' => dsig)
|
134
|
-
signature = @
|
142
|
+
signature = @signing_private_key.sign(sha1, node.canonicalize)
|
135
143
|
encode signature
|
136
144
|
end
|
137
145
|
|
@@ -146,7 +154,15 @@ module Sepa
|
|
146
154
|
add_node_to_root(signature_node)
|
147
155
|
add_value_to_signature('DigestValue', digest)
|
148
156
|
add_value_to_signature('SignatureValue', calculate_signature)
|
149
|
-
add_value_to_signature('X509Certificate', format_cert(@
|
157
|
+
add_value_to_signature('X509Certificate', format_cert(@signing_certificate))
|
158
|
+
end
|
159
|
+
|
160
|
+
def add_target_id_after(node)
|
161
|
+
return unless @bank == :nordea
|
162
|
+
|
163
|
+
target_id = Nokogiri::XML::Node.new 'TargetId', @application_request
|
164
|
+
target_id.content = @target_id
|
165
|
+
@application_request.at(node).add_next_sibling target_id
|
150
166
|
end
|
151
167
|
|
152
168
|
end
|
@@ -7,7 +7,7 @@ module Sepa
|
|
7
7
|
when :nordea
|
8
8
|
[:get_certificate, :get_user_info, :download_file_list, :download_file, :upload_file]
|
9
9
|
when :danske
|
10
|
-
[:get_bank_certificate, :
|
10
|
+
[:get_bank_certificate, :download_file_list, :download_file,
|
11
11
|
:upload_file, :create_certificate]
|
12
12
|
else
|
13
13
|
[]
|
@@ -22,31 +22,31 @@ module Sepa
|
|
22
22
|
return if [:get_certificate, :get_bank_certificate, :create_certificate].include? command
|
23
23
|
|
24
24
|
begin
|
25
|
-
|
25
|
+
rsa_key signing_private_key
|
26
26
|
rescue
|
27
|
-
errors.add(:
|
27
|
+
errors.add(:signing_private_key, "Invalid signing private key")
|
28
28
|
end
|
29
29
|
|
30
30
|
begin
|
31
|
-
OpenSSL::X509::Certificate.new
|
31
|
+
OpenSSL::X509::Certificate.new signing_certificate
|
32
32
|
rescue
|
33
|
-
errors.add(:
|
33
|
+
errors.add(:signing_certificate, "Invalid signing certificate")
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
def
|
37
|
+
def check_signing_csr
|
38
38
|
return unless command == :create_certificate
|
39
39
|
|
40
|
-
unless cert_request_valid?(
|
41
|
-
errors.add(:
|
40
|
+
unless cert_request_valid?(signing_csr)
|
41
|
+
errors.add(:signing_csr, SIGNING_CERT_REQUEST_ERROR_MESSAGE)
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
45
|
def check_encryption_cert_request
|
46
46
|
return unless command == :create_certificate
|
47
47
|
|
48
|
-
unless cert_request_valid?(
|
49
|
-
errors.add(:
|
48
|
+
unless cert_request_valid?(encryption_csr)
|
49
|
+
errors.add(:encryption_csr, ENCRYPTION_CERT_REQUEST_ERROR_MESSAGE)
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -76,6 +76,9 @@ module Sepa
|
|
76
76
|
:create_certificate,
|
77
77
|
:get_bank_certificate].include? command
|
78
78
|
|
79
|
+
# Danske Bank does not use target_id
|
80
|
+
return if bank == :danske
|
81
|
+
|
79
82
|
check_presence_and_length(:target_id, 80, TARGET_ID_ERROR_MESSAGE)
|
80
83
|
end
|
81
84
|
|
@@ -97,44 +100,31 @@ module Sepa
|
|
97
100
|
check_presence_and_length(:pin, 10, PIN_ERROR_MESSAGE)
|
98
101
|
end
|
99
102
|
|
100
|
-
def check_bank_root_cert_serial
|
101
|
-
return unless command == :get_bank_certificate
|
102
|
-
|
103
|
-
unless bank_root_cert_serial && bank_root_cert_serial.length.between?(1, 64)
|
104
|
-
errors.add(:bank_root_cert_serial, "Invalid bank root certificate serial")
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
103
|
def check_environment
|
109
104
|
return if command == :get_bank_certificate
|
110
105
|
|
111
|
-
|
112
|
-
|
113
|
-
unless environments.include? environment
|
106
|
+
unless Client::ENVIRONMENTS.include? environment
|
114
107
|
errors.add(:environment, ENVIRONMENT_ERROR_MESSAGE)
|
115
108
|
end
|
116
109
|
end
|
117
110
|
|
118
111
|
def check_customer_id
|
119
|
-
return if command == :get_bank_certificate
|
120
|
-
|
121
112
|
unless customer_id && customer_id.length.between?(1, 16)
|
122
113
|
errors.add(:customer_id, CUSTOMER_ID_ERROR_MESSAGE)
|
123
114
|
end
|
124
115
|
end
|
125
116
|
|
126
|
-
def
|
127
|
-
return unless
|
117
|
+
def check_encryption_certificate
|
118
|
+
return unless bank == :danske
|
119
|
+
return if command == :get_bank_certificate
|
128
120
|
|
129
|
-
errors.add(:
|
121
|
+
errors.add(:encryption_certificate, ENCRYPTION_CERT_ERROR_MESSAGE) unless encryption_certificate
|
130
122
|
end
|
131
123
|
|
132
124
|
def check_status
|
133
125
|
return unless [:download_file_list, :download_file].include? command
|
134
126
|
|
135
|
-
|
136
|
-
|
137
|
-
unless status && statuses.include?(status)
|
127
|
+
unless status && Client::STATUSES.include?(status)
|
138
128
|
errors.add :status, STATUS_ERROR_MESSAGE
|
139
129
|
end
|
140
130
|
end
|
@@ -147,5 +137,15 @@ module Sepa
|
|
147
137
|
end
|
148
138
|
end
|
149
139
|
|
140
|
+
def check_encryption_private_key
|
141
|
+
return unless bank == :danske
|
142
|
+
return if [:create_certificate, :get_bank_certificate].include? command
|
143
|
+
|
144
|
+
rsa_key encryption_private_key
|
145
|
+
|
146
|
+
rescue
|
147
|
+
errors.add :encryption_private_key, ENCRYPTION_PRIVATE_KEY_ERROR_MESSAGE
|
148
|
+
end
|
149
|
+
|
150
150
|
end
|
151
151
|
end
|
@@ -1,27 +1,43 @@
|
|
1
1
|
module Sepa
|
2
2
|
class DanskeResponse < Response
|
3
3
|
|
4
|
-
def
|
5
|
-
@
|
4
|
+
def application_response
|
5
|
+
@application_response ||= decrypt_application_response
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
9
|
-
|
8
|
+
def bank_encryption_certificate
|
9
|
+
return unless @command == :get_bank_certificate
|
10
|
+
|
11
|
+
@bank_encryption_certificate ||= extract_cert(doc, 'BankEncryptionCert', DANSKE_PKI)
|
10
12
|
end
|
11
13
|
|
12
|
-
def
|
13
|
-
|
14
|
+
def bank_signing_certificate
|
15
|
+
return unless @command == :get_bank_certificate
|
16
|
+
|
17
|
+
@bank_signing_certificate ||= extract_cert(doc, 'BankSigningCert', DANSKE_PKI)
|
14
18
|
end
|
15
19
|
|
16
|
-
def
|
17
|
-
|
20
|
+
def bank_root_certificate
|
21
|
+
return unless @command == :get_bank_certificate
|
22
|
+
|
23
|
+
@bank_root_certificate ||= extract_cert(doc, 'BankRootCert', DANSKE_PKI)
|
18
24
|
end
|
19
25
|
|
20
|
-
def
|
21
|
-
|
26
|
+
def own_encryption_certificate
|
27
|
+
return unless @command == :create_certificate
|
28
|
+
|
29
|
+
@own_encryption_certificate ||= extract_cert(doc, 'EncryptionCert', DANSKE_PKI)
|
30
|
+
end
|
31
|
+
|
32
|
+
def own_signing_certificate
|
33
|
+
return unless @command == :create_certificate
|
34
|
+
|
35
|
+
@own_signing_certificate ||= extract_cert(doc, 'SigningCert', DANSKE_PKI)
|
22
36
|
end
|
23
37
|
|
24
38
|
def ca_certificate
|
39
|
+
return unless @command == :create_certificate
|
40
|
+
|
25
41
|
@ca_certificate ||= extract_cert(doc, 'CACert', DANSKE_PKI)
|
26
42
|
end
|
27
43
|
|
@@ -41,5 +57,28 @@ module Sepa
|
|
41
57
|
node
|
42
58
|
end
|
43
59
|
|
60
|
+
def decrypt_application_response
|
61
|
+
encrypted_application_response = extract_application_response(BXD)
|
62
|
+
encrypted_application_response = xml_doc encrypted_application_response
|
63
|
+
enc_key = encrypted_application_response.css('CipherValue', 'xmlns' => XMLENC)[0].content
|
64
|
+
enc_key = decode enc_key
|
65
|
+
key = @encryption_private_key.private_decrypt(enc_key)
|
66
|
+
|
67
|
+
encypted_data = encrypted_application_response
|
68
|
+
.css('CipherValue', 'xmlns' => XMLENC)[1]
|
69
|
+
.content
|
70
|
+
|
71
|
+
encypted_data = decode encypted_data
|
72
|
+
iv = encypted_data[0, 8]
|
73
|
+
encypted_data = encypted_data[8, encypted_data.length]
|
74
|
+
|
75
|
+
decipher = OpenSSL::Cipher.new('DES-EDE3-CBC')
|
76
|
+
decipher.decrypt
|
77
|
+
decipher.key = key
|
78
|
+
decipher.iv = iv
|
79
|
+
|
80
|
+
decipher.update(encypted_data) + decipher.final
|
81
|
+
end
|
82
|
+
|
44
83
|
end
|
45
84
|
end
|
@@ -15,12 +15,12 @@ module Sepa
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def encrypt_application_request
|
18
|
-
|
19
|
-
encryption_public_key =
|
20
|
-
|
21
|
-
|
18
|
+
encryption_certificate = OpenSSL::X509::Certificate.new(@encryption_certificate)
|
19
|
+
encryption_public_key = encryption_certificate.public_key
|
20
|
+
encryption_certificate = format_cert(encryption_certificate)
|
21
|
+
encrypted_application_request, key = encrypt_ar
|
22
22
|
encrypted_key = encrypt_key(key, encryption_public_key)
|
23
|
-
build_encrypted_ar(
|
23
|
+
build_encrypted_ar(encryption_certificate, encrypted_key, encrypted_application_request)
|
24
24
|
end
|
25
25
|
|
26
26
|
# Encrypts a given symmetric encryption key with a public key and returns it in base64 encoded
|
@@ -60,7 +60,7 @@ module Sepa
|
|
60
60
|
set_node(@template, 'bxd|Timestamp', iso_time)
|
61
61
|
set_node(@template, 'bxd|Language', @language)
|
62
62
|
set_node(@template, 'bxd|UserAgent', "Sepa Transfer Library version " + VERSION)
|
63
|
-
set_node(@template, 'bxd|ReceiverId',
|
63
|
+
set_node(@template, 'bxd|ReceiverId', "DABAFIHH")
|
64
64
|
end
|
65
65
|
|
66
66
|
def set_create_cert_contents
|
@@ -90,6 +90,7 @@ module Sepa
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def build_certificate_request
|
93
|
+
@environment = :customertest if @environment == :test
|
93
94
|
set_create_cert_contents
|
94
95
|
encrypted_request = encrypt_application_request
|
95
96
|
add_encrypted_request_to_soap(encrypted_request)
|
@@ -2,7 +2,7 @@ module Sepa
|
|
2
2
|
class NordeaResponse < Response
|
3
3
|
include Utilities
|
4
4
|
|
5
|
-
def
|
5
|
+
def own_signing_certificate
|
6
6
|
application_response = extract_application_response(NORDEA_PKI)
|
7
7
|
at = 'xmlns|Certificate > xmlns|Certificate'
|
8
8
|
node = Nokogiri::XML(application_response).at(at, xmlns: NORDEA_XML_DATA)
|
@@ -11,9 +11,7 @@ module Sepa
|
|
11
11
|
|
12
12
|
cert_value = process_cert_value node.content
|
13
13
|
cert = x509_certificate cert_value
|
14
|
-
|
15
|
-
|
16
|
-
encode cert_plain
|
14
|
+
cert.to_s
|
17
15
|
end
|
18
16
|
|
19
17
|
end
|
data/lib/sepa/client.rb
CHANGED
@@ -5,13 +5,28 @@ module Sepa
|
|
5
5
|
include ErrorMessages
|
6
6
|
include AttributeChecks
|
7
7
|
|
8
|
-
attr_accessor :bank,
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
8
|
+
attr_accessor :bank,
|
9
|
+
:command,
|
10
|
+
:content,
|
11
|
+
:customer_id,
|
12
|
+
:target_id,
|
13
|
+
:environment,
|
14
|
+
:file_reference,
|
15
|
+
:file_type,
|
16
|
+
:language,
|
17
|
+
:status,
|
18
|
+
:pin,
|
19
|
+
:signing_private_key,
|
20
|
+
:signing_certificate,
|
21
|
+
:signing_csr,
|
22
|
+
:encryption_private_key,
|
23
|
+
:encryption_certificate,
|
24
|
+
:encryption_csr
|
12
25
|
|
13
26
|
BANKS = [:nordea, :danske]
|
14
27
|
LANGUAGES = ['FI', 'SE', 'EN']
|
28
|
+
ENVIRONMENTS = [:production, :test]
|
29
|
+
STATUSES = ['NEW', 'DOWNLOADED', 'ALL']
|
15
30
|
|
16
31
|
validates :bank, inclusion: { in: BANKS }
|
17
32
|
validates :language, inclusion: { in: LANGUAGES }, allow_nil: true
|
@@ -26,15 +41,15 @@ module Sepa
|
|
26
41
|
validate :check_command
|
27
42
|
validate :check_wsdl
|
28
43
|
validate :check_keys
|
29
|
-
validate :
|
44
|
+
validate :check_encryption_certificate
|
30
45
|
validate :check_encryption_cert_request
|
31
|
-
validate :
|
32
|
-
validate :check_bank_root_cert_serial
|
46
|
+
validate :check_signing_csr
|
33
47
|
validate :check_file_reference
|
48
|
+
validate :check_encryption_private_key
|
34
49
|
|
35
50
|
def initialize(hash = {})
|
36
51
|
self.attributes hash
|
37
|
-
self.environment ||=
|
52
|
+
self.environment ||= :production
|
38
53
|
self.language ||= 'EN'
|
39
54
|
self.status ||= 'NEW'
|
40
55
|
end
|
@@ -47,6 +62,10 @@ module Sepa
|
|
47
62
|
@command = value.to_sym
|
48
63
|
end
|
49
64
|
|
65
|
+
def environment=(value)
|
66
|
+
@environment = value.downcase.to_sym
|
67
|
+
end
|
68
|
+
|
50
69
|
def attributes(hash)
|
51
70
|
hash.each do |name, value|
|
52
71
|
send("#{name}=", value)
|
@@ -72,6 +91,7 @@ module Sepa
|
|
72
91
|
error: error,
|
73
92
|
command: command
|
74
93
|
}
|
94
|
+
options[:encryption_private_key] = rsa_key(encryption_private_key) if encryption_private_key
|
75
95
|
|
76
96
|
case bank
|
77
97
|
when :nordea
|
@@ -84,7 +104,7 @@ module Sepa
|
|
84
104
|
private
|
85
105
|
|
86
106
|
def create_hash
|
87
|
-
|
107
|
+
initialize_signing_private_key
|
88
108
|
iv = {}
|
89
109
|
|
90
110
|
# Create hash of all instance variables
|
@@ -98,8 +118,8 @@ module Sepa
|
|
98
118
|
iv
|
99
119
|
end
|
100
120
|
|
101
|
-
def
|
102
|
-
@
|
121
|
+
def initialize_signing_private_key
|
122
|
+
@signing_private_key = rsa_key(@signing_private_key) if @signing_private_key
|
103
123
|
end
|
104
124
|
|
105
125
|
# Returns path to WSDL file
|
data/lib/sepa/error_messages.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Sepa
|
2
2
|
module ErrorMessages
|
3
3
|
CUSTOMER_ID_ERROR_MESSAGE = 'Customer Id needs to be present and needs to have a length of less than 17 characters'
|
4
|
-
ENVIRONMENT_ERROR_MESSAGE = 'Environment needs to be either
|
4
|
+
ENVIRONMENT_ERROR_MESSAGE = 'Environment needs to be either production or test'
|
5
5
|
TARGET_ID_ERROR_MESSAGE = 'Target Id needs to be present and under 80 characters'
|
6
6
|
FILE_TYPE_ERROR_MESSAGE = 'File type needs to be present and under 35 characters'
|
7
7
|
CONTENT_ERROR_MESSAGE = 'Content needs to be present for this command'
|
@@ -11,5 +11,6 @@ module Sepa
|
|
11
11
|
ENCRYPTION_CERT_ERROR_MESSAGE = 'Invalid encryption certificate'
|
12
12
|
STATUS_ERROR_MESSAGE = 'Status is required for this command and must be either NEW, DOWNLOADED or ALL'
|
13
13
|
FILE_REFERENCE_ERROR_MESSAGE = 'File reference is required for this command and must be under 33 characters'
|
14
|
+
ENCRYPTION_PRIVATE_KEY_ERROR_MESSAGE = 'Encryption private key is needed for this bank and this command'
|
14
15
|
end
|
15
16
|
end
|
data/lib/sepa/response.rb
CHANGED
@@ -6,14 +6,15 @@ module Sepa
|
|
6
6
|
attr_reader :soap, :error, :command
|
7
7
|
|
8
8
|
validates :soap, presence: true
|
9
|
-
validate
|
10
|
-
validate
|
11
|
-
validate
|
9
|
+
validate :validate_document_format
|
10
|
+
validate :document_must_validate_against_schema
|
11
|
+
validate :client_errors
|
12
12
|
|
13
13
|
def initialize(hash = {})
|
14
14
|
@soap = hash[:response]
|
15
15
|
@command = hash[:command]
|
16
16
|
@error = hash[:error]
|
17
|
+
@encryption_private_key = hash[:encryption_private_key]
|
17
18
|
end
|
18
19
|
|
19
20
|
def doc
|
@@ -108,6 +109,18 @@ module Sepa
|
|
108
109
|
@soap
|
109
110
|
end
|
110
111
|
|
112
|
+
def bank_encryption_certificate; end
|
113
|
+
|
114
|
+
def bank_signing_certificate; end
|
115
|
+
|
116
|
+
def bank_root_certificate; end
|
117
|
+
|
118
|
+
def own_encryption_certificate; end
|
119
|
+
|
120
|
+
def own_signing_certificate; end
|
121
|
+
|
122
|
+
def ca_certificate; end
|
123
|
+
|
111
124
|
private
|
112
125
|
|
113
126
|
# Finds all reference nodes with digest values in the document and returns
|
@@ -148,6 +161,8 @@ module Sepa
|
|
148
161
|
end
|
149
162
|
|
150
163
|
def document_must_validate_against_schema
|
164
|
+
return if command.to_sym == :get_bank_certificate
|
165
|
+
|
151
166
|
check_validity_against_schema(doc, 'soap.xsd')
|
152
167
|
end
|
153
168
|
|
data/lib/sepa/soap_builder.rb
CHANGED
@@ -6,23 +6,23 @@ module Sepa
|
|
6
6
|
|
7
7
|
# SoapBuilder creates the SOAP structure.
|
8
8
|
def initialize(params)
|
9
|
-
@bank
|
10
|
-
@
|
11
|
-
@command
|
12
|
-
@content
|
13
|
-
@customer_id
|
14
|
-
@
|
15
|
-
@environment
|
16
|
-
@file_reference
|
17
|
-
@file_type
|
18
|
-
@language
|
19
|
-
@
|
20
|
-
@status
|
21
|
-
@target_id
|
22
|
-
|
23
|
-
@application_request
|
24
|
-
@header_template
|
25
|
-
@template
|
9
|
+
@bank = params[:bank]
|
10
|
+
@signing_certificate = params[:signing_certificate]
|
11
|
+
@command = params[:command]
|
12
|
+
@content = params[:content]
|
13
|
+
@customer_id = params[:customer_id]
|
14
|
+
@encryption_certificate = params[:encryption_certificate]
|
15
|
+
@environment = params[:environment]
|
16
|
+
@file_reference = params[:file_reference]
|
17
|
+
@file_type = params[:file_type]
|
18
|
+
@language = params[:language]
|
19
|
+
@signing_private_key = params[:signing_private_key]
|
20
|
+
@status = params[:status]
|
21
|
+
@target_id = params[:target_id]
|
22
|
+
|
23
|
+
@application_request = ApplicationRequest.new params
|
24
|
+
@header_template = load_header_template
|
25
|
+
@template = load_body_template SOAP_TEMPLATE_PATH
|
26
26
|
|
27
27
|
find_correct_bank_extension
|
28
28
|
end
|
@@ -64,7 +64,7 @@ module Sepa
|
|
64
64
|
inclusive_namespaces = nil, with_comments = false
|
65
65
|
)
|
66
66
|
|
67
|
-
signature = @
|
67
|
+
signature = @signing_private_key.sign(sha1, canon_signed_info_node)
|
68
68
|
encode(signature).gsub(/\s+/, "")
|
69
69
|
end
|
70
70
|
|
@@ -84,23 +84,54 @@ module Sepa
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def process_header
|
87
|
+
set_token_id
|
88
|
+
|
87
89
|
set_node(@header_template, 'wsu|Created', iso_time)
|
88
90
|
set_node(@header_template, 'wsu|Expires', (Time.now.utc + 300).iso8601)
|
89
91
|
|
92
|
+
timestamp_id = set_timestamp_id
|
93
|
+
|
90
94
|
timestamp_digest = calculate_digest(@header_template, 'wsu|Timestamp')
|
91
|
-
dsig =
|
95
|
+
dsig = "dsig|Reference[URI='##{timestamp_id}'] dsig|DigestValue"
|
92
96
|
set_node(@header_template, dsig, timestamp_digest)
|
93
97
|
|
98
|
+
body_id = set_body_id
|
99
|
+
|
94
100
|
body_digest = calculate_digest(@template, 'env|Body')
|
95
|
-
dsig =
|
101
|
+
dsig = "dsig|Reference[URI='##{body_id}'] dsig|DigestValue"
|
96
102
|
set_node(@header_template, dsig, body_digest)
|
97
103
|
|
98
104
|
signature = calculate_signature(@header_template, 'dsig|SignedInfo')
|
99
105
|
set_node(@header_template, 'dsig|SignatureValue', signature)
|
100
106
|
|
101
|
-
formatted_cert = format_cert(@
|
107
|
+
formatted_cert = format_cert(@signing_certificate)
|
102
108
|
set_node(@header_template, 'wsse|BinarySecurityToken', formatted_cert)
|
103
109
|
end
|
104
110
|
|
111
|
+
def set_token_id
|
112
|
+
security_token_id = "token-#{SecureRandom.uuid}"
|
113
|
+
|
114
|
+
@header_template.at('wsse|BinarySecurityToken')['wsu:Id'] = security_token_id
|
115
|
+
@header_template.at('wsse|Reference')['URI'] = "##{security_token_id}"
|
116
|
+
end
|
117
|
+
|
118
|
+
def set_timestamp_id
|
119
|
+
timestamp_id = "timestamp-#{SecureRandom.uuid}"
|
120
|
+
|
121
|
+
@header_template.at('wsu|Timestamp')['wsu:Id'] = timestamp_id
|
122
|
+
@header_template.css('dsig|Reference')[0]['URI'] = "##{timestamp_id}"
|
123
|
+
|
124
|
+
timestamp_id
|
125
|
+
end
|
126
|
+
|
127
|
+
def set_body_id
|
128
|
+
body_id = "body-#{SecureRandom.uuid}"
|
129
|
+
|
130
|
+
@template.at('env|Body')['wsu:Id'] = body_id
|
131
|
+
@header_template.css('dsig|Reference')[1]['URI'] = "##{body_id}"
|
132
|
+
|
133
|
+
body_id
|
134
|
+
end
|
135
|
+
|
105
136
|
end
|
106
137
|
end
|
data/lib/sepa/utilities.rb
CHANGED
data/lib/sepa/version.rb
CHANGED
@@ -228,7 +228,7 @@
|
|
228
228
|
</wsdl:binding>
|
229
229
|
<wsdl:service name="CorporateFileService">
|
230
230
|
<wsdl:port binding="tns:CorporateFileServiceHttpBinding" name="CorporateFileServiceHttpPort">
|
231
|
-
<wsdlsoap:address location="https://
|
231
|
+
<wsdlsoap:address location="https://businessws.sampopankki.fi/edifileservice/edifileservice.asmx"/>
|
232
232
|
</wsdl:port>
|
233
233
|
</wsdl:service>
|
234
234
|
</wsdl:definitions>
|