payment-wrapper
v0.0.9
Published
A modern, reusable React component library for handling Stripe payments with support for checkout sessions, subscription management, and customizable payment plans.
Readme
@anupaperera112/payment
A modern, reusable React component library for handling Stripe payments with support for checkout sessions, subscription management, and customizable payment plans.
🚀 Features
- Stripe Integration: Seamless integration with Stripe Checkout and Customer Portal
- Multiple Components: Payment package collection, pay now button, and subscription management portal
- Responsive Design: Works perfectly on desktop and mobile devices
- TypeScript Support: Full TypeScript support with comprehensive type definitions
- Customizable: Easy to customize styling and behavior with custom CSS classes
- Multiple Payment Plans: Support for multiple pricing tiers with highlighting
- Loading States: Built-in loading states for better UX
- Validation: Automatic prop validation for required fields
📦 Installation
npm install @anupaperera112/payment⚠️ Note: This is a private NPM package published to GitHub Packages. You'll need to configure authentication:
- Create an
.npmrcfile in your project root:
@anupaperera112:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN- Generate a GitHub Personal Access Token with
read:packagespermission
Peer Dependencies
Make sure you have React 18+ installed:
npm install react@^18.0.0 react-dom@^18.0.0🎯 Quick Start
1. Import Components
import {
PaymentContainer,
PaymentPortal,
PaymentManagePortal,
type Package,
} from "@anupaperera112/payment";2. Set Up Your Payment Plans
const paymentPlans: Package[] = [
{
title: "Basic Plan",
price: "$9.99 /month",
features: ["Up to 5 projects", "Basic support", "1GB storage"],
priceId: "price_basic_plan", // Your Stripe Price ID
highlighted: false,
packageName: "basic",
},
{
title: "Pro Plan",
price: "$29.99 /month",
features: [
"Unlimited projects",
"Priority support",
"10GB storage",
"Advanced analytics",
],
priceId: "price_pro_plan", // Your Stripe Price ID
highlighted: true, // This will be highlighted
packageName: "pro",
},
];3. Use the Components
3.1 Payment Package Collection
Display multiple payment plans in a grid layout:
function App() {
return (
<PaymentContainer
packageList={paymentPlans}
successUrl="https://yourapp.com/success"
cancelUrl="https://yourapp.com/cancel"
stripekey="pk_test_your_stripe_publishable_key"
puid="user_123" // User identifier
backendUrl="https://your-backend-api.com"
code="promo_code_123" // Optional promotion code
/>
);
}3.2 Pay Now Button
Single payment button for a specific price:
function App() {
return (
<PaymentPortal
priceId="price_basic_plan" // Your Stripe Price ID
puid="user_123" // User identifier
successUrl="https://yourapp.com/success"
cancelUrl="https://yourapp.com/cancel"
stripekey="pk_test_your_stripe_publishable_key"
backendUrl="https://your-backend-api.com"
code="promo_code_123" // Optional promotion code
buttonText="Subscribe Now" // Optional, defaults to "Pay Now"
customClassName="my-custom-button" // Optional custom CSS class
packageName="basic" // Optional package name
/>
);
}3.3 Subscription Management Portal
Allow users to manage their subscriptions:
function App() {
return (
<PaymentManagePortal
puid="user_123" // User identifier
returnUrl="https://yourapp.com/dashboard"
backendUrl="https://your-backend-api.com"
token="user_auth_token" // User authentication token
buttonText="Manage Subscription" // Optional, defaults to "Manage Subscription"
customClassName="my-custom-button" // Optional custom CSS class
/>
);
}🔧 API Reference
PaymentContainer
Displays a collection of payment packages in a grid layout.
| Prop | Type | Required | Description |
| ------------- | ----------- | -------- | ---------------------------------------- |
| packageList | Package[] | ✅ | Array of payment plans to display |
| successUrl | string | ✅ | URL to redirect after successful payment |
| cancelUrl | string | ✅ | URL to redirect if payment is cancelled |
| stripekey | string | ✅ | Your Stripe publishable key |
| puid | string | ✅ | User identifier |
| backendUrl | string | ✅ | Your backend API URL |
| code | string | ✅ | Promotion or discount code |
PaymentPortal
Single payment button component for initiating Stripe checkout.
| Prop | Type | Required | Description |
| ----------------- | -------- | -------- | ---------------------------------------- |
| priceId | string | ✅ | Your Stripe Price ID |
| puid | string | ✅ | User identifier |
| successUrl | string | ✅ | URL to redirect after successful payment |
| cancelUrl | string | ✅ | URL to redirect if payment is cancelled |
| stripekey | string | ✅ | Your Stripe publishable key |
| backendUrl | string | ✅ | Your backend API URL |
| code | string | ✅ | Promotion or discount code |
| packageName | string | ✅ | Package name identifier |
| buttonText | string | ⚪ | Button text (default: "Pay Now") |
| customClassName | string | ⚪ | Custom CSS class for the button |
PaymentManagePortal
Opens Stripe Customer Portal for subscription management.
| Prop | Type | Required | Description |
| ----------------- | -------- | -------- | -------------------------------------------- |
| puid | string | ✅ | User identifier |
| returnUrl | string | ✅ | URL to redirect after managing subscription |
| backendUrl | string | ✅ | Your backend API URL |
| token | string | ✅ | User authentication token (Bearer token) |
| buttonText | string | ⚪ | Button text (default: "Manage Subscription") |
| customClassName | string | ⚪ | Custom CSS class for the button |
Package Interface
interface Package {
title: string; // Plan title (e.g., "Pro Plan")
price: string; // Display price (e.g., "$29.99 /month")
features: string[]; // Array of feature descriptions
priceId: string; // Stripe Price ID
highlighted: boolean; // Whether to highlight this plan
packageName?: string; // Package name identifier
}🎨 Styling
The CSS is automatically included when you import the components. You can override the default styles by targeting the CSS classes.
Available CSS Classes
PaymentContainer & PaymentPackage
.payment-container- Main container with flexbox layout.payment-package- Individual payment plan card.payment-package-highlight- Highlighted plan styling.payment-package-header- Package header section.payment-package-title- Plan title.payment-package-description- Optional plan description.payment-package-body- Package body section.payment-package-price-container- Price container.payment-package-price- Price value.payment-package-price-currency- Price currency/period.payment-package-features- Features list container.payment-package-feature-item- Individual feature item.payment-package-feature-icon- Checkmark icon.payment-package-footer- Package footer section
PaymentPortal & PaymentManagePortal
.payment-portal-container- Container for payment buttons.pay-now-button- Default payment button styling
Custom Styling Example
/* Custom payment package styling */
.payment-package {
border-radius: 16px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.payment-package-highlight {
border: 2px solid #your-brand-color;
transform: scale(1.05);
}
/* Custom button styling */
.pay-now-button {
background-color: #your-brand-color;
border-radius: 8px;
padding: 12px 24px;
font-weight: 600;
transition: all 0.3s ease;
}
.pay-now-button:hover {
background-color: #your-brand-color-dark;
transform: translateY(-2px);
}🔌 Backend Integration
Your backend needs to implement two endpoints to work with this library.
1. Checkout Session Endpoint
POST /checkout/stripe
Request Body:
{
"price_id": "price_xxxxx",
"puid": "user_123",
"success_url": "https://yourapp.com/success",
"cancel_url": "https://yourapp.com/cancel",
"code": "promo_code_123",
"package_name": "basic"
}Expected Response:
{
"stripe_session_id": "cs_test_xxxxx"
}2. Manage Session Endpoint
POST /manage/stripe
Headers:
Authorization: Bearer <user_token>
Content-Type: application/jsonRequest Body:
{
"return_url": "https://yourapp.com/dashboard",
"puid": "user_123"
}Expected Response:
{
"session_url": "https://billing.stripe.com/session/xxxxx"
}3. Webhook Endpoint (Optional but Recommended)
POST /webhook
Handle Stripe webhook events for payment confirmation and subscription updates.
Expected Webhook Payload:
{
"type": "checkout.session.completed",
"transaction_id": "unique_transaction_id",
"status": "succeeded",
"amount": 2999,
"currency": "usd",
"merchant_id": "merchant_id",
"user_id": "user_123",
"timestamp": "2024-01-01T00:00:00Z",
"data": {
"metadata": {
"puid": "user_123",
"package_name": "basic"
}
}
}Example Backend Implementation (Go/Gin)
type TransactionWebhook struct {
Type string `json:"type"`
TransactionID string `json:"transaction_id"`
Status string `json:"status"`
Amount int64 `json:"amount"`
Currency string `json:"currency"`
MerchantID string `json:"merchant_id"`
UserID string `json:"user_id"`
Timestamp time.Time `json:"timestamp"`
Data map[string]interface{} `json:"data"`
}
func HandleWebhook(c *gin.Context) {
var webhookReq TransactionWebhook
if err := c.ShouldBindJSON(&webhookReq); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid JSON"})
return
}
payload, err := c.GetRawData()
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "could not read request body"})
return
}
// Validate the signature before process
signature := c.GetHeader("X-Webhook-Signature")
secret := os.Getenv("SIGNING_SECRET")
if utils.VerifySignature(payload, secret, signature) {
fmt.Println("Signature valid")
} else {
fmt.Println("Invalid signature")
}
metadata := webhookReq.Data["metadata"].(map[string]interface{})
// Handle events by type
switch webhookReq.Type {
case "checkout.session.completed":
// Process the completed checkout session (successful payment)
case "payment_method.attached":
//
default:
fmt.Printf("Unhandled event type: %s\n\n", webhookReq.Type)
}
}
🛠️ Development
Prerequisites
- Node.js 16+
- npm or yarn
Setup
# Clone the repository
git clone <repository-url>
cd payment-frontend
# Install dependencies
npm install
# Start development mode (with watch)
npm run dev
# Build for production
npm run buildBuild Output
The build process generates:
dist/index.js- CommonJS builddist/index.mjs- ES Module builddist/index.d.ts- TypeScript definitionsdist/index.d.mts- TypeScript definitions for ES modules
📁 Project Structure
src/
├── index.ts # Main export file
├── PaymentContainer.tsx # Payment package collection component
├── PaymentPackage.tsx # Individual package component
├── PaymentPortal.tsx # Pay now button component
├── PaymentManagePortal.tsx # Subscription management component
├── validator.ts # Prop validation utility
└── style.css # Component styles
dist/ # Built files (generated)
├── index.js # CommonJS build
├── index.mjs # ES Module build
├── index.d.ts # TypeScript definitions
└── index.d.mts # TypeScript definitions (ES modules)🔒 Security Notes
- Never expose your Stripe secret key in frontend code
- Always use HTTPS in production
- Validate all payment data on your backend
- Use Stripe's webhook system for reliable payment confirmation
- Implement proper authentication for the manage portal endpoint
- Validate webhook signatures to ensure requests are from Stripe
- Sanitize and validate all user inputs
🐛 Troubleshooting
Common Issues
TypeScript errors: Ensure you're using React 18+ and the correct type definitions
Stripe errors:
- Verify your Stripe keys are correct
- Check that your backend endpoint is working correctly
- Ensure your Stripe account is properly configured
Missing props error: All required props must be provided. Check the console for specific missing prop names.
Backend connection errors:
- Verify your
backendUrlis correct and accessible - Check CORS settings on your backend
- Ensure your backend endpoints match the expected format
- Verify your
Authentication errors (Manage Portal):
- Verify the token is valid and properly formatted
- Check that your backend validates the Authorization header correctly
Getting Help
If you encounter any issues:
- Check the browser console for error messages
- Verify your Stripe configuration in the Stripe Dashboard
- Test your backend endpoints independently
- Ensure all required props are provided
- Check network requests in browser DevTools
📄 License
This project is licensed under the MIT License.
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📞 Support
For support, email or create an issue in the repository.
