<?php
declare(strict_types=1);
error_reporting(E_ALL);
ini_set('display_errors', '1');
session_start();
header('Content-Type: application/json; charset=utf-8');
class HttpClient
{
private string $url;
private array $headers;
private string $cookieString;
public function __construct(string $url)
{
$this->url = $url;
$this->headers = [
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Language: en-US,en;q=0.9',
'Cache-Control: max-age=0',
'Connection: keep-alive',
'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',
];
$this->cookieString = 'language=tr_TR.UTF-8; w3p=1943251136.20480.0000; _uid=1740222152-6371b0c0-9419-485e-abf4-f1a4d9de5c3b; ridbb=WyI4MjE2YjU0YWRkN2YxOTkwNDU2NmZjMzgzZTIzZGRmZGQ1MTVmYmIxZTIiXQ%3D%3D; TURKIYESESSIONID=ppvh79th8g07afbs5f9geuvefd; TS01c2accc=015c1cbb6d1a639504e1b29b05b98286d479274aaf94c82d859307282d1c86808d72742a98623567bf8f57c330e2ce30a706ea5e64; _lastptts=1740223200';
}
public function get(string $url): string
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers);
curl_setopt($ch, CURLOPT_COOKIE, $this->cookieString);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
public function post(string $url, array $postData): string
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
curl_setopt($ch, CURLOPT_COOKIE, $this->cookieString);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
if ($response === false) {
$error = curl_error($ch);
curl_close($ch);
throw new Exception("cURL error: $error");
}
curl_close($ch);
return $response;
}
public function getUrl(): string
{
return $this->url;
}
}
class PharmacyScraper
{
private HttpClient $client;
public function __construct(HttpClient $client)
{
$this->client = $client;
}
public function fetchToken(): ?string
{
$response = $this->client->get($this->client->getUrl());
preg_match('/<input type="hidden" name="token" value="([^"]+)"/', $response, $matches);
return $matches[1] ?? null;
}
public function submitSearchForm(string $token, string $plateCode, string $date): void
{
$postData = [
'plakaKodu' => $plateCode,
'nobetTarihi' => $date,
'token' => $token,
'btn' => 'Sorgula'
];
$this->client->post($this->client->getUrl() . '?submit', $postData);
}
public function fetchPharmacies(): array
{
$response = $this->client->get($this->client->getUrl() . '?nobetci=Eczaneler');
$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML($response);
libxml_clear_errors();
$table = $dom->getElementById('searchTable');
if (!$table) return [];
$rows = $table->getElementsByTagName('tr');
$pharmacies = [];
foreach ($rows as $row) {
$cols = $row->getElementsByTagName('td');
if ($cols->length > 0) {
$pharmacies[] = [
'name' => trim($cols->item(0)->textContent),
'district' => trim($cols->item(1)->textContent),
'phone' => trim(str_replace("Ara", "", $cols->item(2)->textContent)),
'address' => trim($cols->item(3)->textContent)
];
}
}
return $pharmacies;
}
}
try {
$time_left = 5 - (time() - $_SESSION['last_request']);
if (isset($_SESSION['last_request']) && $time_left > 0) {
throw new Exception("Rate limit exceeded. Please wait $time_left seconds before trying again.");
}
$_SESSION['last_request'] = time();
$plateCode = filter_input(INPUT_GET, 'plateCode', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$date = filter_input(INPUT_GET, 'date', FILTER_SANITIZE_FULL_SPECIAL_CHARS) ?: date('d/m/Y');
if (!$plateCode || !is_numeric($plateCode)) {
throw new Exception('City/Plate code invalid!');
}
if (!preg_match('/^\d{2}\/\d{2}\/\d{4}$/', $date)) {
throw new Exception('Date format is invalid (ex: 22/02/2025)');
}
$client = new HttpClient("https://turkiye.gov.tr/saglik-titck-nobetci-eczane-sorgulama");
$scraper = new PharmacyScraper($client);
$token = $scraper->fetchToken();
if (!$token) {
throw new Exception('Failed to access the verification token!');
}
$scraper->submitSearchForm($token, $plateCode, $date);
$pharmacies = $scraper->fetchPharmacies();
echo json_encode(['status' => true, 'data' => $pharmacies], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
} catch (Exception $e) {
echo json_encode(['status' => false, 'error' => $e->getMessage()], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}