PaymentApiController
extends AbstractController
in package
Contrôleur d'API de consultation des paiements.
Il expose l'historique des paiements rattachés à l'utilisateur authentifié : liste paginée et filtrable par statut, détail d'un paiement (avec la commande associée et les références Djomy), statistiques agrégées sur une période glissante et vérification du statut d'un paiement Djomy (la seule action pouvant valider un paiement, via MobilePaymentService). La création des paiements relève des tunnels d'abonnement et de commande, leur confirmation du webhook Djomy.
Préfixe de route : /api/payments. Toutes les actions exigent IS_AUTHENTICATED_FULLY
(jeton JWT bearerAuth).
Attributes
- #[Route]
- '/api/payments'
- $name: 'api_payments_'
- #[Tag]
- $name: 'Payments'
- $description: 'Gestion des paiements'
Table of Contents
Properties
- $entityManager : EntityManagerInterface
- $mobilePaymentService : MobilePaymentService
- $serializer : SerializerInterface
Methods
- __construct() : mixed
- list() : JsonResponse
- Retourne la liste paginée des paiements de l'utilisateur authentifié.
- show() : JsonResponse
- Retourne le détail d'un paiement.
- stats() : JsonResponse
- Retourne des statistiques agrégées sur les paiements de l'utilisateur.
- status() : JsonResponse
- Relit le statut d'un paiement Djomy et le valide si Djomy confirme le succès.
Properties
$entityManager
private
EntityManagerInterface
$entityManager
$mobilePaymentService
private
MobilePaymentService
$mobilePaymentService
$serializer
private
SerializerInterface
$serializer
Methods
__construct()
public
__construct(EntityManagerInterface $entityManager, SerializerInterface $serializer, MobilePaymentService $mobilePaymentService) : mixed
Parameters
- $entityManager : EntityManagerInterface
-
Gestionnaire d'entités Doctrine (injecté, non utilisé par les actions actuelles).
- $serializer : SerializerInterface
-
Sérialiseur Symfony (injecté ; les charges utiles sont construites à la main).
- $mobilePaymentService : MobilePaymentService
-
Relit le statut d'un paiement Djomy et le valide si besoin.
list()
Retourne la liste paginée des paiements de l'utilisateur authentifié.
public
list(Request $request, PaymentRepository $paymentRepository) : JsonResponse
Les résultats sont restreints à l'utilisateur courant et triés par created_at
décroissant. Le paramètre page est ramené à 1 au minimum et limit est borné
à l'intervalle [1, 50] (valeur par défaut 10) ; le filtre status n'est appliqué
que s'il est fourni et non vide, sans validation de la valeur transmise. Le nombre
total d'éléments est recalculé avec les mêmes critères pour produire le bloc de
pagination. Pour chaque paiement, la commande liée est aplatie en un sous-objet,
ou vaut null si aucune commande n'est rattachée.
Route : /api/payments (GET), nom api_payments_list. Requiert IS_AUTHENTICATED_FULLY.
Paramètres de requête : status (optionnel), page (optionnel, défaut 1),
limit (optionnel, défaut 10, plafonné à 50).
Réponses : 200 liste renvoyée (éventuellement vide), 401 requête non authentifiée.
Parameters
- $request : Request
-
Requête HTTP portant les paramètres de filtrage et de pagination.
- $paymentRepository : PaymentRepository
-
Dépôt utilisé pour la recherche et le comptage.
Attributes
- #[Get]
- $path: '/api/payments'
- $description: 'Récupère la liste des paiements de l\'utilisateur connecté'
- $summary: 'Liste les paiements de l\'utilisateur'
- $security: [['bearerAuth' => []]]
- $tags: ['Payments']
- $parameters: [new OA\Parameter(name: 'status', description: 'Filtrer par statut de paiement', in: 'query', required: false, schema: new OA\Schema(type: 'string', enum: ['PENDING', 'COMPLETED', 'ACCEPTED', 'REJECTED'])), new OA\Parameter(name: 'page', description: 'Numéro de page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 1)), new OA\Parameter(name: 'limit', description: 'Nombre d\'éléments par page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 10))]
- $responses: [new OA\Response(response: 200, description: 'Liste des paiements récupérée avec succès', content: new OA\JsonContent(properties: [new OA\Property(property: 'payments', type: 'array', items: new OA\Items(properties: [new OA\Property(property: 'id', type: 'integer', example: 1), new OA\Property(property: 'amount', type: 'string', example: '99.99'), new OA\Property(property: 'currency', type: 'string', example: 'GNF'), new OA\Property(property: 'status', type: 'string', example: 'COMPLETED'), new OA\Property(property: 'payment_method', type: 'string', example: 'DJOMY'), new OA\Property(property: 'provider', type: 'string', nullable: true, example: 'djomy'), new OA\Property(property: 'provider_reference', type: 'string', nullable: true, example: 'BCARD-PAY-42'), new OA\Property(property: 'created_at', type: 'string', format: 'date-time'), new OA\Property(property: 'order', properties: [new OA\Property(property: 'id', type: 'integer'), new OA\Property(property: 'total', type: 'string'), new OA\Property(property: 'status', type: 'string')], type: 'object')])), new OA\Property(property: 'pagination', properties: [new OA\Property(property: 'current_page', type: 'integer'), new OA\Property(property: 'total_pages', type: 'integer'), new OA\Property(property: 'total_items', type: 'integer'), new OA\Property(property: 'items_per_page', type: 'integer')], type: 'object')])), new OA\Response(response: 401, description: 'Non authentifié')]
- #[IsGranted]
- 'IS_AUTHENTICATED_FULLY'
- #[Route]
- ''
- $name: 'list'
- $methods: ['GET']
Return values
JsonResponse —Objet JSON {payments: list<array<string, mixed>>, pagination: array<string, int>}.
show()
Retourne le détail d'un paiement.
public
show(int $id, PaymentRepository $paymentRepository) : JsonResponse
Le paiement est chargé par sa clé primaire, puis un contrôle de propriété est
effectué : seul le titulaire du paiement, ou un porteur de ROLE_ADMIN, peut le
consulter. Le bloc order n'est construit que si une commande est rattachée.
{id} est contraint à des chiffres pour ne pas capter /stats.
Route : /api/payments/{id} (GET), nom api_payments_show. Requiert IS_AUTHENTICATED_FULLY.
Réponses : 200 paiement renvoyé, 403 paiement appartenant à un autre utilisateur (hors administrateur), 404 paiement inexistant, 401 requête non authentifiée.
Parameters
- $id : int
-
Identifiant du paiement, issu du chemin.
- $paymentRepository : PaymentRepository
-
Dépôt utilisé pour retrouver le paiement.
Attributes
- #[Get]
- $path: '/api/payments/{id}'
- $summary: 'Récupère un paiement par son ID'
- $description: 'Récupère les détails d\'un paiement spécifique'
- $tags: ['Payments']
- $security: [['bearerAuth' => []]]
- $parameters: [new OA\Parameter(name: 'id', description: 'ID du paiement', in: 'path', required: true, schema: new OA\Schema(type: 'integer'))]
- $responses: [new OA\Response(response: 200, description: 'Détails du paiement', content: new OA\JsonContent(properties: [new OA\Property(property: 'id', type: 'integer', example: 1), new OA\Property(property: 'amount', type: 'string', example: '99.99'), new OA\Property(property: 'currency', type: 'string', example: 'GNF'), new OA\Property(property: 'status', type: 'string', example: 'COMPLETED'), new OA\Property(property: 'payment_method', type: 'string', example: 'DJOMY'), new OA\Property(property: 'provider', type: 'string', nullable: true, example: 'djomy'), new OA\Property(property: 'provider_reference', type: 'string', nullable: true, example: 'BCARD-PAY-42'), new OA\Property(property: 'created_at', type: 'string', format: 'date-time'), new OA\Property(property: 'order', type: 'object', properties: [new OA\Property(property: 'id', type: 'integer'), new OA\Property(property: 'firstname', type: 'string'), new OA\Property(property: 'lastname', type: 'string'), new OA\Property(property: 'email', type: 'string'), new OA\Property(property: 'total', type: 'string'), new OA\Property(property: 'status', type: 'string'), new OA\Property(property: 'created_at', type: 'string', format: 'date-time')])])), new OA\Response(response: 404, description: 'Paiement non trouvé'), new OA\Response(response: 403, description: 'Accès refusé')]
- #[IsGranted]
- 'IS_AUTHENTICATED_FULLY'
- #[Route]
- '/{id}'
- $name: 'show'
- $requirements: ['id' => '\d+']
- $methods: ['GET']
Return values
JsonResponse —Objet JSON {id, amount, currency, status, payment_method, provider, provider_reference, created_at, order} ou message d'erreur.
stats()
Retourne des statistiques agrégées sur les paiements de l'utilisateur.
public
stats(Request $request, PaymentRepository $paymentRepository) : JsonResponse
La borne basse de la période est calculée à partir de l'instant courant : -1 week,
-1 year, ou -1 month par défaut (toute valeur inconnue de period retombe sur
le mois). Tous les paiements de l'utilisateur créés depuis cette borne sont chargés
via un QueryBuilder, puis agrégés en PHP : montant cumulé, comptages par statut
(COMPLETED, PENDING, et REJECTED compté dans failed_payments)
et montant moyen. Les montants sont formatés à deux décimales avec un point comme
séparateur, sans séparateur de milliers. La valeur period renvoyée est celle reçue,
même si elle n'a pas été reconnue.
Route : /api/payments/stats (GET), nom api_payments_stats. Requiert IS_AUTHENTICATED_FULLY.
Paramètres de requête : period (optionnel, week|month|year, défaut month).
Réponses : 200 systématiquement, 401 requête non authentifiée.
Parameters
- $request : Request
-
Requête HTTP portant le paramètre
period. - $paymentRepository : PaymentRepository
-
Dépôt utilisé pour construire la requête de période.
Attributes
- #[Get]
- $path: '/api/payments/stats'
- $summary: 'Statistiques des paiements'
- $description: 'Récupère les statistiques des paiements de l\'utilisateur'
- $tags: ['Payments']
- $security: [['bearerAuth' => []]]
- $parameters: [new OA\Parameter(name: 'period', description: 'Période pour les statistiques', in: 'query', required: false, schema: new OA\Schema(type: 'string', enum: ['week', 'month', 'year'], default: 'month'))]
- $responses: [new OA\Response(response: 200, description: 'Statistiques des paiements', content: new OA\JsonContent(properties: [new OA\Property(property: 'total_payments', type: 'integer', example: 25), new OA\Property(property: 'total_amount', type: 'string', example: '2499.75'), new OA\Property(property: 'completed_payments', type: 'integer', example: 23), new OA\Property(property: 'pending_payments', type: 'integer', example: 1), new OA\Property(property: 'failed_payments', type: 'integer', example: 1), new OA\Property(property: 'average_amount', type: 'string', example: '99.99'), new OA\Property(property: 'period', type: 'string', example: 'month')])), new OA\Response(response: 401, description: 'Non authentifié')]
- #[IsGranted]
- 'IS_AUTHENTICATED_FULLY'
- #[Route]
- '/stats'
- $name: 'stats'
- $methods: ['GET']
Return values
JsonResponse —Objet JSON {total_payments, total_amount, completed_payments, pending_payments, failed_payments, average_amount, period}.
status()
Relit le statut d'un paiement Djomy et le valide si Djomy confirme le succès.
public
status(int $id, PaymentRepository $paymentRepository) : JsonResponse
Le paiement doit appartenir à l'utilisateur authentifié (payment.user), sinon 404, y compris pour un
administrateur : l'endpoint peut valider un paiement et n'est donc pas ouvert aux paiements d'autrui.
La logique est celle de MobilePaymentService::checkStatus() : paiement COMPLETED renvoyé tel
quel ; paiement Djomy PENDING avec transaction relu chez Djomy, validé par
PaymentFulfillmentService::fulfill() (source api_status) si le statut est SUCCESS
et que la référence marchande désigne ce paiement ; FAILED ou CANCELLED donne FAILED sans rien
modifier ; sinon PENDING. Une erreur Djomy donne PENDING avec check_error à true, jamais un 500.
Route : /api/payments/{id}/status (GET), nom api_payments_status. Requiert IS_AUTHENTICATED_FULLY.
Réponses : 200 {success, data: {payment_id, status, subscription_status, order_status[, check_error]}},
401 non authentifié, 404 paiement inexistant ou appartenant à un autre utilisateur.
Parameters
- $id : int
-
Identifiant du paiement, issu du chemin.
- $paymentRepository : PaymentRepository
-
Dépôt utilisé pour retrouver le paiement de l'utilisateur.
Attributes
- #[Get]
- $path: '/api/payments/{id}/status'
- $summary: 'Vérifie le statut d\'un paiement Djomy'
- $description: 'Relit le statut chez Djomy et valide le paiement (abonnement, commande, carte) si Djomy confirme le succès'
- $tags: ['Payments']
- $security: [['bearerAuth' => []]]
- $parameters: [new OA\Parameter(name: 'id', description: 'ID du paiement', in: 'path', required: true, schema: new OA\Schema(type: 'integer'))]
- $responses: [new OA\Response(response: 200, description: 'Statut du paiement', content: new OA\JsonContent(properties: [new OA\Property(property: 'success', type: 'boolean', example: true), new OA\Property(property: 'data', properties: [new OA\Property(property: 'payment_id', type: 'integer', example: 42), new OA\Property(property: 'status', type: 'string', enum: ['COMPLETED', 'PENDING', 'FAILED'], example: 'PENDING'), new OA\Property(property: 'subscription_status', type: 'string', nullable: true, example: 'PENDING'), new OA\Property(property: 'order_status', type: 'string', nullable: true, example: null), new OA\Property(property: 'check_error', type: 'boolean', description: 'Présent (true) si Djomy n\'a pas pu être interrogé', example: true)], type: 'object')])), new OA\Response(response: 401, description: 'Non authentifié'), new OA\Response(response: 404, description: 'Paiement introuvable')]
- #[IsGranted]
- 'IS_AUTHENTICATED_FULLY'
- #[Route]
- '/{id}/status'
- $name: 'status'
- $requirements: ['id' => '\d+']
- $methods: ['GET']
Return values
JsonResponse —Statut du paiement, ou objet d'erreur 404.