Skip to main content

Stripe Integration

ShipNowKit seamlessly integrates with Stripe for payment processing. Follow this guide to set up API keys, configure webhooks, and synchronize product prices.

1. Create Stripe Account

  1. Sign up for a Stripe account and activate payments
  2. Access your API keys from the Developer Console

Tip: Always start with the test environment during development.

Stripe API Keys

2. Configure Webhook

Webhooks are essential for receiving real-time events from Stripe, such as Payment success notifications, Subscription updates, Subscription cancellations, and so on.

Besides, ShipNowKit also uses webhooks for price synchronization.

image.png image.png image.png image.png image.png

Webhook URL: https://[YOUR_DOMAIN]/api/payment/stripe/webhooks

Get and save your webhook signing secret. image.png

3. Configure ShipNowKit

After below steps, you'll have three important keys:

SECRET_KEY=sk_test_51Qdxxxxx
PUBLISHABLE_KEY=pk_test_51Qxxxx
WEBHOOK_SECRET=whsec_ytScyxxxx

Now, you can configure ShipNowKit with these keys.

  1. Set payment provider in config/index.ts:
config/index.ts
export const paymentConfig: PaymentConfig = {
paymentProvider: "stripe",
// ... other config options
}
  1. Add Stripe environment variables:
.env
STRIPE_SECRET_KEY=sk_test_51Qdxxxxx
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_51Qxxxx
STRIPE_WEBHOOK_SECRET=whsec_ytScyxxxx

Note: Restart the service after updating environment variables.

4. Price Configuration

  1. Create Product in Stripe Dashboard image.png image.png

  2. Save and get the Price ID image.png

image.png

After adding the product, the price will be automatically synchronized to the project database, and we can confirm if the price synchronization is successful by checking the webhook notification.

  1. Configure price components Each preset price component will have a priceId field, for example:
components/price/ShipNow.tsx
...
interface PriceCardProps {
title: string;
description: string;
features: string[];
price: {
priceId: string;
isSubscription: boolean;
};
buttonText: string;
}

export interface ShipNowPriceProps {
title: string;
subTitle: string;
card: PriceCardProps;
}
...

After configuring, update the code and restart the service, you can see the updated amount and currency on the page. image.png

Best Practice: It's recommended to configure the priceId variable as an environment variable, so you don't need to modify the code when switching priceId.

5. Event Handling

ShipNowKit provides a EventEmitter class for handling payment events. And you needn't to care about the details of Stripe's events.

Believe me, The EventEmitter is much easier to use than handling Stripe's events directly.

Of course, you can also handle Stripe's events directly in app/api/payment/stripe/webhooks/webhook-processor.ts.

app/api/payment/eventEmitter.ts
// register event handlers
eventEmitter.on('subscription.succeeded', async (eventId: string, subscriptionId: string) => {
// handle new succeeded subscription
console.log(`Subscription ${subscriptionId} succeeded`);
});

eventEmitter.on('subscription.renewed', async (eventId: string, subscriptionId: string) => {
// handle subscription renewed
console.log(`Subscription ${subscriptionId} renewed`);
});

eventEmitter.on('subscription.plan_updated', async (eventId: string, data) => {
// handle subscription plan update(upgrade or downgrade)
console.log(`Subscription ${data.subscriptionId} updated: ${data.oldPriceId} -> ${data.newPriceId}`);
});

eventEmitter.on('payment.succeeded', async (eventId: string, paymentId: string) => {
// handle payment succeeded
console.log(`Payment ${paymentId} succeeded`);
});

eventEmitter.on('subscription.canceled', async (eventId: string, subscriptionId: string) => {
// handle subscription canceled
console.log(`Subscription ${subscriptionId} canceled`);
});

6. Customer Portal

ShipNowKit already integrates with Stripe's customer portal, after a user subscribes to a plan, the user can access the customer portal to manage their subscription through the url /payment/billing.