npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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:

  1. Create an .npmrc file in your project root:
@anupaperera112:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN
  1. Generate a GitHub Personal Access Token with read:packages permission

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/json

Request 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 build

Build Output

The build process generates:

  • dist/index.js - CommonJS build
  • dist/index.mjs - ES Module build
  • dist/index.d.ts - TypeScript definitions
  • dist/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

  1. TypeScript errors: Ensure you're using React 18+ and the correct type definitions

  2. Stripe errors:

    • Verify your Stripe keys are correct
    • Check that your backend endpoint is working correctly
    • Ensure your Stripe account is properly configured
  3. Missing props error: All required props must be provided. Check the console for specific missing prop names.

  4. Backend connection errors:

    • Verify your backendUrl is correct and accessible
    • Check CORS settings on your backend
    • Ensure your backend endpoints match the expected format
  5. 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:

  1. Check the browser console for error messages
  2. Verify your Stripe configuration in the Stripe Dashboard
  3. Test your backend endpoints independently
  4. Ensure all required props are provided
  5. 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.