├── .gitignore ├── .rspec ├── .semaphore └── semaphore.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── epics.gemspec ├── lib ├── epics.rb ├── epics │ ├── azv.rb │ ├── b2b.rb │ ├── bka.rb │ ├── c2s.rb │ ├── c52.rb │ ├── c53.rb │ ├── c54.rb │ ├── c5n.rb │ ├── ccs.rb │ ├── cct.rb │ ├── cd1.rb │ ├── cdb.rb │ ├── cdd.rb │ ├── cds.rb │ ├── cdz.rb │ ├── cip.rb │ ├── client.rb │ ├── crz.rb │ ├── error.rb │ ├── fdl.rb │ ├── ful.rb │ ├── generic_request.rb │ ├── generic_upload_request.rb │ ├── haa.rb │ ├── hac.rb │ ├── header_request.rb │ ├── hev.rb │ ├── hia.rb │ ├── hkd.rb │ ├── hpb.rb │ ├── hpd.rb │ ├── htd.rb │ ├── ini.rb │ ├── key.rb │ ├── letter_renderer.rb │ ├── middleware │ │ ├── parse_ebics.rb │ │ └── xmlsig.rb │ ├── ptk.rb │ ├── response.rb │ ├── signer.rb │ ├── sta.rb │ ├── version.rb │ ├── vmk.rb │ ├── wss.rb │ ├── x_509_certificate.rb │ ├── xct.rb │ ├── xds.rb │ ├── xe2.rb │ ├── xe3.rb │ ├── z01.rb │ ├── z52.rb │ ├── z53.rb │ └── z54.rb └── letter │ ├── ini.erb │ ├── ini_with_certs.erb │ └── locales │ ├── de.yml │ ├── en.yml │ └── fr.yml └── spec ├── .DS_Store ├── client_spec.rb ├── error_spec.rb ├── fixtures ├── SIZBN001.key ├── a006.pem ├── bank_e.pem ├── e002.pem ├── test.zip ├── test_with_general_purpose_bit_3.zip ├── x002.pem └── xml │ ├── cd1.xml │ ├── cd1_init_response.xml │ ├── cd1_transfer_response.xml │ ├── cdb.xml │ ├── cdb_init_response.xml │ ├── cdb_transfer_response.xml │ ├── cip.xml │ ├── ebics_business_nok.xml │ ├── ebics_technical_nok.xml │ ├── haa.xml │ ├── haa_receipt.xml │ ├── hia_request_order_data.xml │ ├── hpb.xml │ ├── hpb_request.xml │ ├── hpb_response_ebics_ns.xml │ ├── hpb_response_order.xml │ ├── hpb_response_order_without_ns.xml │ ├── htd_order_data.xml │ ├── htd_order_data_without_names.xml │ ├── ini_response_h004_ns.xml │ ├── jruby │ ├── hia.xml │ └── ini.xml │ ├── ruby │ ├── hia.xml │ └── ini.xml │ ├── signature_pub_key_order_data.xml │ ├── sta_response.xml │ ├── sta_response_continued.xml │ ├── swiss_credit_transfer.xml │ ├── swiss_direct_debit.xml │ └── upload_init_response.xml ├── generic_upload_spec.rb ├── hpb_spec.rb ├── key_spec.rb ├── middleware └── parse_ebics_spec.rb ├── orders ├── azv_spec.rb ├── b2b_spec.rb ├── bka_spec.rb ├── c2s_spec.rb ├── c52_spec.rb ├── c53_spec.rb ├── c54_spec.rb ├── c5n_spec.rb ├── ccs_spec.rb ├── cct_spec.rb ├── cd1_spec.rb ├── cdb_spec.rb ├── cdd_spec.rb ├── cdz_spec.rb ├── cip_spec.rb ├── crz_spec.rb ├── fdl_spec.rb ├── ful_spec.rb ├── haa_spec.rb ├── hac_spec.rb ├── hev_spec.rb ├── hia_spec.rb ├── hkd_spec.rb ├── hpb_spec.rb ├── hpd_spec.rb ├── htd_spec.rb ├── ini_spec.rb ├── ptk_spec.rb ├── sta_spec.rb ├── vmk_spec.rb ├── wss_spec.rb ├── x_509_certificate_spec.rb ├── xds_spec.rb ├── xe2_spec.rb ├── xe3_spec.rb ├── z01_spec.rb ├── z52_spec.rb ├── z53_spec.rb └── z54_spec.rb ├── response_spec.rb ├── signer_spec.rb ├── spec_helper.rb ├── support ├── ebics_matcher.rb └── x_509_crt_generator.rb └── xsd ├── ebics_H004.xsd ├── ebics_hev.xsd ├── ebics_keymgmt_request_H004.xsd ├── ebics_keymgmt_response_H004.xsd ├── ebics_orders_H004.xsd ├── ebics_request_H004.xsd ├── ebics_response_H004.xsd ├── ebics_signature.xsd ├── ebics_types_H004.xsd └── xmldsig-core-schema.xsd /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | *.bundle 11 | *.so 12 | *.o 13 | *.a 14 | mkmf.log 15 | /ebics_playground 16 | .DS_Store 17 | sbk.key 18 | /mt940 19 | *.key 20 | .idea/ -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require spec_helper 3 | -------------------------------------------------------------------------------- /.semaphore/semaphore.yml: -------------------------------------------------------------------------------- 1 | version: v1.0 2 | name: Test 3 | agent: 4 | machine: 5 | type: e1-standard-2 6 | os_image: ubuntu2004 7 | blocks: 8 | - name: Setup 9 | task: 10 | jobs: 11 | - name: "Checkout" 12 | commands: 13 | - checkout 14 | - ls 15 | - rm -f .rbenv-version .ruby-version 16 | - name: Spec versions 17 | task: 18 | jobs: 19 | - name: "3.1" 20 | commands: 21 | - checkout 22 | - sem-version ruby 3.1 23 | - cache restore 24 | - gem install bundler:2.5.19 25 | - bundle install 26 | - cache store 27 | - bundle exec rspec 28 | - name: "3.2" 29 | commands: 30 | - checkout 31 | - sem-version ruby 3.2 32 | - cache restore 33 | - gem install bundler:2.5.19 34 | - bundle install 35 | - cache store 36 | - bundle exec rspec 37 | - name: "3.3" 38 | commands: 39 | - checkout 40 | - sem-version ruby 3.3 41 | - cache restore 42 | - gem install bundler:2.5.19 43 | - bundle install 44 | - cache store 45 | - bundle exec rspec 46 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### Unreleased 2 | 3 | ### 2.11.0 4 | 5 | - [ENHANCEMENT] Added FUL order type (thanks to @scollon-pl) 6 | 7 | ### 2.10.0 8 | 9 | - [ENHANCEMENT] Added X.509 certificates support for INI and HIA (thanks to @vnoviskyi) 10 | - [ENHANCEMENT] Added Z01 order type (thanks to @Nymuxyzo) 11 | 12 | ### 2.9.0 13 | 14 | - [ENHANCEMENT] Added HEV order type (thanks to @jplot) 15 | 16 | ### 2.8.0 17 | 18 | - [ENHANCEMENT] Added BKA order type 19 | 20 | ### 2.7.0 21 | 22 | - [ENHANCEMENT] Added FDL order type (thanks to @frantisekrokusek) 23 | - [ENHANCEMENT] Added support for configuring locale and client/product name on initialization (thanks to @frantisekrokusek) 24 | 25 | ### 2.6.0 26 | 27 | - [ENHANCEMENT] Added CIP order type (instant transfers) 28 | - [ENHANCEMENT] Added gem metadata (thanks to @Nymuxyzo) 29 | 30 | ### 2.5.0 31 | 32 | - [HOUSEKEEPING] Bump XML dependency requirements to more recent versions 33 | - [HOUSEKEEPING] Bump bundler version to 2.5.19 34 | - [HOUSEKEEPING] Bump ruby required version from 2.7 to 3.1 35 | - [ENHANCEMENT] Request Header generation more generalized (thanks to @jplot) 36 | - [ENHANCEMENT] Multi language support for initialization letter (thanks to @jplot) 37 | - [ENHANCEMENT] Added support for WSS and C5N order types (thanks to @kostja93) 38 | 39 | ### 2.4.0 40 | 41 | - [ENHANCEMENT] Adds XE2 and XE3 order type (CCT and CDD for swiss banks) 42 | 43 | ### 2.3.0 44 | 45 | - [ENHANCEMENT] Adds Z52, Z53, Z54 order type (C52, C53, C54 for swiss banks) 46 | 47 | ### 2.2.0 48 | 49 | - [ENHANCEMENT] Adds C2S order type 50 | - [HOUSEKEEPING] updates nokogiri dependency 51 | - [HOUSEKEEPING] updates rexml dependency 52 | - [HOUSEKEEPING] adds Ruby 3.3 to CI 53 | 54 | ### 2.1.2 55 | 56 | - [BUGFIX] Fix order data encryption for OpenSSL 3 57 | 58 | ### 2.1.1 59 | 60 | - [HOUSEKEEPING] update Bank public key initialization for OpenSSL 3 61 | 62 | ### 2.1.0 63 | 64 | - [HOUSEKEEPING] updates Nokogiri dependencies 65 | - [HOUSEKEEPING] updates Bundler dependency 66 | - [HOUSEKEEPING] updates Gemfile bundler version 67 | - [HOUSEKEEPING] Bump ruby required version from 2.6 to 2.7 68 | 69 | ### 2.0.0 70 | - [BUGFIX] Add Openssl 3.0 support 71 | - [BUGFIX] Update CDZ to download data, not upload it 72 | - [BUGFIX] Support signature for keys later than 2048 bit 73 | - [HOUSEKEEPING] Open rubyzip dependency to allow newer versions and update it 74 | - [HOUSEKEEPING] Update supported ruby versions to 2.6+ 75 | - [HOUSEKEEPING] Update faraday, nokogiri, and development dependencies 76 | - [HOUSEKEEPING] Remove JRuby test execution due to failing tests - needs to be re-added if required 77 | - [ENHANCEMENT] Adds CRZ order type 78 | - [ENHANCEMENT] Make date period optional for CDZ order type 79 | 80 | ### 1.8.1 81 | - [BUGFIX] Remove masking of transport client errors 82 | 83 | ### 1.8.0 84 | 85 | - [HOUSEKEEPING] updates faraday and rubyzip 86 | - [HOUSEKEEPING] as a result: bump required ruby version to 2.4+ 87 | 88 | ### 1.7.2 89 | 90 | - [FEATURE] adds XCT order type (thanks to @punkle64) 91 | 92 | ### 1.7.1 93 | 94 | - [HOUSEKEEPING] sets headers for requests to text/xml 95 | - [HOUSEKEEPING] updates Nokogiri dependencies 96 | 97 | ### 1.7.0 98 | 99 | - [ENHANCEMENT] adds CDB (thanks to @romanlehnert) 100 | - [BUGFIX] fixes CCS order type and attribute (thanks to @gadimbaylisahil) 101 | - [BUGFIX] make CDZ callable via client 102 | 103 | ### 1.6.0 104 | 105 | - [BUGFIX] allow unstreamable zipfile handling 106 | - [ENHANCEMENT] adds CDZ order type 107 | - updates dependencies 108 | 109 | ### 1.5.2 110 | 111 | - [COMPATIBILITY] be removing the `goyku` dependency we're more recilent against old versions of that gem 112 | - [ENHANCEMENT] #order_type gives you more complete overview which order types to current client is entitled 113 | to use, there was already `HAA` which isn't as complete as this, which gets its info from `HTD` 114 | 115 | ### 1.5.1 116 | 117 | - [ENHANCEMENT] some banks are not returning the order_id in the second upload phase, we now fetch it already 118 | from the first response to handle this different behaviour. 119 | - [ENHANCEMENT] New order types: `AZV` (Auslandszahlungsverkehr). `CDS` and `CCS` for submitting SEPA credits/debits 120 | as SRZ (Service Rechen Zentrum) 121 | 122 | ### 1.5.0 123 | 124 | - [ENHANCEMENT] support for fetching the C54 order type 125 | - [ENHANCEMENT] Exceptions expose their internal code via `code` 126 | - [HOUSEKEEPING] Added Ruby 2.4 compatibility 127 | - [HOUSEKEEPING] Drop Ruby 2.0.0 128 | 129 | ### 1.4.1 130 | 131 | - [ENHANCEMENT] support for fetching the VMK order type 132 | 133 | ### 1.4.0 134 | 135 | - [ENHANCEMENT] STA without date range to fetch all statements which have not yet been fetched 136 | - [ENHANCEMENT] HAC without date range to fetch all transaction logs which have not yet been fetched 137 | 138 | ### 1.3.1 139 | 140 | - [ENHANCEMENT] make xpath namespaces explicit, so we can cover a wider 141 | rage of responses 142 | 143 | ### 1.3.0 144 | 145 | - [BUGFIX] unzip C5X payloads 146 | - [ENHANCEMENT] B2B direct debits 147 | 148 | ### 1.2.2 149 | 150 | - [BUGFIX] HPB namespaces are unpredictable so be ignore them 151 | 152 | ### 1.2.1 153 | 154 | - [BUGFIX] fixing wrong variable bind within `credit`, `debit` and `statements` 155 | 156 | ### 1.2.0 157 | 158 | - [ENHANCEMENT] uploads will return both ebics_order_id and ebics_transaction_id 159 | 160 | ### 1.1.2 161 | 162 | - [BUGFIX] missing require statements for `zlib` 163 | - [BUGFIX] #16 `setup` tried to initialize wrong class 164 | 165 | ### 1.1.1 166 | 167 | - [BUGFIX] CCT order was submited as CD1 168 | - [BUGFIX] padding was calculated against the wrong block size 169 | - [BUGFIX] double encoding of the signature 170 | 171 | ### 1.1.0 172 | 173 | - [BUGFIX] Sending `Receipts` after downloading data, to circumvent download locks 174 | - [BUGFIX] adding missing require statements 175 | - adding HAC, HKD, C52 and C53 support 176 | - less verbose object inspection for `Epics::Client` 177 | - readme polishing 178 | 179 | ### 1.0.0 180 | 181 | - first release 182 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Individual Contributor Non-Exclusive License Agreement 2 | 3 | Note: This CLA is for Individual Copyright owner only. If You would like to submit your Contribution as part of your employment or as Legal Entity, please contact Us at team@railslove.com first. 4 | 5 | Thank you for your interest in contributing to the project **„epics - EBICS client for Ruby“ from Railslove GmbH, An der Bottmuehle 5, 50678 Cologne, Germany (“We” or “Us”).** 6 | The purpose of this contributor agreement (**“Agreement”**) is to clarify and document the rights granted by contributors to Us. 7 | 8 | ### 1. DEFINITIONS 9 | **“You”** means the Individual Copyright owner who submits a Contribution to Us. If You are either a Legal Entity or submit the Contribution as part of your employment, please contact Us at team@railslove.com first. 10 | **“Contribution”** means any original work of authorship (software and/or documentation) including any modifications or additions to an existing work, Submitted by You to Us, in which You own the Copyright. If You do not own the Copyright in the entire work of authorship, please contact Us at team@railslove.com. 11 | **“Copyright”** means all rights protecting works of authorship owned or controlled by You, including copyright, moral and neighboring rights, as appropriate, for the full term of their existence including any extensions by You. 12 | **“Material”** means the software or documentation made available by Us to third parties. When this Agreement covers more than one software project, the Material means the software or documentation to which the Contribution was Submitted. After You Submit the Contribution, it may be included in the Material. 13 | **“Submit”** means any form of physical, electronic, or written communication sent to Us, including but not limited to electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, Us, but excluding communication that is conspicuously marked or otherwise designated in writing by You as “Not a Contribution.” 14 | **“Submission Date”** means the date You Submit a Contribution to Us. 15 | **“Documentation”** means any non-software portion of a Contribution. 16 | 17 | ### 2. LICENSE GRANT 18 | 2.1 Copyright License to Us 19 | Subject to the terms and conditions of this Agreement, You hereby grant to Us a worldwide, royalty-free, NON-exclusive, perpetual and irrevocable license, with the right to transfer an unlimited number of non-exclusive licenses or to grant sublicenses to third parties, under the Copyright covering the Contribution to use the Contribution by all means, including, but not limited to: 20 | - to publish the Contribution, 21 | - to modify the Contribution, to prepare derivative works based upon or containing the Contribution and to combine the Contribution with other software code, 22 | - to reproduce the Contribution in original or modified form, 23 | - to distribute, to make the Contribution available to the public, display and publicly perform the Contribution in original or modified form. 24 | 25 | 2.2 Moral Rights remain unaffected to the extent they are recognized and not waivable by applicable law. Notwithstanding, You may add your name in the header of the source code files of Your Contribution and We will respect this attribution when using Your Contribution. 26 | 27 | ### 3. DISCLAIMER 28 | THE CONTRIBUTION IS PROVIDED “AS IS”. MORE PARTICULARLY, ALL EXPRESS OR IMPLIED WARRANTIES INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY DISCLAIMED BY YOU TO US AND BY US TO YOU. TO THE EXTENT THAT ANY SUCH WARRANTIES CANNOT BE DISCLAIMED, SUCH WARRANTY IS LIMITED IN DURATION TO THE MINIMUM PERIOD PERMITTED BY LAW. 29 | 30 | ### 4. Consequential Damage Waiver 31 | TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL YOU OR US BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF ANTICIPATED SAVINGS, LOSS OF DATA, INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL AND EXEMPLARY DAMAGES ARISING OUT OF THIS AGREEMENT REGARDLESS OF THE LEGAL OR EQUITABLE THEORY (CONTRACT, TORT OR OTHERWISE) UPON WHICH THE CLAIM IS BASED. 32 | 33 | ### 5. Approximation of Disclaimer and Damage Waiver 34 | IF THE DISCLAIMER AND DAMAGE WAIVER MENTIONED IN SECTION 3 AND SECTION 4 CANNOT BE GIVEN LEGAL EFFECT UNDER APPLICABLE LOCAL LAW, REVIEWING COURTS SHALL APPLY LOCAL LAW THAT MOST CLOSELY APPROXIMATES AN ABSOLUTE WAIVER OF ALL CIVIL LIABILITY IN CONNECTION WITH THE CONTRIBUTION. 35 | 36 | ### 6. Term 37 | 6.1 This Agreement shall come into effect upon Your acceptance of the terms and conditions. 38 | 6.2 In the event of a termination of this Agreement Sections 3, 4, 5, 6 and 7 shall survive such termination and shall remain in full force thereafter. For the avoidance of doubt, Contributions that are already licensed under a free and open source license at the date of the termination shall remain in full force after the termination of this Agreement. 39 | 40 | ### 7. Miscellaneous 41 | 7.1 This Agreement and all disputes, claims, actions, suits or other proceedings arising out of this agreement or relating in any way to it shall be governed by the laws of Germany excluding its private international law provisions. 42 | 7.2 This Agreement sets out the entire agreement between You and Us for Your Contributions to Us and overrides all other agreements or understandings. 43 | 7.3 If any provision of this Agreement is found void and unenforceable, such provision will be replaced to the extent possible with a provision that comes closest to the meaning of the original provision and that is enforceable. The terms and conditions set forth in this Agreement shall apply notwithstanding any failure of essential purpose of this Agreement or any limited remedy to the maximum extent possible under law. 44 | 7.4 You agree to notify Us of any facts or circumstances of which you become aware that would make this Agreement inaccurate in any respect. 45 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in epics.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require 'rspec/core/rake_task' 3 | 4 | RSpec::Core::RakeTask.new(:spec) 5 | 6 | task default: :spec 7 | 8 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require "bundler/setup" 5 | require "epics" 6 | 7 | require "irb" 8 | IRB.start(__FILE__) 9 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install -------------------------------------------------------------------------------- /epics.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | lib = File.expand_path('lib', __dir__) 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 5 | require 'epics/version' 6 | 7 | Gem::Specification.new do |spec| 8 | spec.name = 'epics' 9 | spec.version = Epics::VERSION 10 | spec.authors = ['Lars Brillert'] 11 | spec.email = ['lars@railslove.com'] 12 | spec.summary = 'a ruby implementation of the EBICS protocol' 13 | spec.description = <<-description 14 | Epics is a ruby implementation of the EBIC standard (H004) 15 | 16 | It supports the complete initialization process comprising INI, HIA and HPB 17 | including the INI letter generation. 18 | 19 | Furthermore it offers support for the most common download types: 20 | STA HAA HTD HPD PKT HAC HKD C52 C53 C54 21 | 22 | And the following upload orders: 23 | CD1 CDD CCT CDB CDS CCS CDZ CRZ 24 | description 25 | 26 | spec.homepage = 'https://github.com/railslove/epics' 27 | spec.license = 'LGPL-3.0' 28 | 29 | spec.required_ruby_version = '>= 3.1' 30 | 31 | spec.files = `git ls-files -z`.split("\x0") 32 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 33 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 34 | spec.require_paths = ['lib'] 35 | 36 | spec.metadata['changelog_uri'] = 'https://github.com/railslove/epics/blob/master/CHANGELOG.md' 37 | spec.metadata['source_code_uri'] = 'https://github.com/railslove/epics' 38 | spec.metadata['bug_tracker_uri'] = 'https://github.com/railslove/epics/issues' 39 | 40 | spec.post_install_message = "\n\e[32m" + ('*' * 60) + "\n\e[0m" 41 | spec.post_install_message += "Thanks for using Epics - your epic EBICS client!\n" 42 | spec.post_install_message += "Epics provides a full production-tested implementation of the Electronic Banking Internet Communication Standard.\n" 43 | spec.post_install_message += "Railslove as the maintainer is commited to provide extensive developer tools to make integrating financial institutions fun and easy.\n" 44 | spec.post_install_message += "Please create an issue on github (railslove/epics) if anything does not work as expected. And contact team@railslove.com if you are looking for support with your integration.\n" 45 | spec.post_install_message += "\e[32m" + ('*' * 60) + "\n\e[0m" 46 | 47 | spec.add_dependency 'base64' 48 | spec.add_dependency 'bigdecimal' 49 | spec.add_dependency 'faraday', '>= 1.10.0' 50 | spec.add_dependency 'i18n', '>= 1.1.0' 51 | spec.add_dependency 'nokogiri', '>= 1.16.7' 52 | spec.add_dependency 'rubyzip', '>= 2.3.2' 53 | spec.add_dependency 'rexml', '>= 3.3.7' 54 | 55 | spec.add_development_dependency 'bundler', '>= 2.5.19' 56 | spec.add_development_dependency 'equivalent-xml' 57 | spec.add_development_dependency 'pry' 58 | spec.add_development_dependency 'rake', '~> 13.0' 59 | spec.add_development_dependency 'rspec' 60 | spec.add_development_dependency 'webmock' 61 | end 62 | -------------------------------------------------------------------------------- /lib/epics.rb: -------------------------------------------------------------------------------- 1 | require 'openssl' 2 | require 'base64' 3 | require 'erb' 4 | require 'i18n' 5 | require 'json' 6 | require 'zlib' 7 | require 'zip' 8 | require 'nokogiri' 9 | require 'faraday' 10 | require 'securerandom' 11 | require 'time' 12 | require "epics/version" 13 | require "epics/key" 14 | require "epics/response" 15 | require "epics/error" 16 | require 'epics/letter_renderer' 17 | require "epics/middleware/xmlsig" 18 | require "epics/middleware/parse_ebics" 19 | require "epics/generic_request" 20 | require "epics/generic_upload_request" 21 | require "epics/header_request" 22 | require "epics/azv" 23 | require "epics/hpb" 24 | require "epics/hkd" 25 | require "epics/htd" 26 | require "epics/haa" 27 | require "epics/sta" 28 | require "epics/fdl" 29 | require "epics/ful" 30 | require "epics/vmk" 31 | require "epics/bka" 32 | require "epics/c52" 33 | require "epics/c53" 34 | require "epics/c54" 35 | require "epics/c5n" 36 | require "epics/z01" 37 | require "epics/z52" 38 | require "epics/z53" 39 | require "epics/z54" 40 | require "epics/ptk" 41 | require "epics/hac" 42 | require "epics/wss" 43 | require "epics/hpd" 44 | require "epics/cd1" 45 | require "epics/cct" 46 | require "epics/ccs" 47 | require "epics/cip" 48 | require "epics/cdb" 49 | require "epics/cdd" 50 | require "epics/xe2" 51 | require "epics/xe3" 52 | require "epics/b2b" 53 | require "epics/xds" 54 | require "epics/cds" 55 | require "epics/c2s" 56 | require "epics/cdz" 57 | require "epics/crz" 58 | require "epics/xct" 59 | require "epics/hia" 60 | require "epics/ini" 61 | require "epics/hev" 62 | require "epics/signer" 63 | require "epics/x_509_certificate" 64 | require "epics/client" 65 | 66 | I18n.load_path += Dir[File.join(File.dirname(__FILE__), 'letter/locales', '*.yml')] 67 | 68 | module Epics 69 | DEFAULT_PRODUCT_NAME = 'EPICS - a ruby ebics kernel' 70 | DEFAULT_LOCALE = :de 71 | end 72 | 73 | Ebics = Epics 74 | -------------------------------------------------------------------------------- /lib/epics/azv.rb: -------------------------------------------------------------------------------- 1 | class Epics::AZV < Epics::GenericUploadRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'CD1', 7 | order_attribute: 'OZHNN', 8 | order_params: {}, 9 | num_segments: 1, 10 | mutable: { TransactionPhase: 'Initialisation' } 11 | ) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/epics/b2b.rb: -------------------------------------------------------------------------------- 1 | class Epics::B2B < Epics::GenericUploadRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'B2B', 7 | order_attribute: 'OZHNN', 8 | order_params: {}, 9 | num_segments: 1, 10 | mutable: { TransactionPhase: 'Initialisation' } 11 | ) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/epics/bka.rb: -------------------------------------------------------------------------------- 1 | class Epics::BKA < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'BKA', 7 | order_attribute: 'DZHNN', 8 | order_params: { 9 | DateRange: { 10 | Start: options[:from], 11 | End: options[:to] 12 | } 13 | }, 14 | mutable: { TransactionPhase: 'Initialisation' } 15 | ) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/epics/c2s.rb: -------------------------------------------------------------------------------- 1 | class Epics::C2S < Epics::GenericUploadRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'C2S', 7 | order_attribute: 'DZHNN', 8 | order_params: {}, 9 | num_segments: 1, 10 | mutable: { TransactionPhase: 'Initialisation' } 11 | ) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/epics/c52.rb: -------------------------------------------------------------------------------- 1 | class Epics::C52 < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'C52', 7 | order_attribute: 'DZHNN', 8 | order_params: { 9 | DateRange: { 10 | Start: options[:from], 11 | End: options[:to] 12 | } 13 | }, 14 | mutable: { TransactionPhase: 'Initialisation' } 15 | ) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/epics/c53.rb: -------------------------------------------------------------------------------- 1 | class Epics::C53 < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'C53', 7 | order_attribute: 'DZHNN', 8 | order_params: { 9 | DateRange: { 10 | Start: options[:from], 11 | End: options[:to] 12 | } 13 | }, 14 | mutable: { TransactionPhase: 'Initialisation' } 15 | ) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/epics/c54.rb: -------------------------------------------------------------------------------- 1 | class Epics::C54 < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'C54', 7 | order_attribute: 'DZHNN', 8 | order_params: { 9 | DateRange: { 10 | Start: options[:from], 11 | End: options[:to] 12 | } 13 | }, 14 | mutable: { TransactionPhase: 'Initialisation' } 15 | ) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/epics/c5n.rb: -------------------------------------------------------------------------------- 1 | class Epics::C5N < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'C5N', 7 | order_attribute: 'DZHNN', 8 | order_params: { 9 | DateRange: { 10 | Start: options[:from], 11 | End: options[:to] 12 | } 13 | }, 14 | mutable: { TransactionPhase: 'Initialisation' } 15 | ) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/epics/ccs.rb: -------------------------------------------------------------------------------- 1 | class Epics::CCS < Epics::GenericUploadRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'CCS', 7 | order_attribute: 'DZHNN', 8 | order_params: {}, 9 | num_segments: 1, 10 | mutable: { TransactionPhase: 'Initialisation' } 11 | ) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/epics/cct.rb: -------------------------------------------------------------------------------- 1 | class Epics::CCT < Epics::GenericUploadRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'CCT', 7 | order_attribute: 'OZHNN', 8 | order_params: {}, 9 | num_segments: 1, 10 | mutable: { TransactionPhase: 'Initialisation' } 11 | ) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/epics/cd1.rb: -------------------------------------------------------------------------------- 1 | class Epics::CD1 < Epics::GenericUploadRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'CD1', 7 | order_attribute: 'OZHNN', 8 | order_params: {}, 9 | num_segments: 1, 10 | mutable: { TransactionPhase: 'Initialisation' } 11 | ) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/epics/cdb.rb: -------------------------------------------------------------------------------- 1 | class Epics::CDB < Epics::GenericUploadRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'CDB', 7 | order_attribute: 'OZHNN', 8 | order_params: {}, 9 | num_segments: 1, 10 | mutable: { TransactionPhase: 'Initialisation' } 11 | ) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/epics/cdd.rb: -------------------------------------------------------------------------------- 1 | class Epics::CDD < Epics::GenericUploadRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'CDD', 7 | order_attribute: 'OZHNN', 8 | order_params: {}, 9 | num_segments: 1, 10 | mutable: { TransactionPhase: 'Initialisation' } 11 | ) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/epics/cds.rb: -------------------------------------------------------------------------------- 1 | class Epics::CDS < Epics::GenericUploadRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'CDS', 7 | order_attribute: 'DZHNN', 8 | order_params: {}, 9 | num_segments: 1, 10 | mutable: { TransactionPhase: 'Initialisation' } 11 | ) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/epics/cdz.rb: -------------------------------------------------------------------------------- 1 | class Epics::CDZ < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'CDZ', 7 | order_attribute: 'DZHNN', 8 | order_params: !!options[:from] && !!options[:to] ? { 9 | DateRange: { 10 | Start: options[:from], 11 | End: options[:to] 12 | } 13 | } : {}, 14 | mutable: { TransactionPhase: 'Initialisation' } 15 | ) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/epics/cip.rb: -------------------------------------------------------------------------------- 1 | class Epics::CIP < Epics::GenericUploadRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'CIP', 7 | order_attribute: 'OZHNN', 8 | order_params: {}, 9 | num_segments: 1, 10 | mutable: { TransactionPhase: 'Initialisation' } 11 | ) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/epics/crz.rb: -------------------------------------------------------------------------------- 1 | class Epics::CRZ < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'CRZ', 7 | order_attribute: 'DZHNN', 8 | order_params: !!options[:from] && !!options[:to] ? { 9 | DateRange: { 10 | Start: options[:from], 11 | End: options[:to] 12 | } 13 | } : {}, 14 | mutable: { TransactionPhase: 'Initialisation' } 15 | ) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/epics/fdl.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Epics::FDL < Epics::GenericRequest 4 | def header 5 | fdl_order_params = Hash.new.tap do |params| 6 | params[:DateRange] = { 7 | Start: options[:from], 8 | End: options[:to], 9 | } if options[:from] && options[:to] 10 | params[:FileFormat] = options[:file_format] 11 | end 12 | 13 | client.header_request.build( 14 | nonce: nonce, 15 | timestamp: timestamp, 16 | order_type: 'FDL', 17 | order_attribute: 'DZHNN', 18 | order_id: 'A00A', 19 | custom_order_params: { FDLOrderParams: fdl_order_params }, 20 | mutable: { TransactionPhase: 'Initialisation' } 21 | ) 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/epics/ful.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Epics::FUL < Epics::GenericUploadRequest 4 | def header 5 | ful_order_params = Hash.new.tap do |params| 6 | params[:FileFormat] = options[:file_format] 7 | end 8 | 9 | client.header_request.build( 10 | nonce: nonce, 11 | timestamp: timestamp, 12 | order_type: 'FUL', 13 | order_attribute: 'DZHNN', 14 | custom_order_params: { FULOrderParams: ful_order_params }, 15 | mutable: { TransactionPhase: 'Initialisation' } 16 | ) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/epics/generic_request.rb: -------------------------------------------------------------------------------- 1 | class Epics::GenericRequest 2 | extend Forwardable 3 | attr_reader :client, :options 4 | attr_accessor :transaction_id 5 | 6 | def initialize(client, **options) 7 | @client = client 8 | @options = options 9 | end 10 | 11 | def nonce 12 | SecureRandom.hex(16) 13 | end 14 | 15 | def timestamp 16 | Time.now.utc.iso8601 17 | end 18 | 19 | def_delegators :client, :host_id, :user_id, :partner_id 20 | 21 | def root 22 | "ebicsRequest" 23 | end 24 | 25 | def body 26 | Nokogiri::XML::Builder.new do |xml| 27 | xml.body 28 | end.doc.root 29 | end 30 | 31 | def header 32 | raise NotImplementedError 33 | end 34 | 35 | def auth_signature 36 | Nokogiri::XML::Builder.new do |xml| 37 | xml.AuthSignature{ 38 | xml.send('ds:SignedInfo') { 39 | xml.send('ds:CanonicalizationMethod', '', Algorithm: "http://www.w3.org/TR/2001/REC-xml-c14n-20010315") 40 | xml.send('ds:SignatureMethod', '', Algorithm: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256") 41 | xml.send('ds:Reference', '', URI: "#xpointer(//*[@authenticate='true'])") { 42 | xml.send('ds:Transforms') { 43 | xml.send('ds:Transform', '', Algorithm: "http://www.w3.org/TR/2001/REC-xml-c14n-20010315") 44 | } 45 | xml.send('ds:DigestMethod', '', Algorithm: "http://www.w3.org/2001/04/xmlenc#sha256") 46 | xml.send('ds:DigestValue', '') 47 | } 48 | } 49 | xml.send('ds:SignatureValue', '') 50 | } 51 | end.doc.root 52 | end 53 | 54 | def to_transfer_xml 55 | Nokogiri::XML::Builder.new do |xml| 56 | xml.send(root, 'xmlns:ds' => 'http://www.w3.org/2000/09/xmldsig#', 'xmlns' => 'urn:org:ebics:H004', 'Version' => 'H004', 'Revision' => '1') { 57 | xml.header(authenticate: true) { 58 | xml.static { 59 | xml.HostID host_id 60 | xml.TransactionID transaction_id 61 | } 62 | xml.mutable { 63 | xml.TransactionPhase 'Transfer' 64 | xml.SegmentNumber(1, lastSegment: true) 65 | } 66 | } 67 | xml.parent.add_child(auth_signature) 68 | xml.body { 69 | xml.DataTransfer { 70 | xml.OrderData encrypted_order_data 71 | } 72 | } 73 | } 74 | end.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML, encoding: 'utf-8') 75 | end 76 | 77 | def to_receipt_xml 78 | Nokogiri::XML::Builder.new do |xml| 79 | xml.send(root, 'xmlns:ds' => 'http://www.w3.org/2000/09/xmldsig#', 'xmlns' => 'urn:org:ebics:H004', 'Version' => 'H004', 'Revision' => '1') { 80 | xml.header(authenticate: true) { 81 | xml.static { 82 | xml.HostID host_id 83 | xml.TransactionID(transaction_id) 84 | } 85 | xml.mutable { 86 | xml.TransactionPhase 'Receipt' 87 | } 88 | } 89 | xml.parent.add_child(auth_signature) 90 | xml.body { 91 | xml.TransferReceipt(authenticate: true) { 92 | xml.ReceiptCode 0 93 | } 94 | } 95 | } 96 | end.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML, encoding: 'utf-8') 97 | end 98 | 99 | def to_xml 100 | Nokogiri::XML::Builder.new do |xml| 101 | xml.send(root, 'xmlns:ds' => 'http://www.w3.org/2000/09/xmldsig#', 'xmlns' => 'urn:org:ebics:H004', 'Version' => 'H004', 'Revision'=> '1') { 102 | xml.parent.add_child(header) 103 | xml.parent.add_child(auth_signature) 104 | xml.parent.add_child(body) 105 | } 106 | end.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML, encoding: 'utf-8') 107 | end 108 | 109 | private 110 | 111 | def x509_data_xml(xml, x_509_certificate) 112 | return unless x_509_certificate 113 | 114 | xml.send('ds:X509Data') do 115 | xml.send('ds:X509IssuerSerial') do 116 | xml.send('ds:X509IssuerName', x_509_certificate.issuer) 117 | xml.send('ds:X509SerialNumber', x_509_certificate.version) 118 | end 119 | xml.send('ds:X509Certificate', x_509_certificate.data) 120 | end 121 | end 122 | end 123 | -------------------------------------------------------------------------------- /lib/epics/generic_upload_request.rb: -------------------------------------------------------------------------------- 1 | class Epics::GenericUploadRequest < Epics::GenericRequest 2 | attr_accessor :key 3 | attr_accessor :iv 4 | attr_accessor :document 5 | 6 | def initialize(client, document, **options) 7 | super(client, **options) 8 | self.document = document 9 | self.key = cipher.random_key 10 | self.iv = 0.chr * cipher.iv_len 11 | end 12 | 13 | def cipher 14 | @cipher ||= OpenSSL::Cipher.new("aes-128-cbc").tap { |cipher| cipher.encrypt } 15 | end 16 | 17 | def digester 18 | @digester ||= OpenSSL::Digest::SHA256.new 19 | end 20 | 21 | def body 22 | Nokogiri::XML::Builder.new do |xml| 23 | xml.body { 24 | xml.DataTransfer { 25 | xml.DataEncryptionInfo(authenticate: true) { 26 | xml.EncryptionPubKeyDigest(client.bank_e.public_digest, Version: 'E002', Algorithm: "http://www.w3.org/2001/04/xmlenc#sha256") 27 | xml.TransactionKey Base64.encode64(client.bank_e.key.public_encrypt(self.key)).gsub(/\n/,'') 28 | } 29 | xml.SignatureData(encrypted_order_signature, authenticate: true) 30 | } 31 | } 32 | end.doc.root 33 | end 34 | 35 | def order_signature 36 | Nokogiri::XML::Builder.new do |xml| 37 | xml.UserSignatureData('xmlns' => 'http://www.ebics.org/S001', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation' => 'http://www.ebics.org/S001 http://www.ebics.org/S001/ebics_signature.xsd') { 38 | xml.OrderSignatureData { 39 | xml.SignatureVersion "A006" 40 | xml.SignatureValue signature_value 41 | xml.PartnerID partner_id 42 | xml.UserID user_id 43 | } 44 | } 45 | end.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML, encoding: 'utf-8') 46 | end 47 | 48 | def signature_value 49 | client.a.sign( digester.digest(document.gsub(/\n|\r/, "")) ) 50 | end 51 | 52 | def encrypt(d) 53 | cipher.reset 54 | cipher.padding = 0 55 | cipher.key = self.key 56 | cipher.iv = self.iv 57 | (cipher.update(pad(d)) + cipher.final) 58 | end 59 | 60 | def encrypted_order_data 61 | dst = Zlib::Deflate.deflate(document) 62 | 63 | Base64.encode64(encrypt(dst)).gsub(/\n/,'') 64 | end 65 | 66 | def encrypted_order_signature 67 | dst = Zlib::Deflate.deflate(order_signature) 68 | 69 | Base64.encode64(encrypt(dst)).gsub(/\n/,'') 70 | end 71 | 72 | def pad(d) 73 | len = cipher.block_size*((d.size / cipher.block_size)+1) 74 | 75 | d.ljust(len, [0].pack("C*")).tap do |padded| 76 | padded[-1] = [len - d.size].pack("C*") 77 | end 78 | end 79 | 80 | end 81 | -------------------------------------------------------------------------------- /lib/epics/haa.rb: -------------------------------------------------------------------------------- 1 | class Epics::HAA < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'HAA', 7 | order_attribute: 'DZHNN', 8 | order_params: {}, 9 | mutable: { TransactionPhase: 'Initialisation' } 10 | ) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/epics/hac.rb: -------------------------------------------------------------------------------- 1 | class Epics::HAC < Epics::GenericRequest 2 | # By default HAC only returns data for transactions which have not yet been fetched. Therefore, 3 | # most applications not not have to specify a date range, but can simply fetch the status and 4 | # be done 5 | def header 6 | client.header_request.build( 7 | nonce: nonce, 8 | timestamp: timestamp, 9 | order_type: 'HAC', 10 | order_attribute: 'DZHNN', 11 | order_params: !!options[:from] && !!options[:to] ? { 12 | DateRange: { 13 | Start: options[:from], 14 | End: options[:to] 15 | } 16 | } : {}, 17 | mutable: { TransactionPhase: 'Initialisation' } 18 | ) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/epics/header_request.rb: -------------------------------------------------------------------------------- 1 | class Epics::HeaderRequest 2 | extend Forwardable 3 | attr_accessor :client 4 | 5 | def initialize(client) 6 | self.client = client 7 | end 8 | 9 | def_delegators :client, :host_id, :user_id, :partner_id 10 | 11 | def build(options = {}) 12 | options[:with_bank_pubkey_digests] = true if options[:with_bank_pubkey_digests].nil? 13 | 14 | Nokogiri::XML::Builder.new do |xml| 15 | xml.header(authenticate: true) { 16 | xml.static { 17 | xml.HostID host_id 18 | xml.Nonce options[:nonce] if options[:nonce] 19 | xml.Timestamp options[:timestamp] if options[:timestamp] 20 | xml.PartnerID partner_id 21 | xml.UserID user_id 22 | xml.Product(client.product_name, 'Language' => client.locale) 23 | xml.OrderDetails { 24 | xml.OrderType options[:order_type] 25 | xml.OrderAttribute options[:order_attribute] 26 | xml.StandardOrderParams { 27 | build_attributes(xml, options[:order_params]) 28 | } if options[:order_params] 29 | build_attributes(xml, options[:custom_order_params]) if options[:custom_order_params] 30 | } 31 | xml.BankPubKeyDigests { 32 | xml.Authentication(client.bank_x.public_digest, Version: 'X002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256') 33 | xml.Encryption(client.bank_e.public_digest, Version: 'E002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256') 34 | } if options[:with_bank_pubkey_digests] 35 | xml.SecurityMedium '0000' 36 | xml.NumSegments options[:num_segments] if options[:num_segments] 37 | } 38 | xml.mutable { 39 | build_attributes(xml, options[:mutable]) 40 | } if options[:mutable] 41 | } 42 | end.doc.root 43 | end 44 | 45 | private 46 | 47 | def build_attributes(xml, attributes) 48 | attributes.each do |key, value| 49 | if value.is_a?(Hash) 50 | xml.send(key) { 51 | build_attributes(xml, value) 52 | } 53 | else 54 | xml.send(key, value) 55 | end 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /lib/epics/hev.rb: -------------------------------------------------------------------------------- 1 | class Epics::HEV < Epics::GenericRequest 2 | def root 3 | "ebicsHEVRequest" 4 | end 5 | 6 | def body 7 | Nokogiri::XML::Builder.new do |xml| 8 | xml.HostID host_id 9 | end.doc.root 10 | end 11 | 12 | def to_xml 13 | Nokogiri::XML::Builder.new do |xml| 14 | xml.send(root, 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation' => 'http://www.ebics.org/H000 http://www.ebics.org/H000/ebics_hev.xsd', 'xmlns' => 'http://www.ebics.org/H000') { 15 | xml.parent.add_child(body) 16 | } 17 | end.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML, encoding: 'utf-8') 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/epics/hia.rb: -------------------------------------------------------------------------------- 1 | class Epics::HIA < Epics::GenericRequest 2 | def root 3 | "ebicsUnsecuredRequest" 4 | end 5 | 6 | def header 7 | client.header_request.build( 8 | order_type: 'HIA', 9 | order_attribute: 'DZNNN', 10 | with_bank_pubkey_digests: false, 11 | mutable: {} 12 | ) 13 | end 14 | 15 | def body 16 | Nokogiri::XML::Builder.new do |xml| 17 | xml.body{ 18 | xml.DataTransfer { 19 | xml.OrderData Base64.strict_encode64(Zlib::Deflate.deflate(order_data)) 20 | } 21 | } 22 | end.doc.root 23 | end 24 | 25 | def order_data 26 | Nokogiri::XML::Builder.new do |xml| 27 | xml.HIARequestOrderData('xmlns:ds' => 'http://www.w3.org/2000/09/xmldsig#', 'xmlns' => 'urn:org:ebics:H004') { 28 | xml.AuthenticationPubKeyInfo { 29 | x509_data_xml(xml, client.x_509_certificate(:x)) 30 | xml.PubKeyValue { 31 | xml.send('ds:RSAKeyValue') { 32 | xml.send('ds:Modulus', Base64.strict_encode64([client.x.n].pack("H*"))) 33 | xml.send('ds:Exponent', Base64.strict_encode64(client.x.key.e.to_s(2))) 34 | } 35 | } 36 | xml.AuthenticationVersion 'X002' 37 | } 38 | xml.EncryptionPubKeyInfo{ 39 | x509_data_xml(xml, client.x_509_certificate(:e)) 40 | xml.PubKeyValue { 41 | xml.send('ds:RSAKeyValue') { 42 | xml.send('ds:Modulus', Base64.strict_encode64([client.e.n].pack("H*"))) 43 | xml.send('ds:Exponent', Base64.strict_encode64(client.e.key.e.to_s(2))) 44 | } 45 | } 46 | xml.EncryptionVersion 'E002' 47 | } 48 | xml.PartnerID partner_id 49 | xml.UserID user_id 50 | } 51 | end.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML, encoding: 'utf-8') 52 | end 53 | 54 | def to_xml 55 | Nokogiri::XML::Builder.new do |xml| 56 | xml.send(root, 'xmlns:ds' => 'http://www.w3.org/2000/09/xmldsig#', 'xmlns' => 'urn:org:ebics:H004', 'Version' => 'H004', 'Revision' => '1') { 57 | xml.parent.add_child(header) 58 | xml.parent.add_child(body) 59 | } 60 | end.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML, encoding: 'utf-8') 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /lib/epics/hkd.rb: -------------------------------------------------------------------------------- 1 | class Epics::HKD < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'HKD', 7 | order_attribute: 'DZHNN', 8 | order_params: {}, 9 | mutable: { TransactionPhase: 'Initialisation' } 10 | ) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/epics/hpb.rb: -------------------------------------------------------------------------------- 1 | class Epics::HPB < Epics::GenericRequest 2 | def root 3 | "ebicsNoPubKeyDigestsRequest" 4 | end 5 | 6 | def header 7 | client.header_request.build( 8 | nonce: nonce, 9 | timestamp: timestamp, 10 | order_type: 'HPB', 11 | order_attribute: 'DZHNN', 12 | with_bank_pubkey_digests: false, 13 | mutable: {} 14 | ) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/epics/hpd.rb: -------------------------------------------------------------------------------- 1 | class Epics::HPD < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'HPD', 7 | order_attribute: 'DZHNN', 8 | order_params: {}, 9 | mutable: { TransactionPhase: 'Initialisation' } 10 | ) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/epics/htd.rb: -------------------------------------------------------------------------------- 1 | class Epics::HTD < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'HTD', 7 | order_attribute: 'DZHNN', 8 | order_params: {}, 9 | mutable: { TransactionPhase: 'Initialisation' } 10 | ) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/epics/ini.rb: -------------------------------------------------------------------------------- 1 | class Epics::INI < Epics::GenericRequest 2 | def root 3 | "ebicsUnsecuredRequest" 4 | end 5 | 6 | def header 7 | client.header_request.build( 8 | order_type: 'INI', 9 | order_attribute: 'DZNNN', 10 | with_bank_pubkey_digests: false, 11 | mutable: {}, 12 | ) 13 | end 14 | 15 | def body 16 | Nokogiri::XML::Builder.new do |xml| 17 | xml.body{ 18 | xml.DataTransfer { 19 | xml.OrderData Base64.strict_encode64(Zlib::Deflate.deflate(key_signature)) 20 | } 21 | } 22 | end.doc.root 23 | end 24 | 25 | def key_signature 26 | Nokogiri::XML::Builder.new do |xml| 27 | xml.SignaturePubKeyOrderData('xmlns:ds' => 'http://www.w3.org/2000/09/xmldsig#', 'xmlns' => 'http://www.ebics.org/S001') { 28 | xml.SignaturePubKeyInfo { 29 | x509_data_xml(xml, client.x_509_certificate(:a)) 30 | xml.PubKeyValue { 31 | xml.send('ds:RSAKeyValue') { 32 | xml.send('ds:Modulus', Base64.strict_encode64([client.a.n].pack("H*"))) 33 | xml.send('ds:Exponent', Base64.strict_encode64(client.a.key.e.to_s(2))) 34 | } 35 | xml.TimeStamp timestamp 36 | } 37 | xml.SignatureVersion 'A006' 38 | } 39 | xml.PartnerID partner_id 40 | xml.UserID user_id 41 | } 42 | end.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML, encoding: 'utf-8') 43 | end 44 | 45 | def to_xml 46 | Nokogiri::XML::Builder.new do |xml| 47 | xml.send(root, 'xmlns:ds' => 'http://www.w3.org/2000/09/xmldsig#', 'xmlns' => 'urn:org:ebics:H004', 'Version' => 'H004', 'Revision' => '1') { 48 | xml.parent.add_child(header) 49 | xml.parent.add_child(body) 50 | } 51 | end.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML, encoding: 'utf-8') 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/epics/key.rb: -------------------------------------------------------------------------------- 1 | class Epics::Key 2 | attr_accessor :key 3 | 4 | def initialize(encoded_key, passphrase = nil) 5 | if encoded_key.kind_of?(OpenSSL::PKey::RSA) 6 | self.key = encoded_key 7 | else 8 | self.key = OpenSSL::PKey::RSA.new(encoded_key) 9 | end 10 | end 11 | 12 | ### 13 | # concat the exponent and modulus (hex representation) with a single whitespace 14 | # remove leading zeros from both 15 | # calculate digest (SHA256) 16 | # encode as Base64 17 | #### 18 | def public_digest 19 | c = [ e.gsub(/^0*/,''), n.gsub(/^0*/,'') ].map(&:downcase).join(" ") 20 | 21 | Base64.encode64(digester.digest(c)).strip 22 | end 23 | 24 | def n 25 | self.key.n.to_s(16) 26 | end 27 | 28 | def e 29 | self.key.e.to_s(16) 30 | end 31 | 32 | def sign(msg) 33 | Base64.encode64( 34 | key.sign_pss( 35 | 'SHA256', 36 | msg, 37 | salt_length: :digest, 38 | mgf1_hash: 'SHA256', 39 | ), 40 | ).gsub("\n", '') 41 | end 42 | 43 | def digester 44 | @digester ||= OpenSSL::Digest::SHA256.new 45 | end 46 | 47 | end 48 | -------------------------------------------------------------------------------- /lib/epics/letter_renderer.rb: -------------------------------------------------------------------------------- 1 | class Epics::LetterRenderer 2 | extend Forwardable 3 | 4 | I18N_SCOPE = 'epics.letter' 5 | 6 | def initialize(client) 7 | @client = client 8 | end 9 | 10 | def translate(key, **options) 11 | I18n.translate(key, **{ locale: @client.locale, scope: I18N_SCOPE }.merge(options)) 12 | end 13 | 14 | alias t translate 15 | 16 | def_delegators :@client, :host_id, :user_id, :partner_id, :a, :x, :e 17 | 18 | def render(bankname) 19 | template_path = File.join(File.dirname(__FILE__), '../letter/', template_filename) 20 | ERB.new(File.read(template_path)).result(binding) 21 | end 22 | 23 | def template_filename 24 | use_x_509_certificate_template? ? 'ini_with_certs.erb' : 'ini.erb' 25 | end 26 | 27 | def use_x_509_certificate_template? 28 | x_509_certificate_a_hash && x_509_certificate_x_hash && x_509_certificate_e_hash 29 | end 30 | 31 | def x_509_certificate_a_hash 32 | @client.x_509_certificate_hash(:a) 33 | end 34 | 35 | def x_509_certificate_x_hash 36 | @client.x_509_certificate_hash(:x) 37 | end 38 | 39 | def x_509_certificate_e_hash 40 | @client.x_509_certificate_hash(:e) 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/epics/middleware/parse_ebics.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Epics::ParseEbics < Faraday::Middleware 4 | def initialize(app = nil, options = {}) 5 | super(app) 6 | @client = options[:client] 7 | end 8 | 9 | def call(env) 10 | @app.call(env).on_complete do |response| 11 | response.body = ::Epics::Response.new(@client, response.body) 12 | raise(Epics::Error::TechnicalError, response.body.technical_code) if response.body.technical_error? 13 | raise(Epics::Error::BusinessError, response.body.business_code) if response.body.business_error? 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/epics/middleware/xmlsig.rb: -------------------------------------------------------------------------------- 1 | class Epics::XMLSIG < Faraday::Middleware 2 | 3 | def initialize(app, options = {}) 4 | super(app) 5 | @client = options[:client] 6 | end 7 | 8 | def call(env) 9 | @signer = Epics::Signer.new(@client, env.request_body) 10 | @signer.digest! 11 | @signer.sign! 12 | 13 | env.request_body = @signer.doc.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML) 14 | @app.call(env) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/epics/ptk.rb: -------------------------------------------------------------------------------- 1 | class Epics::PTK < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'PTK', 7 | order_attribute: 'DZHNN', 8 | order_params: !!options[:from] && !!options[:to] ? { 9 | DateRange: { 10 | Start: options[:from], 11 | End: options[:to] 12 | } 13 | } : {}, 14 | mutable: { TransactionPhase: 'Initialisation' } 15 | ) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/epics/response.rb: -------------------------------------------------------------------------------- 1 | class Epics::Response 2 | attr_accessor :doc 3 | attr_accessor :client 4 | 5 | def initialize(client, xml) 6 | self.doc = Nokogiri::XML.parse(xml) 7 | self.client = client 8 | end 9 | 10 | def technical_error? 11 | !["011000", "000000"].include?(technical_code) 12 | end 13 | 14 | def technical_code 15 | mutable_return_code.empty? ? system_return_code : mutable_return_code 16 | end 17 | 18 | def mutable_return_code 19 | doc.xpath("//xmlns:header/xmlns:mutable/xmlns:ReturnCode", xmlns: "urn:org:ebics:H004").text 20 | end 21 | 22 | def system_return_code 23 | doc.xpath("//xmlns:SystemReturnCode/xmlns:ReturnCode", xmlns: 'http://www.ebics.org/H000').text 24 | end 25 | 26 | def business_error? 27 | !["", "000000"].include?(business_code) 28 | end 29 | 30 | def business_code 31 | doc.xpath("//xmlns:body/xmlns:ReturnCode", xmlns: "urn:org:ebics:H004").text 32 | end 33 | 34 | def ok? 35 | !technical_error? & !business_error? 36 | end 37 | 38 | def last_segment? 39 | !!doc.at_xpath("//xmlns:header/xmlns:mutable/*[@lastSegment='true']", xmlns: "urn:org:ebics:H004") 40 | end 41 | 42 | def segmented? 43 | !!doc.at_xpath("//xmlns:header/xmlns:mutable/xmlns:SegmentNumber", xmlns: "urn:org:ebics:H004") 44 | end 45 | 46 | def return_code 47 | doc.xpath("//xmlns:ReturnCode", xmlns: "urn:org:ebics:H004").last.content 48 | rescue NoMethodError 49 | nil 50 | end 51 | 52 | def report_text 53 | doc.xpath("//xmlns:ReportText", xmlns: "urn:org:ebics:H004").first.content 54 | end 55 | 56 | def transaction_id 57 | doc.xpath("//xmlns:header/xmlns:static/xmlns:TransactionID", xmlns: 'urn:org:ebics:H004').text 58 | end 59 | 60 | def order_id 61 | doc.xpath("//xmlns:header/xmlns:mutable/xmlns:OrderID", xmlns: "urn:org:ebics:H004").text 62 | end 63 | 64 | def digest_valid? 65 | authenticated = doc.xpath("//*[@authenticate='true']").map(&:canonicalize).join 66 | digest_value = doc.xpath("//ds:DigestValue", ds: "http://www.w3.org/2000/09/xmldsig#").first 67 | 68 | digest = Base64.encode64(digester.digest(authenticated)).strip 69 | 70 | digest == digest_value.content 71 | end 72 | 73 | def signature_valid? 74 | signature = doc.xpath("//ds:SignedInfo", ds: "http://www.w3.org/2000/09/xmldsig#").first.canonicalize 75 | signature_value = doc.xpath("//ds:SignatureValue", ds: "http://www.w3.org/2000/09/xmldsig#").first 76 | 77 | client.bank_x.key.verify(digester, Base64.decode64(signature_value.content), signature) 78 | end 79 | 80 | def public_digest_valid? 81 | encryption_pub_key_digest = doc.xpath("//xmlns:EncryptionPubKeyDigest", xmlns: 'urn:org:ebics:H004').first 82 | 83 | client.e.public_digest == encryption_pub_key_digest.content 84 | end 85 | 86 | def order_data 87 | order_data_encrypted = Base64.decode64(doc.xpath("//xmlns:OrderData", xmlns: 'urn:org:ebics:H004').first.content) 88 | 89 | data = (cipher.update(order_data_encrypted) + cipher.final) 90 | 91 | Zlib::Inflate.new.inflate(data) 92 | end 93 | 94 | def cipher 95 | cipher = OpenSSL::Cipher.new("aes-128-cbc") 96 | 97 | cipher.decrypt 98 | cipher.padding = 0 99 | cipher.key = transaction_key 100 | cipher 101 | end 102 | 103 | def transaction_key 104 | transaction_key_encrypted = Base64.decode64(doc.xpath("//xmlns:TransactionKey", xmlns: 'urn:org:ebics:H004').first.content) 105 | 106 | @transaction_key ||= client.e.key.private_decrypt(transaction_key_encrypted) 107 | end 108 | 109 | def digester 110 | @digester ||= OpenSSL::Digest::SHA256.new 111 | end 112 | 113 | end 114 | -------------------------------------------------------------------------------- /lib/epics/signer.rb: -------------------------------------------------------------------------------- 1 | class Epics::Signer 2 | attr_accessor :doc, :client 3 | 4 | def initialize(client, doc = nil) 5 | self.doc = Nokogiri::XML.parse(doc) if doc 6 | self.client = client 7 | end 8 | 9 | def digest! 10 | content_to_digest = Base64.encode64(digester.digest(doc.xpath("//*[@authenticate='true']").map(&:canonicalize).join)).strip 11 | 12 | if digest_node 13 | digest_node.content = content_to_digest 14 | end 15 | 16 | doc 17 | end 18 | 19 | def sign! 20 | signature_value_node = doc.xpath("//ds:SignatureValue", ds: "http://www.w3.org/2000/09/xmldsig#").first 21 | 22 | if signature_node 23 | signature_value_node.content = Base64.encode64(client.x.key.sign(digester, signature_node.canonicalize)).gsub(/\n/,'') 24 | end 25 | 26 | doc 27 | end 28 | 29 | def digest_node 30 | @d ||= doc.xpath("//ds:DigestValue", ds: "http://www.w3.org/2000/09/xmldsig#").first 31 | end 32 | 33 | def signature_node 34 | @s ||= doc.xpath("//ds:SignedInfo", ds: "http://www.w3.org/2000/09/xmldsig#").first 35 | end 36 | 37 | def digester 38 | OpenSSL::Digest::SHA256.new 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/epics/sta.rb: -------------------------------------------------------------------------------- 1 | class Epics::STA < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'STA', 7 | order_attribute: 'DZHNN', 8 | order_params: !!options[:from] && !!options[:to] ? { 9 | DateRange: { 10 | Start: options[:from], 11 | End: options[:to] 12 | } 13 | } : {}, 14 | mutable: { TransactionPhase: 'Initialisation' } 15 | ) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/epics/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Epics 4 | VERSION = '2.11.0' 5 | end 6 | -------------------------------------------------------------------------------- /lib/epics/vmk.rb: -------------------------------------------------------------------------------- 1 | class Epics::VMK < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'VMK', 7 | order_attribute: 'DZHNN', 8 | order_params: !!options[:from] && !!options[:to] ? { 9 | DateRange: { 10 | Start: options[:from], 11 | End: options[:to] 12 | } 13 | } : {}, 14 | mutable: { TransactionPhase: 'Initialisation' } 15 | ) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/epics/wss.rb: -------------------------------------------------------------------------------- 1 | class Epics::WSS < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'WSS', 7 | order_attribute: 'DZHNN', 8 | order_params: {}, 9 | mutable: { TransactionPhase: 'Initialisation' } 10 | ) 11 | end 12 | end 13 | 14 | -------------------------------------------------------------------------------- /lib/epics/x_509_certificate.rb: -------------------------------------------------------------------------------- 1 | class Epics::X509Certificate 2 | extend Forwardable 3 | 4 | attr_reader :certificate 5 | 6 | def_delegators :certificate, :issuer, :version 7 | 8 | def initialize(crt_content) 9 | @certificate = OpenSSL::X509::Certificate.new(crt_content) 10 | end 11 | 12 | def data 13 | Base64.strict_encode64(@certificate.to_der) 14 | end 15 | end -------------------------------------------------------------------------------- /lib/epics/xct.rb: -------------------------------------------------------------------------------- 1 | class Epics::XCT < Epics::GenericUploadRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'XCT', 7 | order_attribute: 'OZHNN', 8 | order_params: {}, 9 | num_segments: 1, 10 | mutable: { TransactionPhase: 'Initialisation' } 11 | ) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/epics/xds.rb: -------------------------------------------------------------------------------- 1 | class Epics::XDS < Epics::GenericUploadRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'XDS', 7 | order_attribute: 'OZHNN', 8 | order_params: {}, 9 | num_segments: 1, 10 | mutable: { TransactionPhase: 'Initialisation' } 11 | ) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/epics/xe2.rb: -------------------------------------------------------------------------------- 1 | class Epics::XE2 < Epics::GenericUploadRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'XE2', 7 | order_attribute: 'OZHNN', 8 | order_params: {}, 9 | num_segments: 1, 10 | mutable: { TransactionPhase: 'Initialisation' } 11 | ) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/epics/xe3.rb: -------------------------------------------------------------------------------- 1 | class Epics::XE3 < Epics::GenericUploadRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'XE3', 7 | order_attribute: 'OZHNN', 8 | order_params: {}, 9 | num_segments: 1, 10 | mutable: { TransactionPhase: 'Initialisation' } 11 | ) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/epics/z01.rb: -------------------------------------------------------------------------------- 1 | class Epics::Z01 < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'Z01', 7 | order_attribute: 'DZHNN', 8 | order_params: { 9 | DateRange: { 10 | Start: options[:from], 11 | End: options[:to] 12 | } 13 | }, 14 | mutable: { TransactionPhase: 'Initialisation' } 15 | ) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/epics/z52.rb: -------------------------------------------------------------------------------- 1 | class Epics::Z52 < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'Z52', 7 | order_attribute: 'DZHNN', 8 | order_params: { 9 | DateRange: { 10 | Start: options[:from], 11 | End: options[:to] 12 | } 13 | }, 14 | mutable: { TransactionPhase: 'Initialisation' } 15 | ) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/epics/z53.rb: -------------------------------------------------------------------------------- 1 | class Epics::Z53 < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'Z53', 7 | order_attribute: 'DZHNN', 8 | order_params: { 9 | DateRange: { 10 | Start: options[:from], 11 | End: options[:to] 12 | } 13 | }, 14 | mutable: { TransactionPhase: 'Initialisation' } 15 | ) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/epics/z54.rb: -------------------------------------------------------------------------------- 1 | class Epics::Z54 < Epics::GenericRequest 2 | def header 3 | client.header_request.build( 4 | nonce: nonce, 5 | timestamp: timestamp, 6 | order_type: 'Z54', 7 | order_attribute: 'DZHNN', 8 | order_params: { 9 | DateRange: { 10 | Start: options[:from], 11 | End: options[:to] 12 | } 13 | }, 14 | mutable: { TransactionPhase: 'Initialisation' } 15 | ) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/letter/locales/de.yml: -------------------------------------------------------------------------------- 1 | de: 2 | epics: 3 | letter: 4 | date: Datum 5 | time: Uhrzeit 6 | recipient: Empfänger 7 | signature: Unterschrift 8 | version: Version 9 | exponent: Exponent 10 | modulus: Modulus 11 | hash: Hash 12 | certificate: Zertifikat 13 | bit: '%{bit} Bit' 14 | issued_in: Ort/Datum 15 | name: Name/Firma 16 | confirmation: Ich bestätige hiermit den obigen öffentlichen Schlüssel für meine elektronische Unterschrift. 17 | initialization_letter: 18 | a: Initialisierungsbrief für SIGNATUR-Zertifikat (INI) 19 | x: Initialisierungsbrief für AUTHENTIFIZIERUNGS-Zertifikat (HIA) 20 | e: Initialisierungsbrief für VERSCHLÜSSELUNGS-Zertifikat (HIA) 21 | -------------------------------------------------------------------------------- /lib/letter/locales/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | epics: 3 | letter: 4 | date: Date 5 | time: Time 6 | recipient: Recipient 7 | signature: Signature 8 | version: Version 9 | exponent: Exponent 10 | modulus: Modulus 11 | hash: Hash 12 | certificate: Certificate 13 | bit: '%{bit} Bit' 14 | issued_in: Location/Date 15 | name: Name/Company 16 | confirmation: I hearby confirm the public key above for my electronic signature. 17 | initialization_letter: 18 | a: Initialization letter for SIGNATURE certificate (INI) 19 | x: Initialization letter for AUTHENTICATION certificate (HIA) 20 | e: Initialization letter for ENCRYPTION certificate (HIA) 21 | -------------------------------------------------------------------------------- /lib/letter/locales/fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | epics: 3 | letter: 4 | date: Date 5 | time: Heure 6 | recipient: Destinataire 7 | signature: Signature 8 | version: Version 9 | exponent: Exponent 10 | modulus: Modulus 11 | hash: Hash 12 | certificate: Certificat 13 | bit: '%{bit} Bit' 14 | issued_in: Lieu/Date 15 | name: Nom/Société 16 | confirmation: Je confirme par la présente la clé publique ci-dessus pour ma signature électronique. 17 | initialization_letter: 18 | a: Lettre d'initialization du certificat de SIGNATURE (INI) 19 | x: Lettre d'initialization du certificat d'AUTHENTIFICATION (HIA) 20 | e: Lettre d'initialization du certificat de CHIFFREMENT (HIA) 21 | -------------------------------------------------------------------------------- /spec/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/railslove/epics/6ab966f1618baa0718a20b93bc2fe25589750693/spec/.DS_Store -------------------------------------------------------------------------------- /spec/error_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Epics::Error::BusinessError do 4 | 5 | subject { Epics::Error::BusinessError.new(code) } 6 | 7 | before do 8 | stub_const("Epics::Error::BusinessError::ERRORS", { 9 | "123" => { 10 | "symbol" => "BOTTMUEHLE", 11 | "short_text" => "home of awesome", 12 | } 13 | }) 14 | end 15 | 16 | let(:code) { '123' } 17 | 18 | describe '#to_s' do 19 | 20 | it 'returns a message composed of symbol and short text' do 21 | expect(subject.to_s).to eql('BOTTMUEHLE - home of awesome') 22 | end 23 | end 24 | 25 | describe '#code' do 26 | it 'returns the code' do 27 | expect(subject.code).to eql('123') 28 | end 29 | end 30 | 31 | describe '#symbol' do 32 | it 'returns the symbol' do 33 | expect(subject.symbol).to eql('BOTTMUEHLE') 34 | end 35 | end 36 | 37 | describe '#short_text' do 38 | it 'returns the short text' do 39 | expect(subject.short_text).to eql('home of awesome') 40 | end 41 | end 42 | 43 | end 44 | -------------------------------------------------------------------------------- /spec/fixtures/SIZBN001.key: -------------------------------------------------------------------------------- 1 | { 2 | "SIZBN001.E002": "T0DbJARPNfDbx3x+pooRViwBpL8so7i/vFPN/s91Fd6/KuvJbbbTPRPrNpK3TDt0VxiPYn8VO7comHesifUUUYm+WJm73cFEjvKzelejz7WvBKaIVHii519bQ8J3TuFPiIReB1Ex/RYcBsEHBGqhRkcUsLALDdBvbfrQ8+L+OKijM0C8OadHWzrl4BKivua5uydkkw2hv0FIi0oJinXXKM0CBU6Id/lGXKCgrM0/yEmu3XLRVxR6Fqw9zUJc1efuS+88WgXqQoArTZphcGExunAvePV7BBiPI0SshyzmyTVOY5pJDHptw/gwT7eqCTWPn7kvOJ7beGVF4cnOuMJWo++0P7vqb5oeSt+RhUtgyWHktofm8UVxMYej27hEi3UmIcaiy9MwtZc=", 3 | "SIZBN001.X002": "E9Lx/LgcG2zCaEtpk2nsz7ix9LioI7utENsMhx9xDet3APsg9mg2wpaLK4WYGHxVlfRBmqwKcVyQJxbkkfupasCL6GChsIrgeavCmSX3fMFr6Z5VpcLXauar5BMZLXp1HvKwheI6iZwwYCyGpChMeY5Di6fN8EcxG2vP8oPQYoLs0COwl5kZ0PVfSFSCK1SWrcNSOeHbrrf0YViYWoVt6D9zTHBf/F3DznicJkgkhVTCVvq/+RpKoK/4YDMjAEheMf0PLvmqUk0HHsAKtFPWe4Q9SVqXmK59h+ZcJweDSkox95nWb67j9Hyw21D0PisgWTx4o7YqcCiEn9yb08EfmQrQUCHzaQHdryMaWNhLcHuTVneGOFpCmcMJsfwUhcOklsqxMbvJu1M=", 4 | "X002": "RYnfScoGWcVvmFWZbqbwc+9yr1TkLiK9EMUOkPbfJkD1kX7f4zPzJv0CtO3jJPvhbCTVC7Cl4Zk10JTPxLUztqZkU6rfGGxi4/Da28SSBr4XHaHmso53sWoA4qIdilb6ibQdZX6nfmBYqQ3Ynd8KanThSyWj39CWECcve7all7ShB9C4+8z7sS57FhAr+XJ/nIiEPxuQ8sajV4urfxiFM+b2tWc3WDckyJ+l+6T0FH+3ZM70GOy8hwwxjN7MyJpPZ5ToqTLUkOlxpOhnzSwlsQErb97Rp3vq/hvfb3S6f6GHE/znZJr/xYo4jaNo41T95efSbpOI5XjPAwsAbjxGEu8DwUBKaUh62mqE9TukJRK2m0kMFI7EgKTTL3N/BNp8vPhmUhWmWKZHUBZIXZNjnjGRRzSvSxS25s2xcNXedfO2AN8w0gcfklLgk32xCFcvAW7VOMWCmRk6V0efeKxn9m1Dk5OZT75nih5DsYWAyx5I7tEig/7K1p3jUh55iRDacjsFwmFdRnpXifAsTn2qIZ88VuHO9QluBhXw7+W3A2Xf3Yrkr75fsTP+uQlpxx43cOLKjTkx9wPt0r6kQhm2Kiy3EtP7oyVOhbe4ahDLFlIkaumhcKedx5ds4cytEx7/0obHxx36c2ldbSYrbdndh7rpdlonC1GKqlPiB2bcQGH43XRfMjee8JLNVHPO2lGMkZlE/L9NMkN8TQ6x8hixekWm0odb4ZVZMneCqFzynv+xbqdWw9ysR6z+viNJbqqTJC0s0Xdx3xRMUK9pjyqH5pl03IFoozfOrBKblW/QMxdUIiRhlu0j9Lq5VVOajwUx/v3bRI7EFXRW8IDnLYjKCKj5Wh2IsI246jTDvAULNc/Cv44bNA2Sj/gen7YA5EmuH18DqibV7AL2ROSH4VKAjW2tcRyyGm4gtDU9iF+jdk0kNcv/IYLqa943EU15JmiVdj3ciEKWxr4YuK4Y1BhZPmRSdGJFWQoqm2QoxmSayNePww8eYt6JsMtFm+BREZwHM0/Jfy6DgpiEPx4Gw5zg636+lLffv81CHlbzcySsKIRx6RdAjKwf5ixHqxYeZx0xhEuJ1KCmsCnJvyC7UBwgxA9ZrBHmq6ijuGsfboOPqYONQOVPjXgiOypyTVSrzt0D3CMQFs4juOM2NSSjx6oLVOe3QIbPDE25wyjQYLHmPhQS5+UqPuocqCo0Z6jLlcIJ/2VkquT1ORdUAcHXk9qp1zPfvFGZbA2OX5Qn27oAVVJA2iGD49/K2aXa1xFrKgha0HkEJSFjCQrs66P7Ku2JHOTkkBJnnE/ZnJ4uiEaNDzXXls7SEMdfxyqKbX0ooONxqv7PbzILgTzN0Dk1b+8Lnnq5CDyQ/BbA1ZcuilsGenGXvqPvIjDzhwe4MrF2A/T3OCAhqiKmqWeyhLNzO9APY2knK9Hq2+nj+FZuQ84uzdRdGPbOFI/1qJm1C+UyB5J00pg/2Glb4HnruAp9eoBbVHZH4XoMVGnOk2KQRsXUvoUZj19XoaX4+eurrIE/hmKrXnwegGLi8d4VYlOdU65bqRhoBytL8FywfXgxPDet/nOFip4D1g612poFSsMlFvof2I1HSW9K3JiPypH4eipSzkOC6bNniA98CjnRGInEXvf5DAP/xc5DPGi9LV45mUfWBNpGhgxfI32YLmE3ENx2aLZKjhYwZq9Dv5kwrRM3NZGKLFMVXPWZsspKwwUfg1tqR729r5s3HiJ2bQ4F1TD8hBx38uGlizX7oDDgbkFUWrrNLUOSGJsGeXFmzOrvBvzAkCVwHNZ/QgXk95J8LEW10JAqSptdJD3hzbG+17PUDFOazw6AebRo9QjUIuk92KDXDP9F/sHPnUZdEJf7UkpH7FTfSGCkcaNi4e4DrxfHVMMOcf66nv0+B2Z1+84/DdBXVGwGsYQw0IH0fL0X8FRflp+CMO6SwwvvCYCTYufCXxB7modxBoj6dUk+NZPdwYkPdQ9xQmmuzwddGi+5TM5LjlnDam3G3ucuisyN7ZIRErnS3uE0MniZrp4la8mJ10G4cX5KO1Ar96+9JoRANYoz1eRTHh6VA4G/pMM4PiOeoPd8KNK4bsOk7RjnoDih685mHbfTn/qj2n9EbAP+H+FhoILNJY/12tQNIzzH76xX/W82V1WPz964wotOSKO1sg9qwNCSu5rt62JQchvmjuCVvZGz3P+iIZilOTjklaaIkrdxHWGSVf99xOxwr3j2VyjThcl8u0MIDZc=", 5 | "A006": "PKftcKEEuAfvNMRkM/E62+8ELgd1+uiUVXLf+2YaXO0yayPYz5JdPQB5pfVFAfmQfS034lj18q2cOefk2gBceiBHCEmW3hSLLZOCvbuafi0YAMCFXrovQuil0QlP1XIjcZ1x9eBRB37Hbkff4tKSHjjj1ex5M0uGtZ9Kf78BGvO8VewPVtifim6XrLSvz8AXVv8TE2VfK4z2jYG5toUO9MqEZV+NA2SscSaFSTOo+8frm0HSAYC9NxWEJCFA4KVQWP4lTAQDv4pjJ83p1cdy6jipzKYraSHZGjGKb1Hzrvt9KXa7+JyzetiaCz2q9iOYoz6WZPmn87rjmqq/8fnck/IfqhH6ESMuaAEWeaA7mkivGB2zxIQSb6E+d7cenSbZmKLSVnGThylKzzzRjoDmwNixyKLqPOtogS4bPKo7eiPSLmla2xVTmlO9pemMMtBmOKYpRYMnmldpFHcCGxqu3gUhq+bT6ry3cMeAOoyimmTO0J1IzIHcuG/mcN7pr3ZZFODe4B/6ca2HslWbUDWfAw76HGatzEmVfJijFQ5bKSQ3Jp4MmlcWzfLRr/3rELzDgH27sYJyaVAJd4NR7BTtXN1o1Ytgj8mYvRvsWW1Z1Vjwwa7vzomcSkcV7TAYsJ3J75us4lsNwStAOLln59gGSMPAvI69tWSKOpy+5zm7Ph0wVY7yr0FE0ZgZFWmnZNMI+jcxfpCuuP80ar+HqyPQAltocgSbylANvXW4cDhg3umzVxkmEB87Xswmx+iKWOiyOLj0gbpNoe4OHYxR7nPkpMJpSr2JmtgIcdDI2c4jZax+3Lh9bq+89V4DvROjna2KWsxdY1t0Dl1F/nGRdnKdR/EpJYATeztMmdLOIxF8vjvkYVkrDhTj1sBOTP8tSFoDBn2NSECRPGnM1lpmdX6TZEXN7hDeb/ZEF1XCfXRuvoH0AZknp/u+9Yv8PC7ORc2VCHEJydg4g+N0U1i7iRPrQ8YXFNZGCRMlEjSnp+oPiMAF78qD2Vcz9lHB1wuPnZ4cPDOQq1WbpdH1TaQmDUQbTBVImxl/iiN3Qwt9STyZ7fKJ3rdC4gBENJ7wSxDYuOEFRpPPtECarhzMb+dzfrA/GB8XRkdl4o9V7XAnCnSr0nC4rEDfgNRbn3Px01LpbLa0aNjZcU1SoIsIDuyraB2ptyTjcdLti8znn0tcb6FSoxtVsk73xs4y+VbV/tUqG9+aHsFiHIV4PqFDqzEKUUTV4LyHctZRyEkIVi6TbfABFRWfWxtK+w/D9QFuI4MVG3DNG+KxWkOiPgi9smMtwV6fCjIaqYcUJgCdV79kfY9hVSJbMcLcNhXTnIAhZgos6GPTSKHMuspUFbpxsSVupwmXtFQMdyIpMn65dJ0iEuzLy2rq469egGeAJAmfofJ1NJgP2dWqKyMHvic8n6wn7ZM0GXmsdgbZPagSB11kwLbo7t9eS068i9Il+dyH56WCzS9N/eBJhr34OdKhwTFVAFZnJR07Oxo5QDTxtw8o4tzcxbQtDca+8Qd9U0C7FPfqsHC4o/JRyuEzu0Q4M8Ln8MLE5W0886kWpuHHwuycQvTYiNAyPNsOOQfR/jLlOyZ9ycp/1HITLYzwfV6L+HRkzy/gcS5PmusxnUHkDqfqcbM97Uaxg6Oq+GY/umFz08TxQ0/8rU4UOuaHqronB/SbvxF9u9WC9uIj0H0RKlaRT6G5xhWpUUlVughsEjEfnRL3dOvgI2HhFpVlIhuQHWA3AuQ/JBS1l9mzfqZOz8BIUVpSvg8esti2BwRZp4+a3uj+xeld7bw9jrn4mlveZP6Jo23KOt5SQ5HWb8dEdj44vpe7J+QeSl1lOu6eD2eVw4Mth9BVREHPLvsOd4Ja3o35mkZHjQl3Q3cxJRPGbXXzSwPDKNaMbq36eBgt2ygNCRg5zlHlfmGoBgVtwMc9ApeIt9lLuXw99XGdpImpe70dAPMn7pSStStMusPIReigHIT3zRVDMwz1nku6paKaGOnES98RAc0PCFlymae+WdWvG5BtBTs255pcvihxq4QLhfofUyKGgKWwcOkqz9pOsOSxSLPlHy1lIreeyQHkRbNkqFhha/kWiWYxrwO3GfWPLotarpvmfvEy2CTIA2R61VWqoNQmETh1ZhNe6d5g0tcIZRmIzMMZOpg4aGZyrPM4XeTyhhq+BjvUgXqzjSzBCQJG0wEuo/cJvAPfJauOqPz2z2LabTa0TvOCPOGtB1jFU58EBa2sCx9E5aGHiV4=", 6 | "E002": "oGTx5v7voHOTcUVVJlMwz7mKUVM9NJzNzLUX8W9c14DjupMSNyMDgqy6m6tUt/p71tUFQpVkztx2VqP9kgnpN67sG9IW2u9nLzAZyL+buZwTUC4KFDuRcYbCaYaXUAd6GD1vL1X5sGGvwhZaZjOQX8A1sRI0+PVVu+hkRHZXwGBMmmzF0QR+tf44d40hb8MjSlUFT4LXny6qgWgQ5jhnZ/+fB/V38GgNsSsaU2pdIL6p0qefRVAtUw9PWbQdZ0ijoPMGc4qtWqy80goKN/YCwmsBO6RyA1VKiYe3v0SsLJ3i3hQEtaaqguBmzLScsGW4ytROhNOaQmW2q/XAZHN6s2NnObcy5VVWR7Vz9ayHP9gqUMZTT+1yhokcPV7Akxg9vS8oWDszxncJbi4i+HWbG3ZtWvkwcBxINYTqf5m6OcA0MEzKXZEIwJwD1jk3eq5Y78pHYStPOzUuInKBjXWLv4tbeHeuKJ+Dd/4Pd/hd3ENLKOiV3cSsRvQW+zE2ST0B3Nv0AqM2SNcj7odiZc9oXZojc3HUI0NNh4s2zaXrs+xrVd/PBNqQy9JBPJhgFGJyMhB0prauV+8Z0HfUyv2V/T/Lc4hOoUAGexWVM5HiE81+LPSMsXZZV9NuUqedMZ2P+ayv6U/yegbOt7prk6EGtvOHYG0mjomebY8SWpPjPB3vwJ2d4bjfedWr3iNfTVjDvqhPw7d54kC3HEbkE82Wb32xM2gCQMu3OLiUgxEP2d+ps31Z562TeudQkPaCB0FRfjV0cmrLcCYYlKYiwJYTyVGtq/7j0hysWjY2hglmag8BBiUE0ZS4+H65ntYwYyPIMN0F0TvC3/p+bmDx1qowbyFp03Lbquld/8HlAcDdSFFF5FqcTuYERTBhU4m0W5cVmw/jm0jLJMCwerj3NLhw3l8WNrB7J1GFjVPSZOuQmBJce4oUX+AjpZASXNPzfL6w7H0kMVnoC4ObMecUnoAKNJLjhCG8h2yswM8YP5xHG0vPKKO145i9+nMMbkbc5ltMiVdHemcDd6h0BM6H3TGcSCPEh/Hx4CDYsyu6qrqT4eFCE3vuGmpNlLJ9CclQZipHVp90bbuHWn6mIlkmJMcR0EWzi6yBWdAz2KiXMp8OsTgcF6qNi13a3wt7kRESjXRYxkixvglggu1f82fSTc0njzHzx3+Vk4BxQmLfx79FB+1V9uJuZ6sDXjXr/oH5sUbJa9oLGBjiwez9r5Vg9fNcy9O3L3OQAYejgPJlI8uFTEGYHJaLZSIR2kr/9jV4bW7MxHcdc0gONvLGiCg+YjFA065xF9kg5RTaWkOC0/wbh9fISgXsv8txOo228n2ukrt31V8lfM/W+TAdg9v+xc1+BfZXUY2fZzlU8gpmwcE9EYP2YpE65CaGuroxkVEu94TfxSdkEwjlMkNVXOSPo1uZOXwzJhn5fgIGFMU+z7pYwp7X41C7LA6DY5afAsxCof1x646m2dAQ3Fz/Dqkzq4bLwq1b0Kas0S8DHDL/V3kz3WrjLDLhUfSRwDgUMQoFseUqC7Hc8X5oiJutvN5aVgoBxTTvj5F5o3jrq47da2WzYuO24YSEQ+fHdHUMZ7uIxzS7aZs6bOi53fpTHMRYWC2JqT/VwuAhppG9Yc/qDZ7a63w209jRvRSFQoYnsMN9lGJ3N+hdXK+qBLn0YjBNuW65uAulzQ94dliQNYUlEaPPKtzJcNhbMGBokMwZDxGJJL5oozY+gAZ+LiTrssMAZrxku294AwftgqckxEdX7/eu1bL2d4I1xlrkAc6cFo4Te0uT5OKsGjGW6KTobSSx3mpOvc2V2YjSbBkJzNJ4s50ywCyFVddBbsn9QjDJQBUQN+149zbHU8HbkoPYq9TTfM5Q4Y0cGNihoyIpfvr4Tt1mzYbTkrjMq39Tgoe7bN4ehyfza/5J9037BKUKSw1wQtFztw4OCQZxQ63WdKKJOFLaMwu9YRucQ0OdT9mr6/pZU1tP9lMyZKwky+BV6A8hFnkaR6ZYf247kMKEaUPaNIUk/71UMoi4aF0ULbc9IGG0aKUaIQECbTPGL8Xql5xTJdrSTla9au+4UuHLLM+rTfJWyf7VFLpf6l7d0ms3RwdHYjgPi+HLPpExrBrxpnBBlSQm+Sp6Ky9yeA5qlVaJU4oXvGyK2F0Gk38fEiL/uH5VdbblN90Sz6LNM29CftiLXDNGf+/LdM/W8qp3rKrhxXJeficHm3hNOK/bgW4KmTd2zAELOQ/ukMauzdw=" 7 | } -------------------------------------------------------------------------------- /spec/fixtures/a006.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDXjmjtnx5eemu2 3 | 3EuBQJ308rxoom5osnnfScdcInwqI7s8y6Z0lVp2w5tsMgdf2FytVf3JZSviwq2r 4 | +PMTJ6IGtGkXFca0graQFvjwelp9YSpDVtpv8CLj9VYPiwdhALAFbwojKwqchilF 5 | BjUOcdD4fdd8WFIGeNUavwjSdsOALbgoG6+Sr0U8LyhL+CRCeaspnnat2MtZLere 6 | R20JC8zKTDgbTC81AYmVL9bEwKRLSt/QnQiPBgBLGXVuXj0na++8tKrAO0Ak8VpY 7 | i6TQwceATrmCc/SHXo6rTU+MwA+7EAemGoueC8ydJaR5gN22it/2N4ASasQt1h0g 8 | X+vMeuonAgMBAAECggEAKXjTxUwE6saA7Nirij2lZlhBWZxOw8P64LPwMFDONMlV 9 | H9hKuUl28zylLYbellkpU4wk3NejPuiXw2uNUNUiPkn9ohxlc5tmhoh08seHm3HT 10 | UMtoEXtRKyyrlyf3jnk0ZIc9mxCP5ReG3ynXkWTigLytddYESgx7a77vcpa4/HL0 11 | 9QEkrZCG92m4ga4/rvwSR/V/UcwNarf96/W4leKlmgfXuz0V7Md6tfoubc3pnfI8 12 | I9D7Xp9eRRxWLqLNhpJ5R5JJOsC8qIwuvN/2qjtT8ClAzg85DSu7hUxv8cVqxcWe 13 | jy+hYpnnolDaTt29Htg5Qo0+K6DMaBA/oisPsz2t4QKBgQDzimHfoaNo8LcXPkr7 14 | eQt/HQvvkkrppfoktMQes142YtaM1e2lWNgtVXG9mwFKI/GrSJ6yJVCC4CGa3zX7 15 | euWEUVuWxmpEpH8Tvi0G3389MIECWLxgkWNN4knmC2IwBM6oD4ihd819wWzwsPpn 16 | a+5Df3yL4/FflhttJCNCUoJR0QKBgQDilYV6ShIVL1XgyP8YPDU8t5vm7n6RoTnP 17 | tJ2gu2lW4fqeHO30jgcPBw8UG6FGYalcCixxGVrrrGmgJe1lHYLUOOdn4x5JqZAn 18 | 7I/hm7QSK1C1+qJMWCaQxzo+2DclJOs4oXgES35RiKb3ErDlQW2GyOgNZoLQFFCx 19 | HSJKiJ9CdwKBgFFSmDQQyXw1RS4hwvAOD2S20lGBTDqRDeJL6mFGC+OlRXdpyB06 20 | eZVJvt1NcTTMo9pKOZPLGgNZzF7mwiPjedihQjAquTmKpFR3YJm278oC9FFQSDcG 21 | 1V4gfgSvMG5QbKF57mnck2W2vSXyMutuAvXPEEu2JdeBTE85jfyLiLDBAoGARcse 22 | yVNljIb/IfVntjRdha1c5V5TOFJ8N0GASFFSGkQTaX6pwWm6POPEvkHghIhynXo4 23 | xEG2IuABzSXBoSLc+Lfqd7Ka0r/bOqEAlNLcPbh/7P4d3fxNLM1hYJhDLDraBaCf 24 | EluatkyseXCVcpibvyfFatNHugZ38IZz2JeKzvMCgYBdz52dlr4TSMigbI93B6Ox 25 | 4bBsu/kue+eL1kcOBEBa/uMQLEWgQLWpHkskVpRzpbyu2drSozW6wOx6EBt7HlRV 26 | eG8rYi6P6SOiUoaLWcRqnaFCL5JgzGMlgmcIhwA9ABCdo6gMWJFXkkrIyKBm2FsQ 27 | KfJIQL6xXtLW1h+56l93XA== 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /spec/fixtures/bank_e.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdv9DqCGcnW/bICm4sKg3MANDb 3 | XFDCGIuhiuz6qEbM7tbsrRp8SY0IRretpDLJVry4Hm1EsHav092MhrGtykHiBmlF 4 | J/YqsrtwaDTjHaNgyzeDXRjGNVkfx22ESkdyR8lEYUwSsNuyknEUXShpeo2PlXF3 5 | EyiS/D41zEB+XA+hswIDAQAB 6 | -----END PUBLIC KEY----- -------------------------------------------------------------------------------- /spec/fixtures/e002.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDWuSNkXpPgLrr3 3 | gKaI5unAj3yTieBqoN4GkhBXyafb9EQCsSOeDBqcklt03nWkLL9KfXRmK2o+yziY 4 | +nKRxMnI0PE7N1mTXbB3MiihOLLIwmgjw36xNYFaUa9PwRHZkQc5tkkAZaoHqw5G 5 | NMRE+qqxDz6xQ1xKhJd9ycxWtuCltVL8uyBDCWeramaxGrfkORV/7TdSFizdCSm3 6 | OFpBcYWZsMNviilPGnVmAmrOXof4YMOEUDn7HPULk9rg4vaM04LK5G7rTDKYfWBz 7 | pw6Ze9hMrIJJVj6Tz/A92rqsXXKVpxMRYWFuL7VkDxFUk+pDM57qBfExcUWgpN6f 8 | VO2SBebpAgMBAAECggEBAJb7Q1mV7yDZevoBahglVgPiYNRVRIl1Z+jy168Cypcs 9 | 4I2MBOFi3WtutgQtUEcKd89m+2vD50cUGk3m/Jxm5QPhd14OA1xNqoGFsW/7sCre 10 | F9/d3L26Q6RAf6byuRxkj9ISzK4MzkvqCXVwMPnX0CID+C8okEKNjQAT3yyyFrAs 11 | z99pAoPD7xfGyZDbpSpdzmm62z69znCZjej1QrknVNmi27/8blat+wHIzTBiyiav 12 | jhcCbZ2YQFghE/Lb1B8dCJvj7eihwTiNWdc61u9U3zCN/AyxV4rl97/NG/bT5jeK 13 | fwkd3yCFSMLBTi0+3GyCv9gN7kokBdFEbkd1oyl43SECgYEA62RFlP2DdAZZMxn6 14 | Q/O8yAncIgLZ+2RlSLn4BWdBHM+O4DGAdXSMjb4BG30UxLZyEwHodSKfolMJdMS/ 15 | UNQXffOTJmNRgbT75iCi+3QYHa+ZXPKUs0YUyWTxH6IlX0soHtAXQBz6TZgj1Alx 16 | hRZ33xdAfOt+yrjebIySWxW6hd0CgYEA6YWiAlnaa8v3VvJCshpx68HEeyyKukvg 17 | HiwyxGO9BoK8sgou/8cQgxhj45foTBwuGspgiyXl5Y6Lr/C+C9s81kskkGzIRZHF 18 | 1t9iQjiIxNaqb5k7+2LmR5ScV/ckkgWd/nfFY94iMCSovLUGJIleB3infKZ2pwHl 19 | F1sI/8CdEn0CgYEAiZTc+p1GVO1U+4JGfasbfwwMRzDFeaMPc/eGWJomO5GxH6av 20 | P3d0o3AXs5pjJirA+A0YckZfaYABOee5LqQYavyP2FMak6ZVyQbwW+paIhe9ms8K 21 | TNI8Wg4OxP9/unfyJjhYLpgBUJMI9ejjGfes7o7nmVwHirONBYMQE/7aO10CgYEA 22 | pkfbhqUInL2OD8FNsJiYCfHdwH+FAQbKPXHnbGRA0wQA7R3HPaY3ocGaTxN5+8gN 23 | JFJ60FpaC02nNc7M5JBmD4lOLfDn4nHcWBaUVub+rHrWvcR1K5nOs6WkdharWbba 24 | O7p5OZWQ7osMA+M6zoVqCRPm3yGBV4ZH5IuUKtiyf9kCgYEAqvbm6V0fu/sphEqj 25 | TxoAG6c/Q7aFu7TD3a6znnnml7gTyuWG88Kt8xwUILKhUJpdf3cpeu+FJ0MTn45q 26 | cbjkhO/fZMVaGzO9IIuu0L3T61fyVhUGB/MNjFGAs8iL0trcrw6/sKFSXm/wuax5 27 | 7YFHryPYM/JT+Ob4xvB6F+1FD6Q= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /spec/fixtures/test.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/railslove/epics/6ab966f1618baa0718a20b93bc2fe25589750693/spec/fixtures/test.zip -------------------------------------------------------------------------------- /spec/fixtures/test_with_general_purpose_bit_3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/railslove/epics/6ab966f1618baa0718a20b93bc2fe25589750693/spec/fixtures/test_with_general_purpose_bit_3.zip -------------------------------------------------------------------------------- /spec/fixtures/x002.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQCmF+Dka//jCuwa 3 | 07aajfdTFyIL8NKbDRF1sGELm9U+yqCa+UOBnVumwZbCxc6IFTkHGlsI2+0EtLuN 4 | H/i1KA2IOtaYk8szTnKAUrOHKH/w13aq1kK38lpC6exJ82kgub5v2HVmK5BGcI6y 5 | +wmrt5QKuomdTkt/8BZYTmD0+Vo5xTTU1GoloxHA4jgj7m7TUvUl0n3rytcCSGCU 6 | gtLDDTK4p2jmpP8KQ48Dq7h7iLM/G8c8Ynnp13rWtF88q92u9K67qAQ7OiVLozq5 7 | 6sYPqsgyKQyG5B/tHUIblwsKMZAoMMOnY1qp7NYDWsPfRHFshgvbertUs5XSfrve 8 | +OIOVqtdAgMBAAECggEAL4QzTYXsLcsJIt+gpPSqZfX/QoVB6yPA8/divAx35D/Z 9 | 1JwtCN64wqstc0ldvaa8quCKXK12UFtYMJaN812jCW8zx3C4uFPgBAAk5iza9U7e 10 | 3x7u9Wr7EZuUgs+FKtyYs6ysYW9jFhPLbz7MVHjvfGZDSmKEzPQloFvD9zGC83WV 11 | /ns+UYnwVTXRvSe68idMhuyzRdl/T//FiAPVr0oq6BIAJ+YfBcGX4NA9Whcnij6Y 12 | /qHyEL3kPJGl6u8O9NwyVIPIX50/060dJabV9g28R3BRmldlKARYZtOto/PMp0eB 13 | D1a/4F/Ak18IX+XUUF796AInCtQ/mA5vM2gyrLJXbQKBgQDkax3FLFT9frmDMujK 14 | 4IzmrAfm1qM+mgNj1kRYpJVcmRr4AMGBYkDfmw5pRrMa76Ms8KaqujhNQVLqxIxb 15 | rrXRK3vjiMnb6b7Sm8fqr4us5q3jUq/u7L0KjhvUXWv6rvnc03htIviTalkC8TsA 16 | WK2dy1Es56mF+YcDt38aP22OuwKBgQC6JinfsHUCNKquNdwB/8Tb/l6D/JuZGM07 17 | 4edJSlczVhWNUD//iQ/dyTOja42MKqFs0x1Nrnf2wZSYr32ZdbIaaNxcun/qHngh 18 | 5eiyJ8Z8ulSL9GmA9DsEguz1jNC3ooeNNGZfC5vBVT9BR2ngoONA+jgt3VqIfZui 19 | Am1CNGaoxwKBgQC+W8qmnMiDrg26mj3JfZPPVYUMSsonDMFQfavd1+OmFO6VykN5 20 | qUF5WEaNU99FznpFpJSxaZosQAlzH7P9YD+j/0IzILdhb46ZBDx6iCu2P1ShQzLd 21 | wivVVRM6S1UGyLXw48fT5DYW3KUrv5A1PLIL8/pFmxb7UTXE0jK51CxgqwKBgGWn 22 | Y6SZSzyaID8kgHHDB/EPVvQC5cHUTneOJOzcIQSS1RAnq9tTMQvvzThICrNpsF+q 23 | Zk0+opppGknLQ+6i3FEZxIUK/8GNRBNW5x0rJXSFmJgZL+hQ902+ZcKuVGiD5DxT 24 | SjhLMZKBiBqQ8hvOIGwieL1rLP5ugagWZS4LSaiPAn9v//cCKLmAJT31VP1vqTOE 25 | 5b0/dFiWil+mpWifk6DpPiuNr1XpCuAK1MpBqPZpBlsDglL8lo57MklIvPixJAtg 26 | NfGFBDi5tQEOm0WpAQ9NAlxpbDKGaY+jdW+gEQOsHzO5Fj/IiCKOhMkljMbX7PYi 27 | 5wdINkqx9+DJp1dQg7cg 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /spec/fixtures/xml/cd1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 3BUCAQDZPOQEYFB4 6 | 2014-10-07T16:10:25Z 7 | 1 8 | 10.00 9 | 10 | Max Mustermann 11 | 12 | 13 | 14 | 3BUCAQDZPOQEYFB4-FRJ5-CORE-FRST 15 | DD 16 | true 17 | 1 18 | 10.00 19 | 20 | 21 | SEPA 22 | 23 | 24 | CORE 25 | 26 | FRST 27 | 28 | 2014-10-15 29 | 30 | Max Mustermann 31 | 32 | 33 | 34 | DE89370400440532013000 35 | 36 | 37 | 38 | 39 | COBADEFFXXX 40 | 41 | 42 | SLEV 43 | 44 | 45 | 46 | 47 | DE98ZZZ09999999999 48 | 49 | SEPA 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 95853B700796473D88F1009A40B4DC18 58 | NOTPROVIDED 59 | 60 | 10.00 61 | 62 | 63 | M00123456 64 | 2014-02-01 65 | false 66 | 67 | 68 | 69 | 70 | BKAUATWW 71 | 72 | 73 | 74 | Maria Musterfrau 75 | 76 | 77 | 78 | AT611904300234573201 79 | 80 | 81 | 82 | Purpose 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /spec/fixtures/xml/cd1_init_response.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 387B7BE88FE33B0F4B60AC64A63F18E2 5 | 6 | 7 | Initialisation 8 | N00L 9 | 000000 10 | [EBICS_OK] OK 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | hSf/fZURBW6ihKUUZDMRpqc3kloVZZRjw+DTBxjS7AM= 23 | 24 | 25 | IFHzo6jch33gA0Ovxh4VWtAwJOJRdxffMy7Yi+a+UUWPM/ekNqcewCWxgjbcWgD/LiH6eQc58iKcZdNKpaKfplQ09CJi1VBry5sd97i4tlCAhoM95JTrJjp2O6PhswAo+a6dpuXmA11u57BK0/nHENMIh4+Qw3aGszn21Ft8qwo= 26 | 27 | 28 | 000000 29 | 2007-10-19T14:58:39.467Z 30 | 31 |
32 | -------------------------------------------------------------------------------- /spec/fixtures/xml/cd1_transfer_response.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 387B7BE88FE33B0F4B60AC64A63F18E2 5 | 6 | 7 | Transfer 8 | 1 9 | N00L 10 | 000000 11 | [EBICS_OK] OK 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 000000 30 | 2007-10-19T14:58:39.467Z 31 | 32 |
33 | -------------------------------------------------------------------------------- /spec/fixtures/xml/cdb.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 1434018161 6 | 2015-06-11T12:22:41+02:00 7 | 1 8 | 1.12 9 | 10 | Max Musterman 11 | 12 | 13 | 14 | 1434018161/1 15 | DD 16 | true 17 | 1 18 | 1.12 19 | 20 | 21 | SEPA 22 | 23 | 24 | B2B 25 | 26 | RCUR 27 | 28 | 2015-06-15 29 | 30 | Max Mustermann 31 | 32 | 33 | 34 | DE89370400440532013000 35 | 36 | 37 | 38 | 39 | COBADEFFXXX 40 | 41 | 42 | SLEV 43 | 44 | 45 | 46 | 47 | DE98ZZZ09999999999 48 | 49 | SEPA 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 86 58 | 59 | 1.12 60 | 61 | 62 | M123123 63 | 2015-06-01 64 | 65 | 66 | 67 | 68 | BKAUATWW 69 | 70 | 71 | 72 | Maria Musterfrau 73 | 74 | 75 | 76 | AT611904300234573201 77 | 78 | 79 | 80 | Purpose 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /spec/fixtures/xml/cdb_init_response.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 387B7BE88FE33B0F4B60AC64A63F18E2 5 | 6 | 7 | Initialisation 8 | N00L 9 | 000000 10 | [EBICS_OK] OK 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | hSf/fZURBW6ihKUUZDMRpqc3kloVZZRjw+DTBxjS7AM= 23 | 24 | 25 | IFHzo6jch33gA0Ovxh4VWtAwJOJRdxffMy7Yi+a+UUWPM/ekNqcewCWxgjbcWgD/LiH6eQc58iKcZdNKpaKfplQ09CJi1VBry5sd97i4tlCAhoM95JTrJjp2O6PhswAo+a6dpuXmA11u57BK0/nHENMIh4+Qw3aGszn21Ft8qwo= 26 | 27 | 28 | 000000 29 | 2007-10-19T14:58:39.467Z 30 | 31 |
32 | -------------------------------------------------------------------------------- /spec/fixtures/xml/cdb_transfer_response.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 387B7BE88FE33B0F4B60AC64A63F18E2 5 | 6 | 7 | Transfer 8 | 1 9 | N00L 10 | 000000 11 | [EBICS_OK] OK 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 000000 30 | 2007-10-19T14:58:39.467Z 31 | 32 |
33 | -------------------------------------------------------------------------------- /spec/fixtures/xml/cip.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Message-ID-0815 6 | 2022-09-15T09:31:39.000Z 7 | 2 8 | 1122.33 9 | 10 | Initiator Name 11 | 12 | 13 | 14 | Payment-Information-ID-0815 15 | TRF 16 | true 17 | 2 18 | 1122.33 19 | 20 | 21 | SEPA 22 | 23 | 24 | INST 25 | 26 | 27 | 28 | 2022-09-16T10:00:00 29 | 30 | 31 | Herr Schnellzahler 32 | 33 | 34 | 35 | DE89370400440532013000 36 | 37 | 38 | 39 | 40 | 41 | NOTPROVIDED 42 | 43 | 44 | 45 | SLEV 46 | 47 | 48 | OriginID1 49 | 50 | 51 | 1022.00 52 | 53 | 54 | John Dough 55 | 56 | 57 | 58 | AT611904300234573201 59 | 60 | 61 | 62 | Unstructured Remittance Information 63 | 64 | 65 | 66 | 67 | OriginID2 68 | 69 | 70 | 100.33 71 | 72 | 73 | Cookie Cutter 74 | 75 | 76 | 77 | AT611904300234573201 78 | 79 | 80 | 81 | Unstructured Remittance Information 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /spec/fixtures/xml/ebics_business_nok.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 000000 6 | [EBICS_OK] OK 7 | 8 | 9 | 10 | 11 | 12 | rwIxSUJAVEFDQ0sdYe+CybdspMllDG6ArNtdCzUbT1E= 13 | CPdd6ODXrCxHWpYrwS/5a3NIZ1R2SDscHHJSONc2I7g8ara7qv5Ra7H03W+336DPQLZQxH+EBRWdE2FQ1vrVTcypK6fkFarmO1dEtQt6Ka89AozC7aQMyp4yGl+zlF+XvFkJXZbRXgoEOPsgcG0xM6nKLXnr1ThYRFOoAasigLDGwqxliyhoR94F9dL7YB8Le/uZeRj78mNp4smkE5ZKKyPhwVx+0IW78YuVCSC2c2qbsMmm4evAvycdpLfuuoG4KVlNMIlvkKeBfMZFELcmeKKm85D2zPYkZ7cqG2IfAAp5qdS6K8P7RY4gtjUhOtP5mi8bZt/ZcjioUmIR9dAMnA== 14 | 15 | lJ/v1HvOYAZKTPkxULH4mOcUy01+EaAsxLzCPhtieAo9m5AtU5URdyBVfmclHbtWe3ELb02lR37bChynq0Esqpljxx7CiB+kl/bVs7XkNQQmtGPlh08O7ApJ7AHdKPFFvE+SM2OWpSwUrqJGtmyaU6s+RM66o/3Q0wvKi4y3+Q2jm8nkiWZpPfNt52g4ReE9Ge86o+L+EBOBgZm634L5Z/i6pq908mXBAklPdk1ERdEgWONaOeYYmB70FToplR1gINJEF2CnfAtD/wV+DuQFPDth+EWHqhe3a4xO0d9eJ55ou2QCYOPUC2g/qz1sp7GR74W7P5IWJdmnUEuPFsKJ6OvM+1V8S06jZGDa/QhUGDK8F3G/TMP09W1MsrlQTRr3YQ5H43+pMY7I6Jysze+X9OKZZTTpv4GmYm1USjmraGyMuPF3j9hrlmpttK+1gg2WzytCJO44YsZp9ckls8JNK4bT5uwTuomKZoRgmiIOTcMh4VP7V28TWj2XdF+T6rBFILTvQyXMOzvbe1kLwg2O31JDBdJ8X1fHCYJxKsIrYCSDPz4sha8h7QmHrCSFmjoXb+LUElnbLXZVRkY5/Dc73EM6Es3wAgjwSJK2asRqdqU0PhbS5qpIlgYKsNcb+Wes 16 | 17 | 091116 18 | 2007-10-19T14:58:39.467Z 19 | 20 | 21 | -------------------------------------------------------------------------------- /spec/fixtures/xml/ebics_technical_nok.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 061001 7 | [EBICS_AUTHENTICATION_FAILED] Authentication signature error 8 | 9 |
10 | 11 | 12 |
13 | -------------------------------------------------------------------------------- /spec/fixtures/xml/haa.xml: -------------------------------------------------------------------------------- 1 | 2 |
SIZBN00195149241ead8ae7dbb72cabe966bf0e32017-10-17T19:56:33ZEBICSEBIXEPICS - a ruby ebics kernelHAADZHNNdFAYe281vj9NB7w+VoWIdfHnjY9hNbZLbHsDOu76QAE=dFAYe281vj9NB7w+VoWIdfHnjY9hNbZLbHsDOu76QAE=0000Initialisation
3 | -------------------------------------------------------------------------------- /spec/fixtures/xml/haa_receipt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | SIZBN001 6 | 7 | 8 | 9 | Receipt 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 0 29 | 30 | 31 |
32 | -------------------------------------------------------------------------------- /spec/fixtures/xml/hia_request_order_data.xml: -------------------------------------------------------------------------------- 1 | 2 | phfg5Gv/4wrsGtO2mo33UxciC/DSmw0RdbBhC5vVPsqgmvlDgZ1bpsGWwsXOiBU5BxpbCNvtBLS7jR/4tSgNiDrWmJPLM05ygFKzhyh/8Nd2qtZCt/JaQunsSfNpILm+b9h1ZiuQRnCOsvsJq7eUCrqJnU5Lf/AWWE5g9PlaOcU01NRqJaMRwOI4I+5u01L1JdJ968rXAkhglILSww0yuKdo5qT/CkOPA6u4e4izPxvHPGJ56dd61rRfPKvdrvSuu6gEOzolS6M6uerGD6rIMikMhuQf7R1CG5cLCjGQKDDDp2NaqezWA1rD30RxbIYL23q7VLOV0n673vjiDlarXQ==AQABX0021rkjZF6T4C6694CmiObpwI98k4ngaqDeBpIQV8mn2/REArEjngwanJJbdN51pCy/Sn10ZitqPss4mPpykcTJyNDxOzdZk12wdzIooTiyyMJoI8N+sTWBWlGvT8ER2ZEHObZJAGWqB6sORjTERPqqsQ8+sUNcSoSXfcnMVrbgpbVS/LsgQwlnq2pmsRq35DkVf+03UhYs3QkptzhaQXGFmbDDb4opTxp1ZgJqzl6H+GDDhFA5+xz1C5Pa4OL2jNOCyuRu60wymH1gc6cOmXvYTKyCSVY+k8/wPdq6rF1ylacTEWFhbi+1ZA8RVJPqQzOe6gXxMXFFoKTen1TtkgXm6Q==AQABE002EBICSEBIX -------------------------------------------------------------------------------- /spec/fixtures/xml/hpb.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | HOST 6 | 7 | 8 | PARTNER 9 | USER 10 | EPICS - a ruby ebics kernel 11 | 12 | HPB 13 | DZHNN 14 | 15 | 0000 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | -------------------------------------------------------------------------------- /spec/fixtures/xml/hpb_request.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | HOST 6 | 014a82626a51ee1cab547bbaf18a13a0 7 | 2014-09-09T09:33:12Z 8 | PARTNER 9 | USER 10 | EPICS - a ruby ebics kernel 11 | 12 | HPB 13 | DZHNN 14 | 15 | 0000 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 5PL08o8acS8kewViTEeVqSiWZshzNG3QgZehRk1EJgg= 29 | 30 | 31 | d+qgWNti7uCsB/CWreyw9AGQOJiqU+CPPrpgdcisauUvJhFszEJasBeky9TsJXgxVsT27fZaHGnV2pO1YwlBmSuJSGRg5ijHCxbG+XyisIwVAVXY7mlkaO5Ms4eznaW2GCPhiwmIJZOcvzYZwzxtrCbAQFoKA+QgBaAytBtWJiOe8nErnb5s7OEg2D0NvWG4hV+NdcXPlUEKiY5Rw4qCukGXnpZmwMw/L+TB1v47eOLpQa/Dl2oJCjZgV4og3Q2o88adpErnKtIdKic8mb5FLXa2gFK63fmpCcwvs8FPb3kR7/QLWSs4WYycKcXDmgDKnVwYYcBfANEq1yFgReRjzQ== 32 | 33 | 34 |
-------------------------------------------------------------------------------- /spec/fixtures/xml/hpb_response_ebics_ns.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 000000 6 | [EBICS_OK] OK 7 | 8 | 9 | 10 | 11 | 12 | rwIxSUJAVEFDQ0sdYe+CybdspMllDG6ArNtdCzUbT1E= 13 | CPdd6ODXrCxHWpYrwS/5a3NIZ1R2SDscHHJSONc2I7g8ara7qv5Ra7H03W+336DPQLZQxH+EBRWdE2FQ1vrVTcypK6fkFarmO1dEtQt6Ka89AozC7aQMyp4yGl+zlF+XvFkJXZbRXgoEOPsgcG0xM6nKLXnr1ThYRFOoAasigLDGwqxliyhoR94F9dL7YB8Le/uZeRj78mNp4smkE5ZKKyPhwVx+0IW78YuVCSC2c2qbsMmm4evAvycdpLfuuoG4KVlNMIlvkKeBfMZFELcmeKKm85D2zPYkZ7cqG2IfAAp5qdS6K8P7RY4gtjUhOtP5mi8bZt/ZcjioUmIR9dAMnA== 14 | 15 | tPp8sZbGSkjaUy4IoNektKEK1KekTQxLwIZ+AYhyuL99erg26xK1ZcvXd+vJwSfl5TV21qQHybID5CnnP5ZvjcxBdwrK0hyMyp2FYJAY16wLAt++Esydx55XSBvutQASBEnPd01uq3Gd4tPLLbrlBGCDEtqJcfbLEOyWvxYFNDb/HU6RpOCD7JN3jL+LRLsFfrZEK96QO8IzpCtiAYBJ6C3OaHsETt0wBx1lYy7JBSw+nIEEzE6+N3EjJjE3++9BfCDE0ca7kpWCSJ666dUuelPuIS45LjcFbTGROdZ1BTJc6F39Zjxud2yUJIEJINQUZA2O8628gVi2GvoUZuILFx1TsCik1T2ims7EVqkfSNEBpKCa3mtmNMEFepdXNTBm3Kf+J+5ATnqq1EJrYBkGpDPii4jgvVPNIkXJlx5DqqhgUUCShnCLOingwrE+z5ekRM5091iHl1C4APfR05gl0Q81D5HiV9m4CuMjx4Lp7mm0vdgP1LNiaA1BnKIeFob+4SN4Kv7AoP7nxk+3nINMd0yGujsnMx6WgGFn4lvv7IH250+LUZJM4rkdVx9FacxU+P+B6+GDHpLKZyT84WKvPXWnoIhPpykR/Pbysoe+WdAf7cMVp9K5Q5QhfPaMu2eIZjR5+IRIUXxhTo8k2vDG4XBcjgVygP5GJAN83pjXuwdo5JRxyGZAOqvBr7cHmmCG 16 | 17 | 000000 18 | 2007-10-19T14:58:39.467Z 19 | 20 | 21 | -------------------------------------------------------------------------------- /spec/fixtures/xml/hpb_response_order.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | AJ2/0OoIZydb9sgKbiwqDcwA0NtcUMIYi6GK7PqoRszu1uytGnxJjQhGt62kMslWvLgebUSwdq/T3YyGsa3KQeIGaUUn9iqyu3BoNOMdo2DLN4NdGMY1WR/HbYRKR3JHyURhTBKw27KScRRdKGl6jY+VcXcTKJL8PjXMQH5cD6Gz 7 | AQAB 8 | 9 | 2007-03-13T11:33:16.616Z 10 | 11 | X002 12 | 13 | 14 | 15 | 16 | AJ2/0OoIZydb9sgKbiwqDcwA0NtcUMIYi6GK7PqoRszu1uytGnxJjQhGt62kMslWvLgebUSwdq/T3YyGsa3KQeIGaUUn9iqyu3BoNOMdo2DLN4NdGMY1WR/HbYRKR3JHyURhTBKw27KScRRdKGl6jY+VcXcTKJL8PjXMQH5cD6Gz 17 | AQAB 18 | 19 | 2007-03-13T11:33:16.616Z 20 | 21 | E002 22 | 23 | SIZBN001 24 | 25 | -------------------------------------------------------------------------------- /spec/fixtures/xml/hpb_response_order_without_ns.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | AJ2/0OoIZydb9sgKbiwqDcwA0NtcUMIYi6GK7PqoRszu1uytGnxJjQhGt62kMslWvLgebUSwdq/T3YyGsa3KQeIGaUUn9iqyu3BoNOMdo2DLN4NdGMY1WR/HbYRKR3JHyURhTBKw27KScRRdKGl6jY+VcXcTKJL8PjXMQH5cD6Gz 7 | AQAB 8 | 9 | 2007-03-13T11:33:16.616Z 10 | 11 | X002 12 | 13 | 14 | 15 | 16 | AJ2/0OoIZydb9sgKbiwqDcwA0NtcUMIYi6GK7PqoRszu1uytGnxJjQhGt62kMslWvLgebUSwdq/T3YyGsa3KQeIGaUUn9iqyu3BoNOMdo2DLN4NdGMY1WR/HbYRKR3JHyURhTBKw27KScRRdKGl6jY+VcXcTKJL8PjXMQH5cD6Gz 17 | AQAB 18 | 19 | 2007-03-13T11:33:16.682Z 20 | 21 | E002 22 | 23 | SIZBN001 24 | 25 | -------------------------------------------------------------------------------- /spec/fixtures/xml/htd_order_data.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Railslove GmbH 6 | Deutschland 7 | 8 | 9 | SIZBN001 10 | 11 | 12 | 1929807319 13 | DE51370501981929807319 14 | 37050198 15 | COLSDE33XXX 16 | 17 | 18 | HTD 19 | Download 20 | Kunden- und Teilnehmerdaten abholen 21 | 22 | 23 | STA 24 | Download 25 | Abholen SWIFT-Tagesauszüge 26 | 27 | 28 | PTK 29 | Download 30 | Abholen Kundenprotokoll 31 | 32 | 33 | HPD 34 | Download 35 | Bankparameter abholen 36 | 37 | 38 | HAC 39 | Download 40 | HAC 41 | 42 | 43 | HAA 44 | Download 45 | Abrufbare Auftragsarten abholen 46 | 47 | 48 | HVT 49 | Download 50 | VEU-Transaktionsdetails abrufen 51 | 52 | 53 | HVU 54 | Download 55 | VEU-Übersicht abholen 56 | 57 | 58 | HVD 59 | Download 60 | VEU-Status abrufen 61 | 62 | 63 | HPB 64 | Download 65 | Abholen Public-Keys der Bank 66 | 67 | 68 | HVZ 69 | Download 70 | VEU-Übersicht mit Zusatzinformationen abholen 71 | 72 | 73 | CCS 74 | Upload 75 | CCS 76 | 1 77 | 78 | 79 | INI 80 | Upload 81 | Passwort-Initialisierung 82 | 1 83 | 84 | 85 | HIA 86 | Upload 87 | Initiales Senden Public Key 88 | 89 | 90 | HCA 91 | Upload 92 | Senden Public Key 93 | 1 94 | 95 | 96 | HSA 97 | Upload 98 | Initiales Senden Public Key 99 | 1 100 | 101 | 102 | SPR 103 | Upload 104 | Sperren der Zugangsberechtigung 105 | 106 | 107 | PUB 108 | Upload 109 | Senden Public Key zur Unterschrift 110 | 1 111 | 112 | 113 | HVE 114 | Upload 115 | VEU-Unterschrift hinzufügen 116 | 1 117 | 118 | 119 | HVS 120 | Upload 121 | VEU-Storno 122 | 1 123 | 124 | 125 | CCT 126 | Upload 127 | Credit Transfer Initiation 128 | 1 129 | 130 | 131 | CIP 132 | Upload 133 | Instant Credit Transfer Initiation 134 | 1 135 | 136 | 137 | CD1 138 | Upload 139 | CD1 140 | 1 141 | 142 | 143 | CDB 144 | Upload 145 | CDB 146 | 1 147 | 148 | 149 | CDD 150 | Upload 151 | Direct Debit Initiation 152 | 1 153 | 154 | 155 | 156 | EBIX 157 | Ebi, Epics 158 | 159 | PTK HPD HTD STA HVD HPB HAA HVT HVU HVZ 160 | 161 | 162 | INI SPR PUB HIA HCA HSA HVE HVS CCS CCT CIP CD1 CDB CDD 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /spec/fixtures/xml/htd_order_data_without_names.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Railslove GmbH 6 | Deutschland 7 | 8 | 9 | SIZBN001 10 | 11 | 12 | HTD 13 | Download 14 | Kunden- und Teilnehmerdaten abholen 15 | 16 | 17 | 18 | EBIX 19 | Ebi, Epics 20 | 21 | HTD 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /spec/fixtures/xml/ini_response_h004_ns.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | B004 6 | 000000 7 | [EBICS_OK] OK 8 | 9 | 10 | 11 | 000000 12 | 13 | 14 | -------------------------------------------------------------------------------- /spec/fixtures/xml/jruby/hia.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 |
6 | 7 | SIZBN001 8 | EBICS 9 | EBIX 10 | EPICS - a ruby ebics kernel 11 | 12 | HIA 13 | DZNNN 14 | 15 | 0000 16 | 17 | 18 |
19 | 20 | 21 | eJzNlEuTqkgQhffzKzqcpTHNQ0A0bG8gIILIW6Td8RIQKKCKh/jrx+ients9cze9mtlVnpMnqyLyi1r9uJXFUx9DlFXgZUI845OnGIRVlIHkZdK1lz/YyY/1b6udzFlx08Wo1WEUQ8Fv/adHEqBHEwTLCibLOMhCtNzhODV5t5bRw03btl5i2DAMz8Ps+dGHkTiOY/gCe/REKEt+n6xXXNemMWiz0G8fzzC6YB+PMrhU69X72fWLLl6vIrS0bO6j/u4lj/ShirqiQ99M1ukloaUeowaIpFYny2o2O97CjMcEuxxwKwo2KU/3roGapOwLITkTQY2k04A8Pdsc6c2tDnitbzeqPb9aGNXaiZYJ8FQqhnrA6THZ7u/pmGKsFpFNe+ZbTPHNDiD7otWyWk6DRUqcs860AK+jHinNPD7ysFHAkVYvGHc6iXSyMApfD484oVmN4h+sQZcpeUp3OKESSqQsGBZ6XJ4mhazaw4CP3T6q6MbB+Fw3OKajYiq7G7d+Z0gKzUQRQ0DrYuz7CPZ21zGJqN+rwmYOTBdDSWCgfMjyQ9qZl7lF8BIdqvxVMveCINSk5jfx/cQRUJjh1i2QX1Vy1sxdVXdxwMxn/TUTCh965svLCvu5krf1iLe6Ag8OvrkfzuQ2b7M+8uu36hMqD+ELSF95c9/pX3s4Tq6wX3v/1D8zKoIQjvX/kVwC5tfzlnEonmEWFF9melAP8oLNKZD4jRBvatl02RKQmCVyULyCZPCBogSRRhM1P2I2IPBz1jYGQlRp1GMeOsqoCTf9Hp1zghyiu1xVTjaOB6WSWW2KnNPmVEi9w4oWeRZ3enBWOOnUbBikW1dHtIymQSY7RUcttCvbu4Tg4MIgqQPXxlSUmEMBGrIukdXMaCF3L1N8dkxf0czM6/ae+qYnbctAEAKqqp1bTZwTpbkXzG4qCUK65ejp7U7wtOFTukpeNZ0fO6tj8GEsd0QSMqFeev2rsx95232d5iw2GFHDwC0xFn7oiKdtGmRT4syxlqsYjXnXYybxbgdvu632TgwIp80Tr2T+U3J/svZBpvhG7b/1z9oXLn3YghjKwlrcyLz9mP+3sDqiD8NbYX8VK+wXf//6T/odHps= 22 | 23 | 24 |
25 | -------------------------------------------------------------------------------- /spec/fixtures/xml/jruby/ini.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 |
6 | 7 | SIZBN001 8 | EBICS 9 | EBIX 10 | EPICS - a ruby ebics kernel 11 | 12 | INI 13 | DZNNN 14 | 15 | 0000 16 | 17 | 18 |
19 | 20 | 21 | eJyVU8tyokAU3c9XpJjl1KQbRQMWkuKlPGSEkAhmB+kWEW2gaUDz9WOZyWuySlUv+p57zrmLe658ezzsrzpMm7wkU46/htwVJk8lykk25Vq2+S1yt8oPOcwzkrCWYr9NXXxaUoSpkbDk6iwnzZTbMlZNAOj7/hqn+VNzXdIMhBDy3Atjgj6T+uGFMYAQAiiBMwc1efaTU/6fZJNNqcgv/1Wyb7Eio2ZyF6qv9Xf9z2qvRO2+bb6p5IVRefMo4phUlLHjInvQkeS7YuI6bbJwRkNIrFh3RDdf3vhee0DOKkHNMk0N24ql7RNdxdIpeqBC47Ia7J7NE841elfNjvGc2e6g0FJBtKpkE5l1wKdJCtRcAKvIEBprHei9FomufWpcYq+ru2DNG8QKflnDeDPbhhrZreZUtCFJjUwfCK7WdkUtzXxdLEOQFQE5UPdxNKBot4jCYT0sENODzjsVvTCHffcnmDv7EERHTy9CSDfQgfauX6vhcc+ne0FyBl3XLcK6N5jq+LMkstsCepaVmeNRRny45cfLGvL+zlP99qha1bZekKzzSBgVeG0gVtKNtMOqeaDmAq2RPQP02aK100+nMnhfyWU95rEqCSbsm/tRA1W7eL3qlUv1ISqKfJ8fcMiSQ6UMIC/85uH53fP8hB9PIHyUwXtfBp8y95bK1cupKCqEYxl8gT9An/KbUEYwtQ3F1Gw9PJu/AfJD89qIZfCv+GLzdnDKX0j2PtE= 22 | 23 | 24 |
25 | -------------------------------------------------------------------------------- /spec/fixtures/xml/ruby/hia.xml: -------------------------------------------------------------------------------- 1 | 2 |
SIZBN001EBICSEBIXEPICS - a ruby ebics kernelHIADZNNN0000
eJytlEuTokgUhff9KyqcpTGVgECpYdmBgAgib5Fyx0tAIIFMHuKvH6dquqdqplcTs8t7zs0bGfd8kavvt7J46mOEswq+TshnYvIUw7CKMpi8Trr28vt88n39bbWTOStuuhi3OopiJPit//S4CfEywq+TtG3rJQDDMDwPs+cKJYAiCAIQC/DoiXCW/Db56H6MRHD5aFjGQRbi5Y4g6Ml6xXVtGsM2C/328QyjC/bxKMNLtV59nF2/6OL1KsJLy+a+1Icq6ooOr+v0kjBSD+gBYanVqbKazY63MOOBYJcDYUXBJuWZ3jVwk5R9ISRnMqixdBqwp2ebI7O51QGv9e1GtV+uFqBbO9EyAZ1KxVAPBDMm2/09HVMw1yKqac98CxTf7CC2L1otq+U0WKTkOetMC/I67rHSvMRHHjUKPDLqBXCnk8gkC6Pw9fBIkJrVKP7BGnSZlqdMR5AqqUTKgp0jj8vTpJBVexiIsdtHFdM4gM91g2M7Oqazu3Hrd4akMGwUsSSyLsa+j1Bvdx2biPq9Kmz2wHYxkgQWyYcsP6SdeXmxSF5iQpW/SuZeEISa0vwmvp84EgkzwroF8ptKzZoXV9VdArIvs/6aCYWPPPP1dQU+LfnPhYu3uoKPrNacyW3e3Z/Ke/UlIPAlvq8pux/MrT2CoFbg194/9c9kiDBEY/1feSFRfj1vWYfmWXZB82WmB/UgL+Y5DRO/EeJNLZvuvIQUsEQOiVeYDD5UlCDSGLLmR2BDkjhnbWNgTJdGPeaho4yacNPv0TknqSG6y1XlZON4UCp5rk2xc9qcCql35qJFncWdHpwVTjo1Gxbr1tURLaNpsDmf4qMW2pXtXUJ4cFGQ1IFrAxUn5lDAhqpLbDUzRsjdy5SYHdM3PDPzur2nvulJ2zIQhICuaudWk+dEae4Fu5tKgpBuOWZ6u5M8Y/i0rlJXTefHzupYYhjLHZmEbKiXXv/m7Efedt+m+RwMRtSwaEuOhR864mmbBtmUPHNzy1WMxrzrMZt4t4O33VZ7J4ak0+aJV7L/My9/J/yDB/GdlX/rn7UvNPiohTGShbW4kXn7Mf+nsDriH4a3An8VK/CLf2797Q98eMYK
3 | -------------------------------------------------------------------------------- /spec/fixtures/xml/ruby/ini.xml: -------------------------------------------------------------------------------- 1 | 2 |
SIZBN001EBICSEBIXEPICS - a ruby ebics kernelINIDZNNN0000
eJxlUltzmkAUfs+vyNDHTrOLogEHyXBTLlIhJIJ5g+yKiC6wLKD59bVJa2Mzcx72u5yzM+d88sPxsL/tMG3ykkw5/g5yt5i8lign2ZRr2eaHyD0oN3KYZyRhLcV+m7r4tKQIUyNhye25nTQT1Ey5LWPVBIC+7+/64V1JMzCAEAIogbMHNXn2jftwX1lxmr827+4QQp5T/v/JJptSkT/eq2TfYkVGzeQxVK+wV6J23zYKL4zK+xcRx6SijB0X2bOOJN8VE9dpk4UzGkJixbojuvny3vfaA3JWCWqWaWrYVixtX+kqlk7RMxUal9Vg92aecK7Rx2p2jOfMdgeFlgqiVSWbyKwDPk1SoOYCWEWG0FjrQO+1SHTtU+MSe109BmveIFbw3RrGm9k21MhuNaeiDUlqZPpAcLW2K2pp5utiGYKsCMiBui+jAUW7RRQO62GBmB503qnohTnsu5/B3NmHIDp6ehFCuoEOtHf9Wg2Pez7dC5Iz6LpuEda9wVTHnyWR3RbQs6zMHI8y4sMtP17WkPd3nuq3R9WqtvWCZJ1HwqjAawOxkm6kHVbNAzUXaI3sGaBvFq2dfjqVwacl/164eaxKgglT1EDV3tUL846uDvSUH3DIkkOlDCAv/ODhuZ54fsKPJxC+yOCfLoOrS1+ysPoIqKJCOJbBF/oTdZWahDKCqW0opmbr4Xn4hZCfm79CLIM/4MuYS8yVm1/X5hKV
3 | -------------------------------------------------------------------------------- /spec/fixtures/xml/signature_pub_key_order_data.xml: -------------------------------------------------------------------------------- 1 | 2 | 145o7Z8eXnprttxLgUCd9PK8aKJuaLJ530nHXCJ8KiO7PMumdJVadsObbDIHX9hcrVX9yWUr4sKtq/jzEyeiBrRpFxXGtIK2kBb48HpafWEqQ1bab/Ai4/VWD4sHYQCwBW8KIysKnIYpRQY1DnHQ+H3XfFhSBnjVGr8I0nbDgC24KBuvkq9FPC8oS/gkQnmrKZ52rdjLWS3q3kdtCQvMykw4G0wvNQGJlS/WxMCkS0rf0J0IjwYASxl1bl49J2vvvLSqwDtAJPFaWIuk0MHHgE65gnP0h16Oq01PjMAPuxAHphqLngvMnSWkeYDdtorf9jeAEmrELdYdIF/rzHrqJw==AQAB2014-10-10T11:16:00ZA006EBICSEBIX -------------------------------------------------------------------------------- /spec/fixtures/xml/sta_response.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | ECD6F062AAEDFA77250526A68CBEC549 6 | 1 7 | 8 | 9 | Initialisation 10 | 1 11 | 000000 12 | [EBICS_OK] OK 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | OnY4VczV+1XfplpMS/SCKFWn+FDMge40X8TJ9pA6HEI= 25 | 26 | 27 | Qiz8clr/Ym+wLpB8CzTuxKP5rgIR2P4SaX8O4gGZx0Di8Lzd4hsBO3koqIuX11NRZo0RYA5E/IKQCoYLepkcM4QHvLT37YidbrXsTZe6cml/yF8OdyRAcd/9U7AoA9GKENFk4lnBFfZYmM4ADK6wVOCE/ABaOk0NeCDDbxrKA75tfTxwxTvQBfUOHZ87LrZxuQf//L9pzmtI07/7GbsQX8ZceQq40SpBFZn/oRvT/Q38Qu2ZO59MZexJn+BTzlhpfv9fQGF/sgXkdhUkPTEW3nL4j7ehasq3CtySGO2RnEppohEvJ4m07RDtEY3OWyAAZoPFVpvnECM6pOLbIuR40w== 28 | 29 | 30 | 31 | 32 | IUW05JB5cuCzRYYa4kIAZ2ehYVrLI3lKvxZvo1uP+ug= 33 | CPdd6ODXrCxHWpYrwS/5a3NIZ1R2SDscHHJSONc2I7g8ara7qv5Ra7H03W+336DPQLZQxH+EBRWdE2FQ1vrVTcypK6fkFarmO1dEtQt6Ka89AozC7aQMyp4yGl+zlF+XvFkJXZbRXgoEOPsgcG0xM6nKLXnr1ThYRFOoAasigLDGwqxliyhoR94F9dL7YB8Le/uZeRj78mNp4smkE5ZKKyPhwVx+0IW78YuVCSC2c2qbsMmm4evAvycdpLfuuoG4KVlNMIlvkKeBfMZFELcmeKKm85D2zPYkZ7cqG2IfAAp5qdS6K8P7RY4gtjUhOtP5mi8bZt/ZcjioUmIR9dAMnA== 34 | 35 | lJ/v1HvOYAZKTPkxULH4mOcUy01+EaAsxLzCPhtieAo9m5AtU5URdyBVfmclHbtWe3ELb02lR37bChynq0Esqpljxx7CiB+kl/bVs7XkNQQmtGPlh08O7ApJ7AHdKPFFvE+SM2OWpSwUrqJGtmyaU6s+RM66o/3Q0wvKi4y3+Q2jm8nkiWZpPfNt52g4ReE9Ge86o+L+EBOBgZm634L5Z/i6pq908mXBAklPdk1ERdEgWONaOeYYmB70FToplR1gINJEF2CnfAtD/wV+DuQFPDth+EWHqhe3a4xO0d9eJ55ou2QCYOPUC2g/qz1sp7GR74W7P5IWJdmnUEuPFsKJ6OvM+1V8S06jZGDa/QhUGDK8F3G/TMP09W1MsrlQTRr3YQ5H43+pMY7I6Jysze+X9OKZZTTpv4GmYm1USjmraGyMuPF3j9hrlmpttK+1gg2WzytCJO44YsZp9ckls8JNK4bT5uwTuomKZoRgmiIOTcMh4VP7V28TWj2XdF+T6rBFILTvQyXMOzvbe1kLwg2O31JDBdJ8X1fHCYJxKsIrYCSDPz4sha8h7QmHrCSFmjoXb+LUElnbLXZVRkY5/Dc73EM6Es3wAgjwSJK2asRqdqU0PhbS5qpIlgYKsNcb+Wes 36 | 37 | 000000 38 | 2013-12-09T15:14:30.000Z 39 | 40 |
41 | -------------------------------------------------------------------------------- /spec/fixtures/xml/sta_response_continued.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | ECD6F062AAEDFA77250526A68CBEC549 6 | 2 7 | 8 | 9 | Initialisation 10 | 1 11 | 000000 12 | [EBICS_OK] OK 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | OnY4VczV+1XfplpMS/SCKFWn+FDMge40X8TJ9pA6HEI= 25 | 26 | 27 | Qiz8clr/Ym+wLpB8CzTuxKP5rgIR2P4SaX8O4gGZx0Di8Lzd4hsBO3koqIuX11NRZo0RYA5E/IKQCoYLepkcM4QHvLT37YidbrXsTZe6cml/yF8OdyRAcd/9U7AoA9GKENFk4lnBFfZYmM4ADK6wVOCE/ABaOk0NeCDDbxrKA75tfTxwxTvQBfUOHZ87LrZxuQf//L9pzmtI07/7GbsQX8ZceQq40SpBFZn/oRvT/Q38Qu2ZO59MZexJn+BTzlhpfv9fQGF/sgXkdhUkPTEW3nL4j7ehasq3CtySGO2RnEppohEvJ4m07RDtEY3OWyAAZoPFVpvnECM6pOLbIuR40w== 28 | 29 | 30 | 31 | 32 | IUW05JB5cuCzRYYa4kIAZ2ehYVrLI3lKvxZvo1uP+ug= 33 | CPdd6ODXrCxHWpYrwS/5a3NIZ1R2SDscHHJSONc2I7g8ara7qv5Ra7H03W+336DPQLZQxH+EBRWdE2FQ1vrVTcypK6fkFarmO1dEtQt6Ka89AozC7aQMyp4yGl+zlF+XvFkJXZbRXgoEOPsgcG0xM6nKLXnr1ThYRFOoAasigLDGwqxliyhoR94F9dL7YB8Le/uZeRj78mNp4smkE5ZKKyPhwVx+0IW78YuVCSC2c2qbsMmm4evAvycdpLfuuoG4KVlNMIlvkKeBfMZFELcmeKKm85D2zPYkZ7cqG2IfAAp5qdS6K8P7RY4gtjUhOtP5mi8bZt/ZcjioUmIR9dAMnA== 34 | 35 | lJ/v1HvOYAZKTPkxULH4mOcUy01+EaAsxLzCPhtieAo9m5AtU5URdyBVfmclHbtWe3ELb02lR37bChynq0Esqpljxx7CiB+kl/bVs7XkNQQmtGPlh08O7ApJ7AHdKPFFvE+SM2OWpSwUrqJGtmyaU6s+RM66o/3Q0wvKi4y3+Q2jm8nkiWZpPfNt52g4ReE9Ge86o+L+EBOBgZm634L5Z/i6pq908mXBAklPdk1ERdEgWONaOeYYmB70FToplR1gINJEF2CnfAtD/wV+DuQFPDth+EWHqhe3a4xO0d9eJ55ou2QCYOPUC2g/qz1sp7GR74W7P5IWJdmnUEuPFsKJ6OvM+1V8S06jZGDa/QhUGDK8F3G/TMP09W1MsrlQTRr3YQ5H43+pMY7I6Jysze+X9OKZZTTpv4GmYm1USjmraGyMuPF3j9hrlmpttK+1gg2WzytCJO44YsZp9ckls8JNK4bT5uwTuomKZoRgmiIOTcMh4VP7V28TWj2XdF+T6rBFILTvQyXMOzvbe1kLwg2O31JDBdJ8X1fHCYJxKsIrYCSDPz4sha8h7QmHrCSFmjoXb+LUElnbLXZVRkY5/Dc73EM6Es3wAgjwSJK2asRqdqU0PhbS5qpIlgYKsNcb+Wes 36 | 37 | 000000 38 | 2013-12-09T15:14:30.000Z 39 | 40 |
41 | -------------------------------------------------------------------------------- /spec/fixtures/xml/swiss_credit_transfer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SPS-KING/7c332aeb9ec40d29232691 6 | 2024-06-20T17:27:56+02:00 7 | 1 8 | 102.50 9 | 10 | Schuldner GmbH 11 | 12 | 13 | 14 | SPS-KING/7c332aeb9ec40d29232691/1 15 | TRF 16 | false 17 | 1 18 | 102.50 19 | 20 | 21 | SEPA 22 | 23 | 24 | 1999-01-01 25 | 26 | Schuldner GmbH 27 | 28 | 29 | 30 | CH5481230000001998736 31 | 32 | 33 | 34 | 35 | RAIFCH22 36 | 37 | 38 | SLEV 39 | 40 | 41 | NOTPROVIDED 42 | 43 | 44 | 102.50 45 | 46 | 47 | 48 | CRESCHZZ80A 49 | 50 | 51 | 52 | Contoso AG 53 | 54 | Mustergasse 55 | 123a 56 | 1234 57 | Musterstadt 58 | CH 59 | 60 | 61 | 62 | 63 | CH9300762011623852957 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /spec/fixtures/xml/swiss_direct_debit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SPS-KING/c1e3bcc1a22c941e6c631b 6 | 2024-06-20T17:43:31+02:00 7 | 1 8 | 39.99 9 | 10 | Glaubiger GmbH 11 | 12 | 13 | 14 | ABC1W 15 | 16 | 17 | 18 | 19 | 20 | 21 | SPS-KING/c1e3bcc1a22c941e6c631b/1 22 | DD 23 | 24 | 25 | CHTA 26 | 27 | 28 | LSV+ 29 | 30 | 31 | 1999-01-01 32 | 33 | Glaubiger GmbH 34 | 35 | 36 | 37 | CH7081232000001998736 38 | 39 | 40 | 41 | 42 | 43 | 81232 44 | 45 | 46 | 010001456 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | ABC1W 55 | 56 | CHLS 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 12345 65 | XYZ/2013-08-ABO/6789 66 | 67 | 39.99 68 | 69 | 70 | 71 | 4835 72 | 73 | 74 | 75 | 76 | Zahlemann Soehne GbR 77 | 78 | Mustergasse 79 | 1234 80 | Musterstadt 81 | CH 82 | 83 | 84 | 85 | 86 | CH9804835011062385295 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | ESR 95 | 96 | 97 | 609323234234234353453423423 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /spec/fixtures/xml/upload_init_response.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | ABF70F5E704E03CFE5B50692BEE55ABA 6 | 7 | 8 | Initialisation 9 | 000000 10 | [EBICS_OK] OK 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 0/3J0Cne3ncZmTUNZuD8S8HOKI95bo9fP1AvVyVZDfc= 23 | 24 | 25 | J1vtnW2TX3sY9IWnWDcYA2SiZcPwSKq8ap7ESJEfHjDsqDhJV5A3dOo/R4v3LwoMe7CdbWc0AX+KMrcL4FSeQ+CnM776ncQV3OELS83ZkHZzbp15B0cJ9pf3lY9JiEDxKLMeoRjNJlc97Io2iJOW6dO2ZoSPXjF2G4ukQ81P7P8= 26 | 27 | 28 | 000000 29 | 2009-06-16T17:56:05.698+02:00 30 | 31 |
32 | -------------------------------------------------------------------------------- /spec/generic_upload_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::GenericUploadRequest 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') } 3 | let(:document) { "\x01" * 12 } 4 | subject { described_class.new(client, document) } 5 | 6 | describe '#pad' do 7 | 8 | it 'will complete the block to the next 16byte' do 9 | expect(subject.pad("\x01" * 13).size).to eq(16) 10 | end 11 | 12 | it 'will pad a complete block if the size is a multiple of 16' do 13 | expect(subject.pad("\x01" * 16).size).to eq(32) 14 | end 15 | 16 | it 'will set the last byte to the padding length' do 17 | expect(subject.pad("\x01" * 13)[-1]).to eq([3].pack("C*")) 18 | end 19 | end 20 | 21 | describe '#signature_value' do 22 | before { allow(OpenSSL::Random).to receive(:random_bytes).with(16).and_return("\x01" * 16) } # fake random_key requires a 16byte lenght but is not used in this test 23 | before { allow(OpenSSL::Random).to receive(:random_bytes).with(32).and_return(Base64.strict_decode64("7wtROfiX4tyN60cygJUSsHkhzxX1RVJa8vGNYnflvKc=")) } # digest requires 32 bytes 24 | 25 | it 'will be the signed document' do 26 | key = subject.client.a.key 27 | 28 | verification_result = key.verify_pss( 29 | 'SHA256', 30 | Base64.decode64(subject.signature_value), 31 | OpenSSL::Digest::SHA256.new.digest(document), 32 | salt_length: :digest, 33 | mgf1_hash: 'SHA256', 34 | ) 35 | 36 | expect(verification_result).to eq(true) 37 | end 38 | end 39 | 40 | describe '#order_signature' do 41 | before { allow(subject).to receive(:signature_value).and_return("FOOBAR") } 42 | let(:signature) { Nokogiri::XML(subject.order_signature) } 43 | 44 | it 'contains the untouched signature_value ' do 45 | expect(signature.at_xpath('//xmlns:SignatureValue').text).to eq("FOOBAR") 46 | end 47 | 48 | end 49 | 50 | describe '#encrypted_order_data' do 51 | it 'returns the same data every time' do 52 | data_1 = subject.encrypted_order_data 53 | data_2 = subject.encrypted_order_data 54 | 55 | expect(data_1).to eq(data_2) 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /spec/hpb_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::HPB 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') } 3 | describe '#to_xml' do 4 | subject { Nokogiri::XML.parse(described_class.new(client).to_xml) } 5 | 6 | specify do 7 | expect(subject.xpath("//xmlns:Timestamp").first.content).to_not be_nil 8 | expect(subject.xpath("//xmlns:Nonce").first.content).to_not be_nil 9 | expect(subject.xpath("//xmlns:HostID").first.content).to eq("SIZBN001") 10 | expect(subject.xpath("//xmlns:UserID").first.content).to eq("EBIX") 11 | expect(subject.xpath("//xmlns:PartnerID").first.content).to eq("EBICS") 12 | end 13 | end 14 | 15 | end 16 | -------------------------------------------------------------------------------- /spec/key_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::Key do 2 | 3 | subject { described_class.new( File.read(File.join( File.dirname(__FILE__), 'fixtures', 'e002.pem'))) } 4 | 5 | describe '#public_digest' do 6 | 7 | it 'will calculate the digest as the specification suggests' do 8 | expect(subject.public_digest).to eq("rwIxSUJAVEFDQ0sdYe+CybdspMllDG6ArNtdCzUbT1E=") 9 | end 10 | end 11 | 12 | 13 | describe '#sign' do 14 | let(:dsi) { OpenSSL::Digest::SHA256.new.digest("ruby is great") } 15 | 16 | it 'will generated a digest that can be verified with openssl key.verify_pss' do 17 | signed_digest = subject.sign(dsi) 18 | 19 | key = subject.key 20 | 21 | verification_result = key.verify_pss( 22 | 'SHA256', 23 | Base64.decode64(signed_digest), 24 | dsi, 25 | salt_length: :digest, 26 | mgf1_hash: 'SHA256', 27 | ) 28 | 29 | expect(verification_result).to eq(true) 30 | end 31 | 32 | end 33 | 34 | 35 | end 36 | -------------------------------------------------------------------------------- /spec/middleware/parse_ebics_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.describe Epics::ParseEbics do 4 | subject do 5 | Faraday.new do |builder| 6 | builder.use Epics::ParseEbics 7 | builder.adapter :test, Faraday::Adapter::Test::Stubs.new do |stub| 8 | stub.post('/business_nok') { [200, {}, File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', 'xml', 'ebics_business_nok.xml'))] } 9 | stub.post('/technical_nok') { [200, {}, File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', 'xml', 'ebics_technical_nok.xml'))] } 10 | stub.post('/ok') { [200, {}, File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', 'xml', 'hpb_response_ebics_ns.xml'))] } 11 | stub.post('/timeout') { raise Faraday::TimeoutError } 12 | stub.post('/no_connection') { raise Faraday::ConnectionFailed, 'peer has finished all lan parties and gone home' } 13 | end 14 | end 15 | end 16 | 17 | it 'will handle errornous response with raising the related error class' do 18 | expect { subject.post('/business_nok') }.to raise_error(Epics::Error::BusinessError, 'EBICS_PROCESSING_ERROR - During processing of the EBICS request, other business-related errors have ocurred') 19 | expect { subject.post('/technical_nok') }.to raise_error(Epics::Error::TechnicalError, 'EBICS_AUTHENTICATION_FAILED - Authentication signature error') 20 | end 21 | 22 | it 'will parsed as Epics::Response' do 23 | expect(subject.post('/ok').body).to be_kind_of(Epics::Response) 24 | end 25 | 26 | context 'failures' do 27 | it 'will raise a timeout correctly' do 28 | expect { subject.post('/timeout') }.to raise_error(Faraday::TimeoutError, 'timeout') 29 | end 30 | 31 | it 'will properly raise non-epics errors' do 32 | expect { subject.post('/no_connection') }.to raise_error(Faraday::ConnectionFailed, 'peer has finished all lan parties and gone home') 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /spec/orders/azv_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::AZV do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | let(:document) { 'DTAZV' } 5 | 6 | subject { described_class.new(client, document) } 7 | 8 | describe '#to_xml' do 9 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 10 | end 11 | 12 | describe '#to_transfer_xml' do 13 | before { subject.transaction_id = SecureRandom.hex(16) } 14 | 15 | specify { expect(subject.to_transfer_xml).to be_a_valid_ebics_doc } 16 | end 17 | 18 | end 19 | -------------------------------------------------------------------------------- /spec/orders/b2b_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::B2B do 2 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 3 | let(:document) { File.read( File.join( File.dirname(__FILE__), '..', 'fixtures', 'xml', 'cd1.xml') ) } 4 | subject { described_class.new(client, document) } 5 | 6 | describe '#to_xml' do 7 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/orders/bka_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::BKA do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | 5 | subject { described_class.new(client, from: "2014-09-01", to: "2014-09-30") } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /spec/orders/c2s_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::C2S do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | let(:document) { File.read( File.join( File.dirname(__FILE__), '..', 'fixtures', 'xml', 'cdb.xml') ) } 5 | subject { described_class.new(client, document) } 6 | 7 | describe 'order attributes' do 8 | it { expect(subject.header.to_s).to include('DZHNN') } 9 | it { expect(subject.header.to_s).to include('C2S') } 10 | end 11 | 12 | describe '#to_xml' do 13 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 14 | end 15 | 16 | describe '#to_transfer_xml' do 17 | before { subject.transaction_id = SecureRandom.hex(16) } 18 | 19 | specify { expect(subject.to_transfer_xml).to be_a_valid_ebics_doc } 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/orders/c52_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::C52 do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | 5 | subject { described_class.new(client, from: "2014-09-01", to: "2014-09-30") } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | end 10 | 11 | end -------------------------------------------------------------------------------- /spec/orders/c53_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::C53 do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | 5 | subject { described_class.new(client, from: "2014-09-01", to: "2014-09-30") } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | end 10 | 11 | end -------------------------------------------------------------------------------- /spec/orders/c54_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::C54 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') } 3 | 4 | subject { described_class.new(client, from: "2014-09-01", to: "2014-09-30") } 5 | 6 | describe '#to_xml' do 7 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/orders/c5n_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::C5N 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') } 3 | 4 | subject { described_class.new(client, from: "2014-09-01", to: "2014-09-01") } 5 | 6 | describe '#to_xml' do 7 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/orders/ccs_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::CCS do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | let(:document) { File.read( File.join( File.dirname(__FILE__), '..', 'fixtures', 'xml', 'cd1.xml') ) } 5 | subject { described_class.new(client, document) } 6 | 7 | describe 'order attributes' do 8 | it { expect(subject.header.to_s).to include('DZHNN') } 9 | it { expect(subject.header.to_s).to include('CCS') } 10 | end 11 | 12 | describe '#to_xml' do 13 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 14 | end 15 | 16 | describe '#to_transfer_xml' do 17 | before { subject.transaction_id = SecureRandom.hex(16) } 18 | 19 | specify { expect(subject.to_transfer_xml).to be_a_valid_ebics_doc } 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/orders/cct_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::CCT do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | let(:document) { File.read( File.join( File.dirname(__FILE__), '..', 'fixtures', 'xml', 'cd1.xml') ) } 5 | subject { described_class.new(client, document) } 6 | 7 | describe 'order attributes' do 8 | it { expect(subject.header.to_s).to include('OZHNN') } 9 | it { expect(subject.header.to_s).to include('CCT') } 10 | end 11 | 12 | describe '#to_xml' do 13 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 14 | end 15 | 16 | describe '#to_transfer_xml' do 17 | before { subject.transaction_id = SecureRandom.hex(16) } 18 | 19 | specify { expect(subject.to_transfer_xml).to be_a_valid_ebics_doc } 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/orders/cd1_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::CD1 do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | let(:document) { File.read( File.join( File.dirname(__FILE__), '..', 'fixtures', 'xml', 'cd1.xml') ) } 5 | subject { described_class.new(client, document) } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | end 10 | 11 | describe '#to_transfer_xml' do 12 | before { subject.transaction_id = SecureRandom.hex(16) } 13 | 14 | specify { expect(subject.to_transfer_xml).to be_a_valid_ebics_doc } 15 | end 16 | 17 | end -------------------------------------------------------------------------------- /spec/orders/cdb_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::CDB do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | let(:document) { File.read( File.join( File.dirname(__FILE__), '..', 'fixtures', 'xml', 'cdb.xml') ) } 5 | subject { described_class.new(client, document) } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | end 10 | 11 | describe '#to_transfer_xml' do 12 | before { subject.transaction_id = SecureRandom.hex(16) } 13 | 14 | specify { expect(subject.to_transfer_xml).to be_a_valid_ebics_doc } 15 | end 16 | 17 | end 18 | -------------------------------------------------------------------------------- /spec/orders/cdd_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::CDD do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | let(:document) { File.read( File.join( File.dirname(__FILE__), '..', 'fixtures', 'xml', 'cd1.xml') ) } 5 | subject { described_class.new(client, document) } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | end 10 | 11 | describe '#to_transfer_xml' do 12 | before { subject.transaction_id = SecureRandom.hex(16) } 13 | 14 | specify { expect(subject.to_transfer_xml).to be_a_valid_ebics_doc } 15 | end 16 | 17 | end -------------------------------------------------------------------------------- /spec/orders/cdz_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::CDZ 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') } 3 | 4 | context 'with date range' do 5 | subject { described_class.new(client, from: "2014-09-01", to: "2014-09-30") } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | 10 | it 'does includes a date range as standard order parameter' do 11 | expect(subject.to_xml).to include('2014-09-012014-09-30') 12 | end 13 | end 14 | end 15 | 16 | context 'without date range' do 17 | subject { described_class.new(client) } 18 | 19 | describe '#to_xml' do 20 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 21 | 22 | it 'does not include a standard order parameter' do 23 | expect(subject.to_xml).to include('') 24 | end 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /spec/orders/cip_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::CIP do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | let(:document) { File.read( File.join( File.dirname(__FILE__), '..', 'fixtures', 'xml', 'cip.xml') ) } 5 | subject { described_class.new(client, document) } 6 | 7 | describe 'order attributes' do 8 | it { expect(subject.header.to_s).to include('OZHNN') } 9 | it { expect(subject.header.to_s).to include('CIP') } 10 | end 11 | 12 | describe '#to_xml' do 13 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 14 | end 15 | 16 | describe '#to_transfer_xml' do 17 | before { subject.transaction_id = SecureRandom.hex(16) } 18 | 19 | specify { expect(subject.to_transfer_xml).to be_a_valid_ebics_doc } 20 | end 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /spec/orders/crz_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::CRZ 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') } 3 | 4 | context 'with date range' do 5 | subject { described_class.new(client, from: "2014-09-01", to: "2014-09-30") } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | 10 | it 'does includes a date range as standard order parameter' do 11 | expect(subject.to_xml).to include('2014-09-012014-09-30') 12 | end 13 | end 14 | end 15 | 16 | context 'without date range' do 17 | subject { described_class.new(client) } 18 | 19 | describe '#to_xml' do 20 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 21 | 22 | it 'does not include a standard order parameter' do 23 | expect(subject.to_xml).to include('') 24 | end 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /spec/orders/fdl_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::FDL 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') } 3 | let(:file_format) { 'camt.xxx.cfonb120.stm.Oby' } 4 | 5 | context 'with file_format' do 6 | subject(:order) { described_class.new(client, file_format: file_format) } 7 | 8 | describe '#to_xml' do 9 | specify { expect(order.to_xml).to be_a_valid_ebics_doc } 10 | 11 | it 'does includes a date range as standard order parameter' do 12 | expect(order.to_xml).to include('camt.xxx.cfonb120.stm.Oby') 13 | end 14 | end 15 | 16 | describe '#to_receipt_xml' do 17 | before { order.transaction_id = SecureRandom.hex(16) } 18 | 19 | specify { expect(order.to_receipt_xml).to be_a_valid_ebics_doc } 20 | end 21 | 22 | context 'with DateRange' do 23 | subject(:order) { described_class.new(client, file_format: file_format, from: Date.new(2024, 1, 1), to: Date.new(2024, 1, 2)) } 24 | 25 | describe '#to_xml' do 26 | specify { expect(order.to_xml).to be_a_valid_ebics_doc } 27 | 28 | it 'does includes a date range as optional order parameter' do 29 | expect(order.to_xml).to include('2024-01-012024-01-02camt.xxx.cfonb120.stm.Oby') 30 | end 31 | end 32 | 33 | describe '#to_receipt_xml' do 34 | before { order.transaction_id = SecureRandom.hex(16) } 35 | 36 | specify { expect(order.to_receipt_xml).to be_a_valid_ebics_doc } 37 | end 38 | end 39 | end 40 | 41 | context 'without file_format' do 42 | subject(:order) { described_class.new(client) } 43 | 44 | describe '#to_xml' do 45 | specify { expect(order.to_xml).to be_a_valid_ebics_doc } 46 | 47 | it 'does not include a standard order parameter' do 48 | expect(order.to_xml).to include('') 49 | end 50 | end 51 | 52 | describe '#to_receipt_xml' do 53 | before { order.transaction_id = SecureRandom.hex(16) } 54 | 55 | specify { expect(order.to_receipt_xml).to be_a_valid_ebics_doc } 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /spec/orders/ful_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::FUL 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') } 3 | let(:document) { File.read( File.join( File.dirname(__FILE__), '..', 'fixtures', 'xml', 'cd1.xml') ) } 4 | 5 | subject { described_class.new(client, document, file_format: 'pain.001.001.02') } 6 | 7 | describe 'order attributes' do 8 | it { expect(subject.header.to_s).to include('DZHNN') } 9 | it { expect(subject.header.to_s).to include('FUL') } 10 | it { expect(subject.header.to_s).to include('pain.001.001.02') } 11 | end 12 | 13 | describe '#to_xml' do 14 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 15 | end 16 | 17 | describe '#to_transfer_xml' do 18 | before { subject.transaction_id = SecureRandom.hex(16) } 19 | 20 | specify { expect(subject.to_transfer_xml).to be_a_valid_ebics_doc } 21 | end 22 | end -------------------------------------------------------------------------------- /spec/orders/haa_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::HAA do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | 5 | subject { described_class.new(client) } 6 | 7 | before do 8 | allow(subject).to receive(:nonce) { "95149241ead8ae7dbb72cabe966bf0e3" } 9 | allow(subject).to receive(:timestamp) { "2017-10-17T19:56:33Z" } 10 | end 11 | 12 | describe '#to_xml' do 13 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 14 | 15 | describe 'validate against fixture' do 16 | let(:signature_order_data) { Nokogiri::XML(File.read(File.join( File.dirname(__FILE__), '..', 'fixtures', 'xml', 'haa.xml'))) } 17 | 18 | it "will match exactly" do 19 | expect(Nokogiri::XML(subject.to_xml)).to be_equivalent_to(signature_order_data) 20 | end 21 | end 22 | end 23 | 24 | describe '#to_receipt_xml' do 25 | describe 'validate against fixture' do 26 | let(:signature_order_data) { Nokogiri::XML(File.read(File.join( File.dirname(__FILE__), '..', 'fixtures', 'xml', 'haa_receipt.xml'))) } 27 | 28 | it "will match exactly" do 29 | expect(Nokogiri::XML(subject.to_receipt_xml)).to be_equivalent_to(signature_order_data) 30 | end 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /spec/orders/hac_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::HAC 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') } 3 | 4 | context 'with date range' do 5 | subject(:order) { described_class.new(client, from: "2014-09-01", to: "2014-09-30") } 6 | 7 | describe '#to_xml' do 8 | specify { expect(order.to_xml).to be_a_valid_ebics_doc } 9 | 10 | it 'does includes a date range as standard order parameter' do 11 | expect(order.to_xml).to include('2014-09-012014-09-30') 12 | end 13 | end 14 | 15 | describe '#to_receipt_xml' do 16 | before { order.transaction_id = SecureRandom.hex(16) } 17 | 18 | specify { expect(order.to_receipt_xml).to be_a_valid_ebics_doc } 19 | end 20 | end 21 | 22 | context 'without date range' do 23 | subject(:order) { described_class.new(client) } 24 | 25 | describe '#to_xml' do 26 | specify { expect(order.to_xml).to be_a_valid_ebics_doc } 27 | 28 | it 'does not include a standard order parameter' do 29 | expect(order.to_xml).to include('') 30 | end 31 | end 32 | 33 | describe '#to_receipt_xml' do 34 | before { order.transaction_id = SecureRandom.hex(16) } 35 | 36 | specify { expect(order.to_receipt_xml).to be_a_valid_ebics_doc } 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /spec/orders/hev_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::HEV do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | 5 | let(:xsd) { Nokogiri::XML::Schema(File.open( File.join( File.dirname(__FILE__), '..', 'xsd', 'ebics_hev.xsd') )) } 6 | let(:validator) { xsd.valid?(Nokogiri::XML(subject.to_xml)) } 7 | 8 | subject { described_class.new(client) } 9 | 10 | describe '#to_xml' do 11 | specify { expect(validator).to be_truthy } 12 | end 13 | 14 | end 15 | -------------------------------------------------------------------------------- /spec/orders/hia_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::HIA do 2 | let(:client) { Epics::Client.new(key, 'secret', 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 3 | let(:key) { File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')) } 4 | 5 | subject { described_class.new(client) } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | 10 | describe 'validate against fixture' do 11 | let(:hia) do 12 | Nokogiri::XML(File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', 'xml', RUBY_ENGINE, 'hia.xml'))) 13 | end 14 | 15 | it 'will match exactly' do 16 | expect(Nokogiri::XML(subject.to_xml)).to be_equivalent_to(hia) 17 | end 18 | end 19 | end 20 | 21 | describe '#order_data' do 22 | specify { expect(subject.order_data).to be_a_valid_ebics_doc } 23 | 24 | describe 'validate against fixture' do 25 | let(:hia_request_order_data) do 26 | Nokogiri::XML(File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', 'xml', 27 | 'hia_request_order_data.xml'))) 28 | end 29 | 30 | it 'will match exactly' do 31 | expect(Nokogiri::XML(subject.order_data)).to be_equivalent_to(hia_request_order_data) 32 | end 33 | end 34 | 35 | context 'with x509 certificate' do 36 | let(:client) do 37 | client = Epics::Client.new(key, 'secret', 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') 38 | client.x_509_certificates_content = { 39 | x: generate_x_509_crt(client.x.key, '/C=GB/O=TestOrg/CN=test.example.org'), 40 | e: generate_x_509_crt(client.e.key, '/C=GB/O=TestOrg/CN=test.example.org') 41 | } 42 | client 43 | end 44 | 45 | it 'includes x509 certificate' do 46 | x_crt = Epics::X509Certificate.new(client.x_509_certificates_content[:x]) 47 | e_crt = Epics::X509Certificate.new(client.x_509_certificates_content[:e]) 48 | expect(subject.order_data).to include('/C=GB/O=TestOrg/CN=test.example.org') 49 | expect(subject.order_data).to include('2') 50 | expect(subject.order_data).to include("#{x_crt.data}") 51 | expect(subject.order_data).to include("#{e_crt.data}") 52 | end 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /spec/orders/hkd_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::HKD do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | 5 | subject { described_class.new(client) } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | end 10 | 11 | end -------------------------------------------------------------------------------- /spec/orders/hpb_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::HPB do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | 5 | subject { described_class.new(client) } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | end 10 | 11 | end -------------------------------------------------------------------------------- /spec/orders/hpd_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::HPD do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | 5 | subject { described_class.new(client) } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | end 10 | 11 | end -------------------------------------------------------------------------------- /spec/orders/htd_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::HTD do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | 5 | subject { described_class.new(client) } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | end 10 | 11 | end -------------------------------------------------------------------------------- /spec/orders/ini_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::INI do 2 | let(:client) { Epics::Client.new(key, 'secret', 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 3 | let(:key) { File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')) } 4 | before { allow(subject).to receive(:timestamp) { '2014-10-10T11:16:00Z' } } 5 | 6 | subject { described_class.new(client) } 7 | 8 | describe '#to_xml' do 9 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 10 | 11 | describe 'validate against fixture' do 12 | let(:signature_order_data) do 13 | Nokogiri::XML(File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', 'xml', RUBY_ENGINE, 'ini.xml'))) 14 | end 15 | 16 | it 'will match exactly' do 17 | expect(Nokogiri::XML(subject.to_xml)).to be_equivalent_to(signature_order_data) 18 | end 19 | end 20 | end 21 | 22 | describe '#key_signature' do 23 | specify { expect(subject.key_signature).to be_a_valid_ebics_doc } 24 | 25 | describe 'validate against fixture' do 26 | let(:signature_order_data) do 27 | Nokogiri::XML(File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', 'xml', 28 | 'signature_pub_key_order_data.xml'))) 29 | end 30 | 31 | it 'will match exactly' do 32 | expect(Nokogiri::XML(subject.key_signature)).to be_equivalent_to(signature_order_data) 33 | end 34 | end 35 | 36 | context 'with x509 certificate' do 37 | let(:client) do 38 | client = Epics::Client.new(key, 'secret', 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') 39 | client.x_509_certificates_content = {a: generate_x_509_crt(client.a.key, '/C=GB/O=TestOrg/CN=test.example.org')} 40 | client 41 | end 42 | 43 | it 'includes x509 certificate' do 44 | a_crt = Epics::X509Certificate.new(client.x_509_certificates_content[:a]) 45 | expect(subject.key_signature).to include('/C=GB/O=TestOrg/CN=test.example.org') 46 | expect(subject.key_signature).to include('2') 47 | expect(subject.key_signature).to include("#{a_crt.data}") 48 | end 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /spec/orders/ptk_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::PTK 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') } 3 | 4 | subject { described_class.new(client, from: "2014-09-01", to: "2014-09-30") } 5 | 6 | describe '#to_xml' do 7 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/orders/sta_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::STA 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') } 3 | 4 | context 'with date range' do 5 | subject(:order) { described_class.new(client, from: "2014-09-01", to: "2014-09-30") } 6 | 7 | describe '#to_xml' do 8 | specify { expect(order.to_xml).to be_a_valid_ebics_doc } 9 | 10 | it 'does includes a date range as standard order parameter' do 11 | expect(order.to_xml).to include('2014-09-012014-09-30') 12 | end 13 | end 14 | 15 | describe '#to_receipt_xml' do 16 | before { order.transaction_id = SecureRandom.hex(16) } 17 | 18 | specify { expect(order.to_receipt_xml).to be_a_valid_ebics_doc } 19 | end 20 | end 21 | 22 | context 'without date range' do 23 | subject(:order) { described_class.new(client) } 24 | 25 | describe '#to_xml' do 26 | specify { expect(order.to_xml).to be_a_valid_ebics_doc } 27 | 28 | it 'does not include a standard order parameter' do 29 | expect(order.to_xml).to include('') 30 | end 31 | end 32 | 33 | describe '#to_receipt_xml' do 34 | before { order.transaction_id = SecureRandom.hex(16) } 35 | 36 | specify { expect(order.to_receipt_xml).to be_a_valid_ebics_doc } 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /spec/orders/vmk_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::VMK 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') } 3 | 4 | subject { described_class.new(client, from: "2014-09-01", to: "2014-09-30") } 5 | 6 | describe '#to_xml' do 7 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/orders/wss_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::WSS 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') } 3 | 4 | subject { described_class.new(client) } 5 | 6 | describe '#to_xml' do 7 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/orders/x_509_certificate_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::X509Certificate do 2 | subject(:x_509_certificate) { described_class.new(crt_content) } 3 | 4 | let(:key) { OpenSSL::PKey::RSA.new(2048) } 5 | let(:crt_content) { generate_x_509_crt(key, distinguished_name) } 6 | let(:distinguished_name) { '/C=GB/O=TestOrg/CN=test.example.org' } 7 | 8 | describe '#issuer' do 9 | it 'returns the issuer of the certificate' do 10 | expect(x_509_certificate.issuer.to_s).to eq(distinguished_name) 11 | end 12 | end 13 | 14 | describe '#version' do 15 | it 'returns the version of the certificate' do 16 | expect(x_509_certificate.version).to eq(2) 17 | end 18 | end 19 | 20 | describe '#data' do 21 | it 'returns the base64 encoded certificate data' do 22 | expect(x_509_certificate.data).to start_with('MIIDDzCCAfegAwIBAgIBATANBgkqhkiG9w0BA') 23 | expect(x_509_certificate.data).to end_with('==') 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /spec/orders/xds_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::XDS 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') } 3 | let(:document) { File.read( File.join( File.dirname(__FILE__), '..', 'fixtures', 'xml', 'cd1.xml') ) } 4 | subject { described_class.new(client, document) } 5 | 6 | describe '#to_xml' do 7 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 8 | end 9 | 10 | describe '#to_transfer_xml' do 11 | before { subject.transaction_id = SecureRandom.hex(16) } 12 | 13 | specify { expect(subject.to_transfer_xml).to be_a_valid_ebics_doc } 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/orders/xe2_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::XE2 do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | let(:document) { File.read( File.join( File.dirname(__FILE__), '..', 'fixtures', 'xml', 'swiss_credit_transfer.xml') ) } 5 | subject { described_class.new(client, document) } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | end 10 | 11 | describe '#to_transfer_xml' do 12 | before { subject.transaction_id = SecureRandom.hex(16) } 13 | 14 | specify { expect(subject.to_transfer_xml).to be_a_valid_ebics_doc } 15 | end 16 | 17 | end 18 | -------------------------------------------------------------------------------- /spec/orders/xe3_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::XE3 do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | let(:document) { File.read( File.join( File.dirname(__FILE__), '..', 'fixtures', 'xml', 'swiss_direct_debit.xml') ) } 5 | subject { described_class.new(client, document) } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | end 10 | 11 | describe '#to_transfer_xml' do 12 | before { subject.transaction_id = SecureRandom.hex(16) } 13 | 14 | specify { expect(subject.to_transfer_xml).to be_a_valid_ebics_doc } 15 | end 16 | 17 | end 18 | -------------------------------------------------------------------------------- /spec/orders/z01_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::Z01 do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | 5 | subject { described_class.new(client, from: "2014-09-01", to: "2014-09-30") } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /spec/orders/z52_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::Z52 do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | 5 | subject { described_class.new(client, from: "2014-09-01", to: "2014-09-30") } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /spec/orders/z53_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::Z53 do 2 | 3 | let(:client) { Epics::Client.new( File.open(File.join( File.dirname(__FILE__), '..', 'fixtures', 'SIZBN001.key')), 'secret' , 'https://194.180.18.30/ebicsweb/ebicsweb', 'SIZBN001', 'EBIX', 'EBICS') } 4 | 5 | subject { described_class.new(client, from: "2014-09-01", to: "2014-09-30") } 6 | 7 | describe '#to_xml' do 8 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /spec/orders/z54_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::Z54 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') } 3 | 4 | subject { described_class.new(client, from: "2014-09-01", to: "2014-09-30") } 5 | 6 | describe '#to_xml' do 7 | specify { expect(subject.to_xml).to be_a_valid_ebics_doc } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/response_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::Response 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') } 3 | subject { described_class.new( client, ebics_response ) } 4 | 5 | describe '#digest_valid?' do 6 | let(:ebics_response) { File.read('spec/fixtures/xml/upload_init_response.xml') } 7 | 8 | it 'checks if //ds:DigestValue matches the calculated digest' do 9 | expect(subject.digest_valid?).to be(true) 10 | end 11 | end 12 | 13 | describe '#technical_code' do 14 | let(:ebics_response) { File.read('spec/fixtures/xml/ini_response_h004_ns.xml') } 15 | 16 | it 'is extracted from the response' do 17 | expect(subject.technical_code).to eq("000000") 18 | end 19 | end 20 | 21 | describe '#business_code' do 22 | let(:ebics_response) { File.read('spec/fixtures/xml/ebics_business_nok.xml') } 23 | 24 | it 'is extracted from the response' do 25 | expect(subject.business_code).to eq("091116") 26 | end 27 | end 28 | 29 | describe '#signature_valid?' do 30 | let(:ebics_response) { File.read('spec/fixtures/xml/upload_init_response.xml') } 31 | 32 | it 'checks if the signature value can be verified with the bank key' do 33 | expect(subject.signature_valid?).to be(true) 34 | end 35 | end 36 | 37 | describe '#public_digest_valid?' do 38 | let(:ebics_response) { File.read('spec/fixtures/xml/hpb_response_ebics_ns.xml') } 39 | 40 | it "checks if //xmlns:EncryptionPubKeyDigest matches the user encryption key" do 41 | expect(subject.public_digest_valid?).to be(true) 42 | end 43 | end 44 | 45 | describe 'order_data' do 46 | let(:ebics_response) { File.read('spec/fixtures/xml/hpb_response_ebics_ns.xml') } 47 | let(:order_data) { File.read('spec/fixtures/xml/hpb_response_order.xml') } 48 | 49 | it "retrieves the decrypted order data" do 50 | expect(subject.order_data).to eq(order_data) 51 | end 52 | end 53 | 54 | describe '#report_text' do 55 | let(:ebics_response) { File.read('spec/fixtures/xml/sta_response.xml') } 56 | it 'pulls the report_text from the response' do 57 | expect(subject.report_text).to eq('[EBICS_OK] OK') 58 | end 59 | end 60 | 61 | describe '#transaction_id' do 62 | let(:ebics_response) { File.read('spec/fixtures/xml/sta_response.xml') } 63 | it 'pulls the transaction_id from the response' do 64 | expect(subject.transaction_id).to eq('ECD6F062AAEDFA77250526A68CBEC549') 65 | end 66 | end 67 | 68 | describe '#order_id' do 69 | let(:ebics_response) { File.read('spec/fixtures/xml/cd1_init_response.xml') } 70 | it 'pulls the order_id from the response' do 71 | expect(subject.order_id).to eq('N00L') 72 | end 73 | end 74 | 75 | describe '#last_segment?' do 76 | describe 'when its the last segement' do 77 | let(:ebics_response) { File.read('spec/fixtures/xml/sta_response.xml') } 78 | 79 | it 'will be true' do 80 | expect(subject.last_segment?).to be(true) 81 | end 82 | end 83 | 84 | describe 'when there are more segments' do 85 | let(:ebics_response) { File.read('spec/fixtures/xml/sta_response_continued.xml') } 86 | it 'will be false' do 87 | expect(subject.last_segment?).to be(false) 88 | end 89 | end 90 | end 91 | 92 | describe '#segmented?' do 93 | describe 'when the response is segemnted' do 94 | let(:ebics_response) { File.read('spec/fixtures/xml/sta_response.xml') } 95 | 96 | it 'will be true' do 97 | expect(subject.segmented?).to be(true) 98 | end 99 | end 100 | 101 | describe 'when the response is not segemnted' do 102 | let(:ebics_response) { File.read('spec/fixtures/xml/hpb_response_ebics_ns.xml') } 103 | 104 | it 'will be false' do 105 | expect(subject.segmented?).to be(false) 106 | end 107 | end 108 | end 109 | 110 | end 111 | -------------------------------------------------------------------------------- /spec/signer_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Epics::Signer 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') } 3 | let(:hpb) { Epics::HPB.new(client) } 4 | 5 | before do 6 | allow(hpb).to receive(:nonce) { "014a82626a51ee1cab547bbaf18a13a0" } 7 | allow(hpb).to receive(:timestamp) { "2014-09-09T09:33:12Z" } 8 | subject.digest! 9 | subject.sign! 10 | end 11 | 12 | subject { described_class.new(client, hpb.to_xml) } 13 | 14 | describe '#digest!' do 15 | it 'creates a digest of the *[authorized=true] nodes' do 16 | expect(subject.digest_node.content).to eq("iXchWJ3xMy508YBhzx0Fn9cYNyyAiS+X8CB8zb7tyfM=") 17 | end 18 | 19 | it 'bar' do 20 | expect(Epics::Response.new(client, subject.doc.to_xml(save_with: 32)).digest_valid?).to be(true) 21 | end 22 | end 23 | 24 | describe '#sign!' do 25 | it 'signs the complete ds:SignedInfo node' do 26 | expect(subject.doc.xpath("//ds:SignatureValue").first.content).to eq("o6G7zeU6IhEkQ51Mp5/aIhPcYiZAG1rERxFad+rVdbRCYJGUn6/BNath1cdTgoHQ+ZWn9+Y6IgFsKUYFp8QHrhYBJNhd38fi5wj2Eqv+J4nsfmSD9x6YFa8Q13cJ9/CakHp/C59bgFSJj77BzRFUPnW1Y1NuHj8n1OJ3iFTyF1vF6H6oRKHoE4cbK4jhD3f6udRvGglhW5J+TUFBM+2aE8njpzBZFjyQlct+5XUx3o+1GvaMUk5riH5sCQ95PAKuGTXFu0OLZvECDMA3kOia/l3VF09QUGsjxYF0jUn5WG6TnLy8+Odrh9tUgV9bS/swSeQ41Cah4Ehb0qTYFZoJ+w==") 27 | end 28 | 29 | it 'can be verified with the same key' do 30 | expect(client.x.key.verify(OpenSSL::Digest::SHA256.new, Base64.decode64(subject.doc.xpath("//ds:SignatureValue").first.content), subject.signature_node.canonicalize)).to be(true) 31 | end 32 | end 33 | 34 | end 35 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) 2 | $LOAD_PATH.unshift(File.dirname(__FILE__)) 3 | 4 | require 'rspec' 5 | require 'epics' 6 | require 'webmock/rspec' 7 | require 'rspec/matchers' # req by equivalent-xml custom matcher `be_equivalent_to` 8 | require 'equivalent-xml' 9 | 10 | Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f} 11 | 12 | RSpec.configure do |config| 13 | # rspec-expectations config goes here. You can use an alternate 14 | # assertion/expectation library such as wrong or the stdlib/minitest 15 | # assertions if you prefer. 16 | config.expect_with :rspec do |expectations| 17 | # This option will default to `true` in RSpec 4. It makes the `description` 18 | # and `failure_message` of custom matchers include text for helper methods 19 | # defined using `chain`, e.g.: 20 | # be_bigger_than(2).and_smaller_than(4).description 21 | # # => "be bigger than 2 and smaller than 4" 22 | # ...rather than: 23 | # # => "be bigger than 2" 24 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true 25 | end 26 | 27 | # rspec-mocks config goes here. You can use an alternate test double 28 | # library (such as bogus or mocha) by changing the `mock_with` option here. 29 | config.mock_with :rspec do |mocks| 30 | # Prevents you from mocking or stubbing a method that does not exist on 31 | # a real object. This is generally recommended, and will default to 32 | # `true` in RSpec 4. 33 | mocks.verify_partial_doubles = true 34 | end 35 | 36 | config.order = :random 37 | 38 | Kernel.srand config.seed 39 | 40 | if config.files_to_run.one? 41 | config.default_formatter = 'doc' 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /spec/support/ebics_matcher.rb: -------------------------------------------------------------------------------- 1 | RSpec::Matchers.define :be_a_valid_ebics_doc do 2 | 3 | ## 4 | # use #open instead of #read to have the includes working 5 | # http://stackoverflow.com/questions/11996326/nokogirixmlschema-syntaxerror-on-schema-load/22971456#22971456 6 | def xsd 7 | @xsd ||= Nokogiri::XML::Schema(File.open( File.join( File.dirname(__FILE__), '..', 'xsd', 'ebics_H004.xsd') )) 8 | end 9 | 10 | match do |actual| 11 | xsd.valid?(Nokogiri::XML(actual)) 12 | end 13 | 14 | failure_message do |actual| 15 | "expected that #{actual} would be a valid EBICS doc:\n\n #{xsd.validate(Nokogiri::XML(actual))}" 16 | end 17 | 18 | description do 19 | "be a valid EBICS document" 20 | end 21 | 22 | end -------------------------------------------------------------------------------- /spec/support/x_509_crt_generator.rb: -------------------------------------------------------------------------------- 1 | def generate_x_509_crt(key, distinguished_name) 2 | name = OpenSSL::X509::Name.parse(distinguished_name) 3 | 4 | cert = OpenSSL::X509::Certificate.new 5 | cert.version = 2 6 | cert.serial = 1 7 | cert.subject = name 8 | cert.issuer = name 9 | cert.public_key = key.public_key 10 | cert.not_before = Time.now 11 | cert.not_after = cert.not_before + 365 * 24 * 60 * 60 12 | 13 | ef = OpenSSL::X509::ExtensionFactory.new 14 | ef.subject_certificate = cert 15 | ef.issuer_certificate = cert 16 | cert.add_extension(ef.create_extension("basicConstraints", "CA:FALSE", true)) 17 | cert.add_extension(ef.create_extension("keyUsage", "digitalSignature,keyEncipherment,nonRepudiation", true)) 18 | 19 | cert.sign(key, OpenSSL::Digest::SHA256.new) 20 | 21 | cert.to_pem 22 | end -------------------------------------------------------------------------------- /spec/xsd/ebics_H004.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ebics_H004.xsd inkludiert alle Schemadateien des EBICS-Protokolls, um die Eindeutigkeit von Element- und Typnamen im EBCIS Namespace zu erzwingen. 5 | ebics_H004.xsd includes all schema files for the EBICS protocol in order to enforce unique element and type names in the EBICS namespace. 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /spec/xsd/ebics_hev.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ebics_hev.xsd ist das EBICS-Protokollschema entweder für Anfragen oder Rückmeldungen der Bank zu unterstützten EBICS-Versionen. 5 | ebics_hev.xsd is the appropriate EBICS protocol schema either for requests or responses according the EBICS versions supported by a bank. 6 | 7 | 8 | 9 | Datentyp für die Host-ID. 10 | Dataype for Host-ID. 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Datentyp für allgemeine Auftragsarten (Grundtyp). 19 | Datatype for general order types (basic type). 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Datentyp für Antwortcodes. 29 | Datatype for the return code 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | Datentyp für den Erklärungstext zum Antwortcode. 39 | Datatype for report text with respect to the return code 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | Datentyp für eine Versionsnummer 48 | Datatype for a release number 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | Datentyp für Versionsnummer des EBICS-schemas 58 | Datatype for release-number of the EBICS scheme 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | Datentyp für technische Fehler. 68 | Datatype for technical error 69 | 70 | 71 | 72 | 73 | Rückmeldung des Ausführungsstatus mit einer eindeutigen Fehlernummer. 74 | Confirmation of the carried out status with a unique error code. 75 | 76 | 77 | 78 | 79 | Klartext der Rückmeldung des Ausführungsstatus. 80 | Clear text of the response (carried out status). 81 | 82 | 83 | 84 | 85 | 86 | 87 | Datentyp für die Request-Daten 88 | Data type for Request data 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | Datentyp für die Response-Daten 98 | Data type for Request data 99 | 100 | 101 | 102 | 103 | 104 | Von der Bank unterstützte EBICS-Versionen, z.B. 2.4 105 | EBICS-releases supported by the bank, e.g. 2.4 106 | 107 | 108 | 109 | 110 | 111 | 112 | der EBICS-Version eindeutig zugeordnete Schema-Version, z.B. H003 113 | EBICS-scheme-version, e.g. H003, well-defined for EBICS-release-Version 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | Requestdaten 126 | request data 127 | 128 | 129 | 130 | 131 | Responsedaten 132 | response data 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /spec/xsd/ebics_keymgmt_response_H004.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ebics_keymgmt_response_H004.xsd ist das EBICS-Protokollschema für Schlüsselmanagement-Antwortnachrichten (HIA, HPB, HSA, INI). 6 | 7 | 8 | 9 | XML-Signature. 10 | 11 | 12 | 13 | 14 | 15 | 16 | Electronic Banking Internet Communication Standard des Zentralen Kreditausschusses (ZKA): Multibankfähige Schnittstelle zur internetbasierten Kommunikation. 17 | 18 | 19 | 20 | 21 | 22 | enthält die technischen Transaktionsdaten. 23 | 24 | 25 | 26 | 27 | 28 | enhält alle festen Headereinträge. 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | enthält alle variablen Headereinträge. 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | enthält die Auftragsdaten und den fachlichen ReturnCode. 46 | 47 | 48 | 49 | 50 | 51 | Transfer von Auftragsdaten; nur bei Download anzugeben (HPB). 52 | 53 | 54 | 55 | 56 | 57 | Informationen zur Verschlüsselung der Auftragsdaten 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | enthält Auftragsdaten. 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | Antwortcode für den vorangegangenen Transfer. 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | Zeitstempel der letzten Aktualisierung der Bankparameter; nur in der Initialisierungsphase anzugeben. 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | Datentyp für den variablen EBICS-Header. 117 | 118 | 119 | 120 | 121 | Auftragsnummer von Sendeaufträgen gemäß DFÜ-Abkommen (used for all key management order types except download order type HPB). 122 | 123 | 124 | 125 | 126 | Rückmeldung des Ausführungsstatus mit einer eindeutigen Fehlernummer. 127 | 128 | 129 | 130 | 131 | Klartext der Rückmeldung des Ausführungsstatus. 132 | 133 | 134 | 135 | 136 | 137 | 138 | --------------------------------------------------------------------------------