Overview

Namespaces

  • Defr
    • QRPlatba

Classes

  • Defr\QRPlatba\QRPlatba

Exceptions

  • Defr\QRPlatba\QRPlatbaException
  • Overview
  • Namespace
  • Class
  1: <?php
  2: 
  3: /*
  4:  * This file is part of the library "QRPlatba".
  5:  *
  6:  * (c) Dennis Fridrich <fridrich.dennis@gmail.com>
  7:  *
  8:  * For the full copyright and license information,
  9:  * please view LICENSE.
 10:  */
 11: 
 12: namespace Defr\QRPlatba;
 13: 
 14: use Endroid\QrCode\QrCode;
 15: 
 16: /**
 17:  * Knihovna pro generování QR plateb v PHP.
 18:  *
 19:  * @see https://raw.githubusercontent.com/snoblucha/QRPlatba/master/QRPlatba.php
 20:  */
 21: class QRPlatba
 22: {
 23:     /**
 24:      * Verze QR formátu QR Platby.
 25:      */
 26:     const VERSION = '1.0';
 27: 
 28:     /**
 29:      * @var array
 30:      */
 31:     private static $currencies = [
 32:         'AED', 'AFN', 'ALL', 'AMD', 'ANG', 'AOA', 'ARS', 'AUD', 'AWG', 'AZN',
 33:         'BAM', 'BBD', 'BDT', 'BGN', 'BHD', 'BIF', 'BMD', 'BND', 'BOB', 'BRL',
 34:         'BSD', 'BTN', 'BWP', 'BYN', 'BZD', 'CAD', 'CDF', 'CHF', 'CLP', 'CNY',
 35:         'COP', 'CRC', 'CUC', 'CUP', 'CVE', 'CZK', 'DJF', 'DKK', 'DOP', 'DZD',
 36:         'EGP', 'ERN', 'ETB', 'EUR', 'FJD', 'FKP', 'GBP', 'GEL', 'GGP', 'GHS',
 37:         'GIP', 'GMD', 'GNF', 'GTQ', 'GYD', 'HKD', 'HNL', 'HRK', 'HTG', 'HUF',
 38:         'IDR', 'ILS', 'IMP', 'INR', 'IQD', 'IRR', 'ISK', 'JEP', 'JMD', 'JOD',
 39:         'JPY', 'KES', 'KGS', 'KHR', 'KMF', 'KPW', 'KRW', 'KWD', 'KYD', 'KZT',
 40:         'LAK', 'LBP', 'LKR', 'LRD', 'LSL', 'LYD', 'MAD', 'MDL', 'MGA', 'MKD',
 41:         'MMK', 'MNT', 'MOP', 'MRO', 'MUR', 'MVR', 'MWK', 'MXN', 'MYR', 'MZN',
 42:         'NAD', 'NGN', 'NIO', 'NOK', 'NPR', 'NZD', 'OMR', 'PAB', 'PEN', 'PGK',
 43:         'PHP', 'PKR', 'PLN', 'PYG', 'QAR', 'RON', 'RSD', 'RUB', 'RWF', 'SAR',
 44:         'SBD', 'SCR', 'SDG', 'SEK', 'SGD', 'SHP', 'SLL', 'SOS', 'SPL', 'SRD',
 45:         'STD', 'SVC', 'SYP', 'SZL', 'THB', 'TJS', 'TMT', 'TND', 'TOP', 'TRY',
 46:         'TTD', 'TVD', 'TWD', 'TZS', 'UAH', 'UGX', 'USD', 'UYU', 'UZS', 'VEF',
 47:         'VND', 'VUV', 'WST', 'XAF', 'XCD', 'XDR', 'XOF', 'XPF', 'YER', 'ZAR',
 48:         'ZMW', 'ZWD',
 49:     ];
 50: 
 51:     /**
 52:      * @var array
 53:      */
 54:     private $keys = [
 55:         'ACC' => null,
 56:         // Max. 46 - znaků IBAN, BIC Identifikace protistrany !povinny
 57:         'ALT-ACC' => null,
 58:         // Max. 93 - znaků Seznam alternativnich uctu. odddeleny carkou,
 59:         'AM' => null,
 60:         //Max. 10 znaků - Desetinné číslo Výše částky platby.
 61:         'CC' => 'CZK',
 62:         // Právě 3 znaky - Měna platby.
 63:         'DT' => null,
 64:         // Právě 8 znaků - Datum splatnosti YYYYMMDD.
 65:         'MSG' => null,
 66:         // Max. 60 znaků - Zpráva pro příjemce.
 67:         'X-VS' => null,
 68:         // Max. 10 znaků - Celé číslo - Variabilní symbol
 69:         'X-SS' => null,
 70:         // Max. 10 znaků - Celé číslo - Specifický symbol
 71:         'X-KS' => null,
 72:         // Max. 10 znaků - Celé číslo - Konstantní symbol
 73:         'RF' => null,
 74:         // Max. 16 znaků - Identifikátor platby pro příjemce.
 75:         'RN' => null,
 76:         // Max. 35 znaků - Jméno příjemce.
 77:         'PT' => null,
 78:         // Právě 3 znaky - Typ platby.
 79:         'CRC32' => null,
 80:         // Právě 8 znaků - Kontrolní součet - HEX.
 81:         'NT' => null,
 82:         // Právě 1 znak P|E - Identifikace kanálu pro zaslání notifikace výstavci platby.
 83:         'NTA' => null,
 84:         //Max. 320 znaků - Telefonní číslo v mezinárodním nebo lokálním vyjádření nebo E-mailová adresa
 85:         'X-PER' => null,
 86:         // Max. 2 znaky -  Celé číslo - Počet dní, po které se má provádět pokus o opětovné provedení neúspěšné platby
 87:         'X-ID' => null,
 88:         // Max. 20 znaků. -  Identifikátor platby na straně příkazce. Jedná se o interní ID, jehož použití a interpretace závisí na bance příkazce.
 89:         'X-URL' => null,
 90:         // Max. 140 znaků. -  URL, které je možno využít pro vlastní potřebu
 91:     ];
 92: 
 93:     /**
 94:      * Kontruktor nové platby.
 95:      *
 96:      * @param null $account
 97:      * @param null $amount
 98:      * @param null $variable
 99:      * @param null $currency
100:      * @throws \InvalidArgumentException
101:      */
102:     public function __construct($account = null, $amount = null, $variable = null, $currency = null)
103:     {
104:         if ($account) {
105:             $this->setAccount($account);
106:         }
107:         if ($amount) {
108:             $this->setAmount($amount);
109:         }
110:         if ($variable) {
111:             $this->setVariableSymbol($variable);
112:         }
113:         if ($currency) {
114:             $this->setCurrency($currency);
115:         }
116:     }
117: 
118:     /**
119:      * Statický konstruktor nové platby.
120:      *
121:      * @param null $account
122:      * @param null $amount
123:      * @param null $variable
124:      *
125:      * @return QRPlatba
126:      * @throws \InvalidArgumentException
127:      */
128:     public static function create($account = null, $amount = null, $variable = null)
129:     {
130:         return new self($account, $amount, $variable);
131:     }
132: 
133:     /**
134:      * Nastavení čísla účtu ve formátu 12-3456789012/0100.
135:      *
136:      * @param $account
137:      *
138:      * @return $this
139:      */
140:     public function setAccount($account)
141:     {
142:         $this->keys['ACC'] = self::accountToIban($account);
143: 
144:         return $this;
145:     }
146: 
147:     /**
148:      * Nastavení částky.
149:      *
150:      * @param $amount
151:      *
152:      * @return $this
153:      */
154:     public function setAmount($amount)
155:     {
156:         $this->keys['AM'] = sprintf('%.2f', $amount);
157: 
158:         return $this;
159:     }
160: 
161:     /**
162:      * Nastavení variabilního symbolu.
163:      *
164:      * @param $vs
165:      *
166:      * @return $this
167:      */
168:     public function setVariableSymbol($vs)
169:     {
170:         $this->keys['X-VS'] = $vs;
171: 
172:         return $this;
173:     }
174: 
175:     /**
176:      * Nastavení konstatního symbolu.
177:      *
178:      * @param $cs
179:      *
180:      * @return $this
181:      */
182:     public function setConstantSymbol($cs)
183:     {
184:         $this->keys['X-CS'] = $cs;
185: 
186:         return $this;
187:     }
188: 
189:     /**
190:      * Nastavení specifického symbolu.
191:      *
192:      * @param $ss
193:      *
194:      * @throws QRPlatbaException
195:      *
196:      * @return $this
197:      */
198:     public function setSpecificSymbol($ss)
199:     {
200:         if (mb_strlen($ss) > 10) {
201:             throw new QRPlatbaException('Specific symbol is higher than 10 chars');
202:         }
203:         $this->keys['X-SS'] = $ss;
204: 
205:         return $this;
206:     }
207: 
208:     /**
209:      * Nastavení zprávy pro příjemce. Z řetězce bude odstraněna diaktirika.
210:      *
211:      * @param $msg
212:      *
213:      * @return $this
214:      */
215:     public function setMessage($msg)
216:     {
217:         $this->keys['MSG'] = mb_substr($this->stripDiacritics($msg), 0, 60);
218: 
219:         return $this;
220:     }
221: 
222:     /**
223:      * Nastavení jména příjemce. Z řetězce bude odstraněna diaktirika.
224:      *
225:      * @param $name
226:      *
227:      * @return $this
228:      */
229:     public function setRecipientName($name)
230:     {
231:         $this->keys['RN'] = mb_substr($this->stripDiacritics($name), 0, 35);
232: 
233:         return $this;
234:     }
235: 
236:     /**
237:      * Nastavení data úhrady.
238:      *
239:      * @param \DateTime $date
240:      *
241:      * @return $this
242:      */
243:     public function setDueDate(\DateTime $date)
244:     {
245:         $this->keys['DT'] = $date->format('Ymd');
246: 
247:         return $this;
248:     }
249: 
250:     /**
251:      * @param $cc
252:      *
253:      * @return $this
254:      * @throws \InvalidArgumentException
255:      */
256:     public function setCurrency($cc)
257:     {
258:         if (!in_array($cc, self::$currencies, true)) {
259:             throw new \InvalidArgumentException(sprintf('Currency %s is not supported.', $cc));
260:         }
261: 
262:         $this->keys['CC'] = $cc;
263: 
264:         return $this;
265:     }
266: 
267:     /**
268:      * Metoda vrátí QR Platbu jako textový řetězec.
269:      *
270:      * @return string
271:      */
272:     public function __toString()
273:     {
274:         $chunks = ['SPD', self::VERSION];
275:         foreach ($this->keys as $key => $value) {
276:             if (null === $value) {
277:                 continue;
278:             }
279:             $chunks[] = $key.':'.$value;
280:         }
281: 
282:         return implode('*', $chunks);
283:     }
284: 
285:     /**
286:      * Metoda vrátí QR kód jako HTML tag, případně jako data-uri.
287:      *
288:      * @param bool $htmlTag
289:      * @param int  $size
290:      *
291:      * @return string
292:      */
293:     public function getQRCodeImage($htmlTag = true, $size = 300)
294:     {
295:         $qrCode = $this->getQRCodeInstance($size);
296:         $data = $qrCode->writeDataUri();
297: 
298:         return $htmlTag
299:             ? sprintf('<img src="%s" alt="QR Platba">', $data)
300:             : $data;
301:     }
302: 
303:     /**
304:      * Uložení QR kódu do souboru.
305:      *
306:      * @param null|string $filename File name of the QR Code
307:      * @param null|string $format Format of the file (png, jpeg, jpg, gif, wbmp)
308:      * @param int $size
309:      *
310:      * @return QRPlatba
311:      * @throws \Endroid\QrCode\Exception\UnsupportedExtensionException
312:      */
313:     public function saveQRCodeImage($filename = null, $format = 'png', $size = 300)
314:     {
315:         $qrCode = $this->getQRCodeInstance($size);
316:         $qrCode->setWriterByExtension($format);
317:         $qrCode->writeFile($filename);
318: 
319:         return $this;
320:     }
321: 
322:     /**
323:      * Instance třídy QrCode pro libovolné úpravy (barevnost, atd.).
324:      *
325:      * @param int $size
326:      *
327:      * @return QrCode
328:      */
329:     public function getQRCodeInstance($size = 300)
330:     {
331:         $qrCode = new QrCode();
332:         $qrCode
333:             ->setText((string) $this)
334:             ->setSize($size)
335:             ->setForegroundColor(['r' => 0, 'g' => 0, 'b' => 0, 'a' => 0])
336:             ->setBackgroundColor(['r' => 255, 'g' => 255, 'b' => 255, 'a' => 0]);
337: 
338:         return $qrCode;
339:     }
340: 
341:     /**
342:      * Převedení čísla účtu na formát IBAN.
343:      *
344:      * @param $accountNumber
345:      *
346:      * @return string
347:      */
348:     public static function accountToIban($accountNumber)
349:     {
350:         $accountNumber = explode('/', $accountNumber);
351:         $bank = $accountNumber[1];
352:         $pre = 0;
353:         $acc = 0;
354:         if (false === mb_strpos($accountNumber[0], '-')) {
355:             $acc = $accountNumber[0];
356:         } else {
357:             list($pre, $acc) = explode('-', $accountNumber[0]);
358:         }
359: 
360:         $accountPart = sprintf('%06d%010s', $pre, $acc);
361:         $iban = 'CZ00'.$bank.$accountPart;
362: 
363:         $alfa = 'A B C D E F G H I J K L M N O P Q R S T U V W X Y Z';
364:         $alfa = explode(' ', $alfa);
365:         $alfa_replace = [];
366:         for ($i = 1; $i < 27; ++$i) {
367:             $alfa_replace[] = $i + 9;
368:         }
369:         $controlegetal = str_replace(
370:             $alfa,
371:             $alfa_replace,
372:             mb_substr($iban, 4, mb_strlen($iban) - 4).mb_substr($iban, 0, 2).'00'
373:         );
374:         $controlegetal = 98 - (int) bcmod($controlegetal, 97);
375:         $iban = sprintf('CZ%02d%04d%06d%010s', $controlegetal, $bank, $pre, $acc);
376: 
377:         return $iban;
378:     }
379: 
380:     /**
381:      * Odstranění diaktitiky.
382:      *
383:      * @param $string
384:      *
385:      * @return mixed
386:      */
387:     private function stripDiacritics($string)
388:     {
389:         $string = str_replace(
390:             [
391:                 'ě', 'š', 'č', 'ř', 'ž', 'ý', 'á', 'í', 'é', 'ú', 'ů',
392:                 'ó', 'ť', 'ď', 'ľ', 'ň', 'ŕ', 'â', 'ă', 'ä', 'ĺ', 'ć',
393:                 'ç', 'ę', 'ë', 'î', 'ń', 'ô', 'ő', 'ö', 'ů', 'ű', 'ü',
394:                 'Ě', 'Š', 'Č', 'Ř', 'Ž', 'Ý', 'Á', 'Í', 'É', 'Ú', 'Ů',
395:                 'Ó', 'Ť', 'Ď', 'Ľ', 'Ň', 'Ä', 'Ć', 'Ë', 'Ö', 'Ü'
396:             ],
397:             [
398:                 'e', 's', 'c', 'r', 'z', 'y', 'a', 'i', 'e', 'u', 'u',
399:                 'o', 't', 'd', 'l', 'n', 'a', 'a', 'a', 'a', 'a', 'a',
400:                 'c', 'e', 'e', 'i', 'n', 'o', 'o', 'o', 'u', 'u', 'u',
401:                 'E', 'S', 'C', 'R', 'Z', 'Y', 'A', 'I', 'E', 'U', 'U',
402:                 'O', 'T', 'D', 'L', 'N', 'A', 'C', 'E', 'O', 'U'
403:             ],
404:             $string
405:         );
406: 
407:         return $string;
408:     }
409: }
410: 
API documentation generated by ApiGen