Jetlink Mobil WebView kullanım rehberi
Jetlink sohbet arayüzünü iOS ve Android uygulamalarınızda WebView içinde açabilir, giriş yapmış kullanıcılarınızın bilgilerini aktarabilir ve JWT ile güvenli kullanıcı doğrulaması sağlayabilirsiniz.
Bu rehber, mobil uygulama ve backend geliştiricileri için hazırlanmıştır. Kurulum, platforma özel App ID ve App Key bilgileri, WebView URL parametreleri ve login sonrası iki kullanıcı aktarım yöntemini kapsar. Mobil entegrasyonda Jetlink’in hazır WebView adresi açılır; bu rehberdeki örnekler bu URL üzerinden çalışır.
Önerilen yöntem: JWT ile kullanıcı doğrulama. Giriş yapmış kullanıcıların kimliğini Jetlink’e aktarırken sunucunuzda imzalanmış JWT kullanmanızı öneriyoruz. Doğrudan URL alanlarına göre daha güvenli olan bu yöntem, kullanıcı kimliğinin veya profil verilerinin değiştirilerek geçerli bir kimlik gibi kabul edilmesine karşı koruma sağlar. Yeni entegrasyonlarda JWT’yi tercih edin; mevcut entegrasyonlar için JWT’ye geçiş planlayın.
1. Mobil entegrasyonun çalışma şekli
- Uygulamanıza bir sohbet giriş noktası ekleyin. Menüde, üst çubukta veya kullanıcıların kolayca ulaşabileceği başka bir alanda bir ikon ya da düğme kullanabilirsiniz.
- Platforma ait WebView URL’sini hazırlayın. iOS ve Android için ilgili panelden alınan App ID ve App Key değerlerini kullanın.
- Kullanıcı durumuna göre URL’yi oluşturun. Anonim ziyaretçi için temel adresi, giriş yapmış kullanıcı için doğrudan kullanıcı alanlarını veya önerilen JWT yöntemini kullanın.
- İkona tıklandığında URL’yi uygulama içindeki WebView’da açın. Jetlink sohbet arayüzü yüklenir ve kullanıcı iletişime başlayabilir.
iOS tarafında WKWebView, Android tarafında uygulamanızın WebView bileşeni üzerinden hazırlanan HTTPS adresini yükleyebilirsiniz. Backend örnekleri hazır bağlantıyı üretir; 5. bölümdeki Swift ve Kotlin örnekleri, uygulamadaki asistan ikonuna basıldığında bu bağlantının WebView içinde nasıl açılacağını gösterir.
2. Panelden platform bilgilerini alma
Jetlink panelinde Ayarlar menüsünden ilgili mobil platform ekranına geçin. Her platformun App ID ve App Key değerlerini kendi ekranından alın.
| Platform | Panel ekranı | URL’de mobileSDKType |
|---|---|---|
| iOS | Ayarlar → iOS | ios |
| Android | Ayarlar → Android | android |
Web Görüntüleme sekmesi
iOS ekranındaki Web Görüntüleme sekmesinde Bundle Kimliği, Uygulama Kimliği, App Token, Web Görüntüleme Link ve Web Görüntüleme After Login Link alanları bulunur. Android tarafında da ilgili platformun kurulum bilgilerini ve WebView bağlantılarını kendi ekranından alın.
| Panel alanı | Kullanım |
|---|---|
| Bundle Kimliği (iOS) | iOS uygulamasının bundle tanımını gösterir. WebView URL’sindeki appId yerine bu değeri kullanmayın. |
| Uygulama Kimliği | WebView URL’sindeki appId parametresi. |
| App Token | WebView URL’sindeki appKey parametresi. |
| Web Görüntüleme Link | Kullanıcı bilgisi olmadan açılan temel WebView bağlantısı. Yanındaki kopyalama simgesiyle alınabilir. |
| Web Görüntüleme After Login Link | Kullanıcı bilgilerinin doğrudan URL parametreleriyle iletildiği bağlantı şablonu. JWT yöntemi ayrıca aşağıda açıklanır. |
| JWT gizli anahtarı | Kullanıcı Doğrulama (JWT) sekmesinde bulunur. Yalnızca backend’de token imzalamak için kullanılır. |
Platform bilgilerini karıştırmayın. iOS ve Android’in App ID ve App Key değerleri farklıdır. Android için yalnızcamobileSDKType=androidyazmak yeterli değildir; Android ekranından alınan App ID ve App Key de kullanılmalıdır. Paneldeki App Token, JWT gizli anahtarı değildir.
3. WebView URL yapısı ve anonim kullanım
Her iki platformda da temel adres https://public.jetlink.io/Home/MobilSDK şeklindedir. MobilSDK yolunu ve parametre adlarını örneklerdeki yazımlarıyla kullanın.
iOS temel bağlantısı
https://public.jetlink.io/Home/MobilSDK?appId=YOUR_IOS_APP_ID&appKey=YOUR_IOS_APP_KEY&mobileSDKType=ios&mobileDeviceName=DEVICE_NAME&mobileDeviceOS=DEVICE_OS_VERSION
Android temel bağlantısı
https://public.jetlink.io/Home/MobilSDK?appId=YOUR_ANDROID_APP_ID&appKey=YOUR_ANDROID_APP_KEY&mobileSDKType=android&mobileDeviceName=DEVICE_NAME&mobileDeviceOS=DEVICE_OS_VERSION
| Parametre | Açıklama |
|---|---|
appId | İlgili mobil platformun Uygulama Kimliği. |
appKey | İlgili mobil platformun App Token değeri. |
mobileSDKType | iOS için ios, Android için android. |
mobileDeviceName | Uygulamanın çalıştığı cihaz adı/modeli. |
mobileDeviceOS | Cihazın işletim sistemi sürümü. |
Panelde görülen {{device_name}} ve {{device_os}} gibi ifadeler yer tutucudur. URL açılmadan önce gerçek cihaz bilgileriyle değiştirilmelidir. Örneklerdeki App ID ve App Key değerleri de yer tutucudur.
URL parametre değerlerini URL-encode edin. Boşluk, +, & veya Türkçe karakter içeren değerleri ham biçimde birleştirmeyin. Özellikle telefon numarasındaki + karakteri doğru kodlanmazsa boşluk olarak yorumlanabilir. URL oluşturma kütüphaneleri kullanın; aynı değeri iki kez kodlamayın.
Kullanıcı bilgisi veya JWT eklenmemiş temel bağlantı anonim kullanım içindir. JWT doğrulaması açıkken de JWT’si olmayan ziyaretçiler Messenger’ı anonim olarak kullanabilir.
4. Login sonrası kullanıcı bilgilerinin aktarılması
Kullanıcı uygulamanızda oturum açtıktan sonra Jetlink’e iki yöntemle tanıtılabilir. Her iki yöntemde de aynı kullanıcının kalıcı kimliğini tutarlı biçimde kullanın.
| Konu | Doğrudan aktarım | JWT ile aktarım — Önerilen |
|---|---|---|
| URL’ye eklenen veri | username, userSurname, userEmail, userPhone, userSourceUserId | userJwt |
| Kimlik güvencesi | Kullanıcı alanları istemci tarafında değiştirilebilir; tek başına sunucu imzalı kimlik doğrulaması sağlamaz. | Sunucunun imzaladığı kullanıcı bilgileri kullanılır; geçerli imza olmadan değiştirilmiş kimlik bilgileri kabul edilmez. |
| Panel ayarı | JWT doğrulaması kapalı. | JWT doğrulaması açık. |
| Öneri | Mevcut entegrasyonlarla uyumluluk için açıklanır. | Yeni entegrasyonlar ve mevcut sistemlerin güvenli aktarım dönüşümü için önerilir. |
4.1. Yöntem 1 — Kullanıcı bilgilerinin doğrudan aktarılması
JWT doğrulaması kapalıyken kullanıcı bilgilerini WebView adresine ayrı parametreler olarak ekleyebilirsiniz. Paneldeki Web Görüntüleme After Login Link alanı bu yöntemin şablonunu verir.
https://public.jetlink.io/Home/MobilSDK?appId=YOUR_IOS_APP_ID&appKey=YOUR_IOS_APP_KEY&mobileSDKType=ios&mobileDeviceName=DEVICE_NAME&mobileDeviceOS=DEVICE_OS_VERSION&username=John&userSurname=Doe&userEmail=john.doe%40example.com&userPhone=%2B905551112233&userSourceUserId=100001
Android’de aynı kullanıcı parametrelerini kullanın; App ID ve App Key’i Android kanalındaki değerlerle, mobileSDKType değerini android ile değiştirin.
| Parametre | Açıklama | JWT karşılığı |
|---|---|---|
username | Kullanıcının adı; kullanıcı adı/login adı anlamında kullanılmaz. | name |
userSurname | Soyadı. | surname |
userEmail | E-posta adresi. | email |
userPhone | Telefon numarası. | phone |
userSourceUserId | Kendi sisteminizdeki benzersiz ve kalıcı kullanıcı kimliği. | user_id |
README’ye göre sisteminizde bulunan bilgilerin tümünü veya bir kısmını gönderebilirsiniz. Jetlink arayüzü bu bilgilerle açılır ve sonraki görüşmelerde kullanıcıyı bu bilgiler üzerinden tanımayı destekler. Kullanıcı eşlemesinin tutarlı olması için kalıcı kullanıcı kimliğini koruyun.
Güvenli aktarım için JWT’ye geçin. URL’de ad, telefon veya kullanıcı kimliği bulunması, bu bilgilerin sunucu tarafından doğrulandığını kanıtlamaz. Giriş yapmış kullanıcıların güvenilir biçimde tanınması için aşağıdaki JWT yöntemini öneriyoruz.
4.2. Yöntem 2 — JWT ile güvenli aktarım (önerilen)
JWT yönteminde kullanıcı bilgileri backend’de hazırlanır, ilgili kanalın JWT gizli anahtarıyla HS256 kullanılarak imzalanır ve WebView URL’sine userJwt parametresiyle eklenir. JWT açıkken kullanıcılar yalnızca geçerli token ile tanınır ve kullanıcı verileri yalnızca token’dan alınır.
JWT ayarlarına ve gizli anahtara erişim
- Entegrasyon yaptığınız platform için Ayarlar → iOS veya Ayarlar → Android ekranını açın.
- Kullanıcı Doğrulama (JWT) sekmesine geçin.
- Kullanıcıları JWT ile doğrula seçeneğini açın.
- JWT geçerlilik süresi alanından süreyi seçin.
- JWT gizli anahtarı alanının yanındaki kopyalama simgesiyle anahtarı alın ve backend’inizin gizli değer yönetiminde saklayın.
Süre seçenekleri: 5 dakika, 10 dakika, 15 dakika, 30 dakika, 1 saat, 12 saat, 1 gün, 7 gün ve 30 gün. iat değeri seçili süreden eski token’lar reddedilir.
Her platformda ilgili JWT ekranındaki anahtarı esas alın. Platformların JWT anahtarlarının aynı olduğunu varsaymayın. Örneklerde backend değişkenleri JETLINK_IOS_JWT_SECRET ve JETLINK_ANDROID_JWT_SECRET olarak ayrılmıştır; bunlar sizin sunucu yapılandırmanızdaki örnek değişken adlarıdır.
JWT gizli anahtarını mobil uygulamaya koymayın. Anahtar iOS/Android uygulama paketinde, WebView içindeki JavaScript’te veya URL’de bulunmamalıdır. Mobil uygulamaya yalnızca sunucuda imzalanmış token veya bu token’ı içeren hazır WebView adresi aktarılır.
JWT payload alanları
user_id ve iat zorunludur; diğer alanlar opsiyoneldir.
| Alan | Tip | Açıklama |
|---|---|---|
user_id | String · Zorunlu | Kullanıcının kendi sisteminizdeki benzersiz, kalıcı kimliği. |
iat | Number · Zorunlu | Token üretim zamanı; Unix zaman damgası, saniye. |
email | String · Opsiyonel | E-posta. |
phone | String · Opsiyonel | Telefon. |
name | String · Opsiyonel | Ad. |
surname | String · Opsiyonel | Soyad. |
avatar_url | String · Opsiyonel | Profil görseli URL’si. |
custom_fields | Object · Opsiyonel | Rol, departman gibi ek kullanıcı bilgileri. |
{ "user_id": "100001", "email": "john.doe@example.com", "phone": "905551112233", "name": "John", "surname": "Doe", "avatar_url": "https://example.com/avatar.png", "custom_fields": { "role": "customer", "department": "sales" }, "iat": 1790860807 }
Örnekteki iat yalnızca yapıyı gösterir. Üretimde güncel sunucu zamanını kullanın; sabit zaman damgasını kopyalamayın. custom_fields içindeki rol gibi bilgiler, uygulamanızın kendi yetki kontrollerinin yerine geçmez.
Login sonrası backend akışı
- Backend, kullanıcının mevcut uygulama oturumunu doğrular.
- Kullanıcı bilgileri güvenilir sunucu kaydından alınır; istemciden gelen serbest kullanıcı kimliği imzalanmaz.
- Hedef platform için App ID, App Key ve JWT gizli anahtarı backend yapılandırmasından seçilir.
- Backend token’ı üretir ve WebView URL’sine
userJwtolarak ekler. - Hazır WebView URL’si mevcut login/oturum akışının yanıtıyla mobil uygulamaya aktarılır.
- Kullanıcı sohbeti açtığında mobil uygulama bu URL’yi WebView’da yükler.
Aşağıdaki örnekler mevcut backend akışında çalıştırılan yardımcı fonksiyonlardır. Token üretimini WebView içindeki JavaScript’e taşımayın. WebView sayfasından token almak için ayrı bir API çağrısı yapılmaz; mobil uygulamaya mevcut doğrulanmış oturum akışı üzerinden hazır adres verildiği varsayılır.
Node.js — Token ve WebView URL’sini backend’de oluşturma
npm install jsonwebtoken
const jwt = require("jsonwebtoken"); function createJetlinkMobileUrl(user, platform, device) { // user: backend'in doğruladığı kullanıcı kaydı. if (!user || user.id == null || String(user.id).trim() === "") { throw new Error("Doğrulanmış kullanıcı kimliği zorunludur."); } if (platform !== "ios" && platform !== "android") { throw new Error("Desteklenmeyen mobil platform."); } const prefix = platform === "ios" ? "JETLINK_IOS" : "JETLINK_ANDROID"; const appId = process.env[prefix + "_APP_ID"]; const appKey = process.env[prefix + "_APP_KEY"]; const secret = process.env[prefix + "_JWT_SECRET"]; if (!appId || !appKey || !secret) { throw new Error("İlgili platformun Jetlink yapılandırması eksik."); } const payload = { user_id: String(user.id), email: user.email, phone: user.phone, name: user.firstName, surname: user.lastName, avatar_url: user.avatarUrl, custom_fields: { role: user.role, department: user.department } }; // jsonwebtoken, güncel iat değerini saniye olarak otomatik ekler. const userJwt = jwt.sign(payload, secret, { algorithm: "HS256" }); const url = new URL("https://public.jetlink.io/Home/MobilSDK"); url.searchParams.set("appId", appId); url.searchParams.set("appKey", appKey); url.searchParams.set("mobileSDKType", platform); url.searchParams.set("mobileDeviceName", device.name); url.searchParams.set("mobileDeviceOS", device.osVersion); url.searchParams.set("userJwt", userJwt); return url.toString(); } // Mevcut backend login/oturum akışınız içinde: // const webViewUrl = createJetlinkMobileUrl(verifiedUser, "ios", device); // Hazır URL'yi oturum yanıtınızla mobil uygulamaya aktarın. // Android için platform = "android" kullanın.
verifiedUser ve device mevcut uygulamanızdaki veri nesnelerini temsil eder. Cihaz adı/sürümü kimlik doğrulama kanıtı değildir. URL oluşturucu değerleri kodlar; userJwt dahil parametrelere önceden ayrıca URL encoding uygulamayın.
C# / ASP.NET Core — Token ve WebView URL’sini backend’de oluşturma
dotnet add package System.IdentityModel.Tokens.Jwt
Aşağıdaki model ve yardımcı sınıf, kullanıcı JWT’sini üretir. Kullanıcı nesnesini backend’in doğruladığı oturum ve kullanıcı kaydından doldurun.
using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Text; using Microsoft.IdentityModel.Tokens; public sealed record JetlinkUser( string Id, string? Email = null, string? Phone = null, string? Name = null, string? Surname = null, string? AvatarUrl = null, Dictionary<string, object>? CustomFields = null); public static class JetlinkTokenFactory { public static string Create(JetlinkUser user, string secret) { if (string.IsNullOrWhiteSpace(user.Id)) throw new ArgumentException("Kullanıcı kimliği zorunludur."); if (string.IsNullOrWhiteSpace(secret)) throw new ArgumentException("JWT gizli anahtarı zorunludur."); // Panelden alınan anahtarın metin değerini kullanın. var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret)); var credentials = new SigningCredentials( signingKey, SecurityAlgorithms.HmacSha256); var payload = new JwtPayload { ["user_id"] = user.Id, ["iat"] = DateTimeOffset.UtcNow.ToUnixTimeSeconds() }; // Boş opsiyonel alanları göndermeyin. if (!string.IsNullOrWhiteSpace(user.Email)) payload["email"] = user.Email; if (!string.IsNullOrWhiteSpace(user.Phone)) payload["phone"] = user.Phone; if (!string.IsNullOrWhiteSpace(user.Name)) payload["name"] = user.Name; if (!string.IsNullOrWhiteSpace(user.Surname)) payload["surname"] = user.Surname; if (!string.IsNullOrWhiteSpace(user.AvatarUrl)) payload["avatar_url"] = user.AvatarUrl; if (user.CustomFields is { Count: > 0 }) payload["custom_fields"] = user.CustomFields; var token = new JwtSecurityToken(new JwtHeader(credentials), payload); return new JwtSecurityTokenHandler().WriteToken(token); } }
Üretilen token’ı ilgili platformun bağlantısına eklemek için aşağıdaki yardımcı sınıfı kullanın. QueryHelpers, ASP.NET Core uygulamalarındaki URL oluşturma yardımcısıdır.
using System; using System.Collections.Generic; using Microsoft.AspNetCore.WebUtilities; public static class JetlinkMobileUrlFactory { public static string Create( JetlinkUser verifiedUser, string platform, string deviceName, string deviceOsVersion) { var prefix = platform switch { "ios" => "JETLINK_IOS", "android" => "JETLINK_ANDROID", _ => throw new ArgumentException("Desteklenmeyen mobil platform.") }; string RequiredSetting(string suffix) { var value = Environment.GetEnvironmentVariable(prefix + suffix); return !string.IsNullOrWhiteSpace(value) ? value : throw new InvalidOperationException(prefix + suffix + " tanımlanmalıdır."); } var userJwt = JetlinkTokenFactory.Create( verifiedUser, RequiredSetting("_JWT_SECRET")); return QueryHelpers.AddQueryString( "https://public.jetlink.io/Home/MobilSDK", new Dictionary<string, string?> { ["appId"] = RequiredSetting("_APP_ID"), ["appKey"] = RequiredSetting("_APP_KEY"), ["mobileSDKType"] = platform, ["mobileDeviceName"] = deviceName, ["mobileDeviceOS"] = deviceOsVersion, ["userJwt"] = userJwt }); } } // Mevcut backend login/oturum akışınız içinde: // var webViewUrl = JetlinkMobileUrlFactory.Create( // verifiedUser, "ios", deviceName, deviceOsVersion); // Hazır URL'yi oturum yanıtınızla mobil uygulamaya aktarın.
Her iki backend örneği için JETLINK_IOS_APP_ID, JETLINK_IOS_APP_KEY, JETLINK_IOS_JWT_SECRET ile bunların JETLINK_ANDROID_... karşılıklarını ilgili panel değerleriyle tanımlayın. App Key ile JWT gizli anahtarını birbirinin yerine kullanmayın. Gizli anahtarı panelden kopyalanan metin olarak kullanın; kendiliğinizden Base64/hex çözümleme uygulamayın.
Oluşacak JWT’li WebView bağlantıları
SERVER_GENERATED_USER_JWT, backend’de üretilen token’ın yerini gösterir. Mobil uygulama yalnızca hazırlanmış URL’yi WebView’da açar.
iOS: https://public.jetlink.io/Home/MobilSDK?appId=YOUR_IOS_APP_ID&appKey=YOUR_IOS_APP_KEY&mobileSDKType=ios&mobileDeviceName=DEVICE_NAME&mobileDeviceOS=DEVICE_OS_VERSION&userJwt=SERVER_GENERATED_USER_JWT Android: https://public.jetlink.io/Home/MobilSDK?appId=YOUR_ANDROID_APP_ID&appKey=YOUR_ANDROID_APP_KEY&mobileSDKType=android&mobileDeviceName=DEVICE_NAME&mobileDeviceOS=DEVICE_OS_VERSION&userJwt=SERVER_GENERATED_USER_JWT
Mobil URL’de parametre adı tam olarak userJwt olmalıdır. Profil alanlarını token payload’una koyun; JWT açıkken URL’de ayrıca username, userEmail gibi alanlar göndererek kullanıcı verisini değiştirmeye çalışmayın.
JWT imzası şifreleme değildir. Token URL’de taşındığı için mobil uygulama ve WebView tarafından görülebilir; payload okunabilir. Güvenlik, imzalama anahtarının yalnızca sunucuda kalmasına dayanır. Tam URL’yi veya token’ı log, analitik ve hata raporlarına kaydetmeyin; şifre veya başka servislerin erişim token’larını payload’a koymayın.
4.3. Mevcut entegrasyondan JWT’ye geçiş
- iOS ve Android’in App ID, App Key ve JWT ayarlarını kendi ekranlarında kontrol edin.
- Mevcut
userSourceUserIddeğerini JWT’dekiuser_idalanına tutarlı biçimde eşleyin. - Backend’de token ve platforma uygun WebView URL’si üretimini hazırlayın.
- Mobil uygulamanın hazır adresi mevcut oturum akışından alıp WebView’da açmasını sağlayın.
- Doğrudan profil parametreleri yerine
userJwtkullanın. - JWT doğrulamasını açmayı backend ve mobil uygulama sürümleriyle birlikte planlayın. Eski uygulama sürümü token göndermiyorsa JWT açıldığında anonim olarak devam eder.
- Her iki platformda doğrulanmış kullanıcı, anonim kullanıcı ve hesap değiştirme senaryolarını test edin.
Kullanıcılar kanallar arasında ortaktır. Tam koruma için JWT’yi Web Messenger, iOS ve Android dahil kullandığınız tüm ilgili kanallarda açın.
5. Asistan ikonundan WebView açma
Mobil uygulamanın görevi, tamamen hazırlanmış Jetlink bağlantısını bir WebView ekranında açmaktır. Kullanıcı uygulamadaki asistan ikonuna dokunur; uygulama sohbet ekranını açar ve hazır URL’yi yükler. JWT üretimi ve URL hazırlama önceki bölümdeki gibi backend’de tamamlanır.
| Bileşen | Sorumluluk |
|---|---|
| Backend | Kullanıcıyı doğrulamak, gerekiyorsa JWT üretmek ve platforma uygun tam WebView URL’sini hazırlamak. |
| Mobil uygulama | Hazır URL’yi mevcut oturum akışından almak, asistan ikonunu göstermek ve tıklamada WebView ekranını açmak. |
| Jetlink WebView sayfası | URL’deki kanal ve kullanıcı bilgileriyle sohbet arayüzünü yüklemek. |
Aşağıdaki örneklerde jetlinkWebViewUrl değerinin uygulamanın mevcut backend akışından alınmış, platforma uygun ve kullanılabilir tam URL olduğu varsayılır. Örneklerde yeni bir token API isteği veya istemci tarafında token üretimi yapılmaz. Anonim bağlantı, doğrudan kullanıcı bilgili bağlantı ve JWT’li bağlantı aynı WebView açma koduyla kullanılabilir.
5.1. iOS — Swift ve WKWebView
UIKit kullanan bu örnekte uygulama ekranına bir asistan ikon düğmesi eklenir. Düğmeye dokunulduğunda, hazır URL’yi yükleyen ayrı bir WKWebView ekranı açılır. Kapat düğmesi kullanıcıyı uygulama ekranına döndürür. Sistem ikonunun kullanımı iOS 13 ve üzeri içindir.
Asistan ikonu bulunan uygulama ekranı
import UIKit final class HomeViewController: UIViewController { // Mevcut backend/oturum akışınızdan gelen tam WebView URL'si. var jetlinkWebViewUrl: String? override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground let assistantButton = UIButton(type: .system) assistantButton.setImage( UIImage(systemName: "message.fill"), for: .normal) assistantButton.accessibilityLabel = "Asistanı aç" assistantButton.translatesAutoresizingMaskIntoConstraints = false assistantButton.addTarget( self, action: #selector(openAssistant), for: .touchUpInside) view.addSubview(assistantButton) NSLayoutConstraint.activate([ assistantButton.widthAnchor.constraint(equalToConstant: 56), assistantButton.heightAnchor.constraint(equalToConstant: 56), assistantButton.trailingAnchor.constraint( equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16), assistantButton.bottomAnchor.constraint( equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16) ]) } @objc private func openAssistant() { guard let value = jetlinkWebViewUrl, let url = URL(string: value), url.scheme == "https", url.host == "public.jetlink.io", url.path == "/Home/MobilSDK" else { let alert = UIAlertController( title: "Asistan açılamadı", message: "Sohbet bağlantısı henüz hazır değil.", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "Tamam", style: .default)) present(alert, animated: true) return } let chat = JetlinkChatViewController(webViewURL: url) let navigation = UINavigationController(rootViewController: chat) navigation.modalPresentationStyle = .fullScreen present(navigation, animated: true) } }
Hazır bağlantıyı yükleyen sohbet ekranı
import UIKit import WebKit final class JetlinkChatViewController: UIViewController, WKNavigationDelegate { private let webViewURL: URL private var webView: WKWebView! init(webViewURL: URL) { self.webViewURL = webViewURL super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("Bu ekran init(webViewURL:) ile oluşturulmalıdır.") } override func viewDidLoad() { super.viewDidLoad() title = "Asistan" view.backgroundColor = .systemBackground navigationItem.leftBarButtonItem = UIBarButtonItem( title: "Kapat", style: .plain, target: self, action: #selector(closeChat)) let configuration = WKWebViewConfiguration() if #available(iOS 14.0, *) { configuration.defaultWebpagePreferences.allowsContentJavaScript = true } webView = WKWebView(frame: .zero, configuration: configuration) webView.navigationDelegate = self webView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(webView) NSLayoutConstraint.activate([ webView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), webView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), webView.leadingAnchor.constraint(equalTo: view.leadingAnchor), webView.trailingAnchor.constraint(equalTo: view.trailingAnchor) ]) // URL tamamen hazırdır; burada token veya query parametresi üretilmez. webView.load(URLRequest(url: webViewURL)) } func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { // URL veya token'ı loglamadan kullanıcıya hata gösterin. guard (error as NSError).code != NSURLErrorCancelled else { return } let alert = UIAlertController( title: "Bağlantı kurulamadı", message: "İnternet bağlantınızı kontrol edip yeniden deneyin.", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "Tamam", style: .default)) present(alert, animated: true) } @objc private func closeChat() { webView.stopLoading() dismiss(animated: true) } }
HomeViewController.jetlinkWebViewUrl alanını mevcut oturum akışınızdan gelen iOS URL’siyle doldurun. Bu atamayı ve ekran işlemlerini ana iş parçacığında yapın. URL’nin içine yeniden App ID, App Key veya token eklemeyin; hazır adresi olduğu gibi yükleyin. URL doğrulaması biçim/adres kontrolüdür; token’ın imza veya süre doğrulamasını yapmaz.
5.2. Android — Kotlin ve WebView
Bu örnek AndroidX Activity kullanan bir Kotlin uygulaması içindir. Ana ekrandaki asistan ikonu, hazır URL’yi ayrı bir Activity’ye iletir; Activity adresi WebView.loadUrl ile açar.
AndroidManifest.xml ayarları
İnternet iznini manifest altında, sohbet Activity’sini mevcut application öğesinin içine ekleyin. Ana Activity’nizin mevcut tanımını koruyun; aşağıdaki gösterim birleştirilecek alanları belirtir.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <uses-permission android:name="android.permission.INTERNET" /> <application> <!-- Mevcut uygulama ve ana Activity ayarlarınız burada kalır. --> <activity android:name=".JetlinkChatActivity" android:exported="false" /> </application> </manifest>
Asistan ikonu bulunan uygulama ekranı
import android.content.Intent import android.net.Uri import android.os.Bundle import android.view.Gravity import android.widget.FrameLayout import android.widget.ImageButton import android.widget.Toast import androidx.activity.ComponentActivity class MainActivity : ComponentActivity() { // Mevcut backend/oturum akışınızdan gelen tam Android WebView URL'si. var jetlinkWebViewUrl: String? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val root = FrameLayout(this) setContentView(root) val assistantButton = ImageButton(this).apply { setImageResource(android.R.drawable.ic_menu_help) contentDescription = "Asistanı aç" setOnClickListener { openAssistant() } } val density = resources.displayMetrics.density val size = (56 * density).toInt() val margin = (16 * density).toInt() root.addView(assistantButton, FrameLayout.LayoutParams( size, size, Gravity.BOTTOM or Gravity.END ).apply { setMargins(margin, margin, margin, margin) }) } private fun openAssistant() { val value = jetlinkWebViewUrl val uri = value?.let { Uri.parse(it) } if (uri == null || uri.scheme != "https" || uri.host != "public.jetlink.io" || uri.path != "/Home/MobilSDK") { Toast.makeText(this, "Sohbet bağlantısı henüz hazır değil.", Toast.LENGTH_SHORT).show() return } startActivity(Intent(this, JetlinkChatActivity::class.java).apply { putExtra(JetlinkChatActivity.EXTRA_URL, value) }) } }
Hazır bağlantıyı yükleyen sohbet Activity’si
import android.annotation.SuppressLint import android.net.Uri import android.os.Bundle import android.webkit.WebView import android.webkit.WebViewClient import android.widget.Button import android.widget.LinearLayout import androidx.activity.ComponentActivity import androidx.activity.OnBackPressedCallback class JetlinkChatActivity : ComponentActivity() { companion object { const val EXTRA_URL = "jetlink_webview_url" } private var webView: WebView? = null @SuppressLint("SetJavaScriptEnabled") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val value = intent.getStringExtra(EXTRA_URL) val uri = value?.let { Uri.parse(it) } if (uri == null || uri.scheme != "https" || uri.host != "public.jetlink.io" || uri.path != "/Home/MobilSDK") { finish() return } val root = LinearLayout(this).apply { orientation = LinearLayout.VERTICAL } val closeButton = Button(this).apply { text = "Kapat" setOnClickListener { finish() } } val chat = WebView(this).apply { settings.javaScriptEnabled = true settings.domStorageEnabled = true webViewClient = WebViewClient() } webView = chat root.addView(closeButton, LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)) root.addView(chat, LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, 0, 1f)) setContentView(root) onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { if (chat.canGoBack()) chat.goBack() else finish() } }) // URL tamamen hazırdır; burada token veya query parametresi üretilmez. chat.loadUrl(uri.toString()) } override fun onDestroy() { webView?.let { chat -> chat.stopLoading() (chat.parent as? android.view.ViewGroup)?.removeView(chat) chat.destroy() } webView = null super.onDestroy() } }
Sınıfları uygulamanızın package yapısına yerleştirin; manifest’teki Activity adı da aynı sınıfı göstermelidir. MainActivity.jetlinkWebViewUrl alanına backend’den gelen Android URL’sini atayın. Mevcut bir ana ekranınız varsa tüm ekranı değiştirmek yerine ikon ve tıklama işleyicisini o ekrana ekleyin.
Örnekte JavaScript ve DOM depolama etkinleştirilir; WebViewClient normal sayfa gezinmesini WebView içinde tutar. Android sistem geri hareketi önce WebView geçmişine döner; geçmiş yoksa sohbet ekranını kapatır. Kapat düğmesi doğrudan uygulama ekranına döner. Uygulamanızın mevcut edge-to-edge ve sistem çubuğu boşluklarını bu ekrana da uygulayın.
Örneklerin kapsamı
Bu örnekler asistan ikonuna tıklama, hazır URL’yi WebView’da açma ve sohbet ekranından çıkış akışını gösterir. Dosya seçimi, kamera/mikrofon erişimi, indirme, yeni pencere veya harici bağlantı davranışları kullanılıyorsa bunları uygulamanızın WebView delegeleri/istemcileri ve izin akışlarıyla ayrıca ele alın. Bu işlevlerin tümünün temel açılış koduyla çalışacağı varsayılmamalıdır.
WebView’ı kapatmak veya Android’de destroy() çağırmak kullanıcı oturumunu temizleyen bir işlem olarak değerlendirilmemelidir. Logout ve hesap değişimi için 6. bölümdeki kontrolleri uygulayın. Native örnekleri kendi iOS/Android projenizde derleyip gerçek cihazda test edin.
6. Token süresi ve kullanıcı oturumu
Token’ı ne zaman üretmelisiniz?
Her sayfa yüklemesinde veya uygulama oturumunda yeni token üretin. Kullanıcı login olduktan uzun süre sonra sohbeti açarsa, oturum başında hazırlanan URL’deki token artık eski olabilir. WebView’ın yükleyeceği adresteki token’ın seçilen geçerlilik süresi içinde olduğundan emin olun; gerekiyorsa mevcut backend oturum akışınızla yeni token içeren adres hazırlayın.
iat üretim anıdır ve saniye cinsinden olmalıdır. Node.js örneğinde otomatik eklenir; C# örneğinde DateTimeOffset.UtcNow.ToUnixTimeSeconds() ile oluşturulur. Sunucu saatini doğru tutun. Belgelenen geçerlilik kontrolü iat ve panel süresine dayanır; yalnızca exp eklemek bu kontrolün yerine geçmez.
Logout ve hesap değiştirme
Kullanıcı uygulamadan çıktığında eski token’ı veya token içeren eski WebView URL’sini sonraki kullanıcı için kullanmayın. Yeni kullanıcı için backend’de yeni token üretin. WebView’ı kapatmak tek başına çerezlerin, yerel depolamanın veya Messenger oturumunun temizlendiğini göstermez; kullandığınız mobil entegrasyonda oturum temizliğini ve yeniden açılış davranışını doğrulayın.
A kullanıcısından çıkış yapıp B kullanıcısıyla giriş yaptığınızda A’ya ait kimlik veya konuşmaların görünmediğini test edin. Token süresinin dolmasından, açık sohbetin otomatik kapanacağı veya SDK’nın token’ı kendiliğinden yenileyeceği sonucu çıkarılmamalıdır.
Anahtar değişikliği
JWT ekranındaki yenileme simgesiyle anahtar değiştirildiğinde ilgili backend yapılandırmasını da kontrollü biçimde güncelleyin. Eski anahtarla üretilmiş token’ların çalışmaya devam edeceğini varsaymayın; yeni token içeren WebView bağlantılarıyla doğrulama yapın.
7. Test ve sorun giderme
iOS ve Android’i kendi kanal bilgileriyle ayrı ayrı test edin. Sohbet ekranının görünmesi, doğru kullanıcı kimliğinin tanındığını tek başına göstermez; Jetlink’te oluşan konuşmanın kullanıcı bilgilerini de kontrol edin.
| Test / belirti | Kontrol veya beklenen sonuç |
|---|---|
| Asistan ikonuna tıklama | Sohbet uygulama içi WebView ekranında açılmalı, hazır URL doğru platform için yüklenmelidir. |
| Kapat ve geri davranışı | iOS Kapat ve Android Kapat/geri işlemlerinin uygulama ekranına beklenen şekilde döndüğünü doğrulayın. |
| Anonim temel URL | Messenger anonim açılmalıdır. JWT açıkken token olmadan anonim kullanım devam eder. |
| JWT kapalı, doğrudan kullanıcı alanları | Gönderilen kullanıcı bilgileri ve kalıcı kullanıcı kimliği kontrol edilir. |
| JWT açık, geçerli token | Kullanıcı token’daki user_id ile tanınır; profil alanları doğru kullanıcıya aittir. |
| Yanlış anahtar veya değiştirilmiş payload | Token doğrulanmış kullanıcı kimliği olarak kabul edilmemelidir. |
| Eksik user_id / iat veya eski iat | Geçerli kullanıcı doğrulaması sağlamamalıdır; güncel ve eksiksiz token ile tekrar denenir. |
| WebView açılmıyor veya yanlış kanal görünüyor | App ID/App Key’in aynı ve doğru platform ekranından alındığını, mobileSDKType değerini, HTTPS erişimini ve WebView yükleme hatalarını kontrol edin. |
| Kullanıcı anonim görünüyor | userJwt adını, URL’ye gerçekten token eklendiğini, imzayı, token yaşını ve ilgili platformun JWT ayarını kontrol edin. |
| Ad veya telefon bozuk aktarılıyor | Parametre encoding’ini; özellikle boşluk, +, & ve Türkçe karakterleri kontrol edin. |
| JWT yanında farklı açık kullanıcı verisi | JWT açıkken verilerin yalnızca token’dan alındığını doğrulayın. |
| Hesap değiştirdikten sonra eski kullanıcı görünüyor | Eski URL/token kullanımını, WebView depolamasını ve oturum temizliğini inceleyin. |
| Bir platformda çalışıp diğerinde çalışmıyor | Her platformun ayrı App ID, App Key, JWT anahtarı, doğrulama ayarı ve mobileSDKType eşleşmesini kontrol edin. |
Destek için platform, uygulama/işletim sistemi sürümü, ilgili kanal, sorun zamanı ve maskelenmiş hata bilgilerini paylaşın. JWT gizli anahtarını veya token içeren tam WebView URL’sini destek kayıtlarına eklemeyin.
Sık sorulan sorular
iOS bağlantısında yalnızca mobileSDKType değiştirerek Android’e geçebilir miyim?
Hayır. Android ekranından alınan App ID ve App Key kullanılmalı, mobileSDKType değeri de android olmalıdır. JWT kullanılıyorsa Android kanalının JWT ayarlarını da esas alın.
App Token ile userJwt aynı şey mi?
Hayır. Paneldeki App Token, URL’nin appKey parametresidir. userJwt ise backend’in kullanıcı bilgilerini imzalayarak ürettiği, kullanıcıya ve üretim zamanına bağlı token’dır. JWT gizli anahtarı bunlardan ayrı bir sunucu sırrıdır.
JWT açıkken giriş yapmamış kullanıcılar sohbet edebilir mi?
Evet. JWT’si olmayan ziyaretçiler anonim olarak Messenger’ı kullanabilir.
Token mobil uygulamada üretilebilir mi?
Token imzalama işlemini yalnızca backend’de yapın. Mobil uygulamaya JWT gizli anahtarını dağıtmayın; uygulama sunucunun hazırladığı token’ı içeren adresi açmalıdır.
JWT kullanınca kullanıcı bilgileri şifrelenmiş olur mu?
Hayır. JWT imzası veri bütünlüğü ve kimlik doğrulamasını destekler; payload’u gizlemez. İletimi HTTPS ile yapın ve token’ı hassas bir değer olarak ele alın.
Doğrudan aktarım yerine neden JWT öneriliyor?
Doğrudan URL alanları istemcide değiştirilebilir. JWT’de kullanıcı bilgileri backend tarafından imzalandığı için, gizli anahtarı bilmeyen bir istemci değiştirdiği bilgiler için geçerli imza üretemez. Bu nedenle login sonrası kullanıcı aktarımında JWT önerilen yöntemdir.
Kaynaklar: Paylaşılan Jetlink iOS WebView README dokümanı, iOS Web Görüntüleme ve Kullanıcı Doğrulama (JWT) ekranları, Android platform farklarına ilişkin ürün açıklamaları. Resmî site: jetlink.io. Native WebView referansları: Apple WKWebView ve Android WebView.