> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.qonversion.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Deferred Purchases

## Deferred and pending purchases

Deferred or interrupted in-app purchases may happen when [SCA](https://developer.apple.com/support/psd2) confirmation is needed, in the case of parental control and some other cases. Here is what the deferred purchase flow looks like:

* a user initiates a purchase
* purchase is received in state `deferred.`
* you receive a purchase result with a pending purchase status (`isPending` / `IsPending` on every platform; verified for hybrid SDKs at `react-native-sdk/src/dto/PurchaseResult.ts:74-76`)

<CodeGroup>
  ```swift Swift theme={null}
  Qonversion.shared().purchase(product) { (result) in
    if result.isPending {
      // Handle pending purchase
    }
  }
  ```

  ```objectivec Objective-C theme={null}
  [[Qonversion sharedInstance] purchaseWithResult:product completion:^(QONPurchaseResult * _Nonnull result) {
    if (result.isPending) {
      // Handle pending purchase
    }
  }];
  ```

  ```java Java theme={null}
  Qonversion.getSharedInstance().purchase(this, product, new QonversionPurchaseCallback() {
      @Override
      public void onResult(@NonNull QPurchaseResult result) {
          if (result.isPending()) {
              // Handle pending purchase
          }
      }
  });
  ```

  ```kotlin Kotlin theme={null}
  Qonversion.shared.purchase(this, product, object : QonversionPurchaseCallback {
      override fun onResult(result: QPurchaseResult) {
          if (result.isPending) {
              // Handle pending purchase
          }
      }
  })
  ```

  ```dart Flutter theme={null}
  final result = await Qonversion.getSharedInstance().purchaseWithResult(product);

  if (result.isPending) {
    // Handle pending purchase
  }
  ```

  ```typescript React Native theme={null}
  const result: PurchaseResult = await Qonversion.getSharedInstance().purchaseWithResult(product);

  if (result.isPending) {
    // Handle pending purchase
  }
  ```

  ```csharp Unity theme={null}
  Qonversion.GetSharedInstance().Purchase(product, (result) =>
  {
      if (result.IsPending)
      {
          // Handle pending purchase
      }
  });
  ```

  ```typescript Cordova theme={null}
  const result = await Qonversion.getSharedInstance().purchase(product);

  if (result.isPending) {
    // Handle pending purchase
  }
  ```

  ```typescript Capacitor theme={null}
  const result = await Qonversion.getSharedInstance().purchase(product);

  if (result.isPending) {
    // Handle pending purchase
  }
  ```
</CodeGroup>

* if a transaction completes successfully later, Apple StoreKit or Google Billing Service returns a successful purchase
* Qonversion SDK returns a successful purchase

Make sure your app handles deferred or interrupted transactions by setting a delegate and a function that is triggered when such a transaction is made.

<Warning>
  ### Attention

  Please note, this function is called only in case of deferred purchases. The purchase flow happens as described [here](making-purchases#1-make-a-purchase) for all other cases.
</Warning>

### Provide entitlements update listener

<Warning>
  `setEntitlementsUpdateListener` is deprecated. Use `setDeferredPurchasesListener` (`QDeferredPurchasesListener` on Android, `QONDeferredPurchasesListener` on iOS) instead - it provides full transaction details (product ID, transaction ID, value), not only the resulting entitlements. The deprecated listener will continue to work for now.
</Warning>

Set the delegate to handle pending purchases and implement the corresponding function to handle new entitlements when the purchase is completed.

<CodeGroup>
  ```swift Swift theme={null}
  Qonversion.shared().setEntitlementsUpdateListener(self)

  ...

  func didReceiveUpdatedEntitlements(_ entitlements: [String : Qonversion.Entitlement]) {
      // handle updated entitlements here
  }
  ```

  ```objectivec Objective-C theme={null}
  [[Qonversion sharedInstance] setEntitlementsUpdateListener:self];

  ...

  - (void)didReceiveUpdatedEntitlements:(NSDictionary<NSString *, QONEntitlement *>  * _Nonnull)entitlements {
      // handle updated entitlements here
  }
  ```

  ```java Java theme={null}
  Qonversion.getSharedInstance().setEntitlementsUpdateListener(entitlements -> {
      // handle updated entitlements here
  });
  ```

  ```kotlin Kotlin theme={null}
  Qonversion.shared.setEntitlementsUpdateListener(object : QEntitlementsUpdateListener {
      override fun onEntitlementsUpdated(entitlements: Map<String, QEntitlement>) {
          // handle updated entitlements here
      }
  })
  ```

  ```dart Flutter theme={null}
  StreamSubscription<Map<String, QEntitlement>> _updatedEntitlementsStream;
  _updatedEntitlementsStream = Qonversion.getSharedInstance().updatedEntitlementsStream.listen((entitlements) => {
     // handle updated entitlements here
  });
  ```

  ```typescript React Native theme={null}
  Qonversion.getSharedInstance().setEntitlementsUpdateListener({
      onEntitlementsUpdated(entitlements) {
          // handle updated entitlements here
      },
  });
  ```

  ```csharp Unity theme={null}
  Qonversion.GetSharedInstance().UpdatedEntitlementsReceived += HandleUpdatedEntitlements;

  private void HandleUpdatedEntitlements(Dictionary<string, Entitlement> entitlements)
  {
      // handle updated entitlements here
  }
  ```

  ```typescript Cordova theme={null}
  Qonversion.getSharedInstance().setEntitlementsUpdateListener({
      onEntitlementsUpdated(entitlements) {
          // handle updated entitlements here
      },
  });
  ```

  ```typescript Capacitor theme={null}
  Qonversion.getSharedInstance().setEntitlementsUpdateListener({
      onEntitlementsUpdated(entitlements) {
          // handle updated entitlements here
      },
  });
  ```
</CodeGroup>

You can also provide a listener during the initialization for some platforms as follows:

<CodeGroup>
  ```java Java theme={null}
  final QonversionConfig qonversionConfig = new QonversionConfig.Builder(
          this,
          "projectKey",
          QLaunchMode.SubscriptionManagement
  )
          .setEntitlementsUpdateListener(entitlements -> {
              // handle updated entitlements here
          })
          .build();
  Qonversion.initialize(qonversionConfig);
  ```

  ```kotlin Kotlin theme={null}
  val qonversionConfig = QonversionConfig.Builder(
      this,
      "projectKey",
      QLaunchMode.SubscriptionManagement
  )
      .setEntitlementsUpdateListener(object : QEntitlementsUpdateListener {
          override fun onEntitlementsUpdated(entitlements: Map<String, QEntitlement>) {
              // handle updated entitlements here
          }
      })
      .build()
  Qonversion.initialize(qonversionConfig)
  ```

  ```typescript React Native theme={null}
  const config = new QonversionConfigBuilder(
    'projectKey',
    LaunchMode.SUBSCRIPTION_MANAGEMENT
  )
    .setEntitlementsUpdateListener({
        onEntitlementsUpdated(entitlements) {
            // handle updated entitlements here
        },
    })
    .build();
  Qonversion.initialize(config);
  ```

  ```typescript Cordova theme={null}
  const config = new Qonversion.ConfigBuilder(
    'projectKey',
    Qonversion.LaunchMode.SUBSCRIPTION_MANAGEMENT
  )
    .setEntitlementsUpdateListener({
        onEntitlementsUpdated(entitlements) {
            // handle updated entitlements here
        },
    })
    .build();
  Qonversion.initialize(config);
  ```

  ```typescript Capacitor theme={null}
  const config = new QonversionConfigBuilder(
    'projectKey',
    LaunchMode.SUBSCRIPTION_MANAGEMENT
  )
    .setEntitlementsUpdateListener({
        onEntitlementsUpdated(entitlements) {
            // handle updated entitlements here
        },
    })
    .build();
  Qonversion.initialize(config);
  ```
</CodeGroup>

***

[Tutorials](tutorials)

[Non-Subscription Purchases](non-subscription-purchases)
