simple-stripe-sdk
v0.1.1
Published
React component and helpers to collect card details with Stripe.js, tokenize in the browser, and hand off to your backend to complete the charge securely.
Readme
Simple Stripe SDK (Frontend)
React component and helpers to collect card details with Stripe.js, tokenize in the browser, and hand off to your backend to complete the charge securely.
This package exports:
TokenizedPaymentForm– a 3-step donation UI (Amount → Information → Payment) that uses Stripe.js to produce a one-time token in the browser and returns it viaonSuccess.SimpleStripeSDK– low-level helpers. In browsers, use it only for Stripe.js tokenization. For Stripe REST actions, route through your backend.
Important: Do not place Stripe secret keys in the browser. Complete charges on the server.
Installation
npm install @engage/simple-stripe-sdk @stripe/stripe-js @stripe/react-stripe-js react react-dom
# or
yarn add @engage/simple-stripe-sdk @stripe/stripe-js @stripe/react-stripe-js react react-domQuick Start
import React from 'react';
import { TokenizedPaymentForm } from '@engage/simple-stripe-sdk';
export default function DonatePage() {
return (
<TokenizedPaymentForm
publishableKey={process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!}
defaultAmount={25}
currency="usd"
onSuccess={async ({ token, amount, donor }) => {
// Send token + donor info to your backend to CREATE + CONFIRM a PaymentIntent
await fetch('/api/payment/charge-with-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token, amount, donor }),
});
}}
onError={(msg) => console.error(msg)}
/>
);
}Component: TokenizedPaymentForm
Renders an accessible three-step donation form and handles Stripe.js tokenization in the browser. It then calls onSuccess with the token and donor info so your backend can complete the charge.
Props
publishableKey(string, required): Your Stripe publishable key.defaultAmount(number, optional): Prefilled amount in dollars. Default 25.currency(string, optional): Display currency (e.g.usd). Defaultusd.existingCustomerId(string, optional): For advanced flows; not required.onSuccess(function, optional): Called with{ token, amount, donor }.onError(function, optional): Called with a human-readable error string.
Returned object (onSuccess)
token(string): Stripe single-use token id (e.g.tok_...).amount(number): Selected amount in dollars.donor({ firstName, lastName, email, phone? }): Donor contact details.
What it does under the hood
- Loads Stripe.js with your publishable key and renders a
CardElement. - Tokenizes the card in the browser (
stripe.createToken). - Calls
onSuccess({ token, amount, donor })so your app can charge server-side.
TypeScript props signature:
type TokenizedPaymentFormProps = {
publishableKey: string;
apiBase?: string;
defaultAmount?: number;
currency?: string;
existingCustomerId?: string;
onSuccess?: (result: {
token: string;
amount: number;
donor: { firstName: string; lastName: string; email: string; phone?: string };
}) => void;
onError?: (message: string) => void;
};Security Guidance
- Do not charge on the client. Use
onSuccessto hand off to your backend to create/confirm a PaymentIntent. - Do not expose your Stripe Secret Key in browsers. Keep secrets on the server.
Backend Charge Example (Node/Express)
// POST /api/payment/charge-with-token
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, { apiVersion: '2024-06-20' });
export async function chargeWithToken(req, res) {
try {
const { token, amount, donor } = req.body; // amount in dollars
if (!token || !amount || !donor?.email) {
return res.status(400).json({ success: false, error: 'token, amount, donor.email are required' });
}
const customer = await stripe.customers.create({
email: donor.email,
name: `${donor.firstName} ${donor.lastName}`.trim(),
});
const paymentMethod = await stripe.paymentMethods.create({
type: 'card',
card: { token },
billing_details: { name: `${donor.firstName} ${donor.lastName}`.trim(), email: donor.email },
});
await stripe.paymentMethods.attach(paymentMethod.id, { customer: customer.id });
const intent = await stripe.paymentIntents.create({
amount: Math.round(Number(amount) * 100),
currency: 'usd',
customer: customer.id,
payment_method: paymentMethod.id,
confirm: true,
automatic_payment_methods: { enabled: true, allow_redirects: 'never' },
receipt_email: donor.email,
});
return res.json({ success: intent.status === 'succeeded', paymentIntentId: intent.id, status: intent.status });
} catch (err: any) {
return res.status(500).json({ success: false, error: err?.message || 'Charge failed' });
}
}Styling
The component ships with clean inline styles and a stepper UX. Wrap it in your own layout or fork to fully customize.
Testing
Use Stripe’s test cards (e.g. 4242 4242 4242 4242, any future expiry, any CVC) to simulate payments.
TypeScript
This package is written in TypeScript and ships with types. Callback payloads and props are typed.
License
MIT
