Different shipping prices based on vendor country – WooCommerce + WCFM Marketplace + Packeta
The support doesn work on Saturdays and Sundays, so some Friday requests can be answered on Monday. If you have problems with registration ask help on contact us page pleaseIf you not got email within 24~36 business hours, firstly check your spam box, and if no any email from the support there - back to the forum and read answer here. DO NOT ANSWER ON EMAILS [noreply@pluginus.net] FROM THE FORUM!! Emails are just for your info, all answers should be published only here.
The support doesn work on Saturdays and Sundays, so some Friday requests can be answered on Monday.
Quote from Pavlina on September 3, 2026, 17:18Hello,
we are currently testing the FOX Currency Switcher plugin on our WooCommerce marketplace and would like to know whether the following setup is possible.
Our website is a multi-vendor marketplace using WooCommerce + WCFM Marketplace + Packeta shipping plugin.
We have sellers from both Slovakia and the Czech Republic, and Packeta has different shipping price lists depending on the country from which the seller ships the parcel.
For example:
- a Slovak seller ships from Slovakia → Slovak Packeta shipping prices should be used,
- a Czech seller ships from the Czech Republic → Czech Packeta shipping prices should be used.
This must depend on the seller/vendor's country, not on the customer's country.
We contacted Packeta directly and they recommended FOX as a currency plugin compatible with their WooCommerce plugin, but they could not confirm whether this specific setup would work with a multi-vendor marketplace.
At the moment, FOX successfully converts our existing product prices, service fee and Packeta shipping prices from EUR to CZK. However, this only converts the same shipping price using the exchange rate.
What we need instead is the ability to use different predefined shipping prices depending on the vendor's country.
For example, if the shipping price is:
- Slovak seller → €3.90
- Czech seller → 89 CZK
we do not want FOX simply to convert €3.90 into CZK for the Czech seller. We need the Czech seller's shipment to use the actual Czech shipping price of 89 CZK.
Is this possible with FOX, either through its standard settings, fixed prices, GeoIP rules, hooks/API, or another feature?
Most importantly, can FOX determine or receive the vendor's country from WCFM Marketplace and use that information to apply the appropriate shipping price/currency?
If custom integration is required, please let us know whether FOX provides the necessary hooks or filters to implement this.
Thank you very much.
Hello,
we are currently testing the FOX Currency Switcher plugin on our WooCommerce marketplace and would like to know whether the following setup is possible.
Our website is a multi-vendor marketplace using WooCommerce + WCFM Marketplace + Packeta shipping plugin.
We have sellers from both Slovakia and the Czech Republic, and Packeta has different shipping price lists depending on the country from which the seller ships the parcel.
For example:
- a Slovak seller ships from Slovakia → Slovak Packeta shipping prices should be used,
- a Czech seller ships from the Czech Republic → Czech Packeta shipping prices should be used.
This must depend on the seller/vendor's country, not on the customer's country.
We contacted Packeta directly and they recommended FOX as a currency plugin compatible with their WooCommerce plugin, but they could not confirm whether this specific setup would work with a multi-vendor marketplace.
At the moment, FOX successfully converts our existing product prices, service fee and Packeta shipping prices from EUR to CZK. However, this only converts the same shipping price using the exchange rate.
What we need instead is the ability to use different predefined shipping prices depending on the vendor's country.
For example, if the shipping price is:
- Slovak seller → €3.90
- Czech seller → 89 CZK
we do not want FOX simply to convert €3.90 into CZK for the Czech seller. We need the Czech seller's shipment to use the actual Czech shipping price of 89 CZK.
Is this possible with FOX, either through its standard settings, fixed prices, GeoIP rules, hooks/API, or another feature?
Most importantly, can FOX determine or receive the vendor's country from WCFM Marketplace and use that information to apply the appropriate shipping price/currency?
If custom integration is required, please let us know whether FOX provides the necessary hooks or filters to implement this.
Thank you very much.
Quote from Alex Dev on September 4, 2026, 14:32Hello Pavlina
We have looked into your setup and studied both plugins you named, WCFM Marketplace and Packeta, together with FOX.
The short answer: this is not available as a built-in setting, but it is achievable with a small amount of custom code, and the architecture is on your side.
Why it is not a setting. FOX has a fixed shipping price feature, but it attaches to the WooCommerce flat rate and free shipping methods only. Packeta registers its own shipping methods, so those fields never appear for them. More importantly, FOX operates on the currency the customer selected, it has no concept of a vendor, so it can only convert a single base price by rate. That is exactly the behaviour you are seeing.
Why a snippet works well here. WCFM splits the cart into one shipping package per vendor and stores the vendor id inside each package. FOX converts shipping rates on the standard WooCommerce filter woocommerce_package_rates at priority 9999. Code running at a higher priority therefore receives the already converted rate and can replace it with a fixed amount chosen by the vendor country and the selected currency. Packeta itself is not modified and its updates will not affect this.
Add the following to your child theme functions.php, or better, to a small must-use plugin. Edit the price table at the top, everything else can stay as it is.
function my_vendor_shipping_table() { return array( 'SK' => array( 'default' => array( 'EUR' => 3.90, 'CZK' => 99.00, ), ), 'CZ' => array( 'default' => array( 'EUR' => 3.50, 'CZK' => 89.00, ), // Example of one carrier priced differently from the rest. // 'packeta_method_zpointcz' => array( 'EUR' => 2.90, 'CZK' => 79.00 ), ), ); } function my_get_package_vendor_country($package) { $vendor_id = 0; // WCFM puts the vendor id into the package when store shipping is on. if (isset($package['vendor_id']) && $package['vendor_id']) { $vendor_id = (int) $package['vendor_id']; } // Fallback: take the vendor of the first product in the package. if (!$vendor_id && !empty($package['contents']) && function_exists('wcfm_get_vendor_id_by_post')) { foreach ($package['contents'] as $item) { if (!empty($item['product_id'])) { $vendor_id = (int) wcfm_get_vendor_id_by_post($item['product_id']); break; } } } if (!$vendor_id || !function_exists('wcfmmp_get_store')) { return ''; } $store = wcfmmp_get_store($vendor_id); if (!$store || !method_exists($store, 'get_address')) { return ''; } $address = $store->get_address(); return isset($address['country']) ? strtoupper(trim($address['country'])) : ''; } add_filter( 'woocommerce_package_rates', function ($rates, $package) { global $WOOCS; if (!is_object($WOOCS) || empty($rates)) { return $rates; } $vendor_country = my_get_package_vendor_country($package); if ('' === $vendor_country) { return $rates; } $table = my_vendor_shipping_table(); if (!isset($table[$vendor_country])) { return $rates; } $currency = strtoupper($WOOCS->current_currency); $rules = $table[$vendor_country]; foreach ($rates as $rate) { $method_id = $rate->get_method_id(); // Only touch Packeta methods, leave everything else alone. if (strpos($method_id, 'packeta') !== 0 && strpos($method_id, 'packetery') !== 0) { continue; } // Per method price first, the shared price second. if (isset($rules[$method_id][$currency])) { $new_cost = $rules[$method_id][$currency]; } elseif (isset($rules['default'][$currency])) { $new_cost = $rules['default'][$currency]; } else { continue; } $new_cost = (float) $new_cost; $rate->set_cost($new_cost); // The tax was calculated from the old cost, recalculate it. if (function_exists('wc_tax_enabled') && wc_tax_enabled() && !WC()->customer->is_vat_exempt()) { $rate->set_taxes(WC_Tax::calc_shipping_tax($new_cost, WC_Tax::get_shipping_tax_rates())); } else { $rate->set_taxes(array()); } } return $rates; }, 99999, 2 ); add_filter( 'woocommerce_cart_shipping_packages', function ($packages) { global $WOOCS; if (!is_object($WOOCS)) { return $packages; } foreach ($packages as $key => $package) { $packages[$key]['woocs_currency'] = $WOOCS->current_currency; } return $packages; }, 100 );A cart containing products from a Slovak and a Czech seller at the same time produces two packages, so each one is priced from its own country independently. That is the behaviour you described.
Points worth checking on your side before you go live:
The country must actually be filled in each vendor's store address, otherwise the package is skipped and the normal converted price is used. This is a safe fallback rather than an error, but it will look like the code is not working.
If your prices are entered including tax, put tax inclusive amounts into the table and remove the tax recalculation block, otherwise tax will be added twice.
If you use the block based cart and checkout rather than the classic shortcodes, please test there specifically. The filter is the same, but the recalculation path differs and it is worth confirming on your setup.
Packeta free shipping thresholds and cash on delivery surcharges are calculated from the cart total and are not touched by this code.
The second filter is useful on its own, with or without the vendor logic. Without it WooCommerce can serve a cached shipping rate from the previously selected currency.
Best regards
Alex
Hello Pavlina
We have looked into your setup and studied both plugins you named, WCFM Marketplace and Packeta, together with FOX.
The short answer: this is not available as a built-in setting, but it is achievable with a small amount of custom code, and the architecture is on your side.
Why it is not a setting. FOX has a fixed shipping price feature, but it attaches to the WooCommerce flat rate and free shipping methods only. Packeta registers its own shipping methods, so those fields never appear for them. More importantly, FOX operates on the currency the customer selected, it has no concept of a vendor, so it can only convert a single base price by rate. That is exactly the behaviour you are seeing.
Why a snippet works well here. WCFM splits the cart into one shipping package per vendor and stores the vendor id inside each package. FOX converts shipping rates on the standard WooCommerce filter woocommerce_package_rates at priority 9999. Code running at a higher priority therefore receives the already converted rate and can replace it with a fixed amount chosen by the vendor country and the selected currency. Packeta itself is not modified and its updates will not affect this.
Add the following to your child theme functions.php, or better, to a small must-use plugin. Edit the price table at the top, everything else can stay as it is.
function my_vendor_shipping_table() {
return array(
'SK' => array(
'default' => array(
'EUR' => 3.90,
'CZK' => 99.00,
),
),
'CZ' => array(
'default' => array(
'EUR' => 3.50,
'CZK' => 89.00,
),
// Example of one carrier priced differently from the rest.
// 'packeta_method_zpointcz' => array( 'EUR' => 2.90, 'CZK' => 79.00 ),
),
);
}
function my_get_package_vendor_country($package) {
$vendor_id = 0;
// WCFM puts the vendor id into the package when store shipping is on.
if (isset($package['vendor_id']) && $package['vendor_id']) {
$vendor_id = (int) $package['vendor_id'];
}
// Fallback: take the vendor of the first product in the package.
if (!$vendor_id && !empty($package['contents']) && function_exists('wcfm_get_vendor_id_by_post')) {
foreach ($package['contents'] as $item) {
if (!empty($item['product_id'])) {
$vendor_id = (int) wcfm_get_vendor_id_by_post($item['product_id']);
break;
}
}
}
if (!$vendor_id || !function_exists('wcfmmp_get_store')) {
return '';
}
$store = wcfmmp_get_store($vendor_id);
if (!$store || !method_exists($store, 'get_address')) {
return '';
}
$address = $store->get_address();
return isset($address['country']) ? strtoupper(trim($address['country'])) : '';
}
add_filter(
'woocommerce_package_rates',
function ($rates, $package) {
global $WOOCS;
if (!is_object($WOOCS) || empty($rates)) {
return $rates;
}
$vendor_country = my_get_package_vendor_country($package);
if ('' === $vendor_country) {
return $rates;
}
$table = my_vendor_shipping_table();
if (!isset($table[$vendor_country])) {
return $rates;
}
$currency = strtoupper($WOOCS->current_currency);
$rules = $table[$vendor_country];
foreach ($rates as $rate) {
$method_id = $rate->get_method_id();
// Only touch Packeta methods, leave everything else alone.
if (strpos($method_id, 'packeta') !== 0 && strpos($method_id, 'packetery') !== 0) {
continue;
}
// Per method price first, the shared price second.
if (isset($rules[$method_id][$currency])) {
$new_cost = $rules[$method_id][$currency];
} elseif (isset($rules['default'][$currency])) {
$new_cost = $rules['default'][$currency];
} else {
continue;
}
$new_cost = (float) $new_cost;
$rate->set_cost($new_cost);
// The tax was calculated from the old cost, recalculate it.
if (function_exists('wc_tax_enabled') && wc_tax_enabled() && !WC()->customer->is_vat_exempt()) {
$rate->set_taxes(WC_Tax::calc_shipping_tax($new_cost, WC_Tax::get_shipping_tax_rates()));
} else {
$rate->set_taxes(array());
}
}
return $rates;
},
99999,
2
);
add_filter(
'woocommerce_cart_shipping_packages',
function ($packages) {
global $WOOCS;
if (!is_object($WOOCS)) {
return $packages;
}
foreach ($packages as $key => $package) {
$packages[$key]['woocs_currency'] = $WOOCS->current_currency;
}
return $packages;
},
100
);
A cart containing products from a Slovak and a Czech seller at the same time produces two packages, so each one is priced from its own country independently. That is the behaviour you described.
Points worth checking on your side before you go live:
The country must actually be filled in each vendor's store address, otherwise the package is skipped and the normal converted price is used. This is a safe fallback rather than an error, but it will look like the code is not working.
If your prices are entered including tax, put tax inclusive amounts into the table and remove the tax recalculation block, otherwise tax will be added twice.
If you use the block based cart and checkout rather than the classic shortcodes, please test there specifically. The filter is the same, but the recalculation path differs and it is worth confirming on your setup.
Packeta free shipping thresholds and cash on delivery surcharges are calculated from the cart total and are not touched by this code.
The second filter is useful on its own, with or without the vendor logic. Without it WooCommerce can serve a cached shipping rate from the previously selected currency.
Best regards
Alex