Depannage et FAQ Technique
Guide de resolution des problemes courants rencontres lors du developpement, de l'integration et de l'exploitation de Scell.io. Chaque section suit le format : symptome, diagnostic, solution.
Erreurs d'Installation
Composer install echoue (extensions PHP manquantes)
Symptome : composer install echoue avec des erreurs du type ext-pgsql is missing ou ext-redis is missing.
Diagnostic : Laravel 12 et les dependances Scell.io requierent PHP 8.2+ avec plusieurs extensions.
Solution :
# Verifier la version PHP
php -v # Doit afficher 8.2+
# Installer les extensions requises (Ubuntu/Debian)
sudo apt install php8.2-pgsql php8.2-redis php8.2-xml php8.2-curl php8.2-mbstring php8.2-zip php8.2-gd php8.2-bcmath
# macOS (via Homebrew)
pecl install redis
pecl install pgsql
# Verifier les extensions chargees
php -m | grep -E "pgsql|redis|xml|curl|mbstring|zip|gd|bcmath"Si horstoeko/zugferd (generation Factur-X) echoue, verifier que ext-xml et ext-dom sont presents.
npm install echoue (version Node.js)
Symptome : Erreurs lors de npm install dans /frontend ou /superpdp-agent.
Diagnostic : Le frontend (Vite 7, React 19) necessite Node.js 18+. Le superpdp-agent necessite egalement Node.js 18+.
Solution :
# Verifier la version Node
node -v # Doit afficher 18+
# Installer via nvm (recommande)
nvm install 20
nvm use 20
# Relancer l'installation
cd frontend && rm -rf node_modules package-lock.json && npm install
cd superpdp-agent && rm -rf node_modules package-lock.json && npm installMigration echoue (connexion PostgreSQL)
Symptome : php artisan migrate retourne SQLSTATE[08006] could not connect to server ou FATAL: password authentication failed.
Diagnostic : Les parametres de connexion dans .env ne correspondent pas a la configuration PostgreSQL.
Solution :
# 1. Verifier que PostgreSQL tourne
sudo systemctl status postgresql
# 2. Verifier la connexion manuellement
psql -h 127.0.0.1 -U scell -d scell_dev
# 3. Verifier le .env
cat backend/.env | grep DB_
# Attendu :
# DB_CONNECTION=pgsql
# DB_HOST=127.0.0.1
# DB_PORT=5432
# DB_DATABASE=scell_dev
# DB_USERNAME=scell
# DB_PASSWORD=votre_mot_de_passe
# 4. Creer la base si elle n'existe pas
sudo -u postgres psql -c "CREATE DATABASE scell_dev OWNER scell;"
# 5. Pour le sandbox (base separee)
sudo -u postgres psql -c "CREATE DATABASE scell_sandbox OWNER scell;"Si les migrations fiscales echouent (tables fiscal_entries, fiscal_sequences), verifier que l'extension pgcrypto est activee :
CREATE EXTENSION IF NOT EXISTS pgcrypto;Redis non disponible
Symptome : Erreurs Connection refused sur les operations de cache, session ou queue. Les headers X-RateLimit-* ne s'affichent pas.
Diagnostic : Redis est utilise pour le cache (CACHE_STORE=redis), les sessions (SESSION_DRIVER=redis), les queues (QUEUE_CONNECTION=redis) et Horizon.
Solution :
# Verifier que Redis tourne
redis-cli ping # Doit retourner PONG
# Demarrer Redis
sudo systemctl start redis
# Verifier la connexion depuis PHP
php -r "echo (new Redis())->connect('127.0.0.1', 6379) ? 'OK' : 'ERREUR';"
# Verifier le .env
# REDIS_HOST=127.0.0.1
# REDIS_PORT=6379
# REDIS_PASSWORD=null (ou votre mot de passe)
# Fallback temporaire (dev uniquement - pas de Horizon)
# SESSION_DRIVER=file
# CACHE_STORE=file
# QUEUE_CONNECTION=syncErreurs d'Authentification
401 Unauthorized - Token expire ou cle API invalide
Symptome : L'API retourne 401 avec API_KEY_MISSING, API_KEY_INVALID ou Unauthenticated.
Diagnostic : Deux modes d'auth coexistent sur Scell.io :
- Token Sanctum (dashboard) :
Authorization: Bearer {token}-- expire apres la duree configuree dansSESSION_LIFETIME. - Cle API (API externe) :
X-API-Key: {cle}-- doit etre une cle active et non expiree. - Cle Tenant (multi-tenant) :
X-API-Key: sk_live_xxxouX-API-Key: sk_test_xxx.
Solution :
# Pour les cles API classiques
curl -H "X-API-Key: sk_live_xxxxxxxxxxxx" https://api.scell.io/api/v1/invoices
# Pour l'auth token Sanctum (dashboard)
curl -H "Authorization: Bearer 12|abc123token..." https://api.scell.io/api/v1/auth/me
# Pour les tenants
curl -H "X-API-Key: sk_live_YOUR_KEY" \
https://api.scell.io/api/v1/tenant/meVerifier que :
- La cle n'a pas ete revoquee (
is_active = truedans la tableapi_keysoutenants). - La cle n'est pas expiree (
expires_at IS NULLouexpires_at > NOW()). - L'environnement correspond : cle sandbox pour
/sandbox/*, cle production pour les autres routes.
403 Forbidden - Permissions insuffisantes ou tenant non autorise
Symptome : 403 avec KYC_REQUIRED, KYB_REQUIRED, TENANT_DISABLED ou API_KEY_ENVIRONMENT_MISMATCH.
Diagnostic : Plusieurs cas possibles :
- KYC/KYB non complete : Les routes production requierent une verification terminee.
- Environnement incorrect : Cle sandbox sur route production (ou inversement).
- Tenant desactive : Le champ
is_activeestfalse. - Permissions fiscales : Les scopes
fiscal:read,fiscal:write,fiscal:adminne sont pas configures.
Solution :
# Verifier le statut KYB d'un tenant
# En base : SELECT kyb_status, is_active FROM tenants WHERE id = 'xxx';
# Pour tester en sandbox (pas de KYB requis)
# Utiliser une cle sk_test_xxx au lieu de sk_live_xxx
# Verifier l'environnement de la cle
# Le prefixe determine l'environnement :
# sk_live_ / sk_live_ -> production (KYC/KYB requis)
# sk_test_ / sk_test_ -> sandbox (pas de KYC/KYB)Pour les permissions fiscales, verifier settings.fiscal_permissions du tenant :
// Par defaut (null) = acces complet
// Sinon, tableau de scopes autorises : ['fiscal:read', 'fiscal:write']
$tenant->settings['fiscal_permissions'] ?? null;Token Sanctum ne fonctionne pas
Symptome : Login reussit mais les requetes suivantes retournent Unauthenticated.
Diagnostic : Probleme de configuration Sanctum ou de domaine.
Solution :
# Verifier la config Sanctum
php artisan config:show sanctum
# Verifier que le domaine frontend est dans SANCTUM_STATEFUL_DOMAINS
# .env :
SANCTUM_STATEFUL_DOMAINS=localhost,localhost:5173,scell.io
# Vider le cache de config
cd backend && php artisan config:clear && php artisan cache:clearErreurs API
422 Validation Error - Champs manquants ou format incorrect
Symptome : 422 Unprocessable Entity avec un objet errors detaillant les champs invalides.
Diagnostic : Les Form Requests Laravel valident strictement les donnees entrantes. Les regles sont definies dans app/Http/Requests/.
Exemples courants :
// Creation de facture - champs obligatoires
{
"company_id": "uuid-requis",
"invoice_number": "FACT-2026-001",
"issue_date": "2026-01-15", // format: YYYY-MM-DD
"due_date": "2026-02-15",
"currency": "EUR",
"total_ht": 1000.00, // decimal, pas de string
"total_tax": 200.00,
"total_ttc": 1200.00,
"seller_siret": "12345678901234", // 14 chiffres exactement
"seller_name": "Ma Societe",
"buyer_siret": "98765432101234",
"buyer_name": "Client SARL"
}
// Erreur typique : seller_siret trop court
{
"errors": {
"seller_siret": ["Le champ seller_siret doit contenir exactement 14 caracteres."]
}
}Solution : Consulter les FormRequest correspondantes dans app/Http/Requests/ pour connaitre les regles exactes. Utiliser le sandbox pour tester les payloads.
429 Too Many Requests - Rate limiting
Symptome : 429 avec RATE_LIMIT_EXCEEDED et un header Retry-After.
Diagnostic : Les limites par defaut sont :
- API classique : 60 requetes/minute par cle API ou utilisateur.
- Tenant : Configurable via
TenantRateLimiter. - Sandbox : 1000 requetes/minute (relaxe pour les tests).
- Onboarding : 5 echanges de code/minute par IP.
Solution :
# Lire les headers de rate limiting dans la reponse
# X-RateLimit-Limit: 60
# X-RateLimit-Remaining: 0
# Retry-After: 42 (secondes avant reset)
# Attendre le temps indique par Retry-After
# Implementer un backoff exponentiel dans votre client
# Si vous avez besoin de limites plus elevees, contacter le support
# Les overrides sont stockes dans la table rate_limit_overrides500 Internal Server Error - Debugging
Symptome : 500 avec un message generique. Les details ne sont pas exposes au client en production.
Diagnostic : L'erreur est loguee dans backend/storage/logs/laravel.log.
Solution :
# Lire les derniers logs
tail -100 backend/storage/logs/laravel.log
# En developpement, activer le mode debug
# .env : APP_DEBUG=true (JAMAIS en production)
# Verifier les logs avec un filtre
grep "ERROR" backend/storage/logs/laravel.log | tail -20
# En production, utiliser Laravel Pail pour le streaming
cd backend && php artisan pailCauses frequentes de 500 :
- Variable d'environnement manquante (cle API externe, config S3).
- Service externe indisponible (OpenAPI.com, SuperPDP, INSEE).
- Timeout base de donnees sur des requetes lourdes.
- Extension PHP manquante apres un deploiement.
Timeout sur les appels SuperPDP
Symptome : Requetes de soumission de facture qui prennent plus de 30 secondes et finissent en timeout.
Diagnostic : Le service SuperPDP est externe avec un circuit breaker configure.
Solution :
# Verifier les parametres dans .env
SUPERPDP_TIMEOUT=30 # secondes
SUPERPDP_RETRY_TIMES=3 # nombre de tentatives
SUPERPDP_RETRY_SLEEP=1000 # ms entre les tentatives
SUPERPDP_CB_FAILURE_THRESHOLD=5 # seuil avant ouverture du circuit
SUPERPDP_CB_RECOVERY_TIMEOUT=60 # secondes avant re-essai
# Verifier l'etat du circuit breaker
# Le circuit s'ouvre apres 5 echecs consecutifs, puis re-essaie apres 60s
# En sandbox, les appels sont simules (MockSuperPDPService)
# Verifier : SUPERPDP_SANDBOX=trueSi le circuit breaker est ouvert, les appels retournent immediatement une erreur 503. Attendre le recovery_timeout ou redemarrer l'application.
Erreurs de Facturation
"Solde insuffisant" lors de la creation
Symptome : 402 Payment Required avec INSUFFICIENT_BALANCE.
Diagnostic : Chaque operation a un cout :
- Facture : 0.04 EUR (
Invoice::PRICE_PER_INVOICE) - Avoir : 0.04 EUR
- Signature : 1.20 EUR (
Signature::PRICE_PER_SIGNATURE)
Le middleware CheckBalance (API classique) ou TenantBalanceMiddleware (multi-tenant) verifie le solde avant l'operation.
Solution :
# Verifier le solde actuel
curl -H "X-API-Key: sk_live_xxx" https://api.scell.io/api/v1/tenant/balance
# Recharger via l'endpoint de top-up
curl -X POST -H "X-API-Key: sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{"amount": 50.00}' \
https://api.scell.io/api/v1/tenant/billing/top-up
# En sandbox, la verification de balance est desactivee
# Utiliser une cle sk_test_xxx pour tester sans fraisFormat Factur-X invalide
Symptome : Erreurs de validation lors de la generation du XML embarque dans le PDF.
Diagnostic : La generation Factur-X utilise horstoeko/zugferd. Les erreurs viennent generalement de donnees manquantes ou incorrectes.
Solution :
Champs obligatoires pour un Factur-X valide (profil BASIC) :
seller_siret: 14 chiffresseller_nameetseller_address: non videsbuyer_nameetbuyer_siret(oubuyer_address)total_ht,total_tax,total_ttc: coherents (total_ht + total_tax == total_ttc)issue_date: format ISO 8601currency: code ISO 4217 (EUR, USD...)
// Verifier la coherence des montants
if (abs($total_ht + $total_tax - $total_ttc) > 0.01) {
// Erreur : les montants ne sont pas coherents
}SIRET/TVA non reconnu
Symptome : Le SIRET ou numero de TVA est rejete lors de la verification.
Diagnostic : La verification utilise l'API INSEE (SIRET) avec authentification mTLS et la base VIES (TVA).
Solution :
# Verifier la configuration INSEE
# .env :
INSEE_API_URL=https://api.insee.fr/entreprises/sirene/V3.11
INSEE_CLIENT_ID=votre_client_id
INSEE_CERT_PATH=storage/certs/insee-client.pem
INSEE_KEY_PATH=storage/certs/insee-client.key
# Verifier que les certificats sont valides
openssl x509 -in backend/storage/certs/insee-client.pem -noout -dates
# En sandbox, utiliser les SIRET/TVA de test (config/sandbox.php)
# SIRET valides : 00000000000001, 00000000000002, 12345678901234
# Tout SIRET commencant par "000" est accepte
# TVA valides : FR00000000000, FR00123456789, DE000000000Facture bloquee en statut "pending"
Symptome : La facture reste en statut pending ou submitted indefiniment.
Diagnostic : Apres soumission, la facture est traitee de maniere asynchrone via un job (ProcessInvoice). Le changement de statut depend du webhook SuperPDP.
Solution :
# 1. Verifier l'etat des jobs
cd backend && php artisan horizon:status
# 2. Verifier les jobs echoues
php artisan queue:failed
# 3. Relancer un job echoue
php artisan queue:retry {job_id}
# 4. Verifier que le webhook SuperPDP est configure
# Le webhook doit pointer vers : https://api.scell.io/api/webhooks/superpdp
# 5. En sandbox, la progression est simulee automatiquement :
# submitted (2s) -> processing (3s) -> validated (5s) -> transmittedErreurs de Signature
Document trop volumineux
Symptome : Erreur lors de l'upload du document a signer.
Diagnostic : Les limites sont definies au niveau PHP, Nginx et de l'application.
Solution :
# Verifier les limites PHP (php.ini)
php -i | grep -E "upload_max_filesize|post_max_size"
# Recommande : upload_max_filesize = 20M, post_max_size = 25M
# Verifier la limite Nginx (nginx.conf)
# client_max_body_size 25m;
# Verifier la validation Laravel (StoreSignatureRequest)
# Le fichier doit etre un PDF de moins de 20 MoSignataire ne recoit pas le SMS OTP
Symptome : Le signataire ne recoit pas le code OTP par SMS.
Diagnostic : Les SMS sont envoyes via BulkGate. En sandbox, le code est toujours 123456.
Solution :
# Verifier la config BulkGate
# .env :
BULKGATE_APPLICATION_ID=votre_app_id
BULKGATE_APPLICATION_TOKEN=votre_token
BULKGATE_SENDER_ID=Scell.io
# Verifier le format du numero de telephone
# Format international requis : +33612345678 (pas 0612345678)
# Verifier les logs SMS
# Table sms_logs : phone, otp_code, sent_at, attempt_count
# En sandbox, le code OTP est toujours 123456
# Pas d'envoi SMS reel en sandboxSignature expiree
Symptome : Le signataire ne peut plus signer. L'API retourne signature_expired.
Diagnostic : Chaque demande de signature a une date d'expiration (expires_at). Passe ce delai, la signature est automatiquement marquee comme expiree.
Solution :
# Verifier la date d'expiration
curl -H "X-API-Key: sk_live_xxx" \
https://api.scell.io/api/v1/signatures/{id}
# Regarder le champ "expires_at"
# Creer une nouvelle demande de signature avec un delai plus long
# Le champ expires_at est optionnel ; par defaut, le systeme applique un delai standardErreur OpenAPI.com
Symptome : Erreurs 401, 403 ou 500 lors de la creation de signature.
Diagnostic : L'integration utilise OAuth2 avec OpenAPI.com. Les tokens expirent et doivent etre renouveles.
Solution :
# Verifier la configuration OAuth
# .env :
OPENAPI_BASE_URL=https://esignature.openapi.com
OPENAPI_SANDBOX_URL=https://test.esignature.openapi.com
OPENAPI_BEARER_TOKEN=votre_token
# Verifier les tokens dans la table openapi_tokens
# Regarder expires_at et rafraichir si necessaire
# En cas d'erreur persistante, verifier la config admin :
# Dashboard > Admin > OpenAPI Settings > Verify ConfigErreurs Fiscales (NF525)
Kill switch active par erreur
Symptome : 503 Service Unavailable avec fiscal_kill_switch_active sur toutes les operations d'ecriture fiscale.
Diagnostic : Le kill switch est un mecanisme d'urgence NF525 qui bloque toutes les ecritures fiscales (factures, avoirs, clotures). Les lectures restent accessibles.
Solution :
# Verifier le statut du kill switch
curl -H "X-API-Key: sk_live_xxx" \
https://api.scell.io/api/v1/tenant/fiscal/kill-switch/status
# Desactiver le kill switch (necessite le scope fiscal:admin)
curl -X POST -H "X-API-Key: sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{"reason": "Fausse alerte, desactivation apres verification"}' \
https://api.scell.io/api/v1/tenant/fiscal/kill-switch/deactivate
# L'activation/desactivation est tracee dans fiscal_audit_log
# Verifier qui l'a active : table fiscal_kill_switches, champs activated_by_*Important : La desactivation du kill switch requiert le scope fiscal:admin. Si votre cle API n'a que fiscal:read ou fiscal:write, vous recevrez un 403.
Cloture journaliere echouee
Symptome : La commande fiscal:daily-closing echoue ou ne s'execute pas.
Diagnostic : La cloture journaliere s'execute automatiquement via le scheduler Laravel (configurable via fiscal.daily_closing_time, par defaut 00:05). Elle produit une entree dans fiscal_closings.
Solution :
# Lancer manuellement une cloture journaliere
cd backend && php artisan fiscal:daily-closing
# Verifier que le scheduler fonctionne
php artisan schedule:list
# Verifier le cron
crontab -l
# Doit contenir : * * * * * cd /path/to/backend && php artisan schedule:run >> /dev/null 2>&1
# Via l'API (scope fiscal:write requis)
curl -X POST -H "X-API-Key: sk_live_xxx" \
https://api.scell.io/api/v1/tenant/fiscal/closings/dailyIntegrite de la chaine compromise
Symptome : La verification d'integrite signale des anomalies (anomalies_found > 0).
Diagnostic : Les ecritures fiscales forment une chaine cryptographique (SHA-256). Chaque entree contient un chain_hash qui depend du previous_hash. Si un maillon est altere, la chaine est rompue.
Solution :
# Lancer une verification d'integrite
curl -H "X-API-Key: sk_live_xxx" \
https://api.scell.io/api/v1/tenant/fiscal/integrity
# Verifier l'historique des anomalies
curl -H "X-API-Key: sk_live_xxx" \
https://api.scell.io/api/v1/tenant/fiscal/integrity/history
# Lancer la commande artisan de verification approfondie
cd backend && php artisan fiscal:integrity-check
# L'integrite est verifiee automatiquement chaque jour a 02:00 UTC
# Configurable dans config/fiscal.php : integrity_check.schedule_timeSi des anomalies sont detectees, NE JAMAIS modifier les ecritures fiscales directement en base. Les tentatives de modification sont bloquees par les traits d'immutabilite (LogsImmutabilityViolation) et enregistrees dans fiscal_audit_log.
Export FEC incomplet
Symptome : L'export FEC (Fichier des Ecritures Comptables) ne contient pas toutes les lignes attendues.
Diagnostic : L'export FEC filtre les ecritures par tenant et par periode. Le format par defaut est pipe (separateur |), encodage UTF-8.
Solution :
# Generer un export FEC
curl -H "X-API-Key: sk_live_xxx" \
"https://api.scell.io/api/v1/tenant/fiscal/fec?start_date=2026-01-01&end_date=2026-12-31" \
-o export-fec.txt
# Verifier que la periode couvre bien les ecritures souhaitees
# Les clotures creent des ecritures supplementaires (type "closing")
# Export forensique (plus detaille, pour audit)
curl -H "X-API-Key: sk_live_xxx" \
"https://api.scell.io/api/v1/tenant/fiscal/forensic-export" \
-o forensic-export.jsonErreurs Multi-Tenant
Tenant non trouve
Symptome : 401 avec INVALID_API_KEY lors des appels sur /v1/tenant/*.
Diagnostic : Le middleware TenantApiKeyMiddleware valide le format de la cle (sk_live_xxx ou sk_test_xxx, 32 caracteres alphanumeriques apres le prefixe) puis recherche le tenant.
Solution :
# Verifier le format de la cle
# Regex attendue : ^tk_(live|test)_[a-zA-Z0-9]{32}$
# Verifier que la cle est envoyee dans le bon header
curl -H "X-API-Key: sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
https://api.scell.io/api/v1/tenant/me
# Le header X-Tenant-Key est aussi accepte (alias)Isolation violation
Symptome : Impossible d'acceder aux ressources d'un sub-tenant, ou les donnees d'un autre tenant apparaissent.
Diagnostic : L'isolation est assuree par :
- Le trait
HasTenantScopesur les modeles fiscaux. - Le middleware
EnsureTenantIsolation(variable PostgreSQLapp.current_tenant_id). - Les scopes Eloquent
forTenant()etforSubTenant().
Solution :
# Verifier que le tenant_id est bien propage
# Dans les controllers tenant, le tenant est injecte via la requete :
# $tenant = $request->attributes->get('tenant');
# Pour debugger, activer le query log
DB::enableQueryLog();
// ... votre requete
dd(DB::getQueryLog());
// Verifier que WHERE tenant_id = 'xxx' est presentSub-tenant non autorise
Symptome : 403 ou 404 lors de l'acces a un sub-tenant.
Diagnostic : Le middleware SubTenantMiddleware verifie que le sub-tenant appartient bien au tenant authentifie.
Solution :
# Verifier l'appartenance du sub-tenant
curl -H "X-API-Key: sk_live_xxx" \
https://api.scell.io/api/v1/tenant/sub-tenants
# Le sub-tenant doit avoir tenant_id = le tenant authentifie
# Rechercher par external_id si necessaire :
curl -H "X-API-Key: sk_live_xxx" \
https://api.scell.io/api/v1/tenant/sub-tenants/by-external-id/EXT-001Onboarding bloque
Symptome : La session d'onboarding reste en statut in_progress ou documents_requested.
Diagnostic : Le flux d'onboarding necessite : verification SIRET -> verification TVA -> upload documents KYB -> completion.
Solution :
# Verifier le statut de la session
curl -H "X-API-Key: pk_xxx" \
https://api.scell.io/api/v1/onboarding/sessions/{session_id}
# Les etapes doivent etre completees dans l'ordre :
# 1. POST /v1/onboarding/verify-siret
# 2. POST /v1/onboarding/verify-vat
# 3. POST /v1/onboarding/documents (upload KYB)
# 4. POST /v1/onboarding/complete
# Verifier les timestamps dans la session :
# siret_verified_at, vat_verified_at, documents_submitted_at, completed_at
# Le code de verification expire (verification_code_expires_at)
# Si expire, il faut relancer une sessionErreurs de Queue/Jobs
Horizon ne demarre pas
Symptome : php artisan horizon echoue ou se termine immediatement.
Diagnostic : Horizon necessite Redis et l'extension pcntl.
Solution :
# Verifier Redis
redis-cli ping
# Verifier l'extension pcntl
php -m | grep pcntl
# Si absent : cette extension est dispo uniquement en CLI, pas en FPM
# Demarrer Horizon
cd backend && php artisan horizon
# En production (supervisor ou systemd)
# Creer un fichier /etc/supervisor/conf.d/horizon.conf :
# [program:horizon]
# command=php /home/ploi/api.scell.io/backend/artisan horizon
# user=ploi
# autostart=true
# autorestart=true
# redirect_stderr=true
# stdout_logfile=/home/ploi/api.scell.io/backend/storage/logs/horizon.log
# Verifier le dashboard Horizon
# URL : https://api.scell.io/horizon (necessite auth admin)Jobs en echec (failed_jobs)
Symptome : Les jobs s'accumulent dans failed_jobs. Les factures/signatures ne sont pas traitees.
Diagnostic : Les jobs principaux sont ProcessInvoice, ProcessSignature, SendWebhook, ProcessIncomingInvoiceWebhook, ProcessSuperPDPWebhook.
Solution :
# Lister les jobs echoues
cd backend && php artisan queue:failed
# Voir le detail d'un job echoue
php artisan queue:failed --id={uuid}
# Relancer un job specifique
php artisan queue:retry {uuid}
# Relancer tous les jobs echoues
php artisan queue:retry all
# Purger les jobs echoues (avec prudence)
php artisan queue:flush
# Causes frequentes d'echec :
# - Service externe indisponible (OpenAPI.com, SuperPDP)
# - Timeout depassé
# - Donnees invalides (payload corrompu)
# - Erreur de serialisation (modele supprime entre-temps)Webhooks non delivres
Symptome : Vos endpoints webhook ne recoivent pas les notifications.
Diagnostic : Les webhooks sortants sont envoyes via le job SendWebhook. Chaque tentative est loguee dans webhook_logs.
Solution :
# Verifier la configuration du webhook
curl -H "Authorization: Bearer {token}" \
https://api.scell.io/api/v1/webhooks
# Verifier les logs de livraison
curl -H "Authorization: Bearer {token}" \
https://api.scell.io/api/v1/webhooks/{id}/logs
# Tester manuellement la livraison
curl -X POST -H "Authorization: Bearer {token}" \
https://api.scell.io/api/v1/webhooks/{id}/test
# Verifier que votre endpoint :
# 1. Repond en HTTP 200 dans les 5 secondes
# 2. Est accessible publiquement (pas de firewall bloquant)
# 3. Accepte le Content-Type: application/json
# 4. Valide la signature HMAC (header X-Webhook-Signature)
# Le systeme effectue des retries avec backoff exponentiel :
# Configurable par webhook : retries, max_retries, backoff_multiplierDebug Tips
Activer le mode debug Laravel
# En developpement UNIQUEMENT
# .env : APP_DEBUG=true
# Recharger la config
cd backend && php artisan config:clear
# Les erreurs s'affichent maintenant en detail dans les reponses JSON
# ATTENTION : NE JAMAIS activer en production (fuite d'informations sensibles)Consulter les logs
# Logs Laravel (erreurs, requetes, jobs)
tail -f backend/storage/logs/laravel.log
# Streaming en temps reel avec Pail
cd backend && php artisan pail
# Filtrer par niveau
php artisan pail --filter="ERROR"
# Logs Horizon (queue, workers)
tail -f backend/storage/logs/horizon.logHorizon dashboard
Accessible a https://api.scell.io/horizon (authentification admin requise). Permet de voir :
- Les workers actifs et leur charge.
- Les jobs en attente, en cours, echoues.
- Les metriques de throughput et de latence.
- L'etat des queues par priorite.
Tester avec le sandbox
Le mode sandbox permet de tester l'integration sans frais et sans services externes reels.
# Utiliser une cle sandbox
# Format : sk_test_xxx (API classique) ou sk_test_xxx (tenant)
# Specifites du sandbox :
# - Pas de verification de balance
# - SIRET/TVA de test acceptes (voir config/sandbox.php)
# - Code OTP toujours 123456
# - Signatures auto-completees apres 10 secondes
# - Progression de statut simulee pour les factures
# - Rate limits relaxes (1000 req/min)
# - Pas d'appels reels vers OpenAPI.com ou SuperPDPFAQ Technique
Comment regenerer une cle API ?
# Pour un utilisateur (via le dashboard)
curl -X DELETE -H "Authorization: Bearer {token}" \
https://api.scell.io/api/v1/api-keys/{key_id}
curl -X POST -H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"name": "Ma nouvelle cle", "environment": "production"}' \
https://api.scell.io/api/v1/api-keys
# Pour un tenant
curl -X POST -H "X-API-Key: sk_live_xxx" \
https://api.scell.io/api/v1/tenant/regenerate-key
# ATTENTION : l'ancienne cle est immediatement invalidee.
# Sauvegarder la nouvelle cle retournee dans la reponse.Comment forcer une cloture fiscale ?
# Cloture journaliere manuelle (via API, scope fiscal:write)
curl -X POST -H "X-API-Key: sk_live_xxx" \
https://api.scell.io/api/v1/tenant/fiscal/closings/daily
# Cloture journaliere manuelle (via artisan)
cd backend && php artisan fiscal:daily-closing
# Cloture mensuelle
cd backend && php artisan fiscal:monthly-closing
# Les clotures sont idempotentes : relancer une cloture pour une date deja traitee
# ne cree pas de doublon.Comment migrer du sandbox vers la production ?
- Completer le KYB : Soumettre les documents requis (identite, K-bis, justificatif de domicile).
- Attendre la validation : Le statut KYB passe de
pendingaverified. - Generer une cle production : Creer une cle
sk_live_xxxousk_live_xxx. - Mettre a jour votre integration : Remplacer la cle sandbox par la cle production.
- Recharger le solde : En production, chaque operation est facturee.
# Verifier le statut KYB
curl -H "X-API-Key: sk_test_xxx" \
https://api.scell.io/api/v1/tenant/kyb/status
# Les donnees sandbox et production sont isolees.
# Les factures creees en sandbox ne migrent PAS vers la production.Comment debugger un webhook ?
# 1. Verifier la configuration
curl -H "Authorization: Bearer {token}" \
https://api.scell.io/api/v1/webhooks/{id}
# 2. Consulter les logs de livraison
curl -H "Authorization: Bearer {token}" \
https://api.scell.io/api/v1/webhooks/{id}/logs
# Chaque log contient : event_name, payload, status_code, response, attempt
# 3. Envoyer un test
curl -X POST -H "Authorization: Bearer {token}" \
https://api.scell.io/api/v1/webhooks/{id}/test
# 4. Verifier la signature HMAC cote recepteur
# Le header X-Webhook-Signature contient un HMAC SHA-256 du body
# Signe avec le secret du webhook
# Exemple de verification (Node.js) :
# const crypto = require('crypto');
# const signature = crypto.createHmac('sha256', webhookSecret)
# .update(rawBody)
# .digest('hex');
# if (signature !== receivedSignature) throw new Error('Invalid signature');
# 5. Regenerer le secret si compromis
curl -X POST -H "Authorization: Bearer {token}" \
https://api.scell.io/api/v1/webhooks/{id}/regenerate-secretContacts et Escalade
| Probleme | Canal |
|---|---|
| Bug API | GitHub Issues du projet |
| Urgence production | Equipe DevOps via Slack |
| Probleme facturation | support@scell.io |
| Conformite fiscale | legal@scell.io |