qrcommunication / viva-merchant-sdk
PHP SDK for Viva Wallet Merchant API — orders, transactions, sources, webhooks
Package info
github.com/QrCommunication/sdk-php-viva-merchant
pkg:composer/qrcommunication/viva-merchant-sdk
Requires
- php: ^8.2
- guzzlehttp/guzzle: ^7.8
Requires (Dev)
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0
README
SDK PHP complet pour l'intégration Viva Wallet. Couvre 9 ressources : Orders, Transactions, Sources, Wallets, BankAccounts, NativeCheckout, DataServices, Account et Webhooks.
PHP 8.2+ requis. Compatible Laravel, Symfony, ou tout projet PHP.
Ce SDK couvre les opérations marchands standard. Pour les opérations ISV (comptes connectés, composite auth), voir
sdk-php-viva-isv.
Table des matières
- Installation
- Démarrage rapide
- Référence des ressources
- Architecture
- Enums
- Gestion d'erreurs
- Webhooks — Guide d'intégration
- Carte de test
- Documentation interactive
- Intégration IA
- Licence
Installation
composer require qrcommunication/viva-merchant-sdk
Prérequis : PHP 8.2+ avec ext-json et ext-curl.
Démarrage rapide
use QrCommunication\VivaMerchant\VivaClient; $viva = new VivaClient( merchantId: 'votre-merchant-uuid', apiKey: 'votre-api-key', clientId: 'xxx.apps.vivapayments.com', clientSecret: 'votre-client-secret', environment: 'demo', // ou 'production' ); // Créer un ordre de paiement $order = $viva->orders->create(amount: 1500, customerDescription: 'Consultation'); // Rediriger le client vers $order['checkout_url'] // Vérifier une transaction après paiement $txn = $viva->transactions->getV2('transaction-uuid'); // Rembourser $viva->transactions->cancel('transaction-uuid', amount: 500); // Capturer une pré-autorisation $viva->transactions->capture('preauth-uuid', amount: 1500); // Charge récurrente $viva->transactions->recurring('initial-txn-uuid', amount: 1500); // Apple Pay / Google Pay $token = $viva->nativeCheckout->createChargeToken(1500, $applePayData); $txn = $viva->nativeCheckout->createTransaction($token['chargeToken'], 1500); // Tester la connexion $viva->testConnection(); // true ou false
Référence des ressources
1. Orders — $viva->orders
Ordres de paiement Smart Checkout.
create() — Créer un ordre
$order = $viva->orders->create( amount: 1500, // Centimes (15,00 EUR) customerDescription: 'Consultation', // Affiché au client merchantReference: 'session_123', // Référence interne allowRecurring: true, // Tokeniser la carte preauth: false, // Pré-autorisation ? maxInstallments: 3, // Paiement en 3x ); echo $order['order_code']; // 1234567890 echo $order['checkout_url']; // https://demo.vivapayments.com/web/checkout?ref=1234567890
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
amount |
int |
requis | Montant en centimes |
customerDescription |
?string |
null |
Texte affiché au client |
merchantReference |
?string |
null |
Référence interne (exports) |
sourceCode |
?string |
null |
Source de paiement |
allowRecurring |
bool |
false |
Autoriser les charges récurrentes |
preauth |
bool |
false |
Pré-autorisation uniquement |
maxInstallments |
int |
0 |
Nombre max de versements |
Retour : array{order_code: int, checkout_url: string}
get() — Statut d'un ordre
$order = $viva->orders->get(orderCode: 1234567890);
cancel() — Annuler un ordre non payé
$viva->orders->cancel(orderCode: 1234567890);
checkoutUrl() — URL de checkout (sans appel API)
$url = $viva->orders->checkoutUrl(orderCode: 1234567890); // 'https://demo.vivapayments.com/web/checkout?ref=1234567890'
2. Transactions — $viva->transactions
Consultation, remboursement, capture et paiements récurrents.
get() — Détails complets (Legacy API, PascalCase)
$txn = $viva->transactions->get('transaction-uuid'); echo $txn['Transactions'][0]['Amount']; echo $txn['Transactions'][0]['StatusId'];
getV2() — Détails légers (New API, camelCase)
$txn = $viva->transactions->getV2('transaction-uuid'); echo $txn['email']; echo $txn['amount']; // En EUR (pas en centimes) echo $txn['statusId']; // 'F' echo $txn['orderCode'];
Recommandé pour vérifier les paiements Smart Checkout.
listByDate() — Lister par date
$transactions = $viva->transactions->listByDate('2026-03-18'); foreach ($transactions as $txn) { echo $txn['TransactionId'] . ' — ' . $txn['Amount'] . "\n"; }
Retour : array<int, array<string, mixed>>
cancel() — Annuler / Rembourser
// Remboursement total $result = $viva->transactions->cancel('transaction-uuid'); // Remboursement partiel (5,00 EUR) $result = $viva->transactions->cancel('transaction-uuid', amount: 500); echo $result['TransactionId']; // UUID du remboursement
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
transactionId |
string |
requis | UUID de la transaction |
amount |
?int |
null |
Centimes (null = total) |
sourceCode |
?string |
null |
Source de paiement |
Même jour = annulation (void). Jour passé = remboursement (refund).
capture() — Capturer une pré-autorisation
$result = $viva->transactions->capture('preauth-uuid', amount: 1500);
Lève ApiException si la capture échoue.
recurring() — Charge récurrente
$result = $viva->transactions->recurring( initialTransactionId: 'initial-txn-uuid', amount: 1500, sourceCode: '1234', // optionnel );
Prérequis : l'ordre initial doit avoir été créé avec allowRecurring: true.
3. Sources — $viva->sources
Gestion des sources de paiement (domaines autorisés, URLs de redirection).
list() — Lister les sources
$sources = $viva->sources->list(); foreach ($sources as $source) { echo $source['Name'] . ' — ' . $source['SourceCode'] . "\n"; }
create() — Créer une source
$source = $viva->sources->create( name: 'Mon site web', sourceCode: '1234', domain: 'www.example.com', pathSuccess: '/paiement/succes', pathFail: '/paiement/echec', );
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
name |
string |
requis | Nom d'affichage |
sourceCode |
string |
requis | Code à 4 chiffres |
domain |
?string |
null |
Domaine du site |
pathSuccess |
?string |
null |
Redirection succès |
pathFail |
?string |
null |
Redirection échec |
4. Wallets — $viva->wallets
Portefeuilles (sous-comptes), soldes et transferts.
list() — Lister les portefeuilles
$wallets = $viva->wallets->list();
balance() — Solde agrégé
$balance = $viva->wallets->balance(); echo $balance['available']; // 150.50 echo $balance['pending']; // 25.00 echo $balance['reserved']; // 0.00 echo $balance['currency']; // 'EUR'
Retour : array{available: float, pending: float, reserved: float, currency: string}
transfer() — Transfert entre wallets
$viva->wallets->transfer( amount: 5000, // 50,00 EUR sourceWalletId: 'source-uuid', targetWalletId: 'target-uuid', description: 'Transfert mensuel', );
Prérequis : « Allow transfers between accounts » dans Settings > API Access.
listDetailed() — Liste enrichie (IBAN, SWIFT)
$wallets = $viva->wallets->listDetailed(); foreach ($wallets as $wallet) { echo $wallet['iban'] . ' — ' . $wallet['amount'] . "\n"; echo $wallet['isPrimary'] ? 'Principal' : 'Secondaire'; }
create() — Créer un portefeuille
$viva->wallets->create(friendlyName: 'Compte secondaire', currencyCode: 'EUR');
update() — Renommer un portefeuille
$viva->wallets->update(walletId: 12345, friendlyName: 'Nouveau nom');
searchTransactions() — Rechercher les transactions de compte
$transactions = $viva->wallets->searchTransactions([ 'date_from' => '2026-03-01', 'date_to' => '2026-03-18', 'walletId' => 12345, ]);
getTransaction() — Détails d'une transaction de compte
$txn = $viva->wallets->getTransaction('transaction-uuid');
5. BankAccounts — $viva->bankAccounts
Comptes bancaires IBAN et virements SEPA.
link() — Lier un IBAN
$result = $viva->bankAccounts->link( iban: 'FR7630006000011234567890189', beneficiaryName: 'Jean Dupont', friendlyName: 'Compte principal', ); echo $result['bankAccountId']; // UUID echo $result['isVivaIban']; // false
transferOptions() — Options de transfert
$options = $viva->bankAccounts->transferOptions('bank-account-uuid');
feeCommand() — Calculer les frais avant virement
$fees = $viva->bankAccounts->feeCommand( bankAccountId: 'bank-account-uuid', amount: 10000, // 100,00 EUR walletId: 'source-wallet-uuid', isInstant: true, // SEPA instantané instructionType: 'SHA', // Frais partagés ); echo $fees['bankCommandId']; // À passer à send() echo $fees['fee']; // Frais en centimes
send() — Exécuter un virement SEPA
$result = $viva->bankAccounts->send( bankAccountId: 'bank-account-uuid', amount: 10000, walletId: 'source-wallet-uuid', bankCommandId: 'fee-command-uuid', // Optionnel description: 'Virement mensuel', ); echo $result['commandId']; // UUID du virement echo $result['isInstant']; // true/false echo $result['fee']; // Frais en centimes
list() — Lister les comptes liés
$accounts = $viva->bankAccounts->list();
get() — Détails d'un compte lié
$account = $viva->bankAccounts->get('bank-account-uuid');
6. NativeCheckout — $viva->nativeCheckout
Paiements Apple Pay et Google Pay.
createChargeToken() — Générer un token de charge
$token = $viva->nativeCheckout->createChargeToken( amount: 1500, paymentData: $applePayPaymentDataString, paymentMethod: 'applepay', // ou 'googlepay' sourceCode: '1234', ); echo $token['chargeToken']; // Token à passer à createTransaction() echo $token['redirectToACSForm']; // Formulaire 3DS (si applicable)
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
amount |
int |
requis | Montant en centimes |
paymentData |
string |
requis | Données Apple Pay / Google Pay |
paymentMethod |
string |
'applepay' |
'applepay' ou 'googlepay' |
sourceCode |
?string |
null |
Source de paiement |
dynamicDescriptor |
?string |
null |
Descripteur dynamique |
createTransaction() — Exécuter la transaction
$txn = $viva->nativeCheckout->createTransaction( chargeToken: $token['chargeToken'], amount: 1500, currencyCode: 978, // EUR (ISO 4217 numérique) merchantTrns: 'ref_123', customerTrns: 'Consultation', ); echo $txn['transactionId']; // UUID echo $txn['statusId']; // 'F' = finalisée echo $txn['amount']; // 1500 echo $txn['orderCode']; // Code de l'ordre
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
chargeToken |
string |
requis | Token de createChargeToken() |
amount |
int |
requis | Montant en centimes |
currencyCode |
int |
978 |
ISO 4217 numérique |
sourceCode |
?string |
null |
Source de paiement |
merchantTrns |
?string |
null |
Référence interne |
customerTrns |
?string |
null |
Description client |
preauth |
bool |
false |
Pré-autorisation ? |
tipAmount |
int |
0 |
Pourboire en centimes |
installments |
?int |
null |
Nombre de versements |
7. DataServices — $viva->dataServices
Rapports MT940 et souscriptions webhook pour les fichiers de données.
mt940() — Rapport MT940
$report = $viva->dataServices->mt940('2026-03-18');
createSubscription() — Créer une souscription webhook
$sub = $viva->dataServices->createSubscription( url: 'https://example.com/webhooks/viva-files', eventType: 'SaleTransactionsFileGenerated', ); echo $sub['subscriptionId'];
updateSubscription() — Mettre à jour
$viva->dataServices->updateSubscription( subscriptionId: 'sub-uuid', url: 'https://example.com/webhooks/new-url', eventType: null, // null = conserver l'actuel );
deleteSubscription() — Supprimer
$viva->dataServices->deleteSubscription('sub-uuid');
listSubscriptions() — Lister
$subs = $viva->dataServices->listSubscriptions(); foreach ($subs as $sub) { echo $sub['subscriptionId'] . ' → ' . $sub['url'] . "\n"; }
requestFile() — Demander la génération d'un fichier
$viva->dataServices->requestFile('2026-03-18');
Déclenche la génération asynchrone. Utilisez une souscription webhook pour être notifié.
8. Webhooks — $viva->webhooks
Vérification et parsing des webhooks Viva Wallet. Aucun appel API — tout est local.
verificationResponse() — Répondre au GET de vérification
public function verify() { return response()->json( $viva->webhooks->verificationResponse('votre-verification-key') ); // => {"StatusCode": 0, "Key": "votre-verification-key"} }
parse() — Parser un webhook POST
public function handle(Request $request) { $event = $viva->webhooks->parse($request->getContent()); echo $event['event_type']; // 'transaction.payment.created' echo $event['event_type_id']; // 1796 echo $event['event_data']; // Données de l'événement match ($event['event_type']) { 'transaction.payment.created' => $this->handlePayment($event['event_data']), 'transaction.refund.created' => $this->handleRefund($event['event_data']), default => null, }; }
Retour : array{event_type: string, event_type_id: int, event_data: array<string, mixed>}
Lève InvalidArgumentException si le JSON est invalide.
isKnownEvent() — Vérifier un ID d'événement
$viva->webhooks->isKnownEvent(1796); // true $viva->webhooks->isKnownEvent(9999); // false
eventTypeIds() — Lister les IDs connus
$ids = $viva->webhooks->eventTypeIds(); // [1796, 1797, 1798, ..., 1828]
21 types d'événements supportés
| ID | Type |
|---|---|
| 1796 | transaction.payment.created |
| 1797 | transaction.refund.created |
| 1798 | transaction.payment.cancelled |
| 1799 | transaction.reversal.created |
| 1800 | transaction.preauth.created |
| 1801 | transaction.preauth.completed |
| 1802 | transaction.preauth.cancelled |
| 1810 | pos.session.created |
| 1811 | pos.session.failed |
| 1812 | transaction.price.calculated |
| 1813 | transaction.failed |
| 1819 | account.connected |
| 1820 | account.verification.status.changed |
| 1821 | account.transaction.created |
| 1822 | command.bank.transfer.created |
| 1823 | command.bank.transfer.executed |
| 1824 | transfer.created |
| 1825 | obligation.created |
| 1826 | obligation.captured |
| 1827 | order.updated |
| 1828 | sale.transactions.file |
9. Account — $viva->account
Informations du compte marchand.
info() — Informations du compte
$info = $viva->account->info(); echo $info['merchantId']; echo $info['businessName']; echo $info['email'];
wallets() — Portefeuilles du compte
$wallets = $viva->account->wallets();
Architecture
src/
├── VivaClient.php # Point d'entrée — instancie les 9 ressources
├── Config.php # Configuration (URLs par environnement)
├── HttpClient.php # Client HTTP Guzzle (OAuth2 auto, Basic Auth)
├── Enums/
│ ├── Environment.php # demo | production
│ ├── Currency.php # Codes ISO 4217 numériques
│ └── TransactionStatus.php # F, A, C, E, M, X, R
├── Exceptions/
│ ├── VivaException.php # Classe de base (RuntimeException)
│ ├── ApiException.php # Erreur API (4xx, 5xx)
│ ├── AuthenticationException.php # Échec OAuth2 (401)
│ └── ValidationException.php # Validation (422)
└── Resources/
├── Orders.php # Smart Checkout
├── Transactions.php # Get, list, cancel, capture, recurring
├── Sources.php # Sources de paiement
├── Wallets.php # Portefeuilles, soldes, transferts
├── BankAccounts.php # IBAN, virements SEPA
├── NativeCheckout.php # Apple Pay, Google Pay
├── DataServices.php # MT940, souscriptions webhook
├── Webhooks.php # Vérification et parsing
└── Account.php # Infos du compte
L'authentification est gérée automatiquement par HttpClient :
- Legacy API (Basic Auth) — utilisée par Orders, Transactions, Sources
- New API (Bearer OAuth2) — utilisée par Wallets, BankAccounts, NativeCheckout, DataServices, Account
Le token OAuth2 est mis en cache en mémoire et rafraîchi automatiquement avant expiration.
Enums
Environment
use QrCommunication\VivaMerchant\Enums\Environment; $env = Environment::DEMO; $env = Environment::PRODUCTION; $env = Environment::from('demo'); $env->value; // 'demo' $env->apiUrl(); // 'https://demo-api.vivapayments.com' $env->legacyUrl(); // 'https://demo.vivapayments.com' $env->checkoutUrl(); // 'https://demo.vivapayments.com/web/checkout' $env->accountsUrl(); // 'https://demo-accounts.vivapayments.com'
Currency
use QrCommunication\VivaMerchant\Enums\Currency; Currency::EUR->value; // 978 Currency::EUR->iso(); // 'EUR' Currency::fromIso('GBP'); // Currency::GBP (826)
Devises supportées : EUR (978), GBP (826), USD (840), PLN (985), RON (946), BGN (975), CZK (203), HRK (191), HUF (348), DKK (208), SEK (752), NOK (578).
TransactionStatus
use QrCommunication\VivaMerchant\Enums\TransactionStatus; $status = TransactionStatus::from('F'); $status->isSuccessful(); // true $status->isPending(); // false $status->isFailed(); // false $status->label(); // 'Finalized'
| Valeur | Constante | isSuccessful() |
isPending() |
isFailed() |
|---|---|---|---|---|
F |
FINALIZED |
oui | ||
A |
PENDING |
oui | ||
C |
CLEARING |
oui | ||
E |
ERROR |
oui | ||
M |
MANUALLY_REVERSED |
oui | ||
X |
REQUIRES_ACTION |
|||
R |
REFUNDED |
Gestion d'erreurs
Toutes les exceptions héritent de VivaException qui étend RuntimeException.
RuntimeException
└── VivaException
├── ApiException
├── AuthenticationException
└── ValidationException
use QrCommunication\VivaMerchant\Exceptions\ApiException; use QrCommunication\VivaMerchant\Exceptions\AuthenticationException; use QrCommunication\VivaMerchant\Exceptions\ValidationException; use QrCommunication\VivaMerchant\Exceptions\VivaException; try { $order = $viva->orders->create(amount: 1500); } catch (AuthenticationException $e) { // Identifiants invalides — httpStatus = 401 echo $e->getMessage(); } catch (ValidationException $e) { // Erreur de validation — httpStatus = 422 foreach ($e->errors as $field => $messages) { echo "$field: " . implode(', ', $messages); } } catch (ApiException $e) { // Erreur API générale — 400, 404, 500, etc. echo $e->httpStatus; echo $e->getErrorCode(); echo $e->getErrorText(); print_r($e->responseBody); } catch (VivaException $e) { // Toute autre erreur SDK }
Propriétés et méthodes de VivaException
| Membre | Type | Description |
|---|---|---|
$httpStatus |
int |
Code HTTP de la réponse |
$responseBody |
?array |
Corps JSON décodé de la réponse |
getErrorCode() |
?int |
Code d'erreur Viva (ErrorCode) |
getErrorText() |
?string |
Message d'erreur Viva (ErrorText, message, ou detail) |
Webhooks — Guide d'intégration
1. Configurer le webhook dans le Dashboard Viva
- Aller dans Settings > API Access > Webhooks
- Ajouter l'URL de votre endpoint
- Noter la clé de vérification
2. Gérer la vérification (GET)
// Route GET /webhooks/viva public function verify() { return response()->json( $viva->webhooks->verificationResponse('votre-clé') ); }
3. Recevoir les événements (POST)
// Route POST /webhooks/viva public function handle(Request $request) { $event = $viva->webhooks->parse($request->getContent()); match ($event['event_type']) { 'transaction.payment.created' => $this->onPayment($event['event_data']), 'transaction.refund.created' => $this->onRefund($event['event_data']), 'transaction.preauth.created' => $this->onPreauth($event['event_data']), 'transaction.preauth.completed' => $this->onCapture($event['event_data']), default => logger()->info('Webhook ignoré : ' . $event['event_type']), }; return response()->json(['status' => 'ok']); }
Carte de test
Pour l'environnement demo :
| Champ | Valeur |
|---|---|
| Numéro de carte | 4111 1111 1111 1111 |
| Expiration | Toute date future |
| CVV | 111 |
| 3DS | Pas de 3DS en demo |
Documentation interactive
La documentation interactive (ReDoc) est disponible en ligne :
https://qrcommunication.github.io/sdk-php-viva-merchant/
Elle détaille chaque classe, méthode, paramètre et type de retour du SDK.
Intégration IA
Ce SDK inclut un skill détaillé (skill/SKILL.md) automatiquement détecté par les assistants IA. Il fournit la référence complète des 9 resources, 34+ méthodes, enums, exceptions et patterns d'implémentation.
| Outil | Fichier | Détection |
|---|---|---|
| Claude Code | CLAUDE.md + skill/SKILL.md |
Automatique |
| Cursor | .cursorrules |
Automatique |
| GitHub Copilot | .github/copilot-instructions.md |
Automatique |
| OpenAI Codex | AGENTS.md |
Automatique |
// Un agent IA peut construire cet appel à partir de : // "Crée un paiement de 25 EUR pour une consultation" $order = $viva->orders->create( amount: 2500, customerDescription: 'Consultation', );
Licence
MIT — QrCommunication