async prePaySteps()

in libs/payments/cart/src/lib/checkout.service.ts [92:238]


  async prePaySteps(
    cart: ResultCart,
    customerData: CheckoutCustomerData
  ): Promise<PrePayStepsResult> {
    const taxAddress = cart.taxAddress;
    if (!taxAddress) {
      throw new CartNoTaxAddressError(cart.id);
    }

    let version = cart.version;

    if (!cart.currency) {
      throw new CartCurrencyNotFoundError(
        cart.currency || undefined,
        taxAddress.countryCode
      );
    }

    const uid = cart.uid;
    if (!uid) {
      throw new CartUidNotFoundError(cart.id);
    }

    const fxaAccounts = await this.accountManager.getAccounts([uid]);
    if (!(fxaAccounts && fxaAccounts.length > 0)) {
      throw new CartAccountNotFoundError(cart.id);
    }
    const email = fxaAccounts[0].email;

    let stripeCustomerId = cart.stripeCustomerId;
    let customer: StripeCustomer;
    if (!stripeCustomerId) {
      customer = await this.customerManager.create({
        uid,
        email,
        displayName: customerData.displayName,
        taxAddress,
      });

      stripeCustomerId = customer.id;
    } else {
      customer = await this.customerManager.retrieve(stripeCustomerId);

      await this.customerManager.update(stripeCustomerId, {
        shipping: {
          name: email,
          address: {
            country: taxAddress.countryCode,
            postal_code: taxAddress.postalCode,
          },
        },
      });
    }

    if (uid && !cart.stripeCustomerId) {
      await this.accountCustomerManager.createAccountCustomer({
        uid,
        stripeCustomerId,
      });
    }

    // Cart only needs to be updated if we created a customer
    if (!cart.uid || !cart.stripeCustomerId) {
      await this.cartManager.updateFreshCart(cart.id, cart.version, {
        uid,
        stripeCustomerId,
      });
      version += 1;
    }

    // validate customer is eligible for product via eligibility service
    // throws cart eligibility mismatch error if no match found
    const eligibility = await this.eligibilityService.checkEligibility(
      cart.interval as SubplatInterval,
      cart.offeringConfigId,
      uid,
      stripeCustomerId
    );

    const cartEligibilityStatus =
      handleEligibilityStatusMap[eligibility.subscriptionEligibilityResult];

    if (cartEligibilityStatus !== cart.eligibilityStatus) {
      throw new CartEligibilityMismatchError(
        cart.id,
        cart.eligibilityStatus,
        cartEligibilityStatus
      );
    }

    // re-validate total amount against upcoming invoice
    // throws cart total mismatch error if no match found
    const price = await this.productConfigurationManager.retrieveStripePrice(
      cart.offeringConfigId,
      cart.interval as SubplatInterval
    );

    const upcomingInvoice = await this.invoiceManager.previewUpcoming({
      priceId: price.id,
      currency: cart.currency,
      customer: customer,
      taxAddress: taxAddress,
    });

    if (upcomingInvoice.subtotal !== cart.amount) {
      throw new CartTotalMismatchError(
        cart.id,
        cart.amount,
        upcomingInvoice.subtotal
      );
    }

    // check if customer already has subscription to price and cancel if they do
    await this.subscriptionManager.cancelIncompleteSubscriptionsToPrice(
      stripeCustomerId,
      price.id
    );

    const enableAutomaticTax = this.customerManager.isTaxEligible(customer);

    let promotionCode: StripePromotionCode | undefined;
    if (cart.couponCode) {
      try {
        await this.promotionCodeManager.assertValidPromotionCodeNameForPrice(
          cart.couponCode,
          price,
          cart.currency
        );

        promotionCode = await this.promotionCodeManager.retrieveByName(
          cart.couponCode
        );
      } catch (e) {
        throw new CartInvalidPromoCodeError(cart.couponCode, cart.id);
      }
    }

    return {
      uid: uid,
      customer,
      enableAutomaticTax,
      promotionCode,
      version,
      price,
      eligibility,
    };
  }