Transactions des marchands connectés (capture, récurrent, annulation)
Composite Basic Auth — format non documenté par Viva Wallet
Le format {ResellerID}:{ConnectedMerchantID} comme username avec {ResellerAPIKey} comme password a été découvert empiriquement lors de la certification ISV. Le SDK construit ce header automatiquement — vous passez uniquement le connectedMerchantId aux méthodes de $isv->transactions.
Token OAuth2 — refresh automatique
Le token Bearer est obtenu automatiquement et rafraîchi avant expiration (marge de 60 secondes). Pour forcer un refresh manuel :
$isv->invalidateToken();
Référence des ressources
1
ConnectedAccounts
$isv->accounts
Gestion des comptes marchands connectés à la plateforme ISV. Création, consultation, onboarding KYB, vérification, mise à jour et suppression.
// Créer un compte connecté avec branding
$account = $isv->accounts->create(
email: 'merchant@example.com',
returnUrl: 'https://myapp.com/onboarding/complete',
partnerName: 'Ma Plateforme',
logoUrl: 'https://myapp.com/logo.png',
);
// Rediriger le marchand vers l'onboarding KYB
header('Location: ' . $account['invitation']['redirectUrl']);
// Vérifier le statut KYB
if ($isv->accounts->isVerified($account['accountId'])) {
echo 'Le marchand peut recevoir des paiements';
}
// Récupérer l'URL d'onboarding (null si déjà vérifié)
$url = $isv->accounts->onboardingUrl($account['accountId']);
// Lister tous les comptes connectés
$accounts = $isv->accounts->list();
// Consulter un compte
$details = $isv->accounts->get($account['accountId']);
// Mettre à jour
$isv->accounts->update($account['accountId'], ['email' => 'new@example.com']);
// Supprimer
$isv->accounts->delete($account['accountId']);
2
IsvAccounts
$isv->isvAccounts
Comptes ISV via le namespace /isv/v1/ avec options de branding personnalisé (couleur primaire, logo).
Création d'ordres de paiement Smart Checkout pour les marchands connectés avec commission ISV.
Méthode
Signature
Retour
create
create(string $connectedMerchantId, int $amount, int $isvAmount, ?string $customerDescription, ?string $merchantReference, bool $allowRecurring, bool $preauth)
array{order_code, checkout_url}
checkoutUrl
checkoutUrl(int $orderCode)
string
$order = $isv->orders->create(
connectedMerchantId: 'merchant-uuid',
amount: 1500, // 15,00 EUR
isvAmount: 100, // 1,00 EUR de commission
customerDescription: 'Consultation bien-être',
merchantReference: 'INV-2026-001',
allowRecurring: true, // Tokeniser la carte pour les récurrents
preauth: false,
);
echo $order['order_code']; // 1234567890
echo $order['checkout_url']; // https://demo.vivapayments.com/web/checkout?ref=...
// Reconstruire l'URL à partir d'un code existant
$url = $isv->orders->checkoutUrl(1234567890);
Règles isvAmount :
isvAmount doit être <= amount — sinon InvalidArgumentException.
Le marchand connecté utilise sa source de paiement par défaut — ne jamais passer de sourceCode.
4
IsvTransactions
$isv->transactions
Opérations sur les transactions des marchands connectés. Le SDK utilise automatiquement le Composite Basic Auth pour tous les appels de cette ressource.
// GET — vérification initiale
$verificationKey = config('services.viva.verification_key');
return response()->json(
$isv->webhooks->verificationResponse($verificationKey)
);
// => {"StatusCode": 0, "Key": "votre-cle"}
// POST — parsing des événements
$event = $isv->webhooks->parse(file_get_contents('php://input'));
echo $event['event_type']; // 'transaction.payment.created'
echo $event['event_type_id']; // 1796
$data = $event['event_data'];
// Pattern Laravel Controller
match ($event['event_type']) {
'transaction.payment.created' => $this->handlePayment($event['event_data']),
'transaction.refund.created' => $this->handleRefund($event['event_data']),
'account.connected' => $this->handleNewAccount($event['event_data']),
default => null,
};
// Vérifier si un eventTypeId est connu (méthode statique)
use QrCommunication\VivaIsv\Resources\Webhooks;
if (Webhooks::isKnownEvent(1796)) {
echo 'Événement reconnu';
}
Enums
EcrEventId — codes résultat Cloud Terminal
use QrCommunication\VivaIsv\Enums\EcrEventId;
$event = EcrEventId::tryFrom($session['eventId']);
$event->isSuccessful(); // true si SUCCESS (0)
$event->isTerminal(); // true si état final (pas IN_PROGRESS)
$event->shouldPoll(); // true si IN_PROGRESS (1100)
$event->label(); // 'Transaction successful', 'Declined', etc.
Valeur
Constante
Description
0
SUCCESS
Transaction réussie
1003
TERMINAL_TIMEOUT
Terminal hors délai
1006
DECLINED
Transaction refusée
1016
ABORTED
Transaction annulée
1020
INSUFFICIENT_FUNDS
Fonds insuffisants
1099
GENERIC_ERROR
Erreur générique
1100
IN_PROGRESS
En cours — continuer le polling
6000
BAD_PARAMS
Paramètres invalides
TransactionEventId — codes de déclin détaillés
use QrCommunication\VivaIsv\Enums\TransactionEventId;
$decline = TransactionEventId::tryFrom($session['transactionEventId']);
echo $decline->label(); // 'Insufficient funds'
echo $decline->testAmount(); // 9951 (montant pour déclencher ce déclin en demo)
Valeur
Constante
Montant test (centimes)
10001
REFER_TO_ISSUER
—
10003
INVALID_MERCHANT
—
10004
PICKUP_CARD
—
10005
DO_NOT_HONOR
—
10006
GENERAL_ERROR
9906
10012
INVALID_TRANSACTION
—
10013
INVALID_AMOUNT
—
10014
INVALID_CARD
9914
10030
FORMAT_ERROR
—
10041
LOST_CARD
—
10043
STOLEN_CARD
9920
10051
INSUFFICIENT_FUNDS
9951
10054
EXPIRED_CARD
9954
10055
INCORRECT_PIN
—
10057
NOT_PERMITTED_CARDHOLDER
9957
10058
NOT_PERMITTED_TERMINAL
—
10061
WITHDRAWAL_LIMIT
9961
10062
RESTRICTED_CARD
—
10063
SECURITY_VIOLATION
—
10065
ACTIVITY_LIMIT
—
10068
LATE_RESPONSE
—
10070
CALL_ISSUER
—
10075
PIN_TRIES_EXCEEDED
—
10200
UNMAPPED
—
Environment
use QrCommunication\VivaIsv\Enums\Environment;
// Passer en string ou en enum — les deux sont acceptés
$isv = new VivaIsvClient(..., environment: 'demo');
$isv = new VivaIsvClient(..., environment: Environment::PRODUCTION);
Gestion des erreurs
Le SDK définit 3 exceptions dans le namespace QrCommunication\VivaIsv\Exceptions :
Les méthodes capture() et recurring() lancent ApiException si ErrorCode !== 0 dans la réponse Viva Wallet.
Événements webhook (21)
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
Test en sandbox
Utiliser environment: 'demo' pour tester sans transactions réelles.
Carte de test
Champ
Valeur
Numéro
4111 1111 1111 1111
Expiration
Toute date future
CVV
111
Montants qui déclenchent des déclin en mode demo
use QrCommunication\VivaIsv\Enums\TransactionEventId;
// Obtenir le montant de test pour un type de déclin
$amount = TransactionEventId::INSUFFICIENT_FUNDS->testAmount(); // 9951
$order = $isv->orders->create('merchant-uuid', $amount);