tepuilabs / mini-meli
Genera access token para poder tener acceso a los recursos disponibles de Mercado libre
Fund package maintenance!
angelcruz.dev/donate
Requires
- php: ^8.3
- guzzlehttp/guzzle: ^7.9
Requires (Dev)
- laravel/pint: ^1.24
- pestphp/pest: ^3.8.2
- phpstan/extension-installer: ^1.3
- phpstan/phpstan: ^2.0
This package is auto-updated.
Last update: 2025-08-16 19:25:13 UTC
README
Librería completa para Mercado Libre con OAuth 2.0 PKCE, refresh tokens y gestión de aplicaciones. Implementa todas las mejores prácticas de seguridad y funcionalidades de la API oficial.
🚀 Características
- ✅ OAuth 2.0 PKCE - Autenticación segura con Proof Key for Code Exchange
- ✅ Refresh Tokens - Renovación automática de tokens con offline_access
- ✅ Multi-Site Support - Soporte para todos los sitios de Mercado Libre
- ✅ App Management - Gestión completa de aplicaciones y permisos
- ✅ Security First - Validación robusta y protección CSRF
- ✅ PHP 8.3+ - Aprovecha las últimas funcionalidades del lenguaje
- ✅ Type Safety - Tipado estricto y union types
- ✅ Readonly Properties - Inmutabilidad donde sea apropiado
- ✅ Match Expressions - Lógica más clara y eficiente
- ✅ Named Arguments - Mejor legibilidad del código
- ✅ First-class Callable Syntax - Sintaxis moderna para callbacks
- ✅ Improved Error Handling - Manejo de errores más específico
- ✅ Backward Compatibility - Compatible con versiones anteriores
📦 Instalación
composer require tepuilabs/mini-meli
⚙️ Configuración
Variables de Entorno
Agrega en tu archivo de configuración:
GRANT_TYPE=authorization_code CLIENT_ID=tu_client_id CLIENT_SECRET=tu_client_secret REDIRECT_URL=http://localhost:9000 SCOPES=read write offline_access
Note
Estos datos los debes configurar en Mercado Libre cuando crees una aplicación. Solo necesitas el client_id y client_secret.
🔐 Uso
1. Autenticación OAuth 2.0 PKCE
<?php use Tepuilabs\MeliServices\MeliConfig; use Tepuilabs\MeliServices\MeliServices; use Tepuilabs\MeliServices\MeliScopes; require 'vendor/autoload.php'; // Generar PKCE y state $pkce = MeliConfig::generatePkce(); $state = MeliConfig::generateState(); // Crear configuración $config = MeliConfig::forAuthorization( clientId: 'tu_client_id', clientSecret: 'tu_client_secret', redirectUri: 'http://localhost:9000', codeVerifier: $pkce['code_verifier'], codeChallenge: $pkce['code_challenge'], state: $state, scopes: MeliScopes::getOfflineAccess() // Incluye refresh tokens ); $meli = new MeliServices($config); // Generar URL de autorización $authUrl = $meli->getAuthorizationUrl('MLA'); // Argentina echo "Ve a: {$authUrl}";
2. Intercambio de Código por Token
// En tu callback $code = $_GET['code'] ?? ''; $state = $_GET['state'] ?? ''; // Verificar state para seguridad if ($state !== $savedState) { throw new Exception("State no coincide"); } $config = new MeliConfig( clientId: 'tu_client_id', clientSecret: 'tu_client_secret', code: $code, redirectUri: 'http://localhost:9000', codeVerifier: $savedCodeVerifier // De la sesión ); $meli = new MeliServices($config); $response = $meli->generateAccessToken(); // Guardar tokens $accessToken = $response->getAccessToken(); $refreshToken = $response->getRefreshToken(); $userId = $response->getUserId();
3. Refresh Tokens
// Renovar token cuando expire $response = $meli->refreshAccessToken($refreshToken); // Actualizar tokens $newAccessToken = $response->getAccessToken(); $newRefreshToken = $response->getRefreshToken(); // Siempre nuevo
4. Llamadas a la API
// Crear instancia para API calls $config = MeliConfig::forAuthorization( clientId: 'tu_client_id', clientSecret: 'tu_client_secret', redirectUri: 'http://localhost:9000' ); $meli = new MeliServices($config); // Hacer llamadas $userProfile = $meli->get('/users/me', $accessToken); $userItems = $meli->get("/users/{$userId}/items/search", $accessToken); $categories = $meli->get('/sites/MLA/categories', $accessToken);
5. Gestión de Aplicaciones
// Obtener detalles de la aplicación $appDetails = $meli->getApplicationDetails($accessToken, $appId); // Obtener aplicaciones autorizadas por el usuario $userApps = $meli->getUserApplications($accessToken, $userId); // Obtener usuarios que dieron permisos a tu app $appGrants = $meli->getApplicationGrants($accessToken, $appId); // Revocar autorización de un usuario $result = $meli->revokeUserAuthorization($accessToken, $userId, $appId);
🌍 Sitios Soportados
La librería soporta todos los sitios de Mercado Libre:
use Tepuilabs\MeliServices\MeliSites; // Sitios disponibles MeliSites::MLA; // Argentina MeliSites::MLB; // Brasil MeliSites::MLM; // México MeliSites::MLC; // Chile MeliSites::MCO; // Colombia MeliSites::MPE; // Perú MeliSites::MLU; // Uruguay MeliSites::MLV; // Venezuela // Obtener información del sitio $siteInfo = MeliSites::getSite('MLA'); $domain = MeliSites::getDomain('MLA'); $name = MeliSites::getName('MLA'); $flag = MeliSites::getFlag('MLA');
🔑 Scopes y Permisos
use Tepuilabs\MeliServices\MeliScopes; // Scopes disponibles MeliScopes::READ; // Solo lectura MeliScopes::WRITE; // Lectura y escritura MeliScopes::OFFLINE_ACCESS; // Incluye refresh tokens // Obtener scopes predefinidos $defaultScopes = MeliScopes::getDefault(); // read write $offlineScopes = MeliScopes::getOfflineAccess(); // read write offline_access // Validar scopes $isValid = MeliScopes::isValid('read'); $hasOffline = MeliScopes::hasOfflineAccess($scopes); $hasRead = MeliScopes::hasRead($scopes); $hasWrite = MeliScopes::hasWrite($scopes);
🛡️ Seguridad
PKCE (Proof Key for Code Exchange)
La librería implementa PKCE para prevenir ataques de interceptación de código:
// Generación automática $pkce = MeliConfig::generatePkce(); // code_verifier: string aleatorio de 32 bytes // code_challenge: hash SHA-256 del verifier, base64url encoded
State Protection
Protección CSRF con parámetros state aleatorios:
$state = MeliConfig::generateState(); // 16 bytes aleatorios
Validación Robusta
// Validación automática de parámetros $config = new MeliConfig( clientId: $clientId, clientSecret: $clientSecret, code: $code, redirectUri: $redirectUri, codeVerifier: $codeVerifier ); if (!$config->isValid()) { throw new Exception("Configuración inválida"); }
📚 API Reference
MeliServices
Métodos Estáticos
fromArray(array $params): self
- Crear desde arrayfromEnvironment(): self
- Crear desde variables de entorno
Métodos de Instancia
generateAccessToken(): MeliResponse
- Generar tokenrefreshAccessToken(string $refreshToken): MeliResponse
- Renovar tokengetAuthorizationUrl(string $site, array $params = []): string
- Generar URL de autorizaciónget(string $endpoint, string $accessToken): array
- GET requestpost(string $endpoint, string $accessToken, array $data = []): array
- POST requestput(string $endpoint, string $accessToken, array $data = []): array
- PUT requestdelete(string $endpoint, string $accessToken): array
- DELETE requestgetApplicationDetails(string $accessToken, string $appId): array
- Detalles de appgetUserApplications(string $accessToken, string $userId): array
- Apps del usuariogetApplicationGrants(string $accessToken, string $appId): array
- Usuarios conectadosrevokeUserAuthorization(string $accessToken, string $userId, string $appId): array
- Revocar autorización
MeliConfig
Métodos Estáticos
fromArray(array $params): self
- Crear desde arrayfromEnvironment(): self
- Crear desde variables de entornoforAuthorization(...): self
- Crear para URLs de autorizacióngeneratePkce(): array
- Generar PKCEgenerateState(): string
- Generar state
Métodos de Instancia
toArray(): array
- Convertir a arrayisValid(): bool
- Verificar si es válidohasPkce(): bool
- Verificar si tiene PKCEhasState(): bool
- Verificar si tiene statehasRefreshToken(): bool
- Verificar si tiene refresh tokenisForTokenExchange(): bool
- Verificar si es para intercambiogetScopesString(): string
- Obtener scopes como stringhasOfflineAccess(): bool
- Verificar offline accesshasReadPermission(): bool
- Verificar permiso de lecturahasWritePermission(): bool
- Verificar permiso de escritura
MeliResponse
Propiedades
data: array
- Datos de la respuestastatusCode: int
- Código de estado HTTP
Métodos
getAccessToken(): ?string
- Obtener access tokengetRefreshToken(): ?string
- Obtener refresh tokengetTokenType(): ?string
- Obtener tipo de tokengetExpiresIn(): ?int
- Obtener tiempo de expiracióngetScope(): ?string
- Obtener scopegetUserId(): ?int
- Obtener ID de usuariohasAccessToken(): bool
- Verificar si tiene access tokenhasRefreshToken(): bool
- Verificar si tiene refresh tokentoArray(): array
- Convertir a arraytoJson(): string
- Convertir a JSONisSuccessful(): bool
- Verificar si la respuesta es exitosagetErrorMessage(): ?string
- Obtener mensaje de errorgetErrorDescription(): ?string
- Obtener descripción del error
MeliScopes
Constantes
READ
- Permiso de lecturaWRITE
- Permiso de escrituraOFFLINE_ACCESS
- Permiso offline (refresh tokens)
Métodos Estáticos
getAll(): array
- Obtener todos los scopesgetDefault(): array
- Obtener scopes por defectogetOfflineAccess(): array
- Obtener scopes con offline accessisValid(string $scope): bool
- Validar scopevalidateScopes(array $scopes): bool
- Validar múltiples scopestoString(array $scopes): string
- Convertir a stringtoArray(string $scopes): array
- Convertir a arrayhasOfflineAccess(array|string $scopes): bool
- Verificar offline accesshasRead(array|string $scopes): bool
- Verificar lecturahasWrite(array|string $scopes): bool
- Verificar escritura
MeliSites
Constantes
MLA
- ArgentinaMLB
- BrasilMLM
- MéxicoMLC
- ChileMCO
- ColombiaMPE
- PerúMLU
- UruguayMLV
- Venezuela
Métodos Estáticos
getAll(): array
- Obtener todos los sitiosgetSite(string $siteId): ?array
- Obtener información del sitiogetDomain(string $siteId): string
- Obtener dominiogetName(string $siteId): string
- Obtener nombregetFlag(string $siteId): string
- Obtener banderaisValid(string $siteId): bool
- Validar sitiogetAuthorizationUrl(string $siteId): string
- Obtener URL de autorizacióngetApiUrl(): string
- Obtener URL base de la APIgetOAuthTokenEndpoint(): string
- Obtener endpoint de tokens
🚨 Manejo de Errores
La librería incluye manejo de errores específico:
try { $response = $meli->generateAccessToken(); } catch (GenericException $e) { echo "Error: " . $e->getMessage(); echo "Código: " . $e->getCode(); }
Tipos de Error
- 400 - Solicitud inválida
- 401 - Credenciales inválidas
- 403 - Acceso denegado
- 404 - Endpoint no encontrado
- 429 - Demasiadas solicitudes
- 5xx - Error del servidor
Errores Específicos de OAuth
- invalid_client - Client ID o Secret inválidos
- invalid_grant - Código o refresh token inválido/expirado
- invalid_scope - Scope inválido
- invalid_request - Parámetros faltantes o inválidos
- unsupported_grant_type - Grant type no soportado
- forbidden - Acceso denegado
- local_rate_limited - Demasiadas solicitudes
- unauthorized_client - Cliente no autorizado
- unauthorized_application - Aplicación bloqueada
🧪 Testing
# Ejecutar tests composer test # Ejecutar tests con coverage composer test-coverage # Formatear código composer format
📝 Ejemplo Completo
<?php use Tepuilabs\MeliServices\Exceptions\GenericException; use Tepuilabs\MeliServices\MeliConfig; use Tepuilabs\MeliServices\MeliServices; use Tepuilabs\MeliServices\MeliScopes; require 'vendor/autoload.php'; session_start(); // Configuración $clientId = 'tu_client_id'; $clientSecret = 'tu_client_secret'; $redirectUri = 'http://localhost:9000'; // Paso 1: Generar URL de autorización if (!isset($_GET['code'])) { $pkce = MeliConfig::generatePkce(); $state = MeliConfig::generateState(); $_SESSION['code_verifier'] = $pkce['code_verifier']; $_SESSION['state'] = $state; $config = MeliConfig::forAuthorization( clientId: $clientId, clientSecret: $clientSecret, redirectUri: $redirectUri, codeVerifier: $pkce['code_verifier'], codeChallenge: $pkce['code_challenge'], state: $state, scopes: MeliScopes::getOfflineAccess() ); $meli = new MeliServices($config); $authUrl = $meli->getAuthorizationUrl('MLA'); echo "Ve a: {$authUrl}"; exit; } // Paso 2: Intercambiar código por token try { $code = $_GET['code']; $state = $_GET['state']; // Verificar state if ($state !== $_SESSION['state']) { throw new Exception("State no coincide"); } $config = new MeliConfig( clientId: $clientId, clientSecret: $clientSecret, code: $code, redirectUri: $redirectUri, codeVerifier: $_SESSION['code_verifier'] ); $meli = new MeliServices($config); $response = $meli->generateAccessToken(); // Guardar tokens $_SESSION['access_token'] = $response->getAccessToken(); $_SESSION['refresh_token'] = $response->getRefreshToken(); $_SESSION['user_id'] = $response->getUserId(); echo "¡Autenticación exitosa!"; } catch (GenericException $e) { echo "Error: " . $e->getMessage(); }
🤝 Contribuir
- Fork el proyecto
- Crea una rama para tu feature (
git checkout -b feature/AmazingFeature
) - Commit tus cambios (
git commit -m 'Add some AmazingFeature'
) - Push a la rama (
git push origin feature/AmazingFeature
) - Abre un Pull Request
📄 Licencia
Este proyecto está bajo la Licencia MIT. Ver el archivo LICENSE.md para más detalles.