mollie / WooCommerce

Official Mollie extension for WooCommerce
https://wordpress.org/plugins/mollie-payments-for-woocommerce/
Other
132 stars 53 forks source link

Dynamically setting the API key doesn't work #936

Closed hchauvat closed 4 hours ago

hchauvat commented 2 months ago

Hi,

Following this question and subsequent discussions with a couple people from Mollie via email and visio, I've tried to come up with a way to dynamically change the Mollie API key according to the item being sold (I voluntarily leave out any case where there are several items being ordered, because it's being handled by something else). In my case, I want to use the api key BBB for ebooks and the AAA one for any other products, hence using the new "multiple balances" Mollie just introduced.

I came up with this function, but somehow, it doesn't work:

// Use the appropriate Mollie API key based on the products in the cart
function set_mollie_api_key_by_product_category($order_id) {
    $order = wc_get_order($order_id);
    $has_ebook = false;
    $has_other_product = false;

    foreach ($order->get_items() as $item_id => $item) {
        $product_id = $item->get_product_id();
        $terms = get_the_terms($product_id, 'product_cat');

        if ($terms) {
            foreach ($terms as $term) {
                if ($term->slug === 'ebook') {
                    $has_ebook = true;
                } else {
                    $has_other_product = true;
                }
            }
        }
    }

    if ($has_ebook && !$has_other_product) {
        // Use API key BBB for ebooks
        $api_key = 'live_BBB';
    } elseif (!$has_ebook && $has_other_product) {
        // Use API key AAA for other products
        $api_key = 'live_AAA';
    }

    // Dynamically set Mollie's API key
    if (isset($api_key)) {
        add_filter('mollie_wc_gateway_initialize_api', function ($mollie) use ($api_key) {
            $mollie->setApiKey($api_key);
            return $mollie;
        });
    }
}
add_action('woocommerce_thankyou', 'set_mollie_api_key_by_product_category');

The call to ?wc-ajax=checkout does return a status 200 but in the response, I get the following error:

{
  "result": "failure", 
  "messages":"",
  "refresh": false, 
  "reload": false
}

Am I using wrong hooks or am I missing something else? Any help would be greatly appreciated!

InpsydeNiklas commented 1 month ago

Hello @hchauvat, I'm not sure if the timing is right with this and there could potentially be issues when e.g. both Mollie profiles have different payment methods enabled. Also this would only apply for new orders, but not for already existing orders, such as from the Pay for Order endpoint. However, please give it a try with this snippet:

// Function to dynamically set Mollie API key based on product category in the order
function set_mollie_api_key_by_product_category($order_id) {
    // Get the order object from the order ID
    $order = wc_get_order($order_id);

    // Ensure that a valid order object is returned
    if (!$order) {
        return; // Exit if no valid order object is retrieved
    }

    $has_ebook = false;
    $has_other_product = false;

    // Loop through the items in the order to check the product categories
    foreach ($order->get_items() as $item_id => $item) {
        $product_id = $item->get_product_id();
        $terms = get_the_terms($product_id, 'product_cat');

        if ($terms) {
            foreach ($terms as $term) {
                if ($term->slug === 'ebook') {
                    $has_ebook = true;
                } else {
                    $has_other_product = true;
                }
            }
        }
    }

    // Set the API key based on the products in the order
    if ($has_ebook && !$has_other_product) {
        // Use API key for ebooks
        $api_key = 'live_ebooks'; // Replace with the actual ebook API key
    } elseif (!$has_ebook && $has_other_product) {
        // Use API key for non-ebook products
        $api_key = 'live_noebooks'; // Replace with the actual API key for other products
    }

    // Return the determined API key
    return isset($api_key) ? $api_key : null;
}

// Hook into 'woocommerce_checkout_order_processed' to apply the filter
add_action('woocommerce_checkout_order_processed', function($order_id) {
    // Set the API key based on the product category
    add_filter('mollie_api_key_filter', function($apiKey) use ($order_id) {
        $custom_api_key = set_mollie_api_key_by_product_category($order_id);

        // If a custom API key is found, return it; otherwise, use the default API key
        return $custom_api_key ? $custom_api_key : $apiKey;
    });
});

However, the plugin would need some tweaks to accommodate this use case better, as managing two different Mollie profiles from the plugin could have deeper implications, e.g. to the payment method availability.