Implementing Swiss Payments Code (SPC) and QR code invoicing with Invoice Ninja

Written by - 13 comments

Published on - last updated on May 23rd 2022 - Listed in Internet Coding Personal


At Infiniroot we asked ourselves a couple of years ago: How can we improve our invoicing mechanism and reduce the time investment in creating invoices? The old method (basically using Excel and Word, creating a PDF of it and sending to the customers) could definitely be improved.

The path to InvoiceNinja

We realized that creating invoices of one-shot projects would still require a certain amount of time, but invoices on recurring services (such as server hosting) could definitely be automated.

But we didn't just want any invoicing solution:

  • Costs: As we are a small company with our own funding, a tight budget wouldn't allow using big name billing systems.  
  • Data Privacy: All our customer data is stored on our own servers, none resides in "the cloud" (unless explicitly requested by the customer). This applies to both customer data on their managed dedicated servers but also to administrative documents such as invoices or contracts. We wanted a billing system which could be self-hosted on our own servers, under our own control.
  • Open Source: As we are working with Open Source, sharing and selling our knowledge of Open Source Software and related Solutions, we also wanted a billing system which is open sourced.

This is when we finally found Invoiceninja! And we were amazed. Working with invoices finally made fun.

ESR Next Generation: QR code invoicing

The automatically created PDF invoices contain our payment information at the footer. We've (probably) been lucky so far, that all our customers never requested an "old style" payment slip, also known as "Einzahlungsschein" or "ESR" (containing a reference number), and copied the payment information from the invoice footer directly into their own payment system.

As ESR's are at the end of their life in Switzerland in 2020, a new kind of "invoice coding" emerges: QR codes on invoices.

The Swiss QR Invoice has a standardized data structure which is documented in the Swiss Implementation Guidelines QR-Bill document. With a bit of technical flair and some "thinking outside the box", the automatic creation of such QR codes can be implemented into InvoiceNinja.

Understanding the SPC data

Behind the optical QR code resides the "SPC data", which is short for "Swiss Payments Code". This data basically contains a couple of lines, each line with a value for a certain field, for example the currency. Here's such an example:

SPC
0200
1
CH5800791123000889012
S
Robert Schneider AG
Rue du Lac
1268
2501
Biel
CH
\n           
\n           
\n           
\n           
\n           
\n           
\n           
3949.75
CHF
S
Pia Rutschmann
Marktgasse
28
9400
Rorschach
CH
NON
\n        
Bill no. 3139 for gardening work and disposal of waste material
EPD
\n

Without going too much into details (read the implementation guide for this), the data starts with SPC internal reference codes (SPC, Version 0200, 1) followed by the invoice sender's (Debitor) IBAN bank account and a structured (S) address of the sender. After exactly 7 new lines the amount of the invoice followed by the currency shows up. Adding the invoice recipient's (Kreditor) address is optional. Finally the data ends with an optional reference code or string and "EPD".

Structured address vs. combined address

The example data above use the "S" address format, which is short for structured format. This basically means that the address is split into multiple fields as this:

S
Company Name
Street Name
House Number
ZIP Code
City
Country Code

When using the "K" (combined) address format, certain elements can be put on the same line:

K
Company Name
Street Name House Number
ZIP Code City
Country Code
\n
\n

Street name and house number are merged into one line. The same happens with ZIP code and the city name. The remaining two lines reserved for the structured address format are now optional and should be left empty (new line).

Why is this important? InvoiceNinja does not split the street into structured fields, which can be seen in the Company Details Settings:

For this reason, the combined (K) address format needs to be used in SPC data.

Creating the QR code in a template

In InvoiceNinja's settings, the Invoice Design can be customized. When "Customize Design" tool is opened, the left side shows the backend code while the right side shows live changes on the final PDF design.

As I mentioned before, we're used to show our payment information in the invoice's footer. We wanted to put the QR code right next to this payment information. The trick however is to find the correct variables to use inside the code. InvoiceNinja's core developer Hillel Coren mentioned some of the variables can be found in the code's transformers. This certainly helps to find most of the needed variables but for certain a workaround is needed (more on that later).

With the following code snipped, almost all of the needed data can be dynamically inserted into the QR code:

    {
      "qr": "SPC\n0200\n1\nHard-Coded-IBAN\nK\n$account.name\n$account.address1\n$account.postal_code $account.city\n\n\nCH\n\n\n\n\n\n\n\n$balance\nCHF\n\n\n\n\n\n\nNON\n\n$invoice_number\nEPD\n",
      "fit": "100",
      "eccLevel": "H",
      "alignment": "right"
    }

Workaround for the invoice's currency

Although there is a $client.currency_id available according to the source code, it never showed any value. And even if it would show a value, it is not certain that the "ID" would actually show the international known currency string, such as USD, EUR or CHF. 

To circumvent this, a custom field can be created. InvoiceNinja supports two custom fields per category (products, clients, invoices, etc) which can then be used in the template. Under Settings -> Advanced Settings -> Invoice Settings, Custom Fields can be defined. Here a custom field called "Currency" is defined under the "Clients" category:

When a Client is now edited (or added), this new custom field shows up in the form:

Here the value "CHF" was added into this custom field.

The QR code was adjusted accordingly to retrieve the invoices currency dynamically from this custom field (using $client.custom_value1):

    {
      "qr": "SPC\n0200\n1\nHard-Coded-IBAN\nK\n$account.name\n$account.address1\n$account.postal_code $account.city\n\n\nCH\n\n\n\n\n\n\n\n$balance\n$client.custom_value1\n\n\n\n\n\n\n\nNON\n\n$invoice_number\nEPD\n",
      "fit": "100",
      "eccLevel": "H",
      "alignment": "right"
    }

This solution was also shared in the official InvoiceNinja community forums.

Creating an invoice with QR code

Now that everything is in place, a new invoice can be created and its QR code tested.

And in the PDF view of the invoice, the QR code shows up:

With a simple QR Code App this can now be read and the SPC data should be shown:

Official validation of the Swiss QR-bill code

An official Swiss QR bill code validator exists and a generated invoice can be uploaded to the validator. If no errors show up, the code is validated and can be used.

Swiss QR Bill Validator

Voilà! The validator scanned the QR code from the uploaded PDF invoice and could not detect any errors. Mission accomplished!

InvoiceNinja has once again proven to us, why we decided for it in the first place!

Final step: Adjusting the QR code design

The integrated custom design editor uses the pdfmake syntax. By using this syntax, the QR Bill design can be implemented as part of the invoice. Note that the footer doesn't hold enough space for the QR Bill - it needs to be placed into the content of the main invoice.

In order to add the Swiss cross in the middle of the QR code as an SVG image, pdfmake needs to be manually updated in Invoice Ninja. This can unfortunately only be done by manually building Invoice Ninja from the source code, using bower, npm and gulp commands.

Hint: use pdfmake's playground to create the design.

Swiss QR Code in invoice PDF, created by Invoice Ninja

Swiss QR Bill in Invoice Ninja v5

Update March 2022: Infiniroot is currently working and testing on a Swiss QR Bill implementation on the newer Invoice Ninja v5! Our first tests were successful and look promising. We are confident that we can roll this out and offer this as a service in the coming weeks! Here's a preview of the v5 with the Swiss QR Code as payment slip:

To get a "feeling" of the new Invoice Ninja version, we created a Getting Started Guide to Invoice Ninja v5, which is publicly available.

Update May 2022: Infiniroot offers hosted Invoice Ninja v5 in Switzerland since April 2022. The server setup fee also includes a template adjustment to enable the Swiss QR-Bill in invoices.

Your own Invoice Ninja server - data hosted in Switzerland

Since July 2020 Infiniroot offers dedicated InvoiceNinja servers in Switzerland. This allows you to run your own billing application using InvoiceNinja in a secure server environment and data in Switzerland, even with a low budget!


Add a comment

Show form to leave a comment

Comments (newest first)

Claudio Kuenzler from Switzerland wrote on Oct 6th, 2021:

By manually updating pdfmake in Invoice Ninja v4 to the current version (0.2.2), the SVG icon can be placed on top of the QR code. However it is quite a hassle to do that (using bower, npm, gulp with very specific versions).


ck from Switzerland wrote on Mar 11th, 2021:

Hi Luca. Sorry, but the pdfmake code will not be shared publicly as it was a lot of (commercial) effort behind it. If you are interested, contact me on Infiniroot and we can implement this for you for a fair price.


Luca from wrote on Mar 11th, 2021:

Hey Daniel
Thanks a lot, I really appreciate your work!
Would you mind sharing your pdfmake code? Thank you very much!


Claudio Kuenzler from Switzerland wrote on Jan 15th, 2021:

Hi Daniel. So yes, it seems that the pdfmake version embedded in Invoice Ninja is too old. From the pdfmake SVG documentation: Minimal version: 0.1.59. But Invoice Ninja uses 0.1.36 (./resources/assets/js/pdfmake.js).


Claudio Kuenzler from Switzerland wrote on Jan 15th, 2021:

Hi Daniel, I can confirm, it works in the pdfmake playground, but not (yet) in Invoice Ninja (uncaught exception: Unrecognized document structure: {"svg":"). I am not sure why though, maybe a difference in the pdfmake version.


Claudio Kuenzler from Switzerland wrote on Jan 15th, 2021:

Hi Daniel. This is an awesome hint! Thanks, I will try this!


Daniel from Greifensee wrote on Jan 15th, 2021:

Hallo Claudio

For the swiss cross maybe the code helps you. It works at http://pdfmake.org/playground.html


// playground requires you to assign document definition to a variable called dd

var dd = {
content: [
{
text: 'Swiss Cross over QR-Code',
fontSize: 32,
margin: [0, 0, 0, 20]
},
{
qr: 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.',
fit: 300
},
{
svg: '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="-55.15715 -55.15715 130.114285714 130.114285714"><rect x="0" y="0" width="19.8" height="19.8" style="fill:#ffffff;stroke:none;"/><rect x="1.41785" y="1.41785" class="st0" width="16.9643" height="16.9643" style="fill:#000000;stroke:none;"/><rect x="8.25" y="4.4" class="st0" width="3.3" height="11" style="fill:#ffffff;stroke:none;"/><rect x="4.4" y="8.25" class="st0" width="11" height="3.3" style="fill:#ffffff;stroke:none;"/></svg>',
fit: [300, 300],
margin: [0, -300, 0, 0]
},
]

}



Freundliche Grüsse
Daniel


ck from Switzerland wrote on Jan 4th, 2021:

Hello mrT. I will keep that in mind and contact you when finished. It might still take a while though.


mrT from wrote on Jan 4th, 2021:

Nice! if you ever plan to release the Business Logic around Invoice Ninja for purchase - let me know pls ... would love to have a complete feature set ... Thank you!


ck from Switzerland wrote on Dec 31st, 2020:

Hi mrT! The QR code is only for the payment from a customer point of view. Afterwards we manually enter the payments in Invoice Ninja. Currently this method works fine for us as the number of incoming payments are fine. However we are currently building a Business Logic around Invoice Ninja for a customer of us and the goal in this Business Logic is to automatically match payments, retrieved from a CAMT export, to invoices and mark them as paid.


mrT from wrote on Dec 30th, 2020:

Great find and nice implementation!

How do you process your invoices after a payment has been made by a customer using QR-code payment trigger?

This seems to be a manual action since the customer is being redirected to his/her banking app after scanning the QR code and making the payment there.
This way no trigger will be executed towards Invoice Ninja to update the invoice to status “paid”.




Claudio from Switzerland wrote on Nov 23rd, 2020:

Hello Frank, thanks for the comment! Actually the Swiss cross in the middle is not needed, it's more a design feature. In the standard it is written that it's there for quickly recognizing the new Swiss QR bill. But I agree, it would look much nicer in the invoices. However I could not find a method to embed a picture inside the QR code created by pdfmakers qr function. If you have a solution for that I am all ears :-)).


Franck from Lausanne wrote on Nov 23rd, 2020:

Hi many thanks for this tuto, it seems that you forgot the swiss cross in the middle of the QR code.
You can found the image here:
https://www.paymentstandards.ch/dam/downloads/swiss-cross.zip
If you found an idea to implement this image in invoiceninja template, I will be happy to share this with you.


RSS feed

Blog Tags:

  AWS   Android   Ansible   Apache   Apple   Atlassian   BSD   Backup   Bash   Bluecoat   CMS   Chef   Cloud   Coding   Consul   Containers   CouchDB   DB   DNS   Database   Databases   Docker   ELK   Elasticsearch   Filebeat   FreeBSD   Galera   Git   GlusterFS   Grafana   Graphics   HAProxy   HTML   Hacks   Hardware   Icinga   Icingaweb   Icingaweb2   Influx   Internet   Java   KVM   Kibana   Kodi   Kubernetes   LVM   LXC   Linux   Logstash   Mac   Macintosh   Mail   MariaDB   Minio   MongoDB   Monitoring   Multimedia   MySQL   NFS   Nagios   Network   Nginx   OSSEC   OTRS   Office   PGSQL   PHP   Perl   Personal   PostgreSQL   Postgres   PowerDNS   Proxmox   Proxy   Python   Rancher   Rant   Redis   Roundcube   SSL   Samba   Seafile   Security   Shell   SmartOS   Solaris   Surveillance   Systemd   TLS   Tomcat   Ubuntu   Unix   VMWare   VMware   Varnish   Virtualization   Windows   Wireless   Wordpress   Wyse   ZFS   Zoneminder   


Update cookies preferences