import { setBankAccounts, setCardType, setInstallmentOptions, setPaymentOptions, setPaymentStepBusy, setSelectedBankAccountPk, setSelectedCreditPaymentPk, setShippingStepBusy } from '../../redux/reducers/checkout'; import { CheckoutContext, AccountUsage, ExtraField, GuestLoginFormParams, Order, PreOrder, SendSmsType, VerifySmsType } from '../../types'; import { buildClientRequestUrl, getCookie } from '../../utils'; import { api } from './api'; import { checkout } from '../urls'; import type { AppDispatch, AppStore } from 'redux/store'; import settings from 'settings'; import { showMobile3dIframe } from '../../utils/mobile-3d-iframe'; import { setCvcRequired, setError, setOtpModalVisible } from '@akinon/pz-masterpass/src/redux/reducer'; import { buildDirectPurchaseForm, buildPurchaseForm } from '@akinon/pz-masterpass/src/utils'; import { devLogger } from '@akinon/next/hooks/use-logger-context'; import { LogLevel } from '@akinon/next/hooks/use-logger'; const getLatestState = async (getState: () => any): Promise => { await new Promise((resolve) => setTimeout(resolve, 250)); return getState(); }; const recentLogMessages = new Map(); const getStore = async (): Promise => { const { store } = await import('redux/store'); return store; }; interface CheckoutResponse { pre_order?: PreOrder; errors: { non_field_errors: string; }; context_list?: CheckoutContext[]; template_name?: string; redirect_url?: string; } const validateCheckoutState = ( state: any, validations: Array<{ condition: (state: any) => boolean; errorMessage: string; severity?: LogLevel; data?: any; action?: () => void; }> ) => { validations.forEach( ({ condition, errorMessage, severity = 'error', data: logData, action }) => { if (condition(state)) { const now = Date.now(); const lastLogged = recentLogMessages.get(errorMessage) || 0; if (now - lastLogged > 2000) { recentLogMessages.set(errorMessage, now); switch (severity) { case 'error': devLogger.error( errorMessage, logData || state.checkout?.preOrder ); action?.(); break; case 'warn': devLogger.warn(errorMessage, logData || state.checkout?.preOrder); action?.(); break; default: devLogger.info(errorMessage, logData || state.checkout?.preOrder); action?.(); } } } } ); }; interface SetAddressesParams { shippingAddressPk: number; billingAddressPk: number; } interface SetRetailStoreParams { retailStorePk: number; billingAddressPk: number; } export interface CompleteCreditCardParams { card_holder: string; card_cvv: string; card_number: string; card_month: string; card_year: string; use_three_d?: boolean; save?: boolean; } interface GetContractResponse { result: string; } interface ApplePaySelectParams { agreement: boolean; validationURL: string; } interface ApplePayQueryParams { agreement: boolean; paymentToken: string; } export interface PayOnDeliveryParams { agreement: string; paymentType: string; } const buildCheckoutRequestUrl = ( path: string, options?: Parameters[1] ) => { const effectivePath = getCookie('pz-post-checkout-flow') === 'true' && /^\/orders\/checkout(\/|\?|$)/.test(path) ? path.replace('/orders/checkout', '/orders/post-checkout') : path; return buildClientRequestUrl(effectivePath, options); }; const completeMasterpassPayment = async ( params: CompleteCreditCardParams, dispatch: AppDispatch, context: CheckoutContext, reduxStore: AppStore ) => { const state = reduxStore.getState(); const { token, order_no, extras } = context.page_context; const { endpoints: apiEndpoints } = checkoutApi; const { preOrder } = state.checkout ?? {}; const { isDirectPurchase, referenceNo, credentials, msisdn, selectedCard, additionalParams, language } = state.masterpass ?? {}; const commonFormValues = { token, orderNo: order_no, referenceNo, merchantId: credentials?.merchant_id ?? null, msisdn, amount: preOrder?.total_amount_with_interest?.replace('.', '') ?? '', additionalParams: additionalParams ?? extras?.additionalParams, language, installmentCount: preOrder?.installment?.installment_count ?? 1 }; const form = isDirectPurchase ? await buildDirectPurchaseForm(commonFormValues, params) : await buildPurchaseForm({ ...commonFormValues, selectedCard, cardCvc: params?.card_cvv }); window.MFS?.[ state.masterpass.isDirectPurchase ? 'directPurchase' : 'purchase' ]($(form), async (statusCode, response) => { if (response.responseCode == '5009') { // TODO: Handle Digital Loan } if (response.responseCode == '5010') { const { isMobileApp } = state.root; const returnUrl = state.masterpass.credentials?.s3d_return_url; const url = response.url3D + '&returnUrl=' + encodeURIComponent(returnUrl); const urlObj = new URL(url, window.location.origin); urlObj.searchParams.set('t', new Date().getTime().toString()); if ( (isMobileApp || /iPad|iPhone|iPod|Android/i.test(navigator.userAgent)) && !settings.checkout?.iframeExcludedPaymentOptions?.includes( preOrder?.payment_option?.slug ) ) { showMobile3dIframe(urlObj.toString()); } else { window.location.href = urlObj.toString(); } return; } if (response.responseCode == '5001') { dispatch(setOtpModalVisible(true)); return; } if (['5013', '5182'].includes(response.responseCode)) { dispatch(setCvcRequired(true)); } if ( response.token && (response.responseCode == '0000' || response.responseCode == '') ) { dispatch( apiEndpoints.completeMasterpassPayment.initiate({ token }) as any ); } if (response.responseDescription.length) { dispatch(setError(response.responseDescription)); } }); }; let checkoutAbortController = new AbortController(); export const getCheckoutAbortSignal = () => { if (checkoutAbortController.signal.aborted) { checkoutAbortController = new AbortController(); } return checkoutAbortController.signal; }; const abortCheckout = () => { checkoutAbortController.abort(); checkoutAbortController = new AbortController(); }; export const checkoutApi = api.injectEndpoints({ endpoints: (build) => ({ fetchCheckout: build.query({ query: () => ({ url: buildCheckoutRequestUrl(checkout.fetchCheckout, {}) }), providesTags: ['Checkout'] }), resetCheckoutState: build.query({ query: () => ({ url: buildCheckoutRequestUrl(checkout.guestLogin, {}) }) }), fetchCheckoutResult: build.query<{ order: Order }, string>({ query: (token: string) => buildCheckoutRequestUrl(checkout.fetchCheckoutResult(token)) }), get3dRedirectForm: build.query<{ result: string }, void>({ query: () => buildCheckoutRequestUrl(checkout.get3dRedirectForm, { responseType: 'text' }) }), getContract: build.query({ query: (slug: string) => buildCheckoutRequestUrl(checkout.getContract(slug), { responseType: 'text' }) }), getCoupons: build.query({ query: () => ({ url: buildCheckoutRequestUrl(checkout.couponSelectionPage) }) }), setCoupon: build.mutation( { query: ({ pk, action }) => ({ url: buildCheckoutRequestUrl(checkout.couponSelectionPage, { useFormData: true }), method: 'POST', body: { coupon: pk, action } }), invalidatesTags: ['Basket'] } ), completeCreditCardPayment: build.mutation< CheckoutResponse, CompleteCreditCardParams >({ async queryFn( { card_holder, card_cvv, card_number, card_month, card_year, use_three_d = true, save = undefined }, _queryApi, _extraOptions, baseQuery ) { const reduxStore = await getStore(); const paymentOption = reduxStore.getState().checkout?.preOrder?.payment_option; if (paymentOption?.payment_type === 'masterpass') { const result = await baseQuery({ url: buildCheckoutRequestUrl(checkout.getMasterpassOrderNo, { useFormData: true }), method: 'POST' }); return result as { data: CheckoutResponse } | { error: any }; } const body: Record = { agreement: '1', use_three_d: use_three_d ? '1' : '0', card_cvv, card_holder, card_month, card_number, card_year }; if (save !== undefined) { body.save = save ? '1' : '0'; } const result = await baseQuery({ url: buildCheckoutRequestUrl(checkout.completeCreditCardPayment, { useFormData: true }), method: 'POST', body }); return result as { data: CheckoutResponse } | { error: any }; }, async onQueryStarted(args, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); const { data } = await queryFulfilled; const reduxStore = await getStore(); const completePaymentContext = data?.context_list?.find( (context) => context?.page_name === 'MasterpassCompletePage' ); if (completePaymentContext) { await completeMasterpassPayment( args, dispatch, completePaymentContext, reduxStore ); } dispatch(setPaymentStepBusy(false)); }, invalidatesTags: ['Basket'] }), completeMasterpassPayment: build.mutation< CheckoutResponse, { token: string; } >({ query: ({ token }) => ({ url: buildCheckoutRequestUrl(checkout.completeMasterpassPayment, { useFormData: true }), method: 'POST', body: { token } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); }, invalidatesTags: ['Basket'] }), completeFundsTransfer: build.mutation({ query: () => ({ url: buildCheckoutRequestUrl(checkout.completeFundsTransfer, { useFormData: true }), method: 'POST', body: { agreement: '1' } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); }, invalidatesTags: ['Basket'] }), guestLogin: build.mutation({ query: ({ user_email, phone_number }) => ({ url: buildCheckoutRequestUrl(checkout.guestLogin, { useFormData: true }), method: 'POST', body: { user_email, phone_number } }), invalidatesTags: ['Checkout'] }), setDeliveryOption: build.mutation({ query: (pk: number) => ({ url: buildCheckoutRequestUrl(checkout.setDeliveryOption, { useFormData: true }), method: 'POST', body: { delivery_option: String(pk) }, signal: getCheckoutAbortSignal() }), async onQueryStarted(arg, { dispatch, queryFulfilled, getState }) { dispatch(setShippingStepBusy(true)); const state = await getLatestState(getState); validateCheckoutState(state, [ { condition: (state) => { const preOrder = state.checkout?.preOrder; return preOrder?.basket?.basketitem_set?.length === 0; }, errorMessage: 'Your shopping basket is empty. Please add items to your basket before selecting a delivery option.', action: () => abortCheckout() } ]); try { await queryFulfilled; dispatch(setShippingStepBusy(false)); } catch (error) { dispatch(setShippingStepBusy(false)); } } }), setAddresses: build.mutation({ query: ({ shippingAddressPk, billingAddressPk }) => ({ url: buildCheckoutRequestUrl(checkout.setAddresses, { useFormData: true }), method: 'POST', body: { shipping_address: String(shippingAddressPk), billing_address: String(billingAddressPk) }, signal: getCheckoutAbortSignal() }), async onQueryStarted(arg, { dispatch, queryFulfilled, getState }) { dispatch(setShippingStepBusy(true)); const state = await getLatestState(getState); validateCheckoutState(state, [ { condition: (state) => { const deliveryOptions = state.checkout?.deliveryOptions; const preOrder = state.checkout?.preOrder; return deliveryOptions?.length > 0 ? preOrder && !preOrder.delivery_option?.pk : false; }, errorMessage: 'You need to select a delivery option before setting your addresses. Dispatch setAddresses action after delivery option selection.', action: () => abortCheckout() } ]); try { await queryFulfilled; dispatch(setShippingStepBusy(false)); } catch (error) { dispatch(setShippingStepBusy(false)); } } }), setShippingOption: build.mutation({ query: (pk: number) => ({ url: buildCheckoutRequestUrl(checkout.setShippingOption, { useFormData: true }), method: 'POST', body: { shipping_option: String(pk) }, signal: getCheckoutAbortSignal() }), async onQueryStarted(arg, { dispatch, queryFulfilled, getState }) { dispatch(setShippingStepBusy(true)); const state = await getLatestState(getState); validateCheckoutState(state, [ { condition: (state) => { const preOrder = state.checkout?.preOrder; return !preOrder?.billing_address; }, errorMessage: 'You need to provide a billing address before selecting a shipping option. Dispatch setShippingOption action after billing address selection.', action: () => abortCheckout() }, { condition: (state) => { const preOrder = state.checkout?.preOrder; return !preOrder?.shipping_address; }, errorMessage: 'You need to provide a shipping address before selecting a shipping option. Dispatch setShippingOption action after shipping address selection.', action: () => abortCheckout() } ]); try { await queryFulfilled; dispatch(setShippingStepBusy(false)); } catch (error) { dispatch(setShippingStepBusy(false)); } } }), setDataSourceShippingOptions: build.mutation({ query: (pks) => ({ url: buildCheckoutRequestUrl(checkout.setDataSourceShippingOption, { useFormData: true }), method: 'POST', body: { data_source_shipping_options: JSON.stringify(pks) } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setShippingStepBusy(true)); await queryFulfilled; dispatch(setShippingStepBusy(false)); } }), setRetailStore: build.mutation({ query: ({ retailStorePk, billingAddressPk }) => ({ url: buildCheckoutRequestUrl( '/orders/checkout?page=RetailStoreSelectionPage', { useFormData: true } ), method: 'POST', body: { retail_store: Number(retailStorePk), billing_address: Number(billingAddressPk) } }) }), fetchPaymentOptions: build.query({ query: () => ({ url: buildCheckoutRequestUrl(checkout.setPaymentOption) }), providesTags: ['PaymentOptions'] }), setPaymentOption: build.mutation({ query: (pk: number) => ({ url: buildCheckoutRequestUrl(checkout.setPaymentOption, { useFormData: true }), method: 'POST', body: { payment_option: String(pk) }, signal: getCheckoutAbortSignal() }), async onQueryStarted(arg, { dispatch, queryFulfilled, getState }) { dispatch(setPaymentStepBusy(true)); dispatch(setInstallmentOptions([])); dispatch(setBankAccounts([])); dispatch(setSelectedBankAccountPk(null)); dispatch(setCardType(null)); const state = await getLatestState(getState); validateCheckoutState(state, [ { condition: (state) => { const preOrder = state.checkout?.preOrder; return !preOrder?.shipping_option?.pk; }, errorMessage: 'You need to select a shipping option before choosing a payment method. Dispatch setPaymentOption action after shipping option selection.', action: () => abortCheckout() } ]); try { await queryFulfilled; dispatch(setPaymentStepBusy(false)); } catch (error) { dispatch(setPaymentStepBusy(false)); } } }), setWalletSelectionPage: build.mutation< CheckoutResponse, { payment_option: number; validationURL?: string; } >({ query: ({ payment_option: pk, validationURL }) => ({ url: buildCheckoutRequestUrl(checkout.setWalletSelectionPage, { useFormData: true }), method: 'POST', body: { agreement: true, payment_option: pk, validationURL } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); } }), setWalletPaymentPage: build.mutation< CheckoutResponse, { payment_token?: string; [key: string]: any; } >({ query: (requestBody) => ({ url: buildCheckoutRequestUrl(checkout.setWalletPaymentPage, { useFormData: true }), method: 'POST', body: requestBody }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); } }), setWalletCompletePage: build.mutation< CheckoutResponse, { success: boolean; cko_payment_id?: string; [key: string]: any; } >({ query: ({ success, ...additionalParams }) => ({ url: buildCheckoutRequestUrl(checkout.setWalletCompletePage, { useFormData: true }), method: 'POST', body: { success, ...additionalParams } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); } }), setBinNumber: build.mutation({ async queryFn(binNumber, _queryApi, _extraOptions, baseQuery) { const reduxStore = await getStore(); const paymentOption = reduxStore.getState().checkout?.preOrder?.payment_option; const binNumberUrl = paymentOption?.payment_type === 'masterpass' ? checkout.setMasterpassBinNumber : checkout.setBinNumber; const result = await baseQuery({ url: buildCheckoutRequestUrl(binNumberUrl, { useFormData: true }), method: 'POST', body: { bin_number: binNumber } }); return result as { data: CheckoutResponse } | { error: any }; }, async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); dispatch(setCardType(arg)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); } }), setInstallmentOption: build.mutation({ async queryFn(pk, _queryApi, _extraOptions, baseQuery) { const reduxStore = await getStore(); const paymentOption = reduxStore.getState().checkout?.preOrder?.payment_option; const installmentOption = paymentOption?.payment_type === 'masterpass' ? checkout.setMasterPassInstallmentOption : checkout.setInstallmentOption; const result = await baseQuery({ url: buildCheckoutRequestUrl(installmentOption, { useFormData: true }), method: 'POST', body: { installment: String(pk) } }); return result as { data: CheckoutResponse } | { error: any }; }, async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); } }), setFundsTransferOption: build.mutation({ query: (pk: number) => ({ url: buildCheckoutRequestUrl(checkout.setFundsTransferOption, { useFormData: true }), method: 'POST', body: { bank_account: String(pk) } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); dispatch(setSelectedBankAccountPk(arg)); } }), setCreditPaymentOption: build.mutation({ query: (pk: number) => ({ url: buildCheckoutRequestUrl(checkout.setCreditPaymentOption, { useFormData: true }), method: 'POST', body: { credit_payment_option: pk } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); dispatch(setSelectedCreditPaymentPk(arg)); } }), confirmationCreditPayment: build.mutation({ query: () => ({ url: buildCheckoutRequestUrl(checkout.confirmationCreditPayment, { useFormData: true }), method: 'POST', body: { agreement: true } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); } }), completeRedirectionPayment: build.mutation({ query: () => ({ url: buildCheckoutRequestUrl(checkout.completeRedirectionPayment, { useFormData: true }), method: 'POST', body: { agreement: true } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); } }), applePaymentSelect: build.mutation({ query: ({ agreement, validationURL }) => ({ url: buildCheckoutRequestUrl(checkout.confirmationPaymentSelect, { useFormData: true }), method: 'POST', body: { agreement, validationURL } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); } }), appleQuery: build.mutation({ query: ({ agreement, paymentToken }) => ({ url: buildCheckoutRequestUrl(checkout.confirmationQuery, { useFormData: true }), method: 'POST', body: { agreement, payment_token: paymentToken } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); } }), completeConfirmation: build.mutation({ query: () => ({ url: buildCheckoutRequestUrl(checkout.confirmationComplete, { useFormData: true }), method: 'POST', body: { agreement: true } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); } }), setCompletePayOnDelivery: build.mutation< CheckoutResponse, PayOnDeliveryParams >({ query: ({ paymentType }) => ({ url: buildCheckoutRequestUrl( `${checkout.fetchCheckout}?page=PayOnDeliveryPage`, { useFormData: true } ), method: 'POST', body: { agreement: '1', paymentType } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); } }), setPayOnDeliveryChoice: build.mutation({ query: (body) => ({ url: buildCheckoutRequestUrl( `${checkout.fetchCheckout}?page=PayOnDeliveryPaymentChoicePage`, { useFormData: true } ), method: 'POST', body: { payment_choice: body } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); } }), completeLoyaltyPayment: build.mutation({ query: () => ({ url: buildCheckoutRequestUrl(checkout.completeLoyaltyPayment, { useFormData: true }), method: 'POST', body: { agreement: true } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); await queryFulfilled; dispatch(setPaymentStepBusy(false)); } }), getCheckoutLoyaltyBalance: build.query({ query: () => ({ url: buildCheckoutRequestUrl(checkout.loyaltyMoneyUsage) }) }), payWithLoyaltyBalance: build.mutation< any, string | { account_usages: AccountUsage[] } >({ query: (params) => { const isAccountUsages = typeof params === 'object' && 'account_usages' in params; return { url: buildCheckoutRequestUrl(checkout.loyaltyMoneyUsage, { useFormData: true }), method: 'POST', body: isAccountUsages ? { account_usages: JSON.stringify(params.account_usages) } : { loyalty_amount_to_use: params } }; }, async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setPaymentStepBusy(true)); dispatch(setPaymentOptions([])); await queryFulfilled; const paymentOptionsData = await dispatch( checkoutApi.endpoints.fetchPaymentOptions.initiate() ).unwrap(); const paymentOptions = paymentOptionsData?.context_list?.find( (context) => context?.page_name === 'PaymentOptionSelectionPage' )?.page_context?.payment_options; if (paymentOptions) { dispatch(setPaymentOptions(paymentOptions)); } dispatch(setPaymentStepBusy(false)); }, invalidatesTags: ['PaymentOptions'] }), setOrderNote: build.mutation({ query: (notes) => ({ url: buildCheckoutRequestUrl(checkout.setOrderNote, { useFormData: true }), method: 'POST', body: { notes } }) }), setDeliveryBags: build.mutation< CheckoutResponse, { sku: string; quantity?: number } >({ query: ({ sku, quantity }) => { const body = { product: sku, ...(quantity !== undefined && { quantity }) }; return { url: buildCheckoutRequestUrl(checkout.deliveryBagsPage, { useFormData: true }), method: 'POST', body }; } }), setAttributeBasedShippingOptions: build.mutation< CheckoutResponse, Record >({ query: (options) => ({ url: buildCheckoutRequestUrl(checkout.setAttributeBasedShippingOption, { useFormData: true }), method: 'POST', body: { attribute_based_shipping_options: JSON.stringify(options) } }), async onQueryStarted(arg, { dispatch, queryFulfilled }) { dispatch(setShippingStepBusy(true)); await queryFulfilled; dispatch(setShippingStepBusy(false)); } }), setOrderSelectionPage: build.mutation< CheckoutResponse, { extra_field: ExtraField } >({ query: ({ extra_field }) => ({ url: buildCheckoutRequestUrl(checkout.setOrderSelectionPage, { useFormData: true }), method: 'POST', body: { extra_field } }) }), fetchLoyaltyData: build.query({ query: () => ({ url: buildCheckoutRequestUrl(checkout.loyaltyCardPage, { accept: 'application/json', contentType: 'application/json' }), method: 'GET' }) }), setLoyaltyData: build.mutation({ query: (amount) => ({ url: buildCheckoutRequestUrl(checkout.loyaltyCardPage, { useFormData: true }), method: 'POST', body: { selected_loyalty_amount: amount } }) }), sendSms: build.mutation({ query: (body) => ({ url: buildCheckoutRequestUrl(checkout.sendSmsPage, { useFormData: true }), method: 'POST', body }) }), verifySms: build.mutation({ query: (body) => ({ url: buildCheckoutRequestUrl(checkout.verifySmsPage, { useFormData: true }), method: 'POST', body }) }), saveSampleProducts: build.mutation({ query: (products = []) => { const formData = new FormData(); products.forEach((product) => { formData.append('sample_products', String(product)); }); return { url: buildCheckoutRequestUrl(checkout.saveSampleProducts), method: 'POST', body: formData }; } }) }), overrideExisting: false }); export const { useFetchCheckoutQuery, useFetchCheckoutResultQuery, useGet3dRedirectFormQuery, useGetContractQuery, useGetCouponsQuery, useSetCouponMutation, useCompleteCreditCardPaymentMutation, useCompleteFundsTransferMutation, useGuestLoginMutation, useSetDeliveryOptionMutation, useSetAddressesMutation, useSetShippingOptionMutation, useSetDataSourceShippingOptionsMutation, useFetchPaymentOptionsQuery, useSetPaymentOptionMutation, useSetBinNumberMutation, useSetInstallmentOptionMutation, useSetFundsTransferOptionMutation, useSetRetailStoreMutation, useSetCreditPaymentOptionMutation, useConfirmationCreditPaymentMutation, useCompleteRedirectionPaymentMutation, useApplePaymentSelectMutation, useAppleQueryMutation, useCompleteConfirmationMutation, useSetCompletePayOnDeliveryMutation, useSetPayOnDeliveryChoiceMutation, useCompleteLoyaltyPaymentMutation, useGetCheckoutLoyaltyBalanceQuery, usePayWithLoyaltyBalanceMutation, useSetOrderNoteMutation, useSetDeliveryBagsMutation, useSetAttributeBasedShippingOptionsMutation, useSetOrderSelectionPageMutation, useFetchLoyaltyDataQuery, useSetLoyaltyDataMutation, useSetWalletSelectionPageMutation, useSetWalletPaymentPageMutation, useSetWalletCompletePageMutation, useSendSmsMutation, useVerifySmsMutation, useResetCheckoutStateQuery, useSaveSampleProductsMutation } = checkoutApi;