# Hizmet Devir Kancaları

https://dev.wisecp.com/tr/hizmet-devir-kancalari

Bir hizmetin sahibini değiştiren yedi kanca: devir talebi, alıcının onayı, ret ve vazgeçme.

## Genel Bakış

Devir **iki tarafın rızasını** ister: mevcut sahip başlatır, alıcı onaylar. Arada bekleyen bir kayıt durur ve iki taraftan biri vazgeçebilir.

Bu kancalar **tip ayrımı yapmaz**: barındırma, sunucu ve alan adı aynı akıştan geçer. Alan adına özgü bir kural yazacaksanız hizmet tipini kendiniz kontrol edin.

## Referans

### Devir talebini durdurma

gateservice.transfer_request

`ClientServices` alan adı da geçer

Mevcut sahip devri başlattığında, bekleyen kayıt yazılmadan önce çalışır.

Parametreler 3

$servicearrayDevredilecek hizmet. Tip ayrımı yoktur: `type` alanı `domain` da olabilir.

$from_idintMevcut sahip. Devri başlatan hesaptır.

$to_idintHedef sahip. E-postadan çözülmüş ve kayıtlı müşteri olduğu **doğrulanmıştır**.

Dönüş 1

stringBoş olmayan bir string devri **durdurur**; metin hata olarak fırlatılır ve müşteriye gösterilir.

Dinleyici PHP

```php
Hook::add('gate:service.transfer_request', 10,
    function ($service, $from_id, $to_id) {
        // Ucretsiz gelistirici lisansi devredilemez: kendi kuralinizi burada yazin.
        if (Acme::nonTransferable($service))
            return 'Bu hizmet baska bir hesaba devredilemez.';

        return null;
    });
```

### Devir talebini izleme

actionservice.transfer.requested

`ClientServices` veri paketi, kayıt değil

Bekleyen devir kaydı oluşturulduktan sonra çalışır. Hizmet hâlâ **eski sahiptedir**.

Parametreler 3

$servicearrayDevredilecek hizmet, hâlâ mevcut sahibinde.

$dataarrayDevrin **veri paketi**: hizmet adı, gönderen ve alıcı bilgileri, doğrulama anahtarı. Kardeş kancalardaki aynı sıradaki parametre **kayıt satırının kendisidir**; bu ise onun içindeki veridir. İkisini karıştırmak boş alan okumaya yol açar.

$uidintDevri başlatan sahibin kimliği.

Dönüş 1

voidDönüş yoksayılır.

Dinleyici PHP

```php
Hook::add('action:service.transfer.requested', 10,
    function ($service, $data, $uid) {
        // $data VERI PAKETIDIR (event satiri degil): alanlari dogrudan okuyun.
        Audit::transferOpened((int) ($service['id'] ?? 0),
            (int) ($data['from_id'] ?? 0), (int) ($data['to_id'] ?? 0));
    });
```

### Devir onayını durdurma

gateservice.transfer_approve

`ClientServices` alıcı onaylıyor

Alıcı devri kabul ettiğinde, sahiplik geçmeden önce çalışır.

Parametreler 3

$servicearrayDevredilecek hizmet kaydı.

$from_idintMevcut sahip.

$to_idintHedef sahip.

Dönüş 1

stringBoş olmayan bir string devri **durdurur**; metin hata olarak fırlatılır ve müşteriye gösterilir.

Dinleyici PHP

```php
Hook::add('gate:service.transfer_approve', 10,
    function ($service, $from_id, $to_id) {
        // Aliciyi da denetleyin: dogrulanmamis hesaba hizmet gecmesin.
        if (!Acme::verifiedAccount($to_id))
            return 'Alici hesap dogrulanmamis.';

        return null;
    });
```

### Devrin tamamlandığını öğrenme

actionservice.transfer.approved

`ClientServices` sahiplik geçti

Sahiplik yeni hesaba geçtikten sonra çalışır.

Parametreler 4

$serviceIdintDevredilen hizmetin kimliği.

$fromIdintÖnceki sahip.

$toIdintYeni sahip.

$newOwnerarrayYeni sahibin kaydı: `id`, `full_name`, `email`.

Dönüş 1

voidDönüş yoksayılır.

Dinleyici PHP

```php
Hook::add('action:service.transfer.approved', 10,
    function ($serviceId, $fromId, $toId, $newOwner) {
        // Eski sahibin erisimini kesin: hizmet artik onun degil.
        Acme::revokeAccess($fromId, $serviceId);
        Acme::grantAccess($toId, $serviceId);
    });
```

### Devrin reddedilmesini izleme

actionservice.transfer.rejected

`ClientServices` hizmet kaydı GELMEZ

Alıcı devri reddettiğinde çalışır.

Parametreler 2

$meintReddeden alıcının hesap kimliği.

$dataarrayDevir verisi: `service_id`, `service_name`, gönderen ve alıcı bilgileri. Bu kanca **hizmet kaydı vermez**; kimliğe ihtiyacınız varsa buradan alın.

Dönüş 1

voidDönüş yoksayılır.

Dinleyici PHP

```php
Hook::add('action:service.transfer.rejected', 10, function ($me, $data) {
    // Hizmet kaydi GELMEZ: id'yi veri paketinden alin.
    Crm::transferRefused((int) ($data['service_id'] ?? 0), (int) ($data['from_id'] ?? 0));
});
```

### Devirden vazgeçmeyi izleme

actionservice.transfer.cancelled

`ClientServices` gönderen vazgeçti

Mevcut sahip bekleyen devirden vazgeçtiğinde çalışır.

Parametreler 2

$servicearrayHizmet kaydı, hâlâ mevcut sahibinde.

$pendingarrayİptal edilen bekleyen **kayıt satırı**; içinde alıcı bilgileri ve doğrulama anahtarı bulunur. Talep kancasındaki aynı sıradaki parametre **veri paketiydi**; bu ise satırın kendisidir ve veri içindedir.

Dönüş 1

voidDönüş yoksayılır.

Dinleyici PHP

```php
Hook::add('action:service.transfer.cancelled', 10, function ($service, $pending) {
    // Burada $pending KAYIT SATIRIDIR: veri bir alt seviyededir.
    $payload = $pending['data'] ?? [];
    Audit::transferClosed((int) ($service['id'] ?? 0), (int) ($payload['to_id'] ?? 0));
});
```

### Davetin yeniden gönderilmesini izleme

actionservice.transfer.resent

`ClientServices` aynı kayıt

Mevcut sahip devir davetini yeniden gönderdiğinde çalışır. Bekleyen kayıt **değişmez**, yalnız bildirim tekrarlanır.

Parametreler 2

$servicearrayHizmet kaydı.

$pendingarrayBekleyen devir kaydı.

Dönüş 1

voidDönüş yoksayılır.

Dinleyici PHP

```php
Hook::add('action:service.transfer.resent', 10, function ($service, $pending) {
    // Tekrarlanabilir: ust uste gonderimi kendi tarafinizda sinirlayin.
    Acme::countResend((int) ($service['id'] ?? 0));
});
```

## Tuzaklar

> **Aynı sıradaki parametre iki farklı şey olabilir**
> 
> Devir talebinde ikinci parametre **veri paketidir**; vazgeçme ve yeniden gönderme kancalarında ise aynı sıra **kayıt satırının kendisini** taşır ve veri bir alt seviyededir. Birini diğeri sanmak **boş alan** okutur: hata çıkmaz, değer gelmez.

> **Alan adları da bu akıştan geçer**
> 
> Devir kancaları hizmet tipine **bakmaz**. Barındırma için yazdığınız bir kural alan adı devirlerine de uygulanır. Yalnız bir tipi hedefliyorsanız hizmet kaydındaki tip alanını **ilk satırda** kontrol edin.

> **Ret kancası hizmet kaydı vermez**
> 
> Reddetme kancasında yalnız reddeden hesabın kimliği ve devir verisi gelir; hizmet kaydı **yoktur**. Diğer devir kancalarına alışmış bir dinleyici burada hizmet adını ararken boş bulur. Kimliği **veri paketinden** alıp kaydı kendiniz okuyun.

> **İki kapı iki ayrı tarafı korur**
> 
> Talep kapısı **gönderen** tarafı, onay kapısı **alıcı** tarafı denetler. "Bu hizmet devredilemez" kuralı talep kapısına, "bu hesap hizmet alamaz" kuralı onay kapısına yazılır. İkisini tek yere yazmak, akışın diğer ucunu açık bırakır.

## İlgili Makaleler

- [Hizmet Durum Kancaları](https://dev.wisecp.com/tr/hizmet-durum-kancalari)
- [Müşteri Hesabı Kancaları](https://dev.wisecp.com/tr/musteri-hesabi-kancalari)
- [Hizmet Yaşam Döngüsü Kancaları](https://dev.wisecp.com/tr/hizmet-yasam-dongusu-kancalari)
