Skip to content

Adding Compatibility for a Multi‐currency Plugin and WooCommerce Amazon Pay plugin

Dimitrios Pantazis edited this page Oct 13, 2023 · 3 revisions

Filters

The plugin provides 3 filters in order to help you make the multi-currency plugin you want compatible with Amazon Pay.

1. Filter woocommerce_amazon_pa_ml_compat_plugins.

In this filter, you are provided with an argument which is an array containing the already compatible multi-currency plugins.

It's a key => value array, where the value is the compatible plugin's name which will appear under the Amazon Pay plugin's settings when detected.

While the key is used to detect whether the multi-currency plugin is active. The key can work as a hint with the following prefixes:

a. global_{GLOBAL_NAME} - The plugin would look inside the $GLOBALS to check if an offset {GLOBAL_NAME} is set.

b. class_{CLASS_NAME} - The plugin would check if the class {CLASS_NAME} exists

c. You can implement your own logic using the 2nd filter.

2. Filter woocommerce_amazon_pa_matched_compat_plugin_{DEFINITION_NAME} Where {DEFINITION_NAME} is the key you have added using the 1st filter.

This filter is only required if 1a or 1b can't work for you. The filter provides you with one argument which is bool and tells you whether or not the plugin has already determined that the compatible multi-currency plugin is already present and available. If true already, nothing more you need to do.

Otherwise, this is where you should apply your own logic to determine if the multi-currency plugin you are making compatible exists and is available to be used. If it is, you should return true.

3. Filter woocommerce_amazon_pa_compat_plugin_instance_{DEFINITION_NAME} Where {DEFINITION_NAME} is the key you have added using the 1st filter.

This filter is provided with 2 arguments:

  • $found_plugin_instance - null or string (full class name) or an instance of WC_Amazon_Payments_Advanced_Multi_Currency_Abstract
  • $init - bool, whether the plugin expects you to return an instance or the full class name as a string.

When adding a new compatibility you should always receive null as the $found_plugin_instance, since the plugin should have failed to determine it on its own.

This is where you require your compatibility class which should be extending the class WC_Amazon_Payments_Advanced_Multi_Currency_Abstract and you return either a new instance of your class or the full class name as a string based on the $init parameter. (if true instance otherwise string).

Extending the Abstract

A full example is provided below of how we would add compatibility external to the WooCommerce Amazon Pay plugin with the plugin FOX – Currency Switcher Professional for WooCommerce by extending the WC_Amazon_Payments_Advanced_Multi_Currency_Abstract class.

Methods provided by the Abstract

  • __construct() - Not required to extend, if you do please also consider the actions that are taking place in the Abstract's constructor and whether you should call parent::__construct()
  • maybe_disable_due_to_unsupported_currency() - Not required to extend. Retrieves the active currency through the compatible multi-currency instance and conditionally disables Amazon Pay if the active currency is not supported.
  • get_selected_currency() - Deprecated, please do not use. Use get_active_currency() instead.
  • get_active_currency - Required to extend, will become abstract in the near future. This is where you should return the active currency integrating with the plugin you are adding compatibility with.
  • is_front_end_compatible() - Not Required to extend, suggested though. This tells the Amazon Pay plugin whether the currency changes take place only on the front end or not. When true, you usually don't need to develop an integration at all other than helping users understand that their multi-currency plugin will be functional with Amazon Pay.
  • is_currency_compatible() - Not Required to extend. Compares the active currency (which comes as an argument) with the currencies the user has selected within Amazon Pay's options to be available.
  • capture_original_checkout_currency() - Not Required to extend. Stores the original currency during checkout init.
  • delete_currency_session() - Not required to extend. Deletes the session variable during Amazon Pay logout.
  • get_currency_switched_times() - Not required to extend. Returns the amount of times the customer has switched currencies.
  • set_presentment_currency() - Not required to extend. Adds the presentmentCurrency offset equal to the active currency in Amazon Pay's button payload.
  • bypass_currency_session() - Not required to extend. Amazon Pay Checkout version 1 relevant. Stores that the currency needs to be bypassed in pending orders.
  • get_original_checkout_currency() - Not required to extend. Amazon Pay Checkout version 1 relevant. Returns the original currency stored in session.
  • reload_wallet_widget() - Not required to extend. Amazon Pay Checkout version 1 relevant. Whether the Amazon Pay wallet needs to be reloaded on the front end.
  • ajax_get_currency() - Not required to extend. Amazon Pay Checkout version 1 relevant. Returns active currency through the multi-currency plugin instance via Ajax.
  • is_order_reference_checkout_suspended() - Not required to extend. Amazon Pay Checkout version 1 relevant. Checks if the order reference for an order awaiting payment is suspended.

Full Example

For the purposes of the example we will create a 2 files plugin. The plugin's slug would be amazon-payments-advanced-woocs-compatibility and of course we would place our plugin in the wp-content/plugins/ directory.

Contents of file amazon-payments-advanced-woocs-compatibility/amazon-payments-advanced-woocs-compatibilty.php

<?php
/*
 * Plugin Name: Amazon Pay WOOCS Compatibility
 * Description: Adds multi-currency support for Amazon Pay and WOOCS
 * Version: 1.0.0
 * Author: Sau/Cal
 * Author URI: https://saucal.com/
 * Text Domain: amazon-payments-advanced-woocs-compatibility
 * Domain Path: /languages/
 * Tested up to: 6.2
 *
 * License: GNU General Public License v3.0
 * License URI: http://www.gnu.org/licenses/gpl-3.0.html
 *
 * @package AmazonPaymentsAdvancedCompatibility
 */

namespace AmazonPaymentsAdvanced\Compatibility\WOOCS;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Declare the multi-currency plugin we are adding compatibility with.
 *
 * The WooCommerce Amazon Pay plugin expects the key to be in the format of `global_{GLOBAL_VARIABLE_NAME}` or
 * `class_{CLASS_NAME}`. It would respectively check if ( isset( $GLOBAL[ {GLOBAL_VARIABLE_NAME} ] ) ) or
 * if ( class_exists( {CLASS_NAME} ) ) to determine if the plugin is active and thats the instance that should be used
 * to achieve compatibility.
 *
 * This is not a requirement, you can implement your own logic using the filter `woocommerce_amazon_pa_matched_compat_plugin_{DEFINITION_NAME}`
 * where {DEFINITION_NAME} is the key you define here. In this case global_WOOCS.
 */
const COMPATIBILITY_TO_BE_ADDED = array(
	'global_WOOCS' => 'WOOCS – Currency Switcher for WooCommerce',
);

add_filter(
	'woocommerce_amazon_pa_ml_compat_plugins',
	function ( $already_compatible_plugins ) {
		foreach ( COMPATIBILITY_TO_BE_ADDED as $definition_name => $name ) {
			if ( isset( $already_compatible_plugins[ $definition_name ] ) ) {
				continue;
			}

			$already_compatible_plugins[ $definition_name ] = $name;
		}

		return $already_compatible_plugins;
	}
);

/**
 * This is only provided for example purposes. In this case its not needed since we are adding the compatibility
 * by already following the plugin's naming convention.
 *
 * Let's assume we weren't though. In that case we would need to implement this filter to tell the plugin that
 * the instance we are adding compatibility with is already loaded and available.
 */
add_filter(
	'woocommerce_amazon_pa_matched_compat_plugin_global_WOOCS',
	function ( $instance_exists_already ) {
		// Since the plugin has already determined the instance exists, nothing more to do.
		if ( $instance_exists_already ) {
			return $instance_exists_already;
		}

		// If the plugin hasn't already determined the instance exists, we need to check for it ourselves.
		// We would (probably) need to perform a check to determine if the multi-currency plugin we are adding compatibility with
		// is available.
		// It could be:
		// 1) A class existing check
		// 2) A global variable existing check
		// 3) A function existing check
		// 4) A constant defined check
		// 5) A file existing check
		// 6) A plugin active check
		// 7) A plugin version check
		// 8) Combinations of the above.
		// 9) More options as well.

		// Here for the purposes of the example we check if the EXAMPLE_MULTICURRENCY_PLUGIN_VERSION constant is defined and is greater or equal than 1.0.0.
		if ( ! defined( 'EXAMPLE_MULTICURRENCY_PLUGIN_VERSION' ) || version_compare( \EXAMPLE_MULTICURRENCY_PLUGIN_VERSION, '1.0.0', '<' ) ) {
			return false;
		}

		// If the conditions are met, then we return true to tell the plugin that the instance is available.
		return true;
	}
);

/**
 * 'woocommerce_amazon_pa_compat_plugin_instance_' . $compatible_plugin
 */
add_filter(
	'woocommerce_amazon_pa_compat_plugin_instance_global_WOOCS',
	function ( $found_plugin_instance, $init ) {
		if ( null !== $found_plugin_instance ) {
			return $found_plugin_instance;
		}

		// We make sure that the WooCommerce Amazon Pay plugin has already loaded the abstract class we will be extending in our own implementation.
		if ( ! class_exists( 'WC_Amazon_Payments_Advanced_Multi_Currency_Abstract' ) ) {
			return $found_plugin_instance;
		}

		require_once __DIR__ . '/includes/class-wc-amazon-payments-advanced-multi-currency-woocs.php';

		return $init ? new WC_Amazon_Payments_Advanced_Multi_Currency_Woocs() : WC_Amazon_Payments_Advanced_Multi_Currency_Woocs::class;
	},
	10,
	2
);

Contents of file amazon-payments-advanced-woocs-compatibility/includes/class-wc-amazon-payments-advanced-multi-currency-woocs.php

<?php
/**
 * Handle WOOCS – Currency Switcher for WooCommerce compatibility.
 * https://wordpress.org/plugins/woocommerce-currency-switcher/
 *
 * @package AmazonPaymentsAdvancedCompatibility
 */

namespace AmazonPaymentsAdvanced\Compatibility\WOOCS;

use WC_Amazon_Payments_Advanced_Multi_Currency_Abstract;

/**
 * WooCommerce WOOCS – Currency Switcher for WooCommerce Multi-currency compatibility.
 */
class WC_Amazon_Payments_Advanced_Multi_Currency_Woocs extends WC_Amazon_Payments_Advanced_Multi_Currency_Abstract {


	/**
	 * Specify hooks where compatibility action takes place.
	 */
	public function __construct() {
		$version = is_a( wc_apa()->get_gateway(), 'WC_Gateway_Amazon_Payments_Advanced_Legacy' ) ? 'v1' : 'v2';
		if ( 'v1' === $version ) {
			// Option woocs_restrike_on_checkout_page === 1 will hide switcher on checkout.
			add_filter( 'option_woocs_restrike_on_checkout_page', array( $this, 'remove_currency_switcher_on_order_reference_suspended' ) );
			add_action( 'init', array( $this, 'remove_shortcode_currency_switcher_on_order_reference_suspended' ) );
		}

		parent::__construct();
	}


	/**
	 * Get Woocs selected currency.
	 *
	 * @return string
	 */
	public static function get_active_currency() {
		global $WOOCS; // phpcs:ignore WordPress.NamingConventions
		return is_object( $WOOCS ) && ! empty( $WOOCS->current_currency ) ? $WOOCS->current_currency : get_woocommerce_currency(); // phpcs:ignore WordPress.NamingConventions
	}

	/**
	 * Woocs has 2 ways of work:
	 * Settings > Advanced > Is multiple allowed
	 * If it is set, users will pay on selected currency (where we hook)
	 * otherwise it will just change currency on frontend, but order will be taken on original shop currency.
	 *
	 * @return bool
	 */
	public function is_front_end_compatible() {
		return get_option( 'woocs_is_multiple_allowed' ) ? false : true;
	}

	/**
	 * LEGACY v1 METHODS AND HOOKS
	 */

	/**
	 * On OrderReferenceStatus === Suspended, hide currency switcher.
	 *
	 * @param  bool $value Wether to remove or not the switcher.
	 * @return bool
	 */
	public function remove_currency_switcher_on_order_reference_suspended( $value ) {
		if ( $this->is_order_reference_checkout_suspended() ) {
			// By Pass Multi-currency, so we don't trigger a new set_order_reference_details on process_payment.
			$this->bypass_currency_session();
			return 1;
		}
		return $value;
	}

	/**
	 * On OrderReferenceStatus === Suspended, hide currency switcher.
	 */
	public function remove_shortcode_currency_switcher_on_order_reference_suspended() {
		if ( $this->is_order_reference_checkout_suspended() ) {
			// By Pass Multi-currency, so we don't trigger a new set_order_reference_details on process_payment.
			$this->bypass_currency_session();
			remove_shortcode( 'woocs' );
		}
	}

}