# Actualización en cPanel · NimiApps 0.2.0 → 0.3.0 (ENT-003)

Este manual actualiza la instalación de **staging** que ya funciona con la
versión 0.2.0 (ENT-002). No es una instalación nueva: se conservan `.env`, la
base de datos, `storage/`, los dos `.htaccess` del servidor y `vendor/`
(al que solo se **añade** la librería oficial de Stripe).

| Dato                     | Valor                                                     |
|--------------------------|-----------------------------------------------------------|
| Usuario de cPanel        | `nimiapss`                                                |
| Carpeta de la aplicación | `/home/nimiapss/public_html/staging.nimiapps.com/`        |
| Document root            | `/home/nimiapss/public_html/staging.nimiapps.com/public/` |
| URL                      | https://staging.nimiapps.com                              |
| PHP                      | 8.3 (ea-php83) · MariaDB 10.6                             |

Tiempo estimado: 30–40 minutos (más la configuración de Stripe del paso 11),
de los cuales la web está en mantenimiento unos 5–10.

> **Importante.** No hay vuelta atrás automática. La vuelta atrás se hace con
> las copias del paso 5 y el apartado 15. No continúes si las copias no se
> han creado bien.

## Índice

1. [Qué cambia y qué no](#1-qué-cambia-y-qué-no)
2. [Contenido del paquete](#2-contenido-del-paquete)
3. [Verificar y subir el ZIP](#3-verificar-y-subir-el-zip)
4. [Comprobar la versión instalada](#4-comprobar-la-versión-instalada)
5. [Copias de seguridad](#5-copias-de-seguridad)
6. [Simulación (sin cambios)](#6-simulación-sin-cambios)
7. [Modo mantenimiento](#7-modo-mantenimiento)
8. [Actualizar los archivos](#8-actualizar-los-archivos)
9. [Cachés y migraciones](#9-cachés-y-migraciones)
10. [Permisos](#10-permisos)
11. [Configurar Stripe en modo de pruebas](#11-configurar-stripe-en-modo-de-pruebas)
12. [Diagnóstico y fin del mantenimiento](#12-diagnóstico-y-fin-del-mantenimiento)
13. [Primeros pasos en el panel](#13-primeros-pasos-en-el-panel)
14. [Comprobaciones en el navegador](#14-comprobaciones-en-el-navegador)
15. [Volver atrás](#15-volver-atrás)
16. [Errores frecuentes](#16-errores-frecuentes)
17. [Antes de cobrar de verdad (modo real)](#17-antes-de-cobrar-de-verdad-modo-real)
18. [Limpieza](#18-limpieza)

---

## 1. Qué cambia y qué no

**Se añade o sustituye** (lista exacta en `manifiesto/`):

- Catálogo comercial, contratación, Stripe, licencias, panel
  `/admin/comercial` y área de contrataciones del cliente.
- 6 migraciones nuevas (`database/migrations/2026_10_22_*`) y 1 del módulo de
  demostración (`modules/Demo/database/migrations/`). Solo **crean tablas**;
  no modifican ni borran datos existentes.
- El módulo `modules/Demo` («Demo de licencias»), microapp de prueba.
- `vendor/stripe/stripe-php` (v17.6.0, nueva dependencia) y 5 archivos de
  `vendor/composer/` (el cargador de clases que la registra). El resto de
  `vendor/` no cambia. **No hace falta Composer en el servidor.**
- Vistas, CSS compilado (`public/build`), `config/commerce.php` (nuevo),
  `config/microapps.php`, `routes/web.php`, `bootstrap/app.php`,
  `.env.example`, `composer.json`, `composer.lock`, `CHECKSUMS.sha256`.
- Documentación (`README.md` y los documentos de ENT-003).

**No se toca:**

| Elemento                       | Motivo                                                        |
|--------------------------------|---------------------------------------------------------------|
| `.env`                         | Credenciales del servidor. Solo lo editas tú en el paso 11.   |
| `.htaccess` (raíz)             | Protege la carpeta de la aplicación.                          |
| `public/.htaccess`             | Contiene la autorización expresa añadida en el servidor.      |
| `storage/`, `bootstrap/cache/` | Logs, sesiones y cachés del servidor.                         |
| Base de datos                  | Solo cambia con `migrate` (paso 9), que únicamente añade.     |

Los CSS antiguos `public/build/assets/app-c66wexFq.css` y
`app-C0d66-7m.css` quedan sin uso (el nuevo `manifest.json` apunta al
nuevo). Son inofensivos y no se borran.

**No hace falta:** Node.js, npm, Composer, Git, cron ni un proceso de colas.

## 2. Contenido del paquete

```
nimiapps-v0.3.0-actualizacion/
├── LEEME.txt
├── actualizar.sh                        Script de actualización
├── ACTUALIZACION-CPANEL-ENT-003.md      Este manual
├── ARQUITECTURA-ENT-003.md              Cómo está construido
├── MANUAL-ADMIN-COMERCIAL.md            Manual breve del panel comercial
├── PRUEBAS-ENT-003.md                   Pruebas realizadas y pendientes
├── CAMBIOS-ENT-003.md                   Lista de cambios
├── manifiesto/
│   ├── archivos-nuevos.txt              Archivos que se añaden
│   ├── archivos-modificados.txt         Archivos que se sustituyen
│   ├── v020-esperado.sha256             Huella que deben tener hoy (0.2.0)
│   └── paquete.sha256                   Huella de cada archivo del paquete
└── archivos/                            Archivos de la versión 0.3.0
```

`actualizar.sh` hace, en orden, deteniéndose ante cualquier error:

1. Se niega a ejecutarse como `root`.
2. Comprueba PHP 8.3 y la integridad del paquete (`paquete.sha256`).
3. Comprueba que el destino tiene `artisan`, `.env` y `vendor/`, y que la
   versión instalada es **0.2.0**. Si ya es 0.3.0 y todo coincide, lo dice y
   termina sin tocar nada.
4. Exige el modo mantenimiento (salvo con `--simular`).
5. Comprueba que ningún archivo que va a sustituir tiene **cambios locales**
   respecto a la 0.2.0 y que no existe ya ningún archivo «nuevo» con otro
   contenido. Si encuentra alguno, **no copia nada** y lo lista.
6. Guarda los archivos que va a sustituir en
   `~/nimiapps-respaldos/actualizacion-ent003-FECHA/`, con la lista de
   archivos nuevos y un script `restaurar-archivos.sh`.
7. Copia cada archivo a un nombre temporal y lo renombra.
   `config/microapps.php` (la versión) se copia el último: si algo falla
   antes, la instalación sigue diciendo 0.2.0 y el script se puede repetir.
8. Verifica la huella SHA-256 de todo lo copiado.

No ejecuta migraciones, no borra archivos y no copia la base de datos.

## 3. Verificar y subir el ZIP

### 3.1 En tu ordenador, antes de subirlo

Compara la huella del ZIP con la de `nimiapps-v0.3.0-actualizacion.zip.sha256`:

- Windows (PowerShell): `Get-FileHash nimiapps-v0.3.0-actualizacion.zip -Algorithm SHA256`
- macOS: `shasum -a 256 nimiapps-v0.3.0-actualizacion.zip`
- Linux: `sha256sum -c nimiapps-v0.3.0-actualizacion.zip.sha256`

### 3.2 Subirlo fuera de public_html

Con el **Administrador de archivos** de cPanel, sube el ZIP y el `.sha256` a
**`/home/nimiapss`** (no a `public_html`).

### 3.3 Comprobar y descomprimir por SSH

```bash
cd /home/nimiapss
sha256sum -c nimiapps-v0.3.0-actualizacion.zip.sha256
# Debe decir: nimiapps-v0.3.0-actualizacion.zip: OK

ls -d nimiapps-v0.3.0-actualizacion 2>/dev/null && echo "YA EXISTE: bórrala o renómbrala antes"
unzip -q nimiapps-v0.3.0-actualizacion.zip
ls nimiapps-v0.3.0-actualizacion
```

## 4. Comprobar la versión instalada

```bash
PHP=/opt/cpanel/ea-php83/root/usr/bin/php        # o PHP=php si "php -v" ya da 8.3
APP=/home/nimiapss/public_html/staging.nimiapps.com
PAQ=/home/nimiapss/nimiapps-v0.3.0-actualizacion
$PHP -v | head -1                                  # Debe ser PHP 8.3.x
cd $APP
grep "'version'" config/microapps.php              # Debe decir '0.2.0'
$PHP artisan microapps:check                       # Debe terminar sin errores
df -h ~ | tail -1                                  # Hacen falta unos 30 MB libres
```

Si la versión no es `0.2.0`, **detente**.

## 5. Copias de seguridad

Se guardan en `/home/nimiapss/nimiapps-respaldos/`, **fuera de public_html**.

### 5.1 Base de datos

```bash
grep -E '^DB_(DATABASE|USERNAME)=' $APP/.env
mkdir -p ~/nimiapps-respaldos && chmod 700 ~/nimiapps-respaldos
FECHA=$(date +%Y%m%d-%H%M)
mysqldump --single-transaction --routines --triggers --default-character-set=utf8mb4 \
  -u NOMBRE_USUARIO_BD -p NOMBRE_BD > ~/nimiapps-respaldos/bd-antes-ent003-$FECHA.sql
ls -lh ~/nimiapps-respaldos/bd-antes-ent003-$FECHA.sql
tail -1 ~/nimiapps-respaldos/bd-antes-ent003-$FECHA.sql   # Debe ser "-- Dump completed ..."
```

Sin SSH: cPanel → **phpMyAdmin** → base de datos → **Exportar** → SQL.

### 5.2 Archivos

```bash
tar -czf ~/nimiapps-respaldos/archivos-antes-ent003-$FECHA.tar.gz \
  -C /home/nimiapss/public_html staging.nimiapps.com
ls -lh ~/nimiapps-respaldos/archivos-antes-ent003-$FECHA.tar.gz
chmod 600 ~/nimiapps-respaldos/*.sql ~/nimiapps-respaldos/*.tar.gz
```

## 6. Simulación (sin cambios)

```bash
PHP=$PHP bash $PAQ/actualizar.sh $APP --simular
```

Debe terminar con **«Todo listo para actualizar. No se ha modificado nada.»**
(avisará de que no está en mantenimiento: es normal aquí).

Si dice **«Modificado localmente»** o **«Ya existe y es distinto»**, no
sigas: esos archivos del servidor no son los de la 0.2.0. Guárdalos aparte y
consúltalo antes de continuar.

## 7. Modo mantenimiento

```bash
cd $APP
$PHP artisan down
```

## 8. Actualizar los archivos

```bash
PHP=$PHP bash $PAQ/actualizar.sh $APP
```

Debe terminar con **«Archivos actualizados correctamente. La aplicación SIGUE
en modo mantenimiento.»** y mostrar la carpeta de la copia
(`~/nimiapps-respaldos/actualizacion-ent003-FECHA/`). Anota esa ruta.

## 9. Cachés y migraciones

```bash
cd $APP
$PHP artisan config:clear
$PHP artisan route:clear
$PHP artisan view:clear
$PHP artisan event:clear
$PHP artisan migrate --force
$PHP artisan optimize
```

`migrate` debe mostrar 7 migraciones con `DONE`:

```
2026_10_22_000001_create_catalog_tables
2026_10_22_000002_create_products_and_plans_tables
2026_10_22_000003_create_promotions_tables
2026_10_22_000004_create_orders_and_billing_tables
2026_10_22_000005_create_licenses_tables
2026_10_22_000006_create_stripe_events_table
2026_10_22_100000_create_demo_notes_table
```

Nunca ejecutes `migrate:fresh`, `migrate:reset` ni `db:wipe`: borran la base
de datos. No se usa `optimize:clear` para no vaciar la caché de la
aplicación (contadores de intentos de acceso).

## 10. Permisos

```bash
cd $APP
find app config database lang modules resources routes public/build vendor/stripe vendor/composer -type f ! -perm 644 | head
find app config database lang modules resources routes public/build vendor/stripe vendor/composer -type d ! -perm 755 | head
ls -l .env            # Debe ser -rw------- (600)
```

Si los `find` muestran algo:

```bash
find app config database lang modules resources routes public/build vendor/stripe vendor/composer -type f -exec chmod 644 {} +
find app config database lang modules resources routes public/build vendor/stripe vendor/composer -type d -exec chmod 755 {} +
```

## 11. Configurar Stripe en modo de pruebas

Sin este paso todo funciona salvo el cobro: el catálogo y los planes se
gestionan, los planes gratuitos se contratan y los de pago muestran que los
pagos no están activados. **Usa solo claves de prueba** (`sk_test_`,
`pk_test_`) en staging.

### 11.1 Claves de API

En https://dashboard.stripe.com, activa **Modo de prueba** (interruptor
arriba a la derecha) → **Desarrolladores → Claves de API**. Copia:

- Clave publicable: `pk_test_...`
- Clave secreta: `sk_test_...` (pulsa «Revelar»)

### 11.2 Endpoint de webhooks

En modo de prueba → **Desarrolladores → Webhooks → Añadir destino** (o
«Añadir endpoint»):

- **URL:** `https://staging.nimiapps.com/stripe/webhook`
- **Versión de la API:** `2025-08-27.basil` si te deja elegirla. (No es
  crítico: NimiApps solo usa el aviso y vuelve a leer cada objeto de la API
  con esa versión.)
- **Eventos** (selecciona exactamente estos):

```
checkout.session.completed
checkout.session.async_payment_succeeded
checkout.session.async_payment_failed
checkout.session.expired
customer.subscription.created
customer.subscription.updated
customer.subscription.deleted
customer.subscription.paused
customer.subscription.resumed
invoice.paid
invoice.payment_failed
charge.refunded
refund.created
refund.updated
```

Guarda y copia el **secreto de firma** (`whsec_...`).

### 11.3 Portal de cliente

**Configuración → Facturación → Portal de clientes** (en modo de prueba):
pulsa **Guardar** una vez (puedes dejar las opciones por defecto). Sin este
paso, el botón «Métodos de pago y facturas» del panel da error.

### 11.4 Editar .env

Con el Administrador de archivos (o `nano $APP/.env`), añade al final:

```
STRIPE_SECRET=sk_test_...
STRIPE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_ALLOW_LIVE=false
```

Opcionales (valores por defecto): `STRIPE_AUTOMATIC_TAX=false`,
`STRIPE_TAX_ID_COLLECTION=true`, `NIMIAPPS_PAST_DUE_GRACE_DAYS=7`,
`NIMIAPPS_SUBSCRIPTION_GRACE_HOURS=72`. **No** pongas `STRIPE_API_BASE` en
el servidor (es solo para el simulador local; además se ignora con
`APP_ENV=production`).

Aplica los cambios:

```bash
cd $APP
$PHP artisan config:clear
$PHP artisan optimize
$PHP artisan microapps:check | sed -n '/Stripe/,/^$/p'
```

Debe decir «Modo de pruebas (test)», `[OK] Pagos activos`, la URL del
webhook y la versión de la API, sin mostrar ninguna clave.

## 12. Diagnóstico y fin del mantenimiento

```bash
cd $APP
$PHP artisan microapps:check
```

Debe mostrar `NimiApps 0.3.0 (ENT-003)` y terminar con
**«Resultado: instalación correcta»**. Ahora distingue tres niveles:

| Nivel        | Significado                                                       |
|--------------|-------------------------------------------------------------------|
| `[ERROR]`    | Hay que resolverlo antes de abrir la web.                         |
| `[AVISO]`    | Funciona, pero conviene revisarlo (SMTP, HTTPS, eventos fallidos...). |
| `[OPCIONAL]` | Algo no configurado que no impide funcionar (por ejemplo, Stripe). |

Después:

```bash
$PHP artisan up
sha256sum -c --quiet CHECKSUMS.sha256 && echo "INTEGRIDAD CORRECTA"
```

`CHECKSUMS.sha256` no incluye los dos `.htaccess` ni `bootstrap/cache/*.php`.

## 13. Primeros pasos en el panel

1. Entra con tu cuenta de administrador en
   https://staging.nimiapps.com/admin/comercial. El Resumen debe indicar
   modo **PRUEBAS**.
2. Sigue `MANUAL-ADMIN-COMERCIAL.md` para crear la ficha de la microapp de
   demostración (código `demo-licencias`), un producto, planes y precios, y
   publicarlos.
3. El módulo de demostración está **habilitado** para poder probar. Sin
   ficha publicada y licencia, nadie entra en `/apps/demo`. Antes de abrir
   el sitio al público, desactívalo: edita
   `modules/Demo/module.json` → `"enabled": false`, y ejecuta
   `config:clear`, `route:clear` y `optimize`. (Es un cambio local: el
   próximo `actualizar.sh` lo detectará como «Modificado localmente».)

## 14. Comprobaciones en el navegador

Mínimo imprescindible (la lista completa está en `PRUEBAS-ENT-003.md`, Parte B):

1. https://staging.nimiapps.com/estado devuelve `"version":"0.3.0"`.
2. Los usuarios y organizaciones de la 0.2.0 siguen entrando.
3. `/aplicaciones` muestra el catálogo (vacío hasta publicar algo).
4. Compra de prueba con la tarjeta `4242 4242 4242 4242`, fecha futura y
   cualquier CVC: el pedido pasa a «Completado», la microapp aparece en
   «Aplicaciones» y `/apps/demo` abre. En Stripe → Webhooks, los eventos
   aparecen con respuesta 200.
5. Una cuenta sin licencia recibe «No tienes acceso a esta aplicación».

## 15. Volver atrás

En todos los casos, pon antes la aplicación en mantenimiento
(`$PHP artisan down`).

### 15.1 Falló la copia de archivos (antes de migrar)

```bash
bash ~/nimiapps-respaldos/actualizacion-ent003-FECHA/restaurar-archivos.sh
```

Pide escribir `RESTAURAR`. Devuelve los archivos sustituidos (incluidos los
5 de `vendor/composer/`) y borra los archivos nuevos (incluido
`vendor/stripe/`). Pueden quedar carpetas vacías, que no afectan. Después:

```bash
cd $APP
$PHP artisan config:clear; $PHP artisan route:clear; $PHP artisan view:clear; $PHP artisan event:clear
$PHP artisan optimize
$PHP artisan microapps:check        # Debe decir 0.2.0 (ENT-002)
$PHP artisan up
```

### 15.2 Ya se ejecutaron las migraciones (deshacerlas)

Primero deshaz las 7 migraciones **con los archivos de la 0.3.0 todavía
instalados**, y después restaura los archivos:

```bash
cd $APP
$PHP artisan migrate:status | grep 2026_10_22     # Deben ser 7 y ser las últimas
$PHP artisan migrate:rollback --step=7 --force
bash ~/nimiapps-respaldos/actualizacion-ent003-FECHA/restaurar-archivos.sh
# y los comandos de caché, check y up de 15.1
```

Esto **borra las tablas de ENT-003** con su contenido (catálogo, pedidos,
pagos, licencias, eventos). Las cuentas, organizaciones y auditoría de la
0.2.0 se conservan. Si ya hubo cobros de prueba en Stripe, siguen en Stripe.

### 15.3 Restauración completa desde las copias del paso 5

```bash
cd /home/nimiapss/public_html
mv staging.nimiapps.com staging.nimiapps.com.fallida
tar -xzf ~/nimiapps-respaldos/archivos-antes-ent003-FECHA.tar.gz
```

Base de datos: borra las tablas de ENT-003 y carga la copia:

```bash
mysql -u NOMBRE_USUARIO_BD -p NOMBRE_BD -e "SET FOREIGN_KEY_CHECKS=0; DROP TABLE IF EXISTS demo_notes, stripe_events, license_assignments, licenses, payments, subscriptions, coupon_redemptions, orders, billing_customers, coupons, promotion_plan, promotions, prices, plan_capabilities, plans, product_microapp, products, capabilities, microapp_media, microapps, catalog_categories; SET FOREIGN_KEY_CHECKS=1;"
mysql -u NOMBRE_USUARIO_BD -p NOMBRE_BD < ~/nimiapps-respaldos/bd-antes-ent003-FECHA.sql
cd $APP
$PHP artisan microapps:check        # Debe decir 0.2.0 (ENT-002)
$PHP artisan up
```

Cuando todo funcione, guarda o borra `staging.nimiapps.com.fallida`
(contiene el `.env`: no la dejes dentro de `public_html`).

## 16. Errores frecuentes

| Síntoma                                                  | Causa y solución                                                              |
|----------------------------------------------------------|-------------------------------------------------------------------------------|
| `actualizar.sh`: «PHP ... es demasiado antiguo»          | `PHP=/opt/cpanel/ea-php83/root/usr/bin/php bash ...`                           |
| «Modificado localmente: vendor/composer/...»             | Se ejecutó Composer en el servidor. Consúltalo antes de seguir.               |
| `Class "Stripe\StripeClient" not found`                  | Falta `vendor/stripe` o no se copió `vendor/composer`. Repite el paso 8.      |
| Los planes de pago dicen que los pagos no están activados| Falta `STRIPE_SECRET` o no se hizo `config:clear` + `optimize` (11.4).        |
| `microapps:check`: «clave live» o «STRIPE_ALLOW_LIVE»    | En staging usa claves `sk_test_`.                                             |
| Stripe → Webhooks muestra 400                            | `STRIPE_WEBHOOK_SECRET` no corresponde a este endpoint. Cópialo de nuevo.     |
| Stripe → Webhooks muestra 503                            | Falta `STRIPE_SECRET` o `STRIPE_WEBHOOK_SECRET` en `.env`.                    |
| Stripe → Webhooks muestra 500                            | Error al procesar: mira `storage/logs/` y `/admin/comercial/eventos`; «Reprocesar». |
| Pagado en Stripe pero el pedido sigue pendiente          | Revisa los webhooks (arriba). La página de regreso también lo confirma al recargarla. |
| «Métodos de pago y facturas» da error                    | Guarda la configuración del portal de clientes (11.3).                        |
| Error 500 tras actualizar                                | `storage/logs/laravel-FECHA.log` y los comandos del paso 9.                   |

## 17. Antes de cobrar de verdad (modo real)

**No forma parte de esta entrega.** Cuando las pruebas de la Parte B estén
superadas:

1. Completar la cuenta de Stripe (datos fiscales, cuenta bancaria).
2. Revisar textos legales y condiciones de contratación.
3. Crear en modo real el mismo endpoint de webhooks con los mismos eventos.
4. En `.env`: claves `sk_live_`/`pk_live_`, el `whsec_` del endpoint real y
   `STRIPE_ALLOW_LIVE=true`. Después `config:clear` + `optimize`.
5. Decidir sobre Stripe Tax (`STRIPE_AUTOMATIC_TAX`) con la asesoría.
6. Desactivar el módulo de demostración.

Los objetos de Stripe (clientes, productos, precios) se crean de nuevo en
modo real; los de prueba no se mezclan.

## 18. Limpieza

Cuando hayas validado la versión:

```bash
rm -rf /home/nimiapss/nimiapps-v0.3.0-actualizacion
rm -f /home/nimiapss/nimiapps-v0.3.0-actualizacion.zip /home/nimiapss/nimiapps-v0.3.0-actualizacion.zip.sha256
```

Conserva `~/nimiapps-respaldos/` al menos hasta la siguiente entrega.
