epics 2.11.0 → 3.0.0.rc2
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/.gitignore +2 -1
- data/.semaphore/semaphore.yml +17 -8
- data/CHANGELOG.md +103 -0
- data/EBICS_REFERENCES.md +169 -0
- data/README.md +223 -50
- data/lib/epics/azv.rb +3 -10
- data/lib/epics/b2b.rb +3 -10
- data/lib/epics/bka.rb +3 -14
- data/lib/epics/builders/body_builder/base.rb +26 -0
- data/lib/epics/builders/body_builder/v2.rb +9 -0
- data/lib/epics/builders/body_builder/v3.rb +9 -0
- data/lib/epics/builders/body_builder.rb +6 -0
- data/lib/epics/builders/data_encryption_info_builder.rb +29 -0
- data/lib/epics/builders/data_transfer_builder/base.rb +52 -0
- data/lib/epics/builders/data_transfer_builder/v2.rb +9 -0
- data/lib/epics/builders/data_transfer_builder/v3.rb +12 -0
- data/lib/epics/builders/data_transfer_builder.rb +6 -0
- data/lib/epics/builders/header_builder/base.rb +26 -0
- data/lib/epics/builders/header_builder/v2.rb +9 -0
- data/lib/epics/builders/header_builder/v3.rb +9 -0
- data/lib/epics/builders/header_builder.rb +6 -0
- data/lib/epics/builders/mutable_builder.rb +28 -0
- data/lib/epics/builders/order_details_builder/base.rb +100 -0
- data/lib/epics/builders/order_details_builder/v2.rb +21 -0
- data/lib/epics/builders/order_details_builder/v3.rb +51 -0
- data/lib/epics/builders/order_details_builder.rb +10 -0
- data/lib/epics/builders/request_builder.rb +25 -0
- data/lib/epics/builders/static_builder/base.rb +75 -0
- data/lib/epics/builders/static_builder/v2.rb +9 -0
- data/lib/epics/builders/static_builder/v3.rb +9 -0
- data/lib/epics/builders/static_builder.rb +9 -0
- data/lib/epics/builders/transfer_receipt_builder.rb +19 -0
- data/lib/epics/builders/xml_builder/base.rb +92 -0
- data/lib/epics/builders/xml_builder/v24.rb +31 -0
- data/lib/epics/builders/xml_builder/v25.rb +31 -0
- data/lib/epics/builders/xml_builder/v3.rb +31 -0
- data/lib/epics/builders/xml_builder.rb +7 -0
- data/lib/epics/builders.rb +13 -0
- data/lib/epics/c2s.rb +3 -10
- data/lib/epics/c52.rb +2 -14
- data/lib/epics/c53.rb +2 -14
- data/lib/epics/c54.rb +2 -14
- data/lib/epics/c5n.rb +3 -14
- data/lib/epics/ccs.rb +3 -10
- data/lib/epics/cct.rb +3 -10
- data/lib/epics/cd1.rb +3 -10
- data/lib/epics/cdb.rb +3 -10
- data/lib/epics/cdd.rb +3 -10
- data/lib/epics/cds.rb +3 -10
- data/lib/epics/cdz.rb +3 -14
- data/lib/epics/cip.rb +3 -10
- data/lib/epics/client.rb +511 -125
- data/lib/epics/crypt/aes.rb +56 -0
- data/lib/epics/crypt/x_509.rb +52 -0
- data/lib/epics/crypt.rb +5 -0
- data/lib/epics/crz.rb +3 -14
- data/lib/epics/factories/crypt/aes_factory.rb +5 -0
- data/lib/epics/factories/crypt.rb +4 -0
- data/lib/epics/factories/request_factory/base.rb +236 -0
- data/lib/epics/factories/request_factory/v2.rb +194 -0
- data/lib/epics/factories/request_factory/v24.rb +32 -0
- data/lib/epics/factories/request_factory/v25.rb +31 -0
- data/lib/epics/factories/request_factory/v3.rb +305 -0
- data/lib/epics/factories/request_factory.rb +8 -0
- data/lib/epics/factories.rb +5 -0
- data/lib/epics/fdl.rb +3 -18
- data/lib/epics/ful.rb +3 -15
- data/lib/epics/generic_request.rb +36 -92
- data/lib/epics/generic_upload_request.rb +14 -67
- data/lib/epics/haa.rb +3 -9
- data/lib/epics/hac.rb +3 -14
- data/lib/epics/handlers/auth_signature_handler.rb +102 -0
- data/lib/epics/handlers/order_data_handler/base.rb +98 -0
- data/lib/epics/handlers/order_data_handler/v2.rb +39 -0
- data/lib/epics/handlers/order_data_handler/v24.rb +11 -0
- data/lib/epics/handlers/order_data_handler/v25.rb +11 -0
- data/lib/epics/handlers/order_data_handler/v3.rb +41 -0
- data/lib/epics/handlers/order_data_handler.rb +8 -0
- data/lib/epics/handlers/user_signature_handler/base.rb +10 -0
- data/lib/epics/handlers/user_signature_handler/v2.rb +17 -0
- data/lib/epics/handlers/user_signature_handler/v3.rb +17 -0
- data/lib/epics/handlers/user_signature_handler.rb +6 -0
- data/lib/epics/handlers.rb +6 -0
- data/lib/epics/hev.rb +2 -15
- data/lib/epics/hia.rb +4 -55
- data/lib/epics/hkd.rb +3 -9
- data/lib/epics/hpb.rb +3 -13
- data/lib/epics/hpd.rb +3 -9
- data/lib/epics/htd.rb +3 -9
- data/lib/epics/ini.rb +4 -46
- data/lib/epics/keyring.rb +17 -0
- data/lib/epics/letter_renderer.rb +17 -22
- data/lib/epics/ptk.rb +3 -14
- data/lib/epics/response.rb +51 -31
- data/lib/epics/services/crypt_service.rb +62 -0
- data/lib/epics/services/digest_resolver/base.rb +30 -0
- data/lib/epics/services/digest_resolver/v2.rb +13 -0
- data/lib/epics/services/digest_resolver/v3.rb +19 -0
- data/lib/epics/services/digest_resolver.rb +6 -0
- data/lib/epics/services.rb +5 -0
- data/lib/epics/signature.rb +50 -0
- data/lib/epics/{key.rb → signature_algorithm/base.rb} +14 -21
- data/lib/epics/signature_algorithm/rsa.rb +50 -0
- data/lib/epics/signature_algorithm/rsapkcs1.rb +16 -0
- data/lib/epics/signature_algorithm/rsapss.rb +20 -0
- data/lib/epics/signature_algorithm.rb +2 -0
- data/lib/epics/sta.rb +3 -14
- data/lib/epics/version.rb +3 -1
- data/lib/epics/vmk.rb +3 -14
- data/lib/epics/wss.rb +3 -9
- data/lib/epics/xct.rb +3 -10
- data/lib/epics/xds.rb +3 -10
- data/lib/epics/xe2.rb +3 -10
- data/lib/epics/xe3.rb +3 -10
- data/lib/epics/xek.rb +5 -0
- data/lib/epics/yct.rb +6 -0
- data/lib/epics/z01.rb +2 -14
- data/lib/epics/z52.rb +2 -14
- data/lib/epics/z53.rb +2 -14
- data/lib/epics/z54.rb +2 -14
- data/lib/epics/zsr.rb +5 -0
- data/lib/epics.rb +94 -5
- data/lib/letter/ini.erb +27 -6
- data/spec/aes_spec.rb +46 -0
- data/spec/auth_signature_handler_spec.rb +58 -0
- data/spec/builders_spec.rb +616 -0
- data/spec/certificate_handling_spec.rb +189 -0
- data/spec/client_setup_block_spec.rb +41 -0
- data/spec/client_spec.rb +143 -91
- data/spec/crypt_service_spec.rb +132 -0
- data/spec/date_range_spec.rb +46 -0
- data/spec/digest_resolver_spec.rb +164 -0
- data/spec/fixtures/bank_x509.pem +3 -0
- data/spec/fixtures/xml/haa.xml +40 -1
- data/spec/fixtures/xml/haa_receipt.xml +33 -30
- data/spec/fixtures/xml/haa_response_h004.xml +4 -0
- data/spec/fixtures/xml/haa_response_h005.xml +38 -0
- data/spec/fixtures/xml/hia_request_order_data.xml +24 -1
- data/spec/fixtures/xml/hpb_request.xml +1 -1
- data/spec/fixtures/xml/hpb_response_x509.xml +16 -0
- data/spec/fixtures/xml/htd_order_data_h005.xml +55 -0
- data/spec/fixtures/xml/jruby/hia.xml +20 -22
- data/spec/fixtures/xml/jruby/ini.xml +1 -3
- data/spec/fixtures/xml/ruby/hia.xml +21 -1
- data/spec/fixtures/xml/ruby/ini.xml +21 -1
- data/spec/handlers_spec.rb +267 -0
- data/spec/hpb_malformed_certificate_spec.rb +36 -0
- data/spec/key_file_decryption_spec.rb +27 -0
- data/spec/key_file_preservation_spec.rb +78 -0
- data/spec/keyring_spec.rb +349 -0
- data/spec/middleware/parse_ebics_spec.rb +2 -1
- data/spec/order_id_spec.rb +65 -0
- data/spec/orders/azv_spec.rb +63 -7
- data/spec/orders/b2b_spec.rb +68 -3
- data/spec/orders/bka_spec.rb +34 -4
- data/spec/orders/c2s_spec.rb +62 -9
- data/spec/orders/c52_spec.rb +34 -4
- data/spec/orders/c53_spec.rb +34 -4
- data/spec/orders/c54_spec.rb +36 -4
- data/spec/orders/c5n_spec.rb +36 -4
- data/spec/orders/camt_parity_spec.rb +80 -0
- data/spec/orders/ccs_spec.rb +62 -9
- data/spec/orders/cct_spec.rb +83 -9
- data/spec/orders/cd1_spec.rb +50 -7
- data/spec/orders/cdb_spec.rb +64 -7
- data/spec/orders/cdd_spec.rb +64 -7
- data/spec/orders/cds_spec.rb +74 -0
- data/spec/orders/cdz_spec.rb +67 -4
- data/spec/orders/cip_spec.rb +61 -9
- data/spec/orders/crz_spec.rb +67 -4
- data/spec/orders/fdl_spec.rb +143 -13
- data/spec/orders/ful_spec.rb +51 -10
- data/spec/orders/haa_spec.rb +115 -9
- data/spec/orders/hac_spec.rb +89 -10
- data/spec/orders/hev_spec.rb +1 -6
- data/spec/orders/hia_spec.rb +25 -22
- data/spec/orders/hkd_spec.rb +23 -4
- data/spec/orders/hpb_spec.rb +7 -4
- data/spec/orders/hpd_spec.rb +23 -4
- data/spec/orders/htd_spec.rb +23 -4
- data/spec/orders/ini_spec.rb +23 -18
- data/spec/orders/ptk_spec.rb +27 -4
- data/spec/orders/sta_spec.rb +129 -11
- data/spec/orders/vmk_spec.rb +36 -4
- data/spec/orders/wss_spec.rb +29 -3
- data/spec/orders/x_509_certificate_spec.rb +9 -1
- data/spec/orders/xct_spec.rb +63 -0
- data/spec/orders/xds_spec.rb +13 -6
- data/spec/orders/xe2_spec.rb +64 -7
- data/spec/orders/xe3_spec.rb +64 -7
- data/spec/orders/xek_spec.rb +31 -0
- data/spec/orders/yct_spec.rb +43 -0
- data/spec/orders/z01_spec.rb +34 -4
- data/spec/orders/z52_spec.rb +34 -4
- data/spec/orders/z53_spec.rb +34 -4
- data/spec/orders/z54_spec.rb +36 -4
- data/spec/orders/zsr_spec.rb +31 -0
- data/spec/request_factory_spec.rb +444 -0
- data/spec/response_business_error_spec.rb +45 -0
- data/spec/response_spec.rb +31 -0
- data/spec/response_validation_spec.rb +23 -0
- data/spec/segmented_download_spec.rb +248 -0
- data/spec/{key_spec.rb → signature_algorithm/rsa_pss_spec.rb} +4 -13
- data/spec/support/ebics_matcher.rb +17 -9
- data/spec/support/ebics_shared_examples.rb +642 -0
- data/spec/support/h005_client_helper.rb +23 -0
- data/spec/upload_digest_spec.rb +69 -0
- data/spec/user_signature_handler_spec.rb +25 -0
- data/spec/version_support_error_spec.rb +76 -0
- data/spec/xsd/{ebics_hev.xsd → H000/ebics_hev.xsd} +0 -0
- data/spec/xsd/H003/ebics.xsd +11 -0
- data/spec/xsd/H003/ebics_keymgmt_request.xsd +555 -0
- data/spec/xsd/H003/ebics_keymgmt_response.xsd +131 -0
- data/spec/xsd/H003/ebics_orders.xsd +1811 -0
- data/spec/xsd/H003/ebics_request.xsd +354 -0
- data/spec/xsd/H003/ebics_response.xsd +161 -0
- data/spec/xsd/{ebics_signature.xsd → H003/ebics_signature.xsd} +0 -0
- data/spec/xsd/H003/ebics_types.xsd +2361 -0
- data/spec/xsd/H003/xmldsig-core-schema.xsd +318 -0
- data/spec/xsd/H004/ebics_signature.xsd +217 -0
- data/spec/xsd/H005/ebics_H005.xsd +11 -0
- data/spec/xsd/H005/ebics_keymgmt_request_H005.xsd +523 -0
- data/spec/xsd/H005/ebics_keymgmt_response_H005.xsd +137 -0
- data/spec/xsd/H005/ebics_orders_H005.xsd +2094 -0
- data/spec/xsd/H005/ebics_request_H005.xsd +349 -0
- data/spec/xsd/H005/ebics_response_H005.xsd +167 -0
- data/spec/xsd/H005/ebics_signature_S002.xsd +177 -0
- data/spec/xsd/H005/ebics_types_H005.xsd +1885 -0
- data/spec/xsd/H005/xmldsig-core-schema.xsd +318 -0
- metadata +199 -36
- data/lib/epics/header_request.rb +0 -58
- data/lib/epics/middleware/xmlsig.rb +0 -16
- data/lib/epics/signer.rb +0 -40
- data/lib/epics/x_509_certificate.rb +0 -15
- data/lib/letter/ini_with_certs.erb +0 -335
- data/spec/generic_upload_spec.rb +0 -58
- data/spec/hpb_spec.rb +0 -15
- data/spec/signer_spec.rb +0 -34
- /data/spec/xsd/{ebics_H004.xsd → H004/ebics_H004.xsd} +0 -0
- /data/spec/xsd/{ebics_keymgmt_request_H004.xsd → H004/ebics_keymgmt_request_H004.xsd} +0 -0
- /data/spec/xsd/{ebics_keymgmt_response_H004.xsd → H004/ebics_keymgmt_response_H004.xsd} +0 -0
- /data/spec/xsd/{ebics_orders_H004.xsd → H004/ebics_orders_H004.xsd} +0 -0
- /data/spec/xsd/{ebics_request_H004.xsd → H004/ebics_request_H004.xsd} +0 -0
- /data/spec/xsd/{ebics_response_H004.xsd → H004/ebics_response_H004.xsd} +0 -0
- /data/spec/xsd/{ebics_types_H004.xsd → H004/ebics_types_H004.xsd} +0 -0
- /data/spec/xsd/{xmldsig-core-schema.xsd → H004/xmldsig-core-schema.xsd} +0 -0
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
RSpec.describe 'RequestFactory' 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:) }
|
|
3
|
+
let(:start_date) { Date.new(2024, 1, 1) }
|
|
4
|
+
let(:end_date) { Date.new(2024, 1, 31) }
|
|
5
|
+
let(:digest) { OpenSSL::Digest::SHA256.digest('test document') }
|
|
6
|
+
let(:transaction_key) { OpenSSL::Cipher::AES.new(128, :CBC).random_key }
|
|
7
|
+
let(:transaction_id) { SecureRandom.hex(16) }
|
|
8
|
+
|
|
9
|
+
def parse(builder)
|
|
10
|
+
Nokogiri::XML(builder.to_xml).tap(&:remove_namespaces!)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# ─── Shared examples ───────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
shared_examples 'a base factory' do |factory_class|
|
|
16
|
+
subject(:factory) { factory_class.new(client) }
|
|
17
|
+
|
|
18
|
+
describe '#create_hev' do
|
|
19
|
+
it 'creates ebicsHEVRequest with HostID' do
|
|
20
|
+
xml = parse(factory.create_hev)
|
|
21
|
+
expect(xml.root.name).to eq('ebicsHEVRequest')
|
|
22
|
+
expect(xml.at('//HostID').text).to eq('SIZBN001')
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe '#create_ini' do
|
|
27
|
+
it 'creates ebicsUnsecuredRequest with INI order details' do
|
|
28
|
+
xml = parse(factory.create_ini('<order_data/>'))
|
|
29
|
+
expect(xml.root.name).to eq('ebicsUnsecuredRequest')
|
|
30
|
+
expect(xml.at('//HostID').text).to eq('SIZBN001')
|
|
31
|
+
expect(xml.at('//PartnerID').text).to eq(client.partner_id)
|
|
32
|
+
expect(xml.at('//UserID').text).to eq(client.user_id)
|
|
33
|
+
expect(xml.at('//SecurityMedium').text).to eq('0000')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe '#create_hia' do
|
|
38
|
+
it 'creates ebicsUnsecuredRequest with HIA order details' do
|
|
39
|
+
xml = parse(factory.create_hia('<order_data/>'))
|
|
40
|
+
expect(xml.root.name).to eq('ebicsUnsecuredRequest')
|
|
41
|
+
expect(xml.at('//HostID').text).to eq('SIZBN001')
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe '#create_hpb' do
|
|
46
|
+
it 'creates ebicsNoPubKeyDigestsRequest with AuthSignature' do
|
|
47
|
+
xml = parse(factory.create_hpb)
|
|
48
|
+
expect(xml.root.name).to eq('ebicsNoPubKeyDigestsRequest')
|
|
49
|
+
expect(xml.at('//AuthSignature')).not_to be_nil
|
|
50
|
+
expect(xml.at('//SecurityMedium').text).to eq('0000')
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
describe '#create_transfer_receipt' do
|
|
55
|
+
it 'creates receipt with TransactionID and ReceiptCode' do
|
|
56
|
+
xml = parse(factory.create_transfer_receipt(transaction_id, 0))
|
|
57
|
+
expect(xml.root.name).to eq('ebicsRequest')
|
|
58
|
+
expect(xml.at('//TransactionID').text).to eq(transaction_id)
|
|
59
|
+
expect(xml.at('//TransactionPhase').text).to eq('Receipt')
|
|
60
|
+
expect(xml.at('//ReceiptCode').text).to eq('0')
|
|
61
|
+
expect(xml.at('//AuthSignature')).not_to be_nil
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
describe '#create_transfer_upload' do
|
|
66
|
+
it 'creates transfer with segment data' do
|
|
67
|
+
xml = parse(factory.create_transfer_upload(transaction_id, transaction_key, 'order_data', 1, true))
|
|
68
|
+
expect(xml.at('//TransactionID').text).to eq(transaction_id)
|
|
69
|
+
expect(xml.at('//TransactionPhase').text).to eq('Transfer')
|
|
70
|
+
node = xml.at('//SegmentNumber')
|
|
71
|
+
expect(node.text).to eq('1')
|
|
72
|
+
expect(node['lastSegment']).to eq('true')
|
|
73
|
+
expect(xml.at('//OrderData')).not_to be_nil
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe '#create_transfer_download' do
|
|
78
|
+
it 'creates transfer without order data' do
|
|
79
|
+
xml = parse(factory.create_transfer_download(transaction_id, 2, false))
|
|
80
|
+
expect(xml.at('//TransactionID').text).to eq(transaction_id)
|
|
81
|
+
expect(xml.at('//TransactionPhase').text).to eq('Transfer')
|
|
82
|
+
expect(xml.at('//SegmentNumber').text).to eq('2')
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
describe 'admin order types' do
|
|
87
|
+
%w[hpd hkd htd haa].each do |order_type|
|
|
88
|
+
it "creates #{order_type.upcase} request with AuthSignature" do
|
|
89
|
+
xml = parse(factory.send("create_#{order_type}"))
|
|
90
|
+
expect(xml.root.name).to eq('ebicsRequest')
|
|
91
|
+
expect(xml.at('//AuthSignature')).not_to be_nil
|
|
92
|
+
expect(xml.at('//TransactionPhase').text).to eq('Initialisation')
|
|
93
|
+
expect(xml.at('//BankPubKeyDigests')).not_to be_nil
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
%w[hac ptk].each do |order_type|
|
|
98
|
+
it "creates #{order_type.upcase} request with date range" do
|
|
99
|
+
xml = parse(factory.send("create_#{order_type}", start_date, end_date))
|
|
100
|
+
expect(xml.at('//AuthSignature')).not_to be_nil
|
|
101
|
+
expect(xml.at('//DateRange/Start').text).to eq('2024-01-01')
|
|
102
|
+
expect(xml.at('//DateRange/End').text).to eq('2024-01-31')
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# ─── V2 shared examples ────────────────────────────────────
|
|
109
|
+
|
|
110
|
+
shared_examples 'a V2 download factory' do |factory_class, namespace|
|
|
111
|
+
subject(:factory) { factory_class.new(client) }
|
|
112
|
+
|
|
113
|
+
describe 'download requests' do
|
|
114
|
+
download_types = {
|
|
115
|
+
'c52' => {}, 'c53' => {}, 'c54' => {}, 'sta' => {},
|
|
116
|
+
'vmk' => {}, 'z52' => {}, 'z53' => {}, 'z54' => {},
|
|
117
|
+
'bka' => {}, 'c5n' => {}, 'cdz' => {}, 'crz' => {}, 'z01' => {}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
download_types.each do |order_type, _|
|
|
121
|
+
it "creates #{order_type.upcase} download request" do
|
|
122
|
+
xml = parse(factory.send("create_#{order_type}", start_date, end_date))
|
|
123
|
+
expect(xml.root.name).to eq('ebicsRequest')
|
|
124
|
+
expect(xml.at('//OrderType').text).to eq(order_type.upcase)
|
|
125
|
+
expect(xml.at('//OrderAttribute').text).to eq('DZHNN')
|
|
126
|
+
expect(xml.at('//AuthSignature')).not_to be_nil
|
|
127
|
+
expect(xml.at('//BankPubKeyDigests')).not_to be_nil
|
|
128
|
+
expect(xml.at('//DateRange/Start').text).to eq('2024-01-01')
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
describe 'WSS download (no date range)' do
|
|
134
|
+
it 'creates WSS request without date range' do
|
|
135
|
+
xml = parse(factory.create_wss)
|
|
136
|
+
expect(xml.at('//OrderType').text).to eq('WSS')
|
|
137
|
+
expect(xml.at('//DateRange')).to be_nil
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
describe 'FDL download with file format' do
|
|
142
|
+
it 'creates FDL request with FDLOrderParams' do
|
|
143
|
+
xml = parse(factory.create_fdl('camt.053', start_date, end_date))
|
|
144
|
+
expect(xml.at('//OrderType').text).to eq('FDL')
|
|
145
|
+
expect(xml.at('//FDLOrderParams/FileFormat').text).to eq('camt.053')
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
shared_examples 'a V2 upload factory' do |factory_class|
|
|
151
|
+
subject(:factory) { factory_class.new(client) }
|
|
152
|
+
|
|
153
|
+
describe 'upload requests' do
|
|
154
|
+
upload_types_with_es = {
|
|
155
|
+
'cct' => true, 'cdd' => true, 'cdb' => true, 'cip' => true,
|
|
156
|
+
'cd1' => true, 'b2b' => true, 'xds' => true, 'xe2' => true, 'xe3' => true
|
|
157
|
+
}
|
|
158
|
+
upload_types_without_es = {
|
|
159
|
+
'ccs' => false, 'cds' => false, 'c2s' => false
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
(upload_types_with_es.merge(upload_types_without_es)).each do |order_type, with_es|
|
|
163
|
+
expected_attr = with_es ? 'OZHNN' : 'DZHNN'
|
|
164
|
+
it "creates #{order_type.upcase} upload with OrderAttribute=#{expected_attr}" do
|
|
165
|
+
xml = parse(factory.send("create_#{order_type}", digest, transaction_key))
|
|
166
|
+
expect(xml.root.name).to eq('ebicsRequest')
|
|
167
|
+
expect(xml.at('//OrderType').text).to eq(order_type.upcase)
|
|
168
|
+
expect(xml.at('//OrderAttribute').text).to eq(expected_attr)
|
|
169
|
+
expect(xml.at('//NumSegments').text).to eq('1')
|
|
170
|
+
expect(xml.at('//SignatureData')).not_to be_nil
|
|
171
|
+
expect(xml.at('//DataEncryptionInfo')).not_to be_nil
|
|
172
|
+
expect(xml.at('//TransactionKey')).not_to be_nil
|
|
173
|
+
expect(xml.at('//AuthSignature')).not_to be_nil
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
describe 'FUL upload with file format' do
|
|
179
|
+
it 'creates FUL request with FULOrderParams' do
|
|
180
|
+
xml = parse(factory.send(:create_ful, digest, transaction_key, file_format: 'pain.001.001.02'))
|
|
181
|
+
expect(xml.at('//OrderType').text).to eq('FUL')
|
|
182
|
+
expect(xml.at('//FULOrderParams/FileFormat').text).to eq('pain.001.001.02')
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
describe 'VersionSupportError for V3-only types' do
|
|
187
|
+
it 'raises for create_btd' do
|
|
188
|
+
expect { factory.create_btd }.to raise_error(Epics::VersionSupportError)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it 'raises for create_btu' do
|
|
192
|
+
expect { factory.create_btu }.to raise_error(Epics::VersionSupportError)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# ─── V24 (H003) ────────────────────────────────────────────
|
|
198
|
+
|
|
199
|
+
describe Epics::Factories::RequestFactory::V24 do
|
|
200
|
+
let(:version) { Epics::Keyring::VERSION_24 }
|
|
201
|
+
|
|
202
|
+
include_examples 'a base factory', Epics::Factories::RequestFactory::V24
|
|
203
|
+
include_examples 'a V2 download factory', Epics::Factories::RequestFactory::V24, 'http://www.ebics.org/H003'
|
|
204
|
+
include_examples 'a V2 upload factory', Epics::Factories::RequestFactory::V24
|
|
205
|
+
|
|
206
|
+
subject(:factory) { described_class.new(client) }
|
|
207
|
+
|
|
208
|
+
describe 'V24-specific: OrderID present' do
|
|
209
|
+
it 'includes OrderID in download requests' do
|
|
210
|
+
xml = parse(factory.create_c52(start_date, end_date))
|
|
211
|
+
expect(xml.at('//OrderID')).not_to be_nil
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it 'includes OrderID in upload requests' do
|
|
215
|
+
xml = parse(factory.create_cct(digest, transaction_key))
|
|
216
|
+
expect(xml.at('//OrderID')).not_to be_nil
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
describe 'INI uses DZNNN attribute' do
|
|
221
|
+
it 'sets OrderAttribute to DZNNN for INI' do
|
|
222
|
+
xml = parse(factory.create_ini('<data/>'))
|
|
223
|
+
expect(xml.at('//OrderAttribute').text).to eq('DZNNN')
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
describe 'H005-only order types' do
|
|
228
|
+
%w[xek yct zsr].each do |type|
|
|
229
|
+
it "raises VersionSupportError for #{type}" do
|
|
230
|
+
expect { factory.send("create_#{type}", start_date, end_date) }
|
|
231
|
+
.to raise_error(Epics::VersionSupportError, 'Supported from version 3.0')
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
describe 'XML namespace' do
|
|
237
|
+
it 'uses H003 namespace' do
|
|
238
|
+
builder = factory.create_hev
|
|
239
|
+
xml = Nokogiri::XML(builder.to_xml)
|
|
240
|
+
# HEV uses H000, so check a standard request
|
|
241
|
+
builder2 = factory.create_hpb
|
|
242
|
+
xml2 = Nokogiri::XML(builder2.to_xml)
|
|
243
|
+
expect(xml2.root.namespace.href).to eq('http://www.ebics.org/H003')
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# ─── V25 (H004) ────────────────────────────────────────────
|
|
249
|
+
|
|
250
|
+
describe Epics::Factories::RequestFactory::V25 do
|
|
251
|
+
let(:version) { Epics::Keyring::VERSION_25 }
|
|
252
|
+
|
|
253
|
+
include_examples 'a base factory', Epics::Factories::RequestFactory::V25
|
|
254
|
+
include_examples 'a V2 download factory', Epics::Factories::RequestFactory::V25, 'urn:org:ebics:H004'
|
|
255
|
+
include_examples 'a V2 upload factory', Epics::Factories::RequestFactory::V25
|
|
256
|
+
|
|
257
|
+
subject(:factory) { described_class.new(client) }
|
|
258
|
+
|
|
259
|
+
describe 'V25-specific: no OrderID' do
|
|
260
|
+
it 'does not include OrderID in download requests' do
|
|
261
|
+
xml = parse(factory.create_c52(start_date, end_date))
|
|
262
|
+
expect(xml.at('//OrderID')).to be_nil
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
describe 'XML namespace' do
|
|
267
|
+
it 'uses H004 namespace' do
|
|
268
|
+
builder = factory.create_hpb
|
|
269
|
+
xml = Nokogiri::XML(builder.to_xml)
|
|
270
|
+
expect(xml.root.namespace.href).to eq('urn:org:ebics:H004')
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# ─── V3 (H005) ────────────────────────────────────────────
|
|
276
|
+
|
|
277
|
+
describe Epics::Factories::RequestFactory::V3 do
|
|
278
|
+
let(:version) { Epics::Keyring::VERSION_30 }
|
|
279
|
+
|
|
280
|
+
include_examples 'a base factory', Epics::Factories::RequestFactory::V3
|
|
281
|
+
|
|
282
|
+
subject(:factory) { described_class.new(client) }
|
|
283
|
+
|
|
284
|
+
describe 'XML namespace' do
|
|
285
|
+
it 'uses H005 namespace' do
|
|
286
|
+
builder = factory.create_hpb
|
|
287
|
+
xml = Nokogiri::XML(builder.to_xml)
|
|
288
|
+
expect(xml.root.namespace.href).to eq('urn:org:ebics:H005')
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
describe 'uses AdminOrderType instead of OrderType' do
|
|
293
|
+
it 'generates AdminOrderType for admin requests' do
|
|
294
|
+
xml = parse(factory.create_hpd)
|
|
295
|
+
expect(xml.at('//AdminOrderType').text).to eq('HPD')
|
|
296
|
+
expect(xml.at('//OrderType')).to be_nil
|
|
297
|
+
expect(xml.at('//OrderAttribute')).to be_nil
|
|
298
|
+
expect(xml.at('//OrderID')).to be_nil
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
describe 'BTD download requests' do
|
|
303
|
+
btd_downloads = {
|
|
304
|
+
'c52' => { service_name: 'STM', msg_name: 'camt.052' },
|
|
305
|
+
'c53' => { service_name: 'EOP', msg_name: 'camt.053', container_type: 'ZIP' },
|
|
306
|
+
'c54' => { service_name: 'REP', msg_name: 'camt.054', container_type: 'ZIP' },
|
|
307
|
+
'sta' => { service_name: 'EOP', msg_name: 'mt940' },
|
|
308
|
+
'vmk' => { service_name: 'STM', msg_name: 'mt942' },
|
|
309
|
+
'z52' => { service_name: 'STM', msg_name: 'camt.052', container_type: 'ZIP' },
|
|
310
|
+
'z53' => { service_name: 'EOP', msg_name: 'camt.053', container_type: 'ZIP' },
|
|
311
|
+
'z54' => { service_name: 'EOP', msg_name: 'camt.054', service_option: 'XQRR' },
|
|
312
|
+
'xek' => { service_name: 'EOP', msg_name: 'pdf', container_type: 'ZIP' },
|
|
313
|
+
'z01' => { service_name: 'PSR', msg_name: 'pain.002', service_option: 'CH003GEN' },
|
|
314
|
+
'bka' => { service_name: 'EOP', msg_name: 'camt.053', scope: 'DE' },
|
|
315
|
+
'c5n' => { service_name: 'STM', msg_name: 'camt.054', scope: 'DE', service_option: 'SCI' },
|
|
316
|
+
'cdz' => { service_name: 'REP', msg_name: 'pain.002', scope: 'DE', service_option: 'SDD' },
|
|
317
|
+
'crz' => { service_name: 'REP', msg_name: 'pain.002', scope: 'DE', service_option: 'SCT' },
|
|
318
|
+
'zsr' => { service_name: 'PSR', msg_name: 'pain.002', scope: 'BIL' },
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
btd_downloads.each do |order_type, expected|
|
|
322
|
+
it "creates #{order_type.upcase} as BTD with correct service params" do
|
|
323
|
+
xml = parse(factory.send("create_#{order_type}", start_date, end_date))
|
|
324
|
+
expect(xml.at('//AdminOrderType').text).to eq('BTD')
|
|
325
|
+
expect(xml.at('//BTDOrderParams/Service/ServiceName').text).to eq(expected[:service_name])
|
|
326
|
+
expect(xml.at('//BTDOrderParams/Service/MsgName').text).to eq(expected[:msg_name])
|
|
327
|
+
|
|
328
|
+
if expected[:scope]
|
|
329
|
+
expect(xml.at('//BTDOrderParams/Service/Scope').text).to eq(expected[:scope])
|
|
330
|
+
else
|
|
331
|
+
expect(xml.at('//BTDOrderParams/Service/Scope')).to be_nil
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
if expected[:service_option]
|
|
335
|
+
expect(xml.at('//BTDOrderParams/Service/ServiceOption').text).to eq(expected[:service_option])
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
if expected[:container_type]
|
|
339
|
+
expect(xml.at('//BTDOrderParams/Service/Container')['containerType']).to eq(expected[:container_type])
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
expect(xml.at('//AuthSignature')).not_to be_nil
|
|
343
|
+
expect(xml.at('//BankPubKeyDigests')).not_to be_nil
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
describe 'BTU upload requests' do
|
|
349
|
+
btu_uploads = {
|
|
350
|
+
'cct' => { service_name: 'SCT', msg_name: 'pain.001', scope: 'DE', filename: 'cct.pain.001.xxx.xml' },
|
|
351
|
+
'cdd' => { service_name: 'SDD', msg_name: 'pain.008', scope: 'DE', service_option: 'COR', filename: 'cdd.pain.008.xxx.xml' },
|
|
352
|
+
'cdb' => { service_name: 'SDD', msg_name: 'pain.008', service_option: 'B2B', filename: 'cdb.pain.008.xxx.xml' },
|
|
353
|
+
'cip' => { service_name: 'SCI', msg_name: 'pain.001', filename: 'cip.pain.001.xxx.xml' },
|
|
354
|
+
'xe2' => { service_name: 'MCT', msg_name: 'pain.001', filename: 'xe2.pain.001.xxx.xml' },
|
|
355
|
+
'xe3' => { service_name: 'SDD', msg_name: 'pain.008', filename: 'xe3.pain.008.xxx.xml' },
|
|
356
|
+
'yct' => { service_name: 'MCT', msg_name: 'pain.001', scope: 'BIL', filename: 'yct.pain.001.xxx.xml' },
|
|
357
|
+
'azv' => { service_name: 'XCT', msg_name: 'dtazv', scope: 'DE', filename: 'azv.dtazv.xxx.xml' },
|
|
358
|
+
'b2b' => { service_name: 'SDD', msg_name: 'pain.008', scope: 'BIL', service_option: 'B2B', filename: 'b2b.pain.008.xxx.xml' },
|
|
359
|
+
'ccs' => { service_name: 'SCT', msg_name: 'pain.001', scope: 'DE', filename: 'ccs.pain.001.xxx.xml' },
|
|
360
|
+
'cds' => { service_name: 'SDD', msg_name: 'pain.008', scope: 'BIL', filename: 'cds.pain.008.xxx.xml' },
|
|
361
|
+
'c2s' => { service_name: 'SDD', msg_name: 'pain.008', scope: 'BIL', filename: 'c2s.pain.008.xxx.xml' },
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
btu_uploads.each do |order_type, expected|
|
|
365
|
+
it "creates #{order_type.upcase} as BTU with correct service params" do
|
|
366
|
+
xml = parse(factory.send("create_#{order_type}", digest, transaction_key))
|
|
367
|
+
expect(xml.at('//AdminOrderType').text).to eq('BTU')
|
|
368
|
+
params = xml.at('//BTUOrderParams')
|
|
369
|
+
expect(params['fileName']).to eq(expected[:filename])
|
|
370
|
+
expect(params.at('Service/ServiceName').text).to eq(expected[:service_name])
|
|
371
|
+
expect(params.at('Service/MsgName').text).to eq(expected[:msg_name])
|
|
372
|
+
|
|
373
|
+
if expected[:scope]
|
|
374
|
+
expect(params.at('Service/Scope').text).to eq(expected[:scope])
|
|
375
|
+
else
|
|
376
|
+
expect(params.at('Service/Scope')).to be_nil
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
if expected[:service_option]
|
|
380
|
+
expect(params.at('Service/ServiceOption').text).to eq(expected[:service_option])
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
# V3-specific upload elements
|
|
384
|
+
expect(xml.at('//DataDigest')).not_to be_nil
|
|
385
|
+
expect(xml.at('//AdditionalOrderInfo')).not_to be_nil
|
|
386
|
+
expect(xml.at('//SignatureData')).not_to be_nil
|
|
387
|
+
expect(xml.at('//DataEncryptionInfo')).not_to be_nil
|
|
388
|
+
expect(xml.at('//AuthSignature')).not_to be_nil
|
|
389
|
+
expect(xml.at('//NumSegments').text).to eq('1')
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
describe 'VersionSupportError for V2-only types' do
|
|
395
|
+
%w[ful fdl cd1 wss xds].each do |type|
|
|
396
|
+
it "raises VersionSupportError for #{type}" do
|
|
397
|
+
expect { factory.send("create_#{type}", digest, transaction_key) }.to raise_error(Epics::VersionSupportError)
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
describe 'V3 upload includes DataDigest with correct SignatureVersion' do
|
|
403
|
+
it 'DataDigest has SignatureVersion matching user signature' do
|
|
404
|
+
xml = parse(factory.create_cct(digest, transaction_key))
|
|
405
|
+
data_digest = xml.at('//DataDigest')
|
|
406
|
+
expect(data_digest['SignatureVersion']).to eq(client.keyring.user_signature.version)
|
|
407
|
+
end
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
describe 'BTU upload override passthrough' do
|
|
411
|
+
it 'create_cct accepts service_option override' do
|
|
412
|
+
xml = parse(factory.create_cct(digest, transaction_key, service_option: 'VOO'))
|
|
413
|
+
params = xml.at('//BTUOrderParams')
|
|
414
|
+
expect(params.at('Service/ServiceName').text).to eq('SCT')
|
|
415
|
+
expect(params.at('Service/ServiceOption').text).to eq('VOO')
|
|
416
|
+
expect(params.at('Service/Scope').text).to eq('DE')
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
it 'create_cct without override has no ServiceOption' do
|
|
420
|
+
xml = parse(factory.create_cct(digest, transaction_key))
|
|
421
|
+
params = xml.at('//BTUOrderParams')
|
|
422
|
+
expect(params.at('Service/ServiceOption')).to be_nil
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
it 'create_cdd override replaces default service_option' do
|
|
426
|
+
xml = parse(factory.create_cdd(digest, transaction_key, service_option: 'NEW'))
|
|
427
|
+
params = xml.at('//BTUOrderParams')
|
|
428
|
+
expect(params.at('Service/ServiceOption').text).to eq('NEW')
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
it 'create_cdb override can change scope' do
|
|
432
|
+
xml = parse(factory.create_cdb(digest, transaction_key, scope: 'CH'))
|
|
433
|
+
params = xml.at('//BTUOrderParams')
|
|
434
|
+
expect(params.at('Service/Scope').text).to eq('CH')
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
it 'override can change filename' do
|
|
438
|
+
xml = parse(factory.create_cct(digest, transaction_key, filename: 'custom.xml'))
|
|
439
|
+
params = xml.at('//BTUOrderParams')
|
|
440
|
+
expect(params['fileName']).to eq('custom.xml')
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
end
|
|
444
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
RSpec.describe Epics::Response do
|
|
2
|
+
let(:client) do
|
|
3
|
+
Epics::Client.new(File.open(File.join(File.dirname(__FILE__), 'fixtures', 'SIZBN001.key')),
|
|
4
|
+
'secret', 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS')
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def response_with(code)
|
|
8
|
+
xml = <<~XML
|
|
9
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
10
|
+
<ebicsResponse xmlns="urn:org:ebics:H004">
|
|
11
|
+
<body><ReturnCode>#{code}</ReturnCode></body>
|
|
12
|
+
</ebicsResponse>
|
|
13
|
+
XML
|
|
14
|
+
described_class.new(client, xml)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe '#business_error?' do
|
|
18
|
+
{ '000000' => false,
|
|
19
|
+
'011000' => false, # positive acknowledgement
|
|
20
|
+
'011301' => false } # bank does not support prevalidation
|
|
21
|
+
.each do |code, expected|
|
|
22
|
+
it "treats #{code} as #{expected ? 'an error' : 'informational'}" do
|
|
23
|
+
expect(response_with(code).business_error?).to eq(expected)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Both are defined as failures in Epics::Error and share the 01 prefix with the
|
|
28
|
+
# informational codes above.
|
|
29
|
+
{ '011001' => 'negative acknowledgement received',
|
|
30
|
+
'011101' => 'segment number not reached' }.each do |code, description|
|
|
31
|
+
it "treats #{code} (#{description}) as an error" do
|
|
32
|
+
expect(response_with(code).business_error?).to be(true)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'treats an absent return code as informational' do
|
|
37
|
+
xml = '<?xml version="1.0"?><ebicsResponse xmlns="urn:org:ebics:H004"><body/></ebicsResponse>'
|
|
38
|
+
expect(described_class.new(client, xml).business_error?).to be(false)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'treats an unrelated failure code as an error' do
|
|
42
|
+
expect(response_with('091010').business_error?).to be(true)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
data/spec/response_spec.rb
CHANGED
|
@@ -89,6 +89,37 @@ RSpec.describe Epics::Response do
|
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
+
describe '#num_segments' do
|
|
93
|
+
let(:ebics_response) { File.read('spec/fixtures/xml/sta_response_continued.xml') }
|
|
94
|
+
|
|
95
|
+
it 'pulls the number of segments from the response' do
|
|
96
|
+
expect(subject.num_segments).to eq(2)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
describe 'when the number has leading zeros' do
|
|
100
|
+
let(:ebics_response) do
|
|
101
|
+
File.read('spec/fixtures/xml/sta_response_continued.xml').sub('<NumSegments>2<', '<NumSegments>09<')
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'reads it as a decimal' do
|
|
105
|
+
expect(subject.num_segments).to eq(9)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
describe 'when the number is missing' do
|
|
110
|
+
let(:ebics_response) do
|
|
111
|
+
File.read('spec/fixtures/xml/sta_response_continued.xml').sub(%r{<NumSegments>2</NumSegments>}, '')
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'raises an error naming the field' do
|
|
115
|
+
expect { subject.num_segments }.to raise_error(Epics::InvalidResponseError, /NumSegments/) do |error|
|
|
116
|
+
expect(error.field).to eq('NumSegments')
|
|
117
|
+
expect(error.cause).to be_a(ArgumentError)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
92
123
|
describe '#segmented?' do
|
|
93
124
|
describe 'when the response is segemnted' do
|
|
94
125
|
let(:ebics_response) { File.read('spec/fixtures/xml/sta_response.xml') }
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
RSpec.describe 'Epics::Response validity checks without keys' do
|
|
2
|
+
let(:client) { Epics::Client.new(nil, 'secret', 'https://example.com/ebics', 'HOST01', 'USER01', 'PARTNER01') }
|
|
3
|
+
let(:xml) { File.read(File.join(File.dirname(__FILE__), 'fixtures', 'xml', 'upload_init_response.xml')) }
|
|
4
|
+
|
|
5
|
+
subject(:response) { Epics::Response.new(client, xml) }
|
|
6
|
+
|
|
7
|
+
# A response can arrive before HPB has run, so these must say what is missing rather
|
|
8
|
+
# than fail on nil.
|
|
9
|
+
it 'reports the missing bank key when verifying a signature' do
|
|
10
|
+
expect { response.signature_valid? }
|
|
11
|
+
.to raise_error(Epics::MissingKeyError, /bank's authentication key/)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'reports the missing encryption key when comparing the public digest' do
|
|
15
|
+
expect { response.public_digest_valid? }
|
|
16
|
+
.to raise_error(Epics::MissingKeyError, /encryption key/)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# The digest is a plain SHA-256 over the authenticated nodes and needs no key at all.
|
|
20
|
+
it 'checks the digest without any key loaded' do
|
|
21
|
+
expect { response.digest_valid? }.not_to raise_error
|
|
22
|
+
end
|
|
23
|
+
end
|