# Bot ve Spam Koruması

https://dev.wisecp.com/tr/bot-ve-spam-korumasi

İstenmeyen trafiği bot kalkanı, captcha ve spam denetimiyle durduran on uç.

## Genel Bakış

Bu on uç istenmeyen trafiği **üç ayrı katmanda** durdurur. Bot kalkanı art arda denemeleri sayar ve keser. Captcha formların önüne bir doğrulama koyar. Spam koruması ise gönderilen içeriğe ve ziyaretçinin itibarına bakar.

Üçü birbirinden bağımsızdır ve **her birinin kendi açma anahtarı** vardır. Bir katmanı ayarlamak diğerlerini etkilemez; bir formun korunması için doğru katmanı açmanız gerekir.

## Referans

### Bot Kalkanını Getirme

get/api/v1/admin/settings/security/bot-shield

`Settings/GetBotShield` admin

Art arda başarısız denemelerde ne zaman durdurulacağını döndürür.

Dönen alanlar data — 3

statusintKalkanın açık olup olmadığı.

within_timeobjectSayımın yapıldığı zaman aralığı. Dönem adından dakikaya eşleme; tek bir dönem tutulur.

attemptsobjectHer korunan işlem için izin verilen deneme sayısı.

Hatalar 1

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl 'https://panel.ornek.com/api/v1/admin/settings/security/bot-shield' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res  = await fetch('https://panel.ornek.com/api/v1/admin/settings/security/bot-shield', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/security/bot-shield');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Deneme sayisi ISLEM BASINA tutulur: bir islem icin dusurmek digerlerini etkilemez.
$shield = Api::Settings()->GetBotShield()['data'];
$signIn = $shield['attempts']['sign-in'] ?? null;
```

### Bot Kalkanını Yazma

put/api/v1/admin/settings/security/bot-shield

`Settings/UpdateBotShield` admin

Kalkanı açar ve sayım penceresiyle deneme sınırlarını yazar.

Gövde 3

statusintKalkanı açar ya da kapatır.

within_timeobjectSayım aralığı. Tek bir dönem kabul edilir; gönderdiğiniz eskisinin yerine geçer.

attemptsobjectİşlem başına deneme sınırı.

Dönen alanlar data — 3

statusintKalkanın açık olup olmadığı.

within_timeobjectSayımın yapıldığı zaman aralığı. Dönem adından dakikaya eşleme; tek bir dönem tutulur.

attemptsobjectHer korunan işlem için izin verilen deneme sayısı.

Hatalar 1

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X PUT 'https://panel.ornek.com/api/v1/admin/settings/security/bot-shield' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"status":1,"within_time":{"hour":60},"attempts":{"sign-in":5}}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/settings/security/bot-shield', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    status: 1,
    within_time: { hour: 60 },
    attempts: { 'sign-in': 5 },
  }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/security/bot-shield');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'status'      => 1,
        'within_time' => ['hour' => 60],
        'attempts'    => ['sign-in' => 5],
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Sinir cok dusukse ortak baglantidan gelen GERCEK musteriler de engellenir.
Api::Settings()->UpdateBotShield([
    'status'      => 1,
    'within_time' => ['hour' => 60],
    'attempts'    => ['sign-in' => 5],
]);
```

### Captcha Ayarlarını Getirme

get/api/v1/admin/settings/security/captcha

`Settings/GetCaptcha` admin

Hangi sağlayıcının kullanıldığını ve hangi formların korunduğunu döndürür.

Dönen alanlar data — 3

statusintCaptcha'nın açık olup olmadığı.

typestringKullanılan sağlayıcı.

protected_areasobjectKorunan formlar. Alan adından açık olup olmadığına eşleme.

Hatalar 1

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl 'https://panel.ornek.com/api/v1/admin/settings/security/captcha' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res  = await fetch('https://panel.ornek.com/api/v1/admin/settings/security/captcha', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/security/captcha');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Genel anahtar kapaliyken korunan alan listesi DOLU gorunur ama hicbiri uygulanmaz.
$cap  = Api::Settings()->GetCaptcha()['data'];
$live = $cap['status'] === 1;
```

### Captcha Ayarlarını Yazma

put/api/v1/admin/settings/security/captcha

`Settings/UpdateCaptcha` admin

Sağlayıcıyı, korunan formları ve sağlayıcının kendi ayarlarını yazar.

Gövde 4

statusintCaptcha'yı açar ya da kapatır.

typestringKullanılacak sağlayıcı. Anahtar, sağlayıcı listesinden gelir.

protected_areasarray | objectKorunacak formlar: `contact-form`, `sign-up`, `sign-in`, `sign-forget`, `customer-feedback`, `newsletter`, `domain-check`, `software-license`. Liste ya da eşleme olarak verilebilir.

configobjectSağlayıcının kendi ayarları; ***** gönderilen parola alanı kayıtlı değerini korur.Yalnız gönderirseniz yazılır.

Dönen alanlar data — 3

statusintCaptcha'nın açık olup olmadığı.

typestringKullanılan sağlayıcı.

protected_areasobjectKorunan formlar. Alan adından açık olup olmadığına eşleme.

Hatalar 1

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X PUT 'https://panel.ornek.com/api/v1/admin/settings/security/captcha' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"status":1,"type":"DefaultCaptcha","protected_areas":["sign-in","sign-up"]}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/settings/security/captcha', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    status: 1,
    type: 'DefaultCaptcha',
    protected_areas: ['sign-in', 'sign-up'],
  }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/security/captcha');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'status'          => 1,
        'type'            => 'DefaultCaptcha',
        'protected_areas' => ['sign-in', 'sign-up'],
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Saglayici degistirmek onun kendi ayarlarini GEREKTIRIR: anahtarsiz saglayici formu bozar.
$fields = Api::Settings()->GetCaptchaFields(['module' => 'ReCaptcha'])['data'];

Api::Settings()->UpdateCaptcha([
    'status' => 1,
    'type'   => 'ReCaptcha',
    'config' => ['site-key' => $siteKey, 'secret-key' => $secret],
]);
```

### Sağlayıcıları Listeleme

get/api/v1/admin/settings/security/captcha/modules

`Settings/GetCaptchaModules` admin

Kurulu captcha sağlayıcılarını döndürür.

Dönen alanlar data[] — 4

keystringSağlayıcının anahtarı. Yazma ucunda bu kullanılır.

namestringSağlayıcının adı.

descriptionstringNe yaptığı.

activeboolŞu an kullanılıyor mu.

Hatalar 1

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl 'https://panel.ornek.com/api/v1/admin/settings/security/captcha/modules' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res  = await fetch('https://panel.ornek.com/api/v1/admin/settings/security/captcha/modules', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/security/captcha/modules');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Yerlesik saglayici listenin BASINDA gelir ve ayar istemez; digerleri anahtar ister.
$modules = Api::Settings()->GetCaptchaModules()['data'];
```

### Sağlayıcı Alanlarını Getirme

get/api/v1/admin/settings/security/captcha/{module}/fields

`Settings/GetCaptchaFields` admin

Bir sağlayıcının hangi ayarları istediğini ve kayıtlı değerlerini döndürür.

Dönen alanlar data — 3

modulestringSağlayıcının anahtarı.

fieldsarrayİstenen ayarların ham tanımı. Alanlar sağlayıcıdan sağlayıcıya değişir.

configobjectKayıtlı ayar değerleri. Parola tipli alanlar ve sır görünümlü anahtarlar burada ve fields[].value içinde ***** döner; kayıtlı sır geri okunamaz.

Hatalar 3

module_required422Sağlayıcı adı verilmedi.

not_found404Sağlayıcı bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl 'https://panel.ornek.com/api/v1/admin/settings/security/captcha/ReCaptcha/fields' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res  = await fetch('https://panel.ornek.com/api/v1/admin/settings/security/captcha/ReCaptcha/fields', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/security/captcha/ReCaptcha/fields');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Saglayiciyi degistirmeden ONCE hangi ayarlari istedigini buradan ogrenin.
$needs = Api::Settings()->GetCaptchaFields(['module' => 'ReCaptcha'])['data']['fields'];
```

### Spam Korumasını Getirme

get/api/v1/admin/settings/security/spam

`Settings/GetSpamProtection` admin

Kelime süzgecini, dış itibar servisini ve vekil sunucu denetimini döndürür.

Dönen alanlar data — 6

word_liststringEngellenen kelimeler.

api_statusintDış itibar servisinin açık olup olmadığı.

api_keystringAnahtar kayıtlıyken *****, yokken boş dize; anahtarın kendisi hiç dönmez.

api_risk_scoreintHangi risk puanından sonra engelleneceği.

block_temporaryintGeçici engelin açık olup olmadığı.

contact_check_proxyintVekil sunucu üzerinden gelenlerin denetlenip denetlenmediği.

Hatalar 1

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl 'https://panel.ornek.com/api/v1/admin/settings/security/spam' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res  = await fetch('https://panel.ornek.com/api/v1/admin/settings/security/spam', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/security/spam');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Dis servis ANAHTARSIZ calismaz: acik gorunse de sorgu yapilamaz.
$spam = Api::Settings()->GetSpamProtection()['data'];
$live = $spam['api_status'] === 1 && $spam['api_key'] !== '';
```

### Spam Korumasını Yazma

put/api/v1/admin/settings/security/spam

`Settings/UpdateSpamProtection` admin

Kelime süzgecini ve dış itibar denetimini yazar.

Gövde 6

word_liststringEngellenecek kelimeler.

api_statusintDış itibar servisini açar.

api_keystringServisin anahtarı; ***** (GET maskesi) gönderilirse kayıtlı anahtar değişmez. Servis bu olmadan çalışmaz.

api_risk_scoreintEngelleme eşiği. Düşük değer daha çok ziyaretçiyi engeller.

block_temporaryintGeçici engeli açar.

contact_check_proxyintVekil sunucu üzerinden gelenleri denetler.

Dönen alanlar data — 6

word_liststringEngellenen kelimeler.

api_statusintDış itibar servisinin açık olup olmadığı.

api_keystringAnahtar kayıtlıyken *****, yokken boş dize; anahtarın kendisi hiç dönmez.

api_risk_scoreintHangi risk puanından sonra engelleneceği.

block_temporaryintGeçici engelin açık olup olmadığı.

contact_check_proxyintVekil sunucu üzerinden gelenlerin denetlenip denetlenmediği.

Hatalar 2

api_key_invalid422Servis açık olacak ama anahtar geçerli 12 harflik bir anahtar değil. Hiçbir şey kaydedilmez.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X PUT 'https://panel.ornek.com/api/v1/admin/settings/security/spam' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"word_list":"spam,scam","block_temporary":1}'
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/settings/security/spam', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    word_list: 'spam,scam',
    block_temporary: 1,
  }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/security/spam');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'word_list'       => 'spam,scam',
        'block_temporary' => 1,
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Servisi acmak ANAHTAR gerektirir; ikisini birlikte gonderin yoksa denetim sessizce calismaz.
Api::Settings()->UpdateSpamProtection([
    'api_status'     => 1,
    'api_key'        => $key,
    'api_risk_score' => 25,
]);
```

### Engellenenleri Listeleme

get/api/v1/admin/settings/security/spam-records

`Settings/GetSpamRecords` admin

Son engellenen istekleri ve toplam engelleme sayısını döndürür.

Dönen alanlar data[] + meta

data[]objectSon engellenen kayıtlar. Yalnız son bir bölümü tutulur, tüm geçmiş değil.

total_blockedintToplam engelleme sayısı. Meta altında döner ve listedeki kayıt sayısından büyük olabilir.

Hatalar 1

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl 'https://panel.ornek.com/api/v1/admin/settings/security/spam-records' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res  = await fetch('https://panel.ornek.com/api/v1/admin/settings/security/spam-records', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/security/spam-records');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Sayac ile liste ayni sey DEGILDIR: toplam sayi listedekinden cok daha buyuk olabilir.
$rec   = Api::Settings()->GetSpamRecords();
$shown = count($rec['data']);
$total = $rec['meta']['total_blocked'];
```

### Engellenenleri Temizleme

delete/api/v1/admin/settings/security/spam-records

`Settings/ClearSpamRecords` admin sayaç da sıfırlanır

Engelleme kayıtlarını ve toplam sayacı sıfırlar.

Dönen alanlar data — 1

clearedboolTemizlik çalıştı mı.

Hatalar 1

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X DELETE 'https://panel.ornek.com/api/v1/admin/settings/security/spam-records' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res = await fetch('https://panel.ornek.com/api/v1/admin/settings/security/spam-records', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/settings/security/spam-records');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Temizlik SAYACI da sifirlar: kurulum boyunca kac engel oldugu bilgisi kaybolur.
// Once okuyup kendi tarafinizda saklayin.
$total = Api::Settings()->GetSpamRecords()['meta']['total_blocked'];
Api::Settings()->ClearSpamRecords();
```

## Tuzaklar

> **Genel anahtar kapalıyken korunan alanlar boşa çıkar**
> 
> Captcha'nın genel anahtarı kapalıyken korunan form listesi **dolu görünmeye devam eder** ama hiçbiri uygulanmaz. Listeye bir form eklemek onu korumaz; genel anahtarın da açık olması gerekir. Aynı şey bot kalkanı için de geçerlidir.

> **Sağlayıcı değiştirmek ayarlarını gerektirir**
> 
> Yerleşik captcha ayarsız çalışır, diğerleri **anahtar ister**. Anahtarları vermeden sağlayıcıyı değiştirmek formları bozar: doğrulama hiç yüklenmez ve müşteri gönderim yapamaz. Değiştirmeden önce sağlayıcının hangi alanları istediğini alan ucundan okuyun.

> **Anahtarsız itibar servisi sessizce çalışmaz**
> 
> Dış itibar servisini açmak tek başına yetmez: anahtar boşken sorgu yapılamaz ve hiçbir ziyaretçi denetlenmez. Ayar **açık görünür**, hata da alınmaz. İkisini birlikte gönderin ve sonra engellenen kayıtların artıp artmadığına bakın.

> **Dar sınır gerçek müşterileri de keser**
> 
> Bot kalkanı denemeleri **adrese göre** sayar. Ofis ya da okul gibi ortak bir bağlantının arkasındaki müşteriler tek bir adres olarak görünür; sınır düşük ayarlandığında birbirlerinin denemelerini harcarlar ve hiçbiri giremez. Sınırı düşürürken sayım penceresini de gözetin.

> **Temizlik sayacı da sıfırlar**
> 
> Engelleme kayıtlarını temizlemek yalnız listeyi boşaltmaz: kurulum boyunca kaç engel olduğunu tutan **toplam sayaç da sıfırlanır**. O sayı bir daha geri gelmez, o yüzden temizlemeden önce okuyup kendi tarafınızda saklayın. Listenin kendisi zaten yalnız son bir bölümü tutar; toplam sayı ondan çok daha büyük olabilir.

## İlgili Makaleler

- [Güvenlik Ayarları](https://dev.wisecp.com/tr/guvenlik-ayarlari)
- [Kimlik Doğrulama Ayarları](https://dev.wisecp.com/tr/kimlik-dogrulama-ayarlari)
- [Müşteri Kayıt Ayarları](https://dev.wisecp.com/tr/musteri-kayit-ayarlari)
