sepafm 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +35 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE +8 -0
- data/README.md +236 -0
- data/Rakefile +10 -0
- data/lib/danske_get_bank_certificate_test.rb +15 -0
- data/lib/sepa/application_request.rb +182 -0
- data/lib/sepa/application_response.rb +123 -0
- data/lib/sepa/client.rb +79 -0
- data/lib/sepa/danske_testing/keys/danske_encryption.crt +24 -0
- data/lib/sepa/filedescriptor.rb +7 -0
- data/lib/sepa/filetypeservice.rb +6 -0
- data/lib/sepa/nordea_testing/keys/CSR.csr +0 -0
- data/lib/sepa/nordea_testing/keys/nordea.crt +27 -0
- data/lib/sepa/nordea_testing/keys/nordea.key +19 -0
- data/lib/sepa/nordea_testing/response/content_053.xml +998 -0
- data/lib/sepa/nordea_testing/response/content_054.xml +1 -0
- data/lib/sepa/nordea_testing/response/download_file_response.xml +14 -0
- data/lib/sepa/nordea_testing/response/download_filelist_response.xml +14 -0
- data/lib/sepa/nordea_testing/response/get_user_info_response.xml +14 -0
- data/lib/sepa/nordea_testing/response/upload_file_response.xml +14 -0
- data/lib/sepa/response.rb +177 -0
- data/lib/sepa/sender_verifier.rb +15 -0
- data/lib/sepa/signature.rb +7 -0
- data/lib/sepa/soap_builder.rb +395 -0
- data/lib/sepa/soap_danske.rb +47 -0
- data/lib/sepa/soap_nordea.rb +68 -0
- data/lib/sepa/userfiletype.rb +16 -0
- data/lib/sepa/version.rb +3 -0
- data/lib/sepa/wsdl/wsdl_danske.xml +234 -0
- data/lib/sepa/wsdl/wsdl_danske_cert.xml +280 -0
- data/lib/sepa/wsdl/wsdl_nordea.xml +234 -0
- data/lib/sepa/wsdl/wsdl_nordea_cert.xml +187 -0
- data/lib/sepa/xml_parser.rb +291 -0
- data/lib/sepa/xml_schemas/application_request.xsd +135 -0
- data/lib/sepa/xml_schemas/application_response.xsd +311 -0
- data/lib/sepa/xml_schemas/cert_application_request.xsd +107 -0
- data/lib/sepa/xml_schemas/danske_pki.xsd +334 -0
- data/lib/sepa/xml_schemas/oasis-200401-wss-wssecurity-secext-1.0.xsd +195 -0
- data/lib/sepa/xml_schemas/oasis-200401-wss-wssecurity-utility-1.0.xsd +108 -0
- data/lib/sepa/xml_schemas/soap.xsd +126 -0
- data/lib/sepa/xml_schemas/wsdl.xml +310 -0
- data/lib/sepa/xml_schemas/xml.xsd +287 -0
- data/lib/sepa/xml_schemas/xmldsig-core-schema.xsd +318 -0
- data/lib/sepa/xml_templates/application_request/create_certificate.xml +10 -0
- data/lib/sepa/xml_templates/application_request/danske_get_bank_certificate.xml +10 -0
- data/lib/sepa/xml_templates/application_request/download_file.xml +32 -0
- data/lib/sepa/xml_templates/application_request/download_file_list.xml +29 -0
- data/lib/sepa/xml_templates/application_request/get_certificate.xml +10 -0
- data/lib/sepa/xml_templates/application_request/get_user_info.xml +26 -0
- data/lib/sepa/xml_templates/application_request/upload_file.xml +29 -0
- data/lib/sepa/xml_templates/soap/create_certificate.xml +15 -0
- data/lib/sepa/xml_templates/soap/danske_get_bank_certificate.xml +14 -0
- data/lib/sepa/xml_templates/soap/download_file.xml +16 -0
- data/lib/sepa/xml_templates/soap/download_file_list.xml +16 -0
- data/lib/sepa/xml_templates/soap/get_certificate.xml +13 -0
- data/lib/sepa/xml_templates/soap/get_user_info.xml +16 -0
- data/lib/sepa/xml_templates/soap/header.xml +37 -0
- data/lib/sepa/xml_templates/soap/upload_file.xml +16 -0
- data/lib/sepa.rb +21 -0
- data/lib/sepa_client_testing_mika.rb +32 -0
- data/lib/sepa_client_testing_tiere.rb +80 -0
- data/sepa.gemspec +29 -0
- data/test/sepa/application_request_test.rb +423 -0
- data/test/sepa/application_response_test.rb +238 -0
- data/test/sepa/cert_application_request_test.rb +99 -0
- data/test/sepa/client_test.rb +425 -0
- data/test/sepa/danske_test_keys/danskeroot.pem +25 -0
- data/test/sepa/danske_test_keys/encryption_pkcs.csr +0 -0
- data/test/sepa/danske_test_keys/signing_key.pem +27 -0
- data/test/sepa/danske_test_keys/signing_pkcs.csr +0 -0
- data/test/sepa/nordea_cert_request_soap_builder_test.rb +112 -0
- data/test/sepa/nordea_generic_soap_builder_test.rb +427 -0
- data/test/sepa/nordea_test_keys/nordea.crt +27 -0
- data/test/sepa/nordea_test_keys/nordea.key +19 -0
- data/test/sepa/nordea_test_keys/root_cert.cer +0 -0
- data/test/sepa/nordea_test_keys/testcert.csr +0 -0
- data/test/sepa/response_test.rb +269 -0
- data/test/sepa/sepa_test.rb +20 -0
- data/test/sepa/test_files/invalid.wsdl +1 -0
- data/test/sepa/test_files/test_responses/df.xml +20 -0
- data/test/sepa/test_files/test_responses/dfl.xml +20 -0
- data/test/sepa/test_files/test_responses/gui.xml +20 -0
- data/test/sepa/test_files/test_responses/uf.xml +20 -0
- data/test/sepa/user_file_type_test.rb +21 -0
- data/test/sepa/xml_parser_test.rb +73 -0
- data/test/test_helper.rb +9 -0
- metadata +256 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<c2b:ApplicationResponse xmlns:c2b="http://bxd.fi/xmldata/"><c2b:CustomerId>679155330</c2b:CustomerId><c2b:Timestamp>2010-09-10T10:20:38+02:00</c2b:Timestamp><c2b:ResponseCode>00</c2b:ResponseCode><c2b:ResponseText>OK.</c2b:ResponseText><c2b:Encrypted>false</c2b:Encrypted><c2b:Compressed>false</c2b:Compressed><c2b:UserFileTypes><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>HAELASKUT</c2b:FileType><c2b:FileTypeName>E-invoice to payer FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-FI3329501800008512</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-FI5229501800000022</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-FI7429501800000014</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-FI8319503000004327</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>HTMKTL</c2b:FileType><c2b:FileTypeName>Reference payments (html) FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000010</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000051</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000014</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000022</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>HTMKTO</c2b:FileType><c2b:FileTypeName>Account statement (html) FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000010</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000051</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000012445</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000086423</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000014</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000022</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>HYLLASKUT</c2b:FileType><c2b:FileTypeName>Rejected e-invoices to sender FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-00370011111111</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>INFO</c2b:FileType><c2b:FileTypeName>Info</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId/><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>N</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>KORKO</c2b:FileType><c2b:FileTypeName>Interest</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId/><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>N</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>KTL</c2b:FileType><c2b:FileTypeName>Reference Payments FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000010</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000051</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000014</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000022</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>LAHLASKUT</c2b:FileType><c2b:FileTypeName>E-invoice from invoicer FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Upload</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-00370011111111</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>LMP300</c2b:FileType><c2b:FileTypeName>Bill Payment service FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Upload</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-011111111</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>LMPPAL</c2b:FileType><c2b:FileTypeName>Bill payment service feedback FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-011111111</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>?</c2b:ServiceId><c2b:ServiceIdOwnerName>?</c2b:ServiceIdOwnerName><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText>?</c2b:ServiceIdText></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>NDCORPAYL</c2b:FileType><c2b:FileTypeName>Corporate payments - feedback FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-111111111</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>NDCORPAYS</c2b:FileType><c2b:FileTypeName>Corporate payments FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Upload</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-111111111</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>TITO</c2b:FileType><c2b:FileTypeName>Account Statement FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000010</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000051</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000012445</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000086423</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000014</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000022</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>TS</c2b:FileType><c2b:FileTypeName>Salaries and pensions FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Upload</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-123456789</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>TSPAL</c2b:FileType><c2b:FileTypeName>Salaries and pensions feedback FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-123456789</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>?</c2b:ServiceId><c2b:ServiceIdOwnerName>?</c2b:ServiceIdOwnerName><c2b:ServiceIdType>O</c2b:ServiceIdType><c2b:ServiceIdText>?</c2b:ServiceIdText></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>TXTKTL</c2b:FileType><c2b:FileTypeName>Reference payments (txt) FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000010</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000051</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000014</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000022</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>TXTKTO</c2b:FileType><c2b:FileTypeName>Account statement (txt) FI</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000010</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000000051</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000012445</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-19503000086423</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000014</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService><c2b:FileTypeService><c2b:ServiceId>NDEAFIHHXXX-FI1-EUR-29501800000022</c2b:ServiceId><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>A</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType><c2b:UserFileType><c2b:TargetId>11111111A1</c2b:TargetId><c2b:FileType>VKEUR</c2b:FileType><c2b:FileTypeName>Rates of exchange</c2b:FileTypeName><c2b:Country>FI</c2b:Country><c2b:Direction>Download</c2b:Direction><c2b:FileTypeServices><c2b:FileTypeService><c2b:ServiceId/><c2b:ServiceIdOwnerName/><c2b:ServiceIdType>N</c2b:ServiceIdType><c2b:ServiceIdText/></c2b:FileTypeService></c2b:FileTypeServices></c2b:UserFileType></c2b:UserFileTypes><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
|
|
2
|
+
<SignedInfo>
|
|
3
|
+
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
|
4
|
+
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
|
|
5
|
+
<Reference URI="">
|
|
6
|
+
<Transforms>
|
|
7
|
+
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
|
8
|
+
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
|
9
|
+
</Transforms>
|
|
10
|
+
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
|
|
11
|
+
<DigestValue>gNqDLvLt1Y3ma0hEFfZe3HR4hYg=</DigestValue>
|
|
12
|
+
</Reference>
|
|
13
|
+
</SignedInfo>
|
|
14
|
+
<SignatureValue>stMf9BuVXOD8XFxvJ3eTAxNfP0j/bm22YNJCpGLjN4TgRHBrS0OgY0WgG8O1TmptlGc63MyhwddGdIj9uYob7/q7uAhG1teY0bRCEvPc4uobDcZ2Umoqt66B2X4CuKIrdCeJNY/GBiSPIW3scA+y19F3rsnzIO3eUqZ7t8osyAk=</SignatureValue><KeyInfo><X509Data><X509Certificate>MIID2TCCAsGgAwIBAgIEAKwkgTANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQGEwJTRTEeMBwGA1UEChMVTm9yZGVhIEJhbmsgQUIgKHB1YmwpMSYwJAYDVQQDEx1Ob3JkZWEgQ29ycG9yYXRlIFNlcnZlciBDQSAwMTEUMBIGA1UEBRMLNTE2NDA2LTAxMjAwHhcNMDgxMDE3MTIzMDQxWhcNMTAxMDE3MTIzMDQxWjBmMQswCQYDVQQGEwJTRTEeMBwGA1UECgwVTm9yZGVhIEJhbmsgQUIgKHB1YmwpMRIwEAYDVQQLDAlOb3JkZWEgSVQxIzAhBgNVBAMMGkZpbGUgVHJhbnNmZXIgV2ViIFNlcnZpY2VzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI78vhz4V6P2jWj4LPIbBv2GDg6DWPhMT0fD90mu+/N+P2wn5RcIyEVpxWWRyP+oDqq5bW+J0Ni0GF9qRB8aTSBXaZ3AHH+tWWwxXk10RhZ47fNH+yzF7HDHmVJ++OkOpELlmUDb5tX+m+qtdL8nkIywvTYBMOrp3lGgWw1NiBMwIDAQABo4IBDDCCAQgwCQYDVR0TBAIwADARBgNVHQ4ECgQISLk+63zpZ78wEwYDVR0jBAwwCoAIRMeT2dl7VsEwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5ub3JkZWEuc2UvU0NBMDEwDgYDVR0PAQH/BAQDAgWgMIGJBgNVHR8EgYEwfzB9oHugeYZ3bGRhcDovL2xkYXAubmIuc2UvY249Tm9yZGVhJTIwQ29ycG9yYXRlJTIwU2VydmVyJTIwQ0ElMjAwMSxvPU5vcmRlYSUyMEJhbmslMjBBQiUyMChwdWJsKSxjPVNFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwDQYJKoZIhvcNAQEFBQADggEBAKqnBbdpbOhhJQLasFA8wUzHciMK6ACGIIPbaxU1X/aKVIpZ+rS92OB0TcIqmcBoAXLyFmzOjNPZCxntp/xC2J1y3Sd0Nbh/6LpwNLkbleinakaR4WnRdV3u38yzC2eczAIIZj/rnxylwh++JmfOdK8/T5ynKYJYx5UoMcG8WICmBRfEWId5/5hrr7PiN5neryz0zRUnmG4r9ML0X93C59yTmjcZXoVZwxIkwfzDTZxlPT1m/sAjOCnSHHuCMmJSXXWOeYJLIOdASgVOl7x6xdKKw6uOD0F2IC1xjpB3XBYMR2jxcb6SSyAkXgBNCPUGFUUkcUOk3+KwIu2Cjp7u1Ro=</X509Certificate><X509IssuerSerial><X509IssuerName>serialNumber=516406-0120, CN=Nordea Corporate Server CA 01, O=Nordea Bank AB (publ), C=SE</X509IssuerName><X509SerialNumber>11281537</X509SerialNumber></X509IssuerSerial></X509Data></KeyInfo></Signature></c2b:ApplicationResponse>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<c2b:ApplicationResponse xmlns:c2b="http://bxd.fi/xmldata/"><c2b:CustomerId>679155330</c2b:CustomerId><c2b:Timestamp>2010-09-13T13:06:34.16+03:00</c2b:Timestamp><c2b:ResponseCode>00</c2b:ResponseCode><c2b:ResponseText>OK.</c2b:ResponseText><c2b:Encrypted>false</c2b:Encrypted><c2b:Compressed>false</c2b:Compressed><c2b:AmountTotal>2312.00</c2b:AmountTotal><c2b:TransactionCount>3</c2b:TransactionCount><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
|
|
2
|
+
<SignedInfo>
|
|
3
|
+
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
|
4
|
+
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
|
|
5
|
+
<Reference URI="">
|
|
6
|
+
<Transforms>
|
|
7
|
+
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
|
8
|
+
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
|
9
|
+
</Transforms>
|
|
10
|
+
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
|
|
11
|
+
<DigestValue>zXN3gtukcU0Hrn5fEJvhkLKMVIs=</DigestValue>
|
|
12
|
+
</Reference>
|
|
13
|
+
</SignedInfo>
|
|
14
|
+
<SignatureValue>ud/gAtrrxg+B28CMV/BPaRSSRqmqNdWjsnoEm3yT9avvq8MV39reVXi/RULw+lSJUQYXDFgfkRxRVUKK71T4PlrdlMK8gfqvREVvPdLXqmtdEvuGXa+YGfeRMgO+IE7mnvb9hTsZi2TBSle/w9BHjrfv1mrg0cFwCovcro5JUXw=</SignatureValue><KeyInfo><X509Data><X509Certificate>MIID2TCCAsGgAwIBAgIEAKwkgTANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQGEwJTRTEeMBwGA1UEChMVTm9yZGVhIEJhbmsgQUIgKHB1YmwpMSYwJAYDVQQDEx1Ob3JkZWEgQ29ycG9yYXRlIFNlcnZlciBDQSAwMTEUMBIGA1UEBRMLNTE2NDA2LTAxMjAwHhcNMDgxMDE3MTIzMDQxWhcNMTAxMDE3MTIzMDQxWjBmMQswCQYDVQQGEwJTRTEeMBwGA1UECgwVTm9yZGVhIEJhbmsgQUIgKHB1YmwpMRIwEAYDVQQLDAlOb3JkZWEgSVQxIzAhBgNVBAMMGkZpbGUgVHJhbnNmZXIgV2ViIFNlcnZpY2VzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI78vhz4V6P2jWj4LPIbBv2GDg6DWPhMT0fD90mu+/N+P2wn5RcIyEVpxWWRyP+oDqq5bW+J0Ni0GF9qRB8aTSBXaZ3AHH+tWWwxXk10RhZ47fNH+yzF7HDHmVJ++OkOpELlmUDb5tX+m+qtdL8nkIywvTYBMOrp3lGgWw1NiBMwIDAQABo4IBDDCCAQgwCQYDVR0TBAIwADARBgNVHQ4ECgQISLk+63zpZ78wEwYDVR0jBAwwCoAIRMeT2dl7VsEwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5ub3JkZWEuc2UvU0NBMDEwDgYDVR0PAQH/BAQDAgWgMIGJBgNVHR8EgYEwfzB9oHugeYZ3bGRhcDovL2xkYXAubmIuc2UvY249Tm9yZGVhJTIwQ29ycG9yYXRlJTIwU2VydmVyJTIwQ0ElMjAwMSxvPU5vcmRlYSUyMEJhbmslMjBBQiUyMChwdWJsKSxjPVNFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwDQYJKoZIhvcNAQEFBQADggEBAKqnBbdpbOhhJQLasFA8wUzHciMK6ACGIIPbaxU1X/aKVIpZ+rS92OB0TcIqmcBoAXLyFmzOjNPZCxntp/xC2J1y3Sd0Nbh/6LpwNLkbleinakaR4WnRdV3u38yzC2eczAIIZj/rnxylwh++JmfOdK8/T5ynKYJYx5UoMcG8WICmBRfEWId5/5hrr7PiN5neryz0zRUnmG4r9ML0X93C59yTmjcZXoVZwxIkwfzDTZxlPT1m/sAjOCnSHHuCMmJSXXWOeYJLIOdASgVOl7x6xdKKw6uOD0F2IC1xjpB3XBYMR2jxcb6SSyAkXgBNCPUGFUUkcUOk3+KwIu2Cjp7u1Ro=</X509Certificate><X509IssuerSerial><X509IssuerName>serialNumber=516406-0120, CN=Nordea Corporate Server CA 01, O=Nordea Bank AB (publ), C=SE</X509IssuerName><X509SerialNumber>11281537</X509SerialNumber></X509IssuerSerial></X509Data></KeyInfo></Signature></c2b:ApplicationResponse>
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
module Sepa
|
|
2
|
+
class Response
|
|
3
|
+
def initialize(response)
|
|
4
|
+
@response = response
|
|
5
|
+
|
|
6
|
+
if !@response.respond_to?(:canonicalize)
|
|
7
|
+
fail ArgumentError,
|
|
8
|
+
"The response you provided is not a valid Nokogiri::XML file."
|
|
9
|
+
elsif !valid_against_schema?(@response)
|
|
10
|
+
fail ArgumentError,
|
|
11
|
+
"The response you provided doesn't validate against soap schema."
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Returns the x509 certificate embedded in the soap as an
|
|
16
|
+
# OpenSSL::X509::Certificate
|
|
17
|
+
def certificate
|
|
18
|
+
cert_value = @response.at_css(
|
|
19
|
+
'wsse|BinarySecurityToken',
|
|
20
|
+
'wsse' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-ws' \
|
|
21
|
+
'security-secext-1.0.xsd'
|
|
22
|
+
).content.gsub(/\s+/, "")
|
|
23
|
+
|
|
24
|
+
cert = process_cert_value(cert_value)
|
|
25
|
+
|
|
26
|
+
begin
|
|
27
|
+
cert = OpenSSL::X509::Certificate.new(cert)
|
|
28
|
+
rescue => e
|
|
29
|
+
fail OpenSSL::X509::CertificateError,
|
|
30
|
+
"The certificate embedded to the soap response could not be process" \
|
|
31
|
+
"ed. It's most likely corrupted. OpenSSL had this to say: #{e}."
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Verifies that the soap's certificate is trusted.
|
|
36
|
+
def cert_is_trusted?(root_cert)
|
|
37
|
+
if root_cert.subject == certificate.issuer
|
|
38
|
+
certificate.verify(root_cert.public_key)
|
|
39
|
+
else
|
|
40
|
+
fail SecurityError,
|
|
41
|
+
"The issuer of the certificate doesn't match the subject of the roo" \
|
|
42
|
+
"t certificate."
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Verifies that all digest values in the response match the actual ones.
|
|
47
|
+
# Takes an optional verbose parameter to show which digests didn't match
|
|
48
|
+
# i.e. verbose: true
|
|
49
|
+
def hashes_match?(options = {})
|
|
50
|
+
digests = find_digest_values(@response)
|
|
51
|
+
nodes = find_nodes_to_verify(@response, digests)
|
|
52
|
+
|
|
53
|
+
verified_digests = digests.select do |uri, digest|
|
|
54
|
+
uri = uri.sub(/^#/, '')
|
|
55
|
+
digest == nodes[uri]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
if digests == verified_digests
|
|
59
|
+
true
|
|
60
|
+
else
|
|
61
|
+
unverified_digests = digests.select do |uri, digest|
|
|
62
|
+
uri = uri.sub(/^#/, '')
|
|
63
|
+
digest != nodes[uri]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
if options[:verbose]
|
|
67
|
+
puts "These digests failed to verify: #{unverified_digests}."
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
false
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Verifies the signature by extracting the public key from the certificate
|
|
75
|
+
# embedded in the soap header and verifying the signature value with that.
|
|
76
|
+
def signature_is_valid?
|
|
77
|
+
node = @response.at_css('xmlns|SignedInfo',
|
|
78
|
+
'xmlns' => 'http://www.w3.org/2000/09/xmldsig#')
|
|
79
|
+
|
|
80
|
+
node = node.canonicalize(
|
|
81
|
+
mode=Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,
|
|
82
|
+
inclusive_namespaces=nil,with_comments=false
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
signature = @response.at_css(
|
|
86
|
+
'xmlns|SignatureValue',
|
|
87
|
+
'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
|
|
88
|
+
).content
|
|
89
|
+
|
|
90
|
+
signature = Base64.decode64(signature)
|
|
91
|
+
|
|
92
|
+
certificate.public_key.verify(OpenSSL::Digest::SHA1.new, signature, node)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Gets the application response from the response as an Nokogiri::XML
|
|
96
|
+
# document
|
|
97
|
+
def application_response
|
|
98
|
+
ar = @response.at_css('mod|ApplicationResponse').content
|
|
99
|
+
ar = Base64.decode64(ar)
|
|
100
|
+
Nokogiri::XML(ar)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
private
|
|
104
|
+
|
|
105
|
+
# Finds all reference nodes with digest values in the document and returns
|
|
106
|
+
# a hash with uri as the key and digest as the value.
|
|
107
|
+
def find_digest_values(doc)
|
|
108
|
+
references = {}
|
|
109
|
+
reference_nodes = @response.css(
|
|
110
|
+
'xmlns|Reference',
|
|
111
|
+
'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
reference_nodes.each do |node|
|
|
115
|
+
uri = node.attr('URI')
|
|
116
|
+
digest_value = node.at_css(
|
|
117
|
+
'xmlns|DigestValue',
|
|
118
|
+
'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
|
|
119
|
+
).content
|
|
120
|
+
|
|
121
|
+
references[uri] = digest_value
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
references
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Finds nodes to verify by comparing their id's to the uris' in the
|
|
128
|
+
# references hash.
|
|
129
|
+
def find_nodes_to_verify(doc, references)
|
|
130
|
+
nodes = {}
|
|
131
|
+
references.each do |uri, digest_value|
|
|
132
|
+
uri = uri.sub(/^#/, '')
|
|
133
|
+
node = doc.at_css(
|
|
134
|
+
"[wsu|Id='" + uri + "']",
|
|
135
|
+
'wsu' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss' \
|
|
136
|
+
'-wssecurity-utility-1.0.xsd'
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
nodes[uri] = calculate_digest(node)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
nodes
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def calculate_digest(node)
|
|
146
|
+
sha1 = OpenSSL::Digest::SHA1.new
|
|
147
|
+
|
|
148
|
+
canon_node = node.canonicalize(
|
|
149
|
+
mode=Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,
|
|
150
|
+
inclusive_namespaces=nil,with_comments=false
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
Base64.encode64(sha1.digest(canon_node)).gsub(/\s+/, "")
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Checks that the response is valid against soap schema.
|
|
157
|
+
def valid_against_schema?(doc)
|
|
158
|
+
schemas_path = File.expand_path('../../../lib/sepa/xml_schemas',
|
|
159
|
+
__FILE__)
|
|
160
|
+
|
|
161
|
+
Dir.chdir(schemas_path) do
|
|
162
|
+
xsd = Nokogiri::XML::Schema(IO.read('soap.xsd'))
|
|
163
|
+
xsd.valid?(doc)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Takes the certificate from the response, adds begin and end
|
|
168
|
+
# certificate texts and splits it into multiple lines so that OpenSSL
|
|
169
|
+
# can read it.
|
|
170
|
+
def process_cert_value(cert_value)
|
|
171
|
+
cert = "-----BEGIN CERTIFICATE-----\n"
|
|
172
|
+
cert += cert_value.to_s.gsub(/\s+/, "").scan(/.{1,64}/).join("\n")
|
|
173
|
+
cert += "\n"
|
|
174
|
+
cert += "-----END CERTIFICATE-----"
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Sepa
|
|
2
|
+
class SenderVerifier
|
|
3
|
+
def initialize(soap_response)
|
|
4
|
+
@soap_response = Nokogiri::XML(soap_response)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def get_digest_values
|
|
8
|
+
@soap_response.remove_namespaces!
|
|
9
|
+
digest_nodes = @soap_response.xpath("//Reference/dsig:DigestValue")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def calculate_digest
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
module Sepa
|
|
2
|
+
class SoapBuilder
|
|
3
|
+
# SoapBuilder checks and validates incoming params and creates the SOAP structure
|
|
4
|
+
def initialize(params)
|
|
5
|
+
|
|
6
|
+
check_params(params)
|
|
7
|
+
# Generate a request ID for the request
|
|
8
|
+
params[:request_id] = generate_request_id
|
|
9
|
+
|
|
10
|
+
# Check if the bank&command need keys/certificates/csr's
|
|
11
|
+
@params = initialize_certificates_and_csr(params)
|
|
12
|
+
|
|
13
|
+
check_if_bank_allows_command(@params)
|
|
14
|
+
|
|
15
|
+
@ar = ApplicationRequest.new(@params).get_as_base64
|
|
16
|
+
|
|
17
|
+
@bank = @params.fetch(:bank)
|
|
18
|
+
find_correct_bank_extension(@bank)
|
|
19
|
+
|
|
20
|
+
@template_path = File.expand_path('../xml_templates/soap/', __FILE__)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_xml
|
|
24
|
+
# Returns a complete SOAP message in xml format
|
|
25
|
+
find_correct_build(@params).to_xml
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def get_ar_as_base64
|
|
29
|
+
@ar
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def generate_request_id
|
|
35
|
+
reqid = SecureRandom.random_number(1000).to_s<<SecureRandom.random_number(1000).to_s
|
|
36
|
+
reqid
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def find_correct_bank_extension(bank)
|
|
40
|
+
case bank
|
|
41
|
+
when :danske
|
|
42
|
+
self.extend(DanskeSoapRequest)
|
|
43
|
+
when :nordea
|
|
44
|
+
self.extend(NordeaSoapRequest)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Generic building steps
|
|
49
|
+
def calculate_digest(doc, node)
|
|
50
|
+
sha1 = OpenSSL::Digest::SHA1.new
|
|
51
|
+
|
|
52
|
+
node = doc.at_css(node)
|
|
53
|
+
|
|
54
|
+
canon_node = node.canonicalize(
|
|
55
|
+
mode=Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,
|
|
56
|
+
inclusive_namespaces=nil,with_comments=false
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
Base64.encode64(sha1.digest(canon_node)).gsub(/\s+/, "")
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def calculate_signature(doc, node, private_key)
|
|
63
|
+
sha1 = OpenSSL::Digest::SHA1.new
|
|
64
|
+
|
|
65
|
+
node = doc.at_css(node)
|
|
66
|
+
|
|
67
|
+
canon_signed_info_node = node.canonicalize(
|
|
68
|
+
mode=Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,inclusive_namespaces=nil,
|
|
69
|
+
with_comments=false
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
signature = private_key.sign(sha1, canon_signed_info_node)
|
|
73
|
+
|
|
74
|
+
Base64.encode64(signature).gsub(/\s+/, "")
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def load_body_template(command)
|
|
78
|
+
case command
|
|
79
|
+
when :download_file_list
|
|
80
|
+
path = "#{@template_path}/download_file_list.xml"
|
|
81
|
+
when :get_user_info
|
|
82
|
+
path = "#{@template_path}/get_user_info.xml"
|
|
83
|
+
when :upload_file
|
|
84
|
+
path = "#{@template_path}/upload_file.xml"
|
|
85
|
+
when :download_file
|
|
86
|
+
path = "#{@template_path}/download_file.xml"
|
|
87
|
+
when :get_certificate
|
|
88
|
+
path = "#{@template_path}/get_certificate.xml"
|
|
89
|
+
when :get_bank_certificate
|
|
90
|
+
path = "#{@template_path}/danske_get_bank_certificate.xml"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
body_template = File.open(path)
|
|
94
|
+
body = Nokogiri::XML(body_template)
|
|
95
|
+
body_template.close
|
|
96
|
+
|
|
97
|
+
body
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def set_node(doc, node, value)
|
|
101
|
+
doc.at_css(node).content = value
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def add_body_to_header(header, body)
|
|
105
|
+
body = body.at_css('env|Body')
|
|
106
|
+
header.root.add_child(body)
|
|
107
|
+
header
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def extract_public_key(cert)
|
|
111
|
+
pkey = cert.public_key
|
|
112
|
+
pkey = OpenSSL::PKey::RSA.new(pkey)
|
|
113
|
+
|
|
114
|
+
pkey
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def format_cert(cert)
|
|
118
|
+
cert = cert.to_s
|
|
119
|
+
cert = cert.split('-----BEGIN CERTIFICATE-----')[1]
|
|
120
|
+
cert = cert.split('-----END CERTIFICATE-----')[0]
|
|
121
|
+
cert.gsub!(/\s+/, "")
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def load_header_template(template_path)
|
|
125
|
+
header_template = File.open("#{template_path}/header.xml")
|
|
126
|
+
header = Nokogiri::XML(header_template)
|
|
127
|
+
header_template.close
|
|
128
|
+
header
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def process_header(header, body, private_key, cert)
|
|
132
|
+
set_node(header, 'wsu|Created', Time.now.iso8601)
|
|
133
|
+
|
|
134
|
+
set_node(header, 'wsu|Expires', (Time.now + 3600).iso8601)
|
|
135
|
+
|
|
136
|
+
timestamp_digest = calculate_digest(header,'wsu|Timestamp')
|
|
137
|
+
set_node(header,'dsig|Reference[URI="#dsfg8sdg87dsf678g6dsg6ds7fg"]' \
|
|
138
|
+
' dsig|DigestValue', timestamp_digest)
|
|
139
|
+
|
|
140
|
+
body_digest = calculate_digest(body, 'env|Body')
|
|
141
|
+
set_node(header,'dsig|Reference[URI="#sdf6sa7d86f87s6df786sd87f6s8fsd'\
|
|
142
|
+
'a"] dsig|DigestValue', body_digest)
|
|
143
|
+
|
|
144
|
+
signature = calculate_signature(header, 'dsig|SignedInfo', private_key)
|
|
145
|
+
set_node(header, 'dsig|SignatureValue', signature)
|
|
146
|
+
|
|
147
|
+
formatted_cert = format_cert(cert)
|
|
148
|
+
set_node(header, 'wsse|BinarySecurityToken', formatted_cert)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Tries to validate the parameters or their presence.
|
|
152
|
+
def check_params(params)
|
|
153
|
+
# Universally for all
|
|
154
|
+
check_params_hash(params)
|
|
155
|
+
check_certificate_and_key_requirements(params)
|
|
156
|
+
check_bank(params[:bank])
|
|
157
|
+
check_env(params[:environment])
|
|
158
|
+
check_customer_id(params[:customer_id])
|
|
159
|
+
|
|
160
|
+
# Generic commands
|
|
161
|
+
generic_commands = [:download_file,:download_file_list,:get_user_info]
|
|
162
|
+
|
|
163
|
+
# Depending on command
|
|
164
|
+
case params[:command]
|
|
165
|
+
when :get_certificate
|
|
166
|
+
check_pin(params[:pin])
|
|
167
|
+
check_service(params[:service])
|
|
168
|
+
when *generic_commands
|
|
169
|
+
if params[:bank] == :nordea
|
|
170
|
+
check_lang(params[:language])
|
|
171
|
+
check_status(params[:status])
|
|
172
|
+
check_target_id(params[:target_id])
|
|
173
|
+
check_file_type(params[:file_type])
|
|
174
|
+
end
|
|
175
|
+
when :upload_file
|
|
176
|
+
check_lang(params[:language])
|
|
177
|
+
check_target_id(params[:target_id])
|
|
178
|
+
check_file_type(params[:file_type])
|
|
179
|
+
check_content(params[:content])
|
|
180
|
+
when :get_bank_certificate
|
|
181
|
+
if params[:bank] == :danske
|
|
182
|
+
# Nothing here
|
|
183
|
+
end
|
|
184
|
+
else
|
|
185
|
+
fail ArgumentError, "Command not supported."
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def check_csr(csr)
|
|
190
|
+
unless csr
|
|
191
|
+
fail ArgumentError, "You didn't provide a certificate signing request"
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def check_params_hash(params)
|
|
196
|
+
unless params.respond_to?(:each_pair)
|
|
197
|
+
fail ArgumentError, "You didn't provide a proper hash"
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def check_bank(bank)
|
|
202
|
+
unless [:nordea, :danske].include?(bank)
|
|
203
|
+
fail ArgumentError, "You didn't provide a proper bank. " \
|
|
204
|
+
"Acceptable values are nordea OR danske."
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def check_request_id(request_id)
|
|
209
|
+
if request_id.to_i == 0
|
|
210
|
+
fail ArgumentError, "Request ID must be a number and not 0"
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def check_keygen_type(keygen)
|
|
215
|
+
unless keygen
|
|
216
|
+
fail ArgumentError, "You didn't provide any Key Generator Type"
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def check_encryption_pkcs10(enc_cert)
|
|
221
|
+
unless enc_cert
|
|
222
|
+
fail ArgumentError, "You didn't provide Encrypting certificate PKCS10"
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def check_signing_pkcs10(sig_cert)
|
|
227
|
+
unless sig_cert
|
|
228
|
+
fail ArgumentError, "You didn't provide Signing certificate PKCS10"
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def check_pin(pin)
|
|
233
|
+
unless pin
|
|
234
|
+
fail ArgumentError, "You didn't provide a secret PIN"
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def check_private_key(private_key)
|
|
239
|
+
unless private_key.respond_to?(:sign)
|
|
240
|
+
fail ArgumentError, "You didn't provide a proper private key. The " \
|
|
241
|
+
"key has to be in OpenSSL::PKey::RSA - format."
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def check_cert(cert)
|
|
246
|
+
unless cert.respond_to?(:check_private_key)
|
|
247
|
+
fail ArgumentError, "You didn't provide a proper certificate. The " \
|
|
248
|
+
"certificate has to be in OpenSSL::X509::Certificate - format."
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def check_customer_id(customer_id)
|
|
253
|
+
unless customer_id && customer_id.respond_to?(:to_s) &&
|
|
254
|
+
customer_id.length <= 16
|
|
255
|
+
fail ArgumentError, "You didn't provide a proper customer id"
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def check_env(env)
|
|
260
|
+
unless ['PRODUCTION', 'TEST', 'customertest'].include?(env)
|
|
261
|
+
fail ArgumentError, "You didn't provide a proper environment. " \
|
|
262
|
+
"Acceptable values are PRODUCTION or TEST or customertest."
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def check_status(status)
|
|
267
|
+
unless ['NEW', 'DOWNLOADED', 'ALL'].include?(status)
|
|
268
|
+
fail ArgumentError, "You didn't provide a proper status. " \
|
|
269
|
+
"Acceptable values are NEW, DOWNLOADED or ALL."
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def check_target_id(target_id)
|
|
274
|
+
unless target_id && target_id.respond_to?(:to_s) &&
|
|
275
|
+
target_id.length <= 80
|
|
276
|
+
fail ArgumentError, "You didn't provide a proper target id"
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def check_lang(lang)
|
|
281
|
+
unless ['FI', 'SE', 'EN'].include?(lang)
|
|
282
|
+
fail ArgumentError, "You didn't provide a proper language. " \
|
|
283
|
+
"Acceptable values are FI, SE or EN."
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def check_file_type(file_type)
|
|
288
|
+
unless file_type && file_type.respond_to?(:to_s) &&
|
|
289
|
+
file_type.length <= 20
|
|
290
|
+
fail ArgumentError, "You didn't provide a proper file type. Check " \
|
|
291
|
+
"Your bank's documentation for available file types."
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def check_content(content)
|
|
296
|
+
unless content
|
|
297
|
+
fail ArgumentError, "You didn't provide any content."
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def check_service(service)
|
|
302
|
+
unless ['service', 'ISSUER', 'MATU'].include?(service)
|
|
303
|
+
fail ArgumentError, "You didn't provide a proper service."
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def check_hmac(hmac)
|
|
308
|
+
unless hmac
|
|
309
|
+
fail ArgumentError, "You didn't provide any HMAC."
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def check_if_bank_allows_command(params)
|
|
314
|
+
bank = params.fetch(:bank)
|
|
315
|
+
command = params.fetch(:command)
|
|
316
|
+
case bank
|
|
317
|
+
when :nordea
|
|
318
|
+
allowed_commands = [:get_certificate,:get_user_info,
|
|
319
|
+
:download_file_list,:download_file,:upload_file]
|
|
320
|
+
unless allowed_commands.include?(command)
|
|
321
|
+
fail ArgumentError, "You didn't provide a matching bank and service."
|
|
322
|
+
end
|
|
323
|
+
when :danske
|
|
324
|
+
allowed_commands = [:get_bank_certificate]
|
|
325
|
+
unless allowed_commands.include?(command)
|
|
326
|
+
fail ArgumentError, "You didn't provide a matching bank and service."
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
def check_certificate_and_key_requirements(params)
|
|
332
|
+
command = params[:command]
|
|
333
|
+
require_private_and_cert = [:get_user_info,:download_file_list,
|
|
334
|
+
:download_file,:upload_file]
|
|
335
|
+
require_nothing = [:get_bank_certificate]
|
|
336
|
+
require_pkcs = [:get_certificate]
|
|
337
|
+
|
|
338
|
+
case command
|
|
339
|
+
when *require_private_and_cert
|
|
340
|
+
if params[:cert_path] == nil && params[:cert_plain] == nil
|
|
341
|
+
fail ArgumentError, "You must provide a path to the certificate " \
|
|
342
|
+
"or certificate in plain text"
|
|
343
|
+
end
|
|
344
|
+
if params[:private_key_path] == nil && params[:private_key_plain] == nil
|
|
345
|
+
fail ArgumentError, "You must provide a path to your private key " \
|
|
346
|
+
"or private key in plain text"
|
|
347
|
+
end
|
|
348
|
+
when *require_nothing
|
|
349
|
+
when *require_pkcs
|
|
350
|
+
if params[:csr_path] == nil && params[:csr_plain] == nil
|
|
351
|
+
fail ArgumentError, "You must provide a path to the CSR or CSR in plain text"
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def initialize_certificates_and_csr(params)
|
|
357
|
+
begin
|
|
358
|
+
command = params[:command]
|
|
359
|
+
require_private_and_cert = [:get_user_info,:download_file_list,
|
|
360
|
+
:download_file,:upload_file]
|
|
361
|
+
require_nothing = [:get_bank_certificate]
|
|
362
|
+
require_pkcs = [:get_certificate]
|
|
363
|
+
|
|
364
|
+
case command
|
|
365
|
+
when *require_private_and_cert
|
|
366
|
+
if params[:cert_path] != nil
|
|
367
|
+
params[:cert] = OpenSSL::X509::Certificate.new(File.read(params.fetch(:cert_path)))
|
|
368
|
+
elsif params[:cert_plain] != nil
|
|
369
|
+
params[:cert] = OpenSSL::X509::Certificate.new(params.fetch(:cert_plain))
|
|
370
|
+
end
|
|
371
|
+
if params[:private_key_path] != nil
|
|
372
|
+
params[:private_key] = OpenSSL::PKey::RSA.new(File.read(params.fetch(:private_key_path)))
|
|
373
|
+
elsif params[:private_key_plain] != nil
|
|
374
|
+
params[:private_key] = OpenSSL::PKey::RSA.new(params.fetch(:private_key_plain))
|
|
375
|
+
end
|
|
376
|
+
check_private_key(params[:private_key])
|
|
377
|
+
check_cert(params[:cert])
|
|
378
|
+
when *require_nothing
|
|
379
|
+
when *require_pkcs
|
|
380
|
+
if params[:csr_path] != nil
|
|
381
|
+
params[:csr] = OpenSSL::X509::Request.new(File.read(params.fetch(:csr_path)))
|
|
382
|
+
elsif params[:csr_plain] != nil
|
|
383
|
+
params[:csr] = OpenSSL::X509::Request.new(params.fetch(:csr_plain))
|
|
384
|
+
end
|
|
385
|
+
check_csr(params[:csr])
|
|
386
|
+
else
|
|
387
|
+
fail ArgumentError, "No matching cases for initialize_certificates_and_csr"
|
|
388
|
+
end
|
|
389
|
+
params
|
|
390
|
+
rescue Exception => e
|
|
391
|
+
fail ArgumentError, "Parameter failed to initialize, check private key and cert path/plain"
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
end
|