Hello @barnaddy06
The best approach is to implement this as a custom shipping carrier.
You should not read the destination country directly from the request or session. Get the current cart and retrieve the country from the cart's shipping address:
use Webkul\Checkout\Facades\Cart;
$cart = Cart::getCart();
$country = $cart->shipping_address?->country
?? $cart->billing_address?->country;
The country value will be the ISO country code, for example:
US
GB
NL
AU
For weight, if you are using Bagisto's native weight attribute, you should use the cart item total_weight instead of recalculating the product weight manually:
$totalWeight = 0;
foreach ($cart->items as $item) {
if (! $item->getTypeInstance()->isStockable()) {
continue;
}
$totalWeight += (float) $item->total_weight;
}
Using $cart->items is important because all_items may include child items and can result in double-counting for configurable or bundle products.
Then create a custom carrier extending AbstractShipping and perform the country + weight calculation inside the calculate() method:
class InternationalRate extends AbstractShipping
{
protected $code = 'international';
public function calculate()
{
if (! $this->isAvailable()) {
return false;
}
$cart = Cart::getCart();
if (! $cart || ! $cart->haveStockableItems()) {
return false;
}
$country = $cart->shipping_address?->country
?? $cart->billing_address?->country;
$weight = 0;
foreach ($cart->items as $item) {
if (! $item->getTypeInstance()->isStockable()) {
continue;
}
$weight += (float) $item->total_weight;
}
$rates = [
'US' => ['handling' => 8, 'per_kg' => 2.5],
'GB' => ['handling' => 6, 'per_kg' => 2],
'NL' => ['handling' => 6.5, 'per_kg' => 2.2],
'AU' => ['handling' => 12, 'per_kg' => 4],
];
if (! isset($rates[$country])) {
return false;
}
$basePrice = $rates[$country]['handling']
+ ($weight * $rates[$country]['per_kg']);
return $this->getRate($basePrice);
}
}
The main point is:
Cart → Shipping Address Country + Cart Item Weight → Custom Carrier → Calculated Shipping Rate
Also, make sure to set both base_price and price on the CartShippingRate. The base price should be calculated in the store's base currency, while price should be converted using:
$rate->base_price = $basePrice;
$rate->price = core()->convertPrice($basePrice);
If the shipping rules become more complex, such as multiple weight slabs per country, I would recommend storing the rules in a database table rather than hardcoding them.
One important note: if your product weight is stored in a completely custom attribute instead of Bagisto's native weight attribute, total_weight may not be populated. In that case, either map your value to Bagisto's native weight field or calculate it from your custom attribute manually.
For this requirement, a custom shipping carrier is the cleanest and most maintainable Bagisto solution.
Best regards,
Shivendra Gupta
Team Bagisto