Flow ve paywall olaylarını yönetme - Unity

Bu kılavuz, satın almalar, yeniden yüklemeler, ürün seçimi ve flow rendering için event yönetimini kapsar. Ayrıca buton işleme (flow’u kapatma, bağlantı açma vb.) özelliklerini de uygulamanız gerekir. Ayrıntılar için flow aksiyonlarını yönetme kılavuzumuza bakın.

Flow Builder veya Paywall Builder ile yapılandırılan flow’lar ve paywall’lar, satın alma yapmak ve geri yüklemek için ekstra kod gerektirmez. Ancak, uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar; düğme basışlarını (kapat düğmeleri, URL’ler, ürün seçimleri vb.) ve satın alma ile ilgili eylemlere ait bildirimleri içerir. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz.

Adapty SDK’nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall’ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren örnek uygulamalarımıza göz atın.

Olayları Yönetme

Mobil uygulamanızdaki flow ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için IAdaptyFlowsEventsListener arayüzünü uygulayın ve Adapty.SetFlowsEventsListener() ile kaydedin:

using UnityEngine;
using AdaptySDK;

public class FlowEventsHandler : MonoBehaviour, IAdaptyFlowsEventsListener
{
    void Start()
    {
        Adapty.SetFlowsEventsListener(this);
    }

    // Implement all interface methods below
}

Bu metodlar, flow olaylarına yanıt vermek için kendi özel mantığınızı eklediğiniz yerlerdir. SDK bunlara herhangi bir varsayılan davranış uygulamaz: başarılı bir satın alma veya hata, görünümü otomatik olarak kapatmaz — uygun olduğunda view.Dismiss(...) metodunu kendiniz çağırın.

Kullanıcı tarafından tetiklenen olaylar

Flow göründü

Flow görünümü ekranda sunulduğunda tetiklenir.

iOS’ta, bir kullanıcı flow içindeki web paywall düğmesine dokunduğunda ve web paywall uygulama içi bir tarayıcıda açıldığında da tetiklenir.

public void FlowViewDidAppear(AdaptyUIFlowView view) { }

Flow kayboldu

Flow görünümü ekrandan kapatıldığında tetiklenir.

iOS’ta, bir flow içinde uygulama içi tarayıcıda açılan web paywall’ın ekrandan kaybolması durumunda da tetiklenir.

public void FlowViewDidDisappear(AdaptyUIFlowView view) { }

Ürün seçimi

Bir ürün satın alma için seçildiğinde (kullanıcı veya sistem tarafından) tetiklenir.

public void FlowViewDidSelectProduct(
    AdaptyUIFlowView view,
    string productId
) { }
Olay örneği (Genişletmek için tıklayın)
{
  "productId": "premium_monthly"
}

Satın alma başlatıldı

Bir kullanıcı satın alma işlemini başlattığında tetiklenir.

public void FlowViewDidStartPurchase(
    AdaptyUIFlowView view,
    AdaptyPaywallProduct product
) { }

Observer mode’da, bir flow’dan başlatılan satın almalar IAdaptyUIObserverModeResolver’ınıza iletilir.

Etkinlik örneği (Genişletmek için tıklayın)
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

Başarılı, iptal edilmiş veya beklemedeki satın alma

Satın alma başarılı olursa, kullanıcı satın almayı iptal ederse ya da satın alma beklemede görünürse bu metod çağrılır. Kullanıcı iptalleri ve beklemedeki ödemeler (örn. ebeveyn onayı gerekmesi) bu metodu tetikler, FlowViewDidFailPurchase metodunu değil.

Flow, satın alma işleminden sonra siz kapatana kadar açık kalmaya devam eder; bu nedenle kullanıcı erişim kazandıktan sonra view.Dismiss(...) metodunu kendiniz çağırın:

public void FlowViewDidFinishPurchase(
    AdaptyUIFlowView view,
    AdaptyPaywallProduct product,
    AdaptyPurchaseResult purchasedResult
) {
    switch (purchasedResult.Type) {
        case AdaptyPurchaseResultType.Success:
            // Check if user has access to premium features
            if (purchasedResult.Profile != null
                && purchasedResult.Profile.AccessLevels.TryGetValue("premium", out var premium)
                && premium.IsActive) {
                view.Dismiss(null);
            }
            break;
        case AdaptyPurchaseResultType.Pending:
            // Handle pending purchase (e.g., user will pay offline with cash)
            break;
        case AdaptyPurchaseResultType.UserCancelled:
            // Handle user cancellation
            break;
        default:
            break;
    }
}
Etkinlik örnekleri (Genişletmek için tıklayın)
// Successful purchase
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "purchaseResult": {
    "type": "Success",
    "profile": {
      "accessLevels": {
        "premium": {
          "id": "premium",
          "isActive": true,
          "expiresAt": "2024-02-15T10:30:00Z"
        }
      }
    }
  }
}

// Cancelled purchase
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "purchaseResult": {
    "type": "UserCancelled"
  }
}

// Pending purchase
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "purchaseResult": {
    "type": "Pending"
  }
}

Başarılı satın alma durumunda flow ekranını kapatmanızı öneririz.

Başarısız satın alma

Bir satın alma hata nedeniyle başarısız olursa bu metot çağrılır. StoreKit/Google Play Billing hataları (ödeme kısıtlamaları, geçersiz ürünler, ağ hataları), işlem doğrulama hataları ve sistem hataları bu kapsama girer. Kullanıcı iptalleri FlowViewDidFinishPurchase’i iptal edilmiş sonucuyla tetikler; bekleyen ödemeler ise bu metodu tetiklemez.

public void FlowViewDidFailPurchase(
    AdaptyUIFlowView view,
    AdaptyPaywallProduct product,
    AdaptyError error
) { }
Olay örneği (Genişletmek için tıklayın)
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "error": {
    "code": "purchase_failed",
    "message": "Purchase failed due to insufficient funds",
    "details": {
      "underlyingError": "Insufficient funds in account"
    }
  }
}

Geri yükleme başladı

Kullanıcı geri yükleme sürecini başlattığında tetiklenir:

public void FlowViewDidStartRestore(AdaptyUIFlowView view) { }

Başarılı geri yükleme

Satın alma geri yükleme işlemi başarıyla tamamlandığında çağrılır. Siz kapatana kadar flow açık kalır:

public void FlowViewDidFinishRestore(
    AdaptyUIFlowView view,
    AdaptyProfile profile
) {
    // Check if user has access to premium features
    if (profile.AccessLevels.TryGetValue("premium", out var premium) && premium.IsActive) {
        view.Dismiss(null);
    }
}
Etkinlik örneği (Genişletmek için tıklayın)
{
  "profile": {
    "accessLevels": {
      "premium": {
        "id": "premium",
        "isActive": true,
        "expiresAt": "2024-02-15T10:30:00Z"
      }
    },
    "subscriptions": [
      {
        "vendorProductId": "premium_monthly",
        "isActive": true,
        "expiresAt": "2024-02-15T10:30:00Z"
      }
    ]
  }
}

accessLevel erişimine sahip kullanıcı için ekranı kapatmanızı öneririz. Bunu nasıl kontrol edeceğinizi öğrenmek için Abonelik durumu konusuna bakın.

Başarısız geri yükleme

Satın alma geri yüklemesi başarısız olduğunda tetiklenir:

public void FlowViewDidFailRestore(
    AdaptyUIFlowView view,
    AdaptyError error
) { }
Olay örneği (Genişletmek için tıklayın)
{
  "error": {
    "code": "restore_failed",
    "message": "Purchase restoration failed",
    "details": {
      "underlyingError": "No previous purchases found"
    }
  }
}

Web ödeme navigasyonu tamamlandı

Satın alma için bir web paywall açmaya çalışıldıktan sonra (başarılı veya başarısız olsun), bu metod çağrılacaktır:

public void FlowViewDidFinishWebPaymentNavigation(
    AdaptyUIFlowView view,
    AdaptyPaywallProduct product,
    AdaptyError error
) { }

Parametreler:

  • product: Web paywall’ın açıldığı (veya açılmaya çalışıldığı) ürün ya da null
  • error: Web paywall başarıyla açıldıysa null, başarısız olduysa bir AdaptyError
Olay örnekleri (Genişletmek için tıklayın)
// Successful navigation
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "error": null
}

// Failed navigation
{
  "product": null,
  "error": {
    "code": "wrong_param",
    "message": "Current method is not available for this product",
    "details": {
      "underlyingError": "Product not configured for web purchases"
    }
  }
}

Veri çekme ve render işlemleri

Ürün yükleme hataları

Ürün yükleme başarısız olduğunda tetiklenir ve AdaptyError döndürür. Başlatma sırasında ürün dizisini geçmediyseniz AdaptyUI gerekli nesneleri sunucudan kendi alır. Bu işlem başarısız olabilir; AdaptyUI hatayı bu metodu çağırarak bildirir:

public void FlowViewDidFailLoadingProducts(
    AdaptyUIFlowView view,
    AdaptyError error
) { }
Olay örneği (Genişletmek için tıklayın)
{
  "error": {
    "code": "products_loading_failed",
    "message": "Failed to load products from the server",
    "details": {
      "underlyingError": "Network timeout"
    }
  }
}

Render ve çalışma zamanı hataları

Arayüz render edilirken bir hata oluşursa veya satın alma dışında başka bir çalışma zamanı hatası meydana gelirse, bu metot tarafından raporlanır. View otomatik olarak kapatılmaz — isterseniz view.Dismiss(...) metodunu kendiniz çağırın:

public void FlowViewDidReceiveError(
    AdaptyUIFlowView view,
    AdaptyError error
) { }
Olay örneği (Genişletmek için tıklayın)
{
  "error": {
    "code": "rendering_failed",
    "message": "Failed to render flow interface",
    "details": {
      "underlyingError": "Invalid flow configuration"
    }
  }
}

Normal koşullarda bu tür hatalar oluşmamalıdır; eğer bununla karşılaşırsanız lütfen bize bildirin.

Analitik olayları

FlowViewDidReceiveAnalyticEvent, bir flow’dan gelen özel analitik olaylar için ayrılmıştır. Flow’lar henüz bu olayları kodunuza iletmediğinden metot gövdesini boş bırakın — IAdaptyFlowsEventsListener bir C# arayüzü olduğundan metotun yine de mevcut olması gerekir:

public void FlowViewDidReceiveAnalyticEvent(
    AdaptyUIFlowView view,
    string name,
    IDictionary<string, object> @params
) { }

Sistem isteklerini yönetme

IAdaptyUISystemRequestsHandler (Adapty.SetSystemRequestsHandler(...) aracılığıyla kaydedilir), bir flow’dan gelen sistem istekleri için ayrılmıştır: OS izin istemleri (push bildirimleri veya kamera erişimi gibi) ve uygulama inceleme istekleri. Flow’lar henüz bu istekleri tetiklemiyor, dolayısıyla bir handler kaydetmenize gerek yok.

Android sistem geri düğmesi

Android sistem geri düğmesi (veya geri hareketi), FlowViewDidPerformAction’a SystemBack eylemi olarak iletilir ve flow’u kendiliğinden kapatmaz — kullanıcı, flow’dan builder’da tanımladığınız bir yol aracılığıyla çıkar; örneğin bir Close düğmesi veya on_device_back eylemi gibi. Sistem geri düğmesinin flow’u kapatmasını istiyorsanız, eylemi kendiniz ele alın:

public void FlowViewDidPerformAction(
    AdaptyUIFlowView view,
    AdaptyUIUserAction action
) {
    switch (action.Type) {
        case AdaptyUIUserActionType.Close:
        case AdaptyUIUserActionType.SystemBack:
            view.Dismiss(null);
            break;
        default:
            // handle other events
            break;
    }
}

Flow aksiyonlarını işlemeyle ilgili tam aksiyon listesi için flow aksiyonlarını işleme kılavuzuna bakın.

Bu kılavuz, satın almalar, yenileme işlemleri, ürün seçimi ve paywall oluşturma için olay yönetimini ele almaktadır. Ayrıca buton işlemlerini de (paywallı kapatma, bağlantı açma vb.) uygulamanız gerekmektedir. Ayrıntılar için buton eylemlerini yönetme kılavuzumuza bakın.

Paywall Builder ile yapılandırılan paywalllar, satın alma ve geri yükleme işlemleri için ekstra kod gerektirmez. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar arasında düğme basımları (kapat düğmeleri, URL’ler, ürün seçimleri vb.) ve paywall’da gerçekleştirilen satın alma işlemlerine ilişkin bildirimler yer alır. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz.

Bu kılavuz yalnızca Adapty SDK v3.3.0 veya üstünü gerektiren yeni Paywall Builder paywallları içindir.

Adapty SDK’nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall’ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren örnek uygulamalarımıza göz atın.

Olayları yönetme

Mobil uygulamanızdaki paywall ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için AdaptyPaywallsEventsListener arayüzünü uygulayın:

using UnityEngine;
using AdaptySDK;

public class PaywallEventsHandler : MonoBehaviour, AdaptyPaywallsEventsListener
{
    void Start()
    {
        Adapty.SetPaywallsEventsListener(this);
    }

    // Implement all required interface methods below
}

Kullanıcı kaynaklı olaylar

Paywall göründü

Paywall görünümü ekranda gösterildiğinde tetiklenir.

iOS’ta, kullanıcı bir paywall içindeki web paywall butonuna dokunduğunda ve uygulama içi tarayıcıda bir web paywall açıldığında da tetiklenir.

public void PaywallViewDidAppear(AdaptyUIPaywallView view) { }

Paywall kayboldu

Paywall görünümü ekrandan kapatıldığında tetiklenir.

iOS’ta, bir paywalldan uygulama içi tarayıcıda açılan web paywall ekrandan kaybolduğunda da tetiklenir.

public void PaywallViewDidDisappear(AdaptyUIPaywallView view) { }

Ürün seçimi

Kullanıcı ya da sistem tarafından satın alma için bir ürün seçildiğinde tetiklenir.

public void PaywallViewDidSelectProduct(
    AdaptyUIPaywallView view, 
    string productId
) { }
Olay örneği (Genişletmek için tıklayın)
{
  "productId": "premium_monthly"
}

Satın alma başladı

Kullanıcı satın alma sürecini başlattığında tetiklenir.

public void PaywallViewDidStartPurchase(
    AdaptyUIPaywallView view, 
    AdaptyPaywallProduct product
) { }
Olay örneği (Genişletmek için tıklayın)
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

Başarılı, iptal edilmiş veya beklemedeki satın alma

Satın alma başarılı olursa, kullanıcı iptal ederse veya satın alma beklemede kalırsa bu metod tetiklenir. Kullanıcı iptalleri ve beklemedeki ödemeler (örn. ebeveyn onayı gerekli) PaywallViewDidFailPurchase yerine bu metodu tetikler.

public void PaywallViewDidFinishPurchase(
    AdaptyUIPaywallView view, 
    AdaptyPaywallProduct product, 
    AdaptyPurchaseResult purchasedResult
) { }
Olay örnekleri (Genişletmek için tıklayın)
// Successful purchase
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "purchaseResult": {
    "type": "Success",
    "profile": {
      "accessLevels": {
        "premium": {
          "id": "premium",
          "isActive": true,
          "expiresAt": "2024-02-15T10:30:00Z"
        }
      }
    }
  }
}

// Cancelled purchase
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "purchaseResult": {
    "type": "UserCancelled"
  }
}

// Pending purchase
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "purchaseResult": {
    "type": "Pending"
  }
}

Bu durumda ekranı kapatmanızı öneririz.

Başarısız satın alma

Bir hata nedeniyle satın alma başarısız olursa bu metod tetiklenir. StoreKit/Google Play Billing hataları (ödeme kısıtlamaları, geçersiz ürünler, ağ hataları), işlem doğrulama hataları ve sistem hataları buna dahildir. Kullanıcı iptallerinin iptal sonucuyla PaywallViewDidFinishPurchase’i, beklemedeki ödemelerin ise bu metodu tetiklemediğini unutmayın.

public void PaywallViewDidFailPurchase(
    AdaptyUIPaywallView view, 
    AdaptyPaywallProduct product, 
    AdaptyError error
) { }
Event example (Click to expand)
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "error": {
    "code": "purchase_failed",
    "message": "Purchase failed due to insufficient funds",
    "details": {
      "underlyingError": "Insufficient funds in account"
    }
  }
}

Restore başlatıldı

Kullanıcı restore işlemini başlattığında çağrılır:

public void PaywallViewDidStartRestore(AdaptyUIPaywallView view) { }

Başarılı geri yükleme

Satın alma geri yüklemesi başarılı olduğunda tetiklenir:

public void PaywallViewDidFinishRestore(
    AdaptyUIPaywallView view, 
    AdaptyProfile profile
) { }
Olay örneği (Genişletmek için tıklayın)
{
  "profile": {
    "accessLevels": {
      "premium": {
        "id": "premium",
        "isActive": true,
        "expiresAt": "2024-02-15T10:30:00Z"
      }
    },
    "subscriptions": [
      {
        "vendorProductId": "premium_monthly",
        "isActive": true,
        "expiresAt": "2024-02-15T10:30:00Z"
      }
    ]
  }
}

Kullanıcının gerekli accessLevel’a sahip olması durumunda ekranı kapatmanızı öneririz. Bunu nasıl kontrol edeceğinizi öğrenmek için Abonelik durumu konusuna bakın.

Başarısız geri yükleme

Satın alma geri yüklemesi başarısız olduğunda tetiklenir:

public void PaywallViewDidFailRestore(
    AdaptyUIPaywallView view, 
    AdaptyError error
) { }
Olay örneği (Genişletmek için tıklayın)
{
  "error": {
    "code": "restore_failed",
    "message": "Purchase restoration failed",
    "details": {
      "underlyingError": "No previous purchases found"
    }
  }
}

Web ödeme navigasyonu tamamlandı

Satın alma için bir web paywall açılmaya çalışıldıktan sonra (başarılı ya da başarısız), bu metod tetiklenir:

public void PaywallViewDidFinishWebPaymentNavigation(
    AdaptyUIPaywallView view, 
    AdaptyPaywallProduct product, 
    AdaptyError error
) { }

Parametreler:

  • product: Web paywallın açıldığı (veya açılmaya çalışıldığı) ürün
  • error: Web paywall başarıyla açıldıysa null, başarısız olduysa bir AdaptyError
Olay örnekleri (Genişletmek için tıklayın)
// Successful navigation
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "error": null
}

// Failed navigation
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  },
  "error": {
    "code": "wrong_param",
    "message": "Current method is not available for this product",
    "details": {
      "underlyingError": "Product not configured for web purchases"
    }
  }
}

Veri çekme ve render etme

Ürün yükleme hataları

Ürün yükleme başarısız olduğunda tetiklenir ve AdaptyError sağlar. Başlatma sırasında ürün dizisini geçmediyseniz, AdaptyUI gerekli nesneleri sunucudan kendisi alır. Bu işlem başarısız olabilir ve AdaptyUI hatayı bu yöntemi çağırarak bildirir:

public void PaywallViewDidFailLoadingProducts(
    AdaptyUIPaywallView view, 
    AdaptyError error
) { }
Olay örneği (Genişletmek için tıklayın)
{
  "error": {
    "code": "products_loading_failed",
    "message": "Failed to load products from the server",
    "details": {
      "underlyingError": "Network timeout"
    }
  }
}

Render hataları

Arayüz render sırasında bir hata oluştuğunda tetiklenir ve AdaptyError döndürür:

public void PaywallViewDidFailRendering(
    AdaptyUIPaywallView view, 
    AdaptyError error
) { }
Olay örneği (Genişletmek için tıklayın)
{
  "error": {
    "code": "rendering_failed",
    "message": "Failed to render paywall interface",
    "details": {
      "underlyingError": "Invalid paywall configuration"
    }
  }
}

Normal koşullarda bu tür hatalar oluşmamalıdır; eğer böyle bir hatayla karşılaşırsanız lütfen bize bildirin.