Aller au contenu principal
QualiForma
CatalogueDevenir formateurQualiopiIADéveloppeurs
Connexion
  • Catalogue
  • Devenir formateur
  • Qualiopi
  • IA
  • Développeurs
  • Connexion
  • Vue d'ensemble

Démarrage

  • Quickstart
  • Authentification

Référence

  • API Reference (Scalar)

Endpoints

  • Tous les endpoints

Cœur LMS

  • Tenants
  • Utilisateurs
  • Formations
  • Inscriptions
  • Sessions live

Conformité Qualiopi

  • Dashboard Qualiopi
  • Conformité
  • Émargement
  • Questionnaires
  • Réclamations
  • Plans d'amélioration
  • Parcours adaptatifs
  • Compétences formateurs
  • BPF
  • Médiateurs

Paiements & Facturation

  • Paiements
  • Facturation Factur-X
  • Webhooks

Design System

  • Vue d'ensemble
  • Couleurs
  • Typographie
  • Espacement
  • Elevation
  • Motion
  • Radius
  • Composants
  • · Formulaires
  • · Feedback
  • · Navigation
  • · Progression
  • · Données
Swagger UI (s'ouvre dans un nouvel onglet)
  1. Développeurs
  2. Endpoints
  3. Paiements

Paiements

Flux de paiement via Viva Wallet ISV (par défaut) ou Stripe Connect. Requiert le rôle ADMIN.

Architecture ISV : Les paiements Viva ISV transitent par QualiForma avec split automatique entre la plateforme et le tenant. Pour Stripe Connect, le split est géré par Stripe directement. Les formations FREE ne passent pas par ce flux.

Schéma Payment

Champs du modèle Payment
ChampTypeDescription
idstringIdentifiant unique (pay_...)
courseIdstringFormation associée
userIdstringApprenant payant
amountnumberMontant en centimes
currencystringCode ISO 4217 (EUR...)
gatewayenumVIVA_ISV | STRIPE | FREE
statusenumPENDING | CAPTURED | REFUNDED | FAILED
gatewayPaymentIdstringID côté gateway (pour support)
createdAtstringDate de création ISO 8601

POST/payments/intent

Crée une intention de paiement et retourne une URL de redirection vers le portail de paiement. Après paiement, le gateway redirige vers successUrl ou cancelUrl.

Créer une intention de paiement · Python
import requests

# Créer une intention de paiement (Viva ISV par défaut)
response = requests.post(
    'https://api.qualiforma.site/api/v1/payments/intent',
    headers={
        'Authorization': f'Bearer {access_token}',
        'X-Tenant-ID': 'votre-tenant',
        'Content-Type': 'application/json'
    },
    json={
        'courseId': 'crs_abc123',
        'userId': 'usr_xyz789',
        'gateway': 'VIVA_ISV',
        'successUrl': 'https://votre-app.com/success',
        'cancelUrl': 'https://votre-app.com/cancel'
    }
)

intent = response.json()['data']
print(f"Paiement {intent['paymentId']} — rediriger vers {intent['redirectUrl']}")
Créer une intention de paiement · cURL / Shell
TOKEN="eyJhbGci..."

# Créer une intention de paiement (Viva ISV par défaut)
curl -X POST https://api.qualiforma.site/api/v1/payments/intent \
  -H "Authorization: Bearer $TOKEN" \
  -H 'X-Tenant-ID: votre-tenant' \
  -H 'Content-Type: application/json' \
  -d '{
    "courseId": "crs_abc123",
    "userId": "usr_xyz789",
    "gateway": "VIVA_ISV",
    "successUrl": "https://votre-app.com/success",
    "cancelUrl": "https://votre-app.com/cancel"
  }'

# Réponse :
# {
#   "data": {
#     "paymentId": "pay_ghi012",
#     "redirectUrl": "https://www.vivapayments.com/web/checkout?ref=...",
#     "expiresAt": "2026-01-01T13:00:00Z"
#   }
# }
Créer une intention de paiement · TypeScript
interface CreatePaymentIntentInput {
  courseId: string;
  userId: string;
  gateway: 'VIVA_ISV' | 'STRIPE';
  successUrl: string;
  cancelUrl: string;
}

interface PaymentIntent {
  paymentId: string;
  redirectUrl: string;
  expiresAt: string;
}

async function createPaymentIntent(
  input: CreatePaymentIntentInput,
  accessToken: string,
  tenantId: string,
): Promise<PaymentIntent> {
  const response = await fetch('https://api.qualiforma.site/api/v1/payments/intent', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${accessToken}`,
      'X-Tenant-ID': tenantId,
    },
    body: JSON.stringify(input),
  });

  if (!response.ok) {
    throw new Error(`Erreur ${response.status}`);
  }
  const { data } = await response.json();
  return data;
}
Créer une intention de paiement · PHP
<?php
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;

$client = new Client(['base_uri' => 'https://api.qualiforma.site/api/v1/']);

try {
    // Creer une intention de paiement (Viva ISV par defaut)
    $response = $client->post('payments/intent', [
        'headers' => [
            'Authorization' => 'Bearer ' . $accessToken,
            'X-Tenant-ID' => 'votre-tenant',
            'Content-Type' => 'application/json',
        ],
        'json' => [
            'courseId' => 'crs_abc123',
            'userId' => 'usr_xyz789',
            'gateway' => 'VIVA_ISV', // VIVA_ISV | STRIPE
            'successUrl' => 'https://votre-app.com/success',
            'cancelUrl' => 'https://votre-app.com/cancel',
        ],
    ]);
    $intent = json_decode($response->getBody()->getContents(), true)['data'];
    echo "Paiement {$intent['paymentId']} - rediriger vers {$intent['redirectUrl']}\n";
} catch (GuzzleException $e) {
    fwrite(STDERR, "Erreur: " . $e->getMessage() . PHP_EOL);
}

POST/payments/:id/refund

Remboursement total ou partiel. Omettre amount pour un remboursement total. Requiert ADMIN. Délai de remboursement : 3-5 jours ouvrés.

Rembourser un paiement · Python
import requests

payment_id = 'pay_ghi012'

# Remboursement partiel (5000 centimes = 50 €)
response = requests.post(
    f'https://api.qualiforma.site/api/v1/payments/{payment_id}/refund',
    headers={
        'Authorization': f'Bearer {access_token}',
        'X-Tenant-ID': 'votre-tenant',
        'Content-Type': 'application/json'
    },
    json={'amount': 5000}
)
refund = response.json()['data']
print(f"Remboursement {refund['id']} — statut : {refund['status']}")

# Remboursement total (omettre amount)
requests.post(
    f'https://api.qualiforma.site/api/v1/payments/{payment_id}/refund',
    headers={
        'Authorization': f'Bearer {access_token}',
        'X-Tenant-ID': 'votre-tenant',
        'Content-Type': 'application/json'
    },
    json={}
)
Rembourser un paiement · cURL / Shell
TOKEN="eyJhbGci..."
PAYMENT_ID="pay_ghi012"

# Remboursement partiel (5000 centimes = 50 €)
curl -X POST "https://api.qualiforma.site/api/v1/payments/$PAYMENT_ID/refund" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'X-Tenant-ID: votre-tenant' \
  -H 'Content-Type: application/json' \
  -d '{"amount": 5000}'

# Remboursement total (omettre amount)
curl -X POST "https://api.qualiforma.site/api/v1/payments/$PAYMENT_ID/refund" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'X-Tenant-ID: votre-tenant' \
  -H 'Content-Type: application/json' \
  -d '{}'
Rembourser un paiement · TypeScript
async function refundPayment(
  paymentId: string,
  accessToken: string,
  tenantId: string,
  amount?: number, // centimes — omettre pour remboursement total
) {
  const response = await fetch(
    `https://api.qualiforma.site/api/v1/payments/${paymentId}/refund`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${accessToken}`,
        'X-Tenant-ID': tenantId,
      },
      body: JSON.stringify(amount !== undefined ? { amount } : {}),
    },
  );
  if (!response.ok) {
    throw new Error(`Erreur ${response.status}`);
  }
  const { data } = await response.json();
  return data; // Refund avec status = 'PENDING' | 'COMPLETED'
}
Rembourser un paiement · PHP
<?php
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;

$client = new Client(['base_uri' => 'https://api.qualiforma.site/api/v1/']);
$paymentId = 'pay_ghi012';

try {
    // Remboursement partiel (5000 centimes = 50 EUR)
    $response = $client->post("payments/{$paymentId}/refund", [
        'headers' => [
            'Authorization' => 'Bearer ' . $accessToken,
            'X-Tenant-ID' => 'votre-tenant',
            'Content-Type' => 'application/json',
        ],
        'json' => ['amount' => 5000],
    ]);
    $refund = json_decode($response->getBody()->getContents(), true)['data'];
    echo "Remboursement {$refund['id']} - statut : {$refund['status']}\n";

    // Remboursement total (omettre amount)
    $client->post("payments/{$paymentId}/refund", [
        'headers' => [
            'Authorization' => 'Bearer ' . $accessToken,
            'X-Tenant-ID' => 'votre-tenant',
            'Content-Type' => 'application/json',
        ],
        'json' => new \stdClass(), // {} JSON object vide
    ]);
} catch (GuzzleException $e) {
    fwrite(STDERR, "Erreur: " . $e->getMessage() . PHP_EOL);
}
QualiForma

La plateforme de formation professionnelle certifiee Qualiopi.

Plateforme

  • Catalogue
  • Espace formateur
  • Étude de besoin

Societe

  • A propos
  • Contact

Ressources

  • Développeurs
  • Référence API
  • Webhooks

Legal

  • CGV
  • Mentions legales
  • Confidentialite

Catalogue par catégorie

  • Management
  • Digital
  • Communication
  • Langues
  • Sécurité
  • Gestion

Comparatifs

  • QualiForma vs Didask
  • QualiForma vs Edusign
  • QualiForma vs Klaxoon
  • QualiForma vs 360Learning

Glossaire Qualiopi

  • I01 — Conditions d'information
  • I05 — Adaptation des prestations
  • I11 — Évaluations en cours
  • I22 — Compétences des intervenants
  • I30 — Recueil des appréciations
  • Voir les 32 indicateurs →

© 2026 QualiForma. Tous droits reserves.

Certifie Qualiopi