Modi Erkek Kuaförü · Yazılımcı rehberi

Randevu onayına bildirim katmanı

Randevu sistemi çalışıyor, ancak onay yalnızca ekranda kalıyor. Bu rehber, mevcut sisteme dokunmadan eklenecek dört küçük parçayı, hazır kodları, test listesini ve maliyet araştırmasını içerir.

Site: modierkekkuaforu.comHazırlanma: 26 Eylül 2026Fiyat ve servis bilgileri bu tarihte kaynaklardan doğrulandı
Örnek kayıt:Ekrem Değirmenci26 Eylül 2026 · 15:30Saç + Sakal · 30 dk₺1.000

Kapsam ve teklif

Berber iki paket için fiyat istiyor. Paket A tamamen ücretsiz servislerle çalışır ve önerilen başlangıçtır.

Paket A Önerilen · aylık 0 TL

  • Onay ekranında Takvime ekle (iPhone/Outlook için .ics, Android için Google Takvim)
  • Her yeni randevuda berbere Telegram bildirimi
  • E-posta girildiyse müşteriye onay e-postası

Paket B SMS ücretli

  • Paket A'nın tamamı
  • Randevu anında SMS onayı
  • Randevudan 2 saat önce SMS hatırlatma (sağlayıcıda zamanlanır, cron gerekmez)

Opsiyon İsteğe bağlı

  • E-posta ve SMS içine iptal / değişiklik linki
  • İptalde berbere Telegram bildirimi ve planlı SMS'in iptali

Akış

Tüm bildirimler tek bir noktadan tetiklenir: randevu kaydının başarıyla veritabanına yazıldığı an. Bildirim hataları randevu kaydını asla engellememeli; her gönderim ayrı try/catch içinde çalışır ve yalnızca loglanır.

flowchart LR
  A[Müşteri formu gönderir] --> B[Randevu kaydedilir]
  B --> C[Onay ekranı]
  C --> C1[Takvime ekle butonu]
  B --> D[notifyBooking]
  D --> E[Telegram: berbere]
  D --> F[Brevo: müşteriye e-posta]
  D --> G[SMS: onay şimdi]
  D --> H[SMS: hatırlatma, 2 saat önce zamanlı]

Adım 1 Takvime ekle

En etkili ve ücretsiz adım. Randevu müşterinin kendi takvimine girer; telefon 2 saat ve 30 dakika önce kendisi hatırlatır. iPhone'da, özellikle ana ekrana eklenmiş uygulama modunda, tarayıcıda üretilen dosya indirmeleri güvenilir değildir. Bu yüzden .ics dosyasını sunucudan text/calendar başlığıyla verin; Android için Google Takvim linkini ikinci buton olarak ekleyin.

Saat dilimi: Randevu zamanını her zaman 2026-09-26T15:30:00+03:00 biçiminde, Türkiye saatiyle oluşturun. Aşağıdaki kod UTC'ye çevirerek yazar; takvim uygulaması yerel saate doğru döndürür.
server · GET /randevu/:id.ics
// Express örneği. Diğer framework'lerde aynı mantık: metni üret, text/calendar olarak dön.
app.get('/randevu/:id.ics', async (req, res) => {
  const r = await getBooking(req.params.id);          // { id, service, start: Date, minutes }
  if (!r) return res.sendStatus(404);
  const f = d => d.toISOString().replace(/[-:]/g, '').split('.')[0] + 'Z';
  const end = new Date(r.start.getTime() + r.minutes * 60000);
  const alarm = t => ['BEGIN:VALARM', `TRIGGER:${t}`, 'ACTION:DISPLAY',
                      'DESCRIPTION:Modi randevu hatırlatma', 'END:VALARM'];
  const ics = ['BEGIN:VCALENDAR', 'VERSION:2.0', 'PRODID:-//Modi//Randevu//TR', 'BEGIN:VEVENT',
    `UID:${r.id}@modierkekkuaforu.com`, `DTSTAMP:${f(new Date())}`,
    `DTSTART:${f(r.start)}`, `DTEND:${f(end)}`,
    `SUMMARY:Modi Erkek Kuaförü – ${r.service}`, 'LOCATION:Modi Erkek Kuaförü',
    ...alarm('-PT2H'), ...alarm('-PT30M'),
    'END:VEVENT', 'END:VCALENDAR'].join('\r\n');
  res.set('Content-Type', 'text/calendar; charset=utf-8');
  res.set('Content-Disposition', `inline; filename="modi-randevu-${r.id}.ics"`);
  res.send(ics);
});
onay ekranı · iki buton
<a class="btn" href="/randevu/{{id}}.ics">Takvime ekle (iPhone)</a>
<a class="btn" target="_blank" rel="noopener" href="{{googleUrl}}">Google Takvim'e ekle</a>

// googleUrl üretimi (sunucu veya istemci):
const g = d => d.toISOString().replace(/[-:]/g, '').split('.')[0] + 'Z';
const googleUrl = 'https://calendar.google.com/calendar/render?action=TEMPLATE'
  + '&text=' + encodeURIComponent('Modi Erkek Kuaförü – ' + r.service)
  + '&dates=' + g(r.start) + '/' + g(end)
  + '&location=' + encodeURIComponent('Modi Erkek Kuaförü');

Adım 2 Berbere Telegram bildirimi

Telegram, botların kullanıcılarına varsayılan olarak ücretsiz mesaj gönderebildiğini belirtiyor; yalnızca toplu yayında hız sınırı var. Berberin telefonunda Telegram uygulaması olması yeterli.

Kurulum (berberle birlikte, 5 dakika)

  1. Telegram'da @BotFather → /newbot → bot adı verilir, token alınır.
  2. Berber kendi telefonundan bota herhangi bir mesaj atar.
  3. https://api.telegram.org/bot<TOKEN>/getUpdates açılır; yanıttaki message.chat.id değeri chat_id'dir. Birden fazla çalışan bildirim alacaksa bir Telegram grubu açılıp bot gruba eklenir; grup chat_id'si negatif bir sayıdır.
server · notifyBarber()
async function notifyBarber(r) {
  const text = `✂️ Yeni randevu\n${r.name} · ${r.phone}\n${r.dateText} ${r.timeText} · ${r.service}`;
  const res = await fetch(`https://api.telegram.org/bot${process.env.TG_TOKEN}/sendMessage`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ chat_id: process.env.TG_CHAT_ID, text })
  });
  if (!res.ok) console.error('Telegram', res.status, await res.text());
}

Adım 3 Müşteriye onay e-postası

Brevo'nun ücretsiz planı süresiz, kredi kartı istemiyor ve günde 300 gönderim hakkı veriyor. Bu limit pazarlama ve işlem e-postaları arasında ortaktır; bir berber için fazlasıyla yeterli. Ücretsiz planda e-postalarda Brevo logosu yer alır.

Kurulum

  1. brevo.com'da ücretsiz hesap → SMTP & API → API anahtarı oluşturulur.
  2. Gönderici adresi (ör. randevu@modierkekkuaforu.com) ve alan adı doğrulanır. Brevo, göndericinin kayıtlı ve doğrulanmış olmasını şart koşuyor; bunun için alan adının DNS'ine Brevo'nun verdiği kayıtlar eklenir.
  3. Randevu formuna isteğe bağlı e-posta alanı eklenir.
server · emailCustomer()
async function emailCustomer(r) {
  if (!r.email) return;
  const res = await fetch('https://api.brevo.com/v3/smtp/email', {
    method: 'POST',
    headers: { 'api-key': process.env.BREVO_KEY, 'content-type': 'application/json', accept: 'application/json' },
    body: JSON.stringify({
      sender: { name: 'Modi Erkek Kuaförü', email: 'randevu@modierkekkuaforu.com' },
      to: [{ email: r.email, name: r.name }],
      subject: `Randevunuz onaylandı · ${r.dateText} ${r.timeText}`,
      htmlContent: `<p>Sayın ${r.name},</p>
        <p><b>${r.dateText} ${r.timeText}</b> tarihli <b>${r.service}</b> randevunuz onaylandı.</p>
        <p><a href="https://modierkekkuaforu.com/randevu/${r.id}.ics">Takviminize ekleyin</a></p>`
    })
  });
  if (!res.ok) console.error('Brevo', res.status, await res.text());
}

Adım 4 SMS onay ve hatırlatma Paket B

Firma adıyla (başlıklı) SMS için BTK onaylı gönderici adı ve lisanslı bir sağlayıcı gerekir; ücretsiz ve güvenilir bir seçenek yoktur. Randevu onayı ve hatırlatması bilgilendirme mesajı sayıldığı için İYS izni gerekmez; mesaja kampanya veya indirim eklenirse ticari ileti olur ve İYS onayı gerekir.

Örnek sağlayıcı olarak iletiMerkezi seçildi, çünkü API'si ileri tarihli gönderimi (sendDateTime) destekliyor. Hatırlatma SMS'i randevu anında sağlayıcıda zamanlanır, sunucuda cron kurmak gerekmez. Başlık onayı gelene kadar testler APITEST göndericisiyle yapılabilir. key ve hash değerleri panelden hazır alınır; sağlayıcı hash'in elle üretilmemesini söylüyor.

server · smsCustomer()
// iletiMerkezi: POST https://api.iletimerkezi.com/v1/send-sms/json
// iys: "0" = bilgilendirme (randevu). sendDateTime: "dd/MM/yyyy HH:mm", Türkiye saati.
async function sendSms(number, text, sendDateTime) {
  const order = { sender: process.env.SMS_SENDER, iys: '0',
                  message: { text, receipents: { number: [number] } } };   // alan adı dokümandaki gibi: receipents
  if (sendDateTime) order.sendDateTime = sendDateTime;
  const res = await fetch('https://api.iletimerkezi.com/v1/send-sms/json', {
    method: 'POST', headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ request: {
      authentication: { key: process.env.SMS_KEY, hash: process.env.SMS_HASH }, order } })
  });
  return res.json();   // yanıttaki sipariş kimliğini randevuya kaydedin (iptal için)
}

const trTime = d => new Intl.DateTimeFormat('tr-TR', { timeZone: 'Europe/Istanbul',
  day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' })
  .format(d).replace(',', '').replace(/\./g, '/');            // "26/09/2026 13:30"

async function smsCustomer(r) {                                  // r.phone: 905XXXXXXXXX
  await sendSms(r.phone, `Modi Erkek Kuaforu: ${r.dateText} ${r.timeText} ${r.service} randevunuz onaylandi.`);
  const remindAt = new Date(r.start.getTime() - 2 * 3600 * 1000);
  if (remindAt > new Date())
    await sendSms(r.phone, `Hatirlatma: Bugun ${r.timeText} Modi Erkek Kuaforu randevunuz var.`, trTime(remindAt));
}
Karakter sınırı: Türkçe karakterli tek SMS 150 karakterle sınırlı; aşan mesaj birden fazla SMS olarak ücretlendirilir. Şablonlar kısa tutuldu. Türkçe karaktersiz yazmak maliyeti düşürür.
İptal durumunda: Opsiyon alınırsa, iptal edilen randevunun planlı hatırlatma SMS'i de iptal edilmeli. Sağlayıcının sipariş iptal uç noktasını API dokümanından doğrulayın. Başka bir sağlayıcı seçilirse ileri tarihli gönderim desteği varsa aynı yapı korunur; yoksa 5 dakikada bir çalışan küçük bir cron gerekir.

Bağlantı noktası

Mevcut koda eklenecek tek satır, randevunun kaydedildiği yerdir. Bildirimler müşteriyi bekletmemesi için yanıt döndükten sonra da çalıştırılabilir.

server · randevu kaydı sonrası
async function notifyBooking(r) {
  const jobs = [notifyBarber(r), emailCustomer(r)];
  if (process.env.SMS_ENABLED === 'true') jobs.push(smsCustomer(r));
  const results = await Promise.allSettled(jobs);          // biri hata verirse diğerleri yine çalışır
  results.filter(x => x.status === 'rejected').forEach(x => console.error('notify', x.reason));
}

// const booking = await saveBooking(form);   ← mevcut kod
// notifyBooking(booking);                     ← eklenecek
Ortam değişkeniNeredenPaket
TG_TOKEN@BotFatherA
TG_CHAT_IDgetUpdates yanıtıA
BREVO_KEYBrevo → SMTP & APIA
SMS_ENABLEDtrue / falseB
SMS_KEY, SMS_HASHiletiMerkezi paneli → güvenlik ayarlarıB
SMS_SENDEROnaylı başlık (test: APITEST)B
Güvenlik ve KVKK: Anahtarların hepsi yalnızca sunucuda ortam değişkeni olarak tutulur, tarayıcıya giden koda ve git deposuna yazılmaz. Telefon ve e-posta alınan formun altına kısa bir aydınlatma metni linki eklenir; SMS ve e-posta içeriğine kampanya eklenmez.

Kabul testleri

Teslimde aşağıdaki maddelerin her biri gerçek bir test randevusuyla gösterilmeli.

Maliyet ve alternatifler

SMS sağlayıcıları (Paket B)

SağlayıcıKaynakta yazan paketBirimNot
iletiMerkezi500 SMS · 189 TL0,378 TLKDV ve ÖİV dahil, taahhüt yok, 1 yıl geçerli. Yeni abonelikte ilk ödemeye 10.000 SMS 879 TL. API'de ileri tarihli gönderim var.
VatanSMS2.500 SMS · 499 TL≈ 0,20 TLİlk alıma özel. KDV ve ÖTV dahil, son kullanım yok, ulaşmayan SMS iade.
Netgsm1.000 SMS · 899 TL'den≈ 0,90 TLYalnızca ulaşan SMS ücretlendirilir.
Senaryo (varsayım: günde 15 randevu)SMS / ay≈ 0,20 TL ile≈ 0,38 TL ile
Yalnızca hatırlatma SMS'i (onay takvim + e-postayla)45090 TL170 TL
Onay + hatırlatma900180 TL340 TL

Hazır randevu platformuna geçmek daha mı mantıklı?

Karşılaştırma için pazardaki hazır sistemlere bakıldı. Hepsi SMS'li hatırlatma sunuyor, ancak berberin kendi markalı sitesi ve mevcut akışı yerine platformun sayfasına geçmek gerekir.

SeçenekFiyatBildirimDeğerlendirme
Mevcut sistem + bu rehber0 TL (A)
+ SMS kullanımı (B)
Takvim, Telegram, e-posta, SMSMarka, tasarım ve müşteri verisi berberde kalır. Tek seferlik geliştirme maliyeti.
RandevuNetÜcretsiz; Pro 417 TL/aySitesine göre SMS ve WhatsApp hatırlatma ücretsizÜcretsiz sürüm reklamlı; markalama Pro'da. Ücretsiz SMS beyanı sitenin kendi ifadesi.
Salon RandevuSilver 779 TL/ay100 hediye SMS/ay, SMS hatırlatmaKDV dahil. WhatsApp ve online randevu sitesi ek 225 TL/ay.
Fresha19,95 USD/ayAyda 100 SMS ücretsiz, sonrası 0,02 USDPazar yerinden gelen yeni müşteri için %20 komisyon.
WhatsApp neden yok: WhatsApp Business Platform 1 Temmuz 2025'ten beri mesaj başına ücretlendiriyor; utility şablonları yalnızca müşteri hizmet penceresi içinde ücretsiz. Randevu hatırlatması pencere dışında gideceği için ücretli olur ve Meta işletme doğrulaması gerektirir. Bu ölçekte SMS'ten daha zahmetli. Resmi olmayan WhatsApp otomasyon kütüphaneleri hesap kapatılma riski taşır, kullanılmamalı.

Kaynaklar

Hepsi 26 Eylül 2026'da kontrol edildi. Fiyatlar değişebilir; satın almadan önce güncelliğini doğrulayın.