|
|
@@ -0,0 +1,192 @@
|
|
|
+<?php
|
|
|
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
|
|
|
+ *
|
|
|
+ * Value Add Tax (VAT) library
|
|
|
+ * Author: Mariusz Muszyński
|
|
|
+ *
|
|
|
+ * Public static methods:
|
|
|
+ *
|
|
|
+ * public bool VAT::validateNIP ( string $nip )
|
|
|
+ * Tells whether the given string is a correct polish tax identification number (TIN/NIP)
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ *
|
|
|
+ * nip
|
|
|
+ * Polish tax identification number
|
|
|
+ *
|
|
|
+ * Public dynamic methods:
|
|
|
+ *
|
|
|
+ * public VAT::__construct ( void )
|
|
|
+ * Creates a new VAT object.
|
|
|
+ *
|
|
|
+ * public bool VAT::isActiveVatPayer ( string $nip )
|
|
|
+ * Tells whether the given NIP belongs to an active VAT payer
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ *
|
|
|
+ * nip
|
|
|
+ * Polish tax identification number
|
|
|
+ *
|
|
|
+ * public mixed VAT::getMessage ( [ bool $whole = false ] )
|
|
|
+ * Returns last message after using VAT::isActiveVatPayer
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ *
|
|
|
+ * whole
|
|
|
+ * When TRUE, whole message is returned as an array
|
|
|
+ * When FALSE, only main message is returned as a string
|
|
|
+ *
|
|
|
+ * HINT:
|
|
|
+ * It's faster to create one object and do many executes of VAT::isActiveVatPayer method
|
|
|
+ * than creating separate objects for each VAT::isActiveVatPayer execute.
|
|
|
+ *
|
|
|
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
+ *
|
|
|
+ * An example of usage:
|
|
|
+ *
|
|
|
+ * $vat = new VAT();
|
|
|
+ * $nip_array = ["5932268672", "6040018535"];
|
|
|
+ * foreach ($nip_array as $nip)
|
|
|
+ * {
|
|
|
+ * echo $nip . " - ";
|
|
|
+ * try
|
|
|
+ * {
|
|
|
+ * $result = $vat->isActiveVatPayer($nip);
|
|
|
+ * if ($result) echo "is active VAT payer";
|
|
|
+ * else echo "is not active VAT payer";
|
|
|
+ * echo " (" . $vat->getMessage() . ")\n";
|
|
|
+ * }
|
|
|
+ * catch (Exception $e)
|
|
|
+ * {
|
|
|
+ * echo "An error occurred (" . $e->getMessage() . ")\n";
|
|
|
+ * }
|
|
|
+ * }
|
|
|
+ *
|
|
|
+\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
+
|
|
|
+Class VAT {
|
|
|
+
|
|
|
+ private $ch, $dom, $headers;
|
|
|
+ private $cookies = "php://memory";
|
|
|
+ private $message = [""];
|
|
|
+ private $initialized = false;
|
|
|
+
|
|
|
+ private function getHeaders($ch, $header) {
|
|
|
+ $len = strlen($header);
|
|
|
+ $header = explode(':', $header, 2);
|
|
|
+ if (count($header) < 2) return $len;
|
|
|
+ $this->headers[trim($header[0])] = trim($header[1]);
|
|
|
+ return $len;
|
|
|
+ }
|
|
|
+
|
|
|
+ private function checkHeaders() {
|
|
|
+ if (!(isset($this->headers['Fast-Ver-Last']) && $this->headers['Fast-Ver-Last'])) throw new Exception("Błąd danych ze strony Ministerstwa Finansów");
|
|
|
+ }
|
|
|
+
|
|
|
+ public static function validateNIP($nip) {
|
|
|
+ $prefix = substr($nip, 0, 2);
|
|
|
+ if (!is_numeric($prefix)) $nip = substr($nip, 2);
|
|
|
+ else $prefix = null;
|
|
|
+ if ($prefix && $prefix != "PL") return false;
|
|
|
+ if (strlen($nip) != 10 || (!is_numeric($nip))) return false;
|
|
|
+ $control = (($nip[0] * 6 + $nip[1] * 5 + $nip[2] * 7 + $nip[3] * 2 + $nip[4] * 3 + $nip[5] * 4 + $nip[6] * 5 + $nip[7] * 6 + $nip[8] * 7) % 11 ) % 10;
|
|
|
+ return ($control == $nip[9]);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static function paramsUrlEncode($params) {
|
|
|
+ $array = [];
|
|
|
+ foreach ($params as $param => $value) $array[] = $param . "=" . urlencode($value);
|
|
|
+ return implode("&", $array);
|
|
|
+ }
|
|
|
+
|
|
|
+ private function execute() {
|
|
|
+ $this->headers = [];
|
|
|
+ $result = curl_exec($this->ch);
|
|
|
+ if (curl_getinfo($this->ch)['http_code'] != 200) throw new Exception("Błąd połączenia ze stroną Ministerstwa Finansów");
|
|
|
+ return $result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private function initialize() {
|
|
|
+ $this->ch = curl_init();
|
|
|
+ curl_setopt($this->ch, CURLOPT_URL, "http://www.finanse.mf.gov.pl/web/wp/pp/sprawdzanie-statusu-podmiotu-w-vat");
|
|
|
+ curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
+ curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, true);
|
|
|
+ curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, false);
|
|
|
+ curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
|
+ curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, 10);
|
|
|
+ curl_setopt($this->ch, CURLOPT_COOKIEJAR, $this->cookies);
|
|
|
+ curl_setopt($this->ch, CURLOPT_COOKIEFILE, $this->cookies);
|
|
|
+ curl_setopt($this->ch, CURLOPT_HEADERFUNCTION, "self::getHeaders");
|
|
|
+ $this->execute();
|
|
|
+
|
|
|
+ $this->checkHeaders();
|
|
|
+ $params = [
|
|
|
+ "Load" => "1",
|
|
|
+ "FAST_VERLAST__" => $this->headers['Fast-Ver-Last'],
|
|
|
+ ];
|
|
|
+ curl_setopt($this->ch, CURLOPT_URL, "https://ppuslugi.mf.gov.pl/_/?" . self::paramsUrlEncode($params));
|
|
|
+ $this->execute();
|
|
|
+
|
|
|
+ curl_setopt($this->ch, CURLOPT_URL, "https://ppuslugi.mf.gov.pl/_/EventOccurred");
|
|
|
+ $this->initialized = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private function reinitialize() {
|
|
|
+ $this->checkHeaders();
|
|
|
+ $params = [
|
|
|
+ "DOC_MODAL_ID__" => "0",
|
|
|
+ "EVENT__" => "b-9",
|
|
|
+ "FAST_VERLAST__" => $this->headers['Fast-Ver-Last'],
|
|
|
+ ];
|
|
|
+ curl_setopt($this->ch, CURLOPT_POSTFIELDS, self::paramsUrlEncode($params));
|
|
|
+ $this->execute();
|
|
|
+ }
|
|
|
+
|
|
|
+ private function getResult($result) {
|
|
|
+ $search = ['/\<br(\s*)?\/?\>/i', '/[[:blank:]]{2,}/', '/[\x00-\x1F\x80-\xFF]/'];
|
|
|
+ $replace = ['|', ' ', ''];
|
|
|
+ $json = preg_replace($search, $replace, $result);
|
|
|
+ $array = json_decode($json, true);
|
|
|
+ if (!($array && isset($array['html']))) throw new Exception("Błąd danych ze strony Ministerstwa Finansów");
|
|
|
+ $html = $array['html'];
|
|
|
+ $this->dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
|
|
|
+ $this->message = array_map("trim", array_values(array_diff(explode("|", $this->dom->getElementById("caption2_b-3")->textContent), [''])));
|
|
|
+ if (!$this->message) throw new Exception("Błąd danych ze strony Ministerstwa Finansów");
|
|
|
+ switch ($this->message[0]) {
|
|
|
+ case "Podmiot o podanym identyfikatorze podatkowym NIP jest zarejestrowany jako podatnik VAT czynny" : return true;
|
|
|
+ case "Podmiot o podanym identyfikatorze podatkowym NIP nie jest zarejestrowany jako podatnik VAT" : return false;
|
|
|
+ default: throw new Exception("Nieznany rezultat");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public function getMessage($whole = false) {
|
|
|
+ if ($whole) return $this->message;
|
|
|
+ else return $this->message[0];
|
|
|
+ }
|
|
|
+
|
|
|
+ public function isActiveVatPayer($nip) {
|
|
|
+ $nip = str_replace("-", "", trim($nip));
|
|
|
+ if (!$this->validateNIP($nip)) throw new Exception("Błędny NIP");
|
|
|
+
|
|
|
+ if (!$this->initialized) $this->initialize();
|
|
|
+ else $this->reinitialize();
|
|
|
+
|
|
|
+ $this->checkHeaders();
|
|
|
+ $params = [
|
|
|
+ "b-7" => $nip,
|
|
|
+ "DOC_MODAL_ID__" => "0",
|
|
|
+ "EVENT__" => "b-8",
|
|
|
+ "FAST_VERLAST__" => $this->headers['Fast-Ver-Last'],
|
|
|
+ ];
|
|
|
+ curl_setopt($this->ch, CURLOPT_POSTFIELDS, self::paramsUrlEncode($params));
|
|
|
+ return $this->getResult($this->execute());
|
|
|
+ }
|
|
|
+
|
|
|
+ function __construct() {
|
|
|
+ $this->dom = new DOMDocument();
|
|
|
+ }
|
|
|
+
|
|
|
+ function __destruct() {
|
|
|
+ curl_close($this->ch);
|
|
|
+ }
|
|
|
+}
|