
Stripe peut transporter l'attribution RefCampaign via les metadata. Le détail important est l'emplacement de ces metadata : metadata de subscription pour le revenu récurrent, metadata de Payment Intent pour les paiements uniques.

Ce guide suppose que votre frontend capture déjà la session RefCampaign avec le SDK navigateur ou le script CDN.

## Prérequis

- Un compte Stripe avec Checkout activé.
- Une clé secrète RefCampaign.
- Le package `@refcampaign/sdk` installé côté backend.
- Une route serveur qui crée les sessions Stripe Checkout.

```bash
pnpm add @refcampaign/sdk stripe
```

Stockez les secrets uniquement côté serveur :

```bash
REFCAMPAIGN_SECRET_KEY=sk_live_votre_secret_refcampaign
STRIPE_SECRET_KEY=sk_live_votre_secret_stripe
APP_URL=https://votreapp.com
```

## Initialiser le SDK serveur

Créez un petit module importable par vos routes checkout.

```ts
// lib/billing.ts
import Stripe from 'stripe'
import { RefCampaignServer } from '@refcampaign/sdk'

export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)
export const refcampaign = new RefCampaignServer(
  process.env.REFCAMPAIGN_SECRET_KEY!
)
```

## Checkout subscription

Pour les produits récurrents, placez les metadata RefCampaign sur `subscription_data.metadata`. Les renouvellements pourront continuer à créditer le même affilié.

```ts
// app/api/stripe/checkout-subscription/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { refcampaign, stripe } from '@/lib/billing'

export async function POST(request: NextRequest) {
  const { priceId, customerEmail } = await request.json()
  const sessionId = request.cookies.get('_rc_sid')?.value

  const session = await stripe.checkout.sessions.create({
    mode: 'subscription',
    customer_email: customerEmail,
    line_items: [{ price: priceId, quantity: 1 }],
    subscription_data: {
      metadata: refcampaign.getStripeMetadata(sessionId),
    },
    success_url: `${process.env.APP_URL}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.APP_URL}/pricing`,
  })

  return NextResponse.json({ url: session.url })
}
```

## Checkout paiement unique

Pour les produits payés une seule fois, placez les metadata sur `payment_intent_data.metadata`.

```ts
// app/api/stripe/checkout-payment/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { refcampaign, stripe } from '@/lib/billing'

export async function POST(request: NextRequest) {
  const { priceId, customerEmail } = await request.json()
  const sessionId = request.cookies.get('_rc_sid')?.value

  const session = await stripe.checkout.sessions.create({
    mode: 'payment',
    customer_email: customerEmail,
    line_items: [{ price: priceId, quantity: 1 }],
    payment_intent_data: {
      metadata: refcampaign.getStripeMetadata(sessionId),
    },
    success_url: `${process.env.APP_URL}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.APP_URL}/pricing`,
  })

  return NextResponse.json({ url: session.url })
}
```

## Vérifier la couverture webhook

RefCampaign traite les revenus Stripe via votre intégration marchand. Votre rôle est de vérifier que les metadata existent avant que Stripe émette l'événement payé.

Utilisez Stripe CLI pour inspecter un checkout de test :

```bash
stripe listen --forward-to localhost:3000/api/webhooks/stripe
stripe trigger checkout.session.completed
```

Pour un vrai test manuel, créez un checkout depuis votre UI après avoir cliqué un lien affilié. Dans le dashboard Stripe :

- ouvrez la Checkout Session ;
- ouvrez la Subscription ou le Payment Intent ;
- vérifiez que `refcampaign_session` apparaît dans les metadata.

## Gérer les sessions absentes

Tous les acheteurs ne viennent pas d'un affilié. `getStripeMetadata()` peut être appelé avec une session ID absente, et le checkout doit continuer normalement.

```ts
const metadata = refcampaign.getStripeMetadata(sessionId)

const subscriptionData =
  Object.keys(metadata).length > 0
    ? { metadata }
    : undefined
```

Utilisez ce pattern si votre helper Stripe refuse les objets metadata vides.

## Erreurs fréquentes

Ne placez pas l'attribution subscription uniquement sur les metadata Customer. Les metadata Customer sont partagées entre achats futurs et peuvent créditer le mauvais affilié quand un client se réabonne plus tard.

N'attachez pas l'attribution d'un paiement unique uniquement à la Checkout Session. RefCampaign a besoin des metadata sur l'objet Stripe qui représente l'événement payé.

Ne loggez pas les clés secrètes RefCampaign ni les payloads Stripe complets en production. Les metadata peuvent être inspectées, les secrets non.

## Étapes suivantes

Associez cette configuration au [guide Next.js affiliate tracking](/fr/guides/suivi-affiliation-nextjs) si votre checkout vit dans App Router. Pour le contexte plus large, lisez [comment fonctionne le suivi d'affiliation](/fr/blog/suivi-affiliation-fonctionnement-pannes-corrections) et gardez la [référence SDK](https://docs.refcampaign.com/fr/docs/integration/sdk) sous la main pendant la review.
