{"id":49136424,"url":"https://github.com/qrcommunication/sdk-php-viva-merchant","last_synced_at":"2026-05-01T11:01:27.459Z","repository":{"id":345317869,"uuid":"1185205766","full_name":"QrCommunication/sdk-php-viva-merchant","owner":"QrCommunication","description":"PHP SDK for Viva Wallet Merchant API — orders, transactions, sources, webhooks","archived":false,"fork":false,"pushed_at":"2026-03-18T19:59:40.000Z","size":118,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-21T22:40:35.521Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/QrCommunication.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-18T10:48:04.000Z","updated_at":"2026-03-18T19:59:43.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/QrCommunication/sdk-php-viva-merchant","commit_stats":null,"previous_names":["qrcommunication/sdk-php-viva-merchant"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/QrCommunication/sdk-php-viva-merchant","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QrCommunication%2Fsdk-php-viva-merchant","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QrCommunication%2Fsdk-php-viva-merchant/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QrCommunication%2Fsdk-php-viva-merchant/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QrCommunication%2Fsdk-php-viva-merchant/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/QrCommunication","download_url":"https://codeload.github.com/QrCommunication/sdk-php-viva-merchant/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QrCommunication%2Fsdk-php-viva-merchant/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32494275,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"online","status_checked_at":"2026-05-01T02:00:05.856Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-21T22:09:17.824Z","updated_at":"2026-05-01T11:01:27.449Z","avatar_url":"https://github.com/QrCommunication.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Viva Wallet Merchant SDK — PHP\n\n[![Version 1.4.0](https://img.shields.io/badge/version-1.4.0-blue.svg)](https://github.com/qrcommunication/sdk-php-viva-merchant/releases)\n[![PHP 8.2+](https://img.shields.io/badge/PHP-8.2%2B-777BB4.svg)](https://php.net)\n[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n[![Packagist](https://img.shields.io/badge/Packagist-qrcommunication%2Fviva--merchant--sdk-orange.svg)](https://packagist.org/packages/qrcommunication/viva-merchant-sdk)\n\nSDK PHP complet pour l'intégration Viva Wallet. Couvre **10 ressources** : Orders, Transactions, Sources, Wallets, BankAccounts, NativeCheckout, DataServices, Account, Webhooks et Messages (abonnements webhook).\n\n**PHP 8.2+** requis. Compatible Laravel, Symfony, ou tout projet PHP.\n\n\u003e **Ce SDK couvre les opérations marchands standard.** Pour les opérations ISV (comptes connectés, composite auth), voir [`sdk-php-viva-isv`](https://github.com/qrcommunication/sdk-php-viva-isv).\n\n---\n\n## Table des matières\n\n- [Installation](#installation)\n- [Démarrage rapide](#démarrage-rapide)\n- [Référence des ressources](#référence-des-ressources)\n  - [1. Orders](#1-orders--vivaorders)\n  - [2. Transactions](#2-transactions--vivatransactions)\n  - [3. Sources](#3-sources--vivasources)\n  - [4. Wallets](#4-wallets--vivawallets)\n  - [5. BankAccounts](#5-bankaccounts--vivabankaccounts)\n  - [6. NativeCheckout](#6-nativecheckout--vivanativecheckout)\n  - [7. DataServices](#7-dataservices--vivadataservices)\n  - [8. Webhooks](#8-webhooks--vivawebhooks)\n  - [9. Account](#9-account--vivaaccount)\n  - [10. Messages](#10-messages--vivamessages)\n- [Enregistrement des webhooks banking](#enregistrement-des-webhooks-banking)\n- [Architecture](#architecture)\n- [Enums](#enums)\n- [Gestion d'erreurs](#gestion-derreurs)\n- [Webhooks — Guide d'intégration](#webhooks--guide-dintégration)\n- [Carte de test](#carte-de-test)\n- [Documentation interactive](#documentation-interactive)\n- [Intégration IA](#intégration-ia)\n- [Licence](#licence)\n\n---\n\n## Installation\n\n```bash\ncomposer require qrcommunication/viva-merchant-sdk\n```\n\n**Prérequis** : PHP 8.2+ avec `ext-json` et `ext-curl`.\n\n---\n\n## Démarrage rapide\n\n```php\nuse QrCommunication\\VivaMerchant\\VivaClient;\n\n$viva = new VivaClient(\n    merchantId: 'votre-merchant-uuid',\n    apiKey: 'votre-api-key',\n    clientId: 'xxx.apps.vivapayments.com',\n    clientSecret: 'votre-client-secret',\n    environment: 'demo', // ou 'production'\n);\n\n// Créer un ordre de paiement\n$order = $viva-\u003eorders-\u003ecreate(amount: 1500, customerDescription: 'Consultation');\n// Rediriger le client vers $order['checkout_url']\n\n// Vérifier une transaction après paiement\n$txn = $viva-\u003etransactions-\u003egetV2('transaction-uuid');\n\n// Rembourser\n$viva-\u003etransactions-\u003ecancel('transaction-uuid', amount: 500);\n\n// Capturer une pré-autorisation\n$viva-\u003etransactions-\u003ecapture('preauth-uuid', amount: 1500);\n\n// Charge récurrente\n$viva-\u003etransactions-\u003erecurring('initial-txn-uuid', amount: 1500);\n\n// Apple Pay / Google Pay\n$token = $viva-\u003enativeCheckout-\u003ecreateChargeToken(1500, $applePayData);\n$txn = $viva-\u003enativeCheckout-\u003ecreateTransaction($token['chargeToken'], 1500);\n\n// Tester la connexion\n$viva-\u003etestConnection(); // true ou false\n```\n\n---\n\n## Référence des ressources\n\n### 1. Orders — `$viva-\u003eorders`\n\nOrdres de paiement Smart Checkout.\n\n#### `create()` — Créer un ordre\n\n```php\n$order = $viva-\u003eorders-\u003ecreate(\n    amount: 1500,                         // Centimes (15,00 EUR)\n    customerDescription: 'Consultation',  // Affiché au client\n    merchantReference: 'session_123',     // Référence interne\n    allowRecurring: true,                 // Tokeniser la carte\n    preauth: false,                       // Pré-autorisation ?\n    maxInstallments: 3,                   // Paiement en 3x\n);\n\necho $order['order_code'];   // 1234567890\necho $order['checkout_url']; // https://demo.vivapayments.com/web/checkout?ref=1234567890\n```\n\n| Paramètre | Type | Défaut | Description |\n|-----------|------|--------|-------------|\n| `amount` | `int` | **requis** | Montant en centimes |\n| `customerDescription` | `?string` | `null` | Texte affiché au client |\n| `merchantReference` | `?string` | `null` | Référence interne (exports) |\n| `sourceCode` | `?string` | `null` | Source de paiement |\n| `allowRecurring` | `bool` | `false` | Autoriser les charges récurrentes |\n| `preauth` | `bool` | `false` | Pré-autorisation uniquement |\n| `maxInstallments` | `int` | `0` | Nombre max de versements |\n\n**Retour :** `array{order_code: int, checkout_url: string}`\n\n#### `get()` — Statut d'un ordre\n\n```php\n$order = $viva-\u003eorders-\u003eget(orderCode: 1234567890);\n```\n\n#### `cancel()` — Annuler un ordre non payé\n\n```php\n$viva-\u003eorders-\u003ecancel(orderCode: 1234567890);\n```\n\n#### `checkoutUrl()` — URL de checkout (sans appel API)\n\n```php\n$url = $viva-\u003eorders-\u003echeckoutUrl(orderCode: 1234567890);\n// 'https://demo.vivapayments.com/web/checkout?ref=1234567890'\n```\n\n---\n\n### 2. Transactions — `$viva-\u003etransactions`\n\nConsultation, remboursement, capture et paiements récurrents.\n\n#### `get()` — Détails complets (Legacy API, PascalCase)\n\n```php\n$txn = $viva-\u003etransactions-\u003eget('transaction-uuid');\necho $txn['Transactions'][0]['Amount'];\necho $txn['Transactions'][0]['StatusId'];\n```\n\n#### `getV2()` — Détails légers (New API, camelCase)\n\n```php\n$txn = $viva-\u003etransactions-\u003egetV2('transaction-uuid');\necho $txn['email'];\necho $txn['amount'];      // En EUR (pas en centimes)\necho $txn['statusId'];    // 'F'\necho $txn['orderCode'];\n```\n\nRecommandé pour vérifier les paiements Smart Checkout.\n\n#### `listByDate()` — Lister par date\n\n```php\n$transactions = $viva-\u003etransactions-\u003elistByDate('2026-03-18');\n\nforeach ($transactions as $txn) {\n    echo $txn['TransactionId'] . ' — ' . $txn['Amount'] . \"\\n\";\n}\n```\n\n**Retour :** `array\u003cint, array\u003cstring, mixed\u003e\u003e`\n\n#### `cancel()` — Annuler / Rembourser\n\n```php\n// Remboursement total\n$result = $viva-\u003etransactions-\u003ecancel('transaction-uuid');\n\n// Remboursement partiel (5,00 EUR)\n$result = $viva-\u003etransactions-\u003ecancel('transaction-uuid', amount: 500);\n\necho $result['TransactionId']; // UUID du remboursement\n```\n\n| Paramètre | Type | Défaut | Description |\n|-----------|------|--------|-------------|\n| `transactionId` | `string` | **requis** | UUID de la transaction |\n| `amount` | `?int` | `null` | Centimes (`null` = total) |\n| `sourceCode` | `?string` | `null` | Source de paiement |\n\nMême jour = annulation (void). Jour passé = remboursement (refund).\n\n#### `capture()` — Capturer une pré-autorisation\n\n```php\n$result = $viva-\u003etransactions-\u003ecapture('preauth-uuid', amount: 1500);\n```\n\nLève `ApiException` si la capture échoue.\n\n#### `recurring()` — Charge récurrente\n\n```php\n$result = $viva-\u003etransactions-\u003erecurring(\n    initialTransactionId: 'initial-txn-uuid',\n    amount: 1500,\n    sourceCode: '1234', // optionnel\n);\n```\n\nPrérequis : l'ordre initial doit avoir été créé avec `allowRecurring: true`.\n\n---\n\n### 3. Sources — `$viva-\u003esources`\n\nGestion des sources de paiement (domaines autorisés, URLs de redirection).\n\n#### `list()` — Lister les sources\n\n```php\n$sources = $viva-\u003esources-\u003elist();\n\nforeach ($sources as $source) {\n    echo $source['Name'] . ' — ' . $source['SourceCode'] . \"\\n\";\n}\n```\n\n#### `create()` — Créer une source\n\n```php\n$source = $viva-\u003esources-\u003ecreate(\n    name: 'Mon site web',\n    sourceCode: '1234',\n    domain: 'www.example.com',\n    pathSuccess: '/paiement/succes',\n    pathFail: '/paiement/echec',\n);\n```\n\n| Paramètre | Type | Défaut | Description |\n|-----------|------|--------|-------------|\n| `name` | `string` | **requis** | Nom d'affichage |\n| `sourceCode` | `string` | **requis** | Code à 4 chiffres |\n| `domain` | `?string` | `null` | Domaine du site |\n| `pathSuccess` | `?string` | `null` | Redirection succès |\n| `pathFail` | `?string` | `null` | Redirection échec |\n\n---\n\n### 4. Wallets — `$viva-\u003ewallets`\n\nPortefeuilles (sous-comptes), soldes et transferts.\n\n#### `list()` — Lister les portefeuilles\n\n```php\n$wallets = $viva-\u003ewallets-\u003elist();\n```\n\n#### `balance()` — Solde agrégé\n\n```php\n$balance = $viva-\u003ewallets-\u003ebalance();\necho $balance['available'];  // 150.50\necho $balance['pending'];    // 25.00\necho $balance['reserved'];   // 0.00\necho $balance['currency'];   // 'EUR'\n```\n\n**Retour :** `array{available: float, pending: float, reserved: float, currency: string}`\n\n#### `transfer()` — Transfert entre wallets\n\n```php\n$viva-\u003ewallets-\u003etransfer(\n    amount: 5000,                        // 50,00 EUR\n    sourceWalletId: 'source-uuid',\n    targetWalletId: 'target-uuid',\n    description: 'Transfert mensuel',\n);\n```\n\nPrérequis : « Allow transfers between accounts » dans Settings \u003e API Access.\n\n#### `listDetailed()` — Liste enrichie (IBAN, SWIFT)\n\n```php\n$wallets = $viva-\u003ewallets-\u003elistDetailed();\n\nforeach ($wallets as $wallet) {\n    echo $wallet['iban'] . ' — ' . $wallet['amount'] . \"\\n\";\n    echo $wallet['isPrimary'] ? 'Principal' : 'Secondaire';\n}\n```\n\n#### `create()` — Créer un portefeuille\n\n```php\n$viva-\u003ewallets-\u003ecreate(friendlyName: 'Compte secondaire', currencyCode: 'EUR');\n```\n\n#### `update()` — Renommer un portefeuille\n\n```php\n$viva-\u003ewallets-\u003eupdate(walletId: 12345, friendlyName: 'Nouveau nom');\n```\n\n#### `searchTransactions()` — Rechercher les transactions de compte\n\n```php\n$transactions = $viva-\u003ewallets-\u003esearchTransactions([\n    'date_from' =\u003e '2026-03-01',\n    'date_to' =\u003e '2026-03-18',\n    'walletId' =\u003e 12345,\n]);\n```\n\n#### `getTransaction()` — Détails d'une transaction de compte\n\n```php\n$txn = $viva-\u003ewallets-\u003egetTransaction('transaction-uuid');\n```\n\n---\n\n### 5. BankAccounts — `$viva-\u003ebankAccounts`\n\nComptes bancaires IBAN et virements SEPA.\n\n#### `link()` — Lier un IBAN\n\n```php\n$result = $viva-\u003ebankAccounts-\u003elink(\n    iban: 'FR7630006000011234567890189',\n    beneficiaryName: 'Jean Dupont',\n    friendlyName: 'Compte principal',\n);\n\necho $result['bankAccountId']; // UUID\necho $result['isVivaIban'];    // false\n```\n\n#### `transferOptions()` — Options de transfert\n\n```php\n$options = $viva-\u003ebankAccounts-\u003etransferOptions('bank-account-uuid');\n```\n\n#### `feeCommand()` — Calculer les frais avant virement\n\n```php\n$fees = $viva-\u003ebankAccounts-\u003efeeCommand(\n    bankAccountId: 'bank-account-uuid',\n    amount: 10000,                    // 100,00 EUR\n    walletId: 'source-wallet-uuid',\n    isInstant: true,                  // SEPA instantané\n    instructionType: 'SHA',           // Frais partagés\n);\n\necho $fees['bankCommandId']; // À passer à send()\necho $fees['fee'];           // Frais en centimes\n```\n\n#### `send()` — Exécuter un virement SEPA\n\n```php\n$result = $viva-\u003ebankAccounts-\u003esend(\n    bankAccountId: 'bank-account-uuid',\n    amount: 10000,\n    walletId: 'source-wallet-uuid',\n    bankCommandId: 'fee-command-uuid',  // Optionnel\n    description: 'Virement mensuel',\n);\n\necho $result['commandId']; // UUID du virement\necho $result['isInstant']; // true/false\necho $result['fee'];       // Frais en centimes\n```\n\n#### `list()` — Lister les comptes liés\n\n```php\n$accounts = $viva-\u003ebankAccounts-\u003elist();\n```\n\n#### `get()` — Détails d'un compte lié\n\n```php\n$account = $viva-\u003ebankAccounts-\u003eget('bank-account-uuid');\n```\n\n---\n\n### 6. NativeCheckout — `$viva-\u003enativeCheckout`\n\nPaiements Apple Pay et Google Pay.\n\n#### `createChargeToken()` — Générer un token de charge\n\n```php\n$token = $viva-\u003enativeCheckout-\u003ecreateChargeToken(\n    amount: 1500,\n    paymentData: $applePayPaymentDataString,\n    paymentMethod: 'applepay', // ou 'googlepay'\n    sourceCode: '1234',\n);\n\necho $token['chargeToken'];       // Token à passer à createTransaction()\necho $token['redirectToACSForm']; // Formulaire 3DS (si applicable)\n```\n\n| Paramètre | Type | Défaut | Description |\n|-----------|------|--------|-------------|\n| `amount` | `int` | **requis** | Montant en centimes |\n| `paymentData` | `string` | **requis** | Données Apple Pay / Google Pay |\n| `paymentMethod` | `string` | `'applepay'` | `'applepay'` ou `'googlepay'` |\n| `sourceCode` | `?string` | `null` | Source de paiement |\n| `dynamicDescriptor` | `?string` | `null` | Descripteur dynamique |\n\n#### `createTransaction()` — Exécuter la transaction\n\n```php\n$txn = $viva-\u003enativeCheckout-\u003ecreateTransaction(\n    chargeToken: $token['chargeToken'],\n    amount: 1500,\n    currencyCode: 978,             // EUR (ISO 4217 numérique)\n    merchantTrns: 'ref_123',\n    customerTrns: 'Consultation',\n);\n\necho $txn['transactionId']; // UUID\necho $txn['statusId'];      // 'F' = finalisée\necho $txn['amount'];        // 1500\necho $txn['orderCode'];     // Code de l'ordre\n```\n\n| Paramètre | Type | Défaut | Description |\n|-----------|------|--------|-------------|\n| `chargeToken` | `string` | **requis** | Token de `createChargeToken()` |\n| `amount` | `int` | **requis** | Montant en centimes |\n| `currencyCode` | `int` | `978` | ISO 4217 numérique |\n| `sourceCode` | `?string` | `null` | Source de paiement |\n| `merchantTrns` | `?string` | `null` | Référence interne |\n| `customerTrns` | `?string` | `null` | Description client |\n| `preauth` | `bool` | `false` | Pré-autorisation ? |\n| `tipAmount` | `int` | `0` | Pourboire en centimes |\n| `installments` | `?int` | `null` | Nombre de versements |\n\n---\n\n### 7. DataServices — `$viva-\u003edataServices`\n\nRapports MT940 et souscriptions webhook pour les fichiers de données.\n\n#### `mt940()` — Rapport MT940\n\n```php\n$report = $viva-\u003edataServices-\u003emt940('2026-03-18');\n```\n\n#### `createSubscription()` — Créer une souscription webhook\n\n```php\n$sub = $viva-\u003edataServices-\u003ecreateSubscription(\n    url: 'https://example.com/webhooks/viva-files',\n    eventType: 'SaleTransactionsFileGenerated',\n);\necho $sub['subscriptionId'];\n```\n\n#### `updateSubscription()` — Mettre à jour\n\n```php\n$viva-\u003edataServices-\u003eupdateSubscription(\n    subscriptionId: 'sub-uuid',\n    url: 'https://example.com/webhooks/new-url',\n    eventType: null, // null = conserver l'actuel\n);\n```\n\n#### `deleteSubscription()` — Supprimer\n\n```php\n$viva-\u003edataServices-\u003edeleteSubscription('sub-uuid');\n```\n\n#### `listSubscriptions()` — Lister\n\n```php\n$subs = $viva-\u003edataServices-\u003elistSubscriptions();\n\nforeach ($subs as $sub) {\n    echo $sub['subscriptionId'] . ' → ' . $sub['url'] . \"\\n\";\n}\n```\n\n#### `requestFile()` — Demander la génération d'un fichier\n\n```php\n$viva-\u003edataServices-\u003erequestFile('2026-03-18');\n```\n\nDéclenche la génération asynchrone. Utilisez une souscription webhook pour être notifié.\n\n---\n\n### 8. Webhooks — `$viva-\u003ewebhooks`\n\nVérification et parsing des webhooks Viva Wallet. Aucun appel API — tout est local.\n\n#### `verificationResponse()` — Répondre au GET de vérification\n\n```php\npublic function verify()\n{\n    return response()-\u003ejson(\n        $viva-\u003ewebhooks-\u003everificationResponse('votre-verification-key')\n    );\n    // =\u003e {\"StatusCode\": 0, \"Key\": \"votre-verification-key\"}\n}\n```\n\n#### `parse()` — Parser un webhook POST\n\n```php\npublic function handle(Request $request)\n{\n    $event = $viva-\u003ewebhooks-\u003eparse($request-\u003egetContent());\n\n    echo $event['event_type'];     // 'transaction.payment.created'\n    echo $event['event_type_id'];  // 1796\n    echo $event['event_data'];     // Données de l'événement\n\n    match ($event['event_type']) {\n        'transaction.payment.created' =\u003e $this-\u003ehandlePayment($event['event_data']),\n        'transaction.refund.created'  =\u003e $this-\u003ehandleRefund($event['event_data']),\n        default =\u003e null,\n    };\n}\n```\n\n**Retour :** `array{event_type: string, event_type_id: int, event_data: array\u003cstring, mixed\u003e}`\n\nLève `InvalidArgumentException` si le JSON est invalide.\n\n#### `isKnownEvent()` — Vérifier un ID d'événement\n\n```php\n$viva-\u003ewebhooks-\u003eisKnownEvent(1796); // true\n$viva-\u003ewebhooks-\u003eisKnownEvent(9999); // false\n```\n\n#### `eventTypeIds()` — Lister les IDs connus\n\n```php\n$ids = $viva-\u003ewebhooks-\u003eeventTypeIds();\n// [1796, 1797, 1798, ..., 1828]\n```\n\n#### 21 types d'événements supportés\n\n| ID | Type |\n|----|------|\n| 1796 | `transaction.payment.created` |\n| 1797 | `transaction.refund.created` |\n| 1798 | `transaction.payment.cancelled` |\n| 1799 | `transaction.reversal.created` |\n| 1800 | `transaction.preauth.created` |\n| 1801 | `transaction.preauth.completed` |\n| 1802 | `transaction.preauth.cancelled` |\n| 1810 | `pos.session.created` |\n| 1811 | `pos.session.failed` |\n| 1812 | `transaction.price.calculated` |\n| 1813 | `transaction.failed` |\n| 1819 | `account.connected` |\n| 1820 | `account.verification.status.changed` |\n| 1821 | `account.transaction.created` |\n| 1822 | `command.bank.transfer.created` |\n| 1823 | `command.bank.transfer.executed` |\n| 1824 | `transfer.created` |\n| 1825 | `obligation.created` |\n| 1826 | `obligation.captured` |\n| 1827 | `order.updated` |\n| 1828 | `sale.transactions.file` |\n\n---\n\n### 9. Account — `$viva-\u003eaccount`\n\nInformations du compte marchand.\n\n#### `info()` — Informations du compte\n\n```php\n$info = $viva-\u003eaccount-\u003einfo();\necho $info['merchantId'];\necho $info['businessName'];\necho $info['email'];\n```\n\n#### `wallets()` — Portefeuilles du compte\n\n```php\n$wallets = $viva-\u003eaccount-\u003ewallets();\n```\n\n---\n\n### 10. Messages — `$viva-\u003emessages()`\n\nGestion des abonnements webhook via `/api/messages/config` (Legacy API, Basic Auth).\n\n\u003e Utilisez `$viva-\u003ewebhookRegistrar()-\u003eregisterAll(...)` pour l'enregistrement idempotent des events banking. `messages()` donne un accès bas niveau si besoin.\n\n#### `register()` — Créer un abonnement webhook\n\n```php\n$sub = $viva-\u003emessages()-\u003eregister(\n    eventTypeId: 768,                                  // Bank Transfer Created\n    callbackUrl: 'https://example.com/webhooks/viva',\n);\n// =\u003e ['Id' =\u003e 'sub-uuid', 'Active' =\u003e true]\n```\n\n#### `list()` — Lister les abonnements\n\n```php\n$subscriptions = $viva-\u003emessages()-\u003elist();\nforeach ($subscriptions as $sub) {\n    echo $sub['Id'] . ' → EventTypeId: ' . $sub['EventTypeId'];\n}\n```\n\n#### `delete()` — Supprimer un abonnement\n\n```php\n$viva-\u003emessages()-\u003edelete('sub-uuid-here');\n```\n\n---\n\n## Enregistrement des webhooks banking\n\nLes events **768** (Bank Transfer Created), **769** (Bank Transfer Executed) et **2054** (Account Transaction Created) doivent être enregistrés par chaque merchant via `/api/messages/config` (pas via les webhooks ISV).\n\nUtilisez `WebhookRegistrar` pour un enregistrement **idempotent** : les erreurs \"duplicate\" sont silencieusement transformées en `already_exists`.\n\n```php\n// Enregistrer les 3 events banking en une ligne\n$results = $viva-\u003ewebhookRegistrar()-\u003eregisterAll(\n    callbackUrl: 'https://example.com/webhooks/viva',\n);\n// =\u003e ['768' =\u003e 'registered', '769' =\u003e 'registered', '2054' =\u003e 'already_exists']\n\n// Ou un sous-ensemble d'events\n$results = $viva-\u003ewebhookRegistrar()-\u003eregisterAll(\n    callbackUrl: 'https://example.com/webhooks/viva',\n    events: [768, 769],\n);\n```\n\nStatuts possibles dans le tableau retourné :\n\n| Statut | Signification |\n|--------|--------------|\n| `registered` | Abonnement créé avec succès |\n| `already_exists` | Déjà enregistré (Viva a retourné 400 duplicate) |\n| `error:{message}` | Échec inattendu (503, réseau, etc.) |\n\n\u003e **Convention cross-SDK** : `WebhookRegistrar::BANKING_EVENTS` et `registerAll()` ont les mêmes noms dans `sdk-php-viva-isv`. La différence est l'absence de `$connectedMerchantId` — ce SDK parle au nom du merchant lui-même.\n\n---\n\n## Architecture\n\n```\nsrc/\n├── VivaClient.php          # Point d'entrée — instancie les 10 ressources + 1 helper\n├── Config.php              # Configuration (URLs par environnement)\n├── HttpClient.php          # Client HTTP Guzzle (OAuth2 auto, Basic Auth)\n├── Contracts/\n│   ├── HttpClientInterface.php   # Interface pour HttpClient (mocking)\n│   └── MessagesInterface.php     # Interface pour Messages (mocking)\n├── Enums/\n│   ├── Environment.php     # demo | production\n│   ├── Currency.php        # Codes ISO 4217 numériques\n│   └── TransactionStatus.php  # F, A, C, E, M, X, R\n├── Exceptions/\n│   ├── VivaException.php          # Classe de base (RuntimeException)\n│   ├── ApiException.php           # Erreur API (4xx, 5xx)\n│   ├── AuthenticationException.php # Échec OAuth2 (401)\n│   └── ValidationException.php    # Validation (422)\n├── Helpers/\n│   └── WebhookRegistrar.php  # Enregistrement idempotent des events banking\n└── Resources/\n    ├── Orders.php           # Smart Checkout\n    ├── Transactions.php     # Get, list, cancel, capture, recurring\n    ├── Sources.php          # Sources de paiement\n    ├── Wallets.php          # Portefeuilles, soldes, transferts\n    ├── BankAccounts.php     # IBAN, virements SEPA\n    ├── NativeCheckout.php   # Apple Pay, Google Pay\n    ├── DataServices.php     # MT940, souscriptions webhook\n    ├── Webhooks.php         # Vérification et parsing local\n    ├── Account.php          # Infos du compte\n    └── Messages.php         # Abonnements webhook (/api/messages/config)\n```\n\nL'authentification est gérée automatiquement par `HttpClient` :\n- **Legacy API** (Basic Auth) — utilisée par Orders, Transactions, Sources\n- **New API** (Bearer OAuth2) — utilisée par Wallets, BankAccounts, NativeCheckout, DataServices, Account\n\nLe token OAuth2 est mis en cache en mémoire et rafraîchi automatiquement avant expiration.\n\n---\n\n## Enums\n\n### `Environment`\n\n```php\nuse QrCommunication\\VivaMerchant\\Enums\\Environment;\n\n$env = Environment::DEMO;\n$env = Environment::PRODUCTION;\n$env = Environment::from('demo');\n\n$env-\u003evalue;         // 'demo'\n$env-\u003eapiUrl();      // 'https://demo-api.vivapayments.com'\n$env-\u003elegacyUrl();   // 'https://demo.vivapayments.com'\n$env-\u003echeckoutUrl(); // 'https://demo.vivapayments.com/web/checkout'\n$env-\u003eaccountsUrl(); // 'https://demo-accounts.vivapayments.com'\n```\n\n### `Currency`\n\n```php\nuse QrCommunication\\VivaMerchant\\Enums\\Currency;\n\nCurrency::EUR-\u003evalue;     // 978\nCurrency::EUR-\u003eiso();     // 'EUR'\nCurrency::fromIso('GBP'); // Currency::GBP (826)\n```\n\nDevises 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).\n\n### `TransactionStatus`\n\n```php\nuse QrCommunication\\VivaMerchant\\Enums\\TransactionStatus;\n\n$status = TransactionStatus::from('F');\n$status-\u003eisSuccessful();  // true\n$status-\u003eisPending();     // false\n$status-\u003eisFailed();      // false\n$status-\u003elabel();         // 'Finalized'\n```\n\n| Valeur | Constante | `isSuccessful()` | `isPending()` | `isFailed()` |\n|--------|-----------|:-:|:-:|:-:|\n| `F` | `FINALIZED` | oui | | |\n| `A` | `PENDING` | | oui | |\n| `C` | `CLEARING` | | oui | |\n| `E` | `ERROR` | | | oui |\n| `M` | `MANUALLY_REVERSED` | | | oui |\n| `X` | `REQUIRES_ACTION` | | | |\n| `R` | `REFUNDED` | | | |\n\n---\n\n## Gestion d'erreurs\n\nToutes les exceptions héritent de `VivaException` qui étend `RuntimeException`.\n\n```\nRuntimeException\n└── VivaException\n    ├── ApiException\n    ├── AuthenticationException\n    └── ValidationException\n```\n\n```php\nuse QrCommunication\\VivaMerchant\\Exceptions\\ApiException;\nuse QrCommunication\\VivaMerchant\\Exceptions\\AuthenticationException;\nuse QrCommunication\\VivaMerchant\\Exceptions\\ValidationException;\nuse QrCommunication\\VivaMerchant\\Exceptions\\VivaException;\n\ntry {\n    $order = $viva-\u003eorders-\u003ecreate(amount: 1500);\n} catch (AuthenticationException $e) {\n    // Identifiants invalides — httpStatus = 401\n    echo $e-\u003egetMessage();\n} catch (ValidationException $e) {\n    // Erreur de validation — httpStatus = 422\n    foreach ($e-\u003eerrors as $field =\u003e $messages) {\n        echo \"$field: \" . implode(', ', $messages);\n    }\n} catch (ApiException $e) {\n    // Erreur API générale — 400, 404, 500, etc.\n    echo $e-\u003ehttpStatus;\n    echo $e-\u003egetErrorCode();\n    echo $e-\u003egetErrorText();\n    print_r($e-\u003eresponseBody);\n} catch (VivaException $e) {\n    // Toute autre erreur SDK\n}\n```\n\n### Propriétés et méthodes de `VivaException`\n\n| Membre | Type | Description |\n|--------|------|-------------|\n| `$httpStatus` | `int` | Code HTTP de la réponse |\n| `$responseBody` | `?array` | Corps JSON décodé de la réponse |\n| `getErrorCode()` | `?int` | Code d'erreur Viva (`ErrorCode`) |\n| `getErrorText()` | `?string` | Message d'erreur Viva (`ErrorText`, `message`, ou `detail`) |\n\n---\n\n## Webhooks — Guide d'intégration\n\n### 1. Configurer le webhook dans le Dashboard Viva\n\n1. Aller dans **Settings \u003e API Access \u003e Webhooks**\n2. Ajouter l'URL de votre endpoint\n3. Noter la **clé de vérification**\n\n### 2. Gérer la vérification (GET)\n\n```php\n// Route GET /webhooks/viva\npublic function verify()\n{\n    return response()-\u003ejson(\n        $viva-\u003ewebhooks-\u003everificationResponse('votre-clé')\n    );\n}\n```\n\n### 3. Recevoir les événements (POST)\n\n```php\n// Route POST /webhooks/viva\npublic function handle(Request $request)\n{\n    $event = $viva-\u003ewebhooks-\u003eparse($request-\u003egetContent());\n\n    match ($event['event_type']) {\n        'transaction.payment.created'   =\u003e $this-\u003eonPayment($event['event_data']),\n        'transaction.refund.created'    =\u003e $this-\u003eonRefund($event['event_data']),\n        'transaction.preauth.created'   =\u003e $this-\u003eonPreauth($event['event_data']),\n        'transaction.preauth.completed' =\u003e $this-\u003eonCapture($event['event_data']),\n        default =\u003e logger()-\u003einfo('Webhook ignoré : ' . $event['event_type']),\n    };\n\n    return response()-\u003ejson(['status' =\u003e 'ok']);\n}\n```\n\n### 4. Enregistrement des webhooks banking par API (optionnel)\n\nLes events **768**, **769** et **2054** (virements et transactions de compte) ne peuvent pas être configurés depuis le Dashboard Viva pour les marchands standard. Ils doivent être enregistrés **par API** via `/api/messages/config`.\n\n```php\n// Enregistrement idempotent au démarrage de l'application\n$results = $viva-\u003ewebhookRegistrar()-\u003eregisterAll(\n    callbackUrl: config('services.viva.webhook_url'),\n);\n\n// $results = ['768' =\u003e 'registered', '769' =\u003e 'registered', '2054' =\u003e 'already_exists']\n// Les 'already_exists' sont silencieux — safe à relancer à chaque boot.\n```\n\n\u003e **Distinction ISV vs merchant** : dans le SDK ISV (`sdk-php-viva-isv`), ces events sont enregistrés au niveau de l'ISV pour un `connectedMerchantId`. Ici, ils s'appliquent directement au compte marchand authentifié.\n\n---\n\n## Carte de test\n\nPour l'environnement `demo` :\n\n| Champ | Valeur |\n|-------|--------|\n| Numéro de carte | `4111 1111 1111 1111` |\n| Expiration | Toute date future |\n| CVV | `111` |\n| 3DS | Pas de 3DS en demo |\n\n---\n\n## Documentation interactive\n\nLa documentation interactive (ReDoc) est disponible en ligne :\n\n**[https://qrcommunication.github.io/sdk-php-viva-merchant/](https://qrcommunication.github.io/sdk-php-viva-merchant/)**\n\nElle détaille chaque classe, méthode, paramètre et type de retour du SDK.\n\n---\n\n## Intégration IA\n\nCe 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.\n\n| Outil | Fichier | Détection |\n|-------|---------|-----------|\n| **Claude Code** | `CLAUDE.md` + `skill/SKILL.md` | Automatique |\n| **Cursor** | `.cursorrules` | Automatique |\n| **GitHub Copilot** | `.github/copilot-instructions.md` | Automatique |\n| **OpenAI Codex** | `AGENTS.md` | Automatique |\n\n```php\n// Un agent IA peut construire cet appel à partir de :\n// \"Crée un paiement de 25 EUR pour une consultation\"\n$order = $viva-\u003eorders-\u003ecreate(\n    amount: 2500,\n    customerDescription: 'Consultation',\n);\n```\n\n---\n\n## Licence\n\nMIT — [QrCommunication](https://qrcommunication.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqrcommunication%2Fsdk-php-viva-merchant","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqrcommunication%2Fsdk-php-viva-merchant","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqrcommunication%2Fsdk-php-viva-merchant/lists"}