Intégrer une prise de RDV au paiement Stripe — le cas d'un artisan d'art de la Côte d'Azur
Comment un artisan de feuilles de pierre a quadruplé sa transformation en intégrant la sélection du créneau d'installation directement dans le tunnel de paiement. Architecture, code, résultat.
Un artisan de feuilles de pierre sur la Côte d'Azur me contacte fin 2024. Beau métier, jolie clientèle premium, chiffre correct mais transformation autour de 3 % sur le site. Le tunnel d'achat fonctionne — c'est ce qui se passe après qui plombe.
Le client paye sur Wix. Il reçoit un mail de confirmation. Trois jours plus tard, l'équipe de pose l'appelle pour caler une date d'installation. Aller-retours téléphoniques sur deux semaines. Calendrier saturé en juin et juillet, créneaux libres en septembre. Le client commence à regretter, parfois annule.
L'artisan voyait clairement le problème. Il ne voyait pas la solution.
Voici l'architecture que j'ai construite avec lui, et le résultat à six mois.
L'idée tient en une phrase
Le client doit choisir son créneau d'installation au moment où il paye, pas trois jours après.
C'est exactement le moment où il est le plus engagé. Il a sa carte bancaire en main, il a pris sa décision. Lui demander une information supplémentaire à cet instant ne le freine pas — au contraire, ça lui apporte de la certitude.
L'outil grand public que cet artisan utilisait (Wix avec deux apps payantes) rendait cette logique difficile. Wix gérait le panier. L'app de réservation gérait l'agenda. Mais relier les deux dans un tunnel unique demandait des contorsions qui finissaient toujours par une étape supplémentaire pour le client.
Le sur mesure rend ça trivial.
Architecture
Voici les briques qu'on a assemblées.
Front-end : Next.js 16 avec App Router. Catalogue des feuilles de pierre, panier, fiche projet (m² à poser, texture, finition).
Paiement : Stripe Checkout. Pas d'intégration custom du paiement — Stripe gère le tunnel sécurisé, le PCI DSS, la gestion des cartes étrangères, Klarna 3× quand le montant est éligible. On lui passe juste les line_items et il s'occupe du reste.
Agenda d'installation : table Postgres simple. Une table creneaux_pose avec date, capacité (combien de poses simultanées possibles selon les équipes disponibles), durée moyenne par projet selon le m². Pas besoin de Cal.com ou Calendly — l'agenda est métier-spécifique.
Liaison : webhook Stripe + metadata. C'est la pièce centrale.
Voici comment ça s'enchaîne.
Le tunnel côté client
L'utilisateur configure son projet — surface, modèle, finition. Le panier calcule le prix et la durée d'installation estimée (par exemple : « 28 m² → demi-journée d'installation »).
L'utilisateur clique « Réserver ». Au lieu de l'envoyer directement vers Stripe, on affiche d'abord l'agenda. Les créneaux disponibles sont calculés en temps réel : on filtre les dates qui ont assez de capacité résiduelle pour absorber cette durée d'installation.
L'utilisateur choisit son créneau. On le pré-réserve pendant 10 minutes (verrou applicatif) — pour éviter qu'un autre acheteur ne prenne le même créneau pendant que celui-ci finit son paiement.
On crée la session Stripe Checkout avec deux informations passées en metadata :
const session = await stripe.checkout.sessions.create({
mode: "payment",
payment_method_types: ["card", "klarna"],
line_items: [
{
quantity: 1,
price_data: {
currency: "eur",
unit_amount: totalCents,
product_data: {
name: `Pose feuilles de pierre — ${m2}m² ${modele}`,
description: `${modele} ${finition} · Installation prévue le ${creneauISO}`,
},
},
},
],
metadata: {
creneau_id: creneauChoisi.id,
duree_pose_min: dureePoseMin,
customer_session_id: sessionTransitoire,
},
success_url: `${origin}/merci?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${origin}/configurer?slot=${creneauChoisi.id}`,
});L'utilisateur paye sur Stripe. Stripe nous renvoie un webhook checkout.session.completed.
Le webhook fait le vrai travail
export async function POST(req: Request) {
const event = stripe.webhooks.constructEvent(
rawBody, signature, webhookSecret,
);
if (event.type !== "checkout.session.completed") {
return NextResponse.json({ ok: true, ignored: event.type });
}
const session = event.data.object as Stripe.Checkout.Session;
const creneauId = session.metadata?.creneau_id;
if (!creneauId) {
// Sécurité : on ne valide pas un paiement sans créneau lié
return NextResponse.json({ ok: false, reason: "no slot" }, { status: 400 });
}
// Idempotence : si on a déjà traité ce paiement, on stoppe
const { data: existing } = await supabase
.from("commandes")
.select("id")
.eq("stripe_session_id", session.id)
.maybeSingle();
if (existing) {
return NextResponse.json({ ok: true, replay: true });
}
// 1. Crée la commande
await supabase.from("commandes").insert({
stripe_session_id: session.id,
montant_cents: session.amount_total,
email: session.customer_details?.email,
nom: session.customer_details?.name,
creneau_id: creneauId,
duree_pose_min: parseInt(session.metadata?.duree_pose_min ?? "0", 10),
});
// 2. Confirme le créneau (lève le verrou pré-réservation, le rend officiel)
await supabase
.from("creneaux_pose")
.update({ statut: "confirme" })
.eq("id", creneauId);
// 3. Envoie les emails (client + poseur)
await sendConfirmationToClient({ email, creneau, projet });
await sendNouvelleInstallationToTeam({ creneau, projet });
return NextResponse.json({ ok: true });
}Le webhook a trois propriétés essentielles. Il est idempotent (rejouer le même webhook ne duplique rien). Il échoue ouvertement (un paiement sans créneau lié est un bug à réparer, pas à masquer). Il confirme à la fois côté client et côté poseur, dans le même mouvement.
Le résultat à six mois
| Métrique | Avant | Après | |---|---|---| | Taux de transformation (visite → achat) | 3 % | 12 % | | Délai moyen entre achat et pose | 17 jours | 9 jours | | Coups de téléphone par projet | 3-4 | 0-1 | | Pose annulée par le client | 8 % | 1,5 % | | Agenda de pose pré-réservé à J+30 | 35 % | 92 % |
La transformation a quadruplé. Mais le chiffre que je trouve plus parlant, c'est le dernier — l'agenda est rempli trois semaines à l'avance. L'équipe de pose ne pose plus la question « qu'est-ce qu'on fait la semaine prochaine ? ». Elle sait. La marge se déplace de la prospection vers la pose.
Ce qui rend cette architecture difficile sur un Wix
Trois raisons techniques expliquent pourquoi ce type d'intégration ne se fait pas proprement sur les plateformes grand public.
Le timing de la mise à jour de l'agenda. Wix peut intégrer une app de réservation, mais elle est pilotée depuis l'admin. La synchroniser au moment du paiement Stripe demande un connecteur que personne ne propose vraiment.
Le verrou de pré-réservation. Quand vous proposez un créneau à un acheteur, vous devez le bloquer pendant qu'il finit son paiement (sinon deux personnes peuvent choisir le même créneau simultanément). Ce verrou applicatif demande de la logique métier que les apps no-code rendent extrêmement difficile.
Le webhook serveur fiable. Stripe envoie son webhook à votre serveur. Avec Wix, vous n'avez pas de serveur — vous avez une plateforme. Vous pouvez éventuellement utiliser une fonction serverless externe, mais vous payez l'orchestration en complexité.
Sur du Next.js déployé sur Vercel, tout est natif. Le webhook arrive sur une route handler, lit la metadata, met à jour la base. Zéro orchestration externe.
Ce qui rend cette architecture portable
Si vous êtes artisan, ce schéma s'adapte directement à tout métier où l'installation est partie de la prestation :
- Marbrier (cuisines, salles de bains, terrasses)
- Ébéniste (mobilier sur mesure livré et posé)
- Cuisiniste (livraison + montage)
- Stores et fermetures (volets roulants, pergolas)
- Climatiseurs et chauffagistes
- Piscinistes (entretien programmé)
- Paysagiste (création de jardin)
Dans tous ces cas, le créneau de pose ou d'intervention est aussi décisif que le prix dans la décision du client. L'intégrer au tunnel de paiement transforme la conversion.
Ce que ça coûte à construire
Pour donner un ordre de grandeur, ce module spécifique (catalogue + configuration projet + agenda + Stripe avec créneau lié) représente environ 1 500 à 3 500 € de développement supplémentaire sur un site sur mesure existant. C'est l'investissement le plus court-amorti que je vois sur ce type de chantier — typiquement compensé en deux à quatre mois sur la hausse de transformation.
Si vous êtes artisan et que cette mécanique vous parle, on peut regarder ensemble votre cas en trente minutes. Pas de pitch, pas d'engagement. Juste un échange honnête sur la faisabilité.
Pour aller plus loin dans la comparaison technique :
- Site sur mesure vs Shopify — où Shopify a du sens, où il n'en a pas
- Site internet artisan d'art Côte d'Azur — le détail de ce qu'on fait sur ces chantiers