---
title: "Flow ve paywall olaylarını yönetme - Android"
description: "Android uygulamanızda flow ve paywall olaylarını yönetin."
---

:::important
Bu kılavuz, satın alma, yenileme, ürün seçimi ve flow render işlemleri için event yönetimini kapsar. Ayrıca düğme işlemlerini de (flow'u kapatma, bağlantı açma vb.) uygulamanız gerekir. Ayrıntılar için [düğme eylemlerini yönetme kılavuzumuza](android-handle-paywall-actions) bakın.
:::
[Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) ile yapılandırılmış flow'lar ve paywall'lar, satın alma ve geri yükleme işlemleri için ekstra kod gerektirmez. Ancak bu ekranlar, uygulamanızın yanıt verebileceği bazı olaylar üretir. Bu olaylar arasında buton tıklamaları (kapat butonları, URL'ler, ürün seçimleri vb.) ve satın alma işlemlerine ilişkin bildirimler yer alır. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz.

:::tip

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](sample-apps) göz atın.

:::

Satın alma ekranında gerçekleşen süreçleri kontrol etmek veya izlemek istiyorsanız `AdaptyFlowEventListener` metodlarını uygulayın.
Bazı durumlarda varsayılan davranışı korumak istiyorsanız, `AdaptyFlowDefaultEventListener` sınıfını genişletip yalnızca değiştirmek istediğiniz metodları override edebilirsiniz.

Aşağıda `AdaptyFlowDefaultEventListener` içindeki varsayılan değerler yer almaktadır.
### Kullanıcı tarafından oluşturulan olaylar \{#user-generated-events\}

#### Ürün seçimi \{#product-selection\}

Bir ürün satın alma için seçildiğinde (kullanıcı veya sistem tarafından), bu method çağrılır:

```kotlin showLineNumbers title="Kotlin"
public override fun onProductSelected(
    product: AdaptyPaywallProduct,
    context: Context,
) {}
```

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

#### Satın alma başlatıldı \{#started-purchase\}

Bir kullanıcı satın alma sürecini başlatırsa bu metot çağrılır:

```kotlin showLineNumbers title="Kotlin"
public override fun onPurchaseStarted(
    product: AdaptyPaywallProduct,
    context: Context,
) {}
```

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

Bu metot Observer modunda çağrılmaz. Ayrıntılar için [Android - Observer modunda Paywall Builder paywalllarını sunma](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın.

#### Başarılı, iptal edilmiş veya beklemedeki satın alma \{#successful-canceled-or-pending-purchase\}

Satın alma başarılı olursa şu metot çağrılır:
```kotlin showLineNumbers title="Kotlin"
public override fun onPurchaseFinished(
    purchaseResult: AdaptyPurchaseResult,
    product: AdaptyPaywallProduct,
    context: Context,
) {
    if (purchaseResult !is AdaptyPurchaseResult.UserCanceled)
        context.getActivityOrNull()?.onBackPressed()
}
```

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

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

// Pending purchase
{
  "purchaseResult": {
    "type": "Pending"
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}
```
</Details>
Bu durumda ekranı kapatmanızı öneririz.

Bu metot, Observer modunda çağrılmayacaktır. Ayrıntılar için [Android - Observer modunda Paywall Builder paywalllarını sunma](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın.

#### Başarısız satın alma \{#failed-purchase\}
Bir satın alma işlemi hata nedeniyle başarısız olursa bu metot çağrılır. Bu durum; Google Play Billing hatalarını (ödeme kısıtlamaları, geçersiz ürünler, ağ hataları), işlem doğrulama hatalarını ve sistem hatalarını kapsar. Kullanıcı iptallerinin `onPurchaseFinished` metodunu iptal edilmiş sonuçla tetiklediğini, beklemedeki ödemelerin ise bu metodu tetiklemediğini unutmayın.

```kotlin showLineNumbers title="Kotlin"
public override fun onPurchaseFailure(
    error: AdaptyError,
    product: AdaptyPaywallProduct,
    context: Context,
) {}
```

<Details>
<summary>Etkinlik örneği (Genişletmek için tıklayın)</summary>
```javascript
{
  "error": {
    "code": "purchase_failed",
    "message": "Purchase failed due to insufficient funds",
    "details": {
      "underlyingError": "Insufficient funds in account"
    }
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}
```
</Details>
Bu yöntem, Observer modunda çağrılmaz. Ayrıntılar için [Android - Observer modunda Paywall Builder paywalllerini sunma](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın.

#### Web ödeme navigasyonu tamamlandı \{#finished-web-payment-navigation\}

Bu yöntem, belirli bir ürün için [web paywall](web-paywall) açma girişiminin ardından çağrılır. Hem başarılı hem de başarısız navigasyon girişimlerini kapsar:

```kotlin showLineNumbers title="Kotlin"
public override fun onFinishWebPaymentNavigation(
    product: AdaptyPaywallProduct?,
    error: AdaptyError?,
    context: Context,
) {}
```
**Parametreler:**

| Parametre   | Açıklama                                                                                               |
|:------------|:-------------------------------------------------------------------------------------------------------|
| **product** | Web paywallın açıldığı `AdaptyPaywallProduct`. `null` olabilir.                                        |
| **error**   | Web paywall navigasyonu başarısız olursa `AdaptyError` nesnesi; navigasyon başarılıysa `null`. |

<Details>
<summary>Etkinlik örnekleri (Genişletmek için tıklayın)</summary>
```javascript
// 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": "web_navigation_failed",
    "message": "Failed to open web paywall",
    "details": {
      "underlyingError": "Browser unavailable"
    }
  }
}
```
</Details>
#### Başarılı geri yükleme \{#successful-restore\}

Bir satın alma başarıyla geri yüklenirse, bu metot çağrılır:

```kotlin showLineNumbers title="Kotlin"
public override fun onRestoreSuccess(
    profile: AdaptyProfile,
    context: Context,
) {}
```

<Details>
<summary>Olay örneği (Genişletmek için tıklayın)</summary>
```javascript
{
  "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"
      }
    ]
  }
}
```
</Details>

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](android-listen-subscription-changes) konusuna bakın.

#### Başarısız geri yükleme \{#failed-restore\}
`Adapty.restorePurchases()` başarısız olursa, bu metot çağrılır:

```kotlin showLineNumbers title="Kotlin"
public override fun onRestoreFailure(
    error: AdaptyError,
    context: Context,
) {}
```

<Details>
<summary>Olay örneği (Genişletmek için tıklayın)</summary>

```javascript
{
  "error": {
    "code": "restore_failed",
    "message": "Purchase restoration failed",
    "details": {
      "underlyingError": "No previous purchases found"
    }
  }
}
```
</Details>

#### Abonelik yükseltme \{#upgrade-subscription\}
Bir kullanıcı aktif bir aboneliği varken yeni bir abonelik satın almaya çalıştığında, bu metodu geçersiz kılarak yeni satın alma işleminin nasıl ele alınacağını kontrol edebilirsiniz. İki seçeneğiniz vardır:
1. **Mevcut aboneliği** yeni olanıyla değiştirin:
```kotlin showLineNumbers title="Kotlin"
public override fun onAwaitingPurchaseParams(
    product: AdaptyPaywallProduct,
    context: Context,
    onPurchaseParamsReceived: AdaptyFlowEventListener.PurchaseParamsCallback,
): AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked {
    onPurchaseParamsReceived(
        AdaptyPurchaseParameters.Builder()
            .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...))
            .build()
    )
    return AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked
}
```
2. **Her iki aboneliği de koru** (yenisini ayrı olarak ekle):
```kotlin showLineNumbers title="Kotlin"
public override fun onAwaitingPurchaseParams(
    product: AdaptyPaywallProduct,
    context: Context,
    onPurchaseParamsReceived: AdaptyFlowEventListener.PurchaseParamsCallback,
): AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked {
    onPurchaseParamsReceived(AdaptyPurchaseParameters.Empty)
    return AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked
}
```
:::note
Bu yöntemi geçersiz kılmazsanız, varsayılan davranış her iki aboneliği de aktif tutmaktır (`AdaptyPurchaseParameters.Empty` kullanımıyla eşdeğer).
:::

Gerekirse ek satın alma parametreleri de ayarlayabilirsiniz:
```kotlin
AdaptyPurchaseParameters.Builder()
    .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) // isteğe bağlı - mevcut aboneliği değiştirmek için
    .withOfferPersonalized(true) // isteğe bağlı - kişiselleştirilmiş fiyatlandırma kullanılıyorsa
    .build()
```

<Details>
<summary>Etkinlik örneği (Genişletmek için tıklayın)</summary>
```javascript
{
  "product": {
    "vendorProductId": "premium_yearly",
    "localizedTitle": "Premium Yearly",
    "localizedDescription": "Premium subscription for 1 year",
    "localizedPrice": "$99.99",
    "price": 99.99,
    "currencyCode": "USD"
  },
  "subscriptionUpdateParams": {
    "replacementMode": "with_time_proration"
  }
}
```
</Details>
### Veri getirme ve render etme \{#data-fetching-and-rendering\}

#### Ürün yükleme hataları \{#product-loading-errors\}

Başlatma sırasında ürünleri iletmezseniz, AdaptyUI gerekli nesneleri sunucudan kendisi alır. Bu işlem başarısız olursa, AdaptyUI hatayı şu metodu çağırarak bildirir:

```kotlin showLineNumbers title="Kotlin"
public override fun onLoadingProductsFailure(
    error: AdaptyError,
    context: Context,
): Boolean = false
```

<Details>
<summary>Etkinlik örneği (Genişletmek için tıklayın)</summary>
```javascript
{
  "error": {
    "code": "products_loading_failed",
    "message": "Failed to load products from the server",
    "details": {
      "underlyingError": "Network timeout"
    }
  }
}
```
</Details>

`true` döndürürseniz, AdaptyUI isteği 2 saniye sonra tekrarlar.

#### Render hataları \{#rendering-errors\}

Arayüz render edilirken bir hata oluşursa, bu metot çağrılarak raporlanır:

```kotlin showLineNumbers title="Kotlin"
public override fun onError(
    error: AdaptyError,
    context: Context,
) {}
```

<Details>
<summary>Olay örneği (Genişletmek için tıklayın)</summary>
```javascript
{
  "error": {
    "code": "rendering_failed",
    "message": "Failed to render flow interface",
    "details": {
      "underlyingError": "Invalid flow configuration"
    }
  }
}
```
</Details>

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.
### Gezinti \{#navigation\}

#### Sistem geri düğmesi \{#system-back-button\}

Varsayılan olarak, bir flow sistem geri düğmesiyle veya geri hareketiyle kapatılamaz — kullanıcı, flow'dan yalnızca sizin tanımladığınız bir yol aracılığıyla çıkar; örneğin bir **Close** düğmesi veya builder'daki bir `on_device_back` eylemi. Sistem geri düğmesinin flow'u kapatmasını istiyorsanız, `onBackPressed` metodunu geçersiz kılın ve ana activity'nizin ya da fragment'ınızın bu basışı işlemesine izin vermek için `false` döndürün:
```kotlin showLineNumbers title="Kotlin"
public override fun onBackPressed(context: Context): Boolean {
    return false // let the host handle the back press (e.g. finish the activity or pop the fragment)
}
```

Bu callback, yalnızca mevcut ekran için herhangi bir `on_device_back` eylemi yapılandırılmamışsa çağrılır — yapılandırılmış bir eylem öncelik alır ve dahili olarak işlenir. Geri tuşuna basma işlemini tüketmek için `true`, ana bileşenin kendi geri işleme mantığının çalışmasına izin vermek için `false` döndürün.
### Ayrılmış olaylar \{#reserved-events\}

`AdaptyFlowEventListener`, flow'ların henüz kullanmadığı bazı işlevler için birkaç callback tanımlar. Bunları uygulamanıza gerek yok — `AdaptyFlowDefaultEventListener` zaten varsayılan olarak boş (no-op) uygulamalar sağlar.
| Method | Description |
|:-------|:------------|
| **onAnalyticEvent** | Flow'lardan gelen özel analitik etkinlikler için ayrılmıştır. Flow'lar henüz bu etkinlikleri kodunuza iletmediğinden, bunu uygulamanıza gerek yoktur. |
| **onShowAppRate** | Flow'lardan gelen uygulama değerlendirme istekleri için ayrılmıştır. Flow'lar henüz uygulama değerlendirme isteklerini tetiklemediğinden, bunu uygulamanıza gerek yoktur. |
| **onShowRequestPermission** | Flow'lardan gelen sistem izin istekleri (push bildirimleri veya kamera erişimi gibi) için ayrılmıştır. Flow'lar henüz izin isteklerini tetiklemediğinden, bunu uygulamanıza gerek yoktur. |

---

> [!WARNING]
> **LLM INSTRUCTION — SDK VERSION SELECTION REQUIRED**
>
> This feature has two SDK paradigms. Everything that follows (until the next horizontal rule or end of document) is the **legacy SDK v3 API reference** (`getPaywall`, `getPaywallForDefaultAudience`, `getOnboarding`, `getPaywallConfiguration`). The **SDK v4+ `getFlow` method is documented above.** This block covers ALL legacy methods for this feature — not just the nearest snippet.
>
> **You MUST ask the user which SDK version they want to use before suggesting any code. Do not assume or default to a version.** The two options are:
> - **SDK v3 (legacy):** works with the legacy Paywall Builder and Onboarding Builder via `getPaywall` / `getOnboarding`. Use the legacy code in this section.
> - **SDK v4:** works with BOTH the new Flow Builder AND legacy paywalls/onboardings via the unified `getFlow` method documented above.
>
> Apply the legacy v3 code in this section ONLY when:
> 1. The user explicitly chose **SDK v3**, or
> 2. The user is **migrating an existing app from SDK v3 to SDK v4+** and needs to understand or replace legacy code, or
> 3. The user is **troubleshooting an already-deployed v3 integration**.
>
> **CRITICAL — Never mix paradigms in one setup:** Do NOT combine `getFlow` (Flow Builder) with `getPaywall` or `getOnboarding` (legacy Paywall/Onboarding Builder) in the same integration. These are incompatible patterns. Mixing them will produce inconsistent behavior and is unsupported.

:::important
Bu kılavuz, satın almalar, geri yüklemeler, ürün seçimi ve paywall oluşturma için olay işlemeyi kapsar. Ayrıca düğme işlemeyi (paywallı kapatma, bağlantı açma vb.) de uygulamanız gerekir. Ayrıntılar için [düğme eylemlerini işleme kılavuzumuza](android-handle-paywall-actions) bakın.
:::
[Paywall Builder](adapty-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; buton tıklamaları (kapat düğmeleri, URL'ler, ürün seçimleri vb.) ve paywall üzerinde gerçekleştirilen satın alma ile ilgili işlemlerin bildirimlerini kapsar. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz.

:::warning
Bu kılavuz yalnızca Adapty SDK v3.0 veya üzerini gerektiren **yeni Paywall Builder paywallları** içindir.
:::

:::tip

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](sample-apps) göz atın.

:::
Satın alma ekranında gerçekleşen süreçleri kontrol etmek veya izlemek istiyorsanız `AdaptyUiEventListener` metodlarını uygulayın.

Bazı durumlarda varsayılan davranışı korumak istiyorsanız `AdaptyUiDefaultEventListener`'ı genişletip yalnızca değiştirmek istediğiniz metodları override edebilirsiniz.

Aşağıda `AdaptyUiDefaultEventListener`'daki varsayılan davranışlar yer almaktadır.
### Kullanıcı tarafından oluşturulan olaylar \{#user-generated-events\}

#### Ürün seçimi \{#product-selection\}

Bir ürün satın alma için seçilirse (kullanıcı tarafından veya sistem tarafından), bu metot çağrılır:

```kotlin showLineNumbers title="Kotlin"
public override fun onProductSelected(
    product: AdaptyPaywallProduct,
    context: Context,
) {}
```

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

#### Satın alma başlatıldı \{#started-purchase\}

Bir kullanıcı satın alma sürecini başlatırsa bu metot çağrılır:

```kotlin showLineNumbers title="Kotlin"
public override fun onPurchaseStarted(
    product: AdaptyPaywallProduct,
    context: Context,
) {}
```

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

Bu metot, Observer modunda çağrılmaz. Ayrıntılar için [Android - Observer modunda Paywall Builder paywall'larını gösterme](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın.

#### Başarılı, iptal edilmiş veya beklemedeki satın alma \{#successful-canceled-or-pending-purchase\}

Satın alma başarılı olursa şu metot çağrılır:
```kotlin showLineNumbers title="Kotlin"
public override fun onPurchaseFinished(
    purchaseResult: AdaptyPurchaseResult,
    product: AdaptyPaywallProduct,
    context: Context,
) {
    if (purchaseResult !is AdaptyPurchaseResult.UserCanceled)
        context.getActivityOrNull()?.onBackPressed()
}
```

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

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

// Pending purchase
{
  "purchaseResult": {
    "type": "Pending"
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}
```
</Details>
Bu durumda ekranı kapatmanızı öneririz.

Bu metot, Observer modunda çağrılmaz. Ayrıntılar için [Android - Observer modunda Paywall Builder paywalllarını gösterme](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın.

#### Başarısız satın alma \{#failed-purchase\}
Bir satın alma işlemi hata nedeniyle başarısız olursa, bu method çağrılır. Buna Google Play Billing hataları (ödeme kısıtlamaları, geçersiz ürünler, ağ hataları), işlem doğrulama hataları ve sistem hataları dahildir. Kullanıcı iptalleri yerine `onPurchaseFinished` methodunu iptal edilmiş sonucuyla tetiklediğini ve bekleyen ödemelerin bu methodu tetiklemediğini unutmayın.

```kotlin showLineNumbers title="Kotlin"
public override fun onPurchaseFailure(
    error: AdaptyError,
    product: AdaptyPaywallProduct,
    context: Context,
) {}
```

<Details>
<summary>Etkinlik örneği (Genişletmek için tıklayın)</summary>
```javascript
{
  "error": {
    "code": "purchase_failed",
    "message": "Purchase failed due to insufficient funds",
    "details": {
      "underlyingError": "Insufficient funds in account"
    }
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}
```
</Details>
Bu metot Observer modunda çağrılmaz. Ayrıntılar için [Android - Observer modunda Paywall Builder paywalllarını gösterme](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın.

#### Web ödeme navigasyonu tamamlandı \{#finished-web-payment-navigation\}

Bu metot, belirli bir ürün için [web paywall](web-paywall) açma girişiminin ardından çağrılır. Başarılı ve başarısız navigasyon denemeleri için de çalışır:

```kotlin showLineNumbers title="Kotlin"
public override fun onFinishWebPaymentNavigation(
    product: AdaptyPaywallProduct?,
    error: AdaptyError?,
    context: Context,
) {}
```
**Parametreler:**

| Parametre   | Açıklama                                                                                                    |
|:------------|:------------------------------------------------------------------------------------------------------------|
| **product** | Web paywallın açıldığı `AdaptyPaywallProduct`. `null` olabilir.                                             |
| **error**   | Web paywall navigasyonu başarısız olduysa `AdaptyError` nesnesi; navigasyon başarılıysa `null`. |

<Details>
<summary>Olay örnekleri (Genişletmek için tıklayın)</summary>
```javascript
// 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": "web_navigation_failed",
    "message": "Failed to open web paywall",
    "details": {
      "underlyingError": "Browser unavailable"
    }
  }
}
```
</Details>
#### Başarılı geri yükleme \{#successful-restore\}

Bir satın alma işleminin geri yüklenmesi başarılı olursa, bu metot çağrılır:

```kotlin showLineNumbers title="Kotlin"
public override fun onRestoreSuccess(
    profile: AdaptyProfile,
    context: Context,
) {}
```

<Details>
<summary>Etkinlik örneği (Genişletmek için tıklayın)</summary>
```javascript
{
  "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"
      }
    ]
  }
}
```
</Details>

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](android-listen-subscription-changes) konusuna bakın.

#### Başarısız geri yükleme \{#failed-restore\}
`Adapty.restorePurchases()` başarısız olursa, şu metot çağrılır:

```kotlin showLineNumbers title="Kotlin"
public override fun onRestoreFailure(
    error: AdaptyError,
    context: Context,
) {}
```

<Details>
<summary>Örnek olay (Genişletmek için tıklayın)</summary>

```javascript
{
  "error": {
    "code": "restore_failed",
    "message": "Purchase restoration failed",
    "details": {
      "underlyingError": "No previous purchases found"
    }
  }
}
```
</Details>

#### Abonelik yükseltme \{#upgrade-subscription\}
<Tabs groupId="current-os" queryString>
<TabItem value="new" label="SDK version 3.10.0 or later" default>

Bir kullanıcı, aktif bir aboneliği varken yeni bir abonelik satın almaya çalıştığında, bu metodu geçersiz kılarak yeni satın alma işleminin nasıl ele alınacağını kontrol edebilirsiniz. İki seçeneğiniz var:
1. **Mevcut aboneliği** yenisiyle değiştirin:
```kotlin showLineNumbers title="Kotlin"
public override fun onAwaitingPurchaseParams(
    product: AdaptyPaywallProduct,
    context: Context,
    onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback,
): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked {
    onPurchaseParamsReceived(
        AdaptyPurchaseParameters.Builder()
            .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...))
            .build()
    )
    return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked
}
```
2. **Her iki aboneliği de koru** (yenisini ayrı olarak ekle):
```kotlin showLineNumbers title="Kotlin"
public override fun onAwaitingPurchaseParams(
    product: AdaptyPaywallProduct,
    context: Context,
    onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback,
): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked {
    onPurchaseParamsReceived(AdaptyPurchaseParameters.Empty)
    return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked
}
```
:::note
Bu metodu override etmezseniz, varsayılan davranış her iki aboneliği de aktif tutmaktır (`AdaptyPurchaseParameters.Empty` kullanımına eşdeğer).
:::

Gerekirse ek satın alma parametreleri de belirleyebilirsiniz:
```kotlin
AdaptyPurchaseParameters.Builder()
    .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) // isteğe bağlı - mevcut aboneliği değiştirmek için
    .withOfferPersonalized(true) // isteğe bağlı - kişiselleştirilmiş fiyatlandırma kullanılıyorsa
    .build()
```

</TabItem>
<TabItem value="old" label="SDK version earlier than 3.10.0" default>
Yeni bir abonelik satın alınırken mevcut bir abonelik hâlâ aktifse, geçerli aboneliği yenisiyle değiştirmek için bu metodu override edin. Aktif abonelik etkin kalmaya devam etmeli ve yeni abonelik ayrı olarak eklenmeliyse `onSubscriptionUpdateParamsReceived(null)` çağırın:

```kotlin showLineNumbers title="Kotlin"
public override fun onAwaitingSubscriptionUpdateParams(
    product: AdaptyPaywallProduct,
    context: Context,
    onSubscriptionUpdateParamsReceived: SubscriptionUpdateParamsCallback,
) {
    onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters(...))
}
```
</TabItem>
</Tabs>

<Details>
<summary>Etkinlik örneği (Genişletmek için tıklayın)</summary>

```javascript
{
  "product": {
    "vendorProductId": "premium_yearly",
    "localizedTitle": "Premium Yearly",
    "localizedDescription": "Premium subscription for 1 year",
    "localizedPrice": "$99.99",
    "price": 99.99,
    "currencyCode": "USD"
  },
  "subscriptionUpdateParams": {
    "replacementMode": "with_time_proration"
  }
}
```
</Details>
### Veri çekme ve render etme \{#data-fetching-and-rendering\}

#### Ürün yükleme hataları \{#product-loading-errors\}

Ürünleri başlatma sırasında geçirmezseniz, AdaptyUI gerekli nesneleri sunucudan kendisi alacaktır. Bu işlem başarısız olursa, AdaptyUI hatayı şu metodu çağırarak bildirir:

```kotlin showLineNumbers title="Kotlin"
public override fun onLoadingProductsFailure(
    error: AdaptyError,
    context: Context,
): Boolean = false
```

<Details>
<summary>Örnek olay (Genişletmek için tıklayın)</summary>
```javascript
{
  "error": {
    "code": "products_loading_failed",
    "message": "Failed to load products from the server",
    "details": {
      "underlyingError": "Network timeout"
    }
  }
}
```
</Details>

`true` döndürürseniz, AdaptyUI isteği 2 saniye sonra tekrar eder.

#### Render hataları \{#rendering-errors\}

Arayüz render edilirken bir hata oluşursa, bu yöntem çağrılarak bildirilir:

```kotlin showLineNumbers title="Kotlin"
public override fun onRenderingError(
    error: AdaptyError,
    context: Context,
) {}
```

<Details>
<summary>Olay örneği (Genişletmek için tıklayın)</summary>
```javascript
{
  "error": {
    "code": "rendering_failed",
    "message": "Failed to render paywall interface",
    "details": {
      "underlyingError": "Invalid paywall configuration"
    }
  }
}
```
</Details>

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.

---