40 | * @see http://www.php-fig.org/psr/psr-0/
41 | * @see http://www.php-fig.org/psr/psr-4/
42 | */
43 | class ClassLoader
44 | {
45 | // PSR-4
46 | private $prefixLengthsPsr4 = array();
47 | private $prefixDirsPsr4 = array();
48 | private $fallbackDirsPsr4 = array();
49 |
50 | // PSR-0
51 | private $prefixesPsr0 = array();
52 | private $fallbackDirsPsr0 = array();
53 |
54 | private $useIncludePath = false;
55 | private $classMap = array();
56 | private $classMapAuthoritative = false;
57 | private $missingClasses = array();
58 | private $apcuPrefix;
59 |
60 | public function getPrefixes()
61 | {
62 | if (!empty($this->prefixesPsr0)) {
63 | return call_user_func_array('array_merge', $this->prefixesPsr0);
64 | }
65 |
66 | return array();
67 | }
68 |
69 | public function getPrefixesPsr4()
70 | {
71 | return $this->prefixDirsPsr4;
72 | }
73 |
74 | public function getFallbackDirs()
75 | {
76 | return $this->fallbackDirsPsr0;
77 | }
78 |
79 | public function getFallbackDirsPsr4()
80 | {
81 | return $this->fallbackDirsPsr4;
82 | }
83 |
84 | public function getClassMap()
85 | {
86 | return $this->classMap;
87 | }
88 |
89 | /**
90 | * @param array $classMap Class to filename map
91 | */
92 | public function addClassMap(array $classMap)
93 | {
94 | if ($this->classMap) {
95 | $this->classMap = array_merge($this->classMap, $classMap);
96 | } else {
97 | $this->classMap = $classMap;
98 | }
99 | }
100 |
101 | /**
102 | * Registers a set of PSR-0 directories for a given prefix, either
103 | * appending or prepending to the ones previously set for this prefix.
104 | *
105 | * @param string $prefix The prefix
106 | * @param array|string $paths The PSR-0 root directories
107 | * @param bool $prepend Whether to prepend the directories
108 | */
109 | public function add($prefix, $paths, $prepend = false)
110 | {
111 | if (!$prefix) {
112 | if ($prepend) {
113 | $this->fallbackDirsPsr0 = array_merge(
114 | (array) $paths,
115 | $this->fallbackDirsPsr0
116 | );
117 | } else {
118 | $this->fallbackDirsPsr0 = array_merge(
119 | $this->fallbackDirsPsr0,
120 | (array) $paths
121 | );
122 | }
123 |
124 | return;
125 | }
126 |
127 | $first = $prefix[0];
128 | if (!isset($this->prefixesPsr0[$first][$prefix])) {
129 | $this->prefixesPsr0[$first][$prefix] = (array) $paths;
130 |
131 | return;
132 | }
133 | if ($prepend) {
134 | $this->prefixesPsr0[$first][$prefix] = array_merge(
135 | (array) $paths,
136 | $this->prefixesPsr0[$first][$prefix]
137 | );
138 | } else {
139 | $this->prefixesPsr0[$first][$prefix] = array_merge(
140 | $this->prefixesPsr0[$first][$prefix],
141 | (array) $paths
142 | );
143 | }
144 | }
145 |
146 | /**
147 | * Registers a set of PSR-4 directories for a given namespace, either
148 | * appending or prepending to the ones previously set for this namespace.
149 | *
150 | * @param string $prefix The prefix/namespace, with trailing '\\'
151 | * @param array|string $paths The PSR-4 base directories
152 | * @param bool $prepend Whether to prepend the directories
153 | *
154 | * @throws \InvalidArgumentException
155 | */
156 | public function addPsr4($prefix, $paths, $prepend = false)
157 | {
158 | if (!$prefix) {
159 | // Register directories for the root namespace.
160 | if ($prepend) {
161 | $this->fallbackDirsPsr4 = array_merge(
162 | (array) $paths,
163 | $this->fallbackDirsPsr4
164 | );
165 | } else {
166 | $this->fallbackDirsPsr4 = array_merge(
167 | $this->fallbackDirsPsr4,
168 | (array) $paths
169 | );
170 | }
171 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
172 | // Register directories for a new namespace.
173 | $length = strlen($prefix);
174 | if ('\\' !== $prefix[$length - 1]) {
175 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
176 | }
177 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
178 | $this->prefixDirsPsr4[$prefix] = (array) $paths;
179 | } elseif ($prepend) {
180 | // Prepend directories for an already registered namespace.
181 | $this->prefixDirsPsr4[$prefix] = array_merge(
182 | (array) $paths,
183 | $this->prefixDirsPsr4[$prefix]
184 | );
185 | } else {
186 | // Append directories for an already registered namespace.
187 | $this->prefixDirsPsr4[$prefix] = array_merge(
188 | $this->prefixDirsPsr4[$prefix],
189 | (array) $paths
190 | );
191 | }
192 | }
193 |
194 | /**
195 | * Registers a set of PSR-0 directories for a given prefix,
196 | * replacing any others previously set for this prefix.
197 | *
198 | * @param string $prefix The prefix
199 | * @param array|string $paths The PSR-0 base directories
200 | */
201 | public function set($prefix, $paths)
202 | {
203 | if (!$prefix) {
204 | $this->fallbackDirsPsr0 = (array) $paths;
205 | } else {
206 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
207 | }
208 | }
209 |
210 | /**
211 | * Registers a set of PSR-4 directories for a given namespace,
212 | * replacing any others previously set for this namespace.
213 | *
214 | * @param string $prefix The prefix/namespace, with trailing '\\'
215 | * @param array|string $paths The PSR-4 base directories
216 | *
217 | * @throws \InvalidArgumentException
218 | */
219 | public function setPsr4($prefix, $paths)
220 | {
221 | if (!$prefix) {
222 | $this->fallbackDirsPsr4 = (array) $paths;
223 | } else {
224 | $length = strlen($prefix);
225 | if ('\\' !== $prefix[$length - 1]) {
226 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
227 | }
228 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
229 | $this->prefixDirsPsr4[$prefix] = (array) $paths;
230 | }
231 | }
232 |
233 | /**
234 | * Turns on searching the include path for class files.
235 | *
236 | * @param bool $useIncludePath
237 | */
238 | public function setUseIncludePath($useIncludePath)
239 | {
240 | $this->useIncludePath = $useIncludePath;
241 | }
242 |
243 | /**
244 | * Can be used to check if the autoloader uses the include path to check
245 | * for classes.
246 | *
247 | * @return bool
248 | */
249 | public function getUseIncludePath()
250 | {
251 | return $this->useIncludePath;
252 | }
253 |
254 | /**
255 | * Turns off searching the prefix and fallback directories for classes
256 | * that have not been registered with the class map.
257 | *
258 | * @param bool $classMapAuthoritative
259 | */
260 | public function setClassMapAuthoritative($classMapAuthoritative)
261 | {
262 | $this->classMapAuthoritative = $classMapAuthoritative;
263 | }
264 |
265 | /**
266 | * Should class lookup fail if not found in the current class map?
267 | *
268 | * @return bool
269 | */
270 | public function isClassMapAuthoritative()
271 | {
272 | return $this->classMapAuthoritative;
273 | }
274 |
275 | /**
276 | * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277 | *
278 | * @param string|null $apcuPrefix
279 | */
280 | public function setApcuPrefix($apcuPrefix)
281 | {
282 | $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
283 | }
284 |
285 | /**
286 | * The APCu prefix in use, or null if APCu caching is not enabled.
287 | *
288 | * @return string|null
289 | */
290 | public function getApcuPrefix()
291 | {
292 | return $this->apcuPrefix;
293 | }
294 |
295 | /**
296 | * Registers this instance as an autoloader.
297 | *
298 | * @param bool $prepend Whether to prepend the autoloader or not
299 | */
300 | public function register($prepend = false)
301 | {
302 | spl_autoload_register(array($this, 'loadClass'), true, $prepend);
303 | }
304 |
305 | /**
306 | * Unregisters this instance as an autoloader.
307 | */
308 | public function unregister()
309 | {
310 | spl_autoload_unregister(array($this, 'loadClass'));
311 | }
312 |
313 | /**
314 | * Loads the given class or interface.
315 | *
316 | * @param string $class The name of the class
317 | * @return bool|null True if loaded, null otherwise
318 | */
319 | public function loadClass($class)
320 | {
321 | if ($file = $this->findFile($class)) {
322 | includeFile($file);
323 |
324 | return true;
325 | }
326 | }
327 |
328 | /**
329 | * Finds the path to the file where the class is defined.
330 | *
331 | * @param string $class The name of the class
332 | *
333 | * @return string|false The path if found, false otherwise
334 | */
335 | public function findFile($class)
336 | {
337 | // class map lookup
338 | if (isset($this->classMap[$class])) {
339 | return $this->classMap[$class];
340 | }
341 | if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
342 | return false;
343 | }
344 | if (null !== $this->apcuPrefix) {
345 | $file = apcu_fetch($this->apcuPrefix.$class, $hit);
346 | if ($hit) {
347 | return $file;
348 | }
349 | }
350 |
351 | $file = $this->findFileWithExtension($class, '.php');
352 |
353 | // Search for Hack files if we are running on HHVM
354 | if (false === $file && defined('HHVM_VERSION')) {
355 | $file = $this->findFileWithExtension($class, '.hh');
356 | }
357 |
358 | if (null !== $this->apcuPrefix) {
359 | apcu_add($this->apcuPrefix.$class, $file);
360 | }
361 |
362 | if (false === $file) {
363 | // Remember that this class does not exist.
364 | $this->missingClasses[$class] = true;
365 | }
366 |
367 | return $file;
368 | }
369 |
370 | private function findFileWithExtension($class, $ext)
371 | {
372 | // PSR-4 lookup
373 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
374 |
375 | $first = $class[0];
376 | if (isset($this->prefixLengthsPsr4[$first])) {
377 | $subPath = $class;
378 | while (false !== $lastPos = strrpos($subPath, '\\')) {
379 | $subPath = substr($subPath, 0, $lastPos);
380 | $search = $subPath . '\\';
381 | if (isset($this->prefixDirsPsr4[$search])) {
382 | $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
383 | foreach ($this->prefixDirsPsr4[$search] as $dir) {
384 | if (file_exists($file = $dir . $pathEnd)) {
385 | return $file;
386 | }
387 | }
388 | }
389 | }
390 | }
391 |
392 | // PSR-4 fallback dirs
393 | foreach ($this->fallbackDirsPsr4 as $dir) {
394 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
395 | return $file;
396 | }
397 | }
398 |
399 | // PSR-0 lookup
400 | if (false !== $pos = strrpos($class, '\\')) {
401 | // namespaced class name
402 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
403 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
404 | } else {
405 | // PEAR-like class name
406 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
407 | }
408 |
409 | if (isset($this->prefixesPsr0[$first])) {
410 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
411 | if (0 === strpos($class, $prefix)) {
412 | foreach ($dirs as $dir) {
413 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
414 | return $file;
415 | }
416 | }
417 | }
418 | }
419 | }
420 |
421 | // PSR-0 fallback dirs
422 | foreach ($this->fallbackDirsPsr0 as $dir) {
423 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
424 | return $file;
425 | }
426 | }
427 |
428 | // PSR-0 include paths.
429 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
430 | return $file;
431 | }
432 |
433 | return false;
434 | }
435 | }
436 |
437 | /**
438 | * Scope isolated include.
439 | *
440 | * Prevents access to $this/self from included files.
441 | */
442 | function includeFile($file)
443 | {
444 | include $file;
445 | }
446 |
--------------------------------------------------------------------------------
/src/component/data.php:
--------------------------------------------------------------------------------
1 | data = array(
20 | "cbc:UBLVersionID" => "2.1",
21 | "cbc:CustomizationID" => "TR1.2",
22 | "cbc:ProfileID" => $veri["ProfileID"],
23 | "cbc:ID" => ($veri["ID"]?$veri["ID"]:""),
24 | "cbc:CopyIndicator" => "false",
25 | "cbc:UUID" => ($veri["UUID"]?$veri["UUID"]:$this->getUuid()),
26 | "cbc:IssueDate" => $veri["IssueDate"],
27 | "cbc:IssueTime" => $veri["IssueTime"],
28 | "cbc:InvoiceTypeCode" => ($veri["InvoiceTypeCode"] ? $veri["InvoiceTypeCode"] : "SATIS"),
29 | "cbc:Note" => array(),
30 | "cbc:DocumentCurrencyCode" => ($veri["DocumentCurrencyCode"] ? $veri["DocumentCurrencyCode"] : "TRY"),
31 | "cbc:LineCountNumeric" => 1,
32 | "cac:AccountingSupplierParty" => array(
33 | "cac:Party" => array(
34 | "cbc:WebsiteURI" => "http://www.aaa.com.tr/",
35 | "cac:PartyIdentification" => array(
36 | "cbc:ID" => "8720616074",
37 | ),
38 | "cac:PartyName" => array(
39 | "cbc:Name" => "AAA Anonim Şirketi",
40 | ),
41 | "cac:PostalAddress" => array(
42 | "cbc:ID" => 1,
43 | "cbc:StreetName" => "Papatya Caddesi Yasemin Sokak",
44 | "cbc:BuildingNumber" => "21",
45 | "cbc:CitySubdivisionName" => "Beşiktaş",
46 | "cbc:CityName" => "İstanbul",
47 | "cbc:PostalZone" => "34100",
48 | "cac:Country" => array(
49 | "cbc:Name" => "Türkiye",
50 | ),
51 | ),
52 | "cac:PartyTaxScheme" => array(
53 | "cac:TaxScheme" => array(
54 | "cbc:Name" => "Büyük Mükellefler",
55 | ),
56 | ),
57 | "cac:Contact" => array(
58 | "cbc:Telephone" => "(212) 925 51515",
59 | "cbc:Telefax" => "(212) 925505015",
60 | "cbc:ElectronicMail" => "aa@aaa.com.tr",
61 | ),
62 | ),
63 | ),
64 | "cac:AccountingCustomerParty" => array(
65 | "cac:Party" => array(
66 | "cbc:WebsiteURI" => "",
67 | "cac:PartyIdentification" => array(
68 | "cbc:ID" => "39667363036",
69 | ),
70 | "cac:PartyName" => array(
71 | "cbc:Name" => "AAA Anonim Şirketi",
72 | ),
73 | "cac:Person" => array(
74 | "cbc:FirstName" => "Muhittin",
75 | "cbc:FamilyName" => "GÜLAP",
76 | ),
77 | "cac:PostalAddress" => array(
78 | "cbc:ID" => 1,
79 | "cbc:StreetName" => "ATATÜRK MAH. 6. Sokak",
80 | "cbc:BuildingNumber" => "1",
81 | "cbc:CitySubdivisionName" => "Beşiktaş",
82 | "cbc:CityName" => "İstanbul",
83 | "cbc:PostalZone" => "34100",
84 | "cac:Country" => array(
85 | "cbc:Name" => "Türkiye",
86 | ),
87 | ),
88 | "cac:PartyTaxScheme" => array(
89 | "cac:TaxScheme" => array(
90 | "cbc:Name" => "",
91 | ),
92 | ),
93 | "cac:Contact" => array(
94 | "cbc:Telephone" => "(212) 925 51515",
95 | "cbc:Telefax" => "(212) 925505015",
96 | "cbc:ElectronicMail" => "aa@aaa.com.tr",
97 | ),
98 | ),
99 | ),
100 | "cac:PaymentTerms" => array(
101 | "cbc:Note" => "BBB Bank Otomatik Ödeme",
102 | "cbc:PaymentDueDate" => "2020-06-30",
103 | ),
104 | "cac:TaxTotal" => array(
105 | "cbc:TaxAmount" => 2.73,
106 | "cac:TaxSubtotal" => array(
107 | 0 => array(
108 | "cbc:TaxableAmount" => 15.15,
109 | "cbc:TaxAmount" => 2.73,
110 | "cac:TaxCategory" => array(
111 | "cac:TaxScheme" => array(
112 | "cbc:Name" => "KDV",
113 | "cbc:TaxTypeCode" => "0015",
114 | ),
115 | ),
116 | ),
117 | 1 => array(
118 | "cbc:TaxableAmount" => 15.15,
119 | "cbc:TaxAmount" => 2.73,
120 | "cac:TaxCategory" => array(
121 | "cac:TaxScheme" => array(
122 | "cbc:Name" => "ÖİV",
123 | "cbc:TaxTypeCode" => "0016",
124 | ),
125 | ),
126 | ),
127 | ),
128 | ),
129 | "cac:LegalMonetaryTotal" => array(
130 | "cbc:LineExtensionAmount" => 15.15,
131 | "cbc:TaxExclusiveAmount" => 15.15,
132 | "cbc:TaxInclusiveAmount" => 17.88,
133 | "cbc:PayableAmount" => 17.88,
134 | ),
135 | "cac:InvoiceLine" => array(),
136 | );
137 | return $this;
138 | }
139 |
140 | public function getUuid($prefix = '')
141 | {
142 | $chars = md5(uniqid(mt_rand(), true));
143 | $parts = [substr($chars, 0, 8), substr($chars, 8, 4), substr($chars, 12, 4), substr($chars, 16, 4), substr($chars, 20, 12)];
144 | return $prefix . implode($parts, '-');
145 | }
146 |
147 | public function getFaturaNo($prefix='TRA'){
148 |
149 | }
150 |
151 | public function setSupplierCustomerParty($type = "Supplier", $data = array())
152 | {
153 | /* example data
154 | $type => Supplier veya Customer gönderilmelidir.
155 | $data = array(
156 | "Person" => array(
157 | "FirstName" => "",
158 | "FamilyName" => "",
159 | ),
160 | "Party" => array(
161 | "WebsiteURI" => "",
162 | "PartyIdentificationID" => "",
163 | "PartyName" => "",
164 | "Telephone" => "",
165 | "Telefax" => "",
166 | "ElectronicMail" => "",
167 | "PartyTaxSchemeName" => "",
168 | ),
169 | "PostalAddress" => array(
170 | "StreetName" => "",
171 | "BuildingNumber" => "",
172 | "CitySubdivisionName" => "",
173 | "CityName" => "",
174 | "PostalZone" => "",
175 | "CountryName" => "",
176 | ),
177 | );
178 | */
179 |
180 | $this->data["cac:Accounting" . $type . "Party"] = array(
181 | "cac:Party" => array(
182 | "cbc:WebsiteURI" => $data["Party"]["WebsiteURI"],
183 | "cac:PartyIdentification" => array(
184 | "cbc:ID" => $data["Party"]["PartyIdentificationID"],
185 | ),
186 | "cac:PartyName" => array(
187 | "cbc:Name" => $data["Party"]["PartyName"],
188 | ),
189 | "cac:PostalAddress" => array(
190 | "cbc:ID" => 1,
191 | "cbc:StreetName" => $data["PostalAddress"]["StreetName"],
192 | "cbc:BuildingNumber" => $data["PostalAddress"]["BuildingNumber"],
193 | "cbc:CitySubdivisionName" => $data["PostalAddress"]["CitySubdivisionName"],
194 | "cbc:CityName" => $data["PostalAddress"]["CityName"],
195 | "cbc:PostalZone" => $data["PostalAddress"]["PostalZone"],
196 | "cac:Country" => array(
197 | "cbc:Name" => $data["PostalAddress"]["CountryName"],
198 | ),
199 | ),
200 | "cac:PartyTaxScheme" => array(
201 | "cac:TaxScheme" => array(
202 | "cbc:Name" => $data["Party"]["PartyTaxSchemeName"],
203 | ),
204 | ),
205 |
206 | "cac:Contact" => array(
207 | "cbc:Telephone" => $data["Party"]["Telephone"],
208 | "cbc:Telefax" => $data["Party"]["Telefax"],
209 | "cbc:ElectronicMail" => $data["Party"]["ElectronicMail"],
210 | ),
211 | ),
212 | );
213 |
214 | return $this;
215 | }
216 |
217 | public function setPaymentTerms($data = array())
218 | {
219 | $this->data["cac:PaymentTerms"] = array(
220 | "cbc:Note" => $data["Note"],
221 | "cbc:PaymentDueDate" => $data["PaymentDueDate"],
222 | );
223 | return $this;
224 | }
225 |
226 | public function setInvoiceLine($data = array())
227 | {
228 | /* example data
229 | $data = array(
230 | "cbc:ID" => 1,
231 | "cbc:InvoicedQuantity" => 101,
232 | "cbc:LineExtensionAmount" => 15.15,
233 | "cac:AllowanceCharge" => array(
234 | "cbc:ChargeIndicator" => "false",
235 | "cbc:MultiplierFactorNumeric" => 0.0,
236 | "cbc:Amount" => 0,
237 | "cbc:BaseAmount" => 15.15,
238 | ),
239 | "cac:TaxTotal" => array(
240 | "cbc:TaxAmount" => 2.73,
241 | "cac:TaxSubtotal" => array(
242 | 0 => array(
243 | "cbc:TaxableAmount" => 15.15,
244 | "cbc:TaxAmount" => 2.73,
245 | "cbc:Percent" => 18.0,
246 | "cac:TaxCategory" => array(
247 | "cac:TaxScheme" => array(
248 | "cbc:Name" => "KDV",
249 | "cbc:TaxTypeCode" => "0015",
250 | ),
251 | ),
252 | ),
253 | 1 => array(
254 | "cbc:TaxableAmount" => 15.15,
255 | "cbc:TaxAmount" => 2.73,
256 | "cbc:Percent" => 18.0,
257 | "cac:TaxCategory" => array(
258 | "cac:TaxScheme" => array(
259 | "cbc:Name" => "Öiv",
260 | "cbc:TaxTypeCode" => "0016",
261 | ),
262 | ),
263 | ),
264 | ),
265 | ),
266 | "cac:Item" => array(
267 | "cbc:Name" => "Tükenmez Kalem",
268 | ),
269 | "cac:Price" => array(
270 | "cbc:PriceAmount" => 10.0,
271 | ),
272 | );
273 | */
274 |
275 | if (count($data["TaxSubtotal"]) > 0) {
276 | foreach ($data["TaxSubtotal"] as $k => $v) {
277 | $TaxSubTotal[] = array(
278 | "cbc:TaxableAmount" => $v["TaxableAmount"],
279 | "cbc:TaxAmount" => $v["TaxAmount"],
280 | "cbc:Percent" => $v["Percent"],
281 | "cac:TaxCategory" => array(
282 | "cac:TaxScheme" => array(
283 | "cbc:Name" => $v["TaxSchemeName"],
284 | "cbc:TaxTypeCode" => $v["TaxSchemeTaxTypeCode"],
285 | ),
286 | ),
287 | );
288 | }
289 | }
290 |
291 | $this->data["cac:InvoiceLine"][$data["ID"]] = array(
292 | "cbc:ID" => $data["ID"],
293 | "cbc:InvoicedQuantity" => $data["InvoicedQuantity"],
294 | "cbc:LineExtensionAmount" => $data["LineExtensionAmount"],
295 | "cac:AllowanceCharge" => array(
296 | "cbc:ChargeIndicator" => "false",
297 | "cbc:MultiplierFactorNumeric" => 0.0,
298 | "cbc:Amount" => 0,
299 | "cbc:BaseAmount" => $data["BaseAmount"],
300 | ),
301 | "cac:TaxTotal" => array(
302 | "cbc:TaxAmount" => $data["TaxAmount"],
303 | "cac:TaxSubtotal" => $TaxSubTotal,
304 | ),
305 | "cac:Item" => array(
306 | "cbc:Name" => $data["ItemName"],
307 | ),
308 | "cac:Price" => array(
309 | "cbc:PriceAmount" => $data["PriceAmount"],
310 | ),
311 | );
312 |
313 | return $this;
314 | }
315 |
316 | public function setAddNote($data = "")
317 | {
318 | /*
319 | * not eklemek için
320 | *
321 | * example data
322 | * $data=array(
323 | * "ID" => 1;
324 | "Value" => "Gönderim Şekli: ELEKTRONIK";
325 | * );
326 | * */
327 |
328 | $this->data["cbc:Note"][$data["ID"]] = $data["Value"];
329 | return $this;
330 | }
331 |
332 | public function setPerson($type="Supplier",$data = "")
333 | {
334 | /*
335 | * Personel eklemek için
336 | *
337 | * example data
338 | *
339 | * $type => Supplier / Customer
340 | *
341 | * $data=array(
342 | * "FirstName" => "Muhittin"
343 | "FamilyName" => "Gülap"
344 | * );
345 | * */
346 |
347 | $this->data["cac:Accounting".$type."Party"]["cac:Party"]["cac:Person"] = array(
348 | "cbc:FirstName" => $data["FirstName"],
349 | "cbc:FamilyName" => $data["FamilyName"],
350 | );
351 | return $this;
352 | }
353 |
354 | public function setTotals()
355 | {
356 | /*
357 | * aşağıdaki alanlar bu fonksiyonda otomatik olarak hesaplanır
358 | LineCountNumeric
359 | TaxTotal
360 | LegalMonetaryTotal
361 | */
362 |
363 | /* toplam satır adedi giriliyor.*/
364 | $this->data["cbc:LineCountNumeric"] = count($this->data["cac:InvoiceLine"]);
365 |
366 | $vergiler = array();
367 | $toplamTutar = $toplamVergiTutari = $toplamMalHizmetTutar = 0;
368 | if (count($this->data["cac:InvoiceLine"]) > 0) {
369 | foreach ($this->data["cac:InvoiceLine"] as $key => $Satir) {
370 | $toplamTutar += $Satir["cbc:LineExtensionAmount"];
371 | $toplamMalHizmetTutar += $Satir["cbc:LineExtensionAmount"];
372 |
373 | if (count($Satir["cac:TaxTotal"]["cac:TaxSubtotal"]) > 0) {
374 | foreach ($Satir["cac:TaxTotal"]["cac:TaxSubtotal"] as $k => $Vergi) {
375 | if (!@$vergiler[@$Vergi["cac:TaxCategory"]["cac:TaxScheme"]["cbc:TaxTypeCode"]]) {
376 | $vergiler[@$Vergi["cac:TaxCategory"]["cac:TaxScheme"]["cbc:TaxTypeCode"]] = $Vergi;
377 | } else {
378 | $vergiler[@$Vergi["cac:TaxCategory"]["cac:TaxScheme"]["cbc:TaxTypeCode"]]["cbc:TaxAmount"] += @$Vergi["cbc:TaxAmount"];
379 | }
380 | $toplamTutar += @$Vergi["cbc:TaxAmount"];
381 | $toplamVergiTutari += @$Vergi["cbc:TaxAmount"];
382 | }
383 | }
384 | }
385 | }
386 |
387 | $this->data["cac:TaxTotal"]["cbc:TaxAmount"] = $toplamVergiTutari;
388 | $this->data["cac:TaxTotal"]["cac:TaxSubtotal"] = $vergiler;
389 |
390 | $this->data["cac:LegalMonetaryTotal"] = array(
391 | "cbc:LineExtensionAmount" => $toplamMalHizmetTutar,
392 | "cbc:TaxExclusiveAmount" => $toplamTutar - $toplamVergiTutari,
393 | "cbc:TaxInclusiveAmount" => $toplamTutar,
394 | "cbc:PayableAmount" => $toplamTutar,
395 | );
396 |
397 | return $this;
398 | }
399 |
400 | public function getData()
401 | {
402 | return $this->data;
403 | }
404 |
405 | }
406 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | E-Fatura / E-Arşiv
QNB Finansbank
4 |
5 | QNB Finansbank E-Fatura ve E-Arşiv PHP Api
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | QNB Finansbank web servisleri için PHP ile yazılmış olan bu kütüphane ile E-Arşiv, E-Fatura bildirim işlemlerini yapabilirsiniz.
17 |
18 | ## Dokümantasyon (QNB FinansBank)
19 | Dokümantasyon dosyalarına ulaşmak için [tıklayınız.](https://www.qnbefinans.com/destek/api-teknik)
20 |
21 | ## Kurulum
22 |
23 | $ composer require muhittingulap/qnbfinansbank
24 |
25 | ## Projenizde Kullanma
26 | ```php
27 | getUuid();
61 |
62 | $veri = array(
63 | "ID" => "",
64 | "ProfileID" => "",
65 | "UUID" => $uuid,
66 | "IssueDate" => "",
67 | "IssueTime" => "",
68 | );
69 |
70 | /* hazırlanan başlangıç datasını set ediyoruz */
71 | $data->setStartData($veri);
72 | ```
73 | **Parameters:**
74 |
75 | | Parametre | Açıklama |
76 | | ------ | -------- |
77 | | ID | Fatura numaranız 'TRA2020000000001' şeklinde boş bırakılması halinde finansbank tarafından otomatik oluşturulur. Finansbank'tan e-arşiv ve e-fatura için seri no belirleme için [tıklayınız.](https://github.com/muhittingulap/qnbfinansbank#e-fatura-ve-e-ar%C5%9Fiv-ek-methodlar) |
78 | | ProfileID | 'TICARIFATURA','TEMELFATURA' veya 'EARSIVFATURA' yazabilirsiniz. E-Arşiv içinbu bilgi boş olduğunda otomaik oluşturulur. |
79 | | UUID | Benzersiz işlem numarasıdır. Otomatik oluşturulması için yukarıda örnek kod bulunur. |
80 | | IssueDate | Fatura Tarihi YYYY-MM-DD şeklinde girilmelidir. örn: 2020-07-01 |
81 | | IssueTime | Fatura Saati HH:ii:ss şeklinde girilmelidir. 20:18:00 |
82 |
83 | #### - Not Bilgilerinin Eklenmesi
84 |
85 | Her Bir Notu set ediyoruz. Notlar için dokümanı inceleyiniz.
86 | ```php
87 | 1, /* not benzersiz id si */
91 | "Value" => "", /* not tu buraya yazınız */
92 | );
93 | $data->setAddNote($veri);
94 | ```
95 |
96 | Örnek:
97 |
98 | ```php
99 | // e faturada zorunluluk yoktur. e arşiv için zorunlu olduğundan aşağıdaki notu eklemeniz yeterlidir.
100 | 1,
104 | "Value" => "Gönderim Şekli: ELEKTRONIK",
105 | );
106 | $data->setAddNote($veri);
107 | ```
108 | **Parameters:**
109 |
110 | | Parametre | Açıklama |
111 | | ---------------------------- | -------- |
112 | | Gönderim Şekli: ELEKTRONIK | Bu not E-Arşiv için zorunludur. Diğer not lar için dokümantasyonu inceleyiniz. |
113 | | #EFN_SERINO_TERCIHI#EF# | Bu not E-Fatura No otomatik üretilmesi istenmesi durumunda başlangıç seri no maksimum 2 hane gönderilmelidir. Bu örnekte : EF |
114 |
115 |
116 | #### - Satıcı ve Alıcı Bilgilerinin Eklenmesi
117 |
118 | Aynı bu set işlemini 'Customer' içinde alıcı bilgilerini yazıp yapmalı ve aşağıdaki 'Supplier' yazan yeri değiştirip set etmelisiniz.
119 | ```php
120 | array(
124 | "WebsiteURI" => "",
125 | "PartyIdentificationID" => "",
126 | "PartyName" => "",
127 | "Telephone" => "",
128 | "Telefax" => "",
129 | "ElectronicMail" => "",
130 | "PartyTaxSchemeName" => "",
131 | ),
132 | "PostalAddress" => array(
133 | "StreetName" => "",
134 | "BuildingNumber" => "",
135 | "CitySubdivisionName" => "",
136 | "CityName" => "",
137 | "PostalZone" => "",
138 | "CountryName" => "Türkiye",
139 | ),
140 | );
141 | $data->setSupplierCustomerParty('Supplier', $veri);
142 | ```
143 | **Parameters:**
144 |
145 | | Parametre | Açıklama |
146 | | ---------------------------- | -------- |
147 | | WebsiteURI | Web site adresi bilgisi|
148 | | PartyIdentificationID | Vergi no veya TC kimlik no bilgisi|
149 | | PartyName | Ad Soyad veya Ünvan bilgisi|
150 | | Telephone | Telefon numarası bilgisi|
151 | | Telefax | Fax numarası bilgisi|
152 | | ElectronicMail | Email adresi bilgisi|
153 | | PartyTaxSchemeName | Vergi Dairesi (varsa) bilgisi|
154 | | StreetName | Açık Adresi bilgisi|
155 | | BuildingNumber | Kapı Numarası bilgisi|
156 | | CitySubdivisionName | İlçe bilgisi|
157 | | CityName | İl bilgisi|
158 | | PostalZone | Posta Kodu bilgisi|
159 | | CountryName | Ülke bilgisi|
160 |
161 | #### - Satıcı ve Alıcı Personel Bilgilerinin Eklenmesi
162 |
163 | 'Customer' için mutlaka set edin çünkü TC kimlik no olduğunda zorunludur. Supplier için zorunlu değil ama girebilirsiniz
164 | ```php
165 | "",
169 | "FamilyName" => "",
170 | );
171 |
172 | $data->setPerson('Customer', $veri);
173 | ```
174 | **Parameters:**
175 |
176 | | Parametre | Açıklama |
177 | | ---------------------------- | -------- |
178 | | FirstName | Ad bilgisi |
179 | | FamilyName | Soyad bilgisi |
180 |
181 |
182 | #### - Ödeme Koşulları Girilmesi
183 |
184 | Bilgi notu şeklinde girilemsi zorunlu değildir.
185 | ```php
186 | "Ziraat Bankası",
190 | "PaymentDueDate" => "2020-07-30",
191 | );
192 | $data->setPaymentTerms($veri);
193 | ```
194 | **Parameters:**
195 |
196 | | Parametre | Açıklama |
197 | | ---------------------------- | -------- |
198 | | Note | Not bilgisi |
199 | | PaymentDueDate | Son Ödeme Tarihi bilgisi. örn: 2020-07-30 |
200 |
201 |
202 | #### - Fatura Satırlarının Girilmesi
203 |
204 | Bu adım da her satır için bu işlemi tekrarlamanız veya bir döngü içerisinde tüm fatura satırlarınızı set etmeniz gerekmektedir.
205 | ```php
206 | "",
210 | "InvoicedQuantity" => "",
211 | "LineExtensionAmount" => "",
212 | "BaseAmount" => 0,
213 | "TaxAmount" => 0,
214 | "TaxSubtotal" => array(
215 | 0 => array(
216 | "TaxableAmount" => 0,
217 | "TaxAmount" => 0,
218 | "Percent" => 0,
219 | "TaxSchemeName" => "KDV",
220 | "TaxSchemeTaxTypeCode" => "0015",
221 | ),
222 | 1 => array(
223 | "TaxableAmount" => 0,
224 | "TaxAmount" => 0,
225 | "Percent" => 0,
226 | "TaxSchemeName" => "Özel İletişim Vergisi",
227 | "TaxSchemeTaxTypeCode" => "4080",
228 | ),
229 | ),
230 | "ItemName" => "",
231 | "PriceAmount" => 0,
232 | );
233 |
234 | $data->setInvoiceLine($veri);
235 | ```
236 | **Parameters:**
237 |
238 | | Parametre | Açıklama |
239 | | --------------------------------------------| -------- |
240 | | ID | Satır sıra no veya benzersiz ID her satır için uniq olmalı |
241 | | InvoicedQuantity | Ürün Adet |
242 | | LineExtensionAmount | Satır toplam vergiler hariç |
243 | | BaseAmount | Satır toplam vergiler dahil |
244 | | TaxAmount | Vergiler toplam tutarı |
245 | | ItemName | Satılan ürün adı |
246 | | PriceAmount | Satır birim fiyat |
247 | | TaxSubtotal -> TaxableAmount | Vergi toplam matrah |
248 | | TaxSubtotal -> TaxAmount | Vergi toplam tutarı |
249 | | TaxSubtotal -> Percent | Vergi Oranı |
250 | | TaxSubtotal -> TaxSchemeName | Vergi başlığı |
251 | | TaxSubtotal -> TaxSchemeTaxTypeCode | Vergi Kodu (dokümantasyon inceleyin) |
252 |
253 |
254 | #### - Datanın Son Halinin Alınması
255 |
256 | Bu adım da fatura satırlarından otomatik olarak parasal toplamların ve vergisel toplamların heaplanıp, E-Arşiv ve E-Fatura ya gönderileck datanın son halinin, xml öncesi array datasının alıp bir değişkene atıyoruz ve artık bildirim aşamasına geçebiliriz.
257 | ```php
258 | setTotals()->getData();
261 | ```
262 |
263 | ## Servis Bağlantı İşlemleri
264 |
265 | Web servislerine bağlantı için TEST veya CANLI ortam username ve password bilgilerini tanımlıyoruz. Bu bilgiler qnbfinansbank tarafından alınır. Email atıp bilgileri alabilirsiniz.
266 | ```php
267 | setUsername("CANLI_VEYA_TEST_USERNAME")
272 | ->setpassword("CANLI_VEYA_TEST_USERNAME")
273 | ->setvergiTcKimlikNo("CANLI_VEYA_TEST_VERGI_KIMLIKNO")
274 | ->setUrl("CANLI_VEYA_TEST_URL")
275 | ->getConfig();
276 | ```
277 | **Parameters:**
278 |
279 | | Parametre | Açıklama |
280 | | --------------------------------------------| -------- |
281 | | setUsername | Belirlenen kullanıcı adınız (bildirimi yapacak firmanın qnbfinansbank hesap bilgisi) |
282 | | setpassword | Belirnenen şifreniz (bildirimi yapacak firmanın qnbfinansbank hesap bilgisi) |
283 | | setvergiTcKimlikNo | Vergi kimlik numaranız (bildirimi yapacak firmanın qnbfinansbank hesap bilgisi) |
284 | | setUrl | E-Arşiv veya E-Fatura, (test veya canlı) Web Servis Url si (qnbfinansbank tarafından alınır.) |
285 | | getConfig | Son olarak oluşturulan ayarların array olarak alıyoruz. |
286 |
287 | Test Url
288 |
289 | - E-Arşiv : https://earsivtest.efinans.com.tr/earsiv/ws/EarsivWebService?wsdl
290 | - E-Fatura : https://erpefaturatest.cs.com.tr:8443/efatura/ws/connectorService?wsdl
291 |
292 | ## E-Fatura İşlemleri
293 |
294 | E-Faturaya bildirim işlemlerini yapabilmek için class ı çağırıyoruz ve set işlemlerine başlıyoruz.
295 | ```php
296 | setConfig($options)
303 | ->setStart()
304 | ->setBelgeNo($belgeNo)
305 | ->setData($qnb_data)
306 | ->setEFatura();
307 |
308 | print $return->belgeOid; /* e faturadan bildirim sonrası dönen key */
309 | ```
310 | **REQUEST Parameters:**
311 |
312 | | Parametre | Açıklama |
313 | | --------------| -------- |
314 | | setConfig | Yukarıda ayarladığımız ayar bilgileri gönderiyoruz. |
315 | | setStart | Servise başlangıç tetiği veriyoruz.(ilgili ayarlara göre soap başlatır.) |
316 | | setBelgeNo | Varitabanınızda fatura Id si veya uniq bir değer olabilir. |
317 | | setData | Yukarıda ilk önce hazırladığıız datayı gönderiyoruz. |
318 | | setEFatura | Son olarak E-Fatura bildirim servisini çalıştırıyoruz. |
319 |
320 | **RESPONSE Parameters:**
321 |
322 | | Parametre | Açıklama |
323 | | --------------| -------- |
324 | | belgeOid | Bildirim sonrası bize qnbfinansbank tarafından gönderilen benzersiz bildirim keyi bu keyi kullanarak e fatura sorgulama işlemi yapacağız. |
325 |
326 |
327 | ## E-Arşiv İşlemleri
328 |
329 | E-Arşiv bildirim işlemlerini yapabilmek için class ı çağırıyoruz ve set işlemlerine başlıyoruz.
330 | ```php
331 | setConfig($options)
336 | ->setStart()
337 | ->setSube("DFLT")
338 | ->setKasa("DFLT")
339 | ->setData($qnb_data)
340 | ->setEArsiv();
341 |
342 | print ''; /* düzgün çıktı görseli için */
343 | print_r($return);
344 | ```
345 |
346 | **REQUEST Parameters:**
347 |
348 | | Parametre | Açıklama |
349 | | --------------| -------- |
350 | | setConfig | Yukarıda ayarladığımız ayar bilgileri gönderiyoruz. (eğer e arşiv için başka ayarlar varsa option değişkenini o ayarlara göre tekrar oluşturun.) |
351 | | setStart | Servise başlangıç tetiği veriyoruz.(ilgili ayarlara göre soap başlatır.) |
352 | | setSube | QNB Finansbank portal yapılandırma ayarlarında WEB SERVİS için tanımlanan Şube bilgisi |
353 | | setKasa | QNB Finansbank portal yapılandırma ayarlarında WEB SERVİS için tanımlanan Kasa bilgisi |
354 | | setData | Yukarıda ilk önce hazırladığıız datayı gönderiyoruz. |
355 | | setEArsiv | Son olarak E-Arşiv bildirim servisini çalıştırıyoruz. |
356 |
357 | **RESPONSE Parameters:**
358 |
359 | | Parametre | Açıklama |
360 | | ----------------------| -------- |
361 | | resultCode | İşlemin durum kodu başarılı için (AE00000) diğer kodlar için dokümantasyon inceleyin. |
362 | | resultText | İşlem sonucu mesajı |
363 | | resultExtra->entry | Başarılı olduğunda dönen kullanabileceğiniz parametreler array şeklide döner. |
364 | | --faturaURL | entry arrayi içinde fatura url si |
365 | | --uuid | entry arrayi içinde gönderdiğinzi UUID bilgisi |
366 | | --faturaNo | entry arrayi içinde sizin bildirdiğiniz veya otomatik bildirilmesini istediğiniz fatura no örn. TMA202000000001 |
367 |
368 |
369 | ## E-Fatura ve E-Arşiv Ek Methodlar
370 |
371 | E-Fatura veya E-Arşiv için ihtiyaca göre ek methodlar kullanabilirsiniz.
372 |
373 | #### - E-Fatura
374 | * **getFaturaNo()** : Portaldaki en son gönderilmiş fatura numaranıza göre sonraki fatura numarasını üretir.
375 |
376 | E-Fatura Numarası üretmek için getFaturaNo() Methodu ile geriye dönen değeri $ID değişkenine alıp başlangıç datasına gönderdiğimizde otomatik değil bizim gönderdiğimiz fatura No yu kabul eder.
377 | ```php
378 | setConfig($options)
383 | ->setStart()
384 | ->getFaturaNo("BASLANGIC_SERI_NO") ;
385 | ```
386 | **Parameters:**
387 |
388 | | Parametre | Açıklama |
389 | | ------------------------------------| -------- |
390 | | setConfig | Servis ayalarını set ediyoruz yukarıdaki gibi |
391 | | setStart | Servisi başlatıyoruz |
392 | | getFaturaNo | Fatura no üretmesi için başlangıç seri no gönderiyoruz örn. TRE |
393 |
394 | * **getEfaturaKullanicisi()** : İlgili kişinin vergi numarasından E-Fatura mükellefi olup olmadığı bilgisini getirir.
395 |
396 | Hazırladığımı datanın E-Fatura ya mı E-Arşiv emi gönderecileceğini tespit etmek için getEfaturaKullanicisi() methodu ile kontrol ediyoruz. Eğer (true veya 1) bir değer dönerse e fatura mükellefi demektir ve hazırladığımız datanın E-Fatura ya gönderileceği anlaşılmaktadır. Aksi durumda ise E-Arşive gönderebilirsiniz.
397 | ```php
398 | setConfig($options)
403 | ->setStart()
404 | ->getEfaturaKullanicisi("VERGI_VEYA_TC_KIMLIK_NO") ;
405 | ```
406 | **Parameters:**
407 |
408 | | Parametre | Açıklama |
409 | | ------------------------------------| -------- |
410 | | setConfig | Servis ayalarını set ediyoruz yukarıdaki gibi |
411 | | setStart | Servisi başlatıyoruz |
412 | | getEfaturaKullanicisi | E-Fatura mükellefimi değilmi öğrenebilmek için fatura sahibinin TC veya VERGİ KİMLİK NO su. |
413 |
414 |
415 | #### - E-Arşiv
416 |
417 | * **getFaturaNo()** : En Son üretilen e arşiv fatura nosu her çalıştığında otomatik olarak counter artarak döner.
418 |
419 | E-Arşiv Numarası üretmek için getFaturaNo() Methodu ile geriye dönen değeri $ID değişkenine alıp başlangıç datasına gönderdiğimizde otomatik değil bizim gönderdiğimiz fatura No yu kabul eder. E-Arşiv olduğu için her çalıştırıldığında yeni bir numara üretir.
420 | ```php
421 | setConfig($options)
426 | ->setStart()
427 | ->setUuid($data->getUuid())
428 | ->getFaturaNo("BASLANGIC_SERI_NO");
429 | ```
430 | **Parameters:**
431 |
432 | | Parametre | Açıklama |
433 | | ------------------------------------| -------- |
434 | | setConfig | Servis ayalarını set ediyoruz yukarıdaki gibi |
435 | | setStart | Servisi başlatıyoruz |
436 | | setUuid | Başlangıç datası hazırladığımızdaki uuid oluşturma işlemi bu uid le sonrasında e arşiv faturamınız bildireceğiz. |
437 | | getFaturaNo | Fatura no üretmesi için başlangıç seri no gönderiyoruz örn. TRA |
438 |
439 |
440 | ## Otomatik Bildirim İşlemleri (Hazırlanıyor..)
441 |
442 | E-Fatura veya E-Arşiv gönderisinin otomatik bir şekilde tespit edilip tek bir class üzerinden göndermek siterseniz aşağıdaki yöntemi kullanabilirsiniz.
443 |
444 |
445 | ## Destek
446 |
447 | Bir hata bulduğunuzu düşünüyorsanız, lütfen [GitHub issue tracker](https://github.com/muhittingulap/qnbfinansbank/issues) kullanarak bildirin,
448 | ya da daha iyisi, kütüphaneyi çatallayın ve bir çekme isteği gönderin.
449 |
450 | ## License
451 |
452 | MIT Lisansı (MIT). Daha fazla bilgi için lütfen [License File](LICENSE) bakın.
453 |
--------------------------------------------------------------------------------