onayOlustur([ * 'sablon' => 'dis-tedavi-plani', * 'imzaci' => ['ad' => 'Ayşe Yılmaz', 'telefon' => '05321234567'], * 'veriler' => ['tedavi' => '2 adet implant', 'tutar' => '45.000 TL', 'odeme' => '6 taksit', 'sure' => '3 ay'], * 'refNo' => 'HASTA-1029', * ]); * echo $onay['onayLinki']; * * Webhook: * $govde = file_get_contents('php://input'); * if (!Nitelora::webhookDogrula($govde, $_SERVER['HTTP_X_NITELORA_IMZA'] ?? '', $webhookSecret)) { http_response_code(401); exit; } * $olay = json_decode($govde, true); // ['olay' => 'onay.tamamlandi', 'id' => ..., 'refNo' => ..., 'pdfUrl' => ...] */ class NiteloraHatasi extends Exception { public $durum; public $kod; public $alan; public function __construct($durum, $kod, $mesaj, $alan = null) { parent::__construct($mesaj); $this->durum = $durum; $this->kod = $kod; $this->alan = $alan; } } class Nitelora { private $taban; private $anahtar; private $klinikId; /** $klinikId: yalnızca platform anahtarı (plt_) ile */ public function __construct($tabanUrl, $anahtar, $klinikId = null) { $this->taban = rtrim($tabanUrl, '/'); $this->anahtar = $anahtar; $this->klinikId = $klinikId; } // Onay linki public function onayOlustur(array $istek, $idempotencyKey = null) { return $this->istek('POST', '/v1/onaylar', $istek, $idempotencyKey); } public function onay($id) { return $this->istek('GET', "/v1/onaylar/$id"); } public function onayPdf($id) { return $this->istek('GET', "/v1/onaylar/$id/pdf", null, null, true); } public function onayKanit($id) { return $this->istek('GET', "/v1/onaylar/$id/kanit"); } public function onayIptal($id) { return $this->istek('POST', "/v1/onaylar/$id/iptal", new stdClass()); } // Tıbbi rıza (SBYS): hasta kodu hekime söyler, hekim girer public function kodGonder($id, $amac) { return $this->istek('POST', "/v1/onaylar/$id/kod", ['amac' => $amac]); } public function telefonDogrula($id, $kod, array $hekim) { return $this->istek('POST', "/v1/onaylar/$id/telefon-dogrula", ['kod' => $kod, 'hekim' => $hekim]); } public function rizaKaydet($id, $kod, array $hekim) { return $this->istek('POST', "/v1/onaylar/$id/riza", ['kod' => $kod, 'hekim' => $hekim]); } // PDF imzalatma public function zarfOlustur($baslik, $pdfYolu, array $imzacilar, array $alanlar, $sirali = false, $refNo = null, $idempotencyKey = null) { return $this->istek('POST', '/v1/zarflar', [ 'baslik' => $baslik, 'belgeAdi' => basename($pdfYolu), 'belge' => base64_encode(file_get_contents($pdfYolu)), 'imzacilar' => $imzacilar, 'alanlar' => $alanlar, 'sirali' => $sirali, 'refNo' => $refNo, ], $idempotencyKey); } public function zarf($id) { return $this->istek('GET', "/v1/zarflar/$id"); } public function imzaliPdf($id) { return $this->istek('GET', "/v1/zarflar/$id/pdf", null, null, true); } public function sablondanGonder($sablonId, array $imzacilar, $refNo = null, $idempotencyKey = null) { return $this->istek('POST', "/v1/zarf-sablonlari/$sablonId/gonder", ['imzacilar' => $imzacilar, 'refNo' => $refNo], $idempotencyKey); } public function topluGonder($sablonId, array $satirlar, $idempotencyKey = null) { return $this->istek('POST', "/v1/zarf-sablonlari/$sablonId/toplu", ['satirlar' => $satirlar], $idempotencyKey); } private function istek($yontem, $yol, $govde = null, $idempotencyKey = null, $ham = false) { $basliklar = ['Authorization: Bearer ' . $this->anahtar, 'Accept: application/json']; if ($this->klinikId) $basliklar[] = 'X-Klinik-Id: ' . $this->klinikId; if ($idempotencyKey) $basliklar[] = 'Idempotency-Key: ' . $idempotencyKey; $c = curl_init($this->taban . $yol); curl_setopt_array($c, [CURLOPT_CUSTOMREQUEST => $yontem, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 60]); if ($govde !== null) { $basliklar[] = 'Content-Type: application/json'; curl_setopt($c, CURLOPT_POSTFIELDS, json_encode($govde, JSON_UNESCAPED_UNICODE)); } curl_setopt($c, CURLOPT_HTTPHEADER, $basliklar); $yanit = curl_exec($c); if ($yanit === false) { $h = curl_error($c); curl_close($c); throw new NiteloraHatasi(0, 'baglanti', $h); } $durum = curl_getinfo($c, CURLINFO_HTTP_CODE); curl_close($c); if ($durum >= 400) { $j = json_decode($yanit, true); $h = $j['hata'] ?? ['kod' => 'bilinmeyen', 'mesaj' => $yanit]; throw new NiteloraHatasi($durum, $h['kod'], $h['mesaj'], $h['alan'] ?? null); } return $ham ? $yanit : json_decode($yanit, true); } /** X-Nitelora-Imza: t={unix},v1={hex HMAC-SHA256(secret, t . "." . hamGovde)} */ public static function webhookDogrula($hamGovde, $imzaBasligi, $webhookSecret, $tolerans = 300) { $p = []; foreach (explode(',', $imzaBasligi) as $parca) { $kv = explode('=', $parca, 2); if (count($kv) === 2) $p[trim($kv[0])] = trim($kv[1]); } if (!isset($p['t'], $p['v1']) || !ctype_digit($p['t'])) return false; if (abs(time() - (int)$p['t']) > $tolerans) return false; $beklenen = hash_hmac('sha256', $p['t'] . '.' . $hamGovde, $webhookSecret); return hash_equals($beklenen, strtolower($p['v1'])); } }