Untitled

mail@pastecode.io avatar
unknown
typescript
a year ago
4.7 kB
3
Indexable
Never
const handlePaymentMethod = async (stripeDetails) => {
  const { paymentMethod, error: paymentMethodError } =
    await stripeHook!.createPaymentMethod({
      elements,
      params: {
        billing_details: {
          name: formState.nameOnCard.value,
          email: summaryForm.current.email.value,
          phone: summaryForm.current.phone.value,
          address: {
            line1: formState.address1.value,
            line2: formState.address2.value,
          },
        },
      },
    });

  if (paymentMethodError) {
    handleValueChange("stripe", {
      ...stripeDetails,
      error: paymentMethodError,
    });
    setPaymentLoading(false);
    return;
  }

  handleValueChange("stripe", {
    ...stripeDetails,
    paymentMethodId: paymentMethod?.id,
  });
};

const handlePaymentIntent = async (
  paymentMethod,
  amount,
  customerId,
  listingId,
  stripeDetails
) => {
  const paymentIntentRequest = await fetch("/api/stripe/createPaymentIntent", {
    method: "POST",
    body: JSON.stringify({
      userAgent: window.navigator.userAgent,
      amount,
      customerId,
      paymentMethodId: paymentMethod?.id,
      returnURL: `${process.env.NEXT_PUBLIC_ORIGIN}/booking/${listingId}/action-completed`,
    }),
    headers: process.env.NEXT_PUBLIC_ORIGIN?.includes("evrinternal.com")
      ? {
          Authorization:
            "Basic " +
            btoa(
              process.env.NEXT_PUBLIC_BASIC_AUTH_USER +
                ":" +
                process.env.NEXT_PUBLIC_BASIC_AUTH_PASSWORD
            ),
          "Content-Type": "application/json",
        }
      : {
          "Content-Type": "application/json",
        },
  });
  const paymentIntentResponse = await paymentIntentRequest.json();

  if (paymentIntentResponse.error) {
    handleValueChange("stripe", {
      ...stripeDetails,
      error: paymentIntentResponse.error,
    });
    setPaymentLoading(false);
    return;
  }

  handleValueChange("stripe", {
    ...stripeDetails,
    paymentIntentId: paymentIntentResponse.intent_id,
  });
  return { paymentIntentResponse };
};

const handlePaymentResponse = async (
  paymentIntentResponse,
  stripeHook,
  stripeDetails
) => {
  if (paymentIntentResponse.status !== "requires_action") {
    setPaymentLoading(false);
    handleSubmit(event);
    return;
  }

  if (
    paymentIntentResponse.action &&
    paymentIntentResponse.action.type === "redirect_to_url"
  ) {
    const width = window.innerWidth
      ? window.innerWidth
      : document.documentElement.clientWidth
      ? document.documentElement.clientWidth
      : screen.width;
    const height = window.innerHeight
      ? window.innerHeight
      : document.documentElement.clientHeight
      ? document.documentElement.clientHeight
      : screen.height;

    const windowFeatures = `left=100,top=100,width=${width * 0.8},height=${
      height * 0.8
    }`;
    const handle = window.open(
      paymentIntentResponse.action.redirect_to_url.url,
      "mozillaWindow",
      windowFeatures
    );

    if (!handle) {
      handleValueChange("stripe", {
        ...stripeDetails,
        error: new Error(
          "Permission denined for Popup, Please allow the popup window"
        ),
      });
      setPaymentLoading(false);
    }

    return;
  }

  const result = await stripeHook.handleNextAction({
    clientSecret: paymentIntentResponse.client_secret,
  });

  if (!result.error) return;

  handleValueChange("stripe", {
    ...stripeDetails,
    error: result.error,
  });
  setPaymentLoading(false);
};

const handleOnSubmit = async (event: React.FormEvent) => {
  event.preventDefault();

  setFormPreSubmit(true);

  const hasErrors = validateFormState();

  if (
    hasErrors ||
    !stripeHook ||
    !elements ||
    !paymentDetailsForm.current.stripe.valid
  ) {
    return;
  }

  const form = { ...paymentDetailsForm.current };
  const { error: stripeElementError, ...stripeDetails } = form.stripe;

  setPaymentLoading(true);

  const { error: submitError } = await elements.submit();
  if (submitError) {
    handleValueChange("stripe", {
      ...stripeDetails,
      error: submitError,
    });
    setPaymentLoading(false);
    return;
  }

  await handlePaymentMethod(stripeDetails);

  try {
    const { paymentIntentResponse } = await handlePaymentIntent(
      paymentMethod,
      quote?.price.total,
      customerId,
      listingId,
      stripeDetails
    );
    await handlePaymentResponse(
      paymentIntentResponse,
      stripeHook,
      stripeDetails
    );
  } catch (err) {
    handleValueChange("stripe", {
      ...stripeDetails,
      error: new Error("Failed on setting up payment"),
    });
    setPaymentLoading(false);
  }
};