Aller au contenu principal

Démarrage rapide

En 10 minutes : lecture, écriture et réception d'un webhook.

Prérequis : MCM.ApiProxy installé (Installation) + clé API configurée (Configuration).


1. Lire — premier appel

Services/EmployeService.cs
using MCM.ApiProxy.Contracts;
using MCM.B2B.Contracts;

public class EmployeService(IEmployesClient employesClient, ILogger<EmployeService> logger)
{
public async Task<List<B2BEmployeItem>> GetAllEmployesAsync()
{
var result = await employesClient.GetAllEmployes();

if (result.IsError)
{
logger.LogError("Erreur récupération employés: {Error}", result.FirstError.Description);
return [];
}

return result.Value.ToList();
}

public async Task<B2BEmployeItem?> GetEmployeAsync(string idExterne)
{
var result = await employesClient.GetEmployeById(idExterne);
return result.IsError ? null : result.Value;
}
}
Program.cs
using MCM.ApiProxy;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddMcmApiClient(builder.Configuration); // tous les clients en une seule fois
builder.Services.AddScoped<EmployeService>();

var app = builder.Build();
Controllers/EmployesController.cs
[ApiController]
[Route("api/[controller]")]
public class EmployesController(EmployeService service) : ControllerBase
{
[HttpGet]
public async Task<IActionResult> GetAll() => Ok(await service.GetAllEmployesAsync());

[HttpGet("{idExterne}")]
public async Task<IActionResult> GetById(string idExterne)
{
var e = await service.GetEmployeAsync(idExterne);
return e is null ? NotFound() : Ok(e);
}
}

2. Comprendre ErrorOr<T>

Toutes les méthodes du SDK retournent ErrorOr<T>. Aucune ne lance d'exception sur erreur métier ou HTTP.

var result = await employesClient.GetEmployeById("EMP-123");

if (result.IsError)
{
var e = result.FirstError;
// e.Code → "Employe.NotFound"
// e.Description → "Aucun employé n'existe avec cet identifiant."
// e.Type → ErrorType.NotFound
// e.Metadata → { "Url": "…", "StatusName": "NotFound", … } selon l'erreur
return;
}

var employe = result.Value;
AspectErrorOrExceptions
PerformancePas de stack unwindingCoûteux à lancer
LisibilitéFlux expliciteFlux caché
Compilationresult.Value non accessible sans vérifier IsError (avec Match/pattern matching)Risque d'oublier le try

Référence complète des codes : catalogue d'erreurs. Patterns de gestion : Gestion des erreurs.


3. Écrire — créer un employé

public async Task<bool> CreateEmployeAsync(B2BUpdateEmployeDto dto)
{
var result = await employesClient.AddEmploye(dto);

if (result.IsError)
{
logger.LogError("Échec création {Id}: [{Code}] {Desc}",
dto.IdExterne, result.FirstError.Code, result.FirstError.Description);
return false;
}

logger.LogInformation("Employé créé: {IdExterne}", dto.IdExterne);
return true;
}

// Appel
await CreateEmployeAsync(new B2BUpdateEmployeDto
{
IdExterne = "PERSON-123",
Prenom = "Alice",
Nom = "Tremblay",
Courriel = "alice@example.com",
NoMembre = "NM-2026-001",
IdentifiantExterneEmployeur = "EMP001",
Matricule = "A123"
});

Pour un import groupé, ne bouclez pas sur AddEmploye. Utilisez ISyncClient.Sync — un seul appel pour des milliers d'employés. Voir Synchronisation des employés.


4. Recevoir un webhook

Quand un événement métier intéressant se produit côté MCM (adhésion signée, liste électorale créée, …), MCM peut envoyer les données à votre application au lieu de vous obliger à les interroger périodiquement.

4.1 Configurer le récepteur

appsettings.json
{
"McmApi": {
"BaseUrl": "https://mcm-dev.neosapiens.com/",
"ApiKey": "<votre-cle>",
"WebhookSecret": "<base64-fourni-par-mcm>"
}
}
Program.cs (suite)
using MCM.ApiProxy.Webhooks;
using MCM.B2B.Contracts.V2;
using MCM.B2B.Contracts.Webhooks;

builder.Services.AddMcmWebhookReceiver(builder.Configuration)
.AddHandler<AdhesionSigneeHandler, B2BAdhesionItemV2>(WebhookEventTypes.AdhesionSignee);

var app = builder.Build();

app.MapMcmWebhooks("/webhooks/mcm");

4.2 Écrire le handler

Webhooks/AdhesionSigneeHandler.cs
using MCM.B2B.Contracts.V2;
using MCM.B2B.Contracts.Webhooks;

public class AdhesionSigneeHandler(ILogger<AdhesionSigneeHandler> logger)
: IMcmWebhookHandler<B2BAdhesionItemV2>
{
public Task HandleAsync(B2BWebhookPayload<B2BAdhesionItemV2> p, CancellationToken ct)
{
logger.LogInformation(
"Adhésion {Id} signée pour {Employe} (syndicat {Syndicat})",
p.Data.IdUniqueAdhesion, p.Data.EmployeIdExterne, p.Data.SyndicatIdExterne);
return Task.CompletedTask;
}
}

C'est tout. Le middleware fourni par le SDK :

  • valide la signature HMAC-SHA256 (X-MCM-Signature),
  • vérifie l'âge du timestamp (X-MCM-Timestamp, fenêtre 5 min),
  • désérialise typé vers B2BWebhookPayload<TData>,
  • résout votre handler depuis le DI.

Tester localement : exposez votre service via ngrok http 5050 et donnez l'URL à l'admin MCM. Détails : Webhooks.


5. Code complet (récapitulatif)

Program.cs (complet)
using MCM.ApiProxy;
using MCM.ApiProxy.Webhooks;
using MCM.B2B.Contracts.V2;
using MCM.B2B.Contracts.Webhooks;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddMcmApiClient(builder.Configuration);
builder.Services.AddScoped<EmployeService>();

builder.Services.AddMcmWebhookReceiver(builder.Configuration)
.AddHandler<AdhesionSigneeHandler, B2BAdhesionItemV2>(WebhookEventTypes.AdhesionSignee);

builder.Services.AddControllers();

var app = builder.Build();

app.MapControllers();
app.MapMcmWebhooks("/webhooks/mcm");

app.Run();

Prochaines étapes


Voir un exemple complet

L'application CLI MCM.ApiProxy.Cli couvre tous les clients du SDK avec un menu interactif (Spectre.Console). C'est la référence vivante pour explorer l'API.