DEV Community

Sahil Gadimbayli
Sahil Gadimbayli

Posted on

Processing SEPA transactions with Ruby

SEPA,
also known as Single European Payment Area, is a system of tools/technologies/regulations,
facilitating simplifacation of bank transfers denominated in EUR.

There are quite a few steps involved in processing
SEPA transactions from start to end. These include:

  • management of EBICS users
  • generation of XML documents with different formats; depending on your needs
  • communicating XML files to financial institutions
  • reading and parsing bank statements to perform updates in your system (if needed)

Building all of the above from scratch would take a considerable
amount of time. I have encountered a few awesome tools in ruby, that
may help us with just that, and save some of your precious time.

We will go through tools that we can use for each step, also
noting some gotchas along the way.

Management of EBICS users

First of all, to submit transactions and fetch bank statements,
we would need to have the EBICS users contracted, configured and confirmed.

This post assumes that you have done a contractual part
with your bank/financial institution and have details
at hand for the user. If not, please contact your
financial institution to provide you with an EBICS user.

EBICS users can be an SRZ type or not. The difference is that the prior
may process transactions on behalf of other customers of
the bank, given the authorization. Normal users (NON-SRZ) may only
process transactions for bank account it is associated with.

So, before asking for an EBICS user, it's good to know what your
needs are for its utilization.

Configuring and confirming an EBICS user involves 3 steps.

  1. Create an EBICS user with data given by your financial institution; saving keys, and other user-related data.
  2. Print INI file received after creation, and physically sign/send to bank
  3. Confirm the user when you receive ok from your bank

Folks at Rails Love built an awesome
gem Epics, to do just that.

Let's get started.

Setting up the user initially...

# initialize user

user =
  Epics::Client.setup(
    "some-secure-password",
    "https://ebics.sandbox",
    "EBICS_HOST_ID",
    "EBICS_USER_ID",
    "EBICS_PARTNER_ID"
  )

# save keys (important!)

user.save_keys('path/to/my.key')

# submit keys to the bank
# sends the signature key
user.INI

# sends the encryption and authentication keys
user.HIA

# save ini file (you will need to print, sign and send this to the bank)

user.save_ini_letter( 'Bank Name', "/path/to/ini.html" )
Enter fullscreen mode Exit fullscreen mode

Once your financial institution confirms that you may proceed
with the user, you will have to confirm the user again(HBP order type)
and download public keys of the bank.

Epics gem becomes handy in this part as well.

# initialize the client you have set up above

user = Epics::Client.new(
  File.open('/path/to/my.key'),
  'some-secure-password',
  'https://ebics.sandbox',
  'EBICS_HOST_ID',
  'EBICS_USER_ID',
  'EBICS_PARTNER_ID'
  )

# confirm and fetch the bank's public keys

user.HBP

# save new keys
# (you will use these keys from now on to initialize client)

user.save_keys('path/to/my.key')

# Try something to see if user works.

# this will return available order
# types for the user. However, from experience
# this list is not always correct :)
user.HAA
Enter fullscreen mode Exit fullscreen mode

Now, we have got the EBICS user creation out of the
way, let's go through how we can build an XML from
list of transactions with correct format.

Generating XML documents consisting your transactions

Folks at SalesKing, wrote
an awesome gem Sepa King
to build XML files for direct debit and credit transactions
with legacy and latest schema format.

Note that, Sepa King will suit your needs only if you are
using a NON-SRZ user.

It is due to differences between container and non-container
XML schema, which Sepa King currently does not support.

Explaining container/non-container format is not part of this
blog post, thus we skip to usage of Sepa King.

Identify if you would like to create a debit or credit
transaction, and create an XML out of it by providing data
to Sepa King.

Have a look at their Readme,
as it is pretty straight forward.

Once you have generated the XML, we need to communicate this to
the bank.

Communicating XML to financial institutions

Now we have the XML file from Sepa King, we can use the
Epics gem again to initialize our EBICS user, and communicate
this XML to the bank.

# Generate the XML file
xml_file =
  'your_xml_output_received_from_sepa_king...'

# initialize EBICS user

user =
  Epics::Client.new(
    File.open('/path/to/my.key'),
    'some-secure-password',
    'https://ebics.sandbox',
    'EBICS_HOST_ID',
    'EBICS_USER_ID',
    'EBICS_PARTNER_ID'
  )

# Submit to bank

puts user.CDD(xml_file) # for direct debit
puts user.CCT(xml_file) # for direct transfer
Enter fullscreen mode Exit fullscreen mode

Response is transaction_id and order_id of the order.
Mind that the order type(CDD|CCT) is important to distinguish
as they are used for seperate things( direct debit vs direct transfers).

It may happen that some order types are not available for
your user, and you may get errors due to not being authorized
to perform such orders. In that case, contact your financial
institution to enable the required order types.

Fetching and parsing bank statements to perform updates

It may be that, you need to follow up with the transactions
you have submitted previously by reading bank statements, parsing
it to perform updates in your system or to send out notifications.
You decide...

Parsing XML documents and digging for data using Xpath is always
painful. To ease their pain for common good, folks at Barzahlen
wrote another awesome gem Camt Parser,
which parses bank statements and supports several formats(C52, 53, 54).

Let's get to use it.

# Initialize EBICS user

user =
  Epics::Client.new(
    File.open('/path/to/my.key'),
    'some-secure-password',
    'https://ebics.sandbox',
    'EBICS_HOST_ID',
    'EBICS_USER_ID',
    'EBICS_PARTNER_ID'
  )

# Request C53 bank statement

collection_of_statements =
  user.C53(from_date = "2020-04-14", to_date = "2020-04-15")

# Pass it to camt_parser

parsed_document =
  CamtParser::String.parse(collection_of_statements[0])

# You may also parse files
parsed_document =
  CamtParser::File.parse '/path/to/your_statement.xml'

# Now, you can iterate over statements

parsed_document.statements.each do |statement|
  puts statement.account.iban
  statement.entries.each do |entry|
    # Access individual entries/bank transfers
    puts entry.amount
    puts entry.debitor.iban
  end
end
Enter fullscreen mode Exit fullscreen mode

See other accessors and how an example C53 statement looks
like here.

That's all for now.

We have gone through:

  • creation and management of EBICS users
  • creation of Direct Debit and Transfer XML files
  • communication with banks
  • parsing and using bank statements

There are lots of small stuff that we did not cover in this
post such as batch booking, differences in statements, container
and non-container XML formats. However, this should get you started.

Wish you chargeback-free statements :), and let me
know if you have any suggestions for the post or questions about SEPA.

This post has also been published @ramblingcode.

Discussion (0)