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
- Sign up for a Stripe account and activate payments
- Access your API keys from the Developer Console
Tip: Always start with the test environment during development.
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.
Webhook URL:
https://[YOUR_DOMAIN]/api/payment/stripe/webhooks
Get and save your webhook signing secret.
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.
- Set payment provider in
config/index.ts
:
export const paymentConfig: PaymentConfig = {
paymentProvider: "stripe",
// ... other config options
}
- Add Stripe environment variables:
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
-
Create Product in Stripe Dashboard
-
Save and get the Price ID
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.
- Configure price components
Each preset price component will have a
priceId
field, for example:
...
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.
Best Practice: It's recommended to configure the
priceId
variable as an environment variable, so you don't need to modify the code when switchingpriceId
.
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
.
// 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
.