---
title: Calculo de tarifas de envio — peso, precio y reglas
section: carriers
slug: shipping-calc
description: "Como calcular tarifas de envio en modulos PrestaShop: getOrderShippingCost por peso y precio, rangos, zonas de envio y configuracion de tarifas."
keywords: prestashop calculo envio tarifa peso precio zona RangeWeight RangePrice getOrderShippingCost modulo transportista
last_updated: 2024-12-01
source_url: "https://ayudaprestashop.es/carriers/shipping-calc"
---

# Calculo de tarifas de envio — peso, precio y reglas

> Como calcular tarifas de envio en modulos PrestaShop: getOrderShippingCost por peso y precio, rangos, zonas de envio y configuracion de tarifas.

Un modulo de transportista debe implementar `getOrderShippingCost()` y/o `getOrderShippingCostExternal()`. PrestaShop llama a estos metodos para calcular el coste de envio durante el checkout.

## getOrderShippingCost() — implementacion

*Implementar getOrderShippingCost() en el modulo*

```php
<?php

class MyCarrierModule extends CarrierModule
{
    /**
     * Calcula el coste de envio usando los rangos definidos en el BO.
     *
     * @param Cart  $params  El carrito actual
     * @param float $shipping_cost Coste calculado por PrestaShop (rangos del BO)
     * @return float|bool  El coste final, o false si no aplica
     */
    public function getOrderShippingCost($params, $shipping_cost)
    {
        // $shipping_cost ya viene calculado por PS segun los rangos del BO
        // Podemos modificarlo o simplemente devolverlo
        if ($shipping_cost === false) {
            return false; // Fuera de rango → no disponible
        }

        // Ejemplo: aplicar un recargo por entrega en domicilio
        $extraCharge = (float) Configuration::get('MYCARRIER_EXTRA');
        return (float) $shipping_cost + $extraCharge;
    }

    /**
     * Calcula el coste con logica completamente propia (ignora rangos del BO).
     * Se usa cuando la tarifa viene de una API externa.
     *
     * @param Cart  $params  El carrito actual
     * @return float|bool
     */
    public function getOrderShippingCostExternal($params)
    {
        $cart   = $params; // $params es el objeto Cart
        $weight = (float) $cart->getTotalWeight();
        $total  = (float) $cart->getOrderTotal(false, Cart::ONLY_PRODUCTS);

        // Llamada a API externa para obtener la tarifa
        $rate = $this->fetchRateFromApi($weight, $total, $cart->id_address_delivery);

        return $rate !== null ? (float) $rate : false;
    }
}
```

## Calcular por peso

*Logica de calculo por peso sin usar rangos del BO*

```php
<?php

private function calculateByWeight(Cart $cart): float
{
    $weight = (float) $cart->getTotalWeight(); // en kg por defecto

    // Tarifa escalonada por peso
    $rates = [
        ['max' => 1.0,  'price' => 3.99],
        ['max' => 5.0,  'price' => 5.99],
        ['max' => 10.0, 'price' => 7.99],
        ['max' => 20.0, 'price' => 9.99],
        ['max' => PHP_FLOAT_MAX, 'price' => 14.99], // >20kg
    ];

    foreach ($rates as $rate) {
        if ($weight <= $rate['max']) {
            return (float) $rate['price'];
        }
    }

    return false; // No deberia llegar aqui por el ultimo catch-all
}

// ── Obtener peso del carrito ──
$weight    = $cart->getTotalWeight();     // Total en unidad del sistema
$products  = $cart->getProducts();
foreach ($products as $product) {
    // $product['weight'] = peso unitario
    // $product['cart_quantity'] = cantidad
    $lineWeight = (float) $product['weight'] * (int) $product['cart_quantity'];
}
```

## Calcular por importe del pedido

*Envio gratuito a partir de un importe minimo*

```php
<?php

private function calculateByOrderTotal(Cart $cart): float
{
    // Importe sin impuestos ni envio
    $total = (float) $cart->getOrderTotal(false, Cart::ONLY_PRODUCTS);

    $freeShippingThreshold = (float) Configuration::get('MYCARRIER_FREE_FROM');
    $baseRate              = (float) Configuration::get('MYCARRIER_BASE_RATE');

    // Envio gratis a partir del umbral
    if ($freeShippingThreshold > 0 && $total >= $freeShippingThreshold) {
        return 0.0;
    }

    // Tarifa porcentual sobre el pedido
    $percentageRate = (float) Configuration::get('MYCARRIER_PERCENT_RATE');
    if ($percentageRate > 0) {
        return round($total * $percentageRate / 100, 2);
    }

    return $baseRate;
}
```

## Rangos y zonas en el BO

Si usas `getOrderShippingCost()` (sin External), PrestaShop aplica los rangos configurados en el BO (Transporte > Transportistas > Editar > Rangos de precio/peso) antes de llamar al modulo. El valor `$shipping_cost` que recibe el metodo ya tiene la tarifa calculada segun esos rangos.

*Configurar rangos de peso al instalar el transportista*

```php
<?php

// En install() del modulo, crear rangos de peso automaticamente:
private function createWeightRanges(int $idCarrier): void
{
    $ranges = [
        ['delimiter1' => 0,  'delimiter2' => 1],
        ['delimiter1' => 1,  'delimiter2' => 5],
        ['delimiter1' => 5,  'delimiter2' => 10],
        ['delimiter1' => 10, 'delimiter2' => 20],
    ];

    foreach ($ranges as $rangeData) {
        $range              = new RangeWeight();
        $range->id_carrier  = $idCarrier;
        $range->delimiter1  = $rangeData['delimiter1'];
        $range->delimiter2  = $rangeData['delimiter2'];
        $range->add();
    }
}
```

## Tarifas dinamicas via API externa

*Obtener tarifa de API externa con cache*

```php
<?php

private function fetchRateFromApi(float $weight, float $total, int $idAddress): ?float
{
    // Cache por session para no llamar a la API en cada renderizado
    $cacheKey = 'mycarrier_rate_' . $idAddress . '_' . round($weight, 2);
    if (Cache::isStored($cacheKey)) {
        return (float) Cache::retrieve($cacheKey);
    }

    $address = new Address($idAddress);
    $country = new Country($address->id_country);

    try {
        $response = file_get_contents(
            'https://api.mycarrier.com/rate?'
            . http_build_query([
                'weight'     => $weight,
                'country'    => $country->iso_code,
                'postal'     => $address->postcode,
                'api_key'    => Configuration::get('MYCARRIER_API_KEY'),
            ])
        );

        $data = json_decode($response, true);
        $rate = (float) ($data['price'] ?? 0);

        Cache::store($cacheKey, $rate, 300); // Cache 5 minutos
        return $rate;

    } catch (\Exception $e) {
        PrestaShopLogger::addLog(
            'MyCarrier API error: ' . $e->getMessage(),
            3, null, 'MyCarrierModule'
        );
        return null;
    }
}
```


---

*Fuente: [https://ayudaprestashop.es/carriers/shipping-calc](https://ayudaprestashop.es/carriers/shipping-calc). Version Markdown generada automaticamente para consumo por LLMs.*
