WISECP'te bir iletişim formunu destek talebine çevirmek için Yönetim API'sinin POST /api/v1/admin/tickets ucu (Tickets/CreateTicket) kullanılır. Bu uç client_id, subject ve message alanlarını zorunlu tutar; yani talep mutlaka kayıtlı bir müşteriye açılır. Belgelenmiş bir misafir talebi ucu yoktur. Formu dolduran kişi kayıtlı değilse ya önce müşteri kaydı oluşturursunuz ya da WISECP'nin kendi iletişim formunu ve Destek Talebine Dönüştür akışını kullanırsınız.

Bu rehberde sitenizdeki formdan gelen veriyi sunucu tarafında doğrulayıp, e-postayla müşteriyi bulan ve talebi açan kısa bir PHP betiği yazıyoruz. API anahtarı hiçbir zaman tarayıcıya gitmez. API'nin genel yapısı, anahtar üretimi ve hata kodları için önce WISECP API kullanımı yazısını okumanızı öneririz. Panel tarafındaki destek sistemi için WISECP destek talebi sistemi yazısına bakabilirsiniz.

Akış: formdan talebe

Akış: formdan talebe: Ziyaretçi sitenizdeki formu doldurur; form kendi sunucunuzdaki bir betiğe POST..., Betik CSRF, honeypot ve hız kontrollerini yapar, girdileri doğrular...
  • Ziyaretçi sitenizdeki formu doldurur; form kendi sunucunuzdaki bir betiğe POST eder.
  • Betik CSRF, honeypot ve hız kontrollerini yapar, girdileri doğrular.
  • Betik WISECP'de bu e-postaya ait müşteriyi arar (GET /clients?search=...).
  • Müşteri varsa POST /tickets ile talep açılır; WISECP talebi açtığı için müşteriye bildirim gider.
  • Müşteri yoksa belgelenmiş iki yoldan birini seçersiniz (aşağıda).

API anahtarını hazırlama: en dar izin

Panelde Ayarlar > Genel Ayarlar > API sekmesinde yeni bir kimlik bilgisi oluşturun ve yalnızca bu iş için gereken izinleri işaretleyin. İzin verilen IP adresleri alanına formu işleyen web sunucunuzun IP'sini yazın; böylece anahtar sızsa bile başka bir yerden kullanılamaz.

İzinNeden gerekli
Tickets/CreateTicketTalebi açmak için
Clients/GetClientsE-postaya göre müşteriyi bulmak için
Tickets/GetTicketDepartmentsDepartman numarasını bir kez okumak için (kurulumda kullanılır, sonra kaldırılabilir)
Clients/CreateClientYalnızca kayıtsız ziyaretçiye hesap açmayı seçerseniz

Departman numarasını koda gömmeden önce listeden okuyun. Belge, departmanların kurulumdan kuruluma değiştiğini ve koda gömülmemesi gerektiğini söyler:

bash
curl 'https://panel.ornek.com/api/v1/admin/tickets/departments' \
  -H "Authorization: Bearer $WISECP_API_KEY"
# data[]: id, name, description, icon, icon_type

Öncelik değerleri için GET /api/v1/admin/tickets/priorities ucu value ve label çiftleri döndürür. Bulduğunuz departman numarasını WISECP_DEPT_ID gibi bir ortam değişkenine yazın.

Talep açma ucu: alanlar ve yanıt

Talep açma ucu: alanlar ve yanıt: client_id, subject, message, department_id

POST /api/v1/admin/tickets belgeye göre personel adına bir müşteriye talep açar ve ilk mesajı yazar. Gövde alanları şunlardır:

AlanTipAçıklama
client_idint, zorunluTalebin sahibi müşteri
subjectstring, zorunluTalebin konusu
messagestring, zorunluİlk mesaj; müşteri verisiyle dolan yer tutucular kullanılabilir
department_idintTalebin departmanı
priorityintÖncelik (tickets/priorities listesinden)
statusstringopen, waiting, process, replied, solved
service_idintİlişkili hizmet; müşterinin kendi hizmeti olmalı
assigned_idintAtanacak personel; atanırsa ona da haber gider
custom_status_idintKuruluma özel durum
lockedboolTalebi kilitli açar; müşteri yanıt yazamaz
encryptboolİlk mesajı şifreli saklar
attachmentsstring / object / arrayEklenecek dosyalar

Başarılı istek 201 ile döner ve data içinde açılan talebin detayını (detay ucuyla aynı şekilde) taşır; talep numarası data.id alanındadır. Belgede sayılan hatalar: invalid_client, subject_required, message_required, invalid_department, invalid_service, invalid_assigned, invalid_custom_status, bir kanca açmayı reddederse blocked_by_gate, create_failed (hepsi 422) ve izin eksikse 403 insufficient_scope.

Mesaj alanında yer tutucular ({FULL_NAME} gibi) çalıştığı için ziyaretçinin yazdığı metindeki süslü parantezleri gönderimden önce başka bir karaktere çevirmek, metnin beklenmedik şekilde değiştirilmesini önlemek için basit bir önlemdir.

Sunucu tarafı PHP betiği

Aşağıdaki betik sitenizin kendi sunucusunda çalışır; WISECP çekirdeğinde hiçbir dosyaya dokunmaz. Formun gösterildiği sayfa oturumda csrf ve form_ts değerlerini üretir, formda website adlı görünmez bir honeypot alanı bulunur. Anahtar getenv() ile okunur.

php
<?php
// iletisim.php: sitenizin sunucusunda çalışır. API anahtarı tarayıcıya hiç gitmez.
session_start();
header('Content-Type: application/json; charset=utf-8');

const PANEL = 'https://panel.ornek.com/api/v1/admin';

function wisecp(string $method, string $path, ?array $body = null, array $query = [], string $idem = ''): array
{
    $ch = curl_init(PANEL . $path . ($query ? '?' . http_build_query($query) : ''));
    $headers = ['Authorization: Bearer ' . getenv('WISECP_API_KEY'), 'Accept: application/json'];
    $opts = [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15, CURLOPT_CUSTOMREQUEST => $method];
    if ($body !== null) {
        $headers[] = 'Content-Type: application/json';
        if ($idem !== '') $headers[] = 'Idempotency-Key: ' . $idem;
        $opts[CURLOPT_POSTFIELDS] = json_encode($body);
    }
    $opts[CURLOPT_HTTPHEADER] = $headers;
    curl_setopt_array($ch, $opts);
    $raw    = curl_exec($ch);
    $status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    return ['status' => $status, 'body' => json_decode((string) $raw, true) ?? []];
}

function bitir(int $kod, string $mesaj): never
{
    http_response_code($kod);
    echo json_encode(['ok' => $kod < 300, 'mesaj' => $mesaj]);
    exit;
}

// 1. Temel kapılar: yöntem, CSRF, honeypot, çok hızlı gönderim
if ($_SERVER['REQUEST_METHOD'] !== 'POST') bitir(405, 'Geçersiz istek.');
if (!hash_equals($_SESSION['csrf'] ?? '', (string) ($_POST['csrf'] ?? ''))) bitir(403, 'Oturum süresi doldu, sayfayı yenileyin.');
if (($_POST['website'] ?? '') !== '') bitir(200, 'Mesajınız alındı.');          // bota başarı gibi görünür
if (time() - (int) ($_SESSION['form_ts'] ?? 0) < 3) bitir(429, 'Lütfen tekrar deneyin.');

// 2. Doğrulama
$ad    = trim(strip_tags((string) ($_POST['ad'] ?? '')));
$email = filter_var(trim((string) ($_POST['email'] ?? '')), FILTER_VALIDATE_EMAIL);
$konu  = trim(strip_tags((string) ($_POST['konu'] ?? '')));
$mesaj = trim(strip_tags((string) ($_POST['mesaj'] ?? '')));
$onay  = ($_POST['aydinlatma'] ?? '') === '1';

if (!$email || mb_strlen($ad) < 2 || mb_strlen($ad) > 100
    || mb_strlen($konu) < 3 || mb_strlen($konu) > 150
    || mb_strlen($mesaj) < 10 || mb_strlen($mesaj) > 5000 || !$onay) {
    bitir(422, 'Lütfen tüm alanları doğru doldurun.');
}
$mesaj = str_replace(['{', '}'], ['(', ')'], $mesaj);   // yer tutucu çakışmasını önler

// 3. Müşteriyi bul: search kısmi eşleşir, e-postayı birebir karşılaştırın
$r = wisecp('GET', '/clients', null, ['search' => $email, 'limit' => 25]);
if ($r['status'] !== 200) bitir(502, 'Şu an mesajınızı iletemiyoruz.');
$musteri = null;
foreach ($r['body']['data'] ?? [] as $c) {
    if (strcasecmp((string) $c['email'], $email) === 0) { $musteri = $c; break; }
}
if (!$musteri) bitir(404, 'Bu e-posta ile kayıtlı hesap bulunamadı. Lütfen müşteri panelinden talep açın.');

// 4. Talebi aç. Aynı içerik tekrar gönderilirse ikinci talep açılmaz.
$idem = 'web-' . hash('sha256', $email . '|' . $konu . '|' . $mesaj);
$t = wisecp('POST', '/tickets', [
    'client_id'     => (int) $musteri['id'],
    'department_id' => (int) getenv('WISECP_DEPT_ID'),
    'subject'       => '[Web formu] ' . $konu,
    'message'       => "Web sitesi iletişim formundan gelen mesaj\nAd: {$ad}\nE-posta: {$email}\n\n" . $mesaj,
], [], $idem);

if ($t['status'] === 201) {
    unset($_SESSION['csrf']);
    bitir(201, 'Talebiniz oluşturuldu. Numara: ' . (int) $t['body']['data']['id']);
}
error_log('wisecp talep hatasi: ' . $t['status'] . ' ' . ($t['body']['error']['code'] ?? '-'));
bitir(502, 'Şu an mesajınızı iletemiyoruz, lütfen daha sonra tekrar deneyin.');

Betikte dikkat edilecek noktalar:

  • Clients/GetClients ucundaki search parametresi belgeye göre ad veya e-postada arama yapar; tam eşleşme garantisi yoktur. Bu yüzden dönen listede e-postayı birebir karşılaştırıyoruz.
  • Idempotency-Key başlığı sayesinde ziyaretçi butona iki kez basarsa ya da ağ hatasında istek tekrarlanırsa ikinci bir talep açılmaz; WISECP saklanan yanıtı döndürür.
  • WISECP'den dönen hata kodunu ziyaretçiye göstermiyoruz, yalnızca sunucu günlüğüne yazıyoruz. Ziyaretçiye genel bir mesaj yeterlidir.
  • never dönüş tipi PHP 8.1 ve üzeri gerektirir; daha eski sürümde tipi kaldırın. PHP sürümleri için PHP nedir yazısına bakabilirsiniz.

Kayıtlı olmayan ziyaretçi ne olacak?

Kayıtlı olmayan ziyaretçi ne olacak? Müşteri kaydı oluşturmak, WISECP iletişim mesajlarını kullanmak

Belgelerde misafir adına talep açan bir yönetim ucu bulunmuyor. Betik bu durumda ziyaretçiyi müşteri paneline yönlendiriyor. Başka iki belgelenmiş seçeneğiniz var:

  • Müşteri kaydı oluşturmak: POST /api/v1/admin/clients (Clients/CreateClient) full_name, email ve password alanlarını zorunlu tutar; e-posta kurulumda benzersiz olmalıdır, aksi halde email_exists döner. Başarıda 201 ile yeni müşterinin data.id değerini alır, ardından talebi o numarayla açarsınız. Ancak bir iletişim formu gönderimini kendiliğinden hesap açmaya çevirmek, ziyaretçinin beklemediği bir işlemdir ve kişisel veri işleme amacını genişletir. Bunu yalnızca formda açıkça belirtir ve ziyaretçiden bu yönde onay alırsanız düşünün.
  • WISECP iletişim mesajlarını kullanmak: WISECP'nin kendi iletişim formundan gelen mesajlar gelen kutusuna düşer. Panelde Destek Talebine Dönüştür ile, API'de ise POST /api/v1/admin/website/messages/{id}/convert-to-ticket (Website/ConvertMessageToTicket) ucuyla talebe çevrilir. Bu uç department alanını zorunlu tutar, isteğe bağlı priority, staff ve notes alır ve ticket_id ile message_id döndürür. Belge, mesajın hangi talebe dönüştüğünü converted_to_ticket_id alanında taşıdığını ve ikinci kez dönüştürmeden önce ona bakılması gerektiğini not eder.
bash
curl -X POST 'https://panel.ornek.com/api/v1/admin/website/messages/20/convert-to-ticket' \
  -H "Authorization: Bearer $WISECP_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"department":1,"priority":2}'
# data: { "ticket_id": ..., "message_id": 20 }

Spam ve kötüye kullanım koruması

Herkese açık bir form, doğrudan destek kuyruğunuza yazan bir kapıdır. Yukarıdaki betik birkaç temel katman içeriyor; bunları kendi ortamınıza göre genişletin:

  • CSRF jetonu: formun sizin sayfanızdan gönderildiğini doğrular.
  • Honeypot alanı: CSS ile gizlenen bir alan; insanlar doldurmaz, basit botlar doldurur.
  • Zaman kontrolü: sayfa açıldıktan birkaç saniye içinde gelen gönderimleri reddeder.
  • IP başına hız sınırı: aynı adresten dakikada çok sayıda gönderimi keser. Yöntemler için rate limiting stratejileri yazısına bakın.
  • CAPTCHA: yoğun spam alıyorsanız sunucu tarafında doğrulanan bir CAPTCHA ekleyin.

WISECP kendi formları için İşlem Kısıtlama ve BotShield gibi korumalar sunar; bunlar WISECP'nin kendi sitesindeki formlarda çalışır, sizin ayrı sitenizdeki betiği korumaz. Ayrıntılar için WISECP güvenlik ayarları ve BotShield yazısına bakabilirsiniz. Bir şey ters giderse Ayarlar > Genel Ayarlar > API > Kayıtlar sekmesi formdan gelen her isteği başlığı, gövdesi ve yanıtıyla gösterir.

KVKK notu

İletişim formu ad, e-posta ve mesaj içeriği gibi kişisel veriler toplar ve bu veriler WISECP'ye aktarılır. Formun yanında bir aydınlatma metni bulundurmanız, yalnızca amaç için gerekli alanları istemeniz ve açık rıza gerektiren işlemleri (ör. pazarlama izni) aydınlatmadan ayırmanız gerekir. Bu konuyu ayrıntılı olarak iletişim formu KVKK aydınlatma ve açık rıza yazısında anlattık. Yukarıdaki betikteki aydinlatma kutusu bir örnektir; metnin içeriğini hukuk danışmanınızla birlikte belirleyin.

Sık Sorulan Sorular

WISECP API ile müşteri olmayan birine destek talebi açabilir miyim?

Belgelenmiş yönetim ucu client_id alanını zorunlu tutar; misafir talebi ucu yoktur. Kayıtsız ziyaretçi için ya müşteri kaydı oluşturursunuz ya da WISECP'nin iletişim mesajlarını talebe dönüştürme akışını kullanırsınız.

Talep açıldığında müşteriye e-posta gider mi?

Evet. Belge, talep açmanın müşteriye bildirim gönderdiğini ve personel atanırsa atanan kişiye de haber gittiğini belirtir.

Form iki kez gönderilirse iki talep açılır mı?

Aynı Idempotency-Key ile gönderilen ikinci POST işi tekrar yapmaz, ilk yanıtı döndürür. Anahtarı mesaj içeriğinden türetirseniz çift tıklama ikinci talep açmaz.

Müşteri API (wck_) anahtarıyla bu iş yapılamaz mı?

Müşteri API'sinde de talep uçları var, ama anahtar tek bir müşteriye bağlıdır ve yalnızca o hesap adına çalışır. Sitenize gelen farklı ziyaretçiler için yönetim API'si ve sunucu tarafında tutulan bir wak_ anahtarı gerekir.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: WISECP nedir · WISECP API kullanımı · WISECP destek talebi sistemi · WISECP güvenlik ayarları · İletişim formu ve KVKK · REST API güvenliği · .env dosyası