Skip to content

Commit a7a298f

Browse files
committedDec 12, 2021
first commit
0 parents  commit a7a298f

14 files changed

+948
-0
lines changed
 

‎.editorconfig

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
end_of_line = crlf
6+
indent_size = 4
7+
indent_style = space
8+
insert_final_newline = true
9+
tab_width = 8
10+
trim_trailing_whitespace = true
11+
12+
[*.md]
13+
trim_trailing_whitespace = false

‎.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
composer.lock
2+
vendor/
3+
.idea
4+
.phpunit.result.cache

‎LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2021 Ayman Alaiwah
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

‎README.md

+176
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
# Laravel ZATCA E-invoicing
2+
3+
4+
## Introduction
5+
Laravel package a helper to Generate the QR code and signed it for ZATCA E-invoicing
6+
7+
## Installation
8+
9+
To get the latest version of laravel-zatca on your project, require it from "composer":
10+
11+
$ composer require prgayman/laravel-zatca
12+
13+
Or you can add it directly in your composer.json file:
14+
15+
```json
16+
{
17+
"require": {
18+
"prgayman/laravel-zatca": "1.0.0"
19+
}
20+
}
21+
```
22+
23+
### Laravel
24+
25+
Register the provider directly in your app configuration file config/app.php `config/app.php`:
26+
27+
Laravel >= 5.5 provides package auto-discovery, thanks to rasmuscnielsen and luiztessadri who help to implement this feature in LaraFcm, the registration of the provider and the facades should not be necessary anymore.
28+
29+
```php
30+
'providers' => [
31+
Prgayman\Zatca\Zatca::class,
32+
]
33+
```
34+
35+
Add the facade aliases in the same file:
36+
37+
```php
38+
'aliases' => [
39+
40+
'Zatca' => Prgayman\Zatca\Facades\Zatca::class,
41+
42+
]
43+
```
44+
45+
### Lumen
46+
47+
Register the provider in your bootstrap app file `boostrap/app.php`
48+
49+
Add the following line in the "Register Service Providers" section at the bottom of the file.
50+
51+
```php
52+
$app->register(Prgayman\Zatca\Zatca::class);
53+
```
54+
55+
For facades, add the following lines in the section "Create The Application" .
56+
57+
```php
58+
class_alias(\Prgayman\Zatca\Facades\Zatca::class, 'Zatca');
59+
```
60+
61+
## Usage
62+
63+
### Generate Base64
64+
```php
65+
use Prgayman\Zatca\Facades\Zatca;
66+
67+
$base64 = Zatca::sellerName('Zatca')
68+
->vatRegistrationNumber("123456789123456")
69+
->timestamp("2021-12-01T14:00:09Z")
70+
->totalWithVat('100.00')
71+
->vatTotal('15.00')
72+
->toBase64();
73+
// Output
74+
// AQVaYXRjYQIPMTIzNDU2Nzg5MTIzNDU2AxQyMDIxLTEyLTAxVDE0OjAwOjA5WgQGMTAwLjAwBQUxNS4wMA==
75+
```
76+
77+
### Generate Plain
78+
```php
79+
use Prgayman\Zatca\Facades\Zatca;
80+
81+
$tlv = Zatca::sellerName('Zatca')
82+
->vatRegistrationNumber("123456789123456")
83+
->timestamp("2021-12-01T14:00:09Z")
84+
->totalWithVat('100.00')
85+
->vatTotal('15.00')
86+
->toTLV();
87+
```
88+
89+
### Render A QR Code Image
90+
```php
91+
use Prgayman\Zatca\Facades\Zatca;
92+
use Prgayman\Zatca\Utilis\QrCodeOptions; // Optional
93+
94+
// Optional
95+
$qrCodeOptions = new QrCodeOptions;
96+
97+
// Format (png,svg,eps)
98+
$qrCodeOptions->format("svg");
99+
100+
// Color
101+
$qrCodeOptions->color(255,0,0,1);
102+
103+
// Background Color
104+
$qrCodeOptions->backgroundColor(0,0,0);
105+
106+
// Size
107+
$qrCodeOptions->size(100);
108+
109+
// Margin
110+
$qrCodeOptions->margin(0);
111+
112+
// Style (square,dot,round)
113+
$qrCodeOptions->style('square',0.5);
114+
115+
// Eye (square,circle)
116+
$qrCodeOptions->eye('square');
117+
118+
$qrCode = Zatca::sellerName('Zatca')
119+
->vatRegistrationNumber("123456789123456")
120+
->timestamp("2021-12-01T14:00:09Z")
121+
->totalWithVat('100.00')
122+
->vatTotal('15.00')
123+
->toQrCode($qrCodeOptions);
124+
```
125+
126+
### Generate Base64 Using Function
127+
```php
128+
129+
$base64 = zatca()
130+
->sellerName('Zatca')
131+
->vatRegistrationNumber("123456789123456")
132+
->timestamp("2021-12-01T14:00:09Z")
133+
->totalWithVat('100.00')
134+
->vatTotal('15.00')
135+
->toBase64();
136+
// Output
137+
// AQVaYXRjYQIPMTIzNDU2Nzg5MTIzNDU2AxQyMDIxLTEyLTAxVDE0OjAwOjA5WgQGMTAwLjAwBQUxNS4wMA==
138+
```
139+
140+
### Generate Plain Using Function
141+
```php
142+
143+
$tlv = zatca()
144+
->sellerName('Zatca')
145+
->vatRegistrationNumber("123456789123456")
146+
->timestamp("2021-12-01T14:00:09Z")
147+
->totalWithVat('100.00')
148+
->vatTotal('15.00')
149+
->toTLV();
150+
```
151+
152+
### Render A QR Code Image Using Function
153+
```php
154+
$qrCode = zatca()
155+
->sellerName('Zatca')
156+
->vatRegistrationNumber("123456789123456")
157+
->timestamp("2021-12-01T14:00:09Z")
158+
->totalWithVat('100.00')
159+
->vatTotal('15.00')
160+
->toQrCode(
161+
qrCodeOptions()
162+
->format("svg")
163+
->color(255,0,0,1)
164+
->size(300)
165+
);
166+
```
167+
168+
## Testing
169+
170+
```bash
171+
composer test
172+
```
173+
174+
## Licence
175+
176+
This library is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT).

‎composer.json

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"name": "prgayman/laravel-zatca",
3+
"description": "Laravel package a helper to Generate the QR code and signed it for ZATCA E-invoicing",
4+
"version": "1.0.0",
5+
"keywords": [
6+
"prgayman",
7+
"laravel",
8+
"qrcode",
9+
"ZATCA",
10+
"e-invoicing"
11+
],
12+
"homepage": "https://github.com/prgayman/laravel-zatca",
13+
"type": "library",
14+
"license": "MIT",
15+
"authors": [
16+
{
17+
"name": "Ayman Alaiwah",
18+
"email": "aymanalaiwah.dev@gmail.com",
19+
"role": "Developer"
20+
}
21+
],
22+
"support": {
23+
"issues": "https://github.com/prgayman/laravel-zatca/issues",
24+
"source": "https://github.com/prgayman/laravel-zatca"
25+
},
26+
"minimum-stability": "stable",
27+
"require": {
28+
"php": ">=7.2|^8.0",
29+
"simplesoftwareio/simple-qrcode": "^4.2"
30+
},
31+
"autoload": {
32+
"psr-4": {
33+
"Prgayman\\Zatca\\": "src"
34+
},
35+
"files": [
36+
"src/helpers.php"
37+
]
38+
},
39+
"autoload-dev": {
40+
"psr-4": {
41+
"Prgayman\\Zatca\\Test\\": "tests/"
42+
}
43+
},
44+
"require-dev": {
45+
"phpunit/phpunit": "~8.0"
46+
},
47+
"extra": {
48+
"laravel": {
49+
"providers": [
50+
"Prgayman\\Zatca\\ZatcaServiceProvider"
51+
],
52+
"aliases": {
53+
"Zatca": "Prgayman\\Zatca\\Facades\\Zatca"
54+
}
55+
}
56+
},
57+
"scripts": {
58+
"test": "phpunit"
59+
}
60+
}

‎phpunit.xml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit bootstrap="vendor/autoload.php" backupGlobals="false" backupStaticAttributes="false" colors="true" verbose="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false">
3+
4+
<testsuites>
5+
<testsuite name="Test Suite">
6+
<directory>tests</directory>
7+
</testsuite>
8+
</testsuites>
9+
<filter>
10+
<whitelist>
11+
<directory suffix=".php">src/</directory>
12+
</whitelist>
13+
</filter>
14+
</phpunit>

‎src/Facades/Zatca.php

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Prgayman\Zatca\Facades;
4+
5+
use Illuminate\Support\Facades\Facade;
6+
7+
/**
8+
* @method static $this sellerName(string $value)
9+
* @method static $this vatRegistrationNumber(string $value)
10+
* @method static $this timestamp(string $value)
11+
* @method static $this totalWithVat(string $value)
12+
* @method static $this vatTotal(string $value)
13+
* @method static string toTLV()
14+
* @method static string toBase64()
15+
* @method static string toQrCode()
16+
*
17+
* @see \Prgayman\Zatca\Zatca
18+
*/
19+
20+
class Zatca extends Facade
21+
{
22+
protected static function getFacadeAccessor()
23+
{
24+
return \Prgayman\Zatca\Zatca::class;
25+
}
26+
}

‎src/Utilis/QrCodeOptions.php

+249
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
<?php
2+
3+
namespace Prgayman\Zatca\Utilis;
4+
5+
class QrCodeOptions
6+
{
7+
8+
/**
9+
* Holds the size of the QrCode in pixels.
10+
*
11+
* @var int
12+
*/
13+
protected $pixels = 100;
14+
15+
/**
16+
* Holds the margin size of the QrCode.
17+
*
18+
* @var int
19+
*/
20+
protected $margin = 0;
21+
22+
/**
23+
* Holds the selected formatter.
24+
*
25+
* @var string
26+
*/
27+
protected $format = 'svg';
28+
29+
/**
30+
* The foreground color of the QrCode.
31+
*
32+
* @var array|null
33+
*/
34+
protected $color = null;
35+
36+
/**
37+
* The background color of the QrCode.
38+
*
39+
* @var array|null
40+
*/
41+
protected $backgroundColor = null;
42+
43+
/**
44+
* The style of the blocks within the QrCode.
45+
* Possible values are square, dot, and round.
46+
*
47+
* @var string
48+
*/
49+
protected $style = 'square';
50+
51+
/**
52+
* The size of the selected style between 0 and 1.
53+
* This only applies to dot and round.
54+
*
55+
* @var float|null
56+
*/
57+
protected $styleSize = null;
58+
59+
/**
60+
* The style to apply to the eye.
61+
* Possible values are circle and square.
62+
*
63+
* @var string|null
64+
*/
65+
protected $eyeStyle = null;
66+
67+
/**
68+
* Sets the size of the QrCode.
69+
*
70+
* @param int $pixels
71+
* @return QrCodeOptions
72+
*/
73+
public function size(int $pixels): self
74+
{
75+
$this->pixels = $pixels;
76+
77+
return $this;
78+
}
79+
80+
/**
81+
* Sets the margin of the QrCode.
82+
*
83+
* @param int $margin
84+
* @return QrCodeOptions
85+
*/
86+
public function margin(int $margin): self
87+
{
88+
$this->margin = $margin;
89+
90+
return $this;
91+
}
92+
93+
/**
94+
* Sets the format of the QrCode.
95+
*
96+
* @param string $format
97+
* @return QrCodeOptions
98+
*/
99+
public function format(string $format): self
100+
{
101+
$this->format = $format;
102+
103+
return $this;
104+
}
105+
106+
107+
/**
108+
* Sets the foreground color of the QrCode.
109+
*
110+
* @param int $red
111+
* @param int $green
112+
* @param int $blue
113+
* @param null|int $alpha
114+
*
115+
* @return QrCodeOptions
116+
*/
117+
public function color(int $red, int $green, int $blue, ?int $alpha = null): self
118+
{
119+
$this->color = [$red, $green, $blue, $alpha];
120+
121+
return $this;
122+
}
123+
124+
/**
125+
* Sets the background color of the QrCode.
126+
*
127+
* @param int $red
128+
* @param int $green
129+
* @param int $blue
130+
* @param null|int $alpha
131+
*
132+
* @return QrCodeOptions
133+
*/
134+
public function backgroundColor(int $red, int $green, int $blue, ?int $alpha = null): self
135+
{
136+
$this->backgroundColor = [$red, $green, $blue, $alpha];
137+
138+
return $this;
139+
}
140+
141+
/**
142+
* Sets the style of the blocks for the QrCode.
143+
*
144+
* @param string $style
145+
* @param float $size
146+
*
147+
* @return QrCodeOptions
148+
*/
149+
public function style(string $style, float $size = 0.5): self
150+
{
151+
$this->style = $style;
152+
$this->styleSize = $size;
153+
154+
return $this;
155+
}
156+
157+
/**
158+
* Sets the eye style.
159+
*
160+
* @param string $style
161+
* @return QrCodeOptions
162+
*/
163+
public function eye(string $style): self
164+
{
165+
$this->eyeStyle = $style;
166+
167+
return $this;
168+
}
169+
170+
/**
171+
* Fetches the size.
172+
*
173+
* @return int
174+
*/
175+
public function getSize(): int
176+
{
177+
return $this->pixels;
178+
}
179+
180+
/**
181+
* Fetches the margin.
182+
*
183+
* @return int
184+
*/
185+
public function getMargin(): int
186+
{
187+
return $this->margin;
188+
}
189+
190+
/**
191+
* Fetches the format.
192+
*
193+
* @return string
194+
*/
195+
public function getFormat(): string
196+
{
197+
return $this->format;
198+
}
199+
200+
/**
201+
* Fetches the foreground color.
202+
*
203+
* @return array|null
204+
*/
205+
public function getColor()
206+
{
207+
return $this->color;
208+
}
209+
210+
/**
211+
* Fetches the background color.
212+
*
213+
* @return array|null
214+
*/
215+
public function getBackgroundColor()
216+
{
217+
return $this->backgroundColor;
218+
}
219+
220+
/**
221+
* Fetches the style.
222+
*
223+
* @return string
224+
*/
225+
public function getStyle(): string
226+
{
227+
return $this->style;
228+
}
229+
230+
/**
231+
* Fetches the style size.
232+
*
233+
* @return float|null
234+
*/
235+
public function getStyleSize()
236+
{
237+
return $this->styleSize;
238+
}
239+
240+
/**
241+
* Fetches the eye style.
242+
*
243+
* @return string|null
244+
*/
245+
public function getEye()
246+
{
247+
return $this->eyeStyle;
248+
}
249+
}

‎src/Utilis/Tag.php

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
namespace Prgayman\Zatca\Utilis;
4+
5+
class Tag
6+
{
7+
8+
/**
9+
* Tag
10+
* @var int
11+
*/
12+
protected $tag;
13+
14+
/**
15+
* Value
16+
* @var string
17+
*/
18+
protected $value;
19+
20+
public function __construct(int $tag, string $value)
21+
{
22+
$this->tag = $tag;
23+
$this->value = $value;
24+
}
25+
26+
/**
27+
* Get tag
28+
*
29+
* @return int
30+
*/
31+
public function getTag(): int
32+
{
33+
return $this->tag;
34+
}
35+
36+
37+
/**
38+
* Get Value
39+
*
40+
* @return string
41+
*/
42+
public function getValue(): string
43+
{
44+
return $this->value;
45+
}
46+
47+
/**
48+
* Get length value
49+
*
50+
* @return int
51+
*/
52+
public function getLength(): int
53+
{
54+
return strlen($this->value);
55+
}
56+
57+
/**
58+
* To convert the string value to hex.
59+
*
60+
* @param $value
61+
*
62+
* @return false|string
63+
*/
64+
protected function toHex($value)
65+
{
66+
return pack("H*", sprintf("%02X", $value));
67+
}
68+
69+
/**
70+
* Representing the encoded TLV data structure.
71+
*
72+
* @return string
73+
*/
74+
public function toTLV(): string
75+
{
76+
return $this->toHex($this->getTag()) . $this->toHex($this->getLength()) . $this->getValue();
77+
}
78+
79+
/**
80+
* Returns a string representing the encoded TLV data structure.
81+
*
82+
* @return string
83+
*/
84+
public function __toString()
85+
{
86+
return $this->toTLV();
87+
}
88+
}

‎src/Zatca.php

+188
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
<?php
2+
3+
namespace Prgayman\Zatca;
4+
5+
use InvalidArgumentException;
6+
use Prgayman\Zatca\Utilis\QrCodeOptions;
7+
use Prgayman\Zatca\Utilis\Tag;
8+
use SimpleSoftwareIO\QrCode\Facades\QrCode;
9+
10+
class Zatca
11+
{
12+
13+
/**
14+
* Seller Name
15+
*
16+
* @var Prgayman\Zatca\Utilis\Tag;
17+
*/
18+
protected $sellerName;
19+
20+
/**
21+
* Vat Registration Number
22+
*
23+
* @var Prgayman\Zatca\Utilis\Tag;
24+
*/
25+
protected $vatRegistrationNumber;
26+
27+
/**
28+
* Invoice date timestamp
29+
*
30+
* @var Prgayman\Zatca\Utilis\Tag;
31+
*/
32+
protected $timestamp;
33+
34+
/**
35+
* Invoice total with vat
36+
*
37+
* @var Prgayman\Zatca\Utilis\Tag;
38+
*/
39+
protected $totalWithVat;
40+
41+
/**
42+
* Invoice vat total
43+
*
44+
* @var Prgayman\Zatca\Utilis\Tag;
45+
*/
46+
protected $vatTotal;
47+
48+
/**
49+
* Set Seller name
50+
*
51+
* @return self
52+
*/
53+
public function sellerName(string $value): self
54+
{
55+
$this->sellerName = new Tag(1, $value);
56+
return $this;
57+
}
58+
59+
/**
60+
* Set Vat Registration Number
61+
*
62+
* @return self
63+
*/
64+
public function vatRegistrationNumber(string $value): self
65+
{
66+
if (strlen($value) != 15) {
67+
throw new InvalidArgumentException('Vat Registration Number must be 15 number');
68+
}
69+
70+
$this->vatRegistrationNumber = new Tag(2, $value);
71+
return $this;
72+
}
73+
74+
/**
75+
* Set invoice date (timestamp)
76+
*
77+
* @return self
78+
*/
79+
public function timestamp(string $value): self
80+
{
81+
$this->timestamp = new Tag(3, date("Y-m-d\TH:i:s\Z", strtotime($value)));
82+
return $this;
83+
}
84+
85+
/**
86+
* Set invoice total with vat
87+
*
88+
* @return self
89+
*/
90+
public function totalWithVat($value): self
91+
{
92+
$this->totalWithVat = new Tag(4, $value);
93+
return $this;
94+
}
95+
96+
/**
97+
* Set vat total
98+
*
99+
* @return self
100+
*/
101+
public function vatTotal($value): self
102+
{
103+
$this->vatTotal = new Tag(5, $value);
104+
return $this;
105+
}
106+
107+
/**
108+
* Representing the encoded TLV data structure.
109+
*
110+
* @return string
111+
*/
112+
public function toTLV(): string
113+
{
114+
return implode('', array_map(function ($tag) {
115+
return (string) $tag;
116+
}, $this->toArray()));
117+
}
118+
119+
/**
120+
* Encodes an TLV as base64
121+
*
122+
* @return string
123+
*/
124+
public function toBase64(): string
125+
{
126+
return base64_encode($this->toTLV());
127+
}
128+
129+
/**
130+
* Generate QrCode
131+
*
132+
* @return string
133+
*/
134+
public function toQrCode(QrCodeOptions $qrCodeOptions = null): string
135+
{
136+
$qrCodeOptions = $qrCodeOptions ?? new QrCodeOptions();
137+
$color = $qrCodeOptions->getColor();
138+
$backgroundColor = $qrCodeOptions->getBackgroundColor();
139+
140+
$qrCode = QrCode::size($qrCodeOptions->getSize())
141+
->margin($qrCodeOptions->getMargin())
142+
->format($qrCodeOptions->getFormat());
143+
144+
if (!is_null($color)) {
145+
$qrCode = $qrCode->color(
146+
$color[0],
147+
$color[1],
148+
$color[2],
149+
$color[3]
150+
);
151+
}
152+
153+
if (!is_null($backgroundColor)) {
154+
$qrCode = $qrCode->backgroundColor(
155+
$backgroundColor[0],
156+
$backgroundColor[1],
157+
$backgroundColor[2],
158+
$backgroundColor[3]
159+
);
160+
}
161+
162+
if (!is_null($qrCodeOptions->getStyleSize())) {
163+
$qrCode = $qrCode->style($qrCodeOptions->getStyle(), $qrCodeOptions->getStyleSize());
164+
}
165+
166+
if (!is_null($qrCodeOptions->getEye())) {
167+
$qrCode = $qrCode->eye($qrCodeOptions->getEye());
168+
}
169+
170+
return $qrCode->generate($this->toBase64());
171+
}
172+
173+
public function toArray()
174+
{
175+
$data = array_filter([
176+
$this->sellerName,
177+
$this->vatRegistrationNumber,
178+
$this->timestamp,
179+
$this->totalWithVat,
180+
$this->vatTotal,
181+
]);
182+
183+
if (count($data) != 5) {
184+
throw new InvalidArgumentException('Malformed data structure');
185+
}
186+
return $data;
187+
}
188+
}

‎src/ZatcaServiceProvider.php

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Prgayman\Zatca;
4+
5+
use Illuminate\Support\ServiceProvider;
6+
use Prgayman\Zatca\Utilis\QrCodeOptions;
7+
8+
class ZatcaServiceProvider extends ServiceProvider
9+
{
10+
public function register()
11+
{
12+
$this->app->bind('zatca', Zatca::class);
13+
$this->app->bind('qrcode.options', QrCodeOptions::class);
14+
}
15+
}

‎src/helpers.php

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
if (!function_exists('zatca')) {
4+
function zatca(): \Prgayman\Zatca\Zatca
5+
{
6+
return app('zatca');
7+
}
8+
}
9+
10+
if (!function_exists('qrCodeOptions')) {
11+
function qrCodeOptions(): \Prgayman\Zatca\Utilis\QrCodeOptions
12+
{
13+
return app('qrcode.options');
14+
}
15+
}

‎tests/TestCase.php

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Prgayman\Zatca\Test;
4+
5+
class TestCase extends \PHPUnit\Framework\TestCase
6+
{
7+
}

‎tests/Unit/ZatcaTest.php

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
namespace Prgayman\Zatca\Test\Unit;
4+
5+
use Prgayman\Zatca\Zatca;
6+
use Prgayman\Zatca\Test\TestCase;
7+
8+
class ZatcaTest extends TestCase
9+
{
10+
/**
11+
* @test
12+
* */
13+
public function shouldBase64()
14+
{
15+
$base64 = (new Zatca)->sellerName('Zatca')
16+
->vatRegistrationNumber("123456789123456")
17+
->timestamp("2021-12-01T14:00:09Z")
18+
->totalWithVat('100.00')
19+
->vatTotal('15.00')
20+
->toBase64();
21+
22+
$this->assertEquals('AQVaYXRjYQIPMTIzNDU2Nzg5MTIzNDU2AxQyMDIxLTEyLTAxVDE0OjAwOjA5WgQGMTAwLjAwBQUxNS4wMA==', $base64);
23+
}
24+
25+
/**
26+
* @test
27+
* */
28+
public function shouldBase64eAsArabic()
29+
{
30+
$base64 = (new Zatca)->sellerName('ايمن')
31+
->vatRegistrationNumber("123456789123456")
32+
->timestamp("2021-12-01T14:00:09Z")
33+
->totalWithVat('100.00')
34+
->vatTotal('15.00')
35+
->toBase64();
36+
37+
$this->assertEquals(
38+
'AQjYp9mK2YXZhgIPMTIzNDU2Nzg5MTIzNDU2AxQyMDIxLTEyLTAxVDE0OjAwOjA5WgQGMTAwLjAwBQUxNS4wMA==',
39+
$base64
40+
);
41+
}
42+
43+
/**
44+
* @test
45+
* */
46+
public function shouldTLV()
47+
{
48+
$tlv = (new Zatca)->sellerName('Zatca')
49+
->vatRegistrationNumber("123456789123456")
50+
->timestamp("2021-12-01T14:00:09Z")
51+
->totalWithVat('100.00')
52+
->vatTotal('15.00')
53+
->toTLV();
54+
55+
$this->assertEquals(
56+
'AQVaYXRjYQIPMTIzNDU2Nzg5MTIzNDU2AxQyMDIxLTEyLTAxVDE0OjAwOjA5WgQGMTAwLjAwBQUxNS4wMA==',
57+
base64_encode($tlv)
58+
);
59+
}
60+
61+
/**
62+
* @test
63+
*/
64+
public function shouldThrowExpectionWithWrongData()
65+
{
66+
$this->expectException(\InvalidArgumentException::class);
67+
68+
(new Zatca)->sellerName('Zatca')
69+
->vatRegistrationNumber("123456789123456")
70+
->toBase64();
71+
}
72+
}

0 commit comments

Comments
 (0)
Please sign in to comment.