epics 2.10.0 → 3.0.0.rc1

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.
Files changed (245) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.semaphore/semaphore.yml +17 -8
  4. data/CHANGELOG.md +97 -0
  5. data/EBICS_REFERENCES.md +169 -0
  6. data/README.md +219 -50
  7. data/lib/epics/azv.rb +3 -10
  8. data/lib/epics/b2b.rb +3 -10
  9. data/lib/epics/bka.rb +3 -14
  10. data/lib/epics/builders/body_builder/base.rb +26 -0
  11. data/lib/epics/builders/body_builder/v2.rb +9 -0
  12. data/lib/epics/builders/body_builder/v3.rb +9 -0
  13. data/lib/epics/builders/body_builder.rb +6 -0
  14. data/lib/epics/builders/data_encryption_info_builder.rb +29 -0
  15. data/lib/epics/builders/data_transfer_builder/base.rb +52 -0
  16. data/lib/epics/builders/data_transfer_builder/v2.rb +9 -0
  17. data/lib/epics/builders/data_transfer_builder/v3.rb +12 -0
  18. data/lib/epics/builders/data_transfer_builder.rb +6 -0
  19. data/lib/epics/builders/header_builder/base.rb +26 -0
  20. data/lib/epics/builders/header_builder/v2.rb +9 -0
  21. data/lib/epics/builders/header_builder/v3.rb +9 -0
  22. data/lib/epics/builders/header_builder.rb +6 -0
  23. data/lib/epics/builders/mutable_builder.rb +28 -0
  24. data/lib/epics/builders/order_details_builder/base.rb +100 -0
  25. data/lib/epics/builders/order_details_builder/v2.rb +21 -0
  26. data/lib/epics/builders/order_details_builder/v3.rb +51 -0
  27. data/lib/epics/builders/order_details_builder.rb +10 -0
  28. data/lib/epics/builders/request_builder.rb +25 -0
  29. data/lib/epics/builders/static_builder/base.rb +75 -0
  30. data/lib/epics/builders/static_builder/v2.rb +9 -0
  31. data/lib/epics/builders/static_builder/v3.rb +9 -0
  32. data/lib/epics/builders/static_builder.rb +9 -0
  33. data/lib/epics/builders/transfer_receipt_builder.rb +19 -0
  34. data/lib/epics/builders/xml_builder/base.rb +92 -0
  35. data/lib/epics/builders/xml_builder/v24.rb +31 -0
  36. data/lib/epics/builders/xml_builder/v25.rb +31 -0
  37. data/lib/epics/builders/xml_builder/v3.rb +31 -0
  38. data/lib/epics/builders/xml_builder.rb +7 -0
  39. data/lib/epics/builders.rb +13 -0
  40. data/lib/epics/c2s.rb +3 -10
  41. data/lib/epics/c52.rb +2 -14
  42. data/lib/epics/c53.rb +2 -14
  43. data/lib/epics/c54.rb +2 -14
  44. data/lib/epics/c5n.rb +3 -14
  45. data/lib/epics/ccs.rb +3 -10
  46. data/lib/epics/cct.rb +3 -10
  47. data/lib/epics/cd1.rb +3 -10
  48. data/lib/epics/cdb.rb +3 -10
  49. data/lib/epics/cdd.rb +3 -10
  50. data/lib/epics/cds.rb +3 -10
  51. data/lib/epics/cdz.rb +3 -14
  52. data/lib/epics/cip.rb +3 -10
  53. data/lib/epics/client.rb +491 -123
  54. data/lib/epics/crypt/aes.rb +56 -0
  55. data/lib/epics/crypt/x_509.rb +52 -0
  56. data/lib/epics/crypt.rb +5 -0
  57. data/lib/epics/crz.rb +3 -14
  58. data/lib/epics/factories/crypt/aes_factory.rb +5 -0
  59. data/lib/epics/factories/crypt.rb +4 -0
  60. data/lib/epics/factories/request_factory/base.rb +236 -0
  61. data/lib/epics/factories/request_factory/v2.rb +194 -0
  62. data/lib/epics/factories/request_factory/v24.rb +32 -0
  63. data/lib/epics/factories/request_factory/v25.rb +31 -0
  64. data/lib/epics/factories/request_factory/v3.rb +305 -0
  65. data/lib/epics/factories/request_factory.rb +8 -0
  66. data/lib/epics/factories.rb +5 -0
  67. data/lib/epics/fdl.rb +3 -18
  68. data/lib/epics/ful.rb +6 -0
  69. data/lib/epics/generic_request.rb +31 -92
  70. data/lib/epics/generic_upload_request.rb +14 -67
  71. data/lib/epics/haa.rb +3 -9
  72. data/lib/epics/hac.rb +3 -14
  73. data/lib/epics/handlers/auth_signature_handler.rb +102 -0
  74. data/lib/epics/handlers/order_data_handler/base.rb +98 -0
  75. data/lib/epics/handlers/order_data_handler/v2.rb +39 -0
  76. data/lib/epics/handlers/order_data_handler/v24.rb +11 -0
  77. data/lib/epics/handlers/order_data_handler/v25.rb +11 -0
  78. data/lib/epics/handlers/order_data_handler/v3.rb +41 -0
  79. data/lib/epics/handlers/order_data_handler.rb +8 -0
  80. data/lib/epics/handlers/user_signature_handler/base.rb +10 -0
  81. data/lib/epics/handlers/user_signature_handler/v2.rb +17 -0
  82. data/lib/epics/handlers/user_signature_handler/v3.rb +17 -0
  83. data/lib/epics/handlers/user_signature_handler.rb +6 -0
  84. data/lib/epics/handlers.rb +6 -0
  85. data/lib/epics/hev.rb +2 -15
  86. data/lib/epics/hia.rb +4 -55
  87. data/lib/epics/hkd.rb +3 -9
  88. data/lib/epics/hpb.rb +3 -13
  89. data/lib/epics/hpd.rb +3 -9
  90. data/lib/epics/htd.rb +3 -9
  91. data/lib/epics/ini.rb +4 -46
  92. data/lib/epics/keyring.rb +17 -0
  93. data/lib/epics/letter_renderer.rb +17 -22
  94. data/lib/epics/ptk.rb +3 -14
  95. data/lib/epics/response.rb +34 -29
  96. data/lib/epics/services/crypt_service.rb +62 -0
  97. data/lib/epics/services/digest_resolver/base.rb +30 -0
  98. data/lib/epics/services/digest_resolver/v2.rb +13 -0
  99. data/lib/epics/services/digest_resolver/v3.rb +19 -0
  100. data/lib/epics/services/digest_resolver.rb +6 -0
  101. data/lib/epics/services.rb +5 -0
  102. data/lib/epics/signature.rb +50 -0
  103. data/lib/epics/{key.rb → signature_algorithm/base.rb} +14 -21
  104. data/lib/epics/signature_algorithm/rsa.rb +50 -0
  105. data/lib/epics/signature_algorithm/rsapkcs1.rb +16 -0
  106. data/lib/epics/signature_algorithm/rsapss.rb +20 -0
  107. data/lib/epics/signature_algorithm.rb +2 -0
  108. data/lib/epics/sta.rb +3 -14
  109. data/lib/epics/version.rb +1 -1
  110. data/lib/epics/vmk.rb +3 -14
  111. data/lib/epics/wss.rb +3 -9
  112. data/lib/epics/xct.rb +3 -10
  113. data/lib/epics/xds.rb +3 -10
  114. data/lib/epics/xe2.rb +3 -10
  115. data/lib/epics/xe3.rb +3 -10
  116. data/lib/epics/xek.rb +5 -0
  117. data/lib/epics/yct.rb +6 -0
  118. data/lib/epics/z01.rb +2 -14
  119. data/lib/epics/z52.rb +2 -14
  120. data/lib/epics/z53.rb +2 -14
  121. data/lib/epics/z54.rb +2 -14
  122. data/lib/epics/zsr.rb +5 -0
  123. data/lib/epics.rb +69 -5
  124. data/lib/letter/ini.erb +27 -6
  125. data/spec/aes_spec.rb +46 -0
  126. data/spec/auth_signature_handler_spec.rb +58 -0
  127. data/spec/builders_spec.rb +616 -0
  128. data/spec/certificate_handling_spec.rb +189 -0
  129. data/spec/client_setup_block_spec.rb +41 -0
  130. data/spec/client_spec.rb +143 -91
  131. data/spec/crypt_service_spec.rb +132 -0
  132. data/spec/date_range_spec.rb +46 -0
  133. data/spec/digest_resolver_spec.rb +164 -0
  134. data/spec/fixtures/bank_x509.pem +3 -0
  135. data/spec/fixtures/xml/haa.xml +40 -1
  136. data/spec/fixtures/xml/haa_receipt.xml +33 -30
  137. data/spec/fixtures/xml/haa_response_h004.xml +4 -0
  138. data/spec/fixtures/xml/haa_response_h005.xml +38 -0
  139. data/spec/fixtures/xml/hia_request_order_data.xml +24 -1
  140. data/spec/fixtures/xml/hpb_request.xml +1 -1
  141. data/spec/fixtures/xml/hpb_response_x509.xml +16 -0
  142. data/spec/fixtures/xml/htd_order_data_h005.xml +55 -0
  143. data/spec/fixtures/xml/jruby/hia.xml +20 -22
  144. data/spec/fixtures/xml/jruby/ini.xml +1 -3
  145. data/spec/fixtures/xml/ruby/hia.xml +21 -1
  146. data/spec/fixtures/xml/ruby/ini.xml +21 -1
  147. data/spec/handlers_spec.rb +267 -0
  148. data/spec/hpb_malformed_certificate_spec.rb +36 -0
  149. data/spec/key_file_decryption_spec.rb +27 -0
  150. data/spec/key_file_preservation_spec.rb +78 -0
  151. data/spec/keyring_spec.rb +349 -0
  152. data/spec/middleware/parse_ebics_spec.rb +2 -1
  153. data/spec/order_id_spec.rb +65 -0
  154. data/spec/orders/azv_spec.rb +63 -7
  155. data/spec/orders/b2b_spec.rb +68 -3
  156. data/spec/orders/bka_spec.rb +34 -4
  157. data/spec/orders/c2s_spec.rb +62 -9
  158. data/spec/orders/c52_spec.rb +34 -4
  159. data/spec/orders/c53_spec.rb +34 -4
  160. data/spec/orders/c54_spec.rb +36 -4
  161. data/spec/orders/c5n_spec.rb +36 -4
  162. data/spec/orders/camt_parity_spec.rb +80 -0
  163. data/spec/orders/ccs_spec.rb +62 -9
  164. data/spec/orders/cct_spec.rb +83 -9
  165. data/spec/orders/cd1_spec.rb +50 -7
  166. data/spec/orders/cdb_spec.rb +64 -7
  167. data/spec/orders/cdd_spec.rb +64 -7
  168. data/spec/orders/cds_spec.rb +74 -0
  169. data/spec/orders/cdz_spec.rb +67 -4
  170. data/spec/orders/cip_spec.rb +61 -9
  171. data/spec/orders/crz_spec.rb +67 -4
  172. data/spec/orders/fdl_spec.rb +143 -13
  173. data/spec/orders/ful_spec.rb +63 -0
  174. data/spec/orders/haa_spec.rb +115 -9
  175. data/spec/orders/hac_spec.rb +89 -10
  176. data/spec/orders/hev_spec.rb +1 -6
  177. data/spec/orders/hia_spec.rb +25 -22
  178. data/spec/orders/hkd_spec.rb +23 -4
  179. data/spec/orders/hpb_spec.rb +7 -4
  180. data/spec/orders/hpd_spec.rb +23 -4
  181. data/spec/orders/htd_spec.rb +23 -4
  182. data/spec/orders/ini_spec.rb +23 -18
  183. data/spec/orders/ptk_spec.rb +27 -4
  184. data/spec/orders/sta_spec.rb +129 -11
  185. data/spec/orders/vmk_spec.rb +36 -4
  186. data/spec/orders/wss_spec.rb +29 -3
  187. data/spec/orders/x_509_certificate_spec.rb +9 -1
  188. data/spec/orders/xct_spec.rb +63 -0
  189. data/spec/orders/xds_spec.rb +13 -6
  190. data/spec/orders/xe2_spec.rb +64 -7
  191. data/spec/orders/xe3_spec.rb +64 -7
  192. data/spec/orders/xek_spec.rb +31 -0
  193. data/spec/orders/yct_spec.rb +43 -0
  194. data/spec/orders/z01_spec.rb +34 -4
  195. data/spec/orders/z52_spec.rb +34 -4
  196. data/spec/orders/z53_spec.rb +34 -4
  197. data/spec/orders/z54_spec.rb +36 -4
  198. data/spec/orders/zsr_spec.rb +31 -0
  199. data/spec/request_factory_spec.rb +444 -0
  200. data/spec/response_business_error_spec.rb +45 -0
  201. data/spec/response_validation_spec.rb +23 -0
  202. data/spec/{key_spec.rb → signature_algorithm/rsa_pss_spec.rb} +4 -13
  203. data/spec/support/ebics_matcher.rb +17 -9
  204. data/spec/support/ebics_shared_examples.rb +642 -0
  205. data/spec/support/h005_client_helper.rb +23 -0
  206. data/spec/upload_digest_spec.rb +69 -0
  207. data/spec/user_signature_handler_spec.rb +25 -0
  208. data/spec/version_support_error_spec.rb +76 -0
  209. data/spec/xsd/{ebics_hev.xsd → H000/ebics_hev.xsd} +0 -0
  210. data/spec/xsd/H003/ebics.xsd +11 -0
  211. data/spec/xsd/H003/ebics_keymgmt_request.xsd +555 -0
  212. data/spec/xsd/H003/ebics_keymgmt_response.xsd +131 -0
  213. data/spec/xsd/H003/ebics_orders.xsd +1811 -0
  214. data/spec/xsd/H003/ebics_request.xsd +354 -0
  215. data/spec/xsd/H003/ebics_response.xsd +161 -0
  216. data/spec/xsd/{ebics_signature.xsd → H003/ebics_signature.xsd} +0 -0
  217. data/spec/xsd/H003/ebics_types.xsd +2361 -0
  218. data/spec/xsd/H003/xmldsig-core-schema.xsd +318 -0
  219. data/spec/xsd/H004/ebics_signature.xsd +217 -0
  220. data/spec/xsd/H005/ebics_H005.xsd +11 -0
  221. data/spec/xsd/H005/ebics_keymgmt_request_H005.xsd +523 -0
  222. data/spec/xsd/H005/ebics_keymgmt_response_H005.xsd +137 -0
  223. data/spec/xsd/H005/ebics_orders_H005.xsd +2094 -0
  224. data/spec/xsd/H005/ebics_request_H005.xsd +349 -0
  225. data/spec/xsd/H005/ebics_response_H005.xsd +167 -0
  226. data/spec/xsd/H005/ebics_signature_S002.xsd +177 -0
  227. data/spec/xsd/H005/ebics_types_H005.xsd +1885 -0
  228. data/spec/xsd/H005/xmldsig-core-schema.xsd +318 -0
  229. metadata +200 -36
  230. data/lib/epics/header_request.rb +0 -58
  231. data/lib/epics/middleware/xmlsig.rb +0 -16
  232. data/lib/epics/signer.rb +0 -40
  233. data/lib/epics/x_509_certificate.rb +0 -15
  234. data/lib/letter/ini_with_certs.erb +0 -335
  235. data/spec/generic_upload_spec.rb +0 -58
  236. data/spec/hpb_spec.rb +0 -15
  237. data/spec/signer_spec.rb +0 -34
  238. /data/spec/xsd/{ebics_H004.xsd → H004/ebics_H004.xsd} +0 -0
  239. /data/spec/xsd/{ebics_keymgmt_request_H004.xsd → H004/ebics_keymgmt_request_H004.xsd} +0 -0
  240. /data/spec/xsd/{ebics_keymgmt_response_H004.xsd → H004/ebics_keymgmt_response_H004.xsd} +0 -0
  241. /data/spec/xsd/{ebics_orders_H004.xsd → H004/ebics_orders_H004.xsd} +0 -0
  242. /data/spec/xsd/{ebics_request_H004.xsd → H004/ebics_request_H004.xsd} +0 -0
  243. /data/spec/xsd/{ebics_response_H004.xsd → H004/ebics_response_H004.xsd} +0 -0
  244. /data/spec/xsd/{ebics_types_H004.xsd → H004/ebics_types_H004.xsd} +0 -0
  245. /data/spec/xsd/{xmldsig-core-schema.xsd → H004/xmldsig-core-schema.xsd} +0 -0
@@ -0,0 +1,349 @@
1
+ RSpec.describe Epics::Keyring do
2
+ describe '#initialize' do
3
+ it 'accepts VERSION_24 (H003)' do
4
+ keyring = described_class.new(Epics::Keyring::VERSION_24)
5
+ expect(keyring.version).to eq('H003')
6
+ end
7
+
8
+ it 'accepts VERSION_25 (H004)' do
9
+ keyring = described_class.new(Epics::Keyring::VERSION_25)
10
+ expect(keyring.version).to eq('H004')
11
+ end
12
+
13
+ it 'accepts VERSION_30 (H005)' do
14
+ keyring = described_class.new(Epics::Keyring::VERSION_30)
15
+ expect(keyring.version).to eq('H005')
16
+ end
17
+
18
+ it 'raises ArgumentError for unsupported version' do
19
+ expect { described_class.new('H006') }.to raise_error(ArgumentError, /Unsupported version/)
20
+ end
21
+
22
+ it 'raises ArgumentError for nil' do
23
+ expect { described_class.new(nil) }.to raise_error(ArgumentError)
24
+ end
25
+
26
+ it 'raises ArgumentError for empty string' do
27
+ expect { described_class.new('') }.to raise_error(ArgumentError)
28
+ end
29
+ end
30
+
31
+ describe 'version is immutable' do
32
+ it 'does not have a version= writer' do
33
+ keyring = described_class.new(Epics::Keyring::VERSION_25)
34
+ expect(keyring).not_to respond_to(:version=)
35
+ end
36
+ end
37
+
38
+ describe 'constants' do
39
+ it 'defines VERSION_24 as H003' do
40
+ expect(Epics::Keyring::VERSION_24).to eq('H003')
41
+ end
42
+
43
+ it 'defines VERSION_25 as H004' do
44
+ expect(Epics::Keyring::VERSION_25).to eq('H004')
45
+ end
46
+
47
+ it 'defines VERSION_30 as H005' do
48
+ expect(Epics::Keyring::VERSION_30).to eq('H005')
49
+ end
50
+
51
+ it 'VERSIONS contains all three versions' do
52
+ expect(Epics::Keyring::VERSIONS).to contain_exactly('H003', 'H004', 'H005')
53
+ end
54
+ end
55
+
56
+ describe 'key accessors' do
57
+ subject(:keyring) { described_class.new(Epics::Keyring::VERSION_25) }
58
+ let(:rsa_key) { OpenSSL::PKey::RSA.generate(2048) }
59
+
60
+ it 'stores and retrieves user_signature' do
61
+ sig = Epics::Signature.new(Epics::Signature::A_VERSION_5, Epics::SignatureAlgorithm::RsaPkcs1.new(rsa_key))
62
+ keyring.user_signature = sig
63
+ expect(keyring.user_signature).to eq(sig)
64
+ end
65
+
66
+ it 'stores and retrieves user_authentication' do
67
+ sig = Epics::Signature.new(Epics::Signature::X_VERSION_2, Epics::SignatureAlgorithm::RsaPkcs1.new(rsa_key))
68
+ keyring.user_authentication = sig
69
+ expect(keyring.user_authentication).to eq(sig)
70
+ end
71
+
72
+ it 'stores and retrieves user_encryption' do
73
+ sig = Epics::Signature.new(Epics::Signature::E_VERSION_2, Epics::SignatureAlgorithm::RsaPkcs1.new(rsa_key))
74
+ keyring.user_encryption = sig
75
+ expect(keyring.user_encryption).to eq(sig)
76
+ end
77
+
78
+ it 'stores and retrieves bank_authentication' do
79
+ sig = Epics::Signature.new(Epics::Signature::X_VERSION_2, Epics::SignatureAlgorithm::RsaPkcs1.new(rsa_key))
80
+ keyring.bank_authentication = sig
81
+ expect(keyring.bank_authentication).to eq(sig)
82
+ end
83
+
84
+ it 'stores and retrieves bank_encryption' do
85
+ sig = Epics::Signature.new(Epics::Signature::E_VERSION_2, Epics::SignatureAlgorithm::RsaPkcs1.new(rsa_key))
86
+ keyring.bank_encryption = sig
87
+ expect(keyring.bank_encryption).to eq(sig)
88
+ end
89
+
90
+ it 'all key slots are nil by default' do
91
+ expect(keyring.user_signature).to be_nil
92
+ expect(keyring.user_authentication).to be_nil
93
+ expect(keyring.user_encryption).to be_nil
94
+ expect(keyring.bank_authentication).to be_nil
95
+ expect(keyring.bank_encryption).to be_nil
96
+ end
97
+ end
98
+
99
+ describe 'key serialization round-trip via Client' do
100
+ let(:passphrase) { 'test_passphrase' }
101
+ let(:client) do
102
+ Epics::Client.setup(passphrase, 'https://example.com/ebics', 'HOST01', 'USER01', 'PARTNER01', 2048)
103
+ end
104
+
105
+ it 'dump_keys produces valid JSON' do
106
+ json = client.send(:dump_keys)
107
+ parsed = JSON.parse(json)
108
+ expect(parsed).to be_a(Hash)
109
+ expect(parsed.keys).to include('A006', 'X002', 'E002')
110
+ end
111
+
112
+ it 'keys survive save and reload' do
113
+ original_keys = client.keys
114
+ json = client.send(:dump_keys)
115
+
116
+ reloaded = Epics::Client.new(json, passphrase, 'https://example.com/ebics', 'HOST01', 'USER01', 'PARTNER01')
117
+
118
+ # Compare public digests to verify same keys
119
+ expect(reloaded.signature_key.public_digest).to eq(original_keys['A006'].public_digest)
120
+ expect(reloaded.authentication_key.public_digest).to eq(original_keys['X002'].public_digest)
121
+ expect(reloaded.encryption_key.public_digest).to eq(original_keys['E002'].public_digest)
122
+ end
123
+
124
+ it 'keys are encrypted (not plaintext PEM)' do
125
+ json = client.send(:dump_keys)
126
+ parsed = JSON.parse(json)
127
+ parsed.each_value do |encrypted_key|
128
+ # Values may be plain strings (user keys) or hashes with 'key'/'cert' (bank keys with certs)
129
+ values_to_check = encrypted_key.is_a?(Hash) ? encrypted_key.values : [encrypted_key]
130
+ values_to_check.each do |v|
131
+ expect(v).not_to include('BEGIN RSA PRIVATE KEY')
132
+ expect(v).not_to include('BEGIN PRIVATE KEY')
133
+ expect(v).not_to include('BEGIN CERTIFICATE')
134
+ end
135
+ end
136
+ end
137
+
138
+ it 'decrypt fails with wrong passphrase' do
139
+ json = client.send(:dump_keys)
140
+ expect do
141
+ Epics::Client.new(json, 'wrong_passphrase', 'https://example.com/ebics', 'HOST01', 'USER01', 'PARTNER01')
142
+ end.to raise_error(OpenSSL::Cipher::CipherError)
143
+ end
144
+ end
145
+
146
+ describe 'bank certificate serialization round-trip' do
147
+ let(:passphrase) { 'test_passphrase' }
148
+ let(:client) do
149
+ Epics::Client.setup(passphrase, 'https://example.com/ebics', 'HOST01', 'USER01', 'PARTNER01', 2048,
150
+ version: Epics::Keyring::VERSION_30)
151
+ end
152
+ let(:dn) { '/C=CH/O=TestBank/CN=test.ebics.org' }
153
+
154
+ before do
155
+ # Simulate HPB: create bank key signatures with certificates
156
+ %i[bank_authentication bank_encryption].each do |slot|
157
+ key = OpenSSL::PKey::RSA.generate(2048)
158
+ version = slot == :bank_authentication ? Epics::Signature::X_VERSION_2 : Epics::Signature::E_VERSION_2
159
+ sig = Epics::Signature.new(version, Epics::SignatureAlgorithm::RsaPkcs1.new(key))
160
+ sig.certificate = Epics::Crypt::X509.new(generate_x_509_crt(key, dn))
161
+ client.keyring.send(:"#{slot}=", sig)
162
+ end
163
+ end
164
+
165
+ it 'preserves bank certificates through dump/reload cycle' do
166
+ original_auth_fp = client.keyring.bank_authentication.certificate.fingerprint
167
+ original_enc_fp = client.keyring.bank_encryption.certificate.fingerprint
168
+
169
+ json = client.send(:dump_keys)
170
+ reloaded = Epics::Client.new(json, passphrase, 'https://example.com/ebics', 'HOST01', 'USER01', 'PARTNER01',
171
+ version: Epics::Keyring::VERSION_30)
172
+
173
+ expect(reloaded.keyring.bank_authentication.certificate).not_to be_nil
174
+ expect(reloaded.keyring.bank_encryption.certificate).not_to be_nil
175
+ expect(reloaded.keyring.bank_authentication.certificate.fingerprint).to eq(original_auth_fp)
176
+ expect(reloaded.keyring.bank_encryption.certificate.fingerprint).to eq(original_enc_fp)
177
+ end
178
+
179
+ it 'uses certificate-based digest after reload' do
180
+ resolver = Epics::Services::DigestResolver::V3.new
181
+ original_digest = resolver.sign_digest(client.keyring.bank_authentication)
182
+
183
+ json = client.send(:dump_keys)
184
+ reloaded = Epics::Client.new(json, passphrase, 'https://example.com/ebics', 'HOST01', 'USER01', 'PARTNER01',
185
+ version: Epics::Keyring::VERSION_30)
186
+
187
+ reloaded_digest = resolver.sign_digest(reloaded.keyring.bank_authentication)
188
+ expect(reloaded_digest).to eq(original_digest)
189
+ end
190
+
191
+ it 'dump_keys includes cert data for bank keys with certificates' do
192
+ json = client.send(:dump_keys)
193
+ parsed = JSON.parse(json)
194
+
195
+ bank_auth = parsed['HOST01.X002']
196
+ bank_enc = parsed['HOST01.E002']
197
+
198
+ expect(bank_auth).to be_a(Hash)
199
+ expect(bank_auth).to have_key('key')
200
+ expect(bank_auth).to have_key('cert')
201
+ expect(bank_enc).to be_a(Hash)
202
+ expect(bank_enc).to have_key('key')
203
+ expect(bank_enc).to have_key('cert')
204
+ end
205
+
206
+ it 'dump_keys uses plain string for bank keys without certificates' do
207
+ # Remove certificates
208
+ client.keyring.bank_authentication.certificate = nil
209
+ client.keyring.bank_encryption.certificate = nil
210
+
211
+ json = client.send(:dump_keys)
212
+ parsed = JSON.parse(json)
213
+
214
+ expect(parsed['HOST01.X002']).to be_a(String)
215
+ expect(parsed['HOST01.E002']).to be_a(String)
216
+ end
217
+
218
+ it 'backward compatible: loads legacy format without certificates' do
219
+ # Remove certificates and save in old format (plain strings)
220
+ client.keyring.bank_authentication.certificate = nil
221
+ client.keyring.bank_encryption.certificate = nil
222
+
223
+ json = client.send(:dump_keys)
224
+ reloaded = Epics::Client.new(json, passphrase, 'https://example.com/ebics', 'HOST01', 'USER01', 'PARTNER01',
225
+ version: Epics::Keyring::VERSION_30)
226
+
227
+ expect(reloaded.keyring.bank_authentication.certificate).to be_nil
228
+ expect(reloaded.keyring.bank_encryption.certificate).to be_nil
229
+ expect(reloaded.keyring.bank_authentication.key).not_to be_nil
230
+ expect(reloaded.keyring.bank_encryption.key).not_to be_nil
231
+ end
232
+ end
233
+
234
+ describe 'Client.setup key generation' do
235
+ it 'generates A006 user signature by default' do
236
+ client = Epics::Client.setup('pass', 'https://example.com', 'H', 'U', 'P', 2048)
237
+ expect(client.keyring.user_signature.version).to eq('A006')
238
+ end
239
+
240
+ it 'can generate A005 user signature via option' do
241
+ client = Epics::Client.setup('pass', 'https://example.com', 'H', 'U', 'P', 2048, signature_version: Epics::Signature::A_VERSION_5)
242
+ expect(client.keyring.user_signature.version).to eq('A005')
243
+ end
244
+
245
+ it 'generates X002 user authentication' do
246
+ client = Epics::Client.setup('pass', 'https://example.com', 'H', 'U', 'P', 2048)
247
+ expect(client.keyring.user_authentication.version).to eq('X002')
248
+ end
249
+
250
+ it 'generates E002 user encryption' do
251
+ client = Epics::Client.setup('pass', 'https://example.com', 'H', 'U', 'P', 2048)
252
+ expect(client.keyring.user_encryption.version).to eq('E002')
253
+ end
254
+
255
+ it 'uses RsaPss for A006 and RsaPkcs1 for X002/E002' do
256
+ client = Epics::Client.setup('pass', 'https://example.com', 'H', 'U', 'P', 2048)
257
+ expect(client.keyring.user_signature.key).to be_a(Epics::SignatureAlgorithm::RsaPss)
258
+ expect(client.keyring.user_authentication.key).to be_a(Epics::SignatureAlgorithm::RsaPkcs1)
259
+ expect(client.keyring.user_encryption.key).to be_a(Epics::SignatureAlgorithm::RsaPkcs1)
260
+ end
261
+
262
+ it 'defaults to H004 version' do
263
+ client = Epics::Client.setup('pass', 'https://example.com', 'H', 'U', 'P', 2048)
264
+ expect(client.version).to eq('H004')
265
+ end
266
+
267
+ it 'accepts version option' do
268
+ client = Epics::Client.setup('pass', 'https://example.com', 'H', 'U', 'P', 2048, version: Epics::Keyring::VERSION_30)
269
+ expect(client.version).to eq('H005')
270
+ end
271
+ end
272
+
273
+ describe 'Client#next_order_id' do
274
+ let(:client) do
275
+ Epics::Client.new(File.open(File.join(File.dirname(__FILE__), 'fixtures', 'SIZBN001.key')), 'secret',
276
+ 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS')
277
+ end
278
+
279
+ it 'increments on each call' do
280
+ first = client.next_order_id
281
+ second = client.next_order_id
282
+ expect(second).to eq(first + 1)
283
+ end
284
+
285
+ it 'raises on overflow (>= 1679615)' do
286
+ client.current_order_id = 1_679_615
287
+ expect { client.next_order_id }.to raise_error(RuntimeError, /overflow/)
288
+ end
289
+
290
+ it 'can be set via options' do
291
+ client2 = Epics::Client.new(File.open(File.join(File.dirname(__FILE__), 'fixtures', 'SIZBN001.key')), 'secret',
292
+ 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS',
293
+ order_id: 500_000)
294
+ expect(client2.next_order_id).to eq(500_001)
295
+ end
296
+ end
297
+
298
+ describe 'Client key extraction from fixture' do
299
+ let(:client) do
300
+ Epics::Client.new(File.open(File.join(File.dirname(__FILE__), 'fixtures', 'SIZBN001.key')), 'secret',
301
+ 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS')
302
+ end
303
+
304
+ it 'extracts all 5 key slots' do
305
+ expect(client.keyring.user_signature).not_to be_nil
306
+ expect(client.keyring.user_authentication).not_to be_nil
307
+ expect(client.keyring.user_encryption).not_to be_nil
308
+ expect(client.keyring.bank_authentication).not_to be_nil
309
+ expect(client.keyring.bank_encryption).not_to be_nil
310
+ end
311
+
312
+ it 'assigns correct types' do
313
+ expect(client.keyring.user_signature.type).to eq('A')
314
+ expect(client.keyring.user_authentication.type).to eq('X')
315
+ expect(client.keyring.user_encryption.type).to eq('E')
316
+ expect(client.keyring.bank_authentication.type).to eq('X')
317
+ expect(client.keyring.bank_encryption.type).to eq('E')
318
+ end
319
+
320
+ it 'bank keys are prefixed with host_id in keys hash' do
321
+ keys = client.keys
322
+ expect(keys).to have_key('SIZBN001.X002')
323
+ expect(keys).to have_key('SIZBN001.E002')
324
+ end
325
+ end
326
+
327
+ describe 'Client#version and #urn_schema' do
328
+ it 'returns H003 URN for VERSION_24' do
329
+ client = Epics::Client.new(File.open(File.join(File.dirname(__FILE__), 'fixtures', 'SIZBN001.key')), 'secret',
330
+ 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS', version: Epics::Keyring::VERSION_24)
331
+ expect(client.version).to eq('H003')
332
+ expect(client.urn_schema).to eq('http://www.ebics.org/H003')
333
+ end
334
+
335
+ it 'returns H004 URN for VERSION_25' do
336
+ client = Epics::Client.new(File.open(File.join(File.dirname(__FILE__), 'fixtures', 'SIZBN001.key')), 'secret',
337
+ 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS', version: Epics::Keyring::VERSION_25)
338
+ expect(client.version).to eq('H004')
339
+ expect(client.urn_schema).to eq('urn:org:ebics:H004')
340
+ end
341
+
342
+ it 'returns H005 URN for VERSION_30' do
343
+ client = Epics::Client.new(File.open(File.join(File.dirname(__FILE__), 'fixtures', 'SIZBN001.key')), 'secret',
344
+ 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS', version: Epics::Keyring::VERSION_30)
345
+ expect(client.version).to eq('H005')
346
+ expect(client.urn_schema).to eq('urn:org:ebics:H005')
347
+ end
348
+ end
349
+ end
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe Epics::ParseEbics do
4
+ let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'HOST', 'USER', 'PARTNER') }
4
5
  subject do
5
6
  Faraday.new do |builder|
6
- builder.use Epics::ParseEbics
7
+ builder.use Epics::ParseEbics, { client: client }
7
8
  builder.adapter :test, Faraday::Adapter::Test::Stubs.new do |stub|
8
9
  stub.post('/business_nok') { [200, {}, File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', 'xml', 'ebics_business_nok.xml'))] }
9
10
  stub.post('/technical_nok') { [200, {}, File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', 'xml', 'ebics_technical_nok.xml'))] }
@@ -0,0 +1,65 @@
1
+ RSpec.describe 'order IDs' do
2
+ def client(**options)
3
+ Epics::Client.new(File.open(File.join(File.dirname(__FILE__), 'fixtures', 'SIZBN001.key')),
4
+ 'secret', 'https://example.com/ebics', 'SIZBN001', 'EBIX', 'EBICS', **options)
5
+ end
6
+
7
+ describe 'accepted input' do
8
+ it 'defaults to A000' do
9
+ expect(client.current_order_id).to eq(Epics::Client::MIN_ORDER_ID)
10
+ end
11
+
12
+ it 'accepts the integer form' do
13
+ expect(client(order_id: 500_000).current_order_id).to eq(500_000)
14
+ end
15
+
16
+ # The bank and the initialisation letter both show the protocol form, so a caller
17
+ # persisting what it saw hands back a string.
18
+ it 'accepts the protocol form' do
19
+ expect(client(order_id: 'A000').current_order_id).to eq(Epics::Client::MIN_ORDER_ID)
20
+ end
21
+
22
+ it 'round-trips the protocol form' do
23
+ expect(client(order_id: 'B7Z9').current_order_id.to_s(36).upcase).to eq('B7Z9')
24
+ end
25
+ end
26
+
27
+ describe 'rejected input' do
28
+ # Anything below A000 renders as e.g. "0002", violating [A-Z][A-Z0-9]{3}.
29
+ it 'rejects a value below A000' do
30
+ expect { client(order_id: 2) }.to raise_error(ArgumentError, /between A000 and ZZZZ/)
31
+ end
32
+
33
+ it 'rejects a value above ZZZZ' do
34
+ expect { client(order_id: 1_679_616) }.to raise_error(ArgumentError, /between A000 and ZZZZ/)
35
+ end
36
+
37
+ it 'rejects a string that is not a valid order id' do
38
+ expect { client(order_id: 'nope!') }.to raise_error(ArgumentError, /between A000 and ZZZZ/)
39
+ end
40
+ end
41
+
42
+ describe '#next_order_id' do
43
+ it 'increments' do
44
+ c = client
45
+ expect { c.next_order_id }.to change(c, :current_order_id).by(1)
46
+ end
47
+
48
+ it 'raises at the end of the range' do
49
+ c = client(order_id: Epics::Client::MAX_ORDER_ID)
50
+
51
+ expect { c.next_order_id }.to raise_error(/overflow/)
52
+ end
53
+ end
54
+
55
+ describe 'rendering' do
56
+ it 'renders every accepted value as a valid OrderID' do
57
+ [Epics::Client::MIN_ORDER_ID, 500_000, Epics::Client::MAX_ORDER_ID].each do |id|
58
+ builder = nil
59
+ Epics::Builders::OrderDetailsBuilder::V2.new { |b| builder = b.add_order_id(id) }
60
+
61
+ expect(builder.doc.at_xpath('//OrderID').text).to match(/\A[A-Z][A-Z0-9]{3}\z/)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -1,18 +1,74 @@
1
1
  RSpec.describe Epics::AZV do
2
-
3
- let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') }
2
+ let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS', version:) }
4
3
  let(:document) { 'DTAZV' }
5
4
 
6
5
  subject { described_class.new(client, document) }
7
6
 
8
- describe '#to_xml' do
9
- specify { expect(subject.to_xml).to be_a_valid_ebics_doc }
7
+ describe 'order attributes' do
8
+ let(:version) { Epics::Keyring::VERSION_25 }
9
+
10
+ it { expect(subject.to_xml).to include('<OrderAttribute>OZHNN</OrderAttribute>') }
11
+ it { expect(subject.to_xml).to include('<OrderType>CD1</OrderType>') }
12
+ end
13
+
14
+ include_examples '#to_xml'
15
+ include_examples '#to_transfer_xml'
16
+
17
+ describe 'H005 request structure' do
18
+ let(:version) { Epics::Keyring::VERSION_30 }
19
+ let(:xml) { Nokogiri::XML(subject.to_xml) }
20
+ let(:ns) { { 'e' => 'urn:org:ebics:H005' } }
21
+
22
+ include_examples 'a valid ebicsRequest H005 upload',
23
+ service_name: 'XCT', msg_name: 'dtazv', scope: 'DE'
24
+ end
25
+
26
+ describe 'H005 transfer structure' do
27
+ let(:version) { Epics::Keyring::VERSION_30 }
28
+ let(:xml) do
29
+ subject.transaction_id = SecureRandom.hex(16)
30
+ Nokogiri::XML(subject.to_transfer_xml)
31
+ end
32
+ let(:ns) { { 'e' => 'urn:org:ebics:H005' } }
33
+
34
+ include_examples 'a valid ebicsRequest H005 transfer'
10
35
  end
11
36
 
12
- describe '#to_transfer_xml' do
13
- before { subject.transaction_id = SecureRandom.hex(16) }
37
+ describe 'H004 request structure' do
38
+ let(:version) { Epics::Keyring::VERSION_25 }
39
+ let(:xml) { Nokogiri::XML(subject.to_xml) }
40
+ let(:ns) { { 'e' => 'urn:org:ebics:H004' } }
14
41
 
15
- specify { expect(subject.to_transfer_xml).to be_a_valid_ebics_doc }
42
+ include_examples 'a valid ebicsRequest upload', order_type: 'CD1', order_attribute: 'OZHNN'
16
43
  end
17
44
 
45
+ describe 'H004 transfer structure' do
46
+ let(:version) { Epics::Keyring::VERSION_25 }
47
+ let(:xml) do
48
+ subject.transaction_id = SecureRandom.hex(16)
49
+ Nokogiri::XML(subject.to_transfer_xml)
50
+ end
51
+ let(:ns) { { 'e' => 'urn:org:ebics:H004' } }
52
+
53
+ include_examples 'a valid ebicsRequest transfer'
54
+ end
55
+
56
+ describe 'H003 request structure' do
57
+ let(:version) { Epics::Keyring::VERSION_24 }
58
+ let(:xml) { Nokogiri::XML(subject.to_xml) }
59
+ let(:ns) { { 'e' => 'http://www.ebics.org/H003' } }
60
+
61
+ include_examples 'a valid ebicsRequest upload', order_type: 'CD1', order_attribute: 'OZHNN', ebics_version: 'H003'
62
+ end
63
+
64
+ describe 'H003 transfer structure' do
65
+ let(:version) { Epics::Keyring::VERSION_24 }
66
+ let(:xml) do
67
+ subject.transaction_id = SecureRandom.hex(16)
68
+ Nokogiri::XML(subject.to_transfer_xml)
69
+ end
70
+ let(:ns) { { 'e' => 'http://www.ebics.org/H003' } }
71
+
72
+ include_examples 'a valid ebicsRequest transfer', ebics_version: 'H003'
73
+ end
18
74
  end
@@ -1,9 +1,74 @@
1
1
  RSpec.describe Epics::B2B do
2
- let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') }
2
+ let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS', version:) }
3
3
  let(:document) { File.read( File.join( File.dirname(__FILE__), '..', 'fixtures', 'xml', 'cd1.xml') ) }
4
+
4
5
  subject { described_class.new(client, document) }
5
6
 
6
- describe '#to_xml' do
7
- specify { expect(subject.to_xml).to be_a_valid_ebics_doc }
7
+ describe 'order attributes' do
8
+ let(:version) { Epics::Keyring::VERSION_25 }
9
+
10
+ it { expect(subject.to_xml).to include('<OrderAttribute>OZHNN</OrderAttribute>') }
11
+ it { expect(subject.to_xml).to include('<OrderType>B2B</OrderType>') }
12
+ end
13
+
14
+ include_examples '#to_xml'
15
+ include_examples '#to_transfer_xml'
16
+
17
+ describe 'H005 request structure' do
18
+ let(:version) { Epics::Keyring::VERSION_30 }
19
+ let(:xml) { Nokogiri::XML(subject.to_xml) }
20
+ let(:ns) { { 'e' => 'urn:org:ebics:H005' } }
21
+
22
+ include_examples 'a valid ebicsRequest H005 upload',
23
+ service_name: 'SDD', msg_name: 'pain.008', scope: 'BIL', service_option: 'B2B'
24
+ end
25
+
26
+ describe 'H005 transfer structure' do
27
+ let(:version) { Epics::Keyring::VERSION_30 }
28
+ let(:xml) do
29
+ subject.transaction_id = SecureRandom.hex(16)
30
+ Nokogiri::XML(subject.to_transfer_xml)
31
+ end
32
+ let(:ns) { { 'e' => 'urn:org:ebics:H005' } }
33
+
34
+ include_examples 'a valid ebicsRequest H005 transfer'
35
+ end
36
+
37
+ describe 'H004 request structure' do
38
+ let(:version) { Epics::Keyring::VERSION_25 }
39
+ let(:xml) { Nokogiri::XML(subject.to_xml) }
40
+ let(:ns) { { 'e' => 'urn:org:ebics:H004' } }
41
+
42
+ include_examples 'a valid ebicsRequest upload', order_type: 'B2B', order_attribute: 'OZHNN'
43
+ end
44
+
45
+ describe 'H004 transfer structure' do
46
+ let(:version) { Epics::Keyring::VERSION_25 }
47
+ let(:xml) do
48
+ subject.transaction_id = SecureRandom.hex(16)
49
+ Nokogiri::XML(subject.to_transfer_xml)
50
+ end
51
+ let(:ns) { { 'e' => 'urn:org:ebics:H004' } }
52
+
53
+ include_examples 'a valid ebicsRequest transfer'
54
+ end
55
+
56
+ describe 'H003 request structure' do
57
+ let(:version) { Epics::Keyring::VERSION_24 }
58
+ let(:xml) { Nokogiri::XML(subject.to_xml) }
59
+ let(:ns) { { 'e' => 'http://www.ebics.org/H003' } }
60
+
61
+ include_examples 'a valid ebicsRequest upload', order_type: 'B2B', order_attribute: 'OZHNN', ebics_version: 'H003'
62
+ end
63
+
64
+ describe 'H003 transfer structure' do
65
+ let(:version) { Epics::Keyring::VERSION_24 }
66
+ let(:xml) do
67
+ subject.transaction_id = SecureRandom.hex(16)
68
+ Nokogiri::XML(subject.to_transfer_xml)
69
+ end
70
+ let(:ns) { { 'e' => 'http://www.ebics.org/H003' } }
71
+
72
+ include_examples 'a valid ebicsRequest transfer', ebics_version: 'H003'
8
73
  end
9
74
  end
@@ -1,11 +1,41 @@
1
1
  RSpec.describe Epics::BKA do
2
+ let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS', version:) }
2
3
 
3
- let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') }
4
+ subject { described_class.new(client, from: Date.parse('2014-09-01'), to: Date.parse('2014-09-30')) }
4
5
 
5
- subject { described_class.new(client, from: "2014-09-01", to: "2014-09-30") }
6
+ describe 'order attributes' do
7
+ let(:version) { Epics::Keyring::VERSION_25 }
6
8
 
7
- describe '#to_xml' do
8
- specify { expect(subject.to_xml).to be_a_valid_ebics_doc }
9
+ it { expect(subject.to_xml).to include('<OrderAttribute>DZHNN</OrderAttribute>') }
10
+ it { expect(subject.to_xml).to include('<OrderType>BKA</OrderType>') }
9
11
  end
10
12
 
13
+ include_examples '#to_xml'
14
+
15
+ describe 'H005 request structure' do
16
+ let(:version) { Epics::Keyring::VERSION_30 }
17
+ let(:xml) { Nokogiri::XML(subject.to_xml) }
18
+ let(:ns) { { 'e' => 'urn:org:ebics:H005' } }
19
+
20
+ include_examples 'a valid ebicsRequest H005 download with date range',
21
+ service_name: 'EOP', msg_name: 'camt.053', scope: 'DE', from: '2014-09-01', to: '2014-09-30'
22
+ end
23
+
24
+ describe 'H004 request structure' do
25
+ let(:version) { Epics::Keyring::VERSION_25 }
26
+ let(:xml) { Nokogiri::XML(subject.to_xml) }
27
+ let(:ns) { { 'e' => 'urn:org:ebics:H004' } }
28
+
29
+ include_examples 'a valid ebicsRequest download with date range',
30
+ order_type: 'BKA', from: '2014-09-01', to: '2014-09-30'
31
+ end
32
+
33
+ describe 'H003 request structure' do
34
+ let(:version) { Epics::Keyring::VERSION_24 }
35
+ let(:xml) { Nokogiri::XML(subject.to_xml) }
36
+ let(:ns) { { 'e' => 'http://www.ebics.org/H003' } }
37
+
38
+ include_examples 'a valid ebicsRequest download with date range',
39
+ order_type: 'BKA', from: '2014-09-01', to: '2014-09-30', ebics_version: 'H003'
40
+ end
11
41
  end