✅ Flujo de validacion de pagos — validateOrder()

Actualizado: 2024-12-01

validateOrder() es el metodo central de cualquier modulo de pago. Crea el pedido en la base de datos, asigna el estado inicial, genera la factura y envia los emails de confirmacion. Se llama desde el ConfirmationFrontController del modulo.

#Firma completa de validateOrder()

Firma de validateOrder() en PaymentModule
php
<?php

/**
 * @param int    $id_cart          ID del carrito a convertir en pedido
 * @param int    $id_order_state   Estado inicial del pedido
 * @param float  $amount_paid      Importe cobrado realmente
 * @param string $payment_method   Nombre del metodo de pago (texto)
 * @param string|null $message     Mensaje interno del pedido
 * @param array  $extra_vars       Variables extra para el email
 * @param int|null $currency_special  Moneda especial (null = moneda del carrito)
 * @param bool   $dont_touch_amount  No redondear el importe
 * @param string|null $secure_key  Clave de seguridad del cliente
 * @param Shop|null   $shop        Tienda (null = tienda actual)
 * @return bool
 */
public function validateOrder(
    $id_cart,
    $id_order_state,
    $amount_paid,
    $payment_method = 'Unknown',
    $message = null,
    $extra_vars = [],
    $currency_special = null,
    $dont_touch_amount = false,
    $secure_key = false,
    Shop $shop = null
)

#Parametros detallados

ParametroTipoDescripcion
id_cartintID del carrito; normalmente Tools::getValue('cart_id')
id_order_stateintEstado inicial: PS_OS_PAYMENT (pagado) o PS_OS_BANKWIRE (pendiente)
amount_paidfloatImporte real cobrado; debe coincidir con el total del carrito
payment_methodstringTexto del metodo: 'Tarjeta', 'PayPal', etc.
messagestringMensaje interno visible solo en el BO (null = sin mensaje)
extra_varsarrayVariables extra para la plantilla del email de confirmacion
secure_keystringMD5 del cliente + salt; previene doble validacion

#Flujo completo de validacion

ConfirmationFrontController completo con validateOrder()
php
<?php

class MyModuleConfirmationModuleFrontController extends ModuleFrontController
{
    public function postProcess(): void
    {
        // 1. Recuperar el carrito del contexto
        $cart = $this->context->cart;

        // 2. Verificar que el carrito es valido
        if (!$cart->id_customer
            || !$cart->id_address_delivery
            || !$cart->id_address_invoice
        ) {
            Tools::redirect('index.php?controller=order');
        }

        // 3. Verificar el modulo de pago
        $authorized = false;
        foreach (Module::getPaymentModules() as $module) {
            if ($module['name'] === $this->module->name) {
                $authorized = true;
                break;
            }
        }
        if (!$authorized) {
            $this->errors[] = $this->trans('Payment module not authorized.', [], 'Shop.Notifications.Error');
            return;
        }

        // 4. Verificar que el cliente es el propietario del carrito
        $customer   = new Customer((int) $cart->id_customer);
        $secureKey  = $customer->secure_key;

        // 5. Recuperar datos de pago de la pasarela
        $paymentId     = Tools::getValue('payment_id');
        $paymentStatus = $this->verifyPaymentWithGateway($paymentId);

        if ($paymentStatus !== 'completed') {
            $this->errors[] = $this->trans('Payment not completed.', [], 'Shop.Notifications.Error');
            return;
        }

        // 6. Llamar a validateOrder()
        $currency = $this->context->currency;
        $this->module->validateOrder(
            (int) $cart->id,
            (int) Configuration::get('PS_OS_PAYMENT'),
            (float) $cart->getOrderTotal(true, Cart::BOTH),
            $this->module->displayName,
            null,                         // mensaje interno
            ['transaction_id' => $paymentId], // vars para el email
            (int) $currency->id,
            false,
            $secureKey
        );

        // 7. Redirigir a la pagina de confirmacion
        Tools::redirect(
            'index.php?controller=order-confirmation'
            . '&id_cart=' . (int) $cart->id
            . '&id_module=' . (int) $this->module->id
            . '&id_order=' . (int) $this->module->currentOrder
            . '&key=' . $secureKey
        );
    }

    private function verifyPaymentWithGateway(string $paymentId): string
    {
        // Aqui va la llamada a la API de la pasarela de pago
        // Devuelve 'completed', 'pending', 'failed', etc.
        return 'completed';
    }
}

#Manejo de errores y pagos fallidos

Manejo de pagos fallidos y pendientes
php
<?php

// ── Pago fallido ──
if ($paymentStatus === 'failed') {
    // Crear el pedido con estado ERROR
    $this->module->validateOrder(
        (int) $cart->id,
        (int) Configuration::get('PS_OS_ERROR'),
        0.0,  // importe 0 porque no se cobro
        $this->module->displayName,
        'Pago rechazado por la pasarela',
        [],
        null,
        false,
        $customer->secure_key
    );
    Tools::redirect('index.php?controller=order?step=3');
}

// ── Pago pendiente (transferencia / verificacion manual) ──
if ($paymentStatus === 'pending') {
    $this->module->validateOrder(
        (int) $cart->id,
        (int) Configuration::get('PS_OS_BANKWIRE'), // pendiente de pago
        (float) $cart->getOrderTotal(true, Cart::BOTH),
        $this->module->displayName,
        'Pago pendiente de confirmacion',
        [],
        null,
        false,
        $customer->secure_key
    );
    // Redirigir a confirmacion igualmente
    Tools::redirect(/*...*/);
}

// ── Acceder al ID del pedido creado ──
// Despues de validateOrder(), el ID esta disponible en:
$idOrder = (int) $this->module->currentOrder;
Descargar en Markdown Pensado para pegar en ChatGPT, Claude u otra IA. Incluye solo el contenido de esta pagina.