epics 3.0.0.rc2 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +39 -19
- data/README.md +22 -0
- data/lib/epics/builders/order_details_builder/v3.rb +25 -1
- data/lib/epics/client.rb +1 -1
- data/lib/epics/generic_upload_request.rb +4 -8
- data/lib/epics/version.rb +1 -1
- data/spec/builders_spec.rb +54 -0
- data/spec/request_factory_spec.rb +19 -0
- data/spec/support/ebics_shared_examples.rb +4 -0
- data/spec/upload_digest_spec.rb +24 -5
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f51f635b331253de3ad314121ac6e0cf657a285415ae7811e986fb6e718649a4
|
|
4
|
+
data.tar.gz: 7889e2e42721731b46886fee4e47b20bdfb0b7a1ed892aace84886aa25edaf47
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7a9213441874971f2d932f36eb0032ef1ecc2063bc9567f5cd036c7dca596088e1e372caf3c10eb7ce0da749015781ad2838cc458433cbf684ecfacc5cc42e3f
|
|
7
|
+
data.tar.gz: 7deab543f728a21a132d63972ef8d8dcbfb659ff22ecccbf2e89f78c1b2666814475c89caace7b485168b08132a5c400bf030e2f1d34610cc6cd25c8e76dd836
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
### Unreleased
|
|
2
2
|
|
|
3
|
+
### 3.0.1
|
|
4
|
+
|
|
5
|
+
- [FIX] Upload order data was transmitted with all CR and LF removed, not as given. Any
|
|
6
|
+
content hashed by the caller no longer matched, so container uploads (e.g. `CCS`, `CDS`,
|
|
7
|
+
`C2S` with a `conxml` container whose `HashValue` covers the canonical pain message) were
|
|
8
|
+
rejected by the bank, and line breaks inside text values were lost. As in 2.x, the order
|
|
9
|
+
data is now sent unchanged and CR and LF are removed only to form the ES (electronic
|
|
10
|
+
signature) hash, as EBICS specifies; the bank removes them the same way before verifying.
|
|
11
|
+
This reverts the 3.0.0.rc1 entry "Upload order data is now normalized once"
|
|
12
|
+
|
|
13
|
+
### 3.0.0
|
|
14
|
+
|
|
15
|
+
- [FIX] H005 uploads were sent without `SignatureFlag` in `BTUOrderParams`, although they
|
|
16
|
+
carry the user's ES (electronic signature), so banks treated them as orders
|
|
17
|
+
to be authorised outside EBICS and some rejected them with `EBICS_INVALID_ORDER_TYPE`.
|
|
18
|
+
`SignatureFlag` is now set by default, matching `OZHNN` on H004. Pass `request_eds: true`
|
|
19
|
+
to spool the order into the EDS (distributed electronic signature, German VEU)
|
|
20
|
+
when signatures are still missing, or `signature_flag: false` to omit the flag
|
|
21
|
+
|
|
22
|
+
### 3.0.0.rc2
|
|
23
|
+
|
|
3
24
|
- [FIX] A download spanning several segments returned only its first segment, so zipped
|
|
4
25
|
downloads such as `C52` and `C53` raised `Zip::Error` and plain ones such as `STA` came
|
|
5
26
|
back cut off without an error. The remaining segments are now requested in the transfer
|
|
@@ -27,6 +48,24 @@ rewrite of request building into builders/factories/handlers.
|
|
|
27
48
|
- [BREAKING] On H005, `Client#HAA` and `Client#order_types` return an array of service
|
|
28
49
|
hashes (`service_name`, `scope`, `service_option`, `container`, `msg_name`) instead of
|
|
29
50
|
an array of order-type strings
|
|
51
|
+
- [BREAKING] `XEK`, `YCT` and `ZSR` raise `Epics::VersionSupportError` on H003/H004
|
|
52
|
+
instead of `NotImplementedError`, matching every other version mismatch
|
|
53
|
+
- [BREAKING] `order_id:` is validated against the EBICS `OrderIDType` range (`A000` to
|
|
54
|
+
`ZZZZ`). Values below `A000` rendered as e.g. `0002`, which violates the
|
|
55
|
+
`[A-Z][A-Z0-9]{3}` pattern; they now raise `ArgumentError`. The protocol form
|
|
56
|
+
(`order_id: 'A000'`) is accepted alongside the integer
|
|
57
|
+
- [BREAKING] Removed `Epics::Builders::MutableBuilder#add_receipt_code`, which emitted
|
|
58
|
+
`ReceiptCode` inside `mutable` where the schema does not allow it. `ReceiptCode`
|
|
59
|
+
belongs to `TransferReceipt`, which `TransferReceiptBuilder` already builds
|
|
60
|
+
- [BREAKING] Upload order data is now normalized once, on the way in, so the bytes
|
|
61
|
+
hashed for the electronic signature are the bytes transmitted. Until 3.0 the digest
|
|
62
|
+
was taken over the normalized document while the raw one was sent, which only
|
|
63
|
+
verifies against banks that normalize before checking the ES
|
|
64
|
+
- [BREAKING] Passing only one date-range bound (e.g. `client.STA(from)`) silently
|
|
65
|
+
omitted the range and fetched the bank's full retention window. Both bounds are
|
|
66
|
+
mandatory within `DateRange`, so this now raises `ArgumentError`
|
|
67
|
+
- [BREAKING] Removed `Epics::Services::CryptService#sign`, which had no callers and
|
|
68
|
+
disagreed with `#encrypt` on how an A005 signature is formed
|
|
30
69
|
|
|
31
70
|
**Fixes**
|
|
32
71
|
|
|
@@ -41,17 +80,12 @@ rewrite of request building into builders/factories/handlers.
|
|
|
41
80
|
when the key they need was not loaded; they now raise `Epics::MissingKeyError` naming
|
|
42
81
|
it. `#digest_valid?` no longer needs a key at all — it is a plain SHA-256 over the
|
|
43
82
|
authenticated nodes
|
|
44
|
-
- [BREAKING] Removed `Epics::Builders::MutableBuilder#add_receipt_code`, which emitted
|
|
45
|
-
`ReceiptCode` inside `mutable` where the schema does not allow it. `ReceiptCode`
|
|
46
|
-
belongs to `TransferReceipt`, which `TransferReceiptBuilder` already builds
|
|
47
83
|
- [FIX] Removed the `container_flag:` order parameter, which emitted a `ContainerFlag`
|
|
48
84
|
element that exists in no EBICS schema. The container is expressed by `Container`
|
|
49
85
|
with a `containerType` attribute, which `container_type:` already emits
|
|
50
86
|
- [ENHANCEMENT] Added the H005-only order types `XEK` (account statements as PDF),
|
|
51
87
|
`ZSR` (payment status reports) and `YCT` (multi-currency credit transfer). Their BTF
|
|
52
88
|
mappings existed in the V3 factory but had no order class or client method
|
|
53
|
-
- [BREAKING] `XEK`, `YCT` and `ZSR` raise `Epics::VersionSupportError` on H003/H004
|
|
54
|
-
instead of `NotImplementedError`, matching every other version mismatch
|
|
55
89
|
- [ENHANCEMENT] `XEK`, `ZSR`, `Z01`, `Z52`, `Z53` and `Z54` accept `scope:`,
|
|
56
90
|
`service_option:`, `msg_name_version:` and `container_type:`. Defaults are unchanged;
|
|
57
91
|
Swiss market practice requires a `Scope` and only `ZSR` sent one, so a bank-specific
|
|
@@ -63,11 +97,6 @@ rewrite of request building into builders/factories/handlers.
|
|
|
63
97
|
keyring slots, so a `host_id` that no longer matched the stored prefix destroyed the
|
|
64
98
|
bank's public keys on save. Unrecognised entries are now carried through unchanged,
|
|
65
99
|
and a warning names each one instead of the failure being swallowed
|
|
66
|
-
- [BREAKING] `order_id:` is validated against the EBICS `OrderIDType` range (`A000` to
|
|
67
|
-
`ZZZZ`). Values below `A000` rendered as e.g. `0002`, which violates the
|
|
68
|
-
`[A-Z][A-Z0-9]{3}` pattern; they now raise `ArgumentError`. The protocol form
|
|
69
|
-
(`order_id: 'A000'`) is accepted alongside the integer
|
|
70
|
-
|
|
71
100
|
- [FIX] `XCT` sent the wrong order type: `CD1` on H003/H004 and the DTAZV service on
|
|
72
101
|
H005, filing credit transfers as direct debits. It now sends `XCT` on H003/H004.
|
|
73
102
|
EBICS 3.0 defines no counterpart for XCT, so on H005 it raises
|
|
@@ -75,25 +104,16 @@ rewrite of request building into builders/factories/handlers.
|
|
|
75
104
|
- [FIX] The electronic signature over order data is again formed with line separators
|
|
76
105
|
removed, matching 2.x. The refactor had signed the raw document, changing the ES for
|
|
77
106
|
every upload
|
|
78
|
-
- [BREAKING] Upload order data is now normalized once, on the way in, so the bytes
|
|
79
|
-
hashed for the electronic signature are the bytes transmitted. Until 3.0 the digest
|
|
80
|
-
was taken over the normalized document while the raw one was sent, which only
|
|
81
|
-
verifies against banks that normalize before checking the ES
|
|
82
107
|
- [FIX] H005 `DataDigest` carried an RSA-PSS signature (256 bytes, non-reproducible)
|
|
83
108
|
instead of the SHA-256 hash of the order data
|
|
84
109
|
- [FIX] `Response#business_error?` treated every `01`-prefixed return code as
|
|
85
110
|
informational, reporting `011001` (negative acknowledgement) and `011101` (segment
|
|
86
111
|
number not reached) as success. It now uses an explicit allow-list
|
|
87
|
-
- [BREAKING] Passing only one date-range bound (e.g. `client.STA(from)`) silently
|
|
88
|
-
omitted the range and fetched the bank's full retention window. Both bounds are
|
|
89
|
-
mandatory within `DateRange`, so this now raises `ArgumentError`
|
|
90
112
|
- [FIX] `Time` and `DateTime` passed as date-range bounds rendered an `xs:dateTime`
|
|
91
113
|
with a local offset into an `xs:date` element; they are now coerced to a date
|
|
92
114
|
- [FIX] `C52` requested no container on H005 while `Client#C52` always unzips the
|
|
93
115
|
response, raising `Zip::Error`. `C52` and `C53` now default to a ZIP container and
|
|
94
116
|
both accept `container_type:` to override it
|
|
95
|
-
- [BREAKING] Removed `Epics::Services::CryptService#sign`, which had no callers and
|
|
96
|
-
disagreed with `#encrypt` on how an A005 signature is formed
|
|
97
117
|
- [FIX] `Epics::Client.setup` forwarded its block to `.new`, which yields before the
|
|
98
118
|
keys are generated, so the block saw an empty keyring and anything touching it —
|
|
99
119
|
`ini_letter`, `save_keys`, `INI`, `HIA` — failed. It now yields once the client is
|
data/README.md
CHANGED
|
@@ -307,6 +307,28 @@ practice requires it to be supplied (guidelines §5.2).
|
|
|
307
307
|
When it is absent the bank assumes a global definition.
|
|
308
308
|
On EBICS 2.4/2.5 these parameters have no equivalent and are ignored.
|
|
309
309
|
|
|
310
|
+
### Signatures on uploads
|
|
311
|
+
|
|
312
|
+
EBICS 3.0 replaces the order attribute (`OZHNN`, `DZHNN`) with `SignatureFlag`, which tells
|
|
313
|
+
the bank whether an upload carries the user's ES (electronic signature). Uploads always
|
|
314
|
+
include it and send `SignatureFlag` by default, the equivalent of `OZHNN`: the bank expects
|
|
315
|
+
every required signature in the request and rejects the order otherwise.
|
|
316
|
+
|
|
317
|
+
```ruby
|
|
318
|
+
# spool into the EDS (distributed electronic signature, German VEU) when signatures are
|
|
319
|
+
# still missing, e.g. for a user who needs a second signer
|
|
320
|
+
e.CCT(document, request_eds: true)
|
|
321
|
+
|
|
322
|
+
# no SignatureFlag: the order is authorised outside EBICS, e.g. by an accompanying slip
|
|
323
|
+
# or in online banking
|
|
324
|
+
e.CCT(document, signature_flag: false)
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
`signature_flag: false` only drops the flag; the user's signature is still sent.
|
|
328
|
+
|
|
329
|
+
On EBICS 2.4/2.5 both options have no effect and are silently ignored: uploads keep
|
|
330
|
+
their fixed order attribute (`OZHNN` for the payment uploads).
|
|
331
|
+
|
|
310
332
|
## Features
|
|
311
333
|
|
|
312
334
|
### Initialization
|
|
@@ -32,8 +32,22 @@ class Epics::Builders::OrderDetailsBuilder::V3 < Epics::Builders::OrderDetailsBu
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def add_btu_order_params(
|
|
35
|
-
filename:,
|
|
35
|
+
filename:,
|
|
36
|
+
service_name:,
|
|
37
|
+
msg_name:,
|
|
38
|
+
scope: nil,
|
|
39
|
+
service_option: nil,
|
|
40
|
+
container_type: nil,
|
|
41
|
+
msg_name_version: nil,
|
|
42
|
+
msg_name_variant: nil,
|
|
43
|
+
msg_name_format: nil,
|
|
44
|
+
signature_flag: true,
|
|
45
|
+
request_eds: false
|
|
36
46
|
)
|
|
47
|
+
if request_eds && !signature_flag
|
|
48
|
+
raise ArgumentError, 'request_eds requires signature_flag'
|
|
49
|
+
end
|
|
50
|
+
|
|
37
51
|
@xml.BTUOrderParams fileName: filename do |xml|
|
|
38
52
|
xml.Service do
|
|
39
53
|
xml.ServiceName service_name
|
|
@@ -46,6 +60,16 @@ class Epics::Builders::OrderDetailsBuilder::V3 < Epics::Builders::OrderDetailsBu
|
|
|
46
60
|
msg_name_attributes[:format] = msg_name_format if msg_name_format
|
|
47
61
|
xml.MsgName msg_name, msg_name_attributes
|
|
48
62
|
end
|
|
63
|
+
# Without SignatureFlag the bank treats the order as carrying no ES (electronic
|
|
64
|
+
# signature) and expects authorisation outside EBICS. requestEDS asks the bank to
|
|
65
|
+
# spool the order into the EDS (distributed electronic signature, German VEU,
|
|
66
|
+
# "Verteilte Elektronische Unterschrift") instead of rejecting it when signatures
|
|
67
|
+
# are still missing.
|
|
68
|
+
if signature_flag
|
|
69
|
+
signature_flag_attributes = {}
|
|
70
|
+
signature_flag_attributes[:requestEDS] = 'true' if request_eds
|
|
71
|
+
xml.SignatureFlag '', signature_flag_attributes
|
|
72
|
+
end
|
|
49
73
|
end
|
|
50
74
|
end
|
|
51
75
|
end
|
data/lib/epics/client.rb
CHANGED
|
@@ -724,7 +724,7 @@ class Epics::Client
|
|
|
724
724
|
data["#{host_id.upcase}.#{sig.version}"] = dump_signature(sig)
|
|
725
725
|
end
|
|
726
726
|
|
|
727
|
-
JSON.pretty_generate(data
|
|
727
|
+
JSON.pretty_generate(data)
|
|
728
728
|
end
|
|
729
729
|
|
|
730
730
|
# Keys without a certificate keep the bare-string form so key files stay readable by
|
|
@@ -3,21 +3,17 @@ class Epics::GenericUploadRequest < Epics::GenericRequest
|
|
|
3
3
|
|
|
4
4
|
def initialize(client, document, **options)
|
|
5
5
|
super(client, **options)
|
|
6
|
-
|
|
6
|
+
@document = document
|
|
7
7
|
aes_factory = Epics::Factories::Crypt::AesFactory.new
|
|
8
8
|
aes = aes_factory.create
|
|
9
9
|
@transaction_key = aes.key
|
|
10
10
|
@crypt_service = Epics::Services::CryptService.new
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
def document=(value)
|
|
16
|
-
@document = value.gsub(/\n|\r/, '')
|
|
17
|
-
end
|
|
18
|
-
|
|
13
|
+
# The ES hash excludes CR and LF; the bank strips them before verifying. The order
|
|
14
|
+
# data itself is transmitted unchanged.
|
|
19
15
|
def document_digest
|
|
20
|
-
@crypt_service.hash(document)
|
|
16
|
+
@crypt_service.hash(document.gsub(/\n|\r/, ''))
|
|
21
17
|
end
|
|
22
18
|
|
|
23
19
|
def to_transfer_xml
|
data/lib/epics/version.rb
CHANGED
data/spec/builders_spec.rb
CHANGED
|
@@ -317,6 +317,60 @@ RSpec.describe 'Builders' do
|
|
|
317
317
|
expect(container).not_to be_nil
|
|
318
318
|
expect(container['containerType']).to eq('ZIP')
|
|
319
319
|
end
|
|
320
|
+
|
|
321
|
+
it 'adds SignatureFlag after Service by default' do
|
|
322
|
+
instance = described_class::V3.new do |b|
|
|
323
|
+
b.add_btu_order_params(
|
|
324
|
+
filename: 'test.xml', service_name: 'MCT', msg_name: 'pain.001'
|
|
325
|
+
)
|
|
326
|
+
end
|
|
327
|
+
xml = parse_doc(instance)
|
|
328
|
+
params = xml.at('OrderDetails/BTUOrderParams')
|
|
329
|
+
expect(params.element_children.map(&:name)).to eq(%w[Service SignatureFlag])
|
|
330
|
+
expect(params.at('SignatureFlag')['requestEDS']).to be_nil
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
it 'sets requestEDS on SignatureFlag when request_eds is given' do
|
|
334
|
+
instance = described_class::V3.new do |b|
|
|
335
|
+
b.add_btu_order_params(
|
|
336
|
+
filename: 'test.xml',
|
|
337
|
+
service_name: 'MCT',
|
|
338
|
+
msg_name: 'pain.001',
|
|
339
|
+
request_eds: true
|
|
340
|
+
)
|
|
341
|
+
end
|
|
342
|
+
xml = parse_doc(instance)
|
|
343
|
+
params = xml.at('OrderDetails/BTUOrderParams')
|
|
344
|
+
expect(params.at('SignatureFlag')['requestEDS']).to eq('true')
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
it 'omits SignatureFlag when signature_flag is false' do
|
|
348
|
+
instance = described_class::V3.new do |b|
|
|
349
|
+
b.add_btu_order_params(
|
|
350
|
+
filename: 'test.xml',
|
|
351
|
+
service_name: 'MCT',
|
|
352
|
+
msg_name: 'pain.001',
|
|
353
|
+
signature_flag: false
|
|
354
|
+
)
|
|
355
|
+
end
|
|
356
|
+
xml = parse_doc(instance)
|
|
357
|
+
params = xml.at('OrderDetails/BTUOrderParams')
|
|
358
|
+
expect(params.at('SignatureFlag')).to be_nil
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
it 'rejects request_eds without signature_flag' do
|
|
362
|
+
expect do
|
|
363
|
+
described_class::V3.new do |b|
|
|
364
|
+
b.add_btu_order_params(
|
|
365
|
+
filename: 'test.xml',
|
|
366
|
+
service_name: 'MCT',
|
|
367
|
+
msg_name: 'pain.001',
|
|
368
|
+
signature_flag: false,
|
|
369
|
+
request_eds: true
|
|
370
|
+
)
|
|
371
|
+
end
|
|
372
|
+
end.to raise_error(ArgumentError, /request_eds/)
|
|
373
|
+
end
|
|
320
374
|
end
|
|
321
375
|
end
|
|
322
376
|
end
|
|
@@ -439,6 +439,25 @@ RSpec.describe 'RequestFactory' do
|
|
|
439
439
|
params = xml.at('//BTUOrderParams')
|
|
440
440
|
expect(params['fileName']).to eq('custom.xml')
|
|
441
441
|
end
|
|
442
|
+
|
|
443
|
+
it 'create_xe2 without override has SignatureFlag without requestEDS' do
|
|
444
|
+
xml = parse(factory.create_xe2(digest, transaction_key))
|
|
445
|
+
params = xml.at('//BTUOrderParams')
|
|
446
|
+
expect(params.at('SignatureFlag')).not_to be_nil
|
|
447
|
+
expect(params.at('SignatureFlag')['requestEDS']).to be_nil
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
it 'create_xe2 accepts request_eds override' do
|
|
451
|
+
xml = parse(factory.create_xe2(digest, transaction_key, request_eds: true))
|
|
452
|
+
params = xml.at('//BTUOrderParams')
|
|
453
|
+
expect(params.at('SignatureFlag')['requestEDS']).to eq('true')
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
it 'create_xe2 accepts signature_flag override' do
|
|
457
|
+
xml = parse(factory.create_xe2(digest, transaction_key, signature_flag: false))
|
|
458
|
+
params = xml.at('//BTUOrderParams')
|
|
459
|
+
expect(params.at('SignatureFlag')).to be_nil
|
|
460
|
+
end
|
|
442
461
|
end
|
|
443
462
|
end
|
|
444
463
|
end
|
|
@@ -469,6 +469,10 @@ RSpec.shared_examples 'a valid ebicsRequest H005 upload' do |service_name:, msg_
|
|
|
469
469
|
expect(service.at_xpath('e:MsgName', ns).text).to eq(msg_name)
|
|
470
470
|
end
|
|
471
471
|
|
|
472
|
+
it 'has SignatureFlag' do
|
|
473
|
+
expect(xml.at_xpath('//e:header/e:static/e:OrderDetails/e:BTUOrderParams/e:SignatureFlag', ns)).not_to be_nil
|
|
474
|
+
end
|
|
475
|
+
|
|
472
476
|
if scope
|
|
473
477
|
it "has Scope #{scope}" do
|
|
474
478
|
service = xml.at_xpath('//e:header/e:static/e:OrderDetails/e:BTUOrderParams/e:Service', ns)
|
data/spec/upload_digest_spec.rb
CHANGED
|
@@ -22,11 +22,18 @@ RSpec.describe 'upload order data digests' do
|
|
|
22
22
|
.not_to eq(OpenSSL::Digest.digest('sha256', document))
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
#
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
# Callers may hash the content themselves, e.g. a container's HashValue over the
|
|
26
|
+
# canonical message, so the transmitted order data must be the input as given.
|
|
27
|
+
it 'transmits the document unchanged' do
|
|
28
|
+
subject.transaction_id = 'ABC'
|
|
29
|
+
order_data = Nokogiri::XML(subject.to_transfer_xml)
|
|
30
|
+
.at_xpath('//e:OrderData', 'e' => 'urn:org:ebics:H004').text
|
|
31
|
+
compressed = Epics::Services::CryptService
|
|
32
|
+
.new
|
|
33
|
+
.decrypt_by_key(subject.transaction_key, Base64.decode64(order_data))
|
|
34
|
+
|
|
35
|
+
expect(document).to include("\n")
|
|
36
|
+
expect(Zlib::Inflate.inflate(compressed)).to eq(document)
|
|
30
37
|
end
|
|
31
38
|
|
|
32
39
|
it 'is identical for CRLF and LF encodings of the same document' do
|
|
@@ -56,6 +63,18 @@ RSpec.describe 'upload order data digests' do
|
|
|
56
63
|
.to eq(data_digest_of(order).text)
|
|
57
64
|
end
|
|
58
65
|
|
|
66
|
+
it 'transmits the document unchanged' do
|
|
67
|
+
order = Epics::CCT.new(client, document)
|
|
68
|
+
order.transaction_id = 'ABC'
|
|
69
|
+
order_data = Nokogiri::XML(order.to_transfer_xml).at_xpath('//e:OrderData', ns).text
|
|
70
|
+
compressed = Epics::Services::CryptService
|
|
71
|
+
.new
|
|
72
|
+
.decrypt_by_key(order.transaction_key, Base64.decode64(order_data))
|
|
73
|
+
|
|
74
|
+
expect(document).to include("\n")
|
|
75
|
+
expect(Zlib::Inflate.inflate(compressed)).to eq(document)
|
|
76
|
+
end
|
|
77
|
+
|
|
59
78
|
it 'is reproducible across two builds of the same document' do
|
|
60
79
|
expect(data_digest_of(Epics::CCT.new(client, document)).text)
|
|
61
80
|
.to eq(data_digest_of(Epics::CCT.new(client, document)).text)
|