queryPastPurchases method

Future<QueryPurchaseDetailsResponse> queryPastPurchases({
  1. String? applicationUserName,
})

Query all previous purchases.

The applicationUserName should match whatever was sent in the initial PurchaseParam, if anything. If no applicationUserName was specified in the initial PurchaseParam, use null.

This does not return consumed products. If you want to restore unused consumable products, you need to persist consumable product information for your user on your own server.

See also:

  • refreshPurchaseVerificationData, for reloading failed PurchaseDetails.verificationData.

Implementation

Future<QueryPurchaseDetailsResponse> queryPastPurchases(
    {String? applicationUserName}) async {
  List<PurchasesResultWrapper> responses;
  PlatformException? exception;

  try {
    responses = await Future.wait(<Future<PurchasesResultWrapper>>[
      _billingClientManager.runWithClient(
        (BillingClient client) => client.queryPurchases(ProductType.inapp),
      ),
      _billingClientManager.runWithClient(
        (BillingClient client) => client.queryPurchases(ProductType.subs),
      ),
    ]);
  } on PlatformException catch (e) {
    exception = e;
    responses = <PurchasesResultWrapper>[
      PurchasesResultWrapper(
        responseCode: BillingResponse.error,
        purchasesList: const <PurchaseWrapper>[],
        billingResult: BillingResultWrapper(
          responseCode: BillingResponse.error,
          debugMessage: e.details.toString(),
        ),
      ),
      PurchasesResultWrapper(
        responseCode: BillingResponse.error,
        purchasesList: const <PurchaseWrapper>[],
        billingResult: BillingResultWrapper(
          responseCode: BillingResponse.error,
          debugMessage: e.details.toString(),
        ),
      )
    ];
  }

  final Set<String> errorCodeSet = responses
      .where((PurchasesResultWrapper response) =>
          response.responseCode != BillingResponse.ok)
      .map((PurchasesResultWrapper response) =>
          response.responseCode.toString())
      .toSet();

  final String errorMessage =
      errorCodeSet.isNotEmpty ? errorCodeSet.join(', ') : '';

  final List<GooglePlayPurchaseDetails> pastPurchases = responses
      .expand((PurchasesResultWrapper response) => response.purchasesList)
      .expand((PurchaseWrapper purchaseWrapper) =>
          GooglePlayPurchaseDetails.fromPurchase(purchaseWrapper))
      .toList();

  IAPError? error;
  if (exception != null) {
    error = IAPError(
        source: kIAPSource,
        code: exception.code,
        message: exception.message ?? '',
        details: exception.details);
  } else if (errorMessage.isNotEmpty) {
    error = IAPError(
        source: kIAPSource,
        code: kRestoredPurchaseErrorCode,
        message: errorMessage);
  }

  return QueryPurchaseDetailsResponse(
      pastPurchases: pastPurchases, error: error);
}