Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Make 'retry' property on errors from checkoutAfterProcessingWithSuccess/Error observers default to true if it's undefined #3261

Merged
merged 2 commits into from Oct 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 3 additions & 5 deletions assets/js/base/context/cart-checkout/checkout-state/index.js
Expand Up @@ -101,6 +101,7 @@ export const CheckoutStateProvider = ( {
isSuccessResponse,
isErrorResponse,
isFailResponse,
shouldRetry,
} = useEmitResponse();

// set observers on ref so it's always current.
Expand Down Expand Up @@ -237,10 +238,7 @@ export const CheckoutStateProvider = ( {
addErrorNotice( response.message, errorOptions );
}
// irrecoverable error so set complete
if (
typeof response.retry !== 'undefined' &&
response.retry !== true
) {
if ( ! shouldRetry( response ) ) {
dispatch( actions.setComplete( response ) );
} else {
dispatch( actions.setIdle() );
Expand Down Expand Up @@ -278,7 +276,7 @@ export const CheckoutStateProvider = ( {
: undefined;
addErrorNotice( response.message, errorOptions );
}
if ( ! response.retry ) {
if ( ! shouldRetry( response ) ) {
dispatch( actions.setComplete( response ) );
} else {
// this will set an error which will end up
Expand Down
5 changes: 5 additions & 0 deletions assets/js/base/hooks/checkout/use-emit-response.js
Expand Up @@ -37,6 +37,10 @@ const isFailResponse = ( response ) => {
return isResponseOf( response, responseTypes.FAIL );
};

const shouldRetry = ( response ) => {
return typeof response.retry === 'undefined' || response.retry === true;
};

/**
* A custom hook exposing response utilities for emitters.
*
Expand All @@ -47,6 +51,7 @@ export const useEmitResponse = () => {
return {
responseTypes,
noticeContexts,
shouldRetry,
isSuccessResponse,
isErrorResponse,
isFailResponse,
Expand Down
2 changes: 2 additions & 0 deletions assets/js/type-defs/hooks.js
Expand Up @@ -148,6 +148,8 @@
* be used in returned response objects.
* @property {NoticeContexts} noticeContexts An object of various notice contexts that can
* be used for targeting where a notice appears.
* @property {function(Object):boolean} shouldRetry Returns whether the user is allowed to retry
* the payment after a failed one.
* @property {function(Object):boolean} isSuccessResponse Returns whether the given response is of a
* success response type.
* @property {function(Object):boolean} isErrorResponse Returns whether the given response is of an
Expand Down
4 changes: 3 additions & 1 deletion docs/extensibility/checkout-flow-and-events.md
Expand Up @@ -174,6 +174,7 @@ const Component = () => {
isFailResponse,
noticeContexts,
responseTypes,
shouldRetry,
} = useEmitResponse;
return null;
};
Expand All @@ -186,6 +187,7 @@ The properties of the object returned by this hook are:
- `PAYMENTS`: This is a reference to the notice area in the payment methods step.
- `EXPRESS_PAYMENTS`: This is a reference to the notice area in the express payment methods step.
- `responseTypes`: This is an object containing properties referencing the various response types that can be returned by observers for some event emitters. It makes it easier for autocompleting the types and avoiding typos due to human error. The types are `SUCCESS`, `FAIL`, `ERROR`. The values for these types also correspond to the [payment status types](https://github.com/woocommerce/woocommerce-gutenberg-products-block/blob/34e17c3622637dbe8b02fac47b5c9b9ebf9e3596/src/Payments/PaymentResult.php#L21) from the [checkout endpoint response from the server](https://github.com/woocommerce/woocommerce-gutenberg-products-block/blob/34e17c3622637dbe8b02fac47b5c9b9ebf9e3596/src/RestApi/StoreApi/Schemas/CheckoutSchema.php#L103-L113).
- `shouldRetry`: This is a function containing the logic whether the checkout flow should allow the user to retry the payment after a previous payment failed. It receives the `response` object and by default checks whether the `retry` property is true/undefined or false. Refer to the [`onCheckoutAfterProcessingWithSuccess`](#oncheckoutafterprocessingwithsuccess) documentation for more details.

Note: `noticeContexts` and `responseTypes` are exposed to payment methods via the `emitResponse` prop given to their component:

Expand Down Expand Up @@ -368,7 +370,7 @@ In all cases, if there are the following properties in the response, additional

- `message`: This string will be added as an error notice.
- `messageContext`: If present, the notice will be configured to show in the designated notice area (otherwise it will just be a general notice for the checkout block).
- `retry`: If this is `true`, then the checkout status will be set to `IDLE`. This basically means that the error is recoverable (for example try a different payment method) and so checkout will be reset to `IDLE` for another attempt by the shopper. If this is `false`, then the checkout status is set to `COMPLETE` and the checkout will redirect to whatever is currently set as the `redirectUrl`.
- `retry`: If this is `true` or not defined, then the checkout status will be set to `IDLE`. This basically means that the error is recoverable (for example try a different payment method) and so checkout will be reset to `IDLE` for another attempt by the shopper. If this is `false`, then the checkout status is set to `COMPLETE` and the checkout will redirect to whatever is currently set as the `redirectUrl`.
- `redirectUrl`: If this is present, then the checkout will redirect to this url when the status is `COMPLETE`.

If all observers return `true`, then the checkout status will just be set to `COMPLETE`.
Expand Down