createDeposit method

Future<Operation?> createDeposit()

Creates a OperationDeposit.

Implementation

Future<Operation?> createDeposit() async {
  operationStatus.value = RxStatus.loading();

  try {
    // Under Web platforms, it's better to open the popup as fast as possible
    // due to browser usual policies to block unexpected popups.
    //
    // Thus the mutation itself is happening within the popup afterwards
    //
    // Message passing cannot be reliable due to iOS Safari, for example,
    // freezing the execution when tab is not in focus.
    if (PlatformUtils.isDesktop && !PlatformUtils.isWeb) {
      operation.value = await _walletService.createOperationDeposit(
        methodId: method.id,
        nominal: nominal,
        country: country,
        paypal: _secret ??= OperationDepositSecret.generate(),
      );
    }

    operationStatus.value = RxStatus.success();

    String? orderId;
    Price? total;

    final OperationDepositMethodPricing? pricing = method.pricing;
    final Price? perNominal = pricing?.total;
    if (perNominal != null) {
      total = nominal * perNominal;
    }

    final Operation? order = operation.value?.value;
    if (order is OperationDeposit) {
      final details = order.details;
      if (details is OperationDepositPayPalDetails) {
        orderId = details.processingUrl.val.split('?order_id=').last;
      }

      if (total == null) {
        final OperationDepositPricing? pricing = order.pricing;
        final Price? perNominal = pricing?.total;
        if (perNominal != null) {
          total = nominal * perNominal;
        }
      }
    }

    // Ensure parameters used by PayPal HTML page are up to date.
    final MyUser? myUser = this.myUser.value;
    if (myUser != null) {
      WebUtils.putAccount(myUser.id);
    }

    final String url = '${Config.origin}/payment/paypal.html';
    final Map<String, dynamic> parameters = {
      'price': total?.l10n ?? nominal.l10next(digits: 0),
      'account': myUser?.num.toString(),
      'name': myUser?.title,
      'client-id': Config.payPalClientId,
      if (orderId == null) ...{
        'operation-id': operation.value?.value.id.val,
        'secret': _secret?.val,
        'method-id': method.id,
        'nominal': nominal.l10next(digits: 0),
        'country': country.val,
      } else
        'order-id': orderId,
    };

    final WindowHandle handle = await WebUtils.openPopup(
      url,
      parameters: parameters,
    );

    _messagesSubscription?.cancel();
    _messagesSubscription = handle.messages.listen((e) async {
      Log.debug('Message received from `WindowHandle` -> $e', '$runtimeType');

      if (e is Map) {
        final type = e['type'];

        if (type is String) {
          switch (type) {
            case 'createOperationDeposit':
              final operationId = e['operationId'];

              if (operationId is String) {
                operation.value = await _walletService.get(
                  id: OperationId(operationId),
                );

                _startResponseTimer();
              }
              break;
          }
        }
      }
    });

    if (!handle.isOpen) {
      Log.warning(
        'createDeposit() -> Popup didn\'t open, trying `launchUrlString()`...',
        '$runtimeType',
      );

      try {
        final bool isOpen = await launchUrlString(
          '$url?${parameters.entries.map((e) => '${e.key}=${e.value}').join('&')}',
        );

        Log.warning(
          'createDeposit() -> `launchUrlString()` is open: $isOpen',
          '$runtimeType',
        );

        if (!isOpen) {
          await MessagePopup.alert(
            'Window cannot be opened automatically',
            button: (context) {
              return PrimaryButton(
                onPressed: () async {
                  await launchUrlString(
                    '$url?${parameters.entries.map((e) => '${e.key}=${e.value}').join('&')}',
                  );
                },
                title: 'btn_proceed'.l10n,
              );
            },
          );
        }
      } catch (e) {
        Log.error(
          'createDeposit() -> unable to do `launchUrlString()` due to $e',
          '$runtimeType',
        );

        MessagePopup.error(e);

        rethrow;
      }

      _startResponseTimer();
    }

    return operation.value?.value;
  } catch (e) {
    operationStatus.value = RxStatus.error('err_data_transfer'.l10n);
    error.value = e.toString();
    rethrow;
  } finally {
    status.value = PayPalDepositStatus.inProgress;
  }
}