Completed
Push — master ( 428623...ba5c84 )
by Kittinan
01:18
created

PromptPay   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 92
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 11
c 1
b 0
f 1
lcom 1
cbo 3
dl 0
loc 92
ccs 43
cts 43
cp 1
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
B generatePayload() 0 25 4
A f() 0 3 1
A serialize() 0 3 1
A sanitizeTarget() 0 4 1
A formatTarget() 0 8 1
A formatAmount() 0 3 1
A crc16() 0 6 1
A generateQrCode() 0 11 1
1
<?php
2
3
namespace KS;
4
5
/**
6
 * Inspired and code logic from https://github.com/dtinth/promptpay-qr
7
 * More information https://www.blognone.com/node/95133
8
 */
9
class PromptPay {
10
11
  const ID_PAYLOAD_FORMAT = '00';
12
  const ID_POI_METHOD = '01';
13
  const ID_MERCHANT_INFORMATION_BOT = '29';
14
  const ID_TRANSACTION_CURRENCY = '53';
15
  const ID_TRANSACTION_AMOUNT = '54';
16
  const ID_COUNTRY_CODE = '58';
17
  const ID_CRC = '63';
18
  
19
  const PAYLOAD_FORMAT_EMV_QRCPS_MERCHANT_PRESENTED_MODE = '01';
20
  const POI_METHOD_STATIC = '11';
21
  const POI_METHOD_DYNAMIC = '12';
22
  const MERCHANT_INFORMATION_TEMPLATE_ID_GUID = '00';
23
  const BOT_ID_MERCHANT_PHONE_NUMBER = '01';
24
  const BOT_ID_MERCHANT_TAX_ID = '02';
25
  const GUID_PROMPTPAY = 'A000000677010111';
26
  const TRANSACTION_CURRENCY_THB = '764';
27
  const COUNTRY_CODE_TH = 'TH';
28
29 2
  public function generatePayload($target, $amount = null) {
30
31 2
    $target = $this->sanitizeTarget($target);
32
33 2
    $targetType = strlen($target) >= 13 ? self::BOT_ID_MERCHANT_TAX_ID : self::BOT_ID_MERCHANT_PHONE_NUMBER;
34
35
    $data = [
36 2
      $this->f(self::ID_PAYLOAD_FORMAT, self::PAYLOAD_FORMAT_EMV_QRCPS_MERCHANT_PRESENTED_MODE),
37 2
      $this->f(self::ID_POI_METHOD, $amount ? self::POI_METHOD_DYNAMIC : self::POI_METHOD_STATIC),
38 2
      $this->f(self::ID_MERCHANT_INFORMATION_BOT, $this->serialize([
39 2
          $this->f(self::MERCHANT_INFORMATION_TEMPLATE_ID_GUID, self::GUID_PROMPTPAY),
40 2
          $this->f($targetType, $this->formatTarget($target))
41
      ])),
42 2
      $this->f(self::ID_COUNTRY_CODE, self::COUNTRY_CODE_TH),
43 2
      $this->f(self::ID_TRANSACTION_CURRENCY, self::TRANSACTION_CURRENCY_THB),
44
    ];
45
    
46 2
    if ($amount !== null) {
47 2
      array_push($data, $this->f(self::ID_TRANSACTION_AMOUNT, $this->formatAmount($amount)));
48
    }
49
    
50 2
    $dataToCrc = $this->serialize($data) . self::ID_CRC . '04';
51 2
    array_push($data, $this->f(self::ID_CRC, $this->crc16($dataToCrc)));
52 2
    return $this->serialize($data);
53
  }
54
55 3
  public function f($id, $value) {
56 3
    return implode('', [$id, substr('00' . strlen($value), -2), $value]);
57
  }
58
  
59 2
  public function serialize($xs) {
60 2
    return implode('', $xs);
61
  }
62
  
63 3
  public function sanitizeTarget($str) {
64 3
    $str = preg_replace('/[^0-9]/', '', $str);
65 3
    return $str;
66
  }
67
68 3
  public function formatTarget($target) {
69
    
70 3
    $str = $this->sanitizeTarget($target);
71 3
    $str = preg_replace('/^0/', '66', $str);
72 3
    $str = '0000000000000' . $str;
73
74 3
    return substr($str, -13);
75
  }
76
77 3
  public function formatAmount($amount) {
78 3
    return number_format($amount, 2, '.', '');
79
  }
80
81 3
  public function crc16($data) {
82 3
    $crc16 = new \mermshaus\CRC\CRC16CCITT();
83 3
    $crc16->update($data);
84 3
    $checksum = $crc16->finish();
85 3
    return strtoupper(bin2hex($checksum));
86
  }
87
  
88 1
  public function generateQrCode($savePath, $target, $amount = null, $width = 256, $height = 256) {
89
90 1
    $payload = $this->generatePayload($target, $amount);
91
92 1
    $renderer = new \BaconQrCode\Renderer\Image\Png();
93 1
    $renderer->setHeight($width);
94 1
    $renderer->setWidth($height);
95 1
    $renderer->setMargin(0);
96 1
    $writer = new \BaconQrCode\Writer($renderer);
97 1
    $writer->writeFile($payload, $savePath);
98 1
  }
99
100
}
101