sepafm 0.1.2 → 0.1.3
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/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>
|