purchase method
Starts a purchase after configuration.
Cancellation is a domain result and must not be reported as a transport exception. Implementations must not both navigate and return a redirect URL unless their documented integration contract explicitly requires it.
Implementation
@override
Future<InappifySdkResult<PurchaseResult>> purchase(
InappifyPurchaseRequest request,
) async {
final cancelled = _preCancelled<PurchaseResult>(
'purchase',
request.cancellation,
);
if (cancelled != null) return cancelled;
final packageIdentifier = _resolvePackageIdentifier(request);
if (packageIdentifier == null) {
return _invalid<PurchaseResult>(
'purchase',
'A packageIdentifier could not be inferred unambiguously.',
);
}
if (_hasUnsupportedNativePurchaseOptions(request)) {
return _invalid<PurchaseResult>(
'purchase',
'Native-store purchase options are not supported by Web checkout.',
);
}
return _run<PurchaseResult>(
'purchase',
action: () async {
final raw = await _bridge.call(
'purchase',
positionalArguments: <Object?>[
_checkoutParameters(request, packageIdentifier),
const <String, Object?>{'redirect': false},
],
cancellation: request.cancellation,
injectAbortSignal: request.cancellation != null,
);
final checkout = InappifyWebPayloadCodec.checkout(raw);
final normalizedStatus = checkout.checkout.status.toLowerCase();
if (normalizedStatus == 'cancelled' || normalizedStatus == 'canceled') {
_bridge.clearPendingCheckout();
throw _WebSemanticException(
code: InappifyFailureCode.purchaseCancelled,
status: checkout.checkout.status,
);
}
if (normalizedStatus == 'failed' || normalizedStatus == 'expired') {
_bridge.clearPendingCheckout();
throw _WebSemanticException(
code: InappifyFailureCode.unknown,
status: checkout.checkout.status,
);
}
if (checkout.isPaid) {
_bridge.clearPendingCheckout();
_readCustomerPropertyBestEffort();
} else {
_bridge.persistPendingCheckout(checkout.checkout.id);
}
return PurchaseResult(
url: checkout.nextAction.url,
purchaseStatus: checkout.isPaid
? PurchaseStatus.DONE
: PurchaseStatus.NEEDTOPAY,
checkoutId: checkout.checkout.id,
checkoutStatus: checkout.checkout.status,
nextActionType: checkout.nextAction.type,
);
},
cancellation: request.cancellation,
mutationMayHaveCommitted: true,
);
}