Next.js + Stripe Integration
This guide demonstrates how to integrate DaisyChain with a Next.js application using Stripe for payments.
Prerequisites
- Next.js 13+ project
- Stripe account
- DaisyChain account
Installation
npm install @daisychain/sdk @stripe/stripe-js stripe
Environment Setup
Create a .env.local
file:
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
DAISYCHAIN_API_KEY=dc_test_...
DAISYCHAIN_STORE_ID=store_...
Implementation Steps
1. DaisyChain Client Setup
Create lib/daisychain.ts
:
import { DaisyChain } from '@daisychain/sdk';
export const daisychain = new DaisyChain({
apiKey: process.env.DAISYCHAIN_API_KEY!,
storeId: process.env.DAISYCHAIN_STORE_ID!,
debug: process.env.NODE_ENV === 'development'
});
// Helper functions
export async function captureReferral() {
return daisychain.captureFromURL();
}
export function addReferralField(formElement: HTMLFormElement) {
daisychain.injectReferralField(formElement, {
label: 'Referral Code (Optional)',
placeholder: 'Enter email or code'
});
}
export async function handleSuccessfulPayment(session: any) {
const storedReferral = daisychain.getStoredReferral();
if (storedReferral) {
await daisychain.submitReferral({
referrerIdentifier: storedReferral.referrerIdentifier,
customerId: session.customer,
orderId: session.id,
orderAmount: session.amount_total / 100
});
}
}
2. Checkout Page
Create app/checkout/page.tsx
:
'use client';
import { useEffect } from 'react';
import { loadStripe } from '@stripe/stripe-js';
import { captureReferral, addReferralField } from '@/lib/daisychain';
const stripePromise = loadStripe(
process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!
);
export default function CheckoutPage() {
useEffect(() => {
// Capture referral from URL if present
captureReferral();
// Add referral field to form
const form = document.getElementById('checkout-form');
if (form) {
addReferralField(form as HTMLFormElement);
}
}, []);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
try {
const response = await fetch('/api/create-checkout-session', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
items: [
{
name: 'Product Name',
price: 2999,
quantity: 1
}
]
}),
});
const { sessionId } = await response.json();
const stripe = await stripePromise;
await stripe!.redirectToCheckout({ sessionId });
} catch (err) {
console.error('Checkout error:', err);
}
}
return (
<div className="max-w-md mx-auto p-6">
<form id="checkout-form" onSubmit={handleSubmit}>
{/* DaisyChain will inject the referral field here */}
<button type="submit">
Checkout
</button>
</form>
</div>
);
}
3. Stripe Checkout Session
Create app/api/create-checkout-session/route.ts
:
import { NextResponse } from 'next/server';
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2023-10-16'
});
export async function POST(req: Request) {
try {
const { items } = await req.json();
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: items.map((item: any) => ({
price_data: {
currency: 'usd',
product_data: {
name: item.name,
},
unit_amount: item.price,
},
quantity: item.quantity,
})),
mode: 'payment',
success_url: `${req.headers.get('origin')}/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${req.headers.get('origin')}/checkout`,
});
return NextResponse.json({ sessionId: session.id });
} catch (err: any) {
return NextResponse.json(
{ error: err.message },
{ status: 500 }
);
}
}
4. Webhook Handler
Create app/api/webhook/route.ts
:
import { NextResponse } from 'next/server';
import Stripe from 'stripe';
import { handleSuccessfulPayment } from '@/lib/daisychain';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2023-10-16'
});
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET!;
export async function POST(req: Request) {
try {
const body = await req.text();
const signature = req.headers.get('stripe-signature')!;
const event = stripe.webhooks.constructEvent(
body,
signature,
webhookSecret
);
if (event.type === 'checkout.session.completed') {
const session = event.data.object;
await handleSuccessfulPayment(session);
}
return new NextResponse(null, { status: 200 });
} catch (err: any) {
console.error('Webhook error:', err.message);
return new NextResponse(
`Webhook Error: ${err.message}`,
{ status: 400 }
);
}
}
Testing
- Start your development server:
npm run dev
- Use Stripe test cards:
- Success: 4242 4242 4242 4242
- Decline: 4000 0000 0000 0002
- Test referral flow:
- Add
?ref=test@example.com
to your checkout URL - Complete a purchase
- Verify referral in DaisyChain dashboard
Going Live
- Update environment variables with production keys
- Update Stripe webhook endpoint in dashboard
- Test the complete flow in production mode
- Monitor webhook delivery in both Stripe and DaisyChain dashboards
Troubleshooting
Common Issues
-
Webhook Errors
- Verify webhook secrets
- Check webhook logs in both dashboards
- Ensure proper error handling
-
Referral Not Tracking
- Check URL parameters
- Verify localStorage access
- Check browser console for errors
-
Payment Issues
- Verify Stripe keys
- Check payment logs in Stripe dashboard
- Verify webhook signature