swissqr

package module
v0.0.0-...-5cc0e94 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2019 License: Apache-2.0 Imports: 16 Imported by: 0

README

QR Bills in Switzerland

Package swissqr creates a QR invoice form as described in version 2.0 of the document “[Schweizer Implementation Guidelines QR-Rechnung] (https://www.paymentstandards.ch/dam/downloads/ig-qr-bill-de.pdf)”, dated 15 November 2018, together with version 1.2 of the document “[Syntaxdefinition der Rechnungsinformationen (S1) bei der QR-Rechnung] (https://www.swiss-qr-invoice.org/downloads/qr-bill-s1-syntax-de.pdf)”, dated 23 November 2018. This is not an officially supported Google product.

For example usage, please consult the example_*_test.go files. The general pattern is: first initialize a struct Payload with the invoice content. Next, validate that the payload is correct by calling the Validate() method on the payload. Last but not least, create the actual invoice and store it in a PDF document. When serializing the payload, it is a precondition that the payload be valid.

The implementation is a best-effort to satisfy the standard to the letter as well as the intention of the standard. Some points that were not clear from the standard have been clarified based on the validation tool available at [https://www.swiss-qr-invoice.org/]. Most importantly, there is an additional check to verify that only the characters specified in the Swiss Implementation Guidelines for Customer-Bank Messages Credit Transfer are used in the invoice:

abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789.,:'+-/()?
 !\"#%&*;<>÷=@_$£[]{}\`´~
àáâäçèéêëìíîïñòóôöùúûüýß
ÀÁÂÄÇÈÉÊËÌÍÎÏÒÓÔÖÙÚÛÜÑ

Documentation

Overview

package swissqr creates a QR code for electronic bills as defined in version 2.0 of the document “Schweizer Implementation Guidelines QR-Rechnung”, which can be downloaded from https://www.paymentstandards.ch/, and version 1.2 of the document “Syntaxdefinition der Rechnungsinformationen (S1) bei der QR- Rechnung”, which can be downloaded from https://www.swiss-qr-invoice.org/.

Example (ArmeeDuSalut)

Third example in Appendix A of the Swiss QR standard.

package main

import (
	"fmt"
	"github.com/krepost/gopdf/pdf"
	"github.com/krepost/swissqr"
	"os"
)

func main() {
	data := swissqr.Payload{
		Account: swissqr.NewIBANOrDie("CH3709000000304442225"),
		Creditor: swissqr.Entity{
			Name: "Fondation Armée du salut suisse",
			Address: swissqr.StructuredAddress{
				PostCode: "3000",
				TownName: "Berne",
			},
			CountryCode: "CH",
		},
		CurrencyAmount: swissqr.PaymentAmount{Currency: swissqr.CHF},
		AdditionalInformation: swissqr.PaymentInformation{
			UnstructuredMessage: "Don pour l'action Fête Hiver",
		},
	}
	if err := data.Validate(); err != nil {
		fmt.Println("Unexpected error:", err)
	}

	doc := pdf.New()
	canvas := doc.NewPage(21.0*pdf.Cm, 10.5*pdf.Cm) // QR invoice size.
	if err := swissqr.DrawInvoiceWithScissors(canvas, data, "fr"); err != nil {
		fmt.Println("Unexpected error:", err)
	}
	canvas.Close()

	if pdfFile, err := os.Create("example_salut.pdf"); err != nil {
		fmt.Println("Unexpected error:", err)
	} else {
		defer pdfFile.Close()
		if err := doc.Encode(pdfFile); err != nil {
			fmt.Println("Unexpected error:", err)
		}
	}

	fmt.Println("PDF file successfully created.")

}
Output:

PDF file successfully created.
Example (BoxWithScissors)

«If the QR-bill with payment part and receipt or the separate payment part with receipt are generated as a PDF document and sent electronically, the A6 format of the payment part and the receipt on the left must be indicated by lines. Each of these lines must bear the scissors symbol “✂” or alternatively the instruction “Separate before paying in” above the line (outside the payment part). This indicates to the debtor that he or she must neatly separate the payment part and receipt if they want to forward the QR-bill to their financial institution by post for payment, or settle it at the post office counter (branches or branches of partner organisations).»

package main

import (
	"fmt"
	"github.com/krepost/gopdf/pdf"
	"github.com/krepost/structref"
	"github.com/krepost/swissqr"
	"math"
	"os"
	"strings"
)

// «If the QR-bill with payment part and receipt or the separate payment part
// with receipt are generated as a PDF document and sent electronically, the A6
// format of the payment part and the receipt on the left must be indicated by
// lines. Each of these lines must bear the scissors symbol “✂” or
// alternatively the instruction “Separate before paying in” above the line
// (outside the payment part). This indicates to the debtor that he or she must
// neatly separate the payment part and receipt if they want to forward the
// QR-bill to their financial institution by post for payment, or settle it at
// the post office counter (branches or branches of partner organisations).»
func main() {
	doc := pdf.New()
	if err := box(doc); err != nil {
		fmt.Println(err)
	}
	if pdfFile, err := os.Create("example_box.pdf"); err != nil {
		fmt.Println(err)
	} else {
		defer pdfFile.Close()
		if err := doc.Encode(pdfFile); err != nil {
			fmt.Println(err)
		}
	}

	fmt.Println("PDF file successfully created.")

}

func box(doc *pdf.Document) error {
	data := swissqr.Payload{
		Account: swissqr.NewIBANOrDie("CH5800791123000889012"),
		Creditor: swissqr.Entity{
			Name: "Mobile Finanz AG",
			Address: swissqr.StructuredAddress{
				StreetName:     "Bernerstrasse",
				BuildingNumber: "234A",
				PostCode:       "8640",
				TownName:       "Rapperswil",
			},
			CountryCode: "CH",
		},
		CurrencyAmount: swissqr.PaymentAmount{
			Amount:   5005.95,
			Currency: swissqr.CHF,
		},
		UltimateDebtor: swissqr.Entity{
			Name: "Pia-Maria Rutschmann-Schnyder",
			Address: swissqr.StructuredAddress{
				StreetName:     "Grosse Marktgasse",
				BuildingNumber: "28/5",
				PostCode:       "9400",
				TownName:       "Rorschach",
			},
			CountryCode: "CH",
		},
		Reference: swissqr.PaymentReference{
			Number: structref.NewCreditorReferenceOrDie("RF83 1234 5678 9123 4567 8912"),
		},
		AdditionalInformation: swissqr.PaymentInformation{
			UnstructuredMessage: "Beachten Sie unsere Sonderangebotswoche bis 23.02.2017!",
		},
	}
	if err := data.Validate(); err != nil {
		return err
	}

	canvas := doc.NewPage(21.0*pdf.Cm, 29.7*pdf.Cm)
	if err := drawRotatedText(canvas); err != nil {
		return err
	}
	if err := drawAddress(canvas, data); err != nil {
		return err
	}
	if err := drawMainText(canvas, data); err != nil {
		return err
	}
	if err := swissqr.DrawInvoiceWithBorder(canvas, data, "de"); err != nil {
		return err
	}
	canvas.Close()
	return nil
}

func drawRotatedText(canvas *pdf.Canvas) error {
	font, err := canvas.Document().AddFont(pdf.HelveticaBold, pdf.WinAnsiEncoding)
	if err != nil {
		return err
	}
	canvas.Push()
	defer canvas.Pop()
	text := new(pdf.Text)
	text.UseFont(font, 120, 120)
	text.Text("Mobile")
	canvas.Rotate(math.Pi / 2.0)
	canvas.Translate(19.9*pdf.Cm-text.X()/2.0, -110)
	canvas.SetColor(0, 0, 0) // White text colour.
	canvas.DrawText(text)
	return nil
}

func drawAddress(canvas *pdf.Canvas, data swissqr.Payload) error {
	creditor, err := data.Creditor.ToLines()
	if err != nil {
		return err
	}
	debtor, err := data.UltimateDebtor.ToLines()
	if err != nil {
		return err
	}
	font, err := canvas.Document().AddFont(pdf.Helvetica, pdf.WinAnsiEncoding)
	if err != nil {
		return err
	}
	canvas.Push()
	defer canvas.Pop()
	address := new(pdf.Text)
	address.UseFont(font, 6, 8)
	address.Text(strings.Join(creditor, "  •  "))
	width := address.X()
	address.NextLine()
	address.UseFont(font, 10, 12)
	for _, line := range debtor {
		address.NextLine()
		address.Text(line)
	}
	canvas.SetColor(0, 0, 0) // Black text colour.
	canvas.Translate(11.0*pdf.Cm, 22.5*pdf.Cm-address.Y()/2.0)
	canvas.DrawText(address)
	adressSeparator := new(pdf.Path)
	adressSeparator.Move(pdf.Point{0, -3})
	adressSeparator.Line(pdf.Point{width, -3})
	canvas.SetLineWidth(0.5)
	canvas.Stroke(adressSeparator)
	return nil
}

func drawMainText(canvas *pdf.Canvas, data swissqr.Payload) error {
	amount := fmt.Sprintf("%v %v", data.CurrencyAmount.Currency, data.CurrencyAmount.Amount)
	roman, err := canvas.Document().AddFont(pdf.Times, pdf.WinAnsiEncoding)
	if err != nil {
		return err
	}
	bold, err := canvas.Document().AddFont(pdf.TimesBold, pdf.WinAnsiEncoding)
	if err != nil {
		return err
	}
	italics, err := canvas.Document().AddFont(pdf.TimesItalic, pdf.WinAnsiEncoding)
	if err != nil {
		return err
	}
	canvas.Push()
	defer canvas.Pop()
	text := new(pdf.Text)
	text.UseFont(bold, 10, 12)
	text.Text("Rechnung")
	text.NextLine()
	text.NextLine()
	text.UseFont(roman, 10, 12)
	text.Text("Für unsere Dienstleistungen per 1. April 2017: " + amount + ".")
	text.NextLine()
	text.NextLine()
	text.Text("Mit freundlichen Grüssen,")
	text.NextLine()
	text.NextLine()
	text.UseFont(italics, 10, 12)
	text.Text("Ihr Mobile-Team")
	canvas.Translate(5*pdf.Cm, 18*pdf.Cm)
	canvas.DrawText(text)
	return nil
}
Output:

PDF file successfully created.
Example (GardeningInvoice)

First example in Appendix A of the Swiss QR standard.

package main

import (
	"fmt"
	"github.com/krepost/gopdf/pdf"
	"github.com/krepost/swissqr"
	"os"
)

func main() {
	data := swissqr.Payload{
		Account: swissqr.NewIBANOrDie("CH58 0079 1123 0008 8901 2"),
		Creditor: swissqr.Entity{
			Name: "Robert Schneider AG",
			Address: swissqr.StructuredAddress{
				StreetName:     "Rue du Lac",
				BuildingNumber: "1268",
				PostCode:       "2501",
				TownName:       "Biel",
			},
			CountryCode: "CH",
		},
		CurrencyAmount: swissqr.PaymentAmount{
			Amount:   3949.75,
			Currency: swissqr.CHF,
		},
		UltimateDebtor: swissqr.Entity{
			Name: "Pia Rutschmann",
			Address: swissqr.StructuredAddress{
				StreetName:     "Marktgasse",
				BuildingNumber: "28",
				PostCode:       "9400",
				TownName:       "Rorschach",
			},
			CountryCode: "CH",
		},
		AdditionalInformation: swissqr.PaymentInformation{
			UnstructuredMessage: "Bill no. 3139 for gardening work and disposal of waste material",
		},
	}
	if err := data.Validate(); err != nil {
		fmt.Println("Unexpected error:", err)
	}

	doc := pdf.New()
	canvas := doc.NewPage(21.0*pdf.Cm, 10.5*pdf.Cm) // QR invoice size.
	if err := swissqr.DrawInvoiceWithScissors(canvas, data, "en"); err != nil {
		fmt.Println("Unexpected error:", err)
	}
	canvas.Close()

	if pdfFile, err := os.Create("example_gardening.pdf"); err != nil {
		fmt.Println("Unexpected error:", err)
	} else {
		defer pdfFile.Close()
		if err := doc.Encode(pdfFile); err != nil {
			fmt.Println("Unexpected error:", err)
		}
	}

	fmt.Println("PDF file successfully created.")

}
Output:

PDF file successfully created.
Example (Riferimento)

Fourth example in Appendix A of the Swiss QR standard.

package main

import (
	"fmt"
	"github.com/krepost/gopdf/pdf"
	"github.com/krepost/structref"
	"github.com/krepost/swissqr"
	"os"
)

func main() {
	data := swissqr.Payload{
		Account: swissqr.NewIBANOrDie("CH58 0079 1123 0008 8901 2"),
		Creditor: swissqr.Entity{
			Name: "Robert Schneider AG",
			Address: swissqr.StructuredAddress{
				StreetName:     "Rue du Lac",
				BuildingNumber: "1268",
				PostCode:       "2501",
				TownName:       "Biel",
			},
			CountryCode: "CH",
		},
		CurrencyAmount: swissqr.PaymentAmount{
			Amount:   199.95,
			Currency: swissqr.CHF,
		},
		UltimateDebtor: swissqr.Entity{
			Name: "Pia-Maria Rutschmann-Schnyder",
			Address: swissqr.StructuredAddress{
				StreetName:     "Grosse Marktgasse",
				BuildingNumber: "28",
				PostCode:       "9400",
				TownName:       "Rorschach",
			},
			CountryCode: "CH",
		},
		Reference: swissqr.PaymentReference{
			Number: structref.NewCreditorReferenceOrDie("RF18 5390 0754 7034"),
		},
	}
	if err := data.Validate(); err != nil {
		fmt.Println("Unexpected error:", err)
	}

	doc := pdf.New()
	canvas := doc.NewPage(21.0*pdf.Cm, 10.5*pdf.Cm) // QR invoice size.
	if err := swissqr.DrawInvoiceWithScissors(canvas, data, "it"); err != nil {
		fmt.Println("Unexpected error:", err)
	}
	canvas.Close()

	if pdfFile, err := os.Create("example_riferimento.pdf"); err != nil {
		fmt.Println("Unexpected error:", err)
	} else {
		defer pdfFile.Close()
		if err := doc.Encode(pdfFile); err != nil {
			fmt.Println("Unexpected error:", err)
		}
	}

	fmt.Println("PDF file successfully created.")

}
Output:

PDF file successfully created.
Example (SchneiderOrder)

Second example in Appendix A of the Swiss QR standard.

package main

import (
	"fmt"
	"github.com/krepost/gopdf/pdf"
	"github.com/krepost/structref"
	"github.com/krepost/swissqr"
	"os"
	"time"
)

func main() {
	data := swissqr.Payload{
		Account: swissqr.NewIBANOrDie("CH4431999123000889012"),
		Creditor: swissqr.Entity{
			Name: "Robert Schneider AG",
			Address: swissqr.StructuredAddress{
				StreetName:     "Rue du Lac",
				BuildingNumber: "1268",
				PostCode:       "2501",
				TownName:       "Biel",
			},
			CountryCode: "CH",
		},
		CurrencyAmount: swissqr.PaymentAmount{
			Amount:   1949.75,
			Currency: swissqr.CHF,
		},
		UltimateDebtor: swissqr.Entity{
			Name: "Pia-Maria Rutschmann-Schnyder",
			Address: swissqr.StructuredAddress{
				StreetName:     "Grosse Marktgasse",
				BuildingNumber: "28",
				PostCode:       "9400",
				TownName:       "Rorschach",
			},
			CountryCode: "CH",
		},
		Reference: swissqr.PaymentReference{
			Number: structref.NewReferenceNumberOrDie("21 00000 00003 13947 14300 09017"),
		},
		AdditionalInformation: swissqr.PaymentInformation{
			UnstructuredMessage: "Order dated 18.06.2020",
			StructuredMessage: swissqr.BillInformation{
				InvoiceNumber:     "10201409",
				InvoiceDate:       swissqr.OneDate(2019, time.May, 12),
				CustomerReference: "140.000-53",
				VATNumber:         "106017086",
				VATDates:          swissqr.OneDate(2018, time.May, 8),
				VATRates: swissqr.TaxRates{
					swissqr.TaxRate{RatePercent: 7.7},
				},
				Conditions: swissqr.PaymentConditions{
					swissqr.PaymentCondition{DiscountPercent: 2, NumberOfDays: 10},
					swissqr.PaymentCondition{DiscountPercent: 0, NumberOfDays: 30},
				},
			},
		},
		AlternativeProcedureParameters: swissqr.AlternativeProcedures{
			swissqr.AlternativeProcedure{"Name AV1", "UV;UltraPay005;12345"},
			swissqr.AlternativeProcedure{"Name AV2", "XY;XYService;54321"},
		},
	}
	if err := data.Validate(); err != nil {
		fmt.Println("Unexpected error:", err)
	}

	doc := pdf.New()
	canvas := doc.NewPage(21.0*pdf.Cm, 29.7*pdf.Cm)
	if err := swissqr.DrawInvoiceWithBorder(canvas, data, "en"); err != nil {
		fmt.Println("Unexpected error:", err)
	}
	canvas.Close()

	if pdfFile, err := os.Create("example_order.pdf"); err != nil {
		fmt.Println("Unexpected error:", err)
	} else {
		defer pdfFile.Close()
		if err := doc.Encode(pdfFile); err != nil {
			fmt.Println("Unexpected error:", err)
		}
	}

	fmt.Println("PDF file successfully created.")

}
Output:

PDF file successfully created.

Index

Examples

Constants

View Source
const (
	CHF = "CHF"
	EUR = "EUR"
)

Variables

This section is empty.

Functions

func BorderText

func BorderText(language string) (string, error)

BorderText returns the text that is to be printed above the QR invoice.

func CreateQR

func CreateQR(data Payload) (image.Image, error)

CreateQR creates a QR code image from the given payload data. The image is 1086×1086 pixels, which amounts to 46×46 mm at 600 dpi, and includes the Swiss cross as required by the Swiss payment QR code standard.

func DrawInvoice

func DrawInvoice(canvas *pdf.Canvas, data Payload, language string) error

DrawInvoice draws a standard Swiss QR Invoice on the given canvas, starting at the current position as the lower left corner of the invoice. The invoice is localized to the given language. The size of the invoice is “DIN A6/5 Querformat”, i.e., 210 mm wide and 105 mm high. It is the responsibility of the caller to make sure that the invoice area in the PDF is clear.

func DrawInvoiceWithBorder

func DrawInvoiceWithBorder(canvas *pdf.Canvas, data Payload, language string) error

DrawInvoiceWithBorder draws a standard Swiss QR Invoice on the given canvas, starting at the current position as the lower left corner of the invoice. The invoice is localized to the given language. The size of the invoice is “DIN A6/5 Querformat”, i.e., 210 mm wide and 105 mm high. A border is drawn around the invoice and a text indicating that the invoice part is to be removed from the rest of the document is printed above the border. It is the responsibility of the caller to make sure that the invoice area in the PDF is clear.

func DrawInvoiceWithScissors

func DrawInvoiceWithScissors(canvas *pdf.Canvas, data Payload, language string) error

DrawInvoiceWithScissors draws a standard Swiss QR Invoice on the given canvas, starting at the current position as the lower left corner of the invoice. The invoice is localized to the given language. The size of the invoice is “DIN A6/5 Querformat”, i.e., 210 mm wide and 105 mm high. A line separating the receipt part and the payment part is drawn, and a scissor symbol indicating that the receipt part is to be removed is added next to the line. It is the responsibility of the caller to make sure that the invoice area in the PDF is clear.

func OneDate

func OneDate(year int, month time.Month, day int) dates

OneDate is a helper function creating a date.

func StartAndEndDate

func StartAndEndDate(
	startYear int, startMonth time.Month, startDay int,
	endYear int, endMonth time.Month, endDay int) dates

StartAndEndDate is a helper function creating a date interval.

func ValidateCharacterSet

func ValidateCharacterSet(s string) error

ValidateCharacterSet validates that s only contains characters that are allowed according to the Swiss Implementation Guidelines for Customer-Bank Messages Credit Transfer.

Types

type AccountNumber

type AccountNumber struct {
	IBAN *iban.IBAN
}

Account contains an IBAN or QR-IBAN.

func NewIBANOrDie

func NewIBANOrDie(s string) AccountNumber

NewIBANOrDie is a helper function to set the IBAN field in Payload. Useful when initializing a Payload struct programmatically.

func (AccountNumber) Serialize

func (a AccountNumber) Serialize(w io.Writer) error

Serialize serializes an account record. It is assumed that the record is valid.

func (AccountNumber) Validate

func (a AccountNumber) Validate() error

Validate validates an Account

type AlternativeProcedure

type AlternativeProcedure struct {
	// Label is shown in bold on the QR invoice.
	Label string

	// Procedure describes the alternative payment procedure.
	Procedure string
}

AlternativeProcedure defines an alternateive payment procedure.

type AlternativeProcedures

type AlternativeProcedures []AlternativeProcedure

AlternativeProcedures is a list of alternative payment procedures.

func (AlternativeProcedures) Serialize

func (vec AlternativeProcedures) Serialize(w io.Writer) error

Serialize serializes alternative procedure parameters. It is assumed that the parameters are valid.

func (AlternativeProcedures) Validate

func (vec AlternativeProcedures) Validate() error

Validate validates alternative payment procedures.

type AmountSectionData

type AmountSectionData struct {
	CurrencyHeading string
	CurrencyValue   string
	AmountHeading   string
	AmountValue     string
}

AmountSectionData represents the payment amount on the payment slip.

func AmountSection

func AmountSection(p Payload, language string) (AmountSectionData, error)

AmountSection returns the payment amount.

type BillInformation

type BillInformation struct {
	// InvoiceNumber is free text.
	InvoiceNumber string

	// InvoiceDate contains one date.
	InvoiceDate dates

	// CustomerReference is free text.
	CustomerReference string

	// VATNumber contains the UID with “CHE” prefix, without separators,
	// and without the  MWST/TVA/IVA/VAT suffix.
	VATNumber string

	// VATDates contains either the date of service
	// or the start and end date of service.
	VATDates dates

	// VATRates contains either the VAT rate for the invoice or a list
	// of rates and amounts.
	VATRates TaxRates

	// VATImportTaxRates contains a list of rates and amounts applied
	// during import.
	VATImportTaxRates TaxRates

	// Conditions contains a list of payment conditions.
	Conditions PaymentConditions
}

BillInformation contains structured bill information that can be added to the Swiss QR invoice. All fields are optional.

func (BillInformation) ToString

func (bi BillInformation) ToString() string

ToString converts a given BillInformation to a string that can be added to a Swiss QR invoice. It is assumed that the parameters are valid.

func (BillInformation) Validate

func (bi BillInformation) Validate() error

Validate valides a given BillInformation.

type CombinedAddress

type CombinedAddress struct {
	// Optional street name and building number, or PO Box.
	// Maximum 70 characters allowed.
	AddressLine1 string

	// Mandatory field containing postal code and town.
	// Maximum 70 characters allowed.
	AddressLine2 string
}

CombinedAdress represents an unstructured address.

func (CombinedAddress) Serialize

func (ca CombinedAddress) Serialize(name string, w io.Writer) error

Serialize serializes a combined address record. It is assumed that the record is valid.

func (CombinedAddress) Validate

func (ca CombinedAddress) Validate() error

Validate validates a CombinedAddress.

type Entity

type Entity struct {
	// Mandatory field. Contains first name (optional) and last name
	// or company name.
	Name string

	// Mandatory field. Must contain either a CombinedAddress
	// or a StructuredAddress.
	Address qrAddress

	// Mandatory two-letter country code according to ISO 3166-1.
	CountryCode string
}

Entity can represent a creditor or a debtor.

func (Entity) Serialize

func (e Entity) Serialize(w io.Writer) error

Serialize serializes an entity record. It is assumed that the record is valid.

func (Entity) ToLines

func (e Entity) ToLines() ([]string, error)

ToLines converts an Entity to a set of lines suitable for display on a payment slip. It is assumed that the Entity is valid.

func (Entity) Validate

func (e Entity) Validate() error

Validate validates an Entity

type Paragraph

type Paragraph struct {
	Heading string
	Lines   []string
}

Paragraph represents a header followed by text lines on the payment slip.

func InformationSection

func InformationSection(p Payload, language string,
	width float64, info int) ([]Paragraph, error)

InformationSection returns a slice of paragraphs to be rendered on the payment slip. The value of info (paymentPartInformation or receiptPartInformation) determines if information for the payment part or receipt part should be returned.

type Payload

type Payload struct {
	// IBAN or QR-IBAN of the creditor, according to ISO 13616.
	Account AccountNumber

	// The creditor. Mandatory data group.
	Creditor Entity

	// Information about the ultimate creditor. For future use.
	UltimateCreditor Entity

	// The payment amount in a given currency. Mandatory data group.
	CurrencyAmount PaymentAmount

	// The ultimate debtor. Optional data group.
	UltimateDebtor Entity

	// Reference contains an optional structured payment reference number.
	Reference PaymentReference

	// AdditionalInformation can be used to send additional
	// information to the biller. Optional data group.
	AdditionalInformation PaymentInformation

	// AlternativeProcedureParameters contains a maximum of two
	// entries describing the parameter character chain of the
	// alternative scheme according to the syntax definition in
	// the section on “Alternative procedure” in the Swiss QR standard.
	AlternativeProcedureParameters AlternativeProcedures
}

Payload contains all information that can be encoded in the Swiss QR Code for invoices.

func (Payload) Serialize

func (p Payload) Serialize(w io.Writer) error

Serialize serializes the payload data to w in a form that can be encoded in a Swiss QR Code. The payload is validated before serialization.

func (Payload) Validate

func (p Payload) Validate() error

Validate validates the payload and returns nil on success.

type PaymentAmount

type PaymentAmount struct {
	// Optional payment amount.
	Amount float64

	// Mandatory payment currency. Only "CHF" and "EUR" are permitted.
	Currency string
}

PaymentAmount contains the amount to be paid.

func (PaymentAmount) Serialize

func (pa PaymentAmount) Serialize(w io.Writer) error

Serialize serializes a payment amount record. It is assumed that the record is valid.

func (PaymentAmount) Validate

func (pa PaymentAmount) Validate() error

Validate validates a PaymentAmount.

type PaymentCondition

type PaymentCondition struct {
	DiscountPercent float64
	NumberOfDays    int
}

PaymentCondition represents a discount applied if the invoice is paid within a specified number of days. For a payment condition of the form “payable within n days”, set DiscountPercent to 0 and NumberOfDays to n.

type PaymentConditions

type PaymentConditions []PaymentCondition

PaymentConditions is a list of payment conditions.

func (PaymentConditions) ToString

func (c PaymentConditions) ToString() string

ToString converts a list of payment conditions to a string that can be added to a structured bill information.

type PaymentInformation

type PaymentInformation struct {
	// UnstructuredMessage can be used to indicate the payment purpose
	// or for additional tectual information about payments with a
	// structured reference. Optional field.
	UnstructuredMessage string

	// StructuredInformation contains coded information for automated
	// booking of the payment. Optional field.
	StructuredMessage BillInformation
}

PaymentInformation includes additional unstructured or coded information about the payment. The two fields combined may contain at most 140 characters.

func (PaymentInformation) Serialize

func (pi PaymentInformation) Serialize(w io.Writer) error

Serialize serializes additional payment information record. It is assumed that the record is valid.

func (PaymentInformation) Validate

func (pi PaymentInformation) Validate() error

Validate validates additional payment information.

type PaymentReference

type PaymentReference struct {
	Number structref.Printer
}

PaymentReference contains either a Swiss ESR reference number, or a structured creditor reference according to ISO 11649, or nil.

func (PaymentReference) Serialize

func (pr PaymentReference) Serialize(w io.Writer) error

Serialize serializes a payment reference record. It is assumed that the record is valid.

func (PaymentReference) Validate

func (r PaymentReference) Validate() error

Validate validates a payment reference.

type StructuredAddress

type StructuredAddress struct {
	// Optional. May not include house or building number.
	// Maximum 70 characters allowed.
	StreetName string

	// Optional. Maximum 16 characters allowed.
	BuildingNumber string

	// Mandatory. Is always to be entered without a country code.
	// Maximum 16 characters allowed.
	PostCode string

	// Mandatory. Maximum 35 characters allowed.
	TownName string
}

StructuredAddress represents an address with structured fields.

func (StructuredAddress) Serialize

func (sa StructuredAddress) Serialize(name string, w io.Writer) error

Serialize serializes a structured address record. It is assumed that the record is valid.

func (StructuredAddress) Validate

func (sa StructuredAddress) Validate() error

Validate validates a StructuredAddress.

type TaxRate

type TaxRate struct {
	RatePercent float64
	Amount      float64
}

TaxRate represents a tax rate with an optional amount. For an amount applicable to the entire invoice amount, set Amount to zero.

type TaxRates

type TaxRates []TaxRate

TaxRates is a list of tax rates.

func (TaxRates) ToString

func (t TaxRates) ToString() string

ToString converts a list of tax rates to a string that can be added to a structured bill information.

type TitleSectionData

type TitleSectionData struct {
	PaymentPart string
	Receipt     string
}

TitleSectionData represents the title sections on the payment slip.

func TitleSection

func TitleSection(p Payload, language string) (TitleSectionData, error)

TitleSection returns the titles of the receipt and payment parts.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL