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,187 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<wsdl:definitions targetNamespace="http://bxd.fi/CertificateService" xmlns:tns="http://bxd.fi/CertificateService" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
|
3
|
+
<wsdl:types>
|
|
4
|
+
<xsd:schema targetNamespace="http://bxd.fi/CertificateService" elementFormDefault="qualified" attributeFormDefault="qualified">
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
<xsd:simpleType name="SoftwareId">
|
|
8
|
+
<xsd:restriction base="xsd:string">
|
|
9
|
+
<xsd:minLength value="1"/>
|
|
10
|
+
<xsd:maxLength value="80"/>
|
|
11
|
+
</xsd:restriction>
|
|
12
|
+
</xsd:simpleType>
|
|
13
|
+
|
|
14
|
+
<xsd:simpleType name="ResponseText">
|
|
15
|
+
<xsd:restriction base="xsd:string">
|
|
16
|
+
<xsd:minLength value="1"/>
|
|
17
|
+
<xsd:maxLength value="80"/>
|
|
18
|
+
</xsd:restriction>
|
|
19
|
+
</xsd:simpleType>
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
<xsd:simpleType name="ResponseCode">
|
|
23
|
+
<xsd:restriction base="xsd:string">
|
|
24
|
+
<xsd:minLength value="1"/>
|
|
25
|
+
<xsd:maxLength value="16"/>
|
|
26
|
+
</xsd:restriction>
|
|
27
|
+
</xsd:simpleType>
|
|
28
|
+
|
|
29
|
+
<xsd:simpleType name="CustomerId">
|
|
30
|
+
<xsd:restriction base="xsd:string">
|
|
31
|
+
<xsd:minLength value="1"/>
|
|
32
|
+
<xsd:maxLength value="16"/>
|
|
33
|
+
</xsd:restriction>
|
|
34
|
+
</xsd:simpleType>
|
|
35
|
+
|
|
36
|
+
<xsd:complexType name="CertificateRequestHeader">
|
|
37
|
+
<xsd:sequence>
|
|
38
|
+
<xsd:element name="SenderId" type="xsd:string" nillable="false"/>
|
|
39
|
+
<xsd:element name="RequestId" type="xsd:string" nillable="false"/>
|
|
40
|
+
<xsd:element name="Timestamp" type="xsd:dateTime" nillable="false"/>
|
|
41
|
+
</xsd:sequence>
|
|
42
|
+
</xsd:complexType>
|
|
43
|
+
<xsd:complexType name="CertificateResponseHeader">
|
|
44
|
+
<xsd:sequence>
|
|
45
|
+
<xsd:element name="SenderId" type="xsd:string" nillable="false"/>
|
|
46
|
+
<xsd:element name="RequestId" type="xsd:string" nillable="false"/>
|
|
47
|
+
<xsd:element name="Timestamp" type="xsd:dateTime" nillable="false"/>
|
|
48
|
+
<xsd:element name="ResponseCode" type="tns:ResponseCode" nillable="true"/>
|
|
49
|
+
<xsd:element name="ResponseText" type="tns:ResponseText" nillable="true"/>
|
|
50
|
+
</xsd:sequence>
|
|
51
|
+
</xsd:complexType>
|
|
52
|
+
<xsd:complexType name="GetCertificateRequest">
|
|
53
|
+
<xsd:sequence>
|
|
54
|
+
<xsd:element name="RequestHeader" type="tns:CertificateRequestHeader" nillable="false"/>
|
|
55
|
+
<xsd:element name="ApplicationRequest" type="xsd:base64Binary" nillable="false"/>
|
|
56
|
+
</xsd:sequence>
|
|
57
|
+
</xsd:complexType>
|
|
58
|
+
<xsd:complexType name="GetCertificateResponse">
|
|
59
|
+
<xsd:sequence>
|
|
60
|
+
<xsd:element name="ResponseHeader" type="tns:CertificateResponseHeader" nillable="false"/>
|
|
61
|
+
<xsd:element name="ApplicationResponse" type="xsd:base64Binary"/>
|
|
62
|
+
</xsd:sequence>
|
|
63
|
+
</xsd:complexType>
|
|
64
|
+
<xsd:complexType name="GetServiceCertificatesRequest">
|
|
65
|
+
<xsd:sequence>
|
|
66
|
+
<xsd:element name="RequestHeader" type="tns:CertificateRequestHeader" nillable="false"/>
|
|
67
|
+
<xsd:element name="ApplicationRequest" type="xsd:base64Binary" nillable="false"/>
|
|
68
|
+
</xsd:sequence>
|
|
69
|
+
</xsd:complexType>
|
|
70
|
+
<xsd:complexType name="GetServiceCertificatesResponse">
|
|
71
|
+
<xsd:sequence>
|
|
72
|
+
<xsd:element name="ResponseHeader" type="tns:CertificateResponseHeader" nillable="false"/>
|
|
73
|
+
<xsd:element name="ApplicationResponse" type="xsd:base64Binary" nillable="false"/>
|
|
74
|
+
</xsd:sequence>
|
|
75
|
+
</xsd:complexType>
|
|
76
|
+
<xsd:complexType name="RevokeCertificateRequest">
|
|
77
|
+
<xsd:sequence>
|
|
78
|
+
<xsd:element name="RequestHeader" type="tns:CertificateRequestHeader" nillable="false"/>
|
|
79
|
+
<xsd:element name="ApplicationRequest" type="xsd:base64Binary" nillable="false"/>
|
|
80
|
+
</xsd:sequence>
|
|
81
|
+
</xsd:complexType>
|
|
82
|
+
<xsd:complexType name="RevokeCertificateResponse">
|
|
83
|
+
<xsd:sequence>
|
|
84
|
+
<xsd:element name="ResponseHeader" type="tns:CertificateResponseHeader" nillable="false"/>
|
|
85
|
+
<xsd:element name="ApplicationResponse" type="xsd:base64Binary" nillable="false"/>
|
|
86
|
+
</xsd:sequence>
|
|
87
|
+
</xsd:complexType>
|
|
88
|
+
<xsd:complexType name="CertificateServiceFaultDetail">
|
|
89
|
+
<xsd:sequence>
|
|
90
|
+
<xsd:element minOccurs="0" maxOccurs="1" name="category" type="xsd:string"/>
|
|
91
|
+
<xsd:element minOccurs="0" maxOccurs="1" name="code" type="xsd:string"/>
|
|
92
|
+
</xsd:sequence>
|
|
93
|
+
</xsd:complexType>
|
|
94
|
+
</xsd:schema>
|
|
95
|
+
<xsd:schema targetNamespace="http://bxd.fi/CertificateService" elementFormDefault="qualified" attributeFormDefault="qualified">
|
|
96
|
+
<xsd:element name="getCertificatein" type="tns:GetCertificateRequest"/>
|
|
97
|
+
<xsd:element name="getCertificateout" type="tns:GetCertificateResponse"/>
|
|
98
|
+
<xsd:element name="getServiceCertificatesin" type="tns:GetServiceCertificatesRequest"/>
|
|
99
|
+
<xsd:element name="getServiceCertificatesout" type="tns:GetServiceCertificatesResponse"/>
|
|
100
|
+
<xsd:element name="revokeCertificatein" type="tns:RevokeCertificateRequest"/>
|
|
101
|
+
<xsd:element name="revokeCertificateout" type="tns:RevokeCertificateResponse"/>
|
|
102
|
+
<xsd:element name="certificateServiceFaultElement" type="tns:CertificateServiceFaultDetail"/>
|
|
103
|
+
</xsd:schema>
|
|
104
|
+
</wsdl:types>
|
|
105
|
+
<wsdl:message name="certificateServiceFault">
|
|
106
|
+
<wsdl:part name="certificateServiceFault" element="tns:certificateServiceFaultElement"/>
|
|
107
|
+
</wsdl:message>
|
|
108
|
+
<wsdl:message name="getCertificateRequest">
|
|
109
|
+
<wsdl:part element="tns:getCertificatein" name="getCertificatein"/>
|
|
110
|
+
</wsdl:message>
|
|
111
|
+
<wsdl:message name="getCertificateResponse">
|
|
112
|
+
<wsdl:part element="tns:getCertificateout" name="getCertificateout"/>
|
|
113
|
+
</wsdl:message>
|
|
114
|
+
<wsdl:message name="getServiceCertificatesRequest">
|
|
115
|
+
<wsdl:part element="tns:getServiceCertificatesin" name="getServiceCertificatesin"/>
|
|
116
|
+
</wsdl:message>
|
|
117
|
+
<wsdl:message name="getServiceCertificatesResponse">
|
|
118
|
+
<wsdl:part element="tns:getServiceCertificatesout" name="getServiceCertificatesout"/>
|
|
119
|
+
</wsdl:message>
|
|
120
|
+
<wsdl:message name="revokeCertificateRequest">
|
|
121
|
+
<wsdl:part element="tns:revokeCertificatein" name="revokeCertificatein"/>
|
|
122
|
+
</wsdl:message>
|
|
123
|
+
<wsdl:message name="revokeCertificateResponse">
|
|
124
|
+
<wsdl:part element="tns:revokeCertificateout" name="revokeCertificateout"/>
|
|
125
|
+
</wsdl:message>
|
|
126
|
+
<wsdl:portType name="CertificateServicePortType">
|
|
127
|
+
<wsdl:operation name="getCertificate">
|
|
128
|
+
<wsdl:input message="tns:getCertificateRequest" name="getCertificateRequest"/>
|
|
129
|
+
<wsdl:output message="tns:getCertificateResponse" name="getCertificateResponse"/>
|
|
130
|
+
<wsdl:fault message="tns:certificateServiceFault" name="certificateServiceFault"/>
|
|
131
|
+
</wsdl:operation>
|
|
132
|
+
<wsdl:operation name="getServiceCertificates">
|
|
133
|
+
<wsdl:input message="tns:getServiceCertificatesRequest" name="getServiceCertificatesRequest"/>
|
|
134
|
+
<wsdl:output message="tns:getServiceCertificatesResponse" name="getServiceCertificatesResponse"/>
|
|
135
|
+
<wsdl:fault message="tns:certificateServiceFault" name="certificateServiceFault"/>
|
|
136
|
+
</wsdl:operation>
|
|
137
|
+
<wsdl:operation name="revokeCertificate">
|
|
138
|
+
<wsdl:input message="tns:revokeCertificateRequest" name="revokeCertificateRequest"/>
|
|
139
|
+
<wsdl:output message="tns:revokeCertificateResponse" name="revokeCertificateResponse"/>
|
|
140
|
+
<wsdl:fault message="tns:certificateServiceFault" name="certificateServiceFault"/>
|
|
141
|
+
</wsdl:operation>
|
|
142
|
+
</wsdl:portType>
|
|
143
|
+
<wsdl:binding name="CertificateServiceHttpBinding" type="tns:CertificateServicePortType">
|
|
144
|
+
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
|
|
145
|
+
<wsdl:operation name="getCertificate">
|
|
146
|
+
<soap:operation soapAction=""/>
|
|
147
|
+
<wsdl:input name="getCertificateRequest">
|
|
148
|
+
<soap:body use="literal"/>
|
|
149
|
+
</wsdl:input>
|
|
150
|
+
<wsdl:output name="getCertificateResponse">
|
|
151
|
+
<soap:body use="literal"/>
|
|
152
|
+
</wsdl:output>
|
|
153
|
+
<wsdl:fault name="certificateServiceFault">
|
|
154
|
+
<soap:fault use="literal" name="certificateServiceFault"/>
|
|
155
|
+
</wsdl:fault>
|
|
156
|
+
</wsdl:operation>
|
|
157
|
+
<wsdl:operation name="getServiceCertificates">
|
|
158
|
+
<soap:operation soapAction=""/>
|
|
159
|
+
<wsdl:input name="getServiceCertificatesRequest">
|
|
160
|
+
<soap:body use="literal"/>
|
|
161
|
+
</wsdl:input>
|
|
162
|
+
<wsdl:output name="getServiceCertificatesResponse">
|
|
163
|
+
<soap:body use="literal"/>
|
|
164
|
+
</wsdl:output>
|
|
165
|
+
<wsdl:fault name="certificateServiceFault">
|
|
166
|
+
<soap:fault use="literal" name="certificateServiceFault"/>
|
|
167
|
+
</wsdl:fault>
|
|
168
|
+
</wsdl:operation>
|
|
169
|
+
<wsdl:operation name="revokeCertificate">
|
|
170
|
+
<soap:operation soapAction=""/>
|
|
171
|
+
<wsdl:input name="revokeCertificateRequest">
|
|
172
|
+
<soap:body use="literal"/>
|
|
173
|
+
</wsdl:input>
|
|
174
|
+
<wsdl:output name="revokeCertificateResponse">
|
|
175
|
+
<soap:body use="literal"/>
|
|
176
|
+
</wsdl:output>
|
|
177
|
+
<wsdl:fault name="certificateServiceFault">
|
|
178
|
+
<soap:fault use="literal" name="certificateServiceFault"/>
|
|
179
|
+
</wsdl:fault>
|
|
180
|
+
</wsdl:operation>
|
|
181
|
+
</wsdl:binding>
|
|
182
|
+
<wsdl:service name="CertificateService">
|
|
183
|
+
<wsdl:port binding="tns:CertificateServiceHttpBinding" name="CertificateServiceHttpPort">
|
|
184
|
+
<soap:address location="https://filetransfer.nordea.com/services/CertificateService"/>
|
|
185
|
+
</wsdl:port>
|
|
186
|
+
</wsdl:service>
|
|
187
|
+
</wsdl:definitions>
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
module Sepa
|
|
2
|
+
# This class is able to handle GetUserInfo, DownloadFileList, DownloadFile responses and pass content
|
|
3
|
+
class XmlParser
|
|
4
|
+
attr_accessor :timestamp, :responseCode, :encrypted, :compressed, :customerId, :responseText, :fileDescriptors, :userFiletypes, :content
|
|
5
|
+
def initialize
|
|
6
|
+
@content = ""
|
|
7
|
+
@fileDescriptors = []
|
|
8
|
+
end
|
|
9
|
+
# Reads values from content field (xml file), returns a hash
|
|
10
|
+
# Bank to customer statement
|
|
11
|
+
def get_account_statement_content(file)
|
|
12
|
+
|
|
13
|
+
if file == ""
|
|
14
|
+
fail ArgumentError, "You didn't provide a file"
|
|
15
|
+
|
|
16
|
+
elsif file != nil
|
|
17
|
+
content = Nokogiri::XML(File.open(file))
|
|
18
|
+
content.remove_namespaces!
|
|
19
|
+
|
|
20
|
+
unless content == ""
|
|
21
|
+
|
|
22
|
+
# To contain all needed values
|
|
23
|
+
statement_content = {}
|
|
24
|
+
|
|
25
|
+
# Selected fields
|
|
26
|
+
|
|
27
|
+
##CASE Devlab selected fields
|
|
28
|
+
# Booking date
|
|
29
|
+
statement_content[:bookingdatefrom] = content.at_css("Document/BkToCstmrStmt/Stmt/FrToDt/FrDtTm").content unless content.at_css("Document/BkToCstmrStmt/Stmt/FrToDt/FrDtTm") == nil
|
|
30
|
+
statement_content[:bookingdateto] = content.at_css("Document/BkToCstmrStmt/Stmt/FrToDt/ToDtTm").content unless content.at_css("Document/BkToCstmrStmt/Stmt/FrToDt/ToDtTm") == nil
|
|
31
|
+
|
|
32
|
+
# Account
|
|
33
|
+
statement_content[:owneracctiban] = content.at_css("Document/BkToCstmrStmt/Stmt/Acct/Id/IBAN").content unless content.at_css("Document/BkToCstmrStmt/Stmt/Acct/Id/IBAN") == nil
|
|
34
|
+
statement_content[:owneracctccy] = content.at_css("Document/BkToCstmrStmt/Stmt/Acct/Ccy").content unless content.at_css("Document/BkToCstmrStmt/Stmt/Acct/Ccy") == nil
|
|
35
|
+
statement_content[:owneraccttype] = content.at_css("Document/BkToCstmrStmt/Stmt/Acct/Nm").content unless content.at_css("Document/BkToCstmrStmt/Stmt/Acct/Nm") == nil
|
|
36
|
+
|
|
37
|
+
# Owner
|
|
38
|
+
statement_content[:acctownername] = content.at_css("Document/BkToCstmrStmt/Stmt/Acct/Ownr/Nm").content unless content.at_css("Document/BkToCstmrStmt/Stmt/Acct/Ownr/Nm") == nil
|
|
39
|
+
|
|
40
|
+
# BIC
|
|
41
|
+
statement_content[:owneracctbic] = content.at_css("Document/BkToCstmrStmt/Stmt/Acct/Svcr/FinInstnId/BIC").content unless content.at_css("Document/BkToCstmrStmt/Stmt/Acct/Svcr/FinInstnId/BIC").content == nil
|
|
42
|
+
|
|
43
|
+
# To contain each transaction listed in the content
|
|
44
|
+
transactions = []
|
|
45
|
+
|
|
46
|
+
content.xpath("//Document/BkToCstmrStmt/Stmt/Ntry").each do |node|
|
|
47
|
+
|
|
48
|
+
# To contain the values of a single transaction
|
|
49
|
+
transaction_content = {}
|
|
50
|
+
|
|
51
|
+
##CASE Devlab selected fields
|
|
52
|
+
##Arkistointitunnus
|
|
53
|
+
transaction_content[:acctsvcrref] = node.at_css("NtryDtls/TxDtls/Refs/AcctSvcrRef").content unless node.at_css("NtryDtls/TxDtls/Refs/AcctSvcrRef") == nil
|
|
54
|
+
##Saajan tilinumero
|
|
55
|
+
transaction_content[:crdtiban] = node.at_css("NtryDtls/TxDtls/RltdPties/CdtrAcct/Id/IBAN").content unless node.at_css("NtryDtls/TxDtls/RltdPties/CdtrAcct/Id/IBAN") == nil
|
|
56
|
+
##Maksupaiva
|
|
57
|
+
transaction_content[:bookingdate] = node.at_css("BookgDt/Dt").content unless node.at_css("BookgDt/Dt") == nil
|
|
58
|
+
##Arvopaiva
|
|
59
|
+
transaction_content[:valuedate] = node.at_css("ValDt/Dt").content unless node.at_css("ValDt/Dt") == nil
|
|
60
|
+
##Saaja/Maksaja
|
|
61
|
+
transaction_content[:crdtname] = node.at_css("NtryDtls/TxDtls/RltdPties/Cdtr/Nm").content unless node.at_css("NtryDtls/TxDtls/RltdPties/Cdtr/Nm") == nil
|
|
62
|
+
##Viesti
|
|
63
|
+
transaction_content[:message] = node.at_css("NtryDtls/TxDtls/RmtInf/Ustrd").content unless node.at_css("NtryDtls/TxDtls/RmtInf/Ustrd") == nil
|
|
64
|
+
##Maara sisaantuleva(arvo)
|
|
65
|
+
transaction_content[:incamt] = node.at_css("NtryDtls/TxDtls/AmtDtls/InstdAmt/Amt").content unless node.at_css("NtryDtls/TxDtls/AmtDtls/InstdAmt/Amt") == nil
|
|
66
|
+
##Valuutta sisaantuleva
|
|
67
|
+
transaction_content[:incccy] = node.at_css("NtryDtls/TxDtls/AmtDtls/InstdAmt/Amt")["Ccy"] unless node.at_css("NtryDtls/TxDtls/AmtDtls/InstdAmt/Amt") == nil
|
|
68
|
+
##Maara kirjanpidollinen(arvo)
|
|
69
|
+
transaction_content[:bkdamt] = node.at_css("NtryDtls/TxDtls/AmtDtls/TxAmt/Amt").content unless node.at_css("NtryDtls/TxDtls/AmtDtls/TxAmt/Amt") == nil
|
|
70
|
+
##Valuutta kirjanpidollinen
|
|
71
|
+
transaction_content[:bkdccy] = node.at_css("NtryDtls/TxDtls/AmtDtls/TxAmt/Amt")["Ccy"] unless node.at_css("NtryDtls/TxDtls/AmtDtls/TxAmt/Amt") == nil
|
|
72
|
+
##Tapahtumalaji (702, 705)
|
|
73
|
+
transaction_content[:trnscttype] = node.at_css("BkTxCd/Prtry/Cd").content unless node.at_css("BkTxCd/Prtry/Cd") == nil
|
|
74
|
+
##Tapahtumien maara
|
|
75
|
+
transaction_content[:trnsctcnt] = node.at_css("NtryDtls/Btch/NbOfTxs").content unless node.at_css("NtryDtls/Btch/NbOfTxs") == nil
|
|
76
|
+
##Oma sisainen viite
|
|
77
|
+
transaction_content[:internalid] = node.at_css("NtryDtls/Btch/PmtInfId").content unless node.at_css("NtryDtls/Btch/PmtInfId") == nil
|
|
78
|
+
##Maksajan viite
|
|
79
|
+
transaction_content[:instrid] = node.at_css("NtryDtls/TxDtls/Refs/InstrId").content unless node.at_css("NtryDtls/TxDtls/Refs/InstrId") == nil
|
|
80
|
+
##BIC koodi (saaja)
|
|
81
|
+
transaction_content[:crdtbin] = node.at_css("NtryDtls/TxDtls/RltdAgts/DbtrAgt/FinInstId").content unless node.at_css("NtryDtls/TxDtls/RltdAgts/DbtrAgt/FinInstId") == nil
|
|
82
|
+
##Maksajan tunniste
|
|
83
|
+
transaction_content[:crdtid] = node.at_css("NtryDtls/TxDtls/RltdPties/CdtrAcct/Id/Othr/Id").content unless node.at_css("NtryDtls/TxDtls/RltdPties/CdtrAcct/Id/Othr/Id") == nil
|
|
84
|
+
##SEPA arkistointitunnus
|
|
85
|
+
transaction_content[:sepabookingid] = node.at_css("AcctSvcrRef").content unless node.at_css("AcctSvcrRef") == nil
|
|
86
|
+
|
|
87
|
+
# Push to array
|
|
88
|
+
transactions<<transaction_content
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
statement_content[:transactions] = transactions
|
|
92
|
+
|
|
93
|
+
# Returns hash
|
|
94
|
+
statement_content
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# Reads values from content field (xml file), returns a hash
|
|
101
|
+
def get_debit_credit_notification_content(file)
|
|
102
|
+
|
|
103
|
+
if file == ""
|
|
104
|
+
fail ArgumentError, "You didn't provide a file"
|
|
105
|
+
|
|
106
|
+
elsif file != nil
|
|
107
|
+
content = Nokogiri::XML(File.open(file))
|
|
108
|
+
content.remove_namespaces!
|
|
109
|
+
|
|
110
|
+
unless content == ""
|
|
111
|
+
|
|
112
|
+
notification_content = {}
|
|
113
|
+
|
|
114
|
+
##CASE Devlab suggested/selected fields
|
|
115
|
+
|
|
116
|
+
# account iban
|
|
117
|
+
notification_content[:account_iban] = content.at_css("Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Acct/Id/IBAN").content unless content.at_css("Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Acct/Id/IBAN") == nil
|
|
118
|
+
|
|
119
|
+
# payer name
|
|
120
|
+
notification_content[:account_owner] = content.at_css("Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Acct/Ownr/Nm").content unless content.at_css("Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Acct/Ownr/Nm") == nil
|
|
121
|
+
|
|
122
|
+
# bic
|
|
123
|
+
notification_content[:account_bic] = content.at_css("Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Acct/Svcr/FinInstnId/BIC").content unless content.at_css("Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Acct/Svcr/FinInstnId/BIC") == nil
|
|
124
|
+
|
|
125
|
+
#Viitesiirtokentat
|
|
126
|
+
# Notification entries
|
|
127
|
+
notification_entries = []
|
|
128
|
+
|
|
129
|
+
#txdtls_content = {}
|
|
130
|
+
|
|
131
|
+
content.xpath("//Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Ntry").each do |node|
|
|
132
|
+
|
|
133
|
+
entry_content = {}
|
|
134
|
+
|
|
135
|
+
# reference
|
|
136
|
+
entry_content[:entry_reference] = node.at_css("NtryRef").content unless node.at_css("NtryRef") == nil
|
|
137
|
+
# sum
|
|
138
|
+
entry_content[:entry_sum] = node.at_css("Amt").content unless node.at_css("Amt") == nil
|
|
139
|
+
# currency code
|
|
140
|
+
entry_content[:entry_currency] = node.at_css("Amt")["Ccy"] unless node.at_css("Amt") == nil
|
|
141
|
+
# entry date
|
|
142
|
+
entry_content[:entry_booking_date] = node.at_css("BookgDt/Dt").content unless node.at_css("BookgDt/Dt") == nil
|
|
143
|
+
# payment date
|
|
144
|
+
entry_content[:entry_value_date] = node.at_css("ValDt/Dt").content unless node.at_css("ValDt/Dt") == nil
|
|
145
|
+
|
|
146
|
+
# LOOP all txdtls
|
|
147
|
+
txdtls_all = Array.new
|
|
148
|
+
node.xpath("//NtryDtls/TxDtls").each do |nodejr|
|
|
149
|
+
txdtls_content = Hash.new
|
|
150
|
+
|
|
151
|
+
# TODO add check to transaction number
|
|
152
|
+
# value before exchange
|
|
153
|
+
txdtls_content[:gross_outgoing_value] = nodejr.at_css("AmtDtls/InstdAmt/Amt").content unless nodejr.at_css("AmtDtls/InstdAmt/Amt") == nil
|
|
154
|
+
# currency before exchange
|
|
155
|
+
txdtls_content[:gross_outgoing_currency] = nodejr.at_css("AmtDtls/InstdAmt/Amt")["Ccy"] unless nodejr.at_css("AmtDtls/InstdAmt/Amt") == nil
|
|
156
|
+
|
|
157
|
+
# exchange rate
|
|
158
|
+
txdtls_content[:currency_exchange_rate] = nodejr.at_css("AmtDtls/InstdAmt/CcyXchg/XchgRate").content unless nodejr.at_css("AmtDtls/InstdAmt/CcyXchg/XchgRate") == nil
|
|
159
|
+
|
|
160
|
+
# value after exchange
|
|
161
|
+
txdtls_content[:value_post_exchange] = nodejr.at_css("AmtDtls/TxAmt/Amt").content unless nodejr.at_css("AmtDtls/TxAmt/Amt") == nil
|
|
162
|
+
# currency after exchange
|
|
163
|
+
txdtls_content[:currency_post_exchange] = nodejr.at_css("AmtDtls/TxAmt/Amt")["Ccy"] unless nodejr.at_css("AmtDtls/TxAmt/Amt") == nil
|
|
164
|
+
|
|
165
|
+
txdtls_all<<txdtls_content unless txdtls_content[:gross_outgoing_currency] == txdtls_content[:currency_post_exchange]
|
|
166
|
+
end
|
|
167
|
+
entry_content[:txdtls] = txdtls_all
|
|
168
|
+
# Add single notification entry to array
|
|
169
|
+
notification_entries<<entry_content
|
|
170
|
+
end
|
|
171
|
+
# Add array to hash
|
|
172
|
+
notification_content[:notification_entries] = notification_entries
|
|
173
|
+
|
|
174
|
+
# Returns hash
|
|
175
|
+
notification_content
|
|
176
|
+
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Add incoming descriptor to array
|
|
183
|
+
def add_descriptor(fdesc)
|
|
184
|
+
fileDescriptors<<fdesc
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Add incoming userfiletype to the array
|
|
188
|
+
def add_userfiletype(ufiletype)
|
|
189
|
+
userFiletypes<<ufiletype
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Returns an array of file descriptors
|
|
193
|
+
def list_new_descriptors
|
|
194
|
+
# Lists NEW (not already downloaded) files only (as filedescriptor objects)
|
|
195
|
+
kek = Array.new
|
|
196
|
+
kek<<@fileDescriptors.select { |fd| fd.status == "NEW" }
|
|
197
|
+
kek
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def list_all_descriptors
|
|
201
|
+
@fileDescriptors
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Returns the full array list of userfiletypes in the response
|
|
205
|
+
def list_userfiletypes
|
|
206
|
+
userFiletypes
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Returns a specific descriptor matching the file reference
|
|
210
|
+
def select_descriptor(fileRef)
|
|
211
|
+
fileDescriptors.select { |fd| fd.fileReference == fileRef }
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Reads response xml from bank and fills attribute values
|
|
215
|
+
def animate_response(file)
|
|
216
|
+
# Open the xml file
|
|
217
|
+
xml = Nokogiri::XML(File.open(file))
|
|
218
|
+
|
|
219
|
+
# To help navigating the response xml
|
|
220
|
+
xml.remove_namespaces!
|
|
221
|
+
|
|
222
|
+
customerId = xml.at_css("CustomerId").content unless xml.at_css("CustomerId") == nil
|
|
223
|
+
timestamp = xml.at_css("Timestamp").content unless xml.at_css("Timestamp") == nil
|
|
224
|
+
responseCode = xml.at_css("ResponseCode").content unless xml.at_css("ResponseCode") == nil
|
|
225
|
+
responseText = xml.at_css("ResponseText").content unless xml.at_css("ResponseText") == nil
|
|
226
|
+
encrypted = xml.at_css("Encrypted").content unless xml.at_css("Encrypted").content == nil
|
|
227
|
+
compressed = xml.at_css("Compressed").content unless xml.at_css("Compressed") == nil
|
|
228
|
+
|
|
229
|
+
# Decode the content portion automatically so that it can be read
|
|
230
|
+
@content = Base64.decode64(xml.at_css("Content").content) unless xml.at_css("Content") == nil
|
|
231
|
+
#puts content unless content == ""
|
|
232
|
+
|
|
233
|
+
# FILEDESCRIPTORS
|
|
234
|
+
# Initialize array
|
|
235
|
+
self.fileDescriptors = Array.new
|
|
236
|
+
|
|
237
|
+
# Iterate all descriptors
|
|
238
|
+
xml.xpath("//FileDescriptors/FileDescriptor").each do |desc|
|
|
239
|
+
# Initialize
|
|
240
|
+
fdesc = Sepa::Filedescriptor.new
|
|
241
|
+
|
|
242
|
+
# Assigning class attributes
|
|
243
|
+
fdesc.fileReference = desc.at_css("FileReference").content
|
|
244
|
+
fdesc.targetId = desc.at_css("TargetId").content
|
|
245
|
+
fdesc.serviceId = desc.at_css("ServiceId").content
|
|
246
|
+
fdesc.serviceIdOwnerName = desc.at_css("ServiceIdOwnerName").content
|
|
247
|
+
fdesc.fileType = desc.at_css("FileType").content
|
|
248
|
+
fdesc.fileTimestamp = desc.at_css("FileTimestamp").content
|
|
249
|
+
fdesc.status = desc.at_css("Status").content
|
|
250
|
+
|
|
251
|
+
# Add to array
|
|
252
|
+
self.add_descriptor(fdesc)
|
|
253
|
+
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# FILETYPESERVICES
|
|
257
|
+
# Initialize array
|
|
258
|
+
self.userFiletypes = Array.new
|
|
259
|
+
|
|
260
|
+
# Iterate all userfiletypes
|
|
261
|
+
xml.xpath("//UserFileTypes/UserFileType").each do |ftype|
|
|
262
|
+
uftype = Sepa::Userfiletype.new
|
|
263
|
+
|
|
264
|
+
# Assign class attributes
|
|
265
|
+
uftype.targetId = ftype.at_css("TargetId").content
|
|
266
|
+
uftype.fileType = ftype.at_css("FileType").content
|
|
267
|
+
uftype.fileTypeName = ftype.at_css("FileTypeName").content
|
|
268
|
+
uftype.country = ftype.at_css("Country").content
|
|
269
|
+
uftype.direction = ftype.at_css("Direction").content
|
|
270
|
+
|
|
271
|
+
uftype.filetypeServices = Array.new
|
|
272
|
+
|
|
273
|
+
# Iterate all filetypeservice
|
|
274
|
+
ftype.xpath("./FileTypeServices/FileTypeService").each do |ftypes|
|
|
275
|
+
|
|
276
|
+
newservice = Sepa::Filetypeservice.new
|
|
277
|
+
newservice.serviceId = ftypes.at_css("ServiceId").content unless ftypes.at_css("ServiceId") == nil
|
|
278
|
+
newservice.serviceIdOwnerName = ftypes.at_css("ServiceIdOwnerName").content unless ftypes.at_css("ServiceIdOwnerName") == nil
|
|
279
|
+
newservice.serviceIdType = ftypes.at_css("ServiceType").content unless ftypes.at_css("ServiceType") == nil
|
|
280
|
+
newservice.serviceIdText = ftypes.at_css("ServiceIdText").content unless ftypes.at_css("ServiceIdText") == nil
|
|
281
|
+
|
|
282
|
+
# Add new service to container
|
|
283
|
+
uftype.add_filetypeservice(newservice)
|
|
284
|
+
|
|
285
|
+
end
|
|
286
|
+
# Add userfiletype to container
|
|
287
|
+
self.add_userfiletype(uftype)
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!-- edited with XMLSpy v2009 (http://www.altova.com) by Petri Luoto (Nordea) -->
|
|
3
|
+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:bxd="http://bxd.fi/xmldata/" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" targetNamespace="http://bxd.fi/xmldata/" elementFormDefault="qualified" attributeFormDefault="unqualified">
|
|
4
|
+
<xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsig-core-schema.xsd"/>
|
|
5
|
+
<xs:element name="ApplicationRequest">
|
|
6
|
+
<xs:annotation>
|
|
7
|
+
<xs:documentation>Wrapper for data. Used for transmitting data. Can be XML Digital Signed.</xs:documentation>
|
|
8
|
+
</xs:annotation>
|
|
9
|
+
<xs:complexType>
|
|
10
|
+
<xs:sequence>
|
|
11
|
+
<xs:element name="CustomerId" nillable="false">
|
|
12
|
+
<xs:simpleType>
|
|
13
|
+
<xs:restriction base="xs:string">
|
|
14
|
+
<xs:minLength value="1"/>
|
|
15
|
+
<xs:maxLength value="16"/>
|
|
16
|
+
</xs:restriction>
|
|
17
|
+
</xs:simpleType>
|
|
18
|
+
</xs:element>
|
|
19
|
+
<xs:element name="Command" nillable="false" minOccurs="0">
|
|
20
|
+
<xs:simpleType>
|
|
21
|
+
<xs:restriction base="xs:string">
|
|
22
|
+
<xs:maxLength value="32"/>
|
|
23
|
+
<xs:minLength value="1"/>
|
|
24
|
+
</xs:restriction>
|
|
25
|
+
</xs:simpleType>
|
|
26
|
+
</xs:element>
|
|
27
|
+
<xs:element name="Timestamp" type="xs:dateTime"/>
|
|
28
|
+
<xs:element name="StartDate" type="xs:date" nillable="false" minOccurs="0"/>
|
|
29
|
+
<xs:element name="EndDate" type="xs:date" minOccurs="0"/>
|
|
30
|
+
<xs:element name="Status" minOccurs="0">
|
|
31
|
+
<xs:simpleType>
|
|
32
|
+
<xs:restriction base="xs:string">
|
|
33
|
+
<xs:minLength value="1"/>
|
|
34
|
+
<xs:maxLength value="10"/>
|
|
35
|
+
</xs:restriction>
|
|
36
|
+
</xs:simpleType>
|
|
37
|
+
</xs:element>
|
|
38
|
+
<xs:element name="ServiceId" minOccurs="0">
|
|
39
|
+
<xs:simpleType>
|
|
40
|
+
<xs:restriction base="xs:string">
|
|
41
|
+
<xs:minLength value="1"/>
|
|
42
|
+
<xs:maxLength value="256"/>
|
|
43
|
+
</xs:restriction>
|
|
44
|
+
</xs:simpleType>
|
|
45
|
+
</xs:element>
|
|
46
|
+
<xs:element name="Environment" type="bxd:EnvironmentCode"/>
|
|
47
|
+
<xs:element name="FileReferences" minOccurs="0">
|
|
48
|
+
<xs:complexType>
|
|
49
|
+
<xs:sequence>
|
|
50
|
+
<xs:element name="FileReference" maxOccurs="unbounded">
|
|
51
|
+
<xs:simpleType>
|
|
52
|
+
<xs:restriction base="xs:string">
|
|
53
|
+
<xs:minLength value="1"/>
|
|
54
|
+
<xs:maxLength value="32"/>
|
|
55
|
+
</xs:restriction>
|
|
56
|
+
</xs:simpleType>
|
|
57
|
+
</xs:element>
|
|
58
|
+
</xs:sequence>
|
|
59
|
+
</xs:complexType>
|
|
60
|
+
</xs:element>
|
|
61
|
+
<xs:element name="UserFilename" minOccurs="0">
|
|
62
|
+
<xs:simpleType>
|
|
63
|
+
<xs:restriction base="xs:string">
|
|
64
|
+
<xs:minLength value="1"/>
|
|
65
|
+
<xs:maxLength value="80"/>
|
|
66
|
+
</xs:restriction>
|
|
67
|
+
</xs:simpleType>
|
|
68
|
+
</xs:element>
|
|
69
|
+
<xs:element name="TargetId" minOccurs="0">
|
|
70
|
+
<xs:simpleType>
|
|
71
|
+
<xs:restriction base="xs:string">
|
|
72
|
+
<xs:minLength value="1"/>
|
|
73
|
+
<xs:maxLength value="80"/>
|
|
74
|
+
</xs:restriction>
|
|
75
|
+
</xs:simpleType>
|
|
76
|
+
</xs:element>
|
|
77
|
+
<xs:element name="ExecutionSerial" minOccurs="0">
|
|
78
|
+
<xs:simpleType>
|
|
79
|
+
<xs:restriction base="xs:string">
|
|
80
|
+
<xs:minLength value="1"/>
|
|
81
|
+
<xs:maxLength value="32"/>
|
|
82
|
+
</xs:restriction>
|
|
83
|
+
</xs:simpleType>
|
|
84
|
+
</xs:element>
|
|
85
|
+
<xs:element name="Encryption" type="xs:boolean" minOccurs="0"/>
|
|
86
|
+
<xs:element name="EncryptionMethod" minOccurs="0">
|
|
87
|
+
<xs:simpleType>
|
|
88
|
+
<xs:restriction base="xs:string">
|
|
89
|
+
<xs:minLength value="1"/>
|
|
90
|
+
<xs:maxLength value="35"/>
|
|
91
|
+
</xs:restriction>
|
|
92
|
+
</xs:simpleType>
|
|
93
|
+
</xs:element>
|
|
94
|
+
<xs:element name="Compression" type="xs:boolean" minOccurs="0"/>
|
|
95
|
+
<xs:element name="CompressionMethod" minOccurs="0">
|
|
96
|
+
<xs:simpleType>
|
|
97
|
+
<xs:restriction base="xs:string">
|
|
98
|
+
<xs:minLength value="1"/>
|
|
99
|
+
<xs:maxLength value="35"/>
|
|
100
|
+
</xs:restriction>
|
|
101
|
+
</xs:simpleType>
|
|
102
|
+
</xs:element>
|
|
103
|
+
<xs:element name="AmountTotal" type="xs:double" minOccurs="0"/>
|
|
104
|
+
<xs:element name="TransactionCount" type="xs:long" minOccurs="0"/>
|
|
105
|
+
<xs:element name="SoftwareId">
|
|
106
|
+
<xs:simpleType>
|
|
107
|
+
<xs:restriction base="xs:string">
|
|
108
|
+
<xs:minLength value="1"/>
|
|
109
|
+
<xs:maxLength value="80"/>
|
|
110
|
+
</xs:restriction>
|
|
111
|
+
</xs:simpleType>
|
|
112
|
+
</xs:element>
|
|
113
|
+
<xs:element name="CustomerExtension" type="xs:anyType" minOccurs="0"/>
|
|
114
|
+
<xs:element name="FileType" minOccurs="0">
|
|
115
|
+
<xs:simpleType>
|
|
116
|
+
<xs:restriction base="xs:string">
|
|
117
|
+
<xs:minLength value="1"/>
|
|
118
|
+
<xs:maxLength value="40"/>
|
|
119
|
+
</xs:restriction>
|
|
120
|
+
</xs:simpleType>
|
|
121
|
+
</xs:element>
|
|
122
|
+
<xs:element name="Content" type="xs:base64Binary" nillable="true" minOccurs="0"/>
|
|
123
|
+
<xs:element ref="ds:Signature" minOccurs="0"/>
|
|
124
|
+
</xs:sequence>
|
|
125
|
+
</xs:complexType>
|
|
126
|
+
</xs:element>
|
|
127
|
+
<xs:simpleType name="EnvironmentCode">
|
|
128
|
+
<xs:annotation>
|
|
129
|
+
<xs:documentation>Production or Test</xs:documentation>
|
|
130
|
+
</xs:annotation>
|
|
131
|
+
<xs:restriction base="xs:NMTOKEN">
|
|
132
|
+
<xs:pattern value="(PRODUCTION|TEST)"/>
|
|
133
|
+
</xs:restriction>
|
|
134
|
+
</xs:simpleType>
|
|
135
|
+
</xs:schema>
|