Genel bakış
Teslimat ve lojistikte kuryelerin zaman zaman müşterileri araması gerekir — ancak saha çalışanlarıyla müşteri telefon numaralarını paylaşmak gizlilik ve kişisel veri koruma sorunlarına yol açar. Müşteri numarası asla sisteminizden çıkmamalıdır.
Bu rehber, Hızlı Arama'yı bir Python webservisi ile birlikte kullanarak yalnızca sipariş numarasıyla çağrı bağlamayı gösterir. Kurye kısa bir dahili hattı çevirir, sipariş kodunu girer ve Hipcall kurye telefon numarasını hiç görmeden müşteriyle bağlantıyı otomatik olarak kurar.
Nasıl çalışır
Kurye hızlı arama dahili hattını çevirir ve sesli anonstaki yönergeyle sipariş numarasını tuşlar. Hipcall, tuşlanan rakamları sunucunuza POST eder; sunucunuz müşterinin telefon numarasını bulup döndürür. Hipcall çağrıyı kurye adına yapar — numara baştan sona gizli kalır.
Mimari
flowchart TD
A[Kurye Hızlı Arama dahili hattını çevirir] --> B[Hipcall giriş anonsunu çalar]
B --> C[Kurye sipariş numarasını tuşlar örn. 1234]
C --> D[Hipcall tuşlanan kodu sunucunuza POST eder]
D --> E{Sipariş bulundu mu?}
E -- Evet --> F[Müşteri telefon numarasını döndür]
E -- Hayır --> G[Hata döndür]
F --> H[Hipcall çağrıyı bağlar\nkurye ↔ müşteri]
Adım 1: Hipcall'da hızlı arama kaydı oluşturma
- Hipcall panelinde Ayarlar → Geliştirici → Hızlı Arama bölümüne gidin ve Yeni butonuna basın.
- Aşağıdaki ayarları girin:
| Alan | Değer |
|---|---|
| Ad | Sipariş Arama |
| İç hat numarası | 72 (veya boş herhangi bir dahili hat) |
| URL | https://xxxx.ngrok-free.app/hizli-arama |
| Webservis kimlik doğrulama | İsteğe bağlı — işaretlerseniz Kullanıcı adı ve Parola girin |
Ayrıca iki adet anons yükleyin:
- Giriş anonsu: "Lütfen sipariş numarasını tuşlayın."
- Hata anonsu: Servis başarısız olduğunda çalınacak ses dosyası.
Yerel geliştirme: Yerel sunucunuzu dışarıya açmak için ngrok kullanın.
ngrok http 5090komutunu çalıştırın ve oluşturulan HTTPS adresini URL alanına yapıştırın.
Adım 2: Telefon numarasını hızlı aramaya yönlendirme
Hızlı arama kaydını oluşturmak tek başına yetmez. Gelen çağrıların bu kayda düşmesi için bir numarayı yönlendirmeniz gerekir:
- Ayarlar → Telefon Sistemi → Telefon Numaraları bölümüne gidin.
- Hızlı aramaya yönlendirmek istediğiniz numarayı seçin.
- Çalışma Saatleri sekmesine geçin.
- Mesai içi hedef alanında oluşturduğunuz hızlı arama dahili numarasını seçin.
Adım 3: Gelen isteği anlama
Kurye tuşlama yaptıktan sonra Hipcall, webservis URL'nize şu yapıda bir POST isteği gönderir:
{
"timestamp": 1791891730,
"number": "1234",
"uuid": "e785****-****-****-****-********87e5",
"user_id": null,
"speed_dial_id": 19
}
İstek alanları
| Alan | Tip | Açıklama |
|---|---|---|
timestamp |
integer | İsteğin unix zaman damgası. |
number |
string | Kurye tarafından tuşlanan DTMF rakamları — sizin sipariş kodunuz. |
uuid |
string | Çağrının benzersiz kimliği. |
user_id |
integer / null | Çağrıyı başlatan kullanıcının ID'si. Dış hat üzerinden geliyorsa null olabilir. |
speed_dial_id |
integer | Tetiklenen hızlı arama kaydının ID'si. |
Kimlik doğrulama etkinleştirdiyseniz Hipcall, isteğin Authorization başlığında Basic <Base64> değerini gönderir:
Authorization: Basic ZmFu****OmZh****MDM=
Adım 4: Siparişi sorgulama ve hedefi döndürme
Sipariş kodunu kullanarak veritabanınızı sorgulayın. Bulunursa müşterinin telefon numarasını destination alanında döndürün. Hipcall çağrıyı hemen o numaraya bağlar.
Başarılı yanıt:
{ "destination": "90530XXXXXXX" }
Telefon numarasını alan kodu ile birlikte, yalnızca rakamlardan oluşan biçimde döndürün (örn. 905301234567).
Bulunamadı / hata yanıtı:
{ "error": "Sipariş bulunamadı" }
Sipariş kodu mevcut değilse veya bir hata oluşursa, HTTP 200 dışında bir durum kodu döndürün (örn. 404, 500). Hipcall, kurye için hata anonsunu çalar.
Adım 5: Python webservisi
Aşağıdaki Python betiği yalnızca standart kütüphaneyi kullanır — ek bağımlılık gerektirmez. Birden fazla test senaryosunu destekler ve Hipcall'dan gelen tüm istekleri loglar.
#!/usr/bin/env python3
"""
Hipcall hızlı arama için test servisi (sadece Python standart kütüphanesi).
Çalıştırma:
DESTINATION=905301234567 python3 hizli_arama_test_servisi.py
İsteğe bağlı ortam değişkenleri:
DESTINATION Aranacak test numarası (varsayılan: 905301234567)
BASIC_USER Basic Auth kullanıcı adı (ikisi de verilirse kontrol edilir)
BASIC_PASS Basic Auth parolası
PORT Dinlenecek port (varsayılan: 5090)
Senaryo, Hipcall paneline yazdığınız webservis URL'sinin SONUNA göre seçilir
(örnek: https://xxxx.ngrok-free.app/hizli-arama/hata):
.../hizli-arama -> 200 + geçerli destination
.../hizli-arama/hata -> 500
.../hizli-arama/bozuk-json -> 200 ama gövde geçersiz JSON
.../hizli-arama/gecersiz-numara -> 200 + destination: "3ASDASDF"
.../hizli-arama/yavas -> 5 sn bekleyip geçerli cevap (3 sn zaman aşımı testi)
"""
import base64
import json
import os
import time
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
DESTINATION = os.environ.get("DESTINATION", "905301234567")
BASIC_USER = os.environ.get("BASIC_USER")
BASIC_PASS = os.environ.get("BASIC_PASS")
PORT = int(os.environ.get("PORT", "5090"))
class Handler(BaseHTTPRequestHandler):
def _send(self, status, body, content_type="application/json"):
data = body.encode("utf-8")
self.send_response(status)
self.send_header("Content-Type", content_type)
self.send_header("Content-Length", str(len(data)))
self.end_headers()
self.wfile.write(data)
print(f"<-- {status} {body}\n")
def do_POST(self):
raw = self.rfile.read(
int(self.headers.get("Content-Length", 0))
).decode("utf-8", "replace")
print(f"--> POST {self.path}")
print(f" Content-Type : {self.headers.get('Content-Type')}")
print(f" Authorization: {self.headers.get('Authorization')}")
print(f" Ham gövde : {raw}")
try:
payload = json.loads(raw)
for key, value in payload.items():
print(f" {key:<10} = {value!r} ({type(value).__name__})")
except ValueError as e:
print(f" UYARI: Gelen gövde geçerli JSON değil: {e}")
# Basic Auth kontrolü
if BASIC_USER and BASIC_PASS:
expected = "Basic " + base64.b64encode(
f"{BASIC_USER}:{BASIC_PASS}".encode()
).decode()
if self.headers.get("Authorization") != expected:
return self._send(401, '{"error": "unauthorized"}')
# URL'nin son segmentine göre senaryo seçimi
path = self.path.split("?")[0].rstrip("/")
if path.endswith("/hata"):
return self._send(500, '{"error": "test hatasi"}')
if path.endswith("/bozuk-json"):
return self._send(200, '{"destination": ')
if path.endswith("/gecersiz-numara"):
return self._send(200, json.dumps({"destination": "3ASDASDF"}))
if path.endswith("/yavas"):
time.sleep(5)
self._send(200, json.dumps({"destination": DESTINATION}))
if __name__ == "__main__":
print(f"Test servisi :{PORT} portunda çalışıyor. Aranacak numara: {DESTINATION}\n")
ThreadingHTTPServer(("0.0.0.0", PORT), Handler).serve_forever()
Servisi başlatmak için:
DESTINATION=905301234567 python3 hizli_arama_test_servisi.py
Ardından ngrok ile dışarıya açın:
ngrok http 5090
ngrok'un verdiği HTTPS adresini Hipcall hızlı arama kaydındaki URL alanına yapıştırın (örn. https://xxxx.ngrok-free.app/hizli-arama).
Test senaryoları
Servis, URL'nin son segmentine göre farklı senaryoları simüle eder. Hipcall panelindeki webservis URL'sini değiştirerek her senaryoyu test edebilirsiniz:
| URL sonu | HTTP kodu | Davranış |
|---|---|---|
/hizli-arama |
200 | Geçerli destination döner, çağrı bağlanır. |
/hizli-arama/hata |
500 | Sunucu hatası döner, Hipcall hata anonsunu çalar. |
/hizli-arama/bozuk-json |
200 | Geçersiz JSON gövdesi döner, Hipcall ayrıştıramaz. |
/hizli-arama/gecersiz-numara |
200 | destination olarak 3ASDASDF döner, aranabilir numara değil. |
/hizli-arama/yavas |
200 | 5 saniye bekler, Hipcall'ın 3 saniyelik zaman aşımına takılır. |
Tam çağrı akışı: Terminal çıktısı
Aşağıda gerçek bir çağrıda sunucuya düşen isteklerin sıralaması yer alır. Hipcall önce webkanca olaylarını, ardından hızlı arama sorgusunu gönderir:
1) call_init webkanca olayı — Çağrı başladı:
--> POST /hipcall/events/whsec_live_XXXXXXXXXXXXXXXX
Content-Type : application/json
Ham gövde : {"data":{...,"caller_number":"+90551XXXXXXX",
"callee_number":"+90850XXXXXXX",
"uuid":"e785****-****-****-****-********87e5",
"direction":"inbound",
"call_flow":[{"action":"init",
"detail":{"id":19,"type":"speed_dial"},
"timestamp":1791891724}],...},
"event":"call_init"}
<-- 200
2) Hızlı arama sorgusu — Kurye tuşlama yaptı:
--> POST /hizli-arama
Content-Type : application/json
Authorization: Basic ZmFu****OmZh****MDM=
Ham gövde : {"timestamp":1791891730,"number":"1234",
"uuid":"e785****-****-****-****-********87e5",
"user_id":null,"speed_dial_id":19}
<-- 200 {"destination": "90530XXXXXXX"}
3) call_bridged webkanca olayı — Çağrı bağlandı:
--> POST /hipcall/events/whsec_live_XXXXXXXXXXXXXXXX
Ham gövde : {"data":{...,"call_flow":[
{"action":"bridge",...},
{"action":"route",...},
{"action":"init","detail":{"id":19,"type":"speed_dial"},...}
],...},"event":"call_bridged"}
<-- 200
4) call_hangup webkanca olayı — Çağrı kapandı:
--> POST /hipcall/events/whsec_live_XXXXXXXXXXXXXXXX
Ham gövde : {"data":{...,"call_duration":39,
"has_recording":true,
"record_url":"https://storage.hipcall.com.tr/recordings/...",
"hangup_by":"user",
"call_flow":[
{"action":"hangup","detail":{"hangup_by":"user"},...},
{"action":"bridge",...},
{"action":"route",...},
{"action":"init","detail":{"id":19,"type":"speed_dial"},...}
],...},"event":"call_hangup"}
<-- 200
Kullanılan araçlar
| Araç | Amaç |
|---|---|
| Hızlı Arama | Kurye için rakam girişi ister ve webservis uç noktanızı çağırır. |
| Webkanca | Çağrı yaşam döngüsü olaylarını (call_init, call_bridged, call_hangup) sunucunuza bildirir. |
Sonraki adımlar
- Hızlı Arama dokümantasyonu — Dahili hatları, anonsu ve webservis entegrasyonunu yapılandırın.
- Webservis uç noktanızı Basic Auth ile güvence altına alın (Hipcall panelinde Webservis kimlik doğrulama seçeneğini işaretleyin).
call_hangupolayındakirecord_urlvecall_durationalanlarını kullanarak çağrı kayıtlarını loglayın.- Sorularınızı Hipcall Topluluk platformunda paylaşın.