Boutique
Cette section détaille le système de boutique permettant aux utilisateurs d'acheter des éléments cosmétiques (avatars, profils) avec leur monnaie virtuelle.
ShopController (shop.controller.ts)
Contrôleur REST gérant les endpoints de la boutique.
Propriétés
router: Router: Router Expressprivate readonly userService: UserService: Service utilisateur pour gérer la monnaie
Méthodes
constructor(private readonly userService: UserService)
Description : Initialise le contrôleur avec le service utilisateur.
Actions : Configure les routes REST
private configureRoutes(): void
Description : Configure les routes de la boutique.
Routes :
GET /check-funds/:itemId: Vérifier les fondsPOST /purchase: Acheter un item
private async checkFunds(req: AuthenticatedRequest, res: Response)
Description : Vérifie si l'utilisateur peut acheter un item.
Paramètres :
req.params.itemId: ID de l'item à vérifier
Validation :
- Utilisateur authentifié
- Item existe dans
SHOP_ITEMS
Réponse :
{
canAfford: boolean,
currentBalance: number,
itemPrice: number
}
Status codes :
200 OK: Vérification réussie401 UNAUTHORIZED: Non authentifié404 NOT_FOUND: Item ou utilisateur introuvable500 INTERNAL_SERVER_ERROR: Erreur serveur
private async purchaseItem(req: AuthenticatedRequest, res: Response)
Description : Effectue l'achat d'un item.
Body :
{ itemId: string }
Validations :
- Utilisateur authentifié
- Item existe
- Item pas déjà acheté (vérification
purchaseHistory) - Solde suffisant
Actions :
- Débit du montant via
userService.updateVirtualCurrencyBalance() - Ajout à l'historique via
userService.addPurchase() - Retour du nouveau solde
Réponse :
{
success: boolean,
message: string,
newBalance: number,
purchasedItem: string
}
Status codes :
200 OK: Achat réussi400 BAD_REQUEST: Item déjà acheté ou fonds insuffisants401 UNAUTHORIZED: Non authentifié404 NOT_FOUND: Item ou utilisateur introuvable500 INTERNAL_SERVER_ERROR: Erreur serveur
Items de la Boutique
Les items sont définis dans @common/shop-item (fichier partagé client/serveur).
Structure ShopItem
{
id: string, // ID unique (ex: 'avatar_cyberpunk')
name: string, // Nom affiché
description: string, // Description de l'item
price: number, // Prix en coins
type: 'avatar' | 'profile',
imageUrl: string // URL de l'image (asset)
}
Catalogue d'items (SHOP_ITEMS)
Avatars
| ID | Nom | Prix | Type |
|---|---|---|---|
avatar_cyberpunk |
Avatar Cyberpunk | 500 | avatar |
avatar_neon |
Avatar Neon | 750 | avatar |
avatar_futuristic |
Avatar Futuriste | 1000 | avatar |
Profils
| ID | Nom | Prix | Type |
|---|---|---|---|
profile_bronze |
Profil Bronze | 300 | profile |
profile_silver |
Profil Argent | 600 | profile |
profile_gold |
Profil Or | 900 | profile |
profile_diamond |
Profil Diamant | 1500 | profile |
Total : 7 items
Intégration avec UserService
Le système de boutique modifie les propriétés suivantes de User :
Propriétés modifiées
virtualCurrencyBalance: number: Solde de monnaie virtuelle (débité lors de l'achat)purchaseHistory: string[]: Liste des IDs d'items achetés
Méthodes utilisées
async updateVirtualCurrencyBalance(firebaseUid: string, newBalance: number)
Description : Met à jour le solde de monnaie virtuelle.
Paramètres :
firebaseUid: Firebase UID de l'utilisateurnewBalance: Nouveau solde
Retour : Promise<void>
async addPurchase(firebaseUid: string, itemId: string)
Description : Ajoute un item à l'historique d'achats.
Paramètres :
firebaseUid: Firebase UID de l'utilisateuritemId: ID de l'item acheté
Actions : Push de itemId dans purchaseHistory
Retour : Promise<void>
Flux d'achat complet
1. Vérification des fonds (optionnelle)
Client → GET /api/shop/check-funds/:itemId
Serveur → Vérifie solde et prix
Serveur → Retourne canAfford, currentBalance, itemPrice
2. Achat
Client → POST /api/shop/purchase { itemId }
Serveur → Validations:
- Item existe?
- Pas déjà acheté?
- Solde suffisant?
Serveur → Débit du solde
Serveur → Ajout à purchaseHistory
Serveur → Retourne success, newBalance, purchasedItem
3. Client met à jour l'interface
Client → Recharge le profil utilisateur
Client → Affiche nouveau solde
Client → Marque item comme possédé
Validations et gestion d'erreurs
Messages d'erreur
| Erreur | Code | Message |
|---|---|---|
| Non authentifié | 401 | "User not authenticated" |
| Utilisateur introuvable | 404 | "User not found" |
| Item introuvable | 404 | "Item not found" |
| Item déjà acheté | 400 | "Item already purchased" |
| Fonds insuffisants | 400 | "Insufficient funds" |
| ID manquant | 400 | "Item ID is required" |
| Erreur serveur | 500 | "Internal server error" |
Validation de l'achat
Le serveur effectue les validations suivantes dans l'ordre :
- Authentification : Vérification du token Firebase via
authMiddleware - Utilisateur existe : Récupération de
req.user.mongoUser - Item existe : Recherche dans
SHOP_ITEMS - Pas déjà acheté : Vérification dans
user.purchaseHistory - Solde suffisant : Comparaison
balance >= price - Transaction : Débit + ajout à l'historique
Sécurité
Authentification
- Middleware
authMiddlewaresur toutes les routes - Vérification token Firebase pour chaque requête
Validation côté serveur
- Tous les prix sont définis côté serveur (
SHOP_ITEMS) - Impossible de modifier le prix depuis le client
- Vérification d'achat multiple (via
purchaseHistory) - Validation du solde en temps réel
Transactions
- Pas de transaction MongoDB (opérations séquentielles)
- Rollback manuel en cas d'erreur
- Logs des erreurs pour debugging
Extensions possibles
Items dynamiques
Actuellement, les items sont statiques dans SHOP_ITEMS. Pour des items dynamiques :
- Stocker les items dans MongoDB
- Endpoint pour lister les items disponibles
- Admin panel pour gérer les items
Promotions
- Réductions temporaires
- Items en édition limitée
- Événements saisonniers
Historique d'achats détaillé
- Date d'achat
- Prix payé (si promotions)
- Métadonnées supplémentaires