# NesaChat — Kurulum ve Bağlama Rehberi

WhatsApp + Instagram DM'lerini tek panelden yöneten, Claude yapay zekası ile otomatik cevap veren,
**çok işletmeli** destek platformu. Tek kurulum, sınırsız işletme: her işletmenin kendi
WhatsApp numarası, Instagram/Messenger sayfası, kullanıcıları, AI ayarları ve sohbetleri vardır.

```
Müşteri (WhatsApp / Instagram)
        │  mesaj yazar
        ▼
Meta sunucuları ──webhook──▶  sizin-siteniz.com/api/webhook  (PHP — TÜM işletmeler için tek uç)
                                      │ phone_number_id / sayfa ID'sinden İŞLETMEYİ bulur
                                      │ mesajı o işletmenin sohbetine kaydeder
                                      ▼
                          Konuşma "AI" modundaysa → Claude API → cevap üretir
                                      │
                                      ▼
                          Meta Graph API ile (işletmenin token'ıyla) müşteriye geri gönderilir
                                      ▲
İşletme Paneli (React) ──REST API──────┘   (temsilci devralabilir, ayarları yönetir)
Ana Yönetim Paneli (süper admin) ── işletme açar, kimlik bilgilerini ve kullanıcıları yönetir
```

**Kurulum akışı (özet):**
1. Veritabanını kurun, `config.php`'yi doldurun (platform ayarları + süper admin bilgileri).
2. Süper admin olarak giriş yapın → ana yönetim paneli açılır.
3. "Yeni İşletme" ile işletmeyi oluşturun; kartına WhatsApp/Instagram/Messenger kimlik
   bilgilerini girin ve işletmeye bir yönetici kullanıcı ekleyin.
4. İşletme yöneticisi kendi e-postasıyla giriş yapar; yalnızca kendi işletmesini görür.

---

## 1. Localhost'ta Çalıştırma (şu an kurulu ve çalışır durumda)

Gereksinimler bu makinede zaten var: PHP 8.4, MariaDB, Node 22.

```bash
# Veritabanı (bir kez yapıldı):
mysql -u emreay -e "CREATE DATABASE nesachat CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -u emreay nesachat < database/schema.sql

# Paneli derle (frontend değiştikçe tekrarla):
cd frontend && npm install && npm run build

# Sunucuyu başlat:
cd /Users/emreay/NesaChat
php -S 127.0.0.1:8090 -t public_html server.php
```

- Panel: **http://127.0.0.1:8090/panel/**
- Giriş: `developeremreay@gmail.com` / `nesachat123`
  (İlk girişte bu bilgilerle bir **süper admin** otomatik oluşturulur; kaynak `config.php` → `panel`.)
- Süper admin girişinde **ana yönetim paneli** açılır: buradan işletme oluşturun,
  "Panele gir" ile işletmenin sohbet paneline geçin.

### Roller, kullanıcılar ve sohbet atama
- **Roller:** `super_admin` (platform sahibi — işletmeleri yönetir), `admin`
  (işletme yöneticisi: kendi işletmesinin kullanıcı + ayar yönetimi) ve `agent` (temsilci).
- İşletme kullanıcıları ya ana yönetim panelindeki işletme kartından ya da işletme
  yöneticisinin panelindeki 👥 simgesinden eklenir/silinir.
- Her sohbet, sohbet başlığındaki açılır listeden bir temsilciye **atanabilir**;
  atama sohbet listesinde mavi etiketle görünür.
- Her sohbetin bir **modu** vardır: 🤖 AI (Claude otomatik cevaplar) veya 🧑 İnsan
  (AI susar, temsilci yazar). Claude `insana_devret` aracını çağırınca mod otomatik İnsan'a döner.
- `config.php` içinde `app.dev = true` olduğu için Meta'ya gerçek mesaj gönderilmez;
  test için sahte gelen mesaj üretebilirsiniz:

```bash
# Önce giriş yapıp token alın:
curl -s -X POST http://127.0.0.1:8090/api/login \
  -H 'Content-Type: application/json' \
  -d '{"email":"developeremreay@gmail.com","password":"nesachat123"}'

# Sahte WhatsApp mesajı düşürün (TOKEN'ı yukarıdaki cevaptan alın):
curl -s -X POST http://127.0.0.1:8090/api/dev/simulate \
  -H "Authorization: Bearer TOKEN" -H 'Content-Type: application/json' \
  -d '{"channel":"whatsapp","external_id":"905551112233","name":"Ali Test","text":"Merhaba"}'
```

**Yapay zekayı localhost'ta denemek için:** [console.anthropic.com](https://console.anthropic.com) →
API Keys → anahtar oluşturun → `config.php` içindeki `anthropic.api_key` alanına (platform geneli)
veya işletme kartındaki "Anthropic API anahtarı" alanına (işletmeye özel) yapıştırın.
Simülasyonla mesaj düşürdüğünüzde Claude'un cevabı panelde görünür (dev modda Meta'ya gitmez).

> **Not:** Süper adminseniz `dev/simulate` ve diğer işletme uçlarına `X-Business-Id: <id>`
> başlığını ekleyin (panel "Panele gir" dediğinizde bunu otomatik yapar).

### Localhost'a webhook ulaştırmak (gerçek WhatsApp/Instagram testleri için)

Meta webhook'ları yalnızca **herkese açık HTTPS** adreslere gönderir. Localhost'u geçici olarak
internete açmak için tünel kullanın:

```bash
# Cloudflare Tunnel (ücretsiz, kayıt gerektirmez):
brew install cloudflared
cloudflared tunnel --url http://127.0.0.1:8090
# Size https://rastgele-isim.trycloudflare.com gibi bir adres verir.
# Meta'ya webhook adresi olarak şunu girin: https://rastgele-isim.trycloudflare.com/api/webhook
```

---

## 2. WhatsApp Numarası Bağlama (Meta WhatsApp Cloud API)

### 2.1. Ön koşullar
- Bir **Facebook hesabı**
- WhatsApp'a bağlanacak bir **telefon numarası** — bu numara kişisel WhatsApp/WhatsApp Business
  uygulamasında KAYITLI OLMAMALI (kayıtlıysa önce o uygulamadan hesabı silin). Sabit hat da olur.

### 2.2. Meta uygulaması oluşturma
1. [developers.facebook.com](https://developers.facebook.com) → sağ üstten **Get Started** ile geliştirici hesabı açın.
2. **My Apps → Create App** → kullanım amacı olarak **Other** → tür olarak **Business** seçin.
3. Uygulamaya isim verin (ör. `NesaChat`), varsa Business portföyünüzü seçin, yoksa oluşturmanız istenir.
4. Uygulama panosunda **Add products** listesinden **WhatsApp → Set up**'a tıklayın.

### 2.3. Test numarası ile ilk deneme (5 dakika)
1. **WhatsApp → API Setup** sayfasına gidin. Meta size ücretsiz bir **test gönderici numarası** verir.
2. Bu sayfadaki iki değeri not alın ve ana yönetim panelindeki **işletme kartına** girin:
   - **Phone number ID** → işletme kartı → "Phone Number ID"
     (gelen mesajlar bu ID üzerinden doğru işletmeye yönlendirilir — kritik alan!)
   - **Temporary access token** (24 saat geçerli) → işletme kartı → "Kalıcı erişim token'ı"
3. "To" alanına kendi cep numaranızı ekleyin (test alıcısı olarak doğrulamanız istenir).
4. Sayfadaki örnek cURL ile kendinize test mesajı gönderin — telefonunuza düşmeli.

### 2.4. Webhook bağlama (mesajların size ulaşması)
1. **WhatsApp → Configuration** sayfasına gidin.
2. **Webhook** bölümünde **Edit**:
   - **Callback URL**: `https://siteniz.com/api/webhook` (localhost testinde tünel adresi)
   - **Verify token**: `config.php` → `meta.verify_token` içine yazdığınız kelimenin AYNISI
   - **Verify and save** → sistemimiz `hub_challenge`'ı otomatik yanıtlar, yeşil onay görürsünüz.
3. Aynı sayfada **Webhook fields → Manage** → **messages** alanına **Subscribe** deyin. (En kritik adım!)
4. Artık test numaranıza WhatsApp'tan yazın → mesaj panelinize düşer → Claude otomatik cevaplar.

### 2.5. Kendi numaranızı ekleme ve kalıcı token
1. **WhatsApp → API Setup → Add phone number**: numaranızı girin, SMS/çağrı ile doğrulayın,
   işletme görünen adını belirleyin. Yeni **Phone number ID**'yi işletme kartına yazın.
2. Geçici token 24 saatte ölür. **Kalıcı token** için:
   - [business.facebook.com/settings](https://business.facebook.com/settings) → **Users → System users** → **Add**
     (rol: Admin) ile bir sistem kullanıcısı oluşturun.
   - Sistem kullanıcısına uygulamanızı atayın (**Add assets → Apps → NesaChat → Full control**).
   - **Generate token** → uygulamanızı seçin → izinler: `whatsapp_business_messaging`,
     `whatsapp_business_management` → süre: **Never expire** → token'ı işletme kartına yazın.
3. **Önemli kurallar:**
   - Müşteri size yazdıktan sonra **24 saat** içinde serbest metinle cevap verebilirsiniz
     (bu platformun senaryosu zaten bu — destek).
   - 24 saat geçtikten sonra konuşmayı SİZ başlatacaksanız onaylı **şablon mesaj** gerekir.
   - İşletme doğrulaması (Business Verification) yapmadan günde 250 konuşma başlatma sınırı vardır;
     gelen mesajlara cevap için sınır sorun olmaz.

---

## 3. Instagram DM Bağlama (Instagram Messaging API)

### 3.1. Ön koşullar
- Instagram hesabınız **Professional** (Business veya Creator) olmalı:
  Instagram uygulaması → Ayarlar → Hesap türü → **Profesyonel hesaba geç**.
- Hesap bir **Facebook Sayfasına bağlı** olmalı:
  Instagram → Ayarlar → Hesap Merkezi → Hesapları bağla, veya Facebook Sayfası →
  Ayarlar → Bağlı hesaplar → Instagram.
- Instagram → Ayarlar → **Mesajlar ve hikaye yanıtları → Bağlantılı araçlar →
  Mesajlara erişime izin ver** AÇIK olmalı (kapalıysa webhook hiç gelmez — en sık yapılan hata).

### 3.2. Aynı Meta uygulamasına Messenger ürünü ekleme
1. Uygulama panosu → **Add products** → **Messenger → Set up**.
2. **Messenger → Instagram settings** (veya "Messenger API for Instagram") bölümüne gidin.
3. **Generate token**: Instagram'a bağlı Facebook Sayfanızı seçin ve çıkan
   **Page access token**'ı işletme kartındaki **Instagram → Sayfa erişim token'ı** alanına yazın.
   İstenen izinler: `instagram_basic`, `instagram_manage_messages`, `pages_manage_metadata`,
   `pages_messaging`.
4. İşletme kartındaki **Instagram hesap ID** alanına, işletmenin Instagram profesyonel hesap
   ID'sini yazın (webhook `entry.id` alanı bununla eşleşir; girilmezse gelen DM'ler
   işletmeye yönlendirilemez).

### 3.3. Instagram webhook aboneliği
1. Uygulama panosu → **Webhooks** ürünü → açılır listeden **Instagram**'ı seçin.
2. **Callback URL** ve **Verify token**: WhatsApp'takiyle AYNI (`/api/webhook` tek uç ikisini de işler).
3. **messages** alanına Subscribe deyin.
4. Sayfa aboneliğini de etkinleştirin: Messenger → Instagram settings → sayfanızın yanındaki
   webhook aboneliğinde **messages** işaretli olsun.

### 3.4. Test
- Geliştirme modunda yalnızca uygulamada **rolü olan** kullanıcıların (Admin/Developer/Tester)
  DM'leri webhook'a düşer. App Roles → Roles bölümünden test edecek Instagram hesabını ekleyin.
- Başka bir hesaptan işletme hesabınıza DM atın → panele düşmeli → Claude cevaplamalı.

---

## 3.5. Facebook Messenger Bağlama

Instagram ile aynı altyapıyı (Messenger Platform) kullanır; ek olarak yalnızca şunlar gerekir:

1. Uygulamanızda **Messenger** ürünü zaten ekli (Instagram için eklemiştiniz).
2. **Messenger → Messenger API Settings**: Facebook Sayfanızı bağlayıp **Page access token** üretin
   (izinler: `pages_messaging`, `pages_manage_metadata`). Token'ı işletme kartındaki
   **Facebook Messenger → Sayfa erişim token'ı** alanına, sayfanızın ID'sini de
   **Facebook sayfa ID** alanına yazın (webhook eşleşmesi için gerekli).
   Instagram'la aynı sayfaysa aynı token'ı iki alana da yazabilirsiniz.
3. **Webhooks** ürünü → açılır listeden **Page**'i seçin → Callback URL ve Verify token AYNI
   (`/api/webhook` üç kanalı da işler) → **messages** alanına Subscribe.
4. Sayfa aboneliği: Messenger ayarlarında sayfanızın webhook aboneliğinde **messages** işaretli olsun.
5. Test: Geliştirme modunda yalnızca uygulamada rolü olan kullanıcıların mesajları düşer;
   herkese açılmak için `pages_messaging` izniyle App Review gerekir.

## 4. Yapay Zeka (Claude / Gemini) Yapılandırması

1. [console.anthropic.com](https://console.anthropic.com) → hesap açın → **API Keys → Create key**.
2. Anahtarı iki şekilde kullanabilirsiniz:
   - **Platform geneli:** `config.php` → `anthropic.api_key` — kendi anahtarı olmayan
     tüm işletmeler bunu kullanır (maliyet size ait olur).
   - **İşletmeye özel:** işletme kartındaki "Anthropic API anahtarı" alanı — o işletme
     kendi anahtarıyla faturalandırılır.
3. İşletme paneli → ⚙️ Ayarlar bölümünden yönetilebilecekler (işletme başına ayrıdır):
   - **Otomatik cevap aç/kapat** (o işletme için)
   - **Model**: `claude-opus-4-8` (en yüksek kalite) · `claude-sonnet-5` (dengeli) ·
     `claude-haiku-4-5` (yüksek hacimde en ekonomik)
   - **Sistem talimatı**: İşletmenizin adı, çalışma saatleri, iade politikası, kargo süreleri gibi
     bilgileri buraya yazın — yapay zeka cevaplarını bu bilgilerle verir.
4. **İşletme bilgi tabanı**: Ayarlar → "İşletme bilgi tabanı" alanına SSS, ürünler, kargo/iade
   politikaları gibi bilgileri yazın; Claude cevaplarını öncelikle buradan verir ve bilgi tabanında
   olmayan işletme bilgilerini uydurmaz.
5. **Konuşma özeti**: Sohbet başlığındaki ✨ Özetle düğmesi konuşmayı Claude'a özetletir;
   özet, müşterinin görmediği bir iç not olarak sohbete eklenir.
6. **İnsana devretme**: Yapay zekaya `insana_devret` adında bir araç (tool) tanımlıdır. Müşteri
   insanla görüşmek istediğinde veya AI emin olmadığında bu aracı çağırır; konuşma otomatik olarak
   **İnsan** moduna geçer, panelde sarı etiketle görünür ve AI sussturulur. Temsilci konuşma
   başlığındaki düğmeyle istediği an modu değiştirebilir.

---

## 5. cPanel Sunucusuna Taşıma (Production)

1. **Veritabanı**: cPanel → MySQL Databases → veritabanı + kullanıcı oluşturun, kullanıcıyı
   veritabanına **All Privileges** ile ekleyin. phpMyAdmin → Import → `database/schema.sql`.
   *Eski tek işletmeli (v1) kurulumu yükseltiyorsanız* `schema.sql` yerine
   `database/upgrade-multitenant.sql` içe aktarın; mevcut veriler "Varsayılan İşletme"ye
   taşınır, betiğin sonundaki satırla kendinizi süper admin yapın.
2. **Dosyalar**:
   - `public_html/` klasörünün İÇERİĞİNİ (api/, panel/, .htaccess) sunucudaki `public_html/`e yükleyin.
   - `app/` klasörünü ve `config.php`'yi `public_html`'in BİR ÜSTÜNE yükleyin (webden erişilemesin):
     ```
     /home/kullanici/
     ├── app/                  ← web dışı
     ├── config.php            ← web dışı (şifreler burada!)
     └── public_html/
         ├── .htaccess
         ├── api/index.php
         └── panel/
     ```
3. **config.php**: gerçek veritabanı bilgileri, webhook `verify_token`, (isteğe bağlı)
   platform geneli AI anahtarları; `panel.admin_password`'ü güçlü bir şifreyle değiştirin ve
   **`app.dev` → `false`** yapın. İşletmelerin Meta token'ları config'e değil,
   ana yönetim panelindeki işletme kartlarına girilir.
4. **SSL**: cPanel → SSL/TLS Status → AutoSSL çalıştırın (Meta webhook'ları HTTPS zorunlu).
5. Meta panelindeki webhook adreslerini `https://siteniz.com/api/webhook` olarak güncelleyin.
6. PHP sürümü: cPanel → Select PHP Version → **8.1+** seçin, `curl` ve `pdo_mysql` eklentileri açık olsun.

---

## 6. REST API Dokümantasyonu (mobil uygulama için)

Taban adres: `https://siteniz.com/api` — tüm istek/cevaplar JSON.
Kimlik doğrulama: `POST /login`'den alınan token, sonraki isteklerde
`Authorization: Bearer <token>` başlığıyla gönderilir. CORS açıktır.

| Metot | Uç | Açıklama |
|---|---|---|
| POST | `/login` | `{email, password}` → `{token, user}` |
| GET | `/me` | Oturum açan kullanıcı bilgisi |
| GET | `/users` | Kullanıcı (temsilci) listesi |
| POST | `/users` | *(admin)* `{name, email, password, role}` — yeni kullanıcı |
| POST | `/users/{id}/delete` | *(admin)* Kullanıcıyı siler; sohbetleri "Atanmamış" olur |
| GET | `/conversations` | Konuşma listesi (kişi, kanal, son mesaj, okunmamış, mod, atanan temsilci) |
| POST | `/conversations/{id}/assign` | `{user_id}` — sohbeti temsilciye atar (`null` → atamayı kaldırır) |
| GET | `/conversations/{id}/messages?after_id=N` | Mesajlar; `after_id` ile artımlı çekim (polling) |
| POST | `/conversations/{id}/messages` | `{text}` — temsilci cevabı gönderir (Meta üzerinden iletilir) |
| POST | `/conversations/{id}/mode` | `{mode: "ai" \| "human"}` — otomatik cevabı devral/geri ver |
| POST | `/conversations/{id}/read` | Okunmamış sayacını sıfırlar |
| POST | `/conversations/{id}/media` | multipart: `file` (+ `caption`) — fotoğraf/ses/video/dosya gönderir |
| POST | `/conversations/{id}/note` | `{text}` — müşteriye gitmeyen iç not ekler |
| POST | `/conversations/{id}/tags` | `{tags}` — virgülle ayrılmış etiketler |
| POST | `/conversations/{id}/summarize` | Konuşmayı Claude ile özetler; özet iç not olarak da kaydedilir |
| GET | `/stats` | Dashboard verileri: günlük sayılar, 7 günlük hacim, kanal dağılımı, temsilci performansı |
| GET | `/canned` | Hazır yanıt şablonları |
| POST | `/canned` | `{shortcut, title, body}` — yeni şablon |
| POST | `/canned/{id}/delete` | Şablonu siler |
| GET | `/settings` | `{ai_enabled, ai_model, system_prompt, knowledge_base}` (işletme başına) |
| POST | `/settings` | *(admin)* Aynı alanlardan gönderilenleri günceller |
| GET/POST | `/webhook` | Meta'ya ayrılmıştır (doğrulama + gelen mesajlar); token istemez |
| POST | `/dev/simulate` | Sadece `app.dev=true` iken: sahte gelen mesaj `{channel, external_id, name, text}` |

**İşletme kapsamı:** Yukarıdaki tüm uçlar, oturum açan kullanıcının işletmesiyle sınırlıdır.
Süper admin bu uçları kullanmak için `X-Business-Id: <id>` başlığı gönderir
(panel "Panele gir" akışı bunu otomatik yapar).

### Ana yönetim paneli uçları (sadece `super_admin`)

| Metot | Uç | Açıklama |
|---|---|---|
| GET | `/admin/overview` | Platform istatistikleri + işletme listesi (kullanım özetiyle) |
| GET | `/admin/businesses` | İşletme listesi |
| POST | `/admin/businesses` | `{name, plan}` — yeni işletme (varsayılan ayarlar + hazır yanıtlarla açılır) |
| GET | `/admin/businesses/{id}` | İşletme detayı: kimlik bilgileri, kullanıcılar, ayarlar, istatistikler |
| POST | `/admin/businesses/{id}` | Alanları günceller: `name, plan, status, notes, wa_token, wa_phone_number_id, wa_waba_id, ig_page_token, ig_page_id, fb_page_token, fb_page_id, anthropic_api_key, gemini_api_key` |
| POST | `/admin/businesses/{id}/delete` | `{confirm_name}` — işletme adı aynen yazılırsa tüm verisiyle siler |

İşletmeye kullanıcı ekleme/silme: `/users` uçlarını `X-Business-Id` başlığıyla çağırın.
İşletmeyi askıya almak: `POST /admin/businesses/{id}` gövdesinde `{"status":"suspended"}`
(kullanıcı girişleri ve webhook işleme durur; veri silinmez).

Mobil uygulama akışı: login → `/conversations`'ı 5 sn'de bir, açık sohbette
`/messages?after_id=sonId`'yi 3 sn'de bir çekin (panel de aynı yöntemi kullanır).

---

## 7. Canlıya Çıkış Kontrol Listesi

- [ ] Meta uygulamasını **Live** moda alın (App settings → Basic → App Mode).
- [ ] Instagram mesajlaşması için **App Review**'a başvurun: `instagram_manage_messages`,
      `pages_messaging` izinlerinin "Advanced Access"i gerekir (ekran kaydıyla kullanım senaryosu gösterilir).
      WhatsApp için kendi numaranıza mesajlaşmada App Review gerekmez.
- [ ] Business Verification'ı tamamlayın (Business Settings → Security Center) — limitleri yükseltir.
- [ ] Kalıcı System User token kullandığınızdan emin olun (geçici token 24 saatte ölür).
- [ ] `config.php`'de `app.dev = false`, güçlü panel şifresi, HTTPS aktif.
- [ ] `nesachat.log` dosyasını arada kontrol edin (Meta/Claude hataları buraya yazılır).

## Sorun Giderme

| Belirti | Muhtemel sebep |
|---|---|
| Webhook doğrulama başarısız | `verify_token` config ile Meta panelinde farklı yazılmış |
| Mesajlar panele düşmüyor | Webhook **fields → messages** aboneliği yapılmamış; Instagram'da "Bağlantılı araçlar" izni kapalı |
| AI cevap vermiyor | `anthropic.api_key` boş/yanlış (`nesachat.log`'a bakın); konuşma "İnsan" modunda; Ayarlar'da AI kapalı |
| Giden mesaj hatası "outside allowed window" | 24 saat penceresi kapanmış — şablon mesaj gerekir |
| Instagram DM'leri gelmiyor (dev modda) | Mesaj atan hesabın uygulamada test rolü yok |
