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.
İçindekiler
1. Mobil entegrasyonun çalışma şekli
2. Panelden platform bilgilerini alma
3. WebView URL yapısı ve anonim kullanım
4. Login sonrası kullanıcı bilgilerinin aktarılması
   4.1. Yöntem 1 — Kullanıcı bilgilerinin doğrudan aktarılması
   4.2. Yöntem 2 — JWT ile güvenli aktarım (önerilen)
   4.3. Mevcut entegrasyondan JWT’ye geçiş
5. Asistan ikonundan WebView açma
   5.1. iOS — Swift ve WKWebView
   5.2. Android — Kotlin ve WebView
6. Token süresi ve kullanıcı oturumu
7. Test ve sorun giderme
Sık sorulan sorular

1. Mobil entegrasyonun çalışma şekli

  1. 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.
  2. 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.
  3. 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.
  4. İ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ızca mobileSDKType=android yazmak 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

  1. Entegrasyon yaptığınız platform için Ayarlar → iOS veya Ayarlar → Android ekranını açın.
  2. Kullanıcı Doğrulama (JWT) sekmesine geçin.
  3. Kullanıcıları JWT ile doğrula seçeneğini açın.
  4. JWT geçerlilik süresi alanından süreyi seçin.
  5. 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ışı

  1. Backend, kullanıcının mevcut uygulama oturumunu doğrular.
  2. Kullanıcı bilgileri güvenilir sunucu kaydından alınır; istemciden gelen serbest kullanıcı kimliği imzalanmaz.
  3. Hedef platform için App ID, App Key ve JWT gizli anahtarı backend yapılandırmasından seçilir.
  4. Backend token’ı üretir ve WebView URL’sine userJwt olarak ekler.
  5. Hazır WebView URL’si mevcut login/oturum akışının yanıtıyla mobil uygulamaya aktarılır.
  6. 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ş

  1. iOS ve Android’in App ID, App Key ve JWT ayarlarını kendi ekranlarında kontrol edin.
  2. Mevcut userSourceUserId değerini JWT’deki user_id alanına tutarlı biçimde eşleyin.
  3. Backend’de token ve platforma uygun WebView URL’si üretimini hazırlayın.
  4. Mobil uygulamanın hazır adresi mevcut oturum akışından alıp WebView’da açmasını sağlayın.
  5. Doğrudan profil parametreleri yerine userJwt kullanın.
  6. 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.
  7. 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.