# Especificación del protocolo

Este documento proporciona la especificación técnica del Network-Agnostic Secure Payment Instruction Protocol (NASPIP) tal como lo implementan Fluxis y [naspip-go](https://github.com/fluxisus/naspip-go).

## Descripción general

NASPIP define un formato estandarizado para instrucciones de pago que pueden transmitirse y validarse de forma segura en cualquier red de pago. Los tokens son **PASETO v4 public** (firmados, no cifrados) — cualquiera con la clave pública del emisor puede verificar autenticidad e integridad del payload.

## Estructura de datos

### Formato del token NASPIP

Un token NASPIP es una cadena delimitada por punto y coma que envuelve un token PASETO v4 public:

```
naspip;{key_issuer};{key_id};v4.public.{paseto_token}
```

| Component | Description | Example |
| --------- | ----------- | ------- |
| Prefix | Identificador del protocolo | `naspip` |
| Key issuer (`kis`) | Entidad que emitió la clave de firma | `fluxis.us` |
| Key ID (`kid`) | Identificador de la clave de firma | `fluxis.qr.dyn.1` |
| PASETO token | Token PASETO v4 public que contiene el payload firmado | `v4.public.IhYyMDI...` |

El payload interno de PASETO usa claims estándar (`iss`, `sub`, `exp`, `iat`, `kid`, `kis`, `kep`) más un campo `data` que contiene instrucciones de pago o un payload URL.

### Esquemas de payload

NASPIP admite dos tipos de payload dentro del campo `data` del token PASETO.

#### Payload de instrucción (pago directo)

```json
{
  "payment": {
    "id": "180ede28-2968-4ac7-8e81-ca446f201949",
    "address": "0x1234567890abcdef1234567890abcdef12345678",
    "unique_asset_id": "npolygon_t0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
    "is_open": false,
    "amount": "49.99",
    "expires_at": 1759397652
  },
  "order": {
    "total": "49.99",
    "coin_code": "USD",
    "description": "Order description",
    "merchant": {
      "name": "Merchant #1",
      "description": "Merchant description"
    },
    "items": []
  }
}
```

#### Payload URL (checkout / instrucciones diferidas)

```json
{
  "url": "https://api.fluxis.us/v1/pos/{posID}/payment-request-checkout",
  "payment_options": ["npolygon_t0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"],
  "order": {
    "total": "49.99",
    "coin_code": "USD",
    "merchant": { "name": "Merchant #1" }
  }
}
```

Los códigos QR estáticos de PoS pueden omitir `payment_options`; las wallets llaman `POST /v1/naspip/read` y Fluxis resuelve las instrucciones obteniendo la URL cuando `payment_options` está ausente.

## Operaciones criptográficas

NASPIP usa **tokens PASETO v4 public** con claves Ed25519. Los payloads se codifican en protobuf antes de firmar. En Fluxis, use [naspip-go](https://github.com/fluxisus/naspip-go) o la REST API — no implemente Ed25519+SHA-256 crudo sobre JSON.

### Firma (create)

1. Construir `InstructionPayload` o `UrlPayload`
2. Codificar el payload como protobuf
3. Firmar con PASETO v4 usando la clave privada Ed25519 del emisor
4. Prefijar con `naspip;{kis};{kid};`

TTL predeterminado del token: **1 hora** para instrucciones de pago; **10 años** (`87600h`) para payloads solo URL.

### Verificación (read)

1. Dividir el token por `;` y validar el prefijo `naspip`
2. Resolver la clave pública por `kis` + `kid`
3. Verificar la firma PASETO v4 y los claims de expiración
4. Devolver `PasetoCompleteResult` con `payload.data` parseado

### Forma de respuesta de Fluxis `POST /v1/naspip/read`

```json
{
  "status": "success",
  "data": {
    "version": "v4",
    "purpose": "public",
    "footer": null,
    "payload": {
      "iss": "fluxis.us",
      "sub": "naspip",
      "exp": "2026-12-31T23:59:59.000Z",
      "iat": "2026-01-01T00:00:00.000Z",
      "kid": "fluxis.qr.dyn.1",
      "kis": "fluxis.us",
      "data": { "payment": { "...": "..." } }
    }
  }
}
```

::::warning Discrepancia en Swagger
OpenAPI documenta actualmente `data` como `PasetoV4PayloadData` plano (`url`, `payment`, `order`). La respuesta en runtime es `PasetoCompleteResult` como se muestra arriba. Consulte `NASPIP_ENHANCEMENTS.md` para la corrección planificada.
:::::

## Soporte de redes

Las instrucciones de pago referencian activos por **`unique_asset_id`** (UAI), no por nombre de red o chain ID. Fluxis admite múltiples redes — consulte [UAI](/es/docs/key-concepts/uai) para la lista completa de activos.

UAIs de ejemplo:

| Network | Asset | Example UAI |
| ------- | ----- | ----------- |
| Polygon | USDC | `npolygon_t0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359` |
| Base | USDC | `nbase_t0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |
| Avalanche | USDC | `navalanche_t0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E` |
| Avalanche | ARGt | `navalanche_t0x2E4e93eCA2E16E4989b894e188B7F7fC0175703B` |
| Arbitrum | USDC | `narbitrum_t0xaf88d065e77c8cC2239327C5EDb3A432268e5831` |
| Arbitrum | USDT | `narbitrum_t0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9` |

## Formato de código QR

Los tokens NASPIP se codifican en códigos QR como la **cadena de token cruda** (no una URI `naspip://`):

```
naspip;fluxis.us;fluxis.qr.dyn.1;v4.public.IhYyMDI...
```

### Especificaciones del código QR

- **Error Correction**: Level M (15% recovery)
- **Size**: Minimum 256x256 pixels
- **Format**: Standard QR Code (ISO/IEC 18004)

## Versionado

Los tokens NASPIP usan **PASETO v4** (`v4.public.*`). El prefijo delimitador por punto y coma es `naspip`. Los cambios incompatibles en esquemas de payload se gestionan mediante releases de naspip-go.

## Manejo de errores

### Códigos de error de la API Fluxis (relacionados con NASPIP)

| Code | HTTP | Description |
| ---- | ---- | ----------- |
| `MD0006` | 406 | Token NASPIP expirado |
| `GE0003` | 404 | Clave pública expirada |
| `MD0004` | 400 | Datos inválidos (p. ej. token o URL inválidos) |
| `PR0006` | 404 | No hay solicitud de pago activa (PoS caja; devuelto al resolver payload URL) |

### Formato de respuesta de error

```json
{
  "status": "error",
  "error": {
    "code": "MD0006",
    "message": "NASPIP token expired"
  }
}
```

## Consideraciones de seguridad

### Buenas prácticas

1. **Administración de claves**: Fluxis gestiona las claves de firma; los integradores verifican vía búsqueda de clave pública (`kis` + `kid`)
2. **Expiración del token**: Los tokens de instrucción de pago expiran tras 1 hora por defecto
3. **Validación de importes**: Valide importes en el lado del emisor y del receptor
4. **Verificación de activos**: Confirme que `unique_asset_id` coincide con la red y token esperados
5. **Verificación de firma**: Verifique siempre los tokens PASETO antes de procesar pagos

### Modelo de amenazas

NASPIP protege contra:

- **Manipulación de datos**: Las firmas PASETO v4 previenen modificaciones
- **Ataques de replay**: La expiración del token y el ciclo de vida de la solicitud de pago previenen reutilización
- **Suplantación**: La verificación de clave pública vía `kis` + `kid` garantiza autenticidad

## Directrices de implementación

### Campos requeridos (payload de instrucción)

- `payment.address` — dirección de destino
- `payment.unique_asset_id` — activo objetivo (UAI)
- `payment.amount` — importe del pago
- `payment.is_open` — si el importe es abierto

### Campos opcionales

- `payment.id` — identificador de solicitud de pago
- `payment.expires_at` — expiración timestamp Unix
- `order` — metadatos de comerciante y pedido

### Reglas de validación

1. El token debe parsearse como `naspip;{kis};{kid};v4.public.{paseto}`
2. La firma PASETO y la expiración deben ser válidas
3. La clave pública para `kis` + `kid` no debe estar expirada
4. `unique_asset_id` debe ser un UAI admitido

## Resolución de payload URL (Fluxis)

Cuando `POST /v1/naspip/read` recibe un token cuyo `payload.data` contiene una `url` no vacía **y** no `payment_options`:

1. Fluxis realiza un HTTP GET a esa URL
2. En caso de éxito, reemplaza `payload.data` con las instrucciones de checkout/pago obtenidas
3. En caso de fallo, devuelve `MD0004` o `PR0006` según corresponda

Si `payment_options` está presente, el token se devuelve tal cual y la wallet selecciona un activo antes de una llamada de checkout posterior.

## Endpoints de la API Fluxis

| Endpoint | Method | Auth | Description |
| -------- | ------ | ---- | ----------- |
| `/v1/naspip/read` | POST | Bearer + `x-fluxis-api-key` | Verificar token y devolver `PasetoCompleteResult` |
| `/v1/naspip/create` | POST | Bearer + `x-fluxis-api-key` | Crear token desde payload de instrucción o URL |

Consulte la [Implementation Guide](/es/docs/key-concepts/naspip/implementation-guide) para ejemplos curl.

## Referencias

- [NASPIP Protocol (GitHub)](https://github.com/fluxisus/naspip)
- [naspip-go library](https://github.com/fluxisus/naspip-go)
- [PASETO specification](https://paseto.io/)
- [ISO/IEC 18004 - QR Code](https://www.iso.org/standard/62021.html)
