confirm method

Future<void> confirm({
  1. required DocumentBase<StripePurchaseModel> purchase,
  2. bool online = true,
  3. required void builder(
    1. Uri endpoint,
    2. Widget webView,
    3. VoidCallback onClosed
    ),
  4. VoidCallback? onClosed,
  5. Duration timeout = const Duration(seconds: 15),
})

Confirm purchase.

3D Secure authentication of your credit card is performed at this point.

If online is true, WebView is displayed by builder if 3D Secure authentication is enabled.

If online is false, you will be notified by email.

onClosed is called when the WebView displayed by builder is closed.

purchaseを確定させます。

クレジットカードの3Dセキュア認証をこの時点で行います。

onlinetrueの場合は、3Dセキュア認証が有効な場合builderによってWebViewが表示されます。

onlinefalseの場合は、メールによって通知が届きます。

onClosedbuilderによって表示されたWebViewが閉じられた際に呼び出されます。

Implementation

Future<void> confirm({
  required DocumentBase<StripePurchaseModel> purchase,
  bool online = true,
  required void Function(
    Uri endpoint,
    Widget webView,
    VoidCallback onClosed,
  ) builder,
  VoidCallback? onClosed,
  Duration timeout = const Duration(seconds: 15),
}) async {
  if (_completer != null) {
    return _completer!.future;
  }
  _completer = Completer<void>();
  Completer<void>? internalCompleter = Completer<void>();
  try {
    final value = purchase.value;
    if (value == null) {
      throw Exception(
        "Purchase information is empty. Please run [create] method.",
      );
    }
    if (value.error) {
      throw Exception(
        "There has been an error with your payment. Please check and Refresh your payment information once.",
      );
    }
    if (value.canceled) {
      throw Exception("This purchase has already canceled.");
    }
    if (value.confirm && value.verified) {
      throw Exception("This purchase has already confirmed.");
    }
    var language = value.locale?.split("_").firstOrNull;
    if (!StripePurchaseMasamuneAdapter
        .primary.threeDSecureOptions.acceptLanguage
        .contains(language)) {
      language = StripePurchaseMasamuneAdapter
          .primary.threeDSecureOptions.acceptLanguage.first;
    }
    final functionsAdapter =
        StripePurchaseMasamuneAdapter.primary.functionsAdapter ??
            FunctionsAdapter.primary;
    final callbackHost = StripePurchaseMasamuneAdapter
        .primary.callbackURLSchemeOrHost
        .toString()
        .trimQuery()
        .trimString("/");
    final hostingEndpoint = StripePurchaseMasamuneAdapter
            .primary.hostingEndpoint
            ?.call(language!) ??
        callbackHost;
    final returnPathOptions =
        StripePurchaseMasamuneAdapter.primary.returnPathOptions;

    final response = await functionsAdapter.execute(
      StripeConfirmPurchaseAction(
        userId: userId,
        orderId: value.orderId,
        returnUrl: online
            ? Uri.parse(
                "$callbackHost/${returnPathOptions.finishedOnConfirmPurchase.trimString("/")}")
            : Uri.parse(
                "${functionsAdapter.endpoint}/${StripePurchaseMasamuneAdapter.primary.threeDSecureOptions.redirectFunctionPath}"),
        failureUrl: Uri.parse(
            "$hostingEndpoint/${StripePurchaseMasamuneAdapter.primary.threeDSecureOptions.failurePath}"),
        successUrl: Uri.parse(
            "$hostingEndpoint/${StripePurchaseMasamuneAdapter.primary.threeDSecureOptions.successPath}"),
      ),
    );

    if (response.purchaseId.isEmpty) {
      throw Exception("Response is invalid.");
    }
    bool authenticated = true;
    onCompleted() {
      if (authenticated) {
        internalCompleter?.complete();
        internalCompleter = null;
      } else {
        internalCompleter
            ?.completeError(Exception("3D Secure authentication failed."));
        internalCompleter = null;
      }
    }

    final nextAction = response.nextActionUrl?.toString();
    if (nextAction.isNotEmpty) {
      final webView = StripeWebview(
        response.nextActionUrl!,
        shouldOverrideUrlLoading: (url) {
          final path = url.trimQuery().replaceAll(callbackHost, "");
          if (path ==
              "/${returnPathOptions.finishedOnConfirmPurchase.trimString("/")}") {
            onClosed?.call();
            onCompleted();
            return StripeNavigationActionPolicy.cancel;
          }
          final uri = Uri.parse(url);
          if (uri.host == "hooks.stripe.com" &&
              uri.queryParameters.containsKey("authenticated")) {
            authenticated = uri.queryParameters["authenticated"] == "true";
          }
          return StripeNavigationActionPolicy.allow;
        },
        onCloseWindow: () {
          onCompleted();
        },
      );
      builder.call(response.nextActionUrl!, webView, onCompleted);
      await internalCompleter!.future;
    }
    await Future.doWhile(() async {
      await Future.delayed(const Duration(milliseconds: 100));
      await purchase.reload();
      return purchase.value != null &&
          (!purchase.value!.confirm || !purchase.value!.verified);
    }).timeout(timeout);
    _completer?.complete();
    _completer = null;
    internalCompleter?.complete();
    internalCompleter = null;
    notifyListeners();
  } catch (e) {
    _completer?.completeError(e);
    _completer = null;
    internalCompleter?.complete();
    internalCompleter = null;
    rethrow;
  } finally {
    _completer?.complete();
    _completer = null;
    internalCompleter?.complete();
    internalCompleter = null;
  }
}