epics 2.9.0 → 2.10.0
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/CHANGELOG.md +5 -0
- data/README.md +73 -3
- data/lib/epics/client.rb +34 -9
- data/lib/epics/generic_request.rb +14 -0
- data/lib/epics/hia.rb +2 -0
- data/lib/epics/ini.rb +1 -0
- data/lib/epics/letter_renderer.rb +23 -3
- data/lib/epics/version.rb +1 -1
- data/lib/epics/x_509_certificate.rb +15 -0
- data/lib/epics/z01.rb +17 -0
- data/lib/epics.rb +2 -0
- data/lib/letter/ini_with_certs.erb +335 -0
- data/lib/letter/locales/de.yml +1 -0
- data/lib/letter/locales/en.yml +1 -0
- data/lib/letter/locales/fr.yml +1 -0
- data/spec/client_spec.rb +150 -58
- data/spec/orders/hia_spec.rb +31 -7
- data/spec/orders/ini_spec.rb +27 -8
- data/spec/orders/x_509_certificate_spec.rb +26 -0
- data/spec/orders/z01_spec.rb +11 -0
- data/spec/support/x_509_crt_generator.rb +22 -0
- metadata +12 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 33e735bd9012ec4df1bc24d5f1621345adfa6aeba90dbf5c3adcc9be9673c696
|
4
|
+
data.tar.gz: f8c5b93115aeb9b60d3be9cbcd36251b6046f5093ed92482c2b4b1d8d4555e90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6021ed35c892dc544032a95e89ef5a8361f27ea022a5a2776dfea3adea1e7ebbbb2642e145a0c4efb01157c228953c171a511747d21087e520a1b59411f82f81
|
7
|
+
data.tar.gz: 71ef90f98028d9e4bff31aa077d52fdbd7cadc12e8126792f7e71bb6e00b4b409a1ad9e36b54e2e345115e602734a7ddaaa26f3b214e54503055929a5600f114
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -41,7 +41,7 @@ Once the paperwork is done, your bank should provide you with:
|
|
41
41
|
Take these parameters and start setting up an UserID (repeat this for every user you want to initialize):
|
42
42
|
|
43
43
|
```ruby
|
44
|
-
e = Epics::Client.setup("my-super-secret", "https://ebics.sandbox", "EBICS_HOST_ID", "EBICS_USER_ID", "EBICS_PARTNER_ID")
|
44
|
+
e = Epics::Client.setup("my-super-secret", "https://ebics.sandbox", "EBICS_HOST_ID", "EBICS_USER_ID", "EBICS_PARTNER_ID", 4096)
|
45
45
|
```
|
46
46
|
|
47
47
|
To use the keys later, just store them in a file
|
@@ -200,6 +200,76 @@ that are hiding some strange names from you:
|
|
200
200
|
If you need more sophisticated EBICS order types, please read the next section
|
201
201
|
about the supported functionalities.
|
202
202
|
|
203
|
+
### Using X.509 Certificates
|
204
|
+
|
205
|
+
Epics supports using X.509 self-signed certificates for INI and HIA requests, as required by some banks. This is in addition to the classic key-based workflow.
|
206
|
+
|
207
|
+
#### When to Use
|
208
|
+
|
209
|
+
Some banks require X.509 certificates for EBICS initialization (INI/HIA).
|
210
|
+
|
211
|
+
You can generate your own X.509 certificate using Ruby’s OpenSSL library:
|
212
|
+
|
213
|
+
This examples showcases the generation of the X.509 certificate A file and can be applied the same way for the others.
|
214
|
+
```ruby
|
215
|
+
key = client.a.key # or e key, or x key
|
216
|
+
name = OpenSSL::X509::Name.parse('/CN=Test Certificate/O=MyOrg/C=DE')
|
217
|
+
cert = OpenSSL::X509::Certificate.new
|
218
|
+
cert.version = 2
|
219
|
+
cert.serial = SecureRandom.random_number(2**64)
|
220
|
+
cert.subject = name
|
221
|
+
cert.issuer = name
|
222
|
+
cert.public_key = key.public_key
|
223
|
+
cert.not_before = Time.current
|
224
|
+
cert.not_after = cert.not_before + 1.year
|
225
|
+
|
226
|
+
ef = OpenSSL::X509::ExtensionFactory.new
|
227
|
+
ef.subject_certificate = cert
|
228
|
+
ef.issuer_certificate = cert
|
229
|
+
cert.add_extension(ef.create_extension('basicConstraints', 'CA:FALSE', true))
|
230
|
+
cert.add_extension(ef.create_extension('keyUsage', 'digitalSignature,nonRepudiation,keyEncipherment', true))
|
231
|
+
|
232
|
+
cert.sign(key, OpenSSL::Digest.new('SHA256'))
|
233
|
+
cert
|
234
|
+
|
235
|
+
# Save to file
|
236
|
+
File.write("cert_a.pem", cert.to_pem)
|
237
|
+
```
|
238
|
+
You can now use the contents of the generated certificate file in PEM format as your
|
239
|
+
`x_509_certificate_a_content`, `x_509_certificate_x_content`, or `x_509_certificate_e_content`
|
240
|
+
in the client initialization.
|
241
|
+
|
242
|
+
**Note:** For production environments, your bank may require certificates issued by a trusted authority. Be sure to confirm your bank’s requirements before proceeding.
|
243
|
+
|
244
|
+
#### Initializing the Client with X.509 Certificates
|
245
|
+
```ruby
|
246
|
+
# Load your certificate data (PEM or DER encoded)
|
247
|
+
certificate_a = File.read("cert_a.pem")
|
248
|
+
certificate_x = File.read("cert_x.pem")
|
249
|
+
certificate_e = File.read("cert_e.pem")
|
250
|
+
|
251
|
+
client = Epics::Client.new(
|
252
|
+
keys, # your key data as before
|
253
|
+
'passphrase',
|
254
|
+
'url',
|
255
|
+
'host',
|
256
|
+
'user',
|
257
|
+
'partner',
|
258
|
+
x_509_certificate_a_content: certificate_a,
|
259
|
+
x_509_certificate_x_content: certificate_x,
|
260
|
+
x_509_certificate_e_content: certificate_e,
|
261
|
+
debug_mode: true # Optional: enables verbose logging of EBICS requests/responses
|
262
|
+
)
|
263
|
+
```
|
264
|
+
### Example: Generating the Initialization Letter with Certificates
|
265
|
+
|
266
|
+
```ruby
|
267
|
+
renderer = Epics::LetterRenderer.new(client)
|
268
|
+
letter = renderer.render("Your Bank Name")
|
269
|
+
File.write("initialization_letter.txt", letter)
|
270
|
+
```
|
271
|
+
If all three certificates are present, the INI letter will use certificate hashes as required for certificate-based registration.
|
272
|
+
|
203
273
|
## Issues and Feature Requests
|
204
274
|
|
205
275
|
[Railslove](http://railslove.com) is commited to provide the best developer tools for integrating
|
@@ -258,8 +328,8 @@ EPICS_VERIFY_SSL=false
|
|
258
328
|
## Contributing
|
259
329
|
Railslove has a [Contributor License Agreement (CLA)](https://github.com/railslove/epics/blob/master/CONTRIBUTING.md) which clarifies the intellectual property rights for contributions from individuals or entities. To ensure every developer has signed the CLA, we use [CLA Assistant](https://cla-assistant.io/).
|
260
330
|
|
261
|
-
After checking out the repo, run `bin/setup` to install dependencies.
|
262
|
-
Then, run `rspec` to run the tests.
|
331
|
+
After checking out the repo, run `bin/setup` to install dependencies.
|
332
|
+
Then, run `rspec` to run the tests.
|
263
333
|
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
264
334
|
|
265
335
|
0. Contact team@railslove.com for information about the CLA
|
data/lib/epics/client.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
class Epics::Client
|
2
2
|
extend Forwardable
|
3
3
|
|
4
|
-
attr_accessor :passphrase, :url, :host_id, :user_id, :partner_id, :keys, :keys_content, :locale, :product_name
|
5
|
-
|
4
|
+
attr_accessor :passphrase, :url, :host_id, :user_id, :partner_id, :keys, :keys_content, :locale, :product_name,
|
5
|
+
:x_509_certificates_content, :debug_mode
|
6
6
|
|
7
|
+
attr_writer :iban, :bic, :name
|
8
|
+
|
7
9
|
def_delegators :connection, :post
|
8
|
-
|
9
|
-
def initialize(keys_content, passphrase, url, host_id, user_id, partner_id,
|
10
|
+
|
11
|
+
def initialize(keys_content, passphrase, url, host_id, user_id, partner_id, options = {})
|
10
12
|
self.keys_content = keys_content.respond_to?(:read) ? keys_content.read : keys_content if keys_content
|
11
13
|
self.passphrase = passphrase
|
12
14
|
self.keys = extract_keys if keys_content
|
@@ -14,8 +16,14 @@ class Epics::Client
|
|
14
16
|
self.host_id = host_id
|
15
17
|
self.user_id = user_id
|
16
18
|
self.partner_id = partner_id
|
17
|
-
self.locale = locale
|
18
|
-
self.product_name = product_name
|
19
|
+
self.locale = options[:locale] || Epics::DEFAULT_LOCALE
|
20
|
+
self.product_name = options[:product_name] || Epics::DEFAULT_PRODUCT_NAME
|
21
|
+
self.debug_mode = !!options[:debug_mode]
|
22
|
+
self.x_509_certificates_content = {
|
23
|
+
a: options[:x_509_certificate_a_content],
|
24
|
+
x: options[:x_509_certificate_x_content],
|
25
|
+
e: options[:x_509_certificate_e_content]
|
26
|
+
}
|
19
27
|
end
|
20
28
|
|
21
29
|
def inspect
|
@@ -61,8 +69,8 @@ class Epics::Client
|
|
61
69
|
@order_types ||= (self.HTD; @order_types)
|
62
70
|
end
|
63
71
|
|
64
|
-
def self.setup(passphrase, url, host_id, user_id, partner_id, keysize = 2048)
|
65
|
-
client = new(nil, passphrase, url, host_id, user_id, partner_id)
|
72
|
+
def self.setup(passphrase, url, host_id, user_id, partner_id, keysize = 2048, options = {})
|
73
|
+
client = new(nil, passphrase, url, host_id, user_id, partner_id, options)
|
66
74
|
client.keys = %w(A006 X002 E002).each_with_object({}) do |type, memo|
|
67
75
|
memo[type] = Epics::Key.new( OpenSSL::PKey::RSA.generate(keysize) )
|
68
76
|
end
|
@@ -225,6 +233,10 @@ class Epics::Client
|
|
225
233
|
download_and_unzip(Epics::C5N, from: from, to: to)
|
226
234
|
end
|
227
235
|
|
236
|
+
def Z01(from, to)
|
237
|
+
download_and_unzip(Epics::Z01, from: from, to: to)
|
238
|
+
end
|
239
|
+
|
228
240
|
def Z52(from, to)
|
229
241
|
download_and_unzip(Epics::Z52, from: from, to: to)
|
230
242
|
end
|
@@ -273,6 +285,19 @@ class Epics::Client
|
|
273
285
|
def save_keys(path)
|
274
286
|
File.write(path, dump_keys)
|
275
287
|
end
|
288
|
+
|
289
|
+
def x_509_certificate(type)
|
290
|
+
content = x_509_certificates_content[type.to_sym]
|
291
|
+
return if content.nil? || content.empty?
|
292
|
+
Epics::X509Certificate.new(content)
|
293
|
+
end
|
294
|
+
|
295
|
+
def x_509_certificate_hash(type)
|
296
|
+
content = x_509_certificates_content[type.to_sym]
|
297
|
+
return if content.nil? || content.empty?
|
298
|
+
cert = OpenSSL::X509::Certificate.new(content)
|
299
|
+
Digest::SHA256.hexdigest(cert.to_der).upcase
|
300
|
+
end
|
276
301
|
|
277
302
|
private
|
278
303
|
|
@@ -313,7 +338,7 @@ class Epics::Client
|
|
313
338
|
faraday.use Epics::XMLSIG, { client: self }
|
314
339
|
faraday.use Epics::ParseEbics, { client: self}
|
315
340
|
# faraday.use MyAdapter
|
316
|
-
|
341
|
+
faraday.response :logger, ::Logger.new(STDOUT), bodies: true if debug_mode # log requests/response to STDOUT
|
317
342
|
end
|
318
343
|
end
|
319
344
|
|
@@ -105,4 +105,18 @@ class Epics::GenericRequest
|
|
105
105
|
}
|
106
106
|
end.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML, encoding: 'utf-8')
|
107
107
|
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def x509_data_xml(xml, x_509_certificate)
|
112
|
+
return unless x_509_certificate
|
113
|
+
|
114
|
+
xml.send('ds:X509Data') do
|
115
|
+
xml.send('ds:X509IssuerSerial') do
|
116
|
+
xml.send('ds:X509IssuerName', x_509_certificate.issuer)
|
117
|
+
xml.send('ds:X509SerialNumber', x_509_certificate.version)
|
118
|
+
end
|
119
|
+
xml.send('ds:X509Certificate', x_509_certificate.data)
|
120
|
+
end
|
121
|
+
end
|
108
122
|
end
|
data/lib/epics/hia.rb
CHANGED
@@ -26,6 +26,7 @@ class Epics::HIA < Epics::GenericRequest
|
|
26
26
|
Nokogiri::XML::Builder.new do |xml|
|
27
27
|
xml.HIARequestOrderData('xmlns:ds' => 'http://www.w3.org/2000/09/xmldsig#', 'xmlns' => 'urn:org:ebics:H004') {
|
28
28
|
xml.AuthenticationPubKeyInfo {
|
29
|
+
x509_data_xml(xml, client.x_509_certificate(:x))
|
29
30
|
xml.PubKeyValue {
|
30
31
|
xml.send('ds:RSAKeyValue') {
|
31
32
|
xml.send('ds:Modulus', Base64.strict_encode64([client.x.n].pack("H*")))
|
@@ -35,6 +36,7 @@ class Epics::HIA < Epics::GenericRequest
|
|
35
36
|
xml.AuthenticationVersion 'X002'
|
36
37
|
}
|
37
38
|
xml.EncryptionPubKeyInfo{
|
39
|
+
x509_data_xml(xml, client.x_509_certificate(:e))
|
38
40
|
xml.PubKeyValue {
|
39
41
|
xml.send('ds:RSAKeyValue') {
|
40
42
|
xml.send('ds:Modulus', Base64.strict_encode64([client.e.n].pack("H*")))
|
data/lib/epics/ini.rb
CHANGED
@@ -26,6 +26,7 @@ class Epics::INI < Epics::GenericRequest
|
|
26
26
|
Nokogiri::XML::Builder.new do |xml|
|
27
27
|
xml.SignaturePubKeyOrderData('xmlns:ds' => 'http://www.w3.org/2000/09/xmldsig#', 'xmlns' => 'http://www.ebics.org/S001') {
|
28
28
|
xml.SignaturePubKeyInfo {
|
29
|
+
x509_data_xml(xml, client.x_509_certificate(:a))
|
29
30
|
xml.PubKeyValue {
|
30
31
|
xml.send('ds:RSAKeyValue') {
|
31
32
|
xml.send('ds:Modulus', Base64.strict_encode64([client.a.n].pack("H*")))
|
@@ -1,7 +1,6 @@
|
|
1
1
|
class Epics::LetterRenderer
|
2
2
|
extend Forwardable
|
3
3
|
|
4
|
-
TEMPLATE_PATH = File.join(File.dirname(__FILE__), '../letter/', 'ini.erb')
|
5
4
|
I18N_SCOPE = 'epics.letter'
|
6
5
|
|
7
6
|
def initialize(client)
|
@@ -12,11 +11,32 @@ class Epics::LetterRenderer
|
|
12
11
|
I18n.translate(key, **{ locale: @client.locale, scope: I18N_SCOPE }.merge(options))
|
13
12
|
end
|
14
13
|
|
15
|
-
|
14
|
+
alias t translate
|
16
15
|
|
17
16
|
def_delegators :@client, :host_id, :user_id, :partner_id, :a, :x, :e
|
18
17
|
|
19
18
|
def render(bankname)
|
20
|
-
|
19
|
+
template_path = File.join(File.dirname(__FILE__), '../letter/', template_filename)
|
20
|
+
ERB.new(File.read(template_path)).result(binding)
|
21
|
+
end
|
22
|
+
|
23
|
+
def template_filename
|
24
|
+
use_x_509_certificate_template? ? 'ini_with_certs.erb' : 'ini.erb'
|
25
|
+
end
|
26
|
+
|
27
|
+
def use_x_509_certificate_template?
|
28
|
+
x_509_certificate_a_hash && x_509_certificate_x_hash && x_509_certificate_e_hash
|
29
|
+
end
|
30
|
+
|
31
|
+
def x_509_certificate_a_hash
|
32
|
+
@client.x_509_certificate_hash(:a)
|
33
|
+
end
|
34
|
+
|
35
|
+
def x_509_certificate_x_hash
|
36
|
+
@client.x_509_certificate_hash(:x)
|
37
|
+
end
|
38
|
+
|
39
|
+
def x_509_certificate_e_hash
|
40
|
+
@client.x_509_certificate_hash(:e)
|
21
41
|
end
|
22
42
|
end
|
data/lib/epics/version.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
class Epics::X509Certificate
|
2
|
+
extend Forwardable
|
3
|
+
|
4
|
+
attr_reader :certificate
|
5
|
+
|
6
|
+
def_delegators :certificate, :issuer, :version
|
7
|
+
|
8
|
+
def initialize(crt_content)
|
9
|
+
@certificate = OpenSSL::X509::Certificate.new(crt_content)
|
10
|
+
end
|
11
|
+
|
12
|
+
def data
|
13
|
+
Base64.strict_encode64(@certificate.to_der)
|
14
|
+
end
|
15
|
+
end
|
data/lib/epics/z01.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
class Epics::Z01 < Epics::GenericRequest
|
2
|
+
def header
|
3
|
+
client.header_request.build(
|
4
|
+
nonce: nonce,
|
5
|
+
timestamp: timestamp,
|
6
|
+
order_type: 'Z01',
|
7
|
+
order_attribute: 'DZHNN',
|
8
|
+
order_params: {
|
9
|
+
DateRange: {
|
10
|
+
Start: options[:from],
|
11
|
+
End: options[:to]
|
12
|
+
}
|
13
|
+
},
|
14
|
+
mutable: { TransactionPhase: 'Initialisation' }
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
data/lib/epics.rb
CHANGED
@@ -32,6 +32,7 @@ require "epics/c52"
|
|
32
32
|
require "epics/c53"
|
33
33
|
require "epics/c54"
|
34
34
|
require "epics/c5n"
|
35
|
+
require "epics/z01"
|
35
36
|
require "epics/z52"
|
36
37
|
require "epics/z53"
|
37
38
|
require "epics/z54"
|
@@ -58,6 +59,7 @@ require "epics/hia"
|
|
58
59
|
require "epics/ini"
|
59
60
|
require "epics/hev"
|
60
61
|
require "epics/signer"
|
62
|
+
require "epics/x_509_certificate"
|
61
63
|
require "epics/client"
|
62
64
|
|
63
65
|
I18n.load_path += Dir[File.join(File.dirname(__FILE__), 'letter/locales', '*.yml')]
|
@@ -0,0 +1,335 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
2
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
5
|
+
<meta charset="UTF-8" />
|
6
|
+
<title>EBICS ini</title>
|
7
|
+
<style>
|
8
|
+
code {
|
9
|
+
font-size: 0.6rem;
|
10
|
+
overflow-wrap: break-word;
|
11
|
+
}
|
12
|
+
.code {
|
13
|
+
border-style: solid;
|
14
|
+
border-width: 1px;
|
15
|
+
padding: 8px;
|
16
|
+
background-color: azure;
|
17
|
+
}
|
18
|
+
.strong {
|
19
|
+
font-weight: bold;
|
20
|
+
}
|
21
|
+
h2 {
|
22
|
+
text-align: center;
|
23
|
+
}
|
24
|
+
td {
|
25
|
+
min-width: 150px;
|
26
|
+
}
|
27
|
+
table {
|
28
|
+
display: flex;
|
29
|
+
justify-content: center;
|
30
|
+
}
|
31
|
+
.column {
|
32
|
+
height: 100px;
|
33
|
+
}
|
34
|
+
</style>
|
35
|
+
</head>
|
36
|
+
<body>
|
37
|
+
<div>
|
38
|
+
<h2><%= t('initialization_letter.a') %></h2>
|
39
|
+
<table>
|
40
|
+
<tr>
|
41
|
+
<td>
|
42
|
+
<div class="column">
|
43
|
+
<table>
|
44
|
+
<tr>
|
45
|
+
<td class="strong">
|
46
|
+
<%= t('date') %> :
|
47
|
+
</td>
|
48
|
+
<td>
|
49
|
+
<%= Date.today.strftime('%d.%m.%Y') %>
|
50
|
+
</td>
|
51
|
+
</tr>
|
52
|
+
<tr>
|
53
|
+
<td class="strong">
|
54
|
+
<%= t('time') %> :
|
55
|
+
</td>
|
56
|
+
<td>
|
57
|
+
<%= Time.now.strftime('%H:%M:%S') %>
|
58
|
+
</td>
|
59
|
+
</tr>
|
60
|
+
<tr>
|
61
|
+
<td class="strong">
|
62
|
+
<%= t('recipient') %> :
|
63
|
+
</td>
|
64
|
+
<td>
|
65
|
+
<%= bankname %>
|
66
|
+
</td>
|
67
|
+
</tr>
|
68
|
+
</table>
|
69
|
+
</div>
|
70
|
+
</td>
|
71
|
+
<td>
|
72
|
+
<div class="column">
|
73
|
+
<table>
|
74
|
+
<tr>
|
75
|
+
<td class="strong">
|
76
|
+
Host-ID :
|
77
|
+
</td>
|
78
|
+
<td>
|
79
|
+
<%= host_id %>
|
80
|
+
</td>
|
81
|
+
</tr>
|
82
|
+
<tr>
|
83
|
+
<td class="strong">
|
84
|
+
User-ID :
|
85
|
+
</td>
|
86
|
+
<td>
|
87
|
+
<%= user_id %>
|
88
|
+
</td>
|
89
|
+
</tr>
|
90
|
+
<tr>
|
91
|
+
<td class="strong">
|
92
|
+
Partner-ID :
|
93
|
+
</td>
|
94
|
+
<td>
|
95
|
+
<%= partner_id %>
|
96
|
+
</td>
|
97
|
+
</tr>
|
98
|
+
<tr>
|
99
|
+
<td class="strong">
|
100
|
+
<%= t('version') %> :
|
101
|
+
</td>
|
102
|
+
<td>
|
103
|
+
A006
|
104
|
+
</td>
|
105
|
+
</tr>
|
106
|
+
</table>
|
107
|
+
</div>
|
108
|
+
</td>
|
109
|
+
</tr>
|
110
|
+
</table>
|
111
|
+
<p><%= t('certificate') %> :</p>
|
112
|
+
<pre class="code"><code><%= @client.x_509_certificates_content[:a] %></code></pre>
|
113
|
+
<p><%= t('hash') %> (SHA-256) :</p>
|
114
|
+
<p class="code"><code><%= x_509_certificate_a_hash.scan(/../).join(":") %></code></p>
|
115
|
+
<p><%= t('confirmation') %></p>
|
116
|
+
<br/>
|
117
|
+
<br/>
|
118
|
+
<br/>
|
119
|
+
<br/>
|
120
|
+
<table>
|
121
|
+
<tr>
|
122
|
+
<td>
|
123
|
+
_________________________
|
124
|
+
</td>
|
125
|
+
<td>
|
126
|
+
_________________________
|
127
|
+
</td>
|
128
|
+
<td>
|
129
|
+
_________________________
|
130
|
+
</td>
|
131
|
+
</tr>
|
132
|
+
<tr>
|
133
|
+
<td>
|
134
|
+
<%= t('issued_in') %>
|
135
|
+
</td>
|
136
|
+
<td>
|
137
|
+
<%= t('name') %>
|
138
|
+
</td>
|
139
|
+
<td>
|
140
|
+
<%= t('signature') %>
|
141
|
+
</td>
|
142
|
+
</tr>
|
143
|
+
</table>
|
144
|
+
</div>
|
145
|
+
<div style="page-break-after:always"></div>
|
146
|
+
<div>
|
147
|
+
<h2><%= t('initialization_letter.x') %></h2>
|
148
|
+
<table>
|
149
|
+
<tr>
|
150
|
+
<td>
|
151
|
+
<div class="column">
|
152
|
+
<table>
|
153
|
+
<tr>
|
154
|
+
<td class="strong">
|
155
|
+
<%= t('date') %> :
|
156
|
+
</td>
|
157
|
+
<td>
|
158
|
+
<%= Date.today.strftime('%d.%m.%Y') %>
|
159
|
+
</td>
|
160
|
+
</tr>
|
161
|
+
<tr>
|
162
|
+
<td class="strong">
|
163
|
+
<%= t('time') %> :
|
164
|
+
</td>
|
165
|
+
<td>
|
166
|
+
<%= Time.now.strftime('%H:%M:%S') %>
|
167
|
+
</td>
|
168
|
+
</tr>
|
169
|
+
<tr>
|
170
|
+
<td class="strong">
|
171
|
+
<%= t('recipient') %> :
|
172
|
+
</td>
|
173
|
+
<td>
|
174
|
+
<%= bankname %>
|
175
|
+
</td>
|
176
|
+
</tr>
|
177
|
+
</table>
|
178
|
+
</div>
|
179
|
+
</td>
|
180
|
+
<td>
|
181
|
+
<div class="column">
|
182
|
+
<table>
|
183
|
+
<tr>
|
184
|
+
<td class="strong">
|
185
|
+
Host-ID :
|
186
|
+
</td>
|
187
|
+
<td>
|
188
|
+
<%= host_id %>
|
189
|
+
</td>
|
190
|
+
</tr>
|
191
|
+
<tr>
|
192
|
+
<td class="strong">
|
193
|
+
User-ID :
|
194
|
+
</td>
|
195
|
+
<td>
|
196
|
+
<%= user_id %>
|
197
|
+
</td>
|
198
|
+
</tr>
|
199
|
+
<tr>
|
200
|
+
<td class="strong">
|
201
|
+
Partner-ID :
|
202
|
+
</td>
|
203
|
+
<td>
|
204
|
+
<%= partner_id %>
|
205
|
+
</td>
|
206
|
+
</tr>
|
207
|
+
<tr>
|
208
|
+
<td class="strong">
|
209
|
+
<%= t('version') %> :
|
210
|
+
</td>
|
211
|
+
<td>
|
212
|
+
X002
|
213
|
+
</td>
|
214
|
+
</tr>
|
215
|
+
</table>
|
216
|
+
</div>
|
217
|
+
</td>
|
218
|
+
</tr>
|
219
|
+
</table>
|
220
|
+
<p><%= t('certificate') %> :</p>
|
221
|
+
<pre class="code"><code><%= @client.x_509_certificates_content[:x] %></code></pre>
|
222
|
+
<p><%= t('hash') %> (SHA-256) :</p>
|
223
|
+
<p class="code"><code><%= x_509_certificate_x_hash.scan(/../).join(":") %></code></p>
|
224
|
+
</div>
|
225
|
+
<div style="page-break-after:always"></div>
|
226
|
+
<div>
|
227
|
+
<h2><%= t('initialization_letter.e') %></h2>
|
228
|
+
<table>
|
229
|
+
<tr>
|
230
|
+
<td>
|
231
|
+
<div class="column">
|
232
|
+
<table>
|
233
|
+
<tr>
|
234
|
+
<td class="strong">
|
235
|
+
<%= t('date') %> :
|
236
|
+
</td>
|
237
|
+
<td>
|
238
|
+
<%= Date.today.strftime('%d.%m.%Y') %>
|
239
|
+
</td>
|
240
|
+
</tr>
|
241
|
+
<tr>
|
242
|
+
<td class="strong">
|
243
|
+
<%= t('time') %> :
|
244
|
+
</td>
|
245
|
+
<td>
|
246
|
+
<%= Time.now.strftime('%H:%M:%S') %>
|
247
|
+
</td>
|
248
|
+
</tr>
|
249
|
+
<tr>
|
250
|
+
<td class="strong">
|
251
|
+
<%= t('recipient') %> :
|
252
|
+
</td>
|
253
|
+
<td>
|
254
|
+
<%= bankname %>
|
255
|
+
</td>
|
256
|
+
</tr>
|
257
|
+
</table>
|
258
|
+
</div>
|
259
|
+
</td>
|
260
|
+
<td>
|
261
|
+
<div class="column">
|
262
|
+
<table>
|
263
|
+
<tr>
|
264
|
+
<td class="strong">
|
265
|
+
Host-ID :
|
266
|
+
</td>
|
267
|
+
<td>
|
268
|
+
<%= host_id %>
|
269
|
+
</td>
|
270
|
+
</tr>
|
271
|
+
<tr>
|
272
|
+
<td class="strong">
|
273
|
+
User-ID :
|
274
|
+
</td>
|
275
|
+
<td>
|
276
|
+
<%= user_id %>
|
277
|
+
</td>
|
278
|
+
</tr>
|
279
|
+
<tr>
|
280
|
+
<td class="strong">
|
281
|
+
Partner-ID :
|
282
|
+
</td>
|
283
|
+
<td>
|
284
|
+
<%= partner_id %>
|
285
|
+
</td>
|
286
|
+
</tr>
|
287
|
+
<tr>
|
288
|
+
<td class="strong">
|
289
|
+
<%= t('version') %> :
|
290
|
+
</td>
|
291
|
+
<td>
|
292
|
+
E002
|
293
|
+
</td>
|
294
|
+
</tr>
|
295
|
+
</table>
|
296
|
+
</div>
|
297
|
+
</td>
|
298
|
+
</tr>
|
299
|
+
</table>
|
300
|
+
<p><%= t('certificate') %> :</p>
|
301
|
+
<pre class="code"><code><%= @client.x_509_certificates_content[:e] %></code></pre>
|
302
|
+
<p><%= t('hash') %> (SHA-256) :</p>
|
303
|
+
<p class="code"><code><%= x_509_certificate_e_hash.scan(/../).join(":") %></code></p>
|
304
|
+
<p><%= t('confirmation') %></p>
|
305
|
+
<br/>
|
306
|
+
<br/>
|
307
|
+
<br/>
|
308
|
+
<br/>
|
309
|
+
<table>
|
310
|
+
<tr>
|
311
|
+
<td>
|
312
|
+
_________________________
|
313
|
+
</td>
|
314
|
+
<td>
|
315
|
+
_________________________
|
316
|
+
</td>
|
317
|
+
<td>
|
318
|
+
_________________________
|
319
|
+
</td>
|
320
|
+
</tr>
|
321
|
+
<tr>
|
322
|
+
<td>
|
323
|
+
<%= t('issued_in') %>
|
324
|
+
</td>
|
325
|
+
<td>
|
326
|
+
<%= t('name') %>
|
327
|
+
</td>
|
328
|
+
<td>
|
329
|
+
<%= t('signature') %>
|
330
|
+
</td>
|
331
|
+
</tr>
|
332
|
+
</table>
|
333
|
+
</div>
|
334
|
+
</body>
|
335
|
+
</html>
|