* Convert woo notices into exceptions when processing legacy payments

* Prevent console errors when a message is not returned in the response

* include top level message property to capture REST error messages

* include capturing rest error messages on afterProcessing action

* clear notices before exception

Co-authored-by: Darren Ethier <darren@roughsmootheng.in>
This commit is contained in:
Mike Jolley 2020-04-16 15:39:46 +01:00 committed by GitHub
parent 9260e7ad89
commit 216a7fc1bf
3 changed files with 44 additions and 5 deletions

View File

@ -141,6 +141,17 @@ export const CheckoutStateProvider = ( {
setOrderId: ( orderId ) =>
void dispatch( actions.setOrderId( orderId ) ),
setAfterProcessing: ( response ) => {
// capture general error message if this is an error response.
if (
! response.payment_result &&
response.message &&
response?.data?.status !== 200
) {
response.payment_result = {
...response.payment_result,
message: response.message,
};
}
if ( response.payment_result ) {
if (
// eslint-disable-next-line camelcase
@ -231,7 +242,7 @@ export const CheckoutStateProvider = ( {
// no error handling in place by anything so let's fall
// back to default
const message =
data.processingResponse.message ||
data.processingResponse?.message ||
__(
'Something went wrong. Please contact us to get assistance.',
'woo-gutenberg-products-block'

View File

@ -33,6 +33,8 @@ const {
*
* @param {Object} data The value of `payment_result` from the checkout
* processing endpoint response.
* @param {string} data.message If there was a general error message it will appear
* on this property.
* @param {string} data.payment_status The payment status. One of 'success', 'failure',
* 'pending', 'error'.
* @param {Array<Object>} data.payment_details An array of Objects with a 'key' property that is a
@ -44,6 +46,7 @@ const {
*/
export const prepareResponseData = ( data ) => {
const responseData = {
message: data?.message || '',
paymentStatus: data.payment_status,
paymentDetails: {},
};

View File

@ -239,9 +239,8 @@ class Library {
$payment_method_object->validate_fields();
if ( 0 !== wc_notice_count( 'error' ) ) {
return;
}
// If errors were thrown, we need to abort.
self::convert_notices_to_exceptions();
// Process Payment.
$gateway_result = $payment_method_object->process_payment( $context->order->get_id() );
@ -249,7 +248,8 @@ class Library {
// Restore $_POST data.
$_POST = $post_data;
// Clear notices so they don't show up in the block.
// If `process_payment` added notices, clear them. Notices are not displayed from the API -- payment should fail,
// and a generic notice will be shown instead if payment failed.
wc_clear_notices();
// Handle result.
@ -259,4 +259,29 @@ class Library {
$result->set_payment_details( array_merge( $result->payment_details, $gateway_result ) );
$result->set_redirect_url( $gateway_result['redirect'] );
}
/**
* Convert notices to Exceptions.
*
* Payment methods may add error notices during validate_fields call to prevent checkout. Since we're not rendering
* notices at all, we need to convert them to exceptions.
*
* This method will find the first error message and thrown an exception instead.
*
* @throws \Exception If an error notice is detected, Exception is thrown.
*/
protected static function convert_notices_to_exceptions() {
if ( 0 === wc_notice_count( 'error' ) ) {
return;
}
$error_notices = wc_get_notices( 'error' );
// Prevent notices from being output later on.
wc_clear_notices();
foreach ( $error_notices as $error_notice ) {
throw new \Exception( $error_notice['notice'] );
}
}
}