Search by

wpay-bj / php-sdk

hkraservices

WPay PHP SDK -Vérification de transactions WebcoomPay

v1.0.3 2026-10-05 14:23 UTC

This package is auto-updated.

Last update: 2026-10-28 01:44:28 UTC


README

Latest Version PHP Version License

SDK PHP officiel pour l'API WPay - vérification de transactions, orders et webhooks.

Installation

composer require wpay-bj/php-sdk

Prérequis : PHP 8.1+ avec les extensions json et hash.

Configuration

Tout ce dont vous avez besoin pour démarrer :

use WPay\WPay;

WPay::setSecretKey($_ENV['WPay_SECRET_KEY']);

C'est tout. Le SDK cible la production par défaut.

Environnements

Chaque environnement regroupe l'URL de l'API et celle du modal de paiement.

WPay::useProduction();   // défaut
WPay::useSandbox();      // avec une clé sandbox (sk_test_xxx)
WPay::useLocal();        // API http://localhost:8000, modal http://localhost:3000

// API et modal ailleurs, ex. depuis un téléphone sur le même Wi-Fi
WPay::useLocal('http://192.168.1.20:8000', 'http://192.168.1.20:3000');

WPay::environment()->name;          // 'production' | 'sandbox' | 'local' | 'custom' (setBaseUrl)
WPay::environment()->apiUrl;
WPay::environment()->checkoutUrl;

HTTPS est obligatoire, sauf en local : HTTP est accepté uniquement pour localhost, *.test, *.localhost, 127.0.0.0/8 et les réseaux privés 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16. Toute autre adresse (publique, CGNAT, métadonnées cloud...) exige HTTPS : la secret key ne circule jamais en clair hors de votre réseau.

WPay::setBaseUrl() et WPay::getBaseUrl() restent disponibles mais sont dépréciés : utilisez WPay::useLocal() et WPay::environment()->apiUrl.

Variables d'environnement recommandées

# Obligatoires
WPay_SECRET_KEY=sk_live_xxxxxxxxxxxx
WPay_WEBHOOK_SECRET=whsec_xxxxxxxxxxxx

# Liens de paiement
WPay_PUBLIC_KEY=pk_live_xxxxxxxxxxxx

# Optionnel : production (défaut) | sandbox | local
WPay_ENV=production
match ($_ENV['WPay_ENV'] ?? 'production') {
    'sandbox' => WPay::useSandbox(),
    'local'   => WPay::useLocal(),
    default   => WPay::useProduction(),
};

🔒 Stockez toujours la secret key dans un .env (jamais en dur dans le code, jamais dans git).

Transactions

// Récupérer une transaction
$tx = WPay::transaction()->retrieve('01kmryyv98aw0mja47zp6h55tk');

$tx->status;              // 'init' | 'pending' | 'success' | 'failed' | 'free'
$tx->amount;              // montant marchand (float), hors frais
$tx->totalAmount;         // montant débité au client, frais inclus
$tx->payment->method;     // 'mtn-bj', 'moov-bj', 'celtiis', ...
$tx->payment->phone;
$tx->metadata;            // custom_metadata transmis au SDK JS
$tx->invoice->pdf;

// ✅ Vérification complète d'un paiement (statut + montant)
$valid = WPay::transaction()->verifyPayment($txId, expectedAmount: 5000);

// Vérifications séparées
$ok       = WPay::transaction()->isSuccessful($txId);
$amountOk = WPay::transaction()->verifyAmount($txId, 5000.00);

// Liste paginée
$list = WPay::transaction()->list([
    'status'   => 'success',
    'from'     => '2026-01-01',
    'per_page' => 20,
]);

Rattacher un paiement à votre commande

Passez votre référence dans custom_metadata côté SDK JS, puis vérifiez côté serveur le statut, le montant et la référence avant de valider la commande :

WPay.init({
  public_key: "pk_live_xxx",
  transaction: { amount: 5000, description: "Commande #42", custom_metadata: { order_id: "42" } },
  onComplete: (result) => fetch(`/orders/42/payment-confirmation`, {
    method: "POST",
    body: JSON.stringify({ transactionId: result.transaction_id }),
  }),
});
$tx = WPay::transaction()->retrieve($transactionId);

if ($tx->isValidPayment($order->amount) && $tx->belongsTo((string) $order->id)) {
    // ✅ Paiement confirmé pour cette commande
}

Ne validez jamais une commande sur la seule base du callback onComplete : vérifiez la transaction côté serveur ou attendez le webhook.

Liens de paiement

Créez la commande côté serveur et envoyez au client un lien qui ouvre le modal de paiement en pleine page (comme le QR code des ventes) : SMS, WhatsApp, e-mail, facture...

WPay::setSecretKey($_ENV['WPay_SECRET_KEY']);
WPay::setPublicKey($_ENV['WPay_PUBLIC_KEY']);   // pk_live_xxx, requise pour les liens de paiement

$link = WPay::paymentLink()->create([
    'amount'      => 5000,
    'description' => 'Commande #42',
    'metadata'    => ['order_id' => '42'],     // conservé sur la commande WPay
    'customer'    => ['firstname' => 'Jean', 'phone' => '0197000000'], // optionnel, pré-remplit le modal
]);

$link->url;            // https://app.webcoompay.com/modal?order=... (selon l'environnement)
$link->orderId;        // à conserver pour renvoyer le lien
$link->transactionId;  // à rapprocher du webhook
ParamètreRequisDescription
amountoui | Montant en FCFA (sauf si articles)
descriptionouiLibellé affiché au client
quantitynonQuantité (défaut : 1)
metadatanonDonnées libres, retournées dans le webhook
articlesnonArticles de votre catalogue : [['id' => '...', 'qty' => 1]]
customernonfirstname, lastname, email, phone

Renvoyer le lien d'une commande existante, sans en créer une nouvelle :

$url = WPay::paymentLink()->url($orderId);

Le paiement se confirme comme pour le SDK JS : webhook ou WPay::transaction()->retrieve(). Le moyen de paiement et les pays proposés sont ceux activés sur votre offre.

Webhooks - vérification de signature

use WPay\Exceptions\WebhookSignatureException;
use WPay\Resources\Webhook;

try {
    $event = Webhook::construct(
        file_get_contents('php://input'),
        $_SERVER['HTTP_X_WPAY_SIGNATURE'] ?? null,
        $_ENV['WPay_WEBHOOK_SECRET'],
    );
} catch (WebhookSignatureException $e) {
    http_response_code(400);
    exit;
}

if ($event->isSuccess() && $event->transaction?->isValidPayment($expectedAmount)) {
    $orderId = $event->metadata['order_id'] ?? null; // custom_metadata du SDK JS
    // ✅ Marquer la commande comme payée (de façon idempotente : le webhook peut être renvoyé)
}

http_response_code(200);

Avec Laravel, lisez le corps brut via $request->getContent() et l'en-tête via $request->header('X-WPay-Signature'), et excluez la route du contrôle CSRF.

Champs utiles de WebhookEvent : ref, status, amount, paymentMethod, paymentPhone, metadata, customer, order, transaction (TransactionObject), transactionId(), invoiceUrl().

Le SDK supporte deux formats de signature dans l'en-tête X-WPay-Signature :

FormatHeaderAnti-replay
Horodaté (recommandé)t=1715610000,v1=<hex_hmac>✅ rejette les requêtes > 5 min
Legacy<hex_hmac>❌

Exceptions

ExceptionCodeCause
AuthenticationException401/403Secret key invalide ou révoquée
NotFoundException404Ressource introuvable
WebhookSignatureException400Signature HMAC invalide, manquante ou expirée
WPayvariableAutre erreur (5xx, réseau, etc.)

Toutes héritent de WPay qui hérite elle-même de RuntimeException - un seul catch (WPay $e) capture tout.

Sécurité

  • ✅ HMAC SHA-256 avec hash_equals (timing-safe)
  • ✅ Anti-replay via timestamp signé (tolérance 5 min)
  • ✅ Vérification SSL forcée
  • ✅ Retry exponentiel sur erreurs réseau transitoires

Pour signaler une vulnérabilité : security@webcoompay.com

Licence

MIT - voir LICENSE.

Versionnage & mises à jour

Ce SDK suit le Semantic Versioning (MAJOR.MINOR.PATCH) :

  • MAJOR - changement non rétrocompatible (signature modifiée, comportement changé)
  • MINOR - nouvelle fonctionnalité, rétrocompatible
  • PATCH - correction de bug, aucun changement d'API

Mettre à jour le SDK dans votre projet

# Récupère la dernière version compatible avec votre contrainte actuelle
composer update wpay-bj/php-sdk

# Passer à une nouvelle version majeure (changement volontaire)
composer require wpay-bj/php-sdk:^2.0

Nous recommandons de fixer votre contrainte sur le MAJOR uniquement (^1.0) dans votre composer.json, pour recevoir automatiquement les correctifs et nouvelles fonctionnalités sans risque de casse :

"require": {
    "wpay-bj/php-sdk": "^1.0"
}

Voir les changements

Consultez CHANGELOG.md avant toute mise à jour majeure - les changements non rétrocompatibles y sont documentés avec un guide de migration.