2022-06-21 14:09:22 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
|
|
|
import type { CheckoutResponse } from '@woocommerce/types';
|
|
|
|
import { store as noticesStore } from '@wordpress/notices';
|
2022-11-18 12:13:00 +00:00
|
|
|
import { dispatch as wpDispatch, select as wpSelect } from '@wordpress/data';
|
2022-06-21 14:09:22 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
2022-11-18 12:13:00 +00:00
|
|
|
import { STORE_KEY as PAYMENT_STORE_KEY } from '../payment/constants';
|
2022-06-21 14:09:22 +00:00
|
|
|
import { removeNoticesByStatus } from '../../utils/notices';
|
|
|
|
import {
|
|
|
|
getPaymentResultFromCheckoutResponse,
|
|
|
|
runCheckoutAfterProcessingWithErrorObservers,
|
|
|
|
runCheckoutAfterProcessingWithSuccessObservers,
|
|
|
|
} from './utils';
|
|
|
|
import {
|
|
|
|
EVENTS,
|
|
|
|
emitEvent,
|
|
|
|
emitEventWithAbort,
|
|
|
|
} from '../../base/context/providers/cart-checkout/checkout-events/event-emit';
|
|
|
|
import type {
|
|
|
|
emitValidateEventType,
|
|
|
|
emitAfterProcessingEventsType,
|
|
|
|
} from './types';
|
|
|
|
import type { DispatchFromMap } from '../mapped-types';
|
|
|
|
import * as actions from './actions';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Based on the result of the payment, update the redirect url,
|
|
|
|
* set the payment processing response in the checkout data store
|
|
|
|
* and change the status to AFTER_PROCESSING
|
|
|
|
*/
|
2022-10-05 10:04:16 +00:00
|
|
|
export const __internalProcessCheckoutResponse = (
|
|
|
|
response: CheckoutResponse
|
|
|
|
) => {
|
2022-06-21 14:09:22 +00:00
|
|
|
return ( {
|
|
|
|
dispatch,
|
|
|
|
}: {
|
|
|
|
dispatch: DispatchFromMap< typeof actions >;
|
|
|
|
} ) => {
|
|
|
|
const paymentResult = getPaymentResultFromCheckoutResponse( response );
|
2022-10-05 10:04:16 +00:00
|
|
|
dispatch.__internalSetRedirectUrl( paymentResult?.redirectUrl || '' );
|
2022-11-18 12:13:00 +00:00
|
|
|
// The local `dispatch` here is bound to the actions of the data store. We need to use the global dispatch here
|
|
|
|
// to dispatch an action on a different store.
|
|
|
|
wpDispatch( PAYMENT_STORE_KEY ).__internalSetPaymentResult(
|
|
|
|
paymentResult
|
|
|
|
);
|
2022-10-05 10:04:16 +00:00
|
|
|
dispatch.__internalSetAfterProcessing();
|
2022-06-21 14:09:22 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Emit the CHECKOUT_VALIDATION_BEFORE_PROCESSING event and process all
|
|
|
|
* registered observers
|
|
|
|
*/
|
2022-10-05 10:04:16 +00:00
|
|
|
export const __internalEmitValidateEvent: emitValidateEventType = ( {
|
2022-06-21 14:09:22 +00:00
|
|
|
observers,
|
|
|
|
setValidationErrors, // TODO: Fix this type after we move to validation store
|
|
|
|
} ) => {
|
|
|
|
return ( { dispatch, registry } ) => {
|
|
|
|
const { createErrorNotice } = registry.dispatch( noticesStore );
|
|
|
|
removeNoticesByStatus( 'error' );
|
|
|
|
emitEvent(
|
|
|
|
observers,
|
|
|
|
EVENTS.CHECKOUT_VALIDATION_BEFORE_PROCESSING,
|
|
|
|
{}
|
|
|
|
).then( ( response ) => {
|
|
|
|
if ( response !== true ) {
|
|
|
|
if ( Array.isArray( response ) ) {
|
|
|
|
response.forEach(
|
|
|
|
( { errorMessage, validationErrors } ) => {
|
|
|
|
createErrorNotice( errorMessage, {
|
|
|
|
context: 'wc/checkout',
|
|
|
|
} );
|
|
|
|
setValidationErrors( validationErrors );
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2022-10-05 10:04:16 +00:00
|
|
|
dispatch.__internalSetIdle();
|
|
|
|
dispatch.__internalSetHasError();
|
2022-06-21 14:09:22 +00:00
|
|
|
} else {
|
2022-10-05 10:04:16 +00:00
|
|
|
dispatch.__internalSetProcessing();
|
2022-06-21 14:09:22 +00:00
|
|
|
}
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Emit the CHECKOUT_AFTER_PROCESSING_WITH_ERROR if the checkout contains an error,
|
|
|
|
* or the CHECKOUT_AFTER_PROCESSING_WITH_SUCCESS if not. Set checkout errors according
|
|
|
|
* to the observer responses
|
|
|
|
*/
|
2022-10-05 10:04:16 +00:00
|
|
|
export const __internalEmitAfterProcessingEvents: emitAfterProcessingEventsType =
|
|
|
|
( { observers, notices } ) => {
|
|
|
|
return ( { select, dispatch, registry } ) => {
|
|
|
|
const { createErrorNotice } = registry.dispatch( noticesStore );
|
|
|
|
const data = {
|
2022-11-24 14:19:59 +00:00
|
|
|
redirectUrl: select.getRedirectUrl(),
|
|
|
|
orderId: select.getOrderId(),
|
|
|
|
customerId: select.getCustomerId(),
|
|
|
|
orderNotes: select.getOrderNotes(),
|
2022-11-18 12:13:00 +00:00
|
|
|
processingResponse:
|
|
|
|
wpSelect( PAYMENT_STORE_KEY ).getPaymentResult(),
|
2022-10-05 10:04:16 +00:00
|
|
|
};
|
2022-11-24 14:19:59 +00:00
|
|
|
if ( select.hasError() ) {
|
2022-10-05 10:04:16 +00:00
|
|
|
// allow payment methods or other things to customize the error
|
|
|
|
// with a fallback if nothing customizes it.
|
|
|
|
emitEventWithAbort(
|
|
|
|
observers,
|
|
|
|
EVENTS.CHECKOUT_AFTER_PROCESSING_WITH_ERROR,
|
|
|
|
data
|
|
|
|
).then( ( observerResponses ) => {
|
|
|
|
runCheckoutAfterProcessingWithErrorObservers( {
|
|
|
|
observerResponses,
|
|
|
|
notices,
|
|
|
|
dispatch,
|
|
|
|
createErrorNotice,
|
|
|
|
data,
|
|
|
|
} );
|
2022-06-21 14:09:22 +00:00
|
|
|
} );
|
2022-10-05 10:04:16 +00:00
|
|
|
} else {
|
|
|
|
emitEventWithAbort(
|
|
|
|
observers,
|
|
|
|
EVENTS.CHECKOUT_AFTER_PROCESSING_WITH_SUCCESS,
|
|
|
|
data
|
|
|
|
).then( ( observerResponses: unknown[] ) => {
|
|
|
|
runCheckoutAfterProcessingWithSuccessObservers( {
|
|
|
|
observerResponses,
|
|
|
|
dispatch,
|
|
|
|
createErrorNotice,
|
|
|
|
} );
|
2022-06-21 14:09:22 +00:00
|
|
|
} );
|
2022-10-05 10:04:16 +00:00
|
|
|
}
|
|
|
|
};
|
2022-06-21 14:09:22 +00:00
|
|
|
};
|