Download the PHP package vnuswilliams/subscription-kpay without Composer
On this page you can find all versions of the php package vnuswilliams/subscription-kpay. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download vnuswilliams/subscription-kpay
More information about vnuswilliams/subscription-kpay
Files in vnuswilliams/subscription-kpay
Package subscription-kpay
Short Description Driver de paiement KPay (Mobile Money & Cartes) pour vnuswilliams/laravel-subscription
License MIT
Informations about the package subscription-kpay
Laravel Subscription — KPay Driver
Intégration KPay (Mobile Money & Cartes) pour vnuswilliams/laravel-subscription.
Ce package est un satellite de paiement, entièrement découplé du cœur du système d'abonnement. Il écoute les événements émis par laravel-subscription, déclenche le paiement via l'API KPay, et confirme ou suspend la souscription en fonction du résultat — sans jamais modifier la structure ou le comportement du package core.
Sommaire
- Philosophie & Architecture
- Prérequis
- Installation
- Configuration
- Préparation des Modèles
- Flux de paiement (bout en bout)
- Configuration du Webhook KPay
- Flux de retour (mode Gateway)
- Utilisation de l'API
- Middleware
- Événements (Laravel Events)
- Base de données
- Notes d'architecture importantes
- Licence
Philosophie & Architecture
laravel-subscription reste totalement agnostique au paiement : subscribeTo() crée une souscription active immédiatement, exactement comme si aucun package de paiement n'était installé. subscription-kpay n'ajoute aucune colonne, aucun statut d'enum, aucune méthode au core. Il se contente d'observer et de réagir, en s'appuyant uniquement sur l'API publique déjà exposée par le core (notamment suppress()).
Principe directeur : c'est à KPay de s'adapter au core, jamais l'inverse. Si demain un autre moyen de paiement doit être intégré (Stripe, PayPal...), il suivra exactement le même schéma : son propre package, sa propre table, ses propres events — sans jamais toucher à laravel-subscription.
Prérequis
- PHP
^8.2 - Laravel
^11.0 | ^12.0 | ^13.0 vnuswilliams/laravel-subscriptioninstallé et configuré, avec les colonnespriceprésentes sur les tablesplansetsubscriptions(voir son README)- Un compte marchand KPay actif (documentation officielle)
Installation
Publiez le fichier de configuration :
La commande kpay:publish-config est interactive : si un fichier config/kpay.php existe déjà, elle vous demandera confirmation avant de l'écraser. Si vous préférez la méthode non interactive, la commande legacy vendor:publish reste disponible :
Si la nouvelle commande artisan n'est pas trouvée après installation, exécutez :
Exécutez les migrations. Le package crée une seule table, kpay_transactions, sans toucher au schéma du core :
Configuration
Ajoutez vos clés KPay dans le fichier .env de votre application :
Note sur
KPAY_CURRENCY: l'API KPay ne prend pas de paramètrecurrencyà l'initiation du paiement — la devise réelle est déduite automatiquement par KPay selon l'opérateur/le pays (XAF,XOF,KES,ZMW...).KPAY_CURRENCYsert donc uniquement de valeur d'affichage et de stockage par défaut danskpay_transactions.currency, pas à un appel API. La valeur par défaut estXAF, cohérente avec la zone FCFA/Cameroun.
Le fichier config/kpay.php publié expose tous ces paramètres, plus :
| Clé | Description | Défaut |
|---|---|---|
timeout |
Timeout HTTP (secondes) des appels à l'API KPay | 10 |
webhook_route_prefix |
Chemin de la route webhook | kpay/webhook |
return_route_prefix |
Chemin de la route de retour (mode gateway) | kpay/return |
payment_pending_route |
Route de redirection si paiement non confirmé (contexte web) | home |
min_amount |
Montant minimum accepté par KPay (zone Cameroun), validé avant tout appel API | 50 |
Préparation des Modèles
Le modèle souscripteur (Company, User, Team, etc.) doit déjà utiliser HasSubscriptions du core. Ajoutez simplement HasKPayBilling par-dessus :
HasKPayBilling reste un proxy fin — aucune logique métier n'y vit, tout est délégué à KPayBillingService, conformément au pattern déjà en place dans le core.
Flux de paiement (bout en bout)
- Souscription —
$company->subscribeTo($plan)crée la souscription côté core (statutactive, comportement inchangé) et émetSubscriptionCreated. - Déclenchement — Le listener
InitiateKPayPaymentOnSubscriptionCreatedintercepte l'événement :- Si
subscription->price <= 0(plan gratuit / essai), rien ne se passe — aucun appel à KPay. - Si
subscription->priceest inférieur àconfig('kpay.min_amount'), l'appel est rejeté avant tout envoi à l'API (log + pas de transaction créée). - Sinon,
KPayBillingService::initiatePayment()appelle l'API KPay avec le montant exact desubscription->price(prix figé au moment de la souscription, indépendant du prix courant du plan) et crée une lignekpay_transactionsen statutpending, avecexternal_id= ID de la souscription.
- Si
- Paiement — L'utilisateur finalise le paiement côté KPay (USSD ou page hébergée selon
KPAY_DEFAULT_MODE). - Webhook — KPay notifie votre application de manière asynchrone (source d'autorité) :
payment.completed→ la transaction passe àsuccess,paid_atest renseigné, l'événementKPayPaymentCompletedest émis. La souscription reste telle quelle côté core.payment.failed→ la transaction passe àfailed, l'événementKPayPaymentFailedest émis, puissubscription->suppress()est appelé pour couper l'accès immédiatement.payment.cancelled→ la transaction passe àcancelled(statut distinct, pas confondu avecfailed), l'événementKPayPaymentCancelledest émis, puissubscription->suppress()est appelé.
Pas de suppression en base. À la différence d'une première version de cette architecture, ni la souscription ni la transaction ne sont supprimées en cas d'échec/annulation : on utilise
suppress()(déjà fourni par le core) qui coupe l'accès sans détruire les enregistrements. L'historique complet reste disponible danskpay_transactionspour l'audit, le support et le rapprochement comptable.Pas de tâche planifiée. Ce package ne fait aucune hypothèse sur un scheduler : toute la logique de confirmation/suspension repose exclusivement sur la réception du webhook.
Configuration du Webhook KPay
Dans votre dashboard KPay, configurez l'URL de callback vers :
La route est enregistrée automatiquement par le package et exemptée de la protection CSRF. La signature de chaque requête entrante est vérifiée via HMAC-SHA256 (en-tête X-KPAY-Signature, comparaison à temps constant) avant tout traitement — toute signature invalide renvoie 401 sans effet de bord.
Flux de retour (mode Gateway)
En mode gateway, après avoir finalisé (ou annulé) le paiement sur la page hébergée KPay, le client est redirigé vers KPAY_RETURN_URL avec des paramètres de requête signés :
Cette signature est distincte de celle du webhook (secret KPAY_RETURN_SECRET, format status|reference|externalId|ts) et comporte une fenêtre anti-replay de 10 minutes basée sur ts.
Comportement de la route kpay/return fournie par le package :
- Vérifie la signature et la fraîcheur du timestamp (
401si invalide ou expiré). - Effectue un
GET /api/v1/payments/{id}auprès de KPay pour confirmer l'état réel du paiement — le contenu de l'URL de retour n'est jamais considéré comme fiable à lui seul, seul le webhook (ou cette vérification active) fait foi. - Affiche une page adaptée selon le résultat :
- Paiement déjà confirmé par le webhook → page de succès.
- Paiement encore
pending/processing→ page d'attente (le webhook n'est pas encore arrivé), redirection possible versconfig('kpay.payment_pending_route'). - Paiement
failed/cancelled→ page d'échec/annulation.
Le webhook reste dans tous les cas la seule source qui déclenche les changements d'état en base ; la route de retour ne fait qu'informer l'utilisateur.
Utilisation de l'API
Vérifier si la souscription active est payée
Consulter l'historique des transactions
Récupérer la dernière transaction de la souscription active
Middleware
Le paiement étant confirmé de façon asynchrone (webhook), il existe une fenêtre entre la création de la souscription (déjà active côté core) et la confirmation KPay. Pour bloquer l'accès pendant cette fenêtre, empilez kpay.paid par-dessus le middleware subscribed du core :
Comportement :
- Requête JSON →
402 Payment Required - Requête web → redirection vers
config('kpay.payment_pending_route')avec un message flasherror
Une fois qu'un paiement échoue ou est annulé, la souscription est suspendue via
suppress()par le webhook — le middlewaresubscribedseul suffit alors à couper l'accès (il s'appuie surhasAccess(), qui tient compte de la suspension).kpay.paidsert uniquement à la fenêtre d'attente de confirmation, avant tout webhook.
Événements (Laravel Events)
| Événement | Déclenché quand | Payload |
|---|---|---|
KPayPaymentInitiated |
Le paiement vient d'être créé côté KPay | KPayTransaction $transaction |
KPayPaymentCompleted |
Le webhook confirme un paiement réussi | KPayTransaction $transaction |
KPayPaymentFailed |
Le webhook signale un échec | KPayTransaction $transaction, array $payload |
KPayPaymentCancelled |
Le webhook signale une annulation côté client | KPayTransaction $transaction, array $payload |
Exemple d'utilisation dans votre EventServiceProvider :
Base de données
Le package crée une seule table, indépendante du schéma du core :
kpay_transactions
| Colonne | Type | Description |
|---|---|---|
subscription_id |
unsignedBigInteger |
Référence applicative vers subscriptions (pas de contrainte FK — voir notes d'architecture) |
external_id |
string, unique |
Identifiant envoyé à KPay lors de l'initiation (= ID de la souscription), utilisé pour le rapprochement et l'idempotence côté init |
kpay_payment_id |
string, unique |
Identifiant du paiement côté KPay (id retourné à l'initiation) |
kpay_reference |
string, nullable |
Référence propre à KPay (ex: KPAY-20260514-ABC123), utile pour le support et le rapprochement comptable |
amount |
unsignedBigInteger |
Montant, copié depuis subscription->price au moment de l'initiation |
currency |
string(3) |
Devise déduite/affichée (XAF par défaut) |
status |
string |
pending | processing | success | failed | cancelled | expired |
raw_payload |
json, nullable |
Réponse brute de l'API / webhook, pour audit |
paid_at |
timestamp, nullable |
Renseigné à la confirmation du paiement |
Notes d'architecture importantes
- Aucune dépendance de schéma dure :
subscription_idn'est pas une clé étrangère contrainte, car le nom de la tablesubscriptionsest configurable côté core (config('subscriptions.table_names.subscriptions')). La cohérence est garantie applicativement, pas au niveau base de données. - Prix figé (snapshot) : le montant facturé provient toujours de
subscription->price, jamais deplan->price. Un changement de tarif sur un plan n'affecte donc jamais les souscriptions déjà créées. - Échec/annulation = suspension, pas de suppression : par choix assumé, une souscription dont le paiement échoue ou est annulé est suspendue via
suppress()(API publique du core), et sa transaction conserve son statut final (failedoucancelled) — aucune donnée n'est détruite, l'historique complet reste disponible pour l'audit et le support. - Statuts distincts pour échec et annulation :
failed(paiement refusé/erreur) etcancelled(abandon volontaire côté client) sont deux statuts et deux événements séparés, pour ne pas mélanger deux causes différentes dans les rapports/notifications. - Idempotence du webhook : une transaction déjà
success,failedoucancelledignore tout nouvel appel webhook — évite les doubles traitements en cas de retry côté KPay. - Plans gratuits ignorés :
subscription->price <= 0court-circuite entièrement l'appel à KPay dès le listener. - Montant minimum validé côté application :
subscription->priceinférieur àconfig('kpay.min_amount')(50 XAF par défaut, zone Cameroun) bloque l'initiation avant tout appel réseau. - Retour utilisateur vs webhook : la route de retour (mode gateway) vérifie sa propre signature (secret et format distincts du webhook) et interroge activement l'API KPay pour informer l'utilisateur — mais seul le webhook fait autorité pour modifier l'état en base.
Licence
Ce package est un logiciel à code source ouvert sous licence MIT.
All versions of subscription-kpay with dependencies
illuminate/support Version ^11.0|^12.0|^13.0
illuminate/database Version ^11.0|^12.0|^13.0
illuminate/http Version ^11.0|^12.0|^13.0
vnuswilliams/laravel-subscription Version ^1.0