Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add container support #120

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 52 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ We love building payment applications! So after developing the [DTAUS library fo

This gem implements the following two messages out of the ISO 20022 standard:

* Credit Transfer Initiation (`pain.001.003.03`, `pain.001.002.03` and `pain.001.001.03`)
* Direct Debit Initiation (`pain.008.003.02`, `pain.008.002.02` and `pain.008.001.02`)
* Credit Transfer Initiation (`pain.001.003.03`, `pain.001.002.03`, `pain.001.001.03`, and `pain.001.001.09`)
* Direct Debit Initiation (`pain.008.003.02`, `pain.008.002.02`, `pain.008.001.02`, and `pain.008.001.08`)

It handles the _Specification of Data Formats_ v3.3 (2019-11-17).
It handles the _Specification of Data Formats_ v3.3 (2019-11-17) and partially v3.7 (2023-11-19).

BTW: **pain** is a shortcut for **Pa**yment **In**itiation.

Expand Down Expand Up @@ -52,7 +52,12 @@ sdd = SEPA::DirectDebit.new(

# Creditor Identifier, in German: Gläubiger-Identifikationsnummer
# String, max. 35 chars
creditor_identifier: 'DE98ZZZ09999999999'
creditor_identifier: 'DE98ZZZ09999999999',

# Optional: Organization ID, in German: Organisationsidentifier
# Can be e.g. an EBICS Account ID
# String
organization_id: 'EXAMPLE1'
)

# Second: Add transactions
Expand Down Expand Up @@ -118,7 +123,7 @@ sdd.add_transaction(

# OPTIONAL: Enables or disables batch booking, in German "Sammelbuchung / Einzelbuchung"
# True or False
batch_booking: true
batch_booking: true,

# OPTIONAL: Use a different creditor account
# CreditorAccount
Expand Down Expand Up @@ -165,7 +170,12 @@ sct = SEPA::CreditTransfer.new(

# International Bank Account Number of the debtor
# String, max. 34 chars
iban: 'DE87200500001234567890'
iban: 'DE87200500001234567890',

# Optional: Organization ID, in German: Organisationsidentifier
# Can be e.g. an EBICS Account ID
# String
organization_id: 'EXAMPLE1'
)

# Second: Add transactions
Expand Down Expand Up @@ -240,6 +250,42 @@ xml_string = sct.to_xml # Use schema pain.001.001.03
xml_string = sct.to_xml('pain.001.002.03') # Use schema pain.001.002.03
```

How to create the XML for Container files

```ruby
sct = SEPA::CreditTransfer.new(
name: 'Schuldner GmbH',
bic: 'BANKDEFFXXX',
iban: 'DE87200500001234567890'
)

sct.add_transaction(
name: 'Telekomiker AG',
bic: 'PBNKDEFF370',
iban: 'DE37112589611964645802',
amount: 102.50,
currency: 'EUR',
instruction: '12345',
reference: 'XYZ-1234/123',
remittance_information: 'Rechnung vom 22.08.2013',
requested_date: Date.new(2024,6,5),
)


container = SEPA::Container.new(
# Depends on alignment with the bank executing the file
sender_id: 'ABCDEFGH',
# Depends on alignment with the bank executing the file
id_type: 'EBIC',
)

container.add_message(sct)
container.add_message ...

container.to_xml # Use schema container.nnn.001.GBIC4
container.to_xml('container.nnn.001.04') # Use schema container.nnn.001.04
```

## Validations

You can rely on our internal validations, raising errors when needed, during
Expand Down
89 changes: 89 additions & 0 deletions lib/schema/container.nnn.001.02.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:conxml="urn:conxml:xsd:container.nnn.001.02" xmlns:DocPain001="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03" xmlns:DocPain008="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02" xmlns:ns1="urn:conxml:xsd:container.nnn.001.02" targetNamespace="urn:conxml:xsd:container.nnn.001.02" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:import namespace="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03" schemaLocation="pain.001.001.03.xsd"/>
<xs:import namespace="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02" schemaLocation="pain.008.001.02.xsd"/>
<xs:element name="conxml" type="conxml:conxml"/>
<xs:complexType name="conxml">
<xs:sequence>
<xs:element name="ContainerId">
<xs:annotation>
<xs:documentation>ContainerId and CreDtTm should form a unique reference. This reference must be provided in the signature authorizing the container.
Defined as optional because the data might be provided by the bank's responder system instead of customers.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="SenderId">
<xs:annotation>
<xs:documentation>User ID (BCS or EBICS or RVS file and station ID, or other)</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="22"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="IdType">
<xs:annotation>
<xs:documentation>Type of ID provided. It may indicate the routing layer/communication protocol the id is valid for. Recommended are: BCS, EBIC, BFTP, H2H, RVS, X400, CD, SFTP, SCP. It is intended to allow for additional bilaterally agreed values, so no enumeration is defined here.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="4"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="TimeStamp">
<xs:annotation>
<xs:documentation>Time Stamp with a millisecond precision, as a numeric string of length 9 (hhmmssxxx)</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:length value="9"/>
<xs:pattern value="[0-9]{9,9}"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="CreDtTm" type="conxml:ISODateTime">
<xs:annotation>
<xs:documentation>Creation Timestamp for container structure</xs:documentation>
</xs:annotation>
</xs:element>
<xs:choice>
<xs:element name="MsgPain001" type="conxml:MsgPain001" maxOccurs="unbounded"/>
<xs:element name="MsgPain008" type="conxml:MsgPain008" maxOccurs="unbounded"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType name="MsgPain001">
<xs:sequence>
<xs:element name="HashValue" type="conxml:HashSHA256" minOccurs="0"/>
<xs:element name="HashAlgorithm" type="conxml:HashAlgorithm" minOccurs="0"/>
<xs:element ref="DocPain001:Document"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="MsgPain008">
<xs:sequence>
<xs:element name="HashValue" type="conxml:HashSHA256" minOccurs="0"/>
<xs:element name="HashAlgorithm" type="conxml:HashAlgorithm" minOccurs="0"/>
<xs:element ref="DocPain008:Document"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="HashSHA256">
<xs:restriction base="xs:string">
<xs:minLength value="64"/>
<xs:maxLength value="64"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="HashAlgorithm">
<xs:restriction base="xs:string">
<xs:enumeration value="SHA256"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ISODateTime">
<xs:restriction base="xs:dateTime"/>
</xs:simpleType>
</xs:schema>
102 changes: 102 additions & 0 deletions lib/schema/container.nnn.001.04.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?xml version="1.0"?>
<!-- XML-Container der DK - Version gemäß DFÜ-Abkommen Anlage 3, Version 3.7, gültig ab November 2023 -->
<!-- Mit XMLSpy v2020 rel. 2 sp1 (http://www.altova.com) am 28.10.2022 von Sabine Wenzel(SIZ GmbH) bearbeitet -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:conxml="urn:conxml:xsd:container.nnn.001.04" xmlns:DocPain001="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" xmlns:DocPain007="urn:iso:std:iso:20022:tech:xsd:pain.007.001.09" xmlns:DocPain008="urn:iso:std:iso:20022:tech:xsd:pain.008.001.08" xmlns:ns1="urn:conxml:xsd:container.nnn.001.04" targetNamespace="urn:conxml:xsd:container.nnn.001.04" elementFormDefault="qualified" attributeFormDefault="unqualified">
<!-- Die Angaben beziehen sich auf die technical Validation Subsets (TSV) der Deutschen Kreditwirtschaft für den SEPA-ZV -->
<!-- Daher ist hier der xsd-Name der DK-TVS genannt - bei Bedarf kann auch schemaLocation ohne den Zusatz _GBIC_4 verwendet werden -->
<xs:import namespace="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" schemaLocation="pain.001.001.09.xsd"/>
<xs:import namespace="urn:iso:std:iso:20022:tech:xsd:pain.007.001.09" schemaLocation="pain.007.001.09.xsd"/>
<xs:import namespace="urn:iso:std:iso:20022:tech:xsd:pain.008.001.08" schemaLocation="pain.008.001.08.xsd"/>
<xs:element name="conxml" type="conxml:conxml"/>
<xs:complexType name="conxml">
<xs:sequence>
<xs:element name="ContainerId">
<xs:annotation>
<xs:documentation>ContainerId and CreDtTm should form a unique reference. This reference must be provided in the signature authorizing the container.
Defined as optional because the data might be provided by the bank's responder system instead of customers.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="SenderId">
<xs:annotation>
<xs:documentation>User ID (BCS or EBICS or RVS file and station ID, or other)</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="22"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="IdType">
<xs:annotation>
<xs:documentation>Type of ID provided. It may indicate the routing layer/communication protocol the id is valid for. Recommended are: BCS, EBIC, BFTP, H2H, RVS, X400, CD, SFTP, SCP. It is intended to allow for additional bilaterally agreed values, so no enumeration is defined here.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="4"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="TimeStamp">
<xs:annotation>
<xs:documentation>Time Stamp with a millisecond precision, as a numeric string of length 9 (hhmmssxxx)</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:length value="9"/>
<xs:pattern value="[0-9]{9,9}"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="CreDtTm" type="conxml:ISODateTime">
<xs:annotation>
<xs:documentation>Creation Timestamp for container structure</xs:documentation>
</xs:annotation>
</xs:element>
<xs:choice>
<xs:element name="MsgPain001" type="conxml:MsgPain001" maxOccurs="unbounded"/>
<xs:element name="MsgPain007" type="conxml:MsgPain007" maxOccurs="unbounded"/>
<xs:element name="MsgPain008" type="conxml:MsgPain008" maxOccurs="unbounded"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType name="MsgPain001">
<xs:sequence>
<xs:element name="HashValue" type="conxml:HashSHA256" minOccurs="0"/>
<xs:element name="HashAlgorithm" type="conxml:HashAlgorithm" minOccurs="0"/>
<xs:element ref="DocPain001:Document"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="MsgPain007">
<xs:sequence>
<xs:element name="HashValue" type="conxml:HashSHA256" minOccurs="0"/>
<xs:element name="HashAlgorithm" type="conxml:HashAlgorithm" minOccurs="0"/>
<xs:element ref="DocPain007:Document"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="MsgPain008">
<xs:sequence>
<xs:element name="HashValue" type="conxml:HashSHA256" minOccurs="0"/>
<xs:element name="HashAlgorithm" type="conxml:HashAlgorithm" minOccurs="0"/>
<xs:element ref="DocPain008:Document"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="HashSHA256">
<xs:restriction base="xs:string">
<xs:minLength value="64"/>
<xs:maxLength value="64"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="HashAlgorithm">
<xs:restriction base="xs:string">
<xs:enumeration value="SHA256"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ISODateTime">
<xs:restriction base="xs:dateTime"/>
</xs:simpleType>
</xs:schema>
102 changes: 102 additions & 0 deletions lib/schema/container.nnn.001.GBIC4.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?xml version="1.0"?>
<!-- XML-Container der DK - Version gemäß DFÜ-Abkommen Anlage 3, Version 3.7, gültig ab November 2023 -->
<!-- Mit XMLSpy v2020 rel. 2 sp1 (http://www.altova.com) am 28.10.2022 von Sabine Wenzel(SIZ GmbH) bearbeitet -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:conxml="urn:conxml:xsd:container.nnn.001.GBIC4" xmlns:DocPain001="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" xmlns:DocPain007="urn:iso:std:iso:20022:tech:xsd:pain.007.001.09" xmlns:DocPain008="urn:iso:std:iso:20022:tech:xsd:pain.008.001.08" xmlns:ns1="urn:conxml:xsd:container.nnn.001.GBIC4" targetNamespace="urn:conxml:xsd:container.nnn.001.GBIC4" elementFormDefault="qualified" attributeFormDefault="unqualified">
<!-- Die Angaben beziehen sich auf die technical Validation Subsets (TSV) der Deutschen Kreditwirtschaft für den SEPA-ZV -->
<!-- Daher ist hier der xsd-Name der DK-TVS genannt - bei Bedarf kann auch schemaLocation ohne den Zusatz _GBIC_4 verwendet werden -->
<xs:import namespace="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" schemaLocation="pain.001.001.09.xsd"/>
<xs:import namespace="urn:iso:std:iso:20022:tech:xsd:pain.007.001.09" schemaLocation="pain.007.001.09.xsd"/>
<xs:import namespace="urn:iso:std:iso:20022:tech:xsd:pain.008.001.08" schemaLocation="pain.008.001.08.xsd"/>
<xs:element name="conxml" type="conxml:conxml"/>
<xs:complexType name="conxml">
<xs:sequence>
<xs:element name="ContainerId">
<xs:annotation>
<xs:documentation>ContainerId and CreDtTm should form a unique reference. This reference must be provided in the signature authorizing the container.
Defined as optional because the data might be provided by the bank's responder system instead of customers.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="SenderId">
<xs:annotation>
<xs:documentation>User ID (BCS or EBICS or RVS file and station ID, or other)</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="22"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="IdType">
<xs:annotation>
<xs:documentation>Type of ID provided. It may indicate the routing layer/communication protocol the id is valid for. Recommended are: BCS, EBIC, BFTP, H2H, RVS, X400, CD, SFTP, SCP. It is intended to allow for additional bilaterally agreed values, so no enumeration is defined here.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="4"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="TimeStamp">
<xs:annotation>
<xs:documentation>Time Stamp with a millisecond precision, as a numeric string of length 9 (hhmmssxxx)</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:length value="9"/>
<xs:pattern value="[0-9]{9,9}"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="CreDtTm" type="conxml:ISODateTime">
<xs:annotation>
<xs:documentation>Creation Timestamp for container structure</xs:documentation>
</xs:annotation>
</xs:element>
<xs:choice>
<xs:element name="MsgPain001" type="conxml:MsgPain001" maxOccurs="unbounded"/>
<xs:element name="MsgPain007" type="conxml:MsgPain007" maxOccurs="unbounded"/>
<xs:element name="MsgPain008" type="conxml:MsgPain008" maxOccurs="unbounded"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType name="MsgPain001">
<xs:sequence>
<xs:element name="HashValue" type="conxml:HashSHA256" minOccurs="0"/>
<xs:element name="HashAlgorithm" type="conxml:HashAlgorithm" minOccurs="0"/>
<xs:element ref="DocPain001:Document"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="MsgPain007">
<xs:sequence>
<xs:element name="HashValue" type="conxml:HashSHA256" minOccurs="0"/>
<xs:element name="HashAlgorithm" type="conxml:HashAlgorithm" minOccurs="0"/>
<xs:element ref="DocPain007:Document"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="MsgPain008">
<xs:sequence>
<xs:element name="HashValue" type="conxml:HashSHA256" minOccurs="0"/>
<xs:element name="HashAlgorithm" type="conxml:HashAlgorithm" minOccurs="0"/>
<xs:element ref="DocPain008:Document"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="HashSHA256">
<xs:restriction base="xs:string">
<xs:minLength value="64"/>
<xs:maxLength value="64"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="HashAlgorithm">
<xs:restriction base="xs:string">
<xs:enumeration value="SHA256"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ISODateTime">
<xs:restriction base="xs:dateTime"/>
</xs:simpleType>
</xs:schema>
Loading
Loading