1 package SL::Helper::QrBill;
10 cross_file => 'image/CH-Kreuz_7mm.png',
11 out_file => 'out.png',
17 my $self = bless {}, $class;
19 $self->_init_check(@_);
27 my ($biller_information, $biller_data, $payment_information, $invoice_recipient_data, $ref_nr_data) = @_;
29 $self->{data}{header} = [
34 $self->{data}{biller_information} = [
35 $biller_information->{iban},
37 $self->{data}{biller_data} = [
38 $biller_data->{address_type},
39 $biller_data->{company},
40 $biller_data->{address_row1},
41 $biller_data->{address_row2},
44 $biller_data->{countrycode},
46 $self->{data}{payment_information} = [
47 $payment_information->{amount},
48 $payment_information->{currency},
50 $self->{data}{invoice_recipient_data} = [
51 $invoice_recipient_data->{address_type},
52 $invoice_recipient_data->{name},
53 $invoice_recipient_data->{address_row1},
54 $invoice_recipient_data->{address_row2},
57 $invoice_recipient_data->{countrycode},
59 $self->{data}{ref_nr_data} = [
61 $ref_nr_data->{ref_number},
63 $self->{data}{additional_information} = [
65 'EPD', # End Payment Data
71 my ($biller_information, $biller_data, $payment_information, $invoice_recipient_data, $ref_nr_data) = @_;
74 my ($group, $href, $elem, $regex) = @_;
75 defined $href->{$elem} && $href->{$elem} =~ $regex
76 or die "field '$elem' in group '$group' not valid", "\n";
79 my $group = 'biller information';
80 $check_re->($group, $biller_information, 'iban', qr{^(?:CH|LI)[0-9a-zA-Z]{19}$});
82 $group = 'biller data';
83 $check_re->($group, $biller_data, 'address_type', qr{^[KS]$});
84 $check_re->($group, $biller_data, 'company', qr{^.{1,70}$});
85 $check_re->($group, $biller_data, 'address_row1', qr{^.{0,70}$});
86 $check_re->($group, $biller_data, 'address_row2', qr{^.{0,70}$});
87 $check_re->($group, $biller_data, 'countrycode', qr{^[A-Z]{2}$});
89 $group = 'payment information';
90 $check_re->($group, $payment_information, 'amount', qr{^(?:(?:0|[1-9][0-9]{0,8})\.[0-9]{2})?$});
91 $check_re->($group, $payment_information, 'currency', qr{^(?:CHF|EUR)$});
93 $group = 'invoice recipient data';
94 $check_re->($group, $invoice_recipient_data, 'address_type', qr{^[KS]$});
95 $check_re->($group, $invoice_recipient_data, 'name', qr{^.{1,70}$});
96 $check_re->($group, $invoice_recipient_data, 'address_row1', qr{^.{0,70}$});
97 $check_re->($group, $invoice_recipient_data, 'address_row2', qr{^.{0,70}$});
98 $check_re->($group, $invoice_recipient_data, 'countrycode', qr{^[A-Z]{2}$});
100 $group = 'reference number data';
101 my %ref_nr_regexes = (
105 $check_re->($group, $ref_nr_data, 'type', qr{^(?:QRR|SCOR|NON)$});
106 $check_re->($group, $ref_nr_data, 'ref_number', $ref_nr_regexes{$ref_nr_data->{type}});
111 my $out_file = defined $_[0] ? $_[0] : $Config{out_file};
113 $self->{qrcode} = $self->_qrcode();
114 $self->{cross} = $self->_cross();
115 $self->{img} = $self->_plot();
118 $self->_write($out_file);
124 return Imager::QRCode->new(
134 my $cross = Imager->new();
135 $cross->read(file => $Config{cross_file}) or die $cross->errstr, "\n";
137 return $cross->scale(xpixels => 35, ypixels => 35, qtype => 'mixing');
144 @{$self->{data}{header}},
145 @{$self->{data}{biller_information}},
146 @{$self->{data}{biller_data}},
147 ('') x 7, # for future use
148 @{$self->{data}{payment_information}},
149 @{$self->{data}{invoice_recipient_data}},
150 @{$self->{data}{ref_nr_data}},
151 @{$self->{data}{additional_information}},
161 my $text = join "\015\012", @data;
163 return $self->{qrcode}->plot($text);
170 src => $self->{cross},
171 left => ($self->{img}->getwidth / 2) - ($self->{cross}->getwidth / 2),
172 top => ($self->{img}->getheight / 2) - ($self->{cross}->getheight / 2),
180 $self->{img}->write(file => $out_file) or die $self->{img}->errstr, "\n";
191 SL::Helper::QrBill - Helper methods for generating Swiss QR-Code
195 use SL::Helper::QrBill;
198 my $qr_image = SL::Helper::QrBill->new(
199 \%biller_information,
201 \%payment_information,
202 \%invoice_recipient_data,
205 $qr_image->generate($outfile);
207 local $_ = $@; chomp; my $error = $_;
208 $::form->error($::locale->text('QR-Image generation failed: ' . $error));
213 This module generates the Swiss QR-Code with data provided to the constructor.
219 Creates a new object. Expects five references to hashes as arguments.
221 The hashes are structured as follows:
225 =item C<%biller_information>
233 Fixed length; 21 alphanumerical characters, only IBANs with CH- or LI-
238 =item C<%biller_data>
240 Fields: address_type, company, address_row1, address_row2 and countrycode.
244 =item C<address_type>
246 Fixed length; 1-digit, alphanumerical. 'K' implemented only.
250 Maximum of 70 characters, name (surname allowable) or company.
252 =item C<address_row1>
254 Maximum of 70 characters, street/nr.
256 =item C<address_row2>
258 Maximum of 70 characters, postal code/place.
262 2-digit country code according to ISO 3166-1.
266 =item C<%payment_information>
268 Fields: amount and currency.
274 Decimal, no leading zeroes, maximum of 12 digits (inclusive decimal
275 separator and places). Only dot as decimal separator is permitted.
283 =item C<%invoice_recipient_data>
285 Fields: address_type, name, address_row1, address_row2 and countrycode.
289 =item C<address_type>
291 Fixed length; 1-digit, alphanumerical. 'K' implemented only.
295 Maximum of 70 characters, name (surname allowable) or company.
297 =item C<address_row1>
299 Maximum of 70 characters, street/nr.
301 =item C<address_row2>
303 Maximum of 70 characters, postal code/place.
307 2-digit country code according to ISO 3166-1.
311 =item C<%ref_nr_data>
313 Fields: type and ref_number.
319 Maximum of 4 characters, alphanumerical. QRR/SCOR/NON.
323 QR-Reference: 27 characters, numerical; without Reference: empty.
331 Generates the QR-Code image. Accepts filename of image as argument.
332 Defaults to C<out.png>.
336 Steven Schubiger E<lt>stsc@refcnt.orgE<gt>