Intégration Stripe Payment Element
Injectez l'identifiant de session RefCampaign dans un PaymentIntent quand vous construisez un checkout custom avec Stripe Elements.
Stripe Elements permet d'embarquer le formulaire de paiement Stripe dans votre propre UI au lieu de rediriger vers Stripe Checkout. RefCampaign attribue les conversions Elements de la même manière que celles de Checkout : en lisant la valeur refcampaign_session que vous attachez aux metadata Stripe. Aucun webhook spécifique à Elements à enregistrer, aucune configuration supplémentaire côté Stripe.
Quand utiliser ce guide
Utilisez ce guide si votre checkout repose sur :
- Payment Element — le formulaire drop-in unifié.
- Express Checkout Element — Apple Pay, Google Pay, Link.
- Un flow custom qui appelle
stripe.paymentIntents.create()côté serveur etstripe.confirmPayment()côté client.
Si vous redirigez vers Stripe Checkout, voyez plutôt le guide SDK — le pattern d'intégration est identique, seul l'emplacement de l'appel à la metadata change.
Démarrage rapide
- 1
Capturer la session côté navigateur
Appelez
RefCampaignBrowser.captureSession()une fois par chargement de page — typiquement dans votre layout racine. La méthode lit la session depuis l'URL (?_rcid=ou?rcsid=), le cookie_rc_sidoulocalStorage, dans cet ordre, et la persiste pour les lectures ultérieures.'use client' import { useEffect } from 'react' import { RefCampaignBrowser } from '@refcampaign/sdk' export default function RootLayout({ children }: { children: React.ReactNode }) { useEffect(() => { RefCampaignBrowser.captureSession() }, []) return ( <html> <body>{children}</body> </html> ) }Si vous utilisez le snippet CDN (
<script src="https://sdk.refcampaign.com/v1.js" async>), cette étape est automatique. - 2
Envoyer l'identifiant de session au backend
Lisez l'identifiant capturé depuis le SDK et passez-le avec votre requête de checkout. Si le visiteur vient d'un lien d'affiliation, la valeur est non-nulle ; sinon la requête passe quand même avec une metadata vide.
'use client' import { RefCampaignBrowser } from '@refcampaign/sdk' async function startCheckout(amount: number, currency: string) { const sessionId = RefCampaignBrowser.getSessionId() const res = await fetch('/api/payment-intent', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ amount, currency, sessionId }), }) const { clientSecret } = await res.json() return clientSecret } - 3
Créer le PaymentIntent avec la metadata RefCampaign
Côté serveur, attachez
rc.getStripeMetadata(sessionId)au PaymentIntent. Stripe recopie automatiquement les metadata du PaymentIntent sur le Charge généré, et c'est ce Charge que RefCampaign lit pour l'attribution.// app/api/payment-intent/route.ts import { NextRequest, NextResponse } from 'next/server' import { RefCampaignServer } from '@refcampaign/sdk' import Stripe from 'stripe' const rc = new RefCampaignServer(process.env.REFCAMPAIGN_SECRET_KEY!) const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!) export async function POST(req: NextRequest) { const { amount, currency, sessionId } = await req.json() const paymentIntent = await stripe.paymentIntents.create({ amount, currency, automatic_payment_methods: { enabled: true }, metadata: rc.getStripeMetadata(sessionId), }) return NextResponse.json({ clientSecret: paymentIntent.client_secret }) }getStripeMetadataretourne{ refcampaign_session: '...' }pour un identifiant valide, et{}sinon — passez le résultat directement, aucun conditionnel n'est nécessaire. - 4
Monter Payment Element et confirmer
Code Stripe Elements standard — rien de spécifique à RefCampaign. La metadata est déjà sur le PaymentIntent.
'use client' import { Elements, PaymentElement, useElements, useStripe } from '@stripe/react-stripe-js' import { loadStripe } from '@stripe/stripe-js' const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!) export function CheckoutForm({ clientSecret }: { clientSecret: string }) { return ( <Elements stripe={stripePromise} options={{ clientSecret }}> <PayForm /> </Elements> ) } function PayForm() { const stripe = useStripe() const elements = useElements() async function handleSubmit(e: React.FormEvent) { e.preventDefault() if (!stripe || !elements) return await stripe.confirmPayment({ elements, confirmParams: { return_url: `${window.location.origin}/checkout/success` }, }) } return ( <form onSubmit={handleSubmit}> <PaymentElement /> <button type="submit">Payer</button> </form> ) }
Comment l'attribution se déclenche
Une fois le paiement réussi, Stripe crée un Charge dont les metadata portent refcampaign_session (recopié depuis le PaymentIntent). RefCampaign le capte par l'un de ces deux chemins, selon le mode de connexion du compte marchand :
- Comptes connectés via OAuth : événement
charge.succeededreçu sur le webhook RefCampaign en quelques secondes. - Comptes par clé API : polling toutes les 30 minutes — la conversion apparaît dans le dashboard au cycle de polling suivant.
Vous n'enregistrez aucun webhook sur votre compte Stripe et vous n'appelez pas l'API RefCampaign directement. La metadata est le seul contrat.
Abonnements via Elements
Si vous créez la Subscription côté serveur après collecte du paiement avec Elements, placez la metadata sur la Subscription, pas sur le Customer :
const subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [{ price: priceId }],
metadata: rc.getStripeMetadata(sessionId),
})Chaque subscription est liée à une seule campagne d'affiliation. Les renouvellements futurs créditent le même affilié ; si le client se réabonne plus tard via un autre lien, la nouvelle subscription est attribuée au nouvel affilié.
Fallback en cas de session perdue
Si RefCampaignBrowser.getSessionId() retourne null au moment du checkout (Safari ITP, cross-device, flow uniquement serveur), appelez RefCampaignBrowser.identify(customer.email) après la connexion ou avant le paiement. RefCampaign attribue alors via le hash SHA-256 de l'email sur le clic le plus récent dans la fenêtre d'attribution de la campagne.
'use client'
import { RefCampaignBrowser } from '@refcampaign/sdk'
// Après connexion ou inscription, quand l'email est connu
await RefCampaignBrowser.identify(currentUser.email)L'email est haché dans le navigateur via Web Crypto — la valeur en clair ne quitte jamais le poste du visiteur.
Objet Charge requis pour l'attribution par webhook
RefCampaign lit refcampaign_session depuis les metadata du Charge, créé par Stripe dès la confirmation réussie du PaymentIntent dans un flow standard. Les flows custom qui confirment sans produire de Charge — par exemple capture manuelle maintenue indéfiniment, vérification ACH par micro-dépôts avant capture finale, ou PaymentIntents qui contournent les Charges via Treasury — ne déclenchent l'attribution qu'à l'arrivée du Charge. Pour ces cas, déclenchez la conversion via le postback serveur à serveur depuis votre propre signal de succès.
Pour aller plus loin
- Intégration SDK — référence complète de
RefCampaignBrowseretRefCampaignServer. - Postback serveur à serveur — stacks non-JS, processeurs custom, ou fallback pour les flows Stripe non standards.