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,642 @@
1
+ RSpec.shared_examples '#to_xml' do |versions: [Epics::Keyring::VERSION_24, Epics::Keyring::VERSION_25, Epics::Keyring::VERSION_30]|
2
+ describe '#to_xml' do
3
+ versions.each do |version|
4
+ context version do
5
+ let(:version) { version }
6
+ specify { expect(subject.to_xml).to be_a_valid_ebics_doc(version) }
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ RSpec.shared_examples '#to_xml pending' do |versions:, reason: 'not yet implemented'|
13
+ describe '#to_xml' do
14
+ versions.each do |version|
15
+ context version do
16
+ let(:version) { version }
17
+ specify(reason) { skip }
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ RSpec.shared_examples '#to_transfer_xml' do |versions: [Epics::Keyring::VERSION_24, Epics::Keyring::VERSION_25, Epics::Keyring::VERSION_30]|
24
+ describe '#to_transfer_xml' do
25
+ versions.each do |version|
26
+ context version do
27
+ let(:version) { version }
28
+ before { subject.transaction_id = SecureRandom.hex(16) }
29
+ specify { expect(subject.to_transfer_xml).to be_a_valid_ebics_doc(version) }
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ RSpec.shared_examples '#to_transfer_xml pending' do |versions:, reason: 'not yet implemented'|
36
+ describe '#to_transfer_xml' do
37
+ versions.each do |version|
38
+ context version do
39
+ let(:version) { version }
40
+ specify(reason) { skip }
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ RSpec.shared_examples '#to_receipt_xml' do |versions: [Epics::Keyring::VERSION_24, Epics::Keyring::VERSION_25, Epics::Keyring::VERSION_30]|
47
+ describe '#to_receipt_xml' do
48
+ versions.each do |version|
49
+ context version do
50
+ let(:version) { version }
51
+ before { subject.transaction_id = SecureRandom.hex(16) }
52
+ specify { expect(subject.to_receipt_xml).to be_a_valid_ebics_doc(version) }
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ RSpec.shared_examples '#to_receipt_xml pending' do |versions:, reason: 'not yet implemented'|
59
+ describe '#to_receipt_xml' do
60
+ versions.each do |version|
61
+ context version do
62
+ let(:version) { version }
63
+ specify(reason) { skip }
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ # Structural shared examples for EBICS V2 requests (H003 and H004)
70
+ # These parse the XML with Nokogiri/XPath and validate each key element.
71
+ # Consumers must define:
72
+ # let(:xml) { Nokogiri::XML(subject.to_xml) }
73
+ # let(:ns) { { 'e' => 'urn:org:ebics:H004' } } # or 'http://www.ebics.org/H003'
74
+ #
75
+ # ebics_version defaults to 'H004'. Pass ebics_version: 'H003' for H003 tests.
76
+
77
+ # Helper to derive the expected namespace href from a version string.
78
+ module EbicsSharedExampleHelpers
79
+ def self.expected_namespace(ebics_version)
80
+ ebics_version == 'H003' ? "http://www.ebics.org/H003" : "urn:org:ebics:#{ebics_version}"
81
+ end
82
+ end
83
+
84
+ RSpec.shared_examples 'a valid ebicsRequest header' do |order_type:, order_attribute:, ebics_version: 'H004'|
85
+ expected_ns_href = EbicsSharedExampleHelpers.expected_namespace(ebics_version)
86
+
87
+ it "has ebicsRequest root with #{ebics_version} namespace and Version" do
88
+ root = xml.root
89
+ expect(root.name).to eq('ebicsRequest')
90
+ expect(root.namespace.href).to eq(expected_ns_href)
91
+ expect(root['Version']).to eq(ebics_version)
92
+ expect(root['Revision']).to eq('1')
93
+ end
94
+
95
+ it 'has header with authenticate=true' do
96
+ header = xml.at_xpath('//e:header', ns)
97
+ expect(header).not_to be_nil
98
+ expect(header['authenticate']).to eq('true')
99
+ end
100
+
101
+ it 'has HostID in static header' do
102
+ expect(xml.at_xpath('//e:header/e:static/e:HostID', ns).text).to eq('SIZBN001')
103
+ end
104
+
105
+ it 'has a valid 32-char hex Nonce' do
106
+ nonce = xml.at_xpath('//e:header/e:static/e:Nonce', ns).text
107
+ expect(nonce).to match(/\A[0-9a-f]{32}\z/)
108
+ end
109
+
110
+ it 'has a Timestamp' do
111
+ timestamp = xml.at_xpath('//e:header/e:static/e:Timestamp', ns).text
112
+ expect(timestamp).not_to be_empty
113
+ end
114
+
115
+ it 'has PartnerID and UserID' do
116
+ expect(xml.at_xpath('//e:header/e:static/e:PartnerID', ns)).not_to be_nil
117
+ expect(xml.at_xpath('//e:header/e:static/e:UserID', ns)).not_to be_nil
118
+ end
119
+
120
+ it 'has Product element' do
121
+ product = xml.at_xpath('//e:header/e:static/e:Product', ns)
122
+ expect(product).not_to be_nil
123
+ end
124
+
125
+ it "has OrderType #{order_type}" do
126
+ expect(xml.at_xpath('//e:header/e:static/e:OrderDetails/e:OrderType', ns).text).to eq(order_type)
127
+ end
128
+
129
+ it "has OrderAttribute #{order_attribute}" do
130
+ expect(xml.at_xpath('//e:header/e:static/e:OrderDetails/e:OrderAttribute', ns).text).to eq(order_attribute)
131
+ end
132
+
133
+ it 'has BankPubKeyDigests with Authentication and Encryption versions' do
134
+ digests = xml.at_xpath('//e:header/e:static/e:BankPubKeyDigests', ns)
135
+ expect(digests).not_to be_nil
136
+
137
+ auth = digests.at_xpath('e:Authentication', ns)
138
+ expect(auth).not_to be_nil
139
+ expect(auth['Version']).not_to be_empty
140
+
141
+ enc = digests.at_xpath('e:Encryption', ns)
142
+ expect(enc).not_to be_nil
143
+ expect(enc['Version']).not_to be_empty
144
+ end
145
+
146
+ it 'has SecurityMedium 0000' do
147
+ expect(xml.at_xpath('//e:header/e:static/e:SecurityMedium', ns).text).to eq('0000')
148
+ end
149
+
150
+ it 'has TransactionPhase Initialisation' do
151
+ expect(xml.at_xpath('//e:header/e:mutable/e:TransactionPhase', ns).text).to eq('Initialisation')
152
+ end
153
+
154
+ it 'has AuthSignature element' do
155
+ expect(xml.at_xpath('//e:AuthSignature', ns)).not_to be_nil
156
+ end
157
+ end
158
+
159
+ RSpec.shared_examples 'a valid ebicsRequest download' do |order_type:, order_attribute: 'DZHNN', ebics_version: 'H004'|
160
+ include_examples 'a valid ebicsRequest header',
161
+ order_type: order_type, order_attribute: order_attribute, ebics_version: ebics_version
162
+
163
+ it 'has an empty body (no DataTransfer)' do
164
+ body = xml.at_xpath('//e:body', ns)
165
+ expect(body).not_to be_nil
166
+ expect(body.at_xpath('e:DataTransfer', ns)).to be_nil
167
+ end
168
+ end
169
+
170
+ RSpec.shared_examples 'a valid ebicsRequest upload' do |order_type:, order_attribute: 'OZHNN', ebics_version: 'H004'|
171
+ include_examples 'a valid ebicsRequest header',
172
+ order_type: order_type, order_attribute: order_attribute, ebics_version: ebics_version
173
+
174
+ it 'has StandardOrderParams' do
175
+ expect(xml.at_xpath('//e:header/e:static/e:OrderDetails/e:StandardOrderParams', ns)).not_to be_nil
176
+ end
177
+
178
+ it 'has NumSegments' do
179
+ expect(xml.at_xpath('//e:header/e:static/e:NumSegments', ns)).not_to be_nil
180
+ end
181
+
182
+ it 'has DataEncryptionInfo with authenticate=true' do
183
+ dei = xml.at_xpath('//e:body/e:DataTransfer/e:DataEncryptionInfo', ns)
184
+ expect(dei).not_to be_nil
185
+ expect(dei['authenticate']).to eq('true')
186
+ end
187
+
188
+ it 'has EncryptionPubKeyDigest with Version' do
189
+ epkd = xml.at_xpath('//e:body/e:DataTransfer/e:DataEncryptionInfo/e:EncryptionPubKeyDigest', ns)
190
+ expect(epkd).not_to be_nil
191
+ expect(epkd['Version']).not_to be_empty
192
+ end
193
+
194
+ it 'has TransactionKey' do
195
+ expect(xml.at_xpath('//e:body/e:DataTransfer/e:DataEncryptionInfo/e:TransactionKey', ns)).not_to be_nil
196
+ end
197
+
198
+ it 'has SignatureData with authenticate=true' do
199
+ sig_data = xml.at_xpath('//e:body/e:DataTransfer/e:SignatureData', ns)
200
+ expect(sig_data).not_to be_nil
201
+ expect(sig_data['authenticate']).to eq('true')
202
+ end
203
+ end
204
+
205
+ RSpec.shared_examples 'a valid ebicsRequest download with date range' do |order_type:, from:, to:, ebics_version: 'H004'|
206
+ include_examples 'a valid ebicsRequest download',
207
+ order_type: order_type, ebics_version: ebics_version
208
+
209
+ it 'has DateRange with correct Start and End dates' do
210
+ date_range = xml.at_xpath('//e:header/e:static/e:OrderDetails/e:StandardOrderParams/e:DateRange', ns)
211
+ expect(date_range).not_to be_nil
212
+ expect(date_range.at_xpath('e:Start', ns).text).to eq(from)
213
+ expect(date_range.at_xpath('e:End', ns).text).to eq(to)
214
+ end
215
+ end
216
+
217
+ RSpec.shared_examples 'a valid ebicsRequest receipt' do |ebics_version: 'H004'|
218
+ expected_ns_href = EbicsSharedExampleHelpers.expected_namespace(ebics_version)
219
+
220
+ it "has ebicsRequest root with #{ebics_version} namespace and Version" do
221
+ root = xml.root
222
+ expect(root.name).to eq('ebicsRequest')
223
+ expect(root.namespace.href).to eq(expected_ns_href)
224
+ expect(root['Version']).to eq(ebics_version)
225
+ expect(root['Revision']).to eq('1')
226
+ end
227
+
228
+ it 'has header with authenticate=true' do
229
+ header = xml.at_xpath('//e:header', ns)
230
+ expect(header).not_to be_nil
231
+ expect(header['authenticate']).to eq('true')
232
+ end
233
+
234
+ it 'has only HostID and TransactionID in static header' do
235
+ expect(xml.at_xpath('//e:header/e:static/e:HostID', ns).text).to eq('SIZBN001')
236
+ expect(xml.at_xpath('//e:header/e:static/e:TransactionID', ns)).not_to be_nil
237
+ expect(xml.at_xpath('//e:header/e:static/e:Nonce', ns)).to be_nil
238
+ expect(xml.at_xpath('//e:header/e:static/e:PartnerID', ns)).to be_nil
239
+ expect(xml.at_xpath('//e:header/e:static/e:UserID', ns)).to be_nil
240
+ expect(xml.at_xpath('//e:header/e:static/e:OrderDetails', ns)).to be_nil
241
+ expect(xml.at_xpath('//e:header/e:static/e:BankPubKeyDigests', ns)).to be_nil
242
+ end
243
+
244
+ it 'has TransactionPhase Receipt' do
245
+ expect(xml.at_xpath('//e:header/e:mutable/e:TransactionPhase', ns).text).to eq('Receipt')
246
+ end
247
+
248
+ it 'has AuthSignature element' do
249
+ expect(xml.at_xpath('//e:AuthSignature', ns)).not_to be_nil
250
+ end
251
+
252
+ it 'has TransferReceipt with authenticate=true and ReceiptCode 0' do
253
+ receipt = xml.at_xpath('//e:body/e:TransferReceipt', ns)
254
+ expect(receipt).not_to be_nil
255
+ expect(receipt['authenticate']).to eq('true')
256
+ expect(receipt.at_xpath('e:ReceiptCode', ns).text).to eq('0')
257
+ end
258
+ end
259
+
260
+ RSpec.shared_examples 'a valid ebicsRequest transfer' do |ebics_version: 'H004'|
261
+ expected_ns_href = EbicsSharedExampleHelpers.expected_namespace(ebics_version)
262
+
263
+ it "has ebicsRequest root with #{ebics_version} namespace and Version" do
264
+ root = xml.root
265
+ expect(root.name).to eq('ebicsRequest')
266
+ expect(root.namespace.href).to eq(expected_ns_href)
267
+ expect(root['Version']).to eq(ebics_version)
268
+ expect(root['Revision']).to eq('1')
269
+ end
270
+
271
+ it 'has header with authenticate=true' do
272
+ header = xml.at_xpath('//e:header', ns)
273
+ expect(header).not_to be_nil
274
+ expect(header['authenticate']).to eq('true')
275
+ end
276
+
277
+ it 'has only HostID and TransactionID in static header' do
278
+ expect(xml.at_xpath('//e:header/e:static/e:HostID', ns).text).to eq('SIZBN001')
279
+ expect(xml.at_xpath('//e:header/e:static/e:TransactionID', ns)).not_to be_nil
280
+ expect(xml.at_xpath('//e:header/e:static/e:Nonce', ns)).to be_nil
281
+ expect(xml.at_xpath('//e:header/e:static/e:PartnerID', ns)).to be_nil
282
+ expect(xml.at_xpath('//e:header/e:static/e:UserID', ns)).to be_nil
283
+ expect(xml.at_xpath('//e:header/e:static/e:OrderDetails', ns)).to be_nil
284
+ expect(xml.at_xpath('//e:header/e:static/e:BankPubKeyDigests', ns)).to be_nil
285
+ end
286
+
287
+ it 'has TransactionPhase Transfer with SegmentNumber' do
288
+ expect(xml.at_xpath('//e:header/e:mutable/e:TransactionPhase', ns).text).to eq('Transfer')
289
+ seg = xml.at_xpath('//e:header/e:mutable/e:SegmentNumber', ns)
290
+ expect(seg).not_to be_nil
291
+ expect(seg['lastSegment']).to eq('true')
292
+ expect(seg.text).to eq('1')
293
+ end
294
+
295
+ it 'has AuthSignature element' do
296
+ expect(xml.at_xpath('//e:AuthSignature', ns)).not_to be_nil
297
+ end
298
+
299
+ it 'has OrderData in body but no DataEncryptionInfo or SignatureData' do
300
+ expect(xml.at_xpath('//e:body/e:DataTransfer/e:OrderData', ns)).not_to be_nil
301
+ expect(xml.at_xpath('//e:body/e:DataTransfer/e:DataEncryptionInfo', ns)).to be_nil
302
+ expect(xml.at_xpath('//e:body/e:DataTransfer/e:SignatureData', ns)).to be_nil
303
+ end
304
+ end
305
+
306
+ RSpec.shared_examples 'a valid ebicsRequest download with FDLOrderParams' do |order_type: 'FDL', file_format:, ebics_version: 'H004'|
307
+ include_examples 'a valid ebicsRequest download',
308
+ order_type: order_type, ebics_version: ebics_version
309
+
310
+ it "has FDLOrderParams with FileFormat #{file_format}" do
311
+ fdl_params = xml.at_xpath('//e:header/e:static/e:OrderDetails/e:FDLOrderParams', ns)
312
+ expect(fdl_params).not_to be_nil
313
+ expect(fdl_params.at_xpath('e:FileFormat', ns).text).to eq(file_format)
314
+ expect(xml.at_xpath('//e:header/e:static/e:OrderDetails/e:StandardOrderParams', ns)).to be_nil
315
+ end
316
+ end
317
+
318
+ RSpec.shared_examples 'a valid ebicsRequest download with FDLOrderParams and date range' do |order_type: 'FDL', file_format:, from:, to:, ebics_version: 'H004'|
319
+ include_examples 'a valid ebicsRequest download with FDLOrderParams',
320
+ order_type: order_type, file_format: file_format, ebics_version: ebics_version
321
+
322
+ it 'has DateRange within FDLOrderParams' do
323
+ date_range = xml.at_xpath('//e:header/e:static/e:OrderDetails/e:FDLOrderParams/e:DateRange', ns)
324
+ expect(date_range).not_to be_nil
325
+ expect(date_range.at_xpath('e:Start', ns).text).to eq(from)
326
+ expect(date_range.at_xpath('e:End', ns).text).to eq(to)
327
+ end
328
+ end
329
+
330
+ # Structural shared examples for EBICS V3/H005 requests
331
+ # H005 uses AdminOrderType instead of OrderType+OrderAttribute,
332
+ # and BTDOrderParams/BTUOrderParams instead of StandardOrderParams.
333
+
334
+ RSpec.shared_examples 'a valid ebicsRequest H005 header' do |admin_order_type:|
335
+ expected_ns_href = 'urn:org:ebics:H005'
336
+
337
+ it 'has ebicsRequest root with H005 namespace and Version' do
338
+ root = xml.root
339
+ expect(root.name).to eq('ebicsRequest')
340
+ expect(root.namespace.href).to eq(expected_ns_href)
341
+ expect(root['Version']).to eq('H005')
342
+ expect(root['Revision']).to eq('1')
343
+ end
344
+
345
+ it 'has header with authenticate=true' do
346
+ header = xml.at_xpath('//e:header', ns)
347
+ expect(header).not_to be_nil
348
+ expect(header['authenticate']).to eq('true')
349
+ end
350
+
351
+ it 'has HostID in static header' do
352
+ expect(xml.at_xpath('//e:header/e:static/e:HostID', ns).text).to eq('SIZBN001')
353
+ end
354
+
355
+ it 'has a valid 32-char hex Nonce' do
356
+ nonce = xml.at_xpath('//e:header/e:static/e:Nonce', ns).text
357
+ expect(nonce).to match(/\A[0-9a-f]{32}\z/)
358
+ end
359
+
360
+ it 'has a Timestamp' do
361
+ timestamp = xml.at_xpath('//e:header/e:static/e:Timestamp', ns).text
362
+ expect(timestamp).not_to be_empty
363
+ end
364
+
365
+ it 'has PartnerID and UserID' do
366
+ expect(xml.at_xpath('//e:header/e:static/e:PartnerID', ns)).not_to be_nil
367
+ expect(xml.at_xpath('//e:header/e:static/e:UserID', ns)).not_to be_nil
368
+ end
369
+
370
+ it 'has Product element' do
371
+ product = xml.at_xpath('//e:header/e:static/e:Product', ns)
372
+ expect(product).not_to be_nil
373
+ end
374
+
375
+ it "has AdminOrderType #{admin_order_type}" do
376
+ expect(xml.at_xpath('//e:header/e:static/e:OrderDetails/e:AdminOrderType', ns).text).to eq(admin_order_type)
377
+ end
378
+
379
+ it 'does not have OrderType or OrderAttribute' do
380
+ expect(xml.at_xpath('//e:header/e:static/e:OrderDetails/e:OrderType', ns)).to be_nil
381
+ expect(xml.at_xpath('//e:header/e:static/e:OrderDetails/e:OrderAttribute', ns)).to be_nil
382
+ end
383
+
384
+ it 'has BankPubKeyDigests with Authentication and Encryption versions' do
385
+ digests = xml.at_xpath('//e:header/e:static/e:BankPubKeyDigests', ns)
386
+ expect(digests).not_to be_nil
387
+
388
+ auth = digests.at_xpath('e:Authentication', ns)
389
+ expect(auth).not_to be_nil
390
+ expect(auth['Version']).not_to be_empty
391
+
392
+ enc = digests.at_xpath('e:Encryption', ns)
393
+ expect(enc).not_to be_nil
394
+ expect(enc['Version']).not_to be_empty
395
+ end
396
+
397
+ it 'has SecurityMedium 0000' do
398
+ expect(xml.at_xpath('//e:header/e:static/e:SecurityMedium', ns).text).to eq('0000')
399
+ end
400
+
401
+ it 'has TransactionPhase Initialisation' do
402
+ expect(xml.at_xpath('//e:header/e:mutable/e:TransactionPhase', ns).text).to eq('Initialisation')
403
+ end
404
+
405
+ it 'has AuthSignature element' do
406
+ expect(xml.at_xpath('//e:AuthSignature', ns)).not_to be_nil
407
+ end
408
+ end
409
+
410
+ RSpec.shared_examples 'a valid ebicsRequest H005 download' do |service_name:, msg_name:, scope: nil, service_option: nil|
411
+ include_examples 'a valid ebicsRequest H005 header', admin_order_type: 'BTD'
412
+
413
+ it 'has BTDOrderParams with Service element' do
414
+ btd = xml.at_xpath('//e:header/e:static/e:OrderDetails/e:BTDOrderParams', ns)
415
+ expect(btd).not_to be_nil
416
+ service = btd.at_xpath('e:Service', ns)
417
+ expect(service).not_to be_nil
418
+ expect(service.at_xpath('e:ServiceName', ns).text).to eq(service_name)
419
+ expect(service.at_xpath('e:MsgName', ns).text).to eq(msg_name)
420
+ end
421
+
422
+ if scope
423
+ it "has Scope #{scope}" do
424
+ service = xml.at_xpath('//e:header/e:static/e:OrderDetails/e:BTDOrderParams/e:Service', ns)
425
+ expect(service.at_xpath('e:Scope', ns).text).to eq(scope)
426
+ end
427
+ end
428
+
429
+ if service_option
430
+ it "has ServiceOption #{service_option}" do
431
+ service = xml.at_xpath('//e:header/e:static/e:OrderDetails/e:BTDOrderParams/e:Service', ns)
432
+ expect(service.at_xpath('e:ServiceOption', ns).text).to eq(service_option)
433
+ end
434
+ end
435
+
436
+ it 'has an empty body (no DataTransfer)' do
437
+ body = xml.at_xpath('//e:body', ns)
438
+ expect(body).not_to be_nil
439
+ expect(body.at_xpath('e:DataTransfer', ns)).to be_nil
440
+ end
441
+
442
+ it 'does not have StandardOrderParams' do
443
+ expect(xml.at_xpath('//e:header/e:static/e:OrderDetails/e:StandardOrderParams', ns)).to be_nil
444
+ end
445
+ end
446
+
447
+ RSpec.shared_examples 'a valid ebicsRequest H005 download with date range' do |service_name:, msg_name:, from:, to:, scope: nil, service_option: nil|
448
+ include_examples 'a valid ebicsRequest H005 download',
449
+ service_name: service_name, msg_name: msg_name, scope: scope, service_option: service_option
450
+
451
+ it 'has DateRange within BTDOrderParams' do
452
+ date_range = xml.at_xpath('//e:header/e:static/e:OrderDetails/e:BTDOrderParams/e:DateRange', ns)
453
+ expect(date_range).not_to be_nil
454
+ expect(date_range.at_xpath('e:Start', ns).text).to eq(from)
455
+ expect(date_range.at_xpath('e:End', ns).text).to eq(to)
456
+ end
457
+ end
458
+
459
+ RSpec.shared_examples 'a valid ebicsRequest H005 upload' do |service_name:, msg_name:, scope: nil, service_option: nil|
460
+ include_examples 'a valid ebicsRequest H005 header', admin_order_type: 'BTU'
461
+
462
+ it 'has BTUOrderParams with Service element' do
463
+ btu = xml.at_xpath('//e:header/e:static/e:OrderDetails/e:BTUOrderParams', ns)
464
+ expect(btu).not_to be_nil
465
+ expect(btu['fileName']).not_to be_nil
466
+ service = btu.at_xpath('e:Service', ns)
467
+ expect(service).not_to be_nil
468
+ expect(service.at_xpath('e:ServiceName', ns).text).to eq(service_name)
469
+ expect(service.at_xpath('e:MsgName', ns).text).to eq(msg_name)
470
+ end
471
+
472
+ if scope
473
+ it "has Scope #{scope}" do
474
+ service = xml.at_xpath('//e:header/e:static/e:OrderDetails/e:BTUOrderParams/e:Service', ns)
475
+ expect(service.at_xpath('e:Scope', ns).text).to eq(scope)
476
+ end
477
+ end
478
+
479
+ if service_option
480
+ it "has ServiceOption #{service_option}" do
481
+ service = xml.at_xpath('//e:header/e:static/e:OrderDetails/e:BTUOrderParams/e:Service', ns)
482
+ expect(service.at_xpath('e:ServiceOption', ns).text).to eq(service_option)
483
+ end
484
+ end
485
+
486
+ it 'has NumSegments' do
487
+ expect(xml.at_xpath('//e:header/e:static/e:NumSegments', ns)).not_to be_nil
488
+ end
489
+
490
+ it 'has DataEncryptionInfo with authenticate=true' do
491
+ dei = xml.at_xpath('//e:body/e:DataTransfer/e:DataEncryptionInfo', ns)
492
+ expect(dei).not_to be_nil
493
+ expect(dei['authenticate']).to eq('true')
494
+ end
495
+
496
+ it 'has SignatureData with authenticate=true' do
497
+ sig_data = xml.at_xpath('//e:body/e:DataTransfer/e:SignatureData', ns)
498
+ expect(sig_data).not_to be_nil
499
+ expect(sig_data['authenticate']).to eq('true')
500
+ end
501
+
502
+ it 'has DataDigest element' do
503
+ data_digest = xml.at_xpath('//e:body/e:DataTransfer/e:DataDigest', ns)
504
+ expect(data_digest).not_to be_nil
505
+ expect(data_digest['SignatureVersion']).not_to be_empty
506
+ end
507
+
508
+ it 'has AdditionalOrderInfo element' do
509
+ expect(xml.at_xpath('//e:body/e:DataTransfer/e:AdditionalOrderInfo', ns)).not_to be_nil
510
+ end
511
+
512
+ it 'does not have StandardOrderParams' do
513
+ expect(xml.at_xpath('//e:header/e:static/e:OrderDetails/e:StandardOrderParams', ns)).to be_nil
514
+ end
515
+ end
516
+
517
+ RSpec.shared_examples 'a valid ebicsRequest H005 receipt' do
518
+ expected_ns_href = 'urn:org:ebics:H005'
519
+
520
+ it 'has ebicsRequest root with H005 namespace and Version' do
521
+ root = xml.root
522
+ expect(root.name).to eq('ebicsRequest')
523
+ expect(root.namespace.href).to eq(expected_ns_href)
524
+ expect(root['Version']).to eq('H005')
525
+ expect(root['Revision']).to eq('1')
526
+ end
527
+
528
+ it 'has header with authenticate=true' do
529
+ header = xml.at_xpath('//e:header', ns)
530
+ expect(header).not_to be_nil
531
+ expect(header['authenticate']).to eq('true')
532
+ end
533
+
534
+ it 'has only HostID and TransactionID in static header' do
535
+ expect(xml.at_xpath('//e:header/e:static/e:HostID', ns).text).to eq('SIZBN001')
536
+ expect(xml.at_xpath('//e:header/e:static/e:TransactionID', ns)).not_to be_nil
537
+ expect(xml.at_xpath('//e:header/e:static/e:Nonce', ns)).to be_nil
538
+ expect(xml.at_xpath('//e:header/e:static/e:PartnerID', ns)).to be_nil
539
+ expect(xml.at_xpath('//e:header/e:static/e:UserID', ns)).to be_nil
540
+ expect(xml.at_xpath('//e:header/e:static/e:OrderDetails', ns)).to be_nil
541
+ expect(xml.at_xpath('//e:header/e:static/e:BankPubKeyDigests', ns)).to be_nil
542
+ end
543
+
544
+ it 'has TransactionPhase Receipt' do
545
+ expect(xml.at_xpath('//e:header/e:mutable/e:TransactionPhase', ns).text).to eq('Receipt')
546
+ end
547
+
548
+ it 'has AuthSignature element' do
549
+ expect(xml.at_xpath('//e:AuthSignature', ns)).not_to be_nil
550
+ end
551
+
552
+ it 'has TransferReceipt with authenticate=true and ReceiptCode 0' do
553
+ receipt = xml.at_xpath('//e:body/e:TransferReceipt', ns)
554
+ expect(receipt).not_to be_nil
555
+ expect(receipt['authenticate']).to eq('true')
556
+ expect(receipt.at_xpath('e:ReceiptCode', ns).text).to eq('0')
557
+ end
558
+ end
559
+
560
+ RSpec.shared_examples 'a valid ebicsRequest H005 transfer' do
561
+ expected_ns_href = 'urn:org:ebics:H005'
562
+
563
+ it 'has ebicsRequest root with H005 namespace and Version' do
564
+ root = xml.root
565
+ expect(root.name).to eq('ebicsRequest')
566
+ expect(root.namespace.href).to eq(expected_ns_href)
567
+ expect(root['Version']).to eq('H005')
568
+ expect(root['Revision']).to eq('1')
569
+ end
570
+
571
+ it 'has header with authenticate=true' do
572
+ header = xml.at_xpath('//e:header', ns)
573
+ expect(header).not_to be_nil
574
+ expect(header['authenticate']).to eq('true')
575
+ end
576
+
577
+ it 'has only HostID and TransactionID in static header' do
578
+ expect(xml.at_xpath('//e:header/e:static/e:HostID', ns).text).to eq('SIZBN001')
579
+ expect(xml.at_xpath('//e:header/e:static/e:TransactionID', ns)).not_to be_nil
580
+ expect(xml.at_xpath('//e:header/e:static/e:Nonce', ns)).to be_nil
581
+ expect(xml.at_xpath('//e:header/e:static/e:PartnerID', ns)).to be_nil
582
+ expect(xml.at_xpath('//e:header/e:static/e:UserID', ns)).to be_nil
583
+ expect(xml.at_xpath('//e:header/e:static/e:OrderDetails', ns)).to be_nil
584
+ expect(xml.at_xpath('//e:header/e:static/e:BankPubKeyDigests', ns)).to be_nil
585
+ end
586
+
587
+ it 'has TransactionPhase Transfer with SegmentNumber' do
588
+ expect(xml.at_xpath('//e:header/e:mutable/e:TransactionPhase', ns).text).to eq('Transfer')
589
+ seg = xml.at_xpath('//e:header/e:mutable/e:SegmentNumber', ns)
590
+ expect(seg).not_to be_nil
591
+ expect(seg['lastSegment']).to eq('true')
592
+ expect(seg.text).to eq('1')
593
+ end
594
+
595
+ it 'has AuthSignature element' do
596
+ expect(xml.at_xpath('//e:AuthSignature', ns)).not_to be_nil
597
+ end
598
+
599
+ it 'has OrderData in body but no DataEncryptionInfo or SignatureData' do
600
+ expect(xml.at_xpath('//e:body/e:DataTransfer/e:OrderData', ns)).not_to be_nil
601
+ expect(xml.at_xpath('//e:body/e:DataTransfer/e:DataEncryptionInfo', ns)).to be_nil
602
+ expect(xml.at_xpath('//e:body/e:DataTransfer/e:SignatureData', ns)).to be_nil
603
+ end
604
+ end
605
+
606
+ RSpec.shared_examples 'a valid ebicsRequest upload with FULOrderParams' do |order_type: 'FUL', order_attribute: 'DZHNN', file_format:, ebics_version: 'H004'|
607
+ include_examples 'a valid ebicsRequest header',
608
+ order_type: order_type, order_attribute: order_attribute, ebics_version: ebics_version
609
+
610
+ it "has FULOrderParams with FileFormat #{file_format}" do
611
+ ful_params = xml.at_xpath('//e:header/e:static/e:OrderDetails/e:FULOrderParams', ns)
612
+ expect(ful_params).not_to be_nil
613
+ expect(ful_params.at_xpath('e:FileFormat', ns).text).to eq(file_format)
614
+ expect(xml.at_xpath('//e:header/e:static/e:OrderDetails/e:StandardOrderParams', ns)).to be_nil
615
+ end
616
+
617
+ it 'has NumSegments' do
618
+ expect(xml.at_xpath('//e:header/e:static/e:NumSegments', ns)).not_to be_nil
619
+ end
620
+
621
+ it 'has DataEncryptionInfo with authenticate=true' do
622
+ dei = xml.at_xpath('//e:body/e:DataTransfer/e:DataEncryptionInfo', ns)
623
+ expect(dei).not_to be_nil
624
+ expect(dei['authenticate']).to eq('true')
625
+ end
626
+
627
+ it 'has EncryptionPubKeyDigest with Version' do
628
+ epkd = xml.at_xpath('//e:body/e:DataTransfer/e:DataEncryptionInfo/e:EncryptionPubKeyDigest', ns)
629
+ expect(epkd).not_to be_nil
630
+ expect(epkd['Version']).not_to be_empty
631
+ end
632
+
633
+ it 'has TransactionKey' do
634
+ expect(xml.at_xpath('//e:body/e:DataTransfer/e:DataEncryptionInfo/e:TransactionKey', ns)).not_to be_nil
635
+ end
636
+
637
+ it 'has SignatureData with authenticate=true' do
638
+ sig_data = xml.at_xpath('//e:body/e:DataTransfer/e:SignatureData', ns)
639
+ expect(sig_data).not_to be_nil
640
+ expect(sig_data['authenticate']).to eq('true')
641
+ end
642
+ end
@@ -0,0 +1,23 @@
1
+ # Almost every H005 request needs certificates, so they are injected into any `client`
2
+ # let rather than set up in each spec. Tag an example or group
3
+ # `without_certificates: true` to exercise the path where none are configured.
4
+ RSpec.configure do |config|
5
+ # Bank signatures hold a public key only, so a throwaway pair stands in. Generated
6
+ # once -- per-example generation dominated the suite runtime.
7
+ throwaway_key = OpenSSL::PKey::RSA.generate(2048)
8
+ dn = '/C=DE/O=TestBank/CN=test.ebics.org'
9
+
10
+ config.before(:each) do |example|
11
+ next if example.metadata[:without_certificates]
12
+ next unless defined?(client) && client.is_a?(Epics::Client) && client.version == Epics::Keyring::VERSION_30
13
+
14
+ [client.keyring.user_signature, client.keyring.user_authentication, client.keyring.user_encryption,
15
+ client.keyring.bank_authentication, client.keyring.bank_encryption].each do |sig|
16
+ next unless sig && sig.certificate.nil?
17
+
18
+ key = sig.key.key
19
+ key = throwaway_key unless key.private?
20
+ sig.certificate = Epics::Crypt::X509.new(generate_x_509_crt(key, dn))
21
+ end
22
+ end
23
+ end