queryPastPurchases method
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 failedPurchaseDetails.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,
);
}