UNPKG

@noaignite/react-centra-checkout

Version:

React components and helpers for Centra checkout api

1 lines 8.08 kB
{"version":3,"file":"PaymentEmbed.cjs","names":["memo","useState","useRef","useCentraSelection","useCentraHandlers","useMemo","useCallback","isPlainObject","HtmlEmbed","isEqual"],"sources":["../src/PaymentEmbed.tsx"],"sourcesContent":["import type * as CheckoutApi from '@noaignite/centra-types'\nimport { isPlainObject } from '@noaignite/utils'\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport isEqual from 'react-fast-compare'\nimport { useCentraHandlers, useCentraSelection } from './Context'\nimport { HtmlEmbed } from './internal/HtmlEmbed'\n\nexport interface PaymentEmbedProps {\n values: Record<string, unknown>\n onPaymentSuccess?: (paymentResult: CheckoutApi.SuccessResponse<CheckoutApi.Payment>) => void\n onPaymentError?: (error: CheckoutApi.Errors) => void\n}\n\n/** This component handles rendering of payment widgets such as Klarna Checkout and Adyen drop-in, if you submit payments yourself directly,\nyou should simply call the submitPayment method of the context instead */\nexport const PaymentEmbed = memo(function PaymentEmbed(\n props: PaymentEmbedProps,\n): React.ReactElement | null {\n const { values, onPaymentError, onPaymentSuccess } = props\n\n const [paymentResult, setPaymentResult] =\n useState<CheckoutApi.Response<CheckoutApi.Payment> | null>(null)\n const [paymentCallbackError, setPaymentCallbackError] = useState<CheckoutApi.Errors | null>(null)\n\n const previousPaymentMethod = useRef<string | null>(null)\n\n // Get selection\n const { selection, paymentMethods } = useCentraSelection()\n const { submitPayment } = useCentraHandlers()\n\n // Get payment method\n const paymentMethodId = selection?.paymentMethod\n const paymentMethod = useMemo(\n () => paymentMethods?.find((p) => p.paymentMethod === paymentMethodId),\n [paymentMethods, paymentMethodId],\n )\n\n // Submit payment\n const handlePaymentCallback = useCallback(\n (event: GlobalEventHandlersEventMap['centra_checkout_payment_callback']) => {\n const {\n addressIncluded,\n billingAddress: detailsAddress,\n shippingAddress: detailsShippingAddress,\n paymentMethod: detailsPaymentMethod,\n paymentMethodSpecificFields,\n } = event.detail\n\n const payload = {\n address: values.address,\n shippingAddress: values.shippingAddress,\n paymentMethod: detailsPaymentMethod,\n paymentMethodSpecificFields,\n termsAndConditions: values.termsAndConditions,\n } as Record<string, unknown>\n\n if (addressIncluded) {\n // if address is included in event, send that address instead\n payload.address = detailsAddress\n payload.shippingAddress = detailsShippingAddress\n }\n\n submitPayment?.(payload)\n .then((result) => {\n if ('errors' in result && Boolean(result.errors)) {\n onPaymentError?.(result.errors)\n // set paymentResult to null so that a new POST /payment request is made to refresh the widget\n setPaymentResult(null)\n setPaymentCallbackError(result.errors)\n } else {\n onPaymentSuccess?.(result)\n setPaymentCallbackError(null)\n }\n })\n .catch((err: unknown) => {\n console.error('@noaignite/react-centra-checkout: Could not submit payment')\n\n if (isPlainObject(err)) {\n setPaymentCallbackError(err)\n }\n\n console.error(err)\n })\n },\n [submitPayment, onPaymentSuccess, onPaymentError, values],\n )\n\n // Reset payment result when method changes\n useEffect(() => {\n if (selection?.paymentMethod !== previousPaymentMethod.current) {\n setPaymentResult(null)\n }\n }, [selection?.paymentMethod])\n\n // Retrieve formHtml\n useEffect(() => {\n const shouldRequestPayment =\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- we actually want || here because we are checking for undefined, null and false\n paymentMethod?.supportsInitiateOnly || paymentMethod?.providesCustomerAddressAfterPayment // if either of these are true, this is a paymentMethod which provides an embed\n\n if (\n ((selection?.paymentMethod === previousPaymentMethod.current || !shouldRequestPayment) &&\n !paymentCallbackError) ||\n !selection?.paymentMethod\n ) {\n return\n }\n\n previousPaymentMethod.current = selection.paymentMethod\n\n // don't send termsAndConditions when fetching embed payments, as we don't want it to fail just yet.\n submitPayment?.({ ...values, termsAndConditions: undefined })\n .then((result) => {\n if ('errors' in result) {\n console.error(result.errors)\n onPaymentError?.(result.errors)\n throw new Error('@noaignite/react-centra-checkout: Error while fetching widget')\n }\n\n if (result.action === 'form' && !result.formHtml) {\n throw new Error('@noaignite/react-centra-checkout: No form to render')\n }\n\n setPaymentResult(result)\n setPaymentCallbackError(null)\n })\n .catch((err: unknown) => {\n console.error(err)\n setPaymentResult(null)\n })\n }, [\n onPaymentError,\n paymentCallbackError,\n paymentMethod,\n selection?.paymentMethod,\n selection?.totals?.grandTotalPriceAsNumber,\n submitPayment,\n values,\n ])\n\n useEffect(() => {\n // Fires when customer submits payment\n document.addEventListener('centra_checkout_payment_callback', handlePaymentCallback)\n\n return () => {\n document.removeEventListener('centra_checkout_payment_callback', handlePaymentCallback)\n }\n }, [handlePaymentCallback])\n\n const formHtml = paymentResult && 'formHtml' in paymentResult && paymentResult.formHtml\n\n return formHtml ? <HtmlEmbed html={formHtml} id=\"centra-payment-form\" /> : null\n}, isEqual)\n"],"mappings":"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"}