Skip to content

Actions and Filters

Niklas Gutberlet edited this page Apr 10, 2024 · 46 revisions

Plugin Architecture

Adding Modules and Accessing the Plugin Container

PayPal Payments implements a modular plugin architecture. Every "piece of logic" of a complex plugin is considered a "module" and the actual plugin is essentially a collection of multiple smaller plugins. To interact with the plugin container from an external source, you can add your custom module by utilizing the filter provided below.

By doing so, you will be able to access the container and extend or modify its services from within your module.

Here is a simplified example demonstrating this process:

Step 1: Configure your composer.json file:

{
  "name": "vendor_name/test-plugin",
  "description": "description",
  "minimum-stability": "stable",
  "require": {
    "dhii/module-interface": "0.3.x-dev"
  }
}

Step 2: Create your custom module in the your-plugin.php file:

$module = new class implements Dhii\Modular\Module\ModuleInterface{
	public function setup(): ServiceProviderInterface
	{
		return new ServiceProvider(
			[], //place here your services you want to add to container,
                        [] // place here your extensions to replace existing container services (see links below for more details).
		);
	}
	
	public function run(ContainerInterface $c): void
	{
                //here you can get the container instance and do something with it.
		add_action('admin_notices', function() use ($c){
			$c->get('admin-notices.renderer')->render();
		});
	}
};

add_filter('woocommerce_paypal_payments_modules', function($modules) use ($module) {
	array_push($modules, $module);
	
	return $modules;
});

For more information on how to work with service providers and modules, refer to the following resources:


Extend feature availability

Add advanced credit and debit card (ACDC) countries

PayPal Payments enables the Advanced Card Processing for the officially supported countries/currencies as listed here: https://developer.paypal.com/docs/checkout/advanced/#link-eligibility

The filters below extend the supported country and currency list from within the plugin. Whether or not the PayPal account is operating from an supported or unsupported region, PayPal must first approve the application for advanced card payments.

woocommerce_paypal_payments_supported_country_currency_matrix - To filter supported countries and their currencies.

woocommerce_paypal_payments_supported_country_card_matrix - To filter supported countries and their cards.

Here is the example of how the filters can be used to allow ACDC for Singapore.

add_filter('woocommerce_paypal_payments_supported_country_currency_matrix', static function(array $countries): array {

    $countries['SG'] = [
        'AUD',
        'CAD',
        'CHF',
        'CZK',
        'DKK',
        'EUR',
        'GBP',
        'HKD',
        'HUF',
        'JPY',
        'NOK',
        'NZD',
        'PLN',
        'SEK',
        'SGD',
        'USD',
    ];

    return $countries;
});

add_filter('woocommerce_paypal_payments_supported_country_card_matrix', static function(array $countries): array {

    $countries['SG'] = [
        'mastercard' => [],
        'visa'       => [],
        'amex'       => array( 'AUD' ),
    ];

    return $countries;
});

Checkout gateway

Checkout form field validation before creating the PayPal order

PayPal Payments version 2.0 introduced an early server-side checkout validation when clicking a smart button on the Checkout page. This validation is triggered in a non-standard way and might cause issues on some sites. When implementing your own validation mechanism, consider using the woocommerce_after_checkout_validation hook because validate_checkout is called before opening the popup window when using the early WC validation. To disable early WC validation, use this filter:

add_filter( 'woocommerce_paypal_payments_early_wc_checkout_validation_enabled', '__return_false' );

If you are encountering potential compatibility problems with the early WC validation, you may want to try the basic validation instead:

add_filter( 'woocommerce_paypal_payments_basic_checkout_validation_enabled', '__return_true' );

This basic validation prevents users from attempting the payment by displaying an error when not all fields are filled (e.g., terms checkbox). This check happens in the user's browser and does not validate the data on the server. In any case, after the buyer confirms the payment in the PayPal popup window, it is only captured after WooCommerce successfully completes its own validation after the popup window closes.

Adding a gateway icon

While PayPal Payments does not provide a default payment gateway icon, you can add one with a filter like the one below. Exchange the img src for any icon URL you prefer.

function woocommerce_paypal_payments_gateway_icon( $icon, $id ) {
    if ( $id === 'ppcp-gateway' ) {
        return '<img src="' . esc_url( plugins_url( 'woocommerce-paypal-payments/modules/ppcp-wc-gateway/assets/images/paypal.png', ) ) . '" > ';
	}
		if ( $id === 'ppcp-pay-upon-invoice-gateway' ) {
       return '<img src="' . esc_url( plugins_url( 'woocommerce-paypal-payments/modules/ppcp-wc-gateway/assets/images/paypal.png', ) ) . '" > ';
    } else {
        return $icon;
    }
}
add_filter( 'woocommerce_gateway_icon', 'woocommerce_paypal_payments_gateway_icon', 10, 2 );

The ppcp-pay-upon-invoice-gateway is only relevant for merchants from Germany.

The Advanced Card Processing feature already provides a selection of default credit card icons depending on the eligibility.


PayPal Order creation

Disable item breakdown being sent to PayPal

By default, PayPal Payments sends the items breakdown to PayPal so the purchased items can be seen in the PayPal order. Enbabling this filter will turn off the functionality and leave the PayPal order with no items.

add_filter( 'ppcp_ditch_items_breakdown', '__return_true' );

Modify the order creation request body data

apply_filters( 'ppcp_create_order_request_body_data', array $data ) Filters the order creation request body data.

Parameters

$data (array) The order creation request body data.

More Information

The filter will allow to modify the request body data before it is sent to PayPal. The structured data is created in regards of how PayPal API expects it so if after modification it contains the incorrect parts then the error message will be shown.

Example

Filter is used to modify the Brand Name to be New Brand Name

add_filter('ppcp_create_order_request_body_data', static function (array $data): array {
    $data['application_context']['brand_name'] = 'New Brand Name';
    return $data;
});

Result:

Screen Shot 2022-03-16 at 15 58 19

Modify the order patching request body data

Keep in mind that after the order is created, it may later be patched with new details, and the patch process may override the changes made during the order creation.

To modify the patch data as well, use the ppcp_patch_order_request_body_data filter described below.

apply_filters( 'ppcp_patch_order_request_body_data', array $patches_array )

Filters the order patching request body data (the final prices, items).

Parameters

$patches_array (array) The order patching request body data.

More Information

The filter can be used to modify the order patching request body data, ensuring that e.g. any changes made during the order creation process remain intact.

Example

The filter is used to add a "Lifetime Access" line item with no price and add "Lifetime VIP - " before the buyer's (shipping) name.

function customize_paypal_order( $patches_array ) {
    // Add "Lifetime VIP -" before the buyer shipping address name 
    if ( isset( $patches_array[0]['value']['shipping'] ) ) {
        $original_full_name = $patches_array[0]['value']['shipping']['name']['full_name'];
        $patches_array[0]['value']['shipping']['name']['full_name'] = "Lifetime VIP - " . $original_full_name;
    }

    // Add a new line item "Lifetime Access" with no price
    $lifetime_access_item = array(
        'name'        => 'Lifetime Access',
        'quantity'    => '1',
        'unit_amount' => array(
            'currency_code' => 'USD',
            'value'         => '0.00',
        ),
    );

    // Add the new line item to the items array
    if ( isset( $patches_array[0]['value']['items'] ) ) {
        $patches_array[0]['value']['items'][] = $lifetime_access_item;
    } else {
        $patches_array[0]['value']['items'] = array( $lifetime_access_item );
    }

    return $patches_array;
}
add_filter( 'ppcp_patch_order_request_body_data', 'customize_paypal_order', 10 );

Order management

Disable PayPal Checkout Gateway migration layer (PPEC Helper)

PayPal Payments automatically takes over subscriptions from the PayPal Checkout plugin.

Add this filter to disable the subscription migration functionality:

add_filter('woocommerce_paypal_payments_process_legacy_subscriptions', static function(){
return false;
});

Disable PayPal Package Tracking in 2.3.0+

Package Tracking functionality has been enabled by default since version 2.3.0. Return false to disable the module and remove all package tracking features from the integration.

add_filter('woocommerce_paypal_payments_shipment_tracking_enabled', '__return_false');

The PayPal Package Tracking metabox can be hidden via Screen Options:

image Hiding the metabox this way does not impact the automatic shipment tracking background sync.

Add custom Tracking Carrier/Status

PayPal Payments offers a Tracking integration to send shipment data to PayPal. These filters can add a new carrier and a new shipping status:

add_filter('woocommerce_paypal_payments_tracking_carriers', static function(array $carriers): array {
    $carriers['DE']['items']['custom'] = 'Custom';
    return $carriers;
});

add_filter('woocommerce_paypal_payments_tracking_statuses', static function(array $statuses): array {
    $statuses['custom'] = 'Custom';
    return $statuses;
});

Modify tracking data before creating/updating in PayPal

Parameters

$data. (array) The tracking data. (transaction_id, status, tracking_number, carrier)

Please note: Status can only be changed to the values PayPal allows

Please note: Carrier can only be changed to the values PayPal allows

$order_id. (int) The WooCommerce Order ID.

More Information

The filter will allow to modify the tracking data before it is sent to PayPal. The structured data is created in regards of how PayPal API expects it so if after modification it contains the incorrect parts then the error message will be shown.

Example

Filter is used to modify the Status to be DELIVERED when adding for first time.

add_filter('woocommerce_paypal_payments_tracking_data_before_sending', static function(array $data, int $order_id){
    $data['status'] = "DELIVERED";
    return $data;
}, 10, 2);

Filter is used to modify the Status to be DELIVERED when updating the existing tracking.

add_filter('woocommerce_paypal_payments_tracking_data_before_update', static function(array $data, int $order_id){
    $data['status'] = "DELIVERED";
    return $data;
}, 10, 2);

Action: before/after tracking is added/updated

Parameters

$order_id. (int) The WooCommerce Order ID.

$data. (array) The tracking data. (transaction_id, status, tracking_number, carrier)

More Information

The action will allow to hook when tracking information is about to be added/updated or after it is added/updated.

Example

Before:

add_action('woocommerce_paypal_payments_before_tracking_is_added', static function(int $order_id, array $data){
    ///do whatever is needed
}, 10, 2);
add_action('woocommerce_paypal_payments_before_tracking_is_updated', static function(int $order_id, array $data){
    ///do whatever is needed
}, 10, 2);

After:

add_action('woocommerce_paypal_payments_after_tracking_is_added', static function(int $order_id, array $data){
    ///do whatever is needed
}, 10, 2);
add_action('woocommerce_paypal_payments_after_tracking_is_updated', static function(int $order_id, array $data){
    ///do whatever is needed
}, 10, 2);

Disable PayPal fee & payout display in WooCommerce order

By default, PayPal Payments displays the PayPal fees and PayPal payout amounts in the WooCommerce order:

image

Use this filter to turn off the fee & payout display:

add_filter( 'woocommerce_paypal_payments_show_fees_on_order_admin_page', '__return_false' );

image

Webhook order creation

Enable this to allow PayPal order approved webooks to create WooCommerce orders. This can be useful especially for APM payments when the buyer did not return the Checkout page, resulting in no WooCommerce order being created.

add_filter('woocommerce_paypal_payments_order_approved_webhook_can_create_wc_order', '__return_true');

Programmatically capture, reauthorize, void, or refund a PayPal order

Using the provided functions, you can programmatically perform capture, reauthorize, void, or refund actions on PayPal orders. Please note that performing these actions will not immediately change the state of the WooCommerce order. However, the respective order may be updated by a webhook after a short time.

Here are examples of how to use these API functions:

Capture authorized payments

use function WooCommerce\PayPalCommerce\Api\ppcp_capture_order;

add_action('init', function () {

	// Get the order with the specified number.
    $capture_order_number = 123;
    $capture_order = wc_get_order($capture_order_number);

	try {
		// Capture the order.
		ppcp_capture_order($capture_order);
	} catch (\Exception $exception) {
		echo($exception->getMessage());
	}
});

Reauthorize authorized payments

use function WooCommerce\PayPalCommerce\Api\ppcp_reauthorize_order;

add_action('init', function () {

	// Get the order with the specified number.
	$reauthorize_order_number = 123;
	$reauthorize_order = wc_get_order($reauthorize_order_number);

	try {
		// Reauthorize the order.
		ppcp_reauthorize_order($reauthorize_order);
	} catch (\Exception $exception) {
		echo($exception->getMessage());
	}
});

Void authorized payments

use function WooCommerce\PayPalCommerce\Api\ppcp_void_order;

add_action('init', function () {

	// Get the order with the specified number.
    $void_order_number = 123;
    $void_order = wc_get_order($void_order_number);

	try {
		// Void the order.
		ppcp_void_order($void_order);
	} catch (\Exception $exception) {
		echo($exception->getMessage());
	}
});

Refund captured payments

use function WooCommerce\PayPalCommerce\Api\ppcp_refund_order;

add_action('init', function () {

	// Get the order with the specified number.
    $refund_order_number = 123;
    $refund_order = wc_get_order($refund_order_number);
	// In this case, get the total amount for the refund order.
    $total_amount = $refund_order->get_total(); 
    $refund_amount = $total_amount;
    
	try {
		// Refund the order.
		ppcp_refund_order($refund_order, $refund_amount);
	} catch (\Exception $exception) {
		echo($exception->getMessage());
	}
});

Smart button customizations

Change button placement via render hooks

The placement of the PayPal smart buttons, Pay Later messaging, Apple Pay & Google Pay buttons can be adjusted programmatically. See the filter examples below. This page has a comprehensive list of available WooCommerce hooks. Some themes or page builders may not provide all default hooks, which can result in the buttons not rendering.

PayPal smart button render hooks:

  • woocommerce_paypal_payments_single_product_renderer_hook
  • woocommerce_paypal_payments_proceed_to_checkout_button_renderer_hook
  • woocommerce_paypal_payments_checkout_button_renderer_hook
  • woocommerce_paypal_payments_mini_cart_button_renderer_hook

Advanced Card Processing "Place order" button render hooks:

  • woocommerce_paypal_payments_checkout_dcc_renderer_hook
  • woocommerce_paypal_payments_pay_order_dcc_renderer_hook

Google Pay button render hooks:

  • woocommerce_paypal_payments_googlepay_single_product_button_render_hook
  • woocommerce_paypal_payments_googlepay_cart_button_render_hook
  • woocommerce_paypal_payments_googlepay_checkout_button_render_hook
  • woocommerce_paypal_payments_googlepay_payorder_button_render_hook
  • woocommerce_paypal_payments_googlepay_minicart_button_render_hook

Apple Pay button render hooks:

  • woocommerce_paypal_payments_applepay_single_product_button_render_hook
  • woocommerce_paypal_payments_applepay_cart_button_render_hook
  • woocommerce_paypal_payments_applepay_checkout_button_render_hook
  • woocommerce_paypal_payments_applepay_payorder_button_render_hook
  • woocommerce_paypal_payments_applepay_minicart_button_render_hook

Pay Later messaging:

Pay Later messaging render hooks:

  • woocommerce_paypal_payments_home_messages_renderer_hook
  • woocommerce_paypal_payments_shop_messages_renderer_hook
  • woocommerce_paypal_payments_product_messages_renderer_hook
  • woocommerce_paypal_payments_cart_messages_renderer_hook
  • woocommerce_paypal_payments_checkout_messages_renderer_hook
  • woocommerce_paypal_payments_pay-now_messages_renderer_hook

Pay Later messaging render priority:

  • woocommerce_paypal_payments_home_messages_renderer_priority
  • woocommerce_paypal_payments_shop_messages_renderer_priority
  • woocommerce_paypal_payments_product_messages_renderer_priority
  • woocommerce_paypal_payments_cart_messages_renderer_priority
  • woocommerce_paypal_payments_checkout_messages_renderer_priority
  • woocommerce_paypal_payments_pay-now_messages_renderer_priority

Filter Examples:

Example filter to display the PayPal smart buttons on the single product page below the add to cart button: (Depending on the theme, this may need custom CSS to add a margin to the #ppc-button-ppcp-gateway div.)

add_filter('woocommerce_paypal_payments_single_product_renderer_hook', function() {
    return 'woocommerce_after_add_to_cart_button';
});

Restore <2.4.0 Pay Later messaging Checkout location (within PayPal gateway area instead of above gateway selection)

add_filter('woocommerce_paypal_payments_checkout_messages_renderer_hook', function () {
	return 'ppcp_start_button_wrapper_ppcp_gateway';
});

Change the priority for rendering Pay Later messages on checkout to 20 (can impact ordering when the hook is also used by other elements)

add_filter( 'woocommerce_paypal_payments_checkout_messages_renderer_priority', function( $default_priority ) {
    return 20;
} );

Disable smart buttons on the single product page for specific products

The woocommerce_paypal_payments_product_supports_payment_request_button hook can be used to hide the smart buttons on specific product pages. In the example below, the buttons are hidden for subscription-type products:

function ppcp_remove_single_product_buttons( $enable_button, $product ){
    if ( $product->is_type( 'subscription' ) ) {
       $enable_button = false;
    }
    return $enable_button;
}
add_action( 'woocommerce_paypal_payments_product_supports_payment_request_button', 'ppcp_remove_single_product_buttons', 10, 2 );

The Cart, Mini Cart, and Checkout buttons are not affected by this filter.

Programmatically disable the PayPal smart buttons (grey out/visible but unclickable)

Using the provided filters, you can set the conditions under which you want the PayPal smart buttons to be disabled on the single product page or all other pages.

//Disable buttons on Cart, Mini Cart & Checkout
add_filter('woocommerce_paypal_payments_buttons_disabled', function (?bool $is_disabled, string $context): bool {
	return true;
}, 10, 2);

//Disable buttons on single product
add_filter('woocommerce_paypal_payments_product_buttons_disabled', function (?bool $is_disabled, $product): bool {
	return true;
}, 10, 2);

Modify cart simulation behavior

The cart simulation triggers when product attributes change on the single product page. This allows PayPal Payments to bypass the regular WooCommerce cart and instead simulate a separate cart for operations such as calculating the Pay Later messaging installment amounts on variable or composite products. On high-traffic websites or to avoid potential plugin compatibility issues, you may want to modify the cart simulation behavior. Without the cart simulation, the plugin will continue to operate but the Pay Later messaging may not display accurate installment amounts at all times on the single product page.

Apply this filter to disable the cart simulation:

add_filter( 'woocommerce_paypal_payments_simulate_cart_enabled', '__return_false' );

Apply this filter to reduce simulate cart frequency instead of disabling it:

function my_custom_simulate_cart_throttling( $throttling ) {
    return 10000;  // Returning 10000 will trigger the cart simulation no more than once every 10 seconds
}
add_filter( 'woocommerce_paypal_payments_simulate_cart_throttling', 'my_custom_simulate_cart_throttling' );

Apply this filter to prevent shutdown suppression. This can help when the cart simulation should remain active, but is potentially causing race conditions resulting in empty carts after adding a product:

add_filter( 'woocommerce_paypal_payments_simulate_cart_prevent_updates', '__return_false' );

Programmatically disable Pay Later

Apply these filters to disable the Pay Later button & messaging on the single product pages and the rest of the site:

add_filter('woocommerce_paypal_payments_product_buttons_paylater_disabled', '__return_true');
add_filter('woocommerce_paypal_payments_buttons_paylater_disabled', '__return_true');

Disable Checkout smart buttons

The PayPal smart buttons can be disabled to fall back to the default "Place order" button, redirecting the buyer to the PayPal website.

//Enable "Place order" button for PayPal gateway
add_filter('woocommerce_paypal_payments_use_place_order_button', '__return_true');


//Change the button label - defaults to "Proceed to PayPal"
add_filter('woocommerce_paypal_payments_place_order_button_text', function() {
    return __( 'Place order', 'woocommerce' );
});

In PayPal Payments 2.4.2 and newer, the Block Checkout automatically presents a PayPal gateway while the Express Block Checkout smart button location is enabled. This gateway can be disabled if you prefer to only present the PayPal express buttons.

//Disable the "Proceed to PayPal" PayPal gateway on the Block Checkout page
add_filter('woocommerce_paypal_payments_blocks_add_place_order_method', '__return_false');

Translate smart button labels

By default, PayPal automatically translates the button labels based on the browser/device preferences of the website visitor. So every user may see personalized button languages. PayPal supports the following locale codes: https://developer.paypal.com/reference/locale-codes/

To set a fixed button loale for all users, you can either add a new language to the Smart Button Language selector to choose from the Standard Payments tab with this code snippet:

add_filter( 'woocommerce_paypal_payments_button_locales', function( $locales ) {
    // Add your custom locale to the existing array.
    $locales['es_MX'] = __( 'Custom Spanish (Mexico)', 'woocommerce-paypal-payments' );

    return $locales;
});

Or you can directly override the language to the buttons without creating a new language selection in the plugin settings with this snippet:

add_filter('woocommerce_paypal_payments_smart_buttons_locale', static function(string $locale): string {
	return 'es_MX';
});

Disable Pay Later messaging Configurator in 2.6.0+

Update 2.6.0 introduced the Pay Later messaging configurator, which replaces the legacy Pay Later configuration.

The legacy Pay Later configuration can be restored with this code snippet:

add_filter( 'woocommerce.feature-flags.woocommerce_paypal_payments.paylater_configurator_enabled', '__return_false' );

Tweak fraud-prevention behavior

Update 2.6.1 introduced new filters to modify the behavior for fraud-prevention-related behavior.

By default the buyers PayPal account email address is displayed in the order details. Use this filter to hide this data.

/**
 * Disables the display of the PayPal email address in the order details.
 *
 * @param $show
 * @return bool
 */
 add_filter( 'woocommerce_paypal_payments_order_details_show_paypal_email', function ( bool $show ) {
    return false;
} );

Configure the 3D Secure Contingency for Advanced Card Processing. This filter will override the configuration from the Advanced Card Processing settings.

/**
 * Configures the 3D Secure Contingency behavior for PayPal payments.
 *
 * @param $contingency [ NO_3D_SECURE | SCA_WHEN_REQUIRED | SCA_ALWAYS ]
 * @return string
 */
add_filter( 'woocommerce_paypal_payments_three_d_secure_contingency', function ( string $contingency ) {
    return 'SCA_ALWAYS';
} );

Execute custom logic before 3D Secure.

/**
 * Executes custom logic right before the 3D Secure check is performed.
 *
 * @param $order
 */
add_action( 'woocommerce_paypal_payments_three_d_secure_before_check', function ( \WooCommerce\PayPalCommerce\ApiClient\Entity\Order $order ) {
    // your code here ...
} );

Execute custom logic after 3D Secure.

/**
 * Executes custom logic immediately after the 3D Secure check has been performed.
 *
 * @param $order
 * @param $decision [ NO_DECISION = 0 | PROCCEED = 1 | REJECT = 2 | RETRY = 3 ]
 */
add_action( 'woocommerce_paypal_payments_three_d_secure_after_check', function ( \WooCommerce\PayPalCommerce\ApiClient\Entity\Order $order, int $decision ) {
    // your code here ...
}, 10, 2 );

Alters the decision made after 3D Secure.

/**
 * Filters and possibly alters the decision made after a 3D Secure check.
 *
 * @param $decision [ NO_DECISION = 0 | PROCCEED = 1 | REJECT = 2 | RETRY = 3 ]
 * @param $order
 * @return int
 */
add_filter( 'woocommerce_paypal_payments_three_d_secure_decision', function ( int $decision, \WooCommerce\PayPalCommerce\ApiClient\Entity\Order $order ) {
    return 1;
}, 10, 2 );

Example: Customizing 3D Secure Behavior Based on Order Total and Buyer Location

This example demonstrates how to customize the 3D Secure process for PayPal payments in WooCommerce, based on the order total and the buyer's location. It includes three customizations:

  • 3D Secure Contingency Configuration: Adjusts the need for 3D Secure authentication depending on the order's total price.
  • Post-3D Secure Logic: Implements custom logic immediately after the 3D Secure check, for additional order processing steps or logging.
  • 3D Secure Decision Alteration: Overrides the decision from the 3D Secure check under specific conditions, such as high-value orders from certain locations.
/**
 * Adjusts the 3D Secure contingency based on the order total.
 * Orders below €50 will bypass 3D Secure, while orders of €50 and above will always require 3D Secure authentication.
 */
add_filter( 'woocommerce_paypal_payments_three_d_secure_contingency', function ( $contingency ) {
    global $woocommerce;
    $cart_total = $woocommerce->cart->total;

    if ($cart_total < 50) {
        return 'NO_3D_SECURE';
    }

    return 'SCA_ALWAYS';
} );
/**
 * Adds an order note with the 3D Secure decision after the 3D Secure check.
 * This is useful for record-keeping and provides clear communication to the site administrators
 * regarding the 3D Secure verification status of each order.
 */
add_action( 'woocommerce_paypal_payments_three_d_secure_after_check', function ( $order, $decision ) {
    // Mapping decision codes to readable outcomes
    $decision_map = [
        0 => 'NO_DECISION',
        1 => 'PROCEED',
        2 => 'REJECT',
        3 => 'RETRY',
    ];

    $decision_text = isset($decision_map[$decision]) ? $decision_map[$decision] : 'UNKNOWN';

    // Adding an order note with the 3D Secure decision
    $order->add_order_note(sprintf(
        '3D Secure decision: %s. Order ID: %s',
        $decision_text,
        $order->get_id()
    ));
}, 10, 2 );
/**
 * Alters the 3D Secure decision for orders above €500 and buyers from Germany.
 * In such cases, the order is always allowed to proceed.
 */
add_filter( 'woocommerce_paypal_payments_three_d_secure_decision', function ( $decision, $order ) {
    $order_total = $order->get_total();
    $shipping_country = $order->get_shipping_country();

    if ($order_total > 500 && $shipping_country == 'DE') {
        return 1; // PROCCEED
    }

    return $decision;
}, 10, 2 );
Clone this wiki locally