🔧 Extender el WebService — recursos personalizados

Actualizado: 2024-12-01

PrestaShop permite exponer cualquier ObjectModel a traves de la API REST agregando la propiedad $webserviceParameters. Ademas se pueden agregar campos virtuales (calculados) al recurso.

#Exponer un ObjectModel via WebService

Agregar $webserviceParameters al ObjectModel
php
<?php

class MyModuleItem extends ObjectModel
{
    public $name;
    public $description;
    public $active;
    public $price;
    public $date_add;

    public static $definition = [
        'table'   => 'mymodule_item',
        'primary' => 'id_mymodule_item',
        'multilang' => true,
        'fields'  => [
            'active'      => ['type' => self::TYPE_BOOL,   'validate' => 'isBool'],
            'price'       => ['type' => self::TYPE_FLOAT,  'validate' => 'isPrice'],
            'date_add'    => ['type' => self::TYPE_DATE,   'validate' => 'isDate'],
            'name'        => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCatalogName', 'required' => true, 'size' => 255],
            'description' => ['type' => self::TYPE_HTML,   'lang' => true, 'validate' => 'isCleanHtml'],
        ],
    ];

    // ── Exponer via WebService ──
    protected $webserviceParameters = [
        'objectsNodeName' => 'mymodule_items',    // Nodo XML plural
        'objectNodeName'  => 'mymodule_item',     // Nodo XML singular
        'fields' => [
            'id_mymodule_item' => [],              // Campos extra a exponer
            'active' => [],
            'price'  => [],
        ],
        // Campos de asociaciones (relaciones N:N)
        'associations' => [
            'categories' => [
                'resource' => 'category',
                'fields'   => ['id' => []],
            ],
        ],
    ];
}

#Agregar campos virtuales

Campos virtuales (calculados) en el recurso WS
php
<?php

// En el ObjectModel, agregar metodo getWsFieldName() para campos virtuales
// El metodo debe seguir el patron getWs{FieldName}()

class MyModuleItem extends ObjectModel
{
    // ... (resto de la clase)

    /**
     * Campo virtual: precio con IVA (calculado en PHP, no en DB).
     * Accesible como 'price_with_tax' en la API.
     */
    public function getWsPriceWithTax(): float
    {
        $taxRate = 0.21; // IVA 21%
        return round($this->price * (1 + $taxRate), 2);
    }

    /**
     * Campo virtual: nombre completo del recurso.
     */
    public function getWsFullName(): string
    {
        $lang = Context::getContext()->language->id;
        return $this->name[$lang] ?? '';
    }

    protected $webserviceParameters = [
        'objectsNodeName' => 'mymodule_items',
        'objectNodeName'  => 'mymodule_item',
        'fields' => [
            // Campos de la BD
            'price'  => ['sqlId' => 'price'],
            'active' => ['sqlId' => 'active'],
            // Campos virtuales (calculados)
            'price_with_tax' => [
                'getter'     => 'getWsPriceWithTax',
                'setter'     => false, // Solo lectura
                'sqlId'      => false, // No hay columna en BD
            ],
            'full_name' => [
                'getter' => 'getWsFullName',
                'setter' => false,
                'sqlId'  => false,
            ],
        ],
    ];
}

#Hook actionWebserviceResources

Registrar el recurso en el WebService via hook
php
<?php

// En mymodule.php
public function install(): bool
{
    return parent::install()
        && $this->registerHook('addWebserviceResources');
}

/**
 * Registra los nuevos recursos en el sistema WebService.
 * Los recursos aparecen en Parametros Avanzados → WebService → Permisos.
 */
public function hookAddWebserviceResources(array $params): array
{
    return [
        'mymodule_items' => [
            'description' => 'Items del modulo MyModule',
            'class'       => 'MyModuleItem',
            'forbidden_method' => ['DELETE'], // Metodos prohibidos
        ],
    ];
}

// ── Despues de instalar el modulo, el recurso aparece en:
// Parametros Avanzados → WebService → Editar clave → Permisos
// y se puede acceder en:
// GET https://mitienda.com/api/mymodule_items
// GET https://mitienda.com/api/mymodule_items/42
// POST https://mitienda.com/api/mymodule_items
// PUT https://mitienda.com/api/mymodule_items/42

#Limitar acceso por IP o clave

Restringir acceso al WebService por IP
php
<?php

// ── Restriccion de IP en el BO ──
// Parametros Avanzados → WebService → Editar clave → IPs permitidas
// Dejar vacio para permitir cualquier IP

// ── Restriccion personalizada desde un modulo ──
public function install(): bool
{
    return parent::install()
        && $this->registerHook('actionWebserviceCheckAuthentication');
}

public function hookActionWebserviceCheckAuthentication(array $params): void
{
    // $params['authentication_key'] = la API key usada
    // $params['request'] = objeto WebserviceRequest

    $allowedIps = ['192.168.1.0/24', '10.0.0.5'];
    $clientIp   = $_SERVER['REMOTE_ADDR'] ?? '';

    // Verificar si la IP esta en la lista blanca
    $isAllowed = false;
    foreach ($allowedIps as $ip) {
        if ($ip === $clientIp || $this->ipInRange($clientIp, $ip)) {
            $isAllowed = true;
            break;
        }
    }

    if (!$isAllowed) {
        // Bloquear la peticion
        header('HTTP/1.1 403 Forbidden');
        die(json_encode(['error' => 'IP not allowed']));
    }
}

private function ipInRange(string $ip, string $cidr): bool
{
    if (strpos($cidr, '/') === false) {
        return $ip === $cidr;
    }
    [$subnet, $mask] = explode('/', $cidr);
    return (ip2long($ip) & ~((1 << (32 - $mask)) - 1)) === ip2long($subnet);
}
Descargar en Markdown Pensado para pegar en ChatGPT, Claude u otra IA. Incluye solo el contenido de esta pagina.