PSLWallet API v1
Intégrez les paiements USD dans votre plateforme. Simple, sécurisé, rapide.
Version 1.0
Devise : USD
REST / JSON
OTP Email
Base URL
https://pslwallet.com/pslwallet/api/v1
Authentification
Toutes les requêtes (sauf /health) nécessitent votre clé API dans le header HTTP :
HTTP HeaderX-API-Key: votre_api_key_ici
Ou via Bearer token :
HTTP HeaderAuthorization: Bearer votre_api_key_ici
⚠️ Ne jamais exposer votre clé API dans du code frontend JavaScript côté client. Faites toujours les appels depuis votre serveur backend.
Mode TEST / LIVE
Deux modes disponibles pour développer et tester sans risque.
| Mode | Comment activer | Comportement |
|---|---|---|
| LIVE | 5364b6aaec51f74c... | Vrai débit USD sur le solde du client |
| TEST | test_5364b6aaec51f74c... | Simulation — aucun débit réel |
💡 En mode TEST, les références commencent par PSL-TEST- et les transactions sont enregistrées avec mode=test.
Ajouter le préfixe test_ devant votre clé API pour activer le mode TEST.
Ajouter le préfixe test_ devant votre clé API pour activer le mode TEST.
Flux de paiement
① Votre site
→
POST /initiate
→
② Reçoit order_id + payment_url
→
③ Redirige le client
→
④ Client paie + OTP
→
⑤ Webhook → votre site
① Votre site appelle /payment/initiate → reçoit order_id + payment_url
② Votre site sauvegarde order_id + reference en base, puis redirige le client vers payment_url
③ Le client se connecte à PSLWallet, reçoit un OTP par email et confirme le paiement
④ PSLWallet envoie le webhook à votre webhook_url avec order_id + tx_id
⑤ Votre site reçoit le webhook → identifie la commande par order_id → débloque l'accès
② Votre site sauvegarde order_id + reference en base, puis redirige le client vers payment_url
③ Le client se connecte à PSLWallet, reçoit un OTP par email et confirme le paiement
④ PSLWallet envoie le webhook à votre webhook_url avec order_id + tx_id
⑤ Votre site reçoit le webhook → identifie la commande par order_id → débloque l'accès
Endpoints
GET
/health
Vérifier l'état de l'API — sans authentification
curlcurl https://pslwallet.com/pslwallet/api/v1/health
Réponse 200{ "success": true, "status": "ok", "api": "PSLWallet v1", "mode": "live", "db": "connected" }
POST
/payment/initiate
Créer une demande de paiement
Paramètres Body JSON
| Champ | Type | Statut | Description |
|---|---|---|---|
| amount | float | requis | Montant en USD — ex: 25.00 |
| description | string | requis | Description du paiement |
| customer_email | string | requis | Email du client PSLWallet |
| order_id | string | optionnel | Votre référence commande — retournée dans le webhook. Si absent, PSLWallet génère automatiquement. |
| redirect_url | string | optionnel | URL de retour après paiement |
| webhook_url | string | optionnel | Surcharge le webhook de votre compte partenaire |
| metadata | object | optionnel | Données libres retournées dans le webhook — product_id, user_id, etc. |
| expires_in | int | optionnel | Expiration en minutes — défaut : 30 |
curlcurl -X POST https://pslwallet.com/pslwallet/api/v1/payment/initiate \ -H "X-API-Key: votre_api_key" \ -H "Content-Type: application/json" \ -d '{ "amount": 25.00, "description": "Commande #1042 — MonSite", "customer_email": "client@email.com", "order_id": "CMD-1042", "redirect_url": "https://monsite.com/confirm", "metadata": { "product_id": "42", "user_id": "789" } }'
Réponse 201{ "success": true, "order_id": "CMD-1042", // votre order_id — à sauvegarder "reference": "PSL-71F9B1C08DA0EA84", // référence interne PSLWallet "payment_url": "https://pslwallet.com/pslwallet/pay/PSL-71F9B1C08DA0EA84", "amount": 25.00, "currency": "USD", "description": "Commande #1042 — MonSite", "status": "pending", "mode": "live", "partner": "Solisyon", "customer_email": "client@email.com", "expires_at": "2026-03-16T21:30:00+00:00", "created_at": "2026-03-16T21:00:00+00:00", "webhook_url": "https://monsite.com/webhook/pslwallet", "customer": { "name": "Jean Dupont", "has_account": true, "balance": 100.00, "can_pay": true } }
⚠️ Important : Sauvegarder order_id et reference en base de données immédiatement après avoir reçu la réponse, avant de rediriger le client.
GET
/payment/status
Vérifier le statut — par order_id ou reference
Deux façons d'interroger — par order_id (votre référence) ou par reference PSLWallet :
Par order_id — recommandécurl "https://pslwallet.com/pslwallet/api/v1/payment/status?order_id=CMD-1042" \ -H "X-API-Key: votre_api_key"
Par reference PSLWalletcurl "https://pslwallet.com/pslwallet/api/v1/payment/status?ref=PSL-71F9B1C08DA0EA84" \ -H "X-API-Key: votre_api_key"
Statuts possibles
pending
completed
failed
expired
refunded
GET
/payment/verify/{ref}
Vérifier par référence dans l'URL
curlcurl https://pslwallet.com/pslwallet/api/v1/payment/verify/PSL-71F9B1C08DA0EA84 \ -H "X-API-Key: votre_api_key"
POST
/payment/refund
Rembourser un paiement completed
| Champ | Type | Statut | Description |
|---|---|---|---|
| order_id | string | ou reference | Votre order_id passé lors de /initiate |
| reference | string | ou order_id | Référence PSLWallet — PSL-... |
| reason | string | optionnel | Motif du remboursement |
curlcurl -X POST https://pslwallet.com/pslwallet/api/v1/payment/refund \ -H "X-API-Key: votre_api_key" \ -H "Content-Type: application/json" \ -d '{ "order_id": "CMD-1042", "reason": "Client annulé" }'
GET
/balance?email=...
Vérifier votre propre solde USD
⚠️ Accès restreint : Vous ne pouvez consulter que le solde du compte associé à votre clé API. Toute tentative de vérifier un autre email retourne 403 FORBIDDEN.
curlcurl "https://pslwallet.com/pslwallet/api/v1/balance?email=votre@email.com" \ -H "X-API-Key: votre_api_key"
Réponse 200{ "success": true, "has_account": true, "customer_name": "Jean Dupont", "balance": 100.00, "pending_holds": 0.00, "available": 100.00, "currency": "USD", "can_pay": true }
Réponse 403 — email différent du compte partenaire{ "success": false, "error": { "code": "FORBIDDEN", "message": "Vous ne pouvez consulter que le solde de votre propre compte." } }
Codes d'erreur
Toutes les erreurs retournent ce format JSON avec le code HTTP approprié.
| HTTP | Code | Cause et solution |
|---|---|---|
| 401 | UNAUTHORIZED | Header X-API-Key manquant ou clé invalide |
| 403 | FORBIDDEN | Email demandé différent du compte lié à votre clé API — /balance uniquement |
| 404 | NOT_FOUND | order_id ou reference introuvable pour ce compte partenaire |
| 409 | CANNOT_REFUND | Statut incompatible — seuls les paiements completed sont remboursables |
| 409 | DUPLICATE_ORDER_ID | Cet order_id est déjà utilisé — utiliser un ID unique par paiement |
| 422 | MISSING_FIELDS | Champs JSON requis absents — vérifier amount, description, customer_email |
| 422 | INVALID_AMOUNT | Montant ≤ 0 ou supérieur à 100 000 USD |
| 422 | INVALID_EMAIL | Format d'email invalide |
| 500 | DB_ERROR | Erreur serveur PSLWallet — réessayer après 30 secondes |
Format erreur JSON{ "success": false, "error": { "code": "INVALID_AMOUNT", "message": "Montant doit être > 0" } }
Webhook
PSLWallet envoie un POST JSON à votre webhook_url (configuré dans votre compte partenaire) après chaque événement de paiement. Votre endpoint doit répondre HTTP 200.
Payload — payment.completed
JSON reçu sur votre serveur{ "event": "payment.completed", "order_id": "CMD-1042", // votre order_id passé à /initiate "reference": "PSL-71F9B1C08DA0EA84", // référence interne PSLWallet "amount": 25.00, "currency": "USD", "customer": "client@email.com", "customer_name": "Jean Dupont", "description": "Commande #1042 — MonSite", "partner": "Solisyon", "tx_id": 471, // ID transaction PSLWallet "metadata": { "product_id": "42", "user_id": "789" }, "mode": "live", "paid_at": "2026-03-16T21:00:00+00:00" }
⚠️ Toujours vérifier que mode === "live" avant de valider une commande. En mode test, loguer l'événement sans modifier votre base de données.
Recevoir le webhook — PHP
PHP — webhook/pslwallet.php// URL configurée : https://monsite.com/webhook/pslwallet $payload = json_decode(file_get_contents('php://input'), true); if (!$payload) { http_response_code(400); exit; } if ($payload['event'] === 'payment.completed' && $payload['mode'] === 'live') { $orderId = $payload['order_id']; // votre order_id passé à /initiate $txId = $payload['tx_id']; // ID transaction PSLWallet $amount = $payload['amount']; $order = get_order($orderId); if ($order && $order['status'] === 'pending') { mark_order_paid($orderId, $txId); send_confirmation_email($payload['customer'], $orderId); unlock_product_access($orderId); } } // Toujours répondre 200 http_response_code(200); echo 'OK';
Intégration PHP complète
Fichier helper pslgateway.php
PHP — pslgateway.phpdefine('PSL_KEY', getenv('PSL_API_KEY')); // dans votre .env ou config.php define('PSL_URL', 'https://pslwallet.com/pslwallet/api/v1'); function psl($method, $path, $body = []) { $ch = curl_init(PSL_URL . $path); curl_setopt_array($ch, [ CURLOPT_CUSTOMREQUEST => $method, CURLOPT_HTTPHEADER => ['X-API-Key: '.PSL_KEY, 'Content-Type: application/json'], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15, ...($body ? [CURLOPT_POSTFIELDS => json_encode($body)] : []), ]); $r = json_decode(curl_exec($ch), true); curl_close($ch); return $r; }
Page checkout — initier le paiement
PHP — checkout.phprequire_once 'pslgateway.php'; $r = psl('POST', '/payment/initiate', [ 'amount' => 25.00, 'description' => 'Commande #1042', 'customer_email' => 'client@email.com', 'order_id' => 'CMD-1042', 'redirect_url' => 'https://monsite.com/confirm', 'metadata' => ['product_id' => '42', 'user_id' => '789'], ]); if ($r['success']) { // Sauvegarder avant de rediriger db_query("UPDATE orders SET psl_order_id=?, psl_ref=?, psl_status='pending' WHERE id=?", [$r['order_id'], $r['reference'], '1042']); header('Location: ' . $r['payment_url']); exit; } else { // Afficher l'erreur $error = $r['error']['message']; }
Intégration Node.js
JavaScript — pslgateway.js + Expressconst PSL = { key: process.env.PSL_API_KEY, url: 'https://pslwallet.com/pslwallet/api/v1', async req(method, path, body) { const r = await fetch(this.url + path, { method, headers: { 'X-API-Key': this.key, 'Content-Type': 'application/json' }, ...(body ? { body: JSON.stringify(body) } : {}), }); const data = await r.json(); if (!data.success) throw new Error(data.error?.message); return data; }, initiate(amount, desc, email, orderId, meta = {}) { return this.req('POST', '/payment/initiate', { amount, description: desc, customer_email: email, order_id: orderId, redirect_url: `${process.env.APP_URL}/confirm`, metadata: meta, }); }, status(orderId) { return this.req('GET', `/payment/status?order_id=${orderId}`); }, refund(orderId, reason) { return this.req('POST', '/payment/refund', { order_id: orderId, reason }); }, }; // Checkout app.post('/checkout/pslwallet', async (req, res) => { const { orderId, amount, email } = req.body; const payment = await PSL.initiate(amount, `Commande #${orderId}`, email, `CMD-${orderId}`); await Order.update(orderId, { pslOrderId: payment.order_id, pslRef: payment.reference }); res.json({ payment_url: payment.payment_url }); }); // Webhook app.post('/webhook/pslwallet', (req, res) => { const { event, order_id, tx_id, mode } = req.body; if (event === 'payment.completed' && mode === 'live') { Order.markPaid(order_id, tx_id); } res.json({ ok: true }); });
WooCommerce
📁 Créer le dossier wp-content/plugins/psl-gateway/ et y placer ce fichier. Activer ensuite dans Extensions → Méthodes de paiement.
PHP — psl-gateway.php/* * Plugin Name: PSL Gateway * Description: Paiements USD via PSL Wallet * Version: 1.0 */ add_filter('woocommerce_payment_gateways', fn($g) => [...$g, 'WC_PSL_Gateway']); add_action('plugins_loaded', function() { class WC_PSL_Gateway extends WC_Payment_Gateway { public function __construct() { $this->id = 'psl_gateway'; $this->method_title = 'PSL Wallet'; $this->method_description = 'Paiement USD sécurisé via PSL Wallet'; $this->has_fields = false; $this->init_form_fields(); $this->init_settings(); $this->title = $this->get_option('title'); $this->api_key = $this->get_option('api_key'); add_action('woocommerce_update_options_payment_gateways_psl_gateway', [$this, 'process_admin_options']); } public function init_form_fields() { $this->form_fields = [ 'title' => ['title'=>'Titre affiché', 'type'=>'text', 'default'=>'PSL Wallet (USD)'], 'api_key' => ['title'=>'Clé API PSLWallet', 'type'=>'password'], ]; } public function process_payment($wc_order_id) { $order = wc_get_order($wc_order_id); $order_id = 'WC-' . $wc_order_id; $ch = curl_init('https://pslwallet.com/pslwallet/api/v1/payment/initiate'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['X-API-Key: '.$this->api_key, 'Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode([ 'amount' => (float)$order->get_total(), 'description' => 'Commande #'.$wc_order_id.' — '.get_bloginfo('name'), 'customer_email' => $order->get_billing_email(), 'order_id' => $order_id, 'redirect_url' => $this->get_return_url($order), 'webhook_url' => home_url('/wp-json/psl/webhook'), 'metadata' => ['wc_order_id' => $wc_order_id], ]), ]); $r = json_decode(curl_exec($ch), true); curl_close($ch); if ($r['success']) { $order->update_meta_data('_psl_order_id', $r['order_id']); $order->update_meta_data('_psl_reference', $r['reference']); $order->save(); return ['result'=>'success', 'redirect'=>$r['payment_url']]; } wc_add_notice($r['error']['message'] ?? 'Erreur PSL Wallet', 'error'); return ['result'=>'failure']; } } }); // Webhook REST WooCommerce add_action('rest_api_init', function() { register_rest_route('psl', '/webhook', [ 'methods' => 'POST', 'permission_callback' => '__return_true', 'callback' => function($req) { $p = $req->get_json_params(); if (($p['mode'] ?? '') !== 'live') return new WP_REST_Response(['ok'=>true]); if ($p['event'] === 'payment.completed') { $wc_id = $p['metadata']['wc_order_id']; $order = wc_get_order($wc_id); if ($order && $order->get_status() === 'pending') { $order->payment_complete($p['tx_id']); $order->add_order_note('Payé via PSL Wallet · order: '.$p['order_id']); } } return new WP_REST_Response(['ok'=>true], 200); }, ]); });