initCertDir(); $this->checkFiles(); $this->ntakLogger = NtakLogger::getInstance(); } /** * */ private function checkFiles(): void { $this->checkCertFile(self::CERT_PEM); $this->checkCertFile(self::CERT_B64); } /** * */ private function checkCertFile(string $file): void { $fullPath = $this->certDir.$file; if (file_exists($fullPath)) { if (!is_file($fullPath)) { throw new \Exception('CERT FILE IS NOT FILE ('.$fullPath.')'); } if (!is_readable($fullPath)) { throw new \Exception('CERT FILE IS NOT READABLE ('.$fullPath.')'); } } else { throw new \Exception('CERT FILE MISSING ('.$fullPath.')'); } } /** * */ private function initCertDir(): void { $certPath = [ __DIR__, '..', '..', 'cert' ]; $this->certDir = implode(DIRECTORY_SEPARATOR, $certPath).DIRECTORY_SEPARATOR; } /** * */ public function sendToServer(array $data): NtakSendResult { $this->postFields = $data; $logData = json_encode($data); $invoiceRefs = array_map(function ($item) { return $item['tranzakcioAzonosito']; }, $data['tranzakcioAdatok']); $this->ntakLogger->logIntoFile($logData, LOG_INFO); $curl = $this->getCurlResource(NtakConfig::URL_SALE); $response = curl_exec($curl); $this->ntakLogger->logIntoFile($response, LOG_INFO); $ntakSendResult = new NtakSendResult; if ($response) { $resultStatus = 0; $result = json_decode($response, true); if (!empty($result['feldolgozasAzonosito'])) { $ntakSendResult->ntakId = $result['feldolgozasAzonosito']; $checkResult = $this->check($result['feldolgozasAzonosito']); if (!empty($checkResult['uzenetValaszok'][0]['statusz'])) { $resultStatus = NtakConst::getDbResponseStatusByStatus($checkResult['uzenetValaszok'][0]['statusz']); $ntakSendResult->ntakStatus = $checkResult['uzenetValaszok'][0]['statusz']; $ntakSendResult->status = $resultStatus; } $this->ntakLogger->logIntoFile("Invoice sent successfully to NTAK (Ref: ".implode(', ', $invoiceRefs).")", LOG_INFO); $this->ntakLogger->logIntoFile("Invoice data: {$logData}", LOG_INFO); $this->ntakLogger->massDbLogByInvoiceRef($invoiceRefs, $resultStatus, curl_error($curl), $logData, $result['feldolgozasAzonosito']); } else { $this->ntakLogger->logIntoFile("Invoice sent failed to NTAK (Ref: ".implode(', ', $invoiceRefs).")", LOG_INFO); $this->ntakLogger->logIntoFile($response, LOG_INFO); $this->ntakLogger->massDbLogByInvoiceRef($invoiceRefs, $resultStatus, $response, $logData); } } else { $this->ntakLogger->logIntoFile("Cannot send invoice (Ref: ".implode(', ', $invoiceRefs).")", LOG_ALERT); $this->ntakLogger->massDbLogByInvoiceRef($invoiceRefs, NtakLog::STATUS_CANCELED, curl_error($curl), $logData); } curl_close($curl); return $ntakSendResult; } /** * @var bool $send If false, not send and return with the generated data */ public function send(NtakInvoice $ntakInvoice, bool $send = true): NtakSendResult { $this->ntakLogger->logIntoFile("Send invoice to NTAK (Ref: {$ntakInvoice->ref})", LOG_INFO); $ntakSendResult = new NtakSendResult; $this->invoice = $ntakInvoice; $this->date = gmdate(DATE_RFC3339, time()); $this->initServiceProvider(); $this->initSenderData(); $this->initMessageData(); $this->setPostFieldsProgramData(); $this->setPostFieldsTransactionData(); if ($ntakInvoice->array_options['options_ntak_status'] == NtakConst::INVOICE_SENDING_RESPONSE_STATUS_SEND_AGAIN) { $origData = $this->ntakLogger->getOrigSentData($ntakInvoice->array_options['options_ntak_id']); if (!empty($origData)) { $this->postFields = $origData; } } if ($send) { //echo json_encode($this->postFields); die; //print_r($this->postFields); die; $ntakSendResult = $this->sendToServer($this->postFields); } else { $ntakSendResult->generatedData = $this->postFields; } return $ntakSendResult; } /** * */ private function getCurlResource(string $url) { $curl = curl_init(); curl_setopt_array( $curl, [ CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_SSLCERT => $this->certDir.self::CERT_PEM, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => json_encode($this->postFields), CURLOPT_POST => 1, CURLOPT_HTTPHEADER => $this->getHttpHeader(), ] ); return $curl; } /** * */ private function base64url_encode($data) { return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); } /** * */ /* private function base64url_decode($data) { return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT)); } */ /** * */ private function setPostFieldsTransactionData(): void { //$prices = $this->invoice->getRoundedTransactionPrices(); $prices = $this->invoice->getTotalTransaction(); $ticketsSold = $this->invoice->ntakSoldTickets(); $paymentMethods = $this->invoice->ntakPaymentMethods(); if (!empty($ticketsSold)) { //$prices = array_sum(array_column($ticketsSold, 'bruttoAr')); array_walk($paymentMethods, function (&$item) use ($prices) { if (array_key_exists('fizetettOsszegHUF', $item) && $item['fizetesiMod'] == NtakConst::PAYMENT_METHOD_CASH_EUR) { //$item['fizetettOsszegHUF'] = $item['']; } }); $this->postFields['tranzakcioAdatok'] = [ [ 'tranzakcioAzonosito' => $this->invoice->ref, 'tranzakcioIdopontja' => NtakDate::timestampToRfc3339($this->invoice->date_modification), 'osszesitett' => false, 'tranzakcioVegosszege' => $prices, //$prices['rounded'], 'ertekesitesiCsatorna' => NtakConst::SALES_CHANNEL_LOCAL, // ITT TISZTAZNI, HOGY MIT KELL A MOKUS ES A HOTEL ESETEN 'fizetesiModok' => $paymentMethods, //$this->invoice->ntakPaymentMethods(), 'latogatoiAdatok' => $this->invoice->ntakCustomerData(), 'eladottJegyek' => $ticketsSold, //$this->invoice->ntakSoldTickets(), 'egyebTetelek' => $this->invoice->ntakDiscount() ] ]; } } /** * */ private function setPostFieldsProgramData(): void { $this->postFields['programAdatok'] = $this->invoice->ntakProgramDetails(); } /** * */ private function initMessageData(): void { $this->postFields['uzenetAdatok'] = [ 'uzenetKuldesIdeje' => $this->date ]; } /** * */ private function initSenderData(): void { $this->postFields['kuldoRendszerAdatok'] = [ 'tssRendszerNTAKAzonosito' => NtakConfig::TSS_ID, 'tssRendszerVerzioszam' => NtakConfig::TSS_VERSION ]; } /** * */ private function initServiceProvider(): void { $this->postFields['szolgaltatoAdatok'] = [ 'adoszam' => NtakConfig::TAX_NUMBER, 'szolgHelyRegisztraciosSzam' => NtakConfig::REGISTRATION_NUMBER ]; } /** * */ private function getHttpHeader(): array { $header = [ "alg" => "RS256" ]; $headerBase64URLencodedValue = 'eyJhbGciOiJSUzI1NiJ9'; // CERT file $filenameCert = $this->certDir.self::CERT_B64; $handle = fopen($filenameCert, 'r'); $certificateStr = fread($handle, filesize($filenameCert)); fclose($handle); $headerBaseUrlEnc = json_encode($header); $token = $this->base64url_encode($headerBaseUrlEnc).'.'.$this->base64url_encode(json_encode($this->postFields)); // a json adat maga // PEM file $filenameSslCert = $this->certDir.self::CERT_PEM; $fileContent = file_get_contents($filenameSslCert); $privateKey = openssl_pkey_get_private($fileContent); openssl_sign("$token", $signature, $privateKey, "sha256"); $signatureBase64 = $this->base64url_encode($signature); $payloadBase64URLencodedValue = ''; return [ 'Content-Type: application/json', 'x-jws-signature: '.$headerBase64URLencodedValue.'.'.$payloadBase64URLencodedValue.'.'.$signatureBase64, 'x-certificate: '.$certificateStr ]; } /** * */ public function validate(int $ticketId, string $factureRef, string $ntakId, string $productRef, string $productDate, string $logDate, int $factureId): void { $this->ntakLogger->logIntoFile('Validate start', LOG_INFO); $this->date = gmdate(DATE_RFC3339, time()); $this->initServiceProvider(); $this->initSenderData(); $this->initMessageData(); $this->postFields['jegyek'] = []; $this->postFields['jegyek'][] = [ 'ervenyesitesiAzonosito' => $ntakId, 'belepettSzemelyekSzama' => 1, 'ervenyesitesIdopontja' => NtakDate::timestampToRfc3339(strtotime($logDate)), 'felhasznalasModja' => NtakConst::TICKET_USE_METHOD_ENTRY, 'jegyAzonosito' => 'J-'.$factureRef, 'programazonosito' => [ 'tssProgramAzonosito' => $productRef, //'utolsoModositasIdeje' => NtakDate::timestampToRfc3339(strtotime($productDate)) 'utolsoModositasIdeje' => NtakDate::timestampToRfc3339(strtotime('today midnight')) ] ]; $curl = $this->getCurlResource(NtakConfig::URL_VALIDATE); $response = curl_exec($curl); $logData = json_encode($this->postFields); if ($response) { $result = json_decode($response, true); if (array_key_exists('feldolgozasAzonosito', $result)) { $this->ntakLogger->logIntoFile("Validate sent successfully to NTAK (Ticket ID: {$ticketId})", LOG_INFO); } else { $this->ntakLogger->logIntoFile("Validate sent failed to NTAK (Ticket ID: {$ticketId})", LOG_ERR); $this->ntakLogger->logIntoFile($logData, LOG_ERR); $this->ntakLogger->logIntoFile($response, LOG_ERR); } } else { $this->ntakLogger->logIntoFile("Validate sent failed to NTAK (Ticket ID: {$ticketId})", LOG_ERR); $this->ntakLogger->logIntoFile($logData, LOG_ERR); } curl_close($curl); } /** * */ public function checkWithLog(string $ntakProcessId, int $invoiceId): array { $this->ntakLogger->logIntoFile("Check with log start ({$ntakProcessId})", LOG_INFO); $resultStatus = NtakLog::STATUS_DRAFT; $checkResult = $this->check($ntakProcessId); if (!empty($checkResult['uzenetValaszok'][0]['statusz'])) { $resultStatus = NtakConst::getDbResponseStatusByStatus($checkResult['uzenetValaszok'][0]['statusz']); } $this->ntakLogger->logIntoFile("Check successfully at NTAK (NTAK ID: {$ntakProcessId})", LOG_INFO); $this->ntakLogger->logIntoDb($invoiceId, $resultStatus, '', '', $ntakProcessId); $this->ntakLogger->logIntoFile("Check with log end ({$ntakProcessId})", LOG_INFO); return $checkResult; } /** * */ public function check(string $ntakProcessId): array { $result = []; $this->ntakLogger->logIntoFile("Check sent data ({$ntakProcessId})", LOG_INFO); $this->postFields = []; $this->date = gmdate(DATE_RFC3339, time()); $this->initServiceProvider(); $this->initSenderData(); $this->initMessageData(); $this->postFields['feldolgozasAzonositok'] = [ $ntakProcessId ]; $this->ntakLogger->logIntoFile(json_encode($this->postFields), LOG_INFO); $curl = $this->getCurlResource(NtakConfig::URL_CHECK); $response = curl_exec($curl); if ($response) { $result = json_decode($response, true); $this->ntakLogger->logIntoFile("Check invoice process at NTAK (NTAK process ID: {$ntakProcessId})", LOG_INFO); $this->ntakLogger->logIntoFile($response, LOG_INFO); } else { $this->ntakLogger->logIntoFile("Cannot check invoice process at NTAK (NTAK process ID: {$ntakProcessId})", LOG_ALERT); } curl_close($curl); return $result; } }