- Firebase project with Functions enabled
- Node.js 20+ and npm installed
- TypeScript configured in your project
- Stripe account (test and/or live)
# Navigate to your Firebase project directory
cd YOUR_PROJECT_DIR
# Copy all Stripe service files
cp -r /path/to/Firebase-TypeScript-Stripe-API/src/services/stripe src/services/
# Copy all Stripe type files
cp -r /path/to/Firebase-TypeScript-Stripe-API/src/types/stripe src/types/
# Copy Stripe components (optional)
cp -r /path/to/Firebase-TypeScript-Stripe-API/src/components/stripe src/components/
# Copy configuration files
cp /path/to/Firebase-TypeScript-Stripe-API/src/config/environment.ts src/config/
cp /path/to/Firebase-TypeScript-Stripe-API/src/utils/firebase/config.ts src/utils/firebase/
cp /path/to/Firebase-TypeScript-Stripe-API/src/services/errorHandler.ts src/services/
# Copy Firebase Function files
cp /path/to/Firebase-TypeScript-Stripe-API/functions/src/stripe-proxy.ts functions/src/
cp /path/to/Firebase-TypeScript-Stripe-API/functions/src/cors-helper.ts functions/src/
cp /path/to/Firebase-TypeScript-Stripe-API/functions/src/environment.ts functions/src/
cp /path/to/Firebase-TypeScript-Stripe-API/functions/src/services/errorHandler.ts functions/src/services/# Frontend dependencies
npm install firebase
# Functions dependencies
cd functions
npm install firebase-functions firebase-admin stripe
cd ..Update src/utils/firebase/config.ts with your Firebase project details:
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT.firebaseapp.com",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_PROJECT.firebasestorage.app",
messagingSenderId: "YOUR_SENDER_ID",
appId: "YOUR_APP_ID"
};# Test environment secrets
firebase functions:secrets:set STRIPE_TEST_SECRET_KEY
# Enter: sk_test_...
firebase functions:secrets:set STRIPE_TEST_PUBLISHABLE_KEY
# Enter: pk_test_...
firebase functions:secrets:set STRIPE_TEST_ACCOUNT_ID
# Enter: acct_... (optional, for Connect)
# Live environment secrets
firebase functions:secrets:set STRIPE_LIVE_SECRET_KEY
# Enter: sk_live_...
firebase functions:secrets:set STRIPE_LIVE_PUBLISHABLE_KEY
# Enter: pk_live_...
firebase functions:secrets:set STRIPE_LIVE_ACCOUNT_ID
# Enter: acct_... (optional, for Connect)Create a document at /config/stripe in Firestore:
{
"environment": "test",
"testPublishableKey": "pk_test_...",
"livePublishableKey": "pk_live_...",
"createdAt": "2025-10-01T00:00:00.000Z",
"updatedAt": "2025-10-01T00:00:00.000Z"
}Add the stripeProxy export to functions/src/index.ts:
export { stripeProxy } from './stripe-proxy';In functions/src/cors-helper.ts, update the allowed origins:
export const CORS_CONFIG = {
origins: [
'https://YOUR_PROJECT.web.app',
'https://YOUR_PROJECT.firebaseapp.com',
'http://localhost:3000',
'http://localhost:5173',
// Add your custom domains
],
// ... rest of config
};firebase deploy --only functions:stripeProxyWait for deployment to complete. You'll get a function URL like:
https://us-central1-YOUR_PROJECT.cloudfunctions.net/stripeProxy
import { customersCreateService } from 'src/services/stripe';
async function testStripeIntegration() {
try {
const result = await customersCreateService.create({
email: 'test@example.com',
name: 'Test Customer'
});
if (result.success) {
console.log('✅ Stripe integration working!', result.customer);
} else {
console.error('❌ Error:', result.error);
}
} catch (error) {
console.error('❌ Failed:', error);
}
}Update the Firestore document at /config/stripe:
// Switch to LIVE
await updateDoc(doc(db, 'config', 'stripe'), {
environment: 'live',
updatedAt: new Date()
});
// Switch to TEST
await updateDoc(doc(db, 'config', 'stripe'), {
environment: 'test',
updatedAt: new Date()
});Changes take effect immediately - no redeployment needed!
- Check
functions/src/cors-helper.tshas your domain - Redeploy functions:
firebase deploy --only functions:stripeProxy - Clear browser cache
- Verify function is deployed:
firebase functions:list - Check function logs:
firebase functions:log --only stripeProxy - Ensure Firebase config points to correct project
- Verify all files copied correctly
- Check
tsconfig.jsonincludessrcdirectory - Restart TypeScript server in your IDE
- Verify Firestore document exists at
/config/stripe - Check Firebase Functions has Firestore permissions
- Review function logs for environment retrieval errors
import { customersCreateService } from 'src/services/stripe';
const result = await customersCreateService.create({
email: 'customer@example.com',
name: 'John Doe',
phone: '+1234567890',
metadata: {
userId: 'user_123'
}
});import { paymentIntentsCreateService } from 'src/services/stripe';
const result = await paymentIntentsCreateService.create({
amount: 10000, // $100.00 in cents
currency: 'usd',
customer: 'cus_...',
metadata: {
orderId: 'order_123'
}
});import { checkoutSessionsCreateService } from 'src/services/stripe';
const result = await checkoutSessionsCreateService.create({
success_url: 'https://yoursite.com/success',
cancel_url: 'https://yoursite.com/cancel',
mode: 'payment',
line_items: [{
price: 'price_...',
quantity: 1
}]
});import { subscriptionsCreateService } from 'src/services/stripe';
const result = await subscriptionsCreateService.create({
customer: 'cus_...',
items: [{
price: 'price_...'
}],
payment_behavior: 'default_incomplete',
payment_settings: {
payment_method_types: ['card']
}
});- Never expose secret keys in frontend code
- All Stripe API calls go through the Cloud Function proxy
- Secret keys stored in Firebase Secret Manager
- Frontend only has access to publishable keys
- CORS configuration restricts allowed origins
Firebase-TypeScript-Stripe-API/
├── src/
│ ├── services/
│ │ ├── stripe/ # 87 folders, 290+ service files
│ │ │ ├── accounts/
│ │ │ ├── customers/
│ │ │ ├── paymentIntents/
│ │ │ └── ...
│ │ └── errorHandler.ts
│ ├── types/
│ │ └── stripe/ # 77 type files
│ │ ├── common.ts
│ │ ├── accounts.ts
│ │ ├── customers.ts
│ │ ├── index.ts # Barrel export
│ │ └── ...
│ ├── components/
│ │ └── stripe/ # Reusable UI components
│ ├── config/
│ │ └── environment.ts # Frontend env config
│ └── utils/
│ └── firebase/
│ └── config.ts # Firebase init
└── functions/
└── src/
├── stripe-proxy.ts # Main proxy function
├── cors-helper.ts # CORS utilities
├── environment.ts # Runtime env switching
└── services/
└── errorHandler.ts # Error handling
- No CORS Issues - All Stripe API calls proxied through Firebase Function
- Type Safety - Complete TypeScript coverage prevents errors
- Environment Switching - Runtime switch between test/live
- AI-Friendly - Consistent structure prevents AI coding mistakes
- Production-Ready - Comprehensive error handling
- Easy to Use - Simple, predictable API
- Fully Documented - JSDoc comments throughout
import { ErrorHandler, ErrorContext } from 'src/services/errorHandler';
const context: ErrorContext = {
operation: 'createCustomer',
customerEmail: email,
orderId: orderId
};
const errorResult = ErrorHandler.handleStripeError(error, context);
// Returns user-friendly error messageimport { getStripeEnvironment } from 'src/config/environment';
const env = await getStripeEnvironment();
console.log('Current environment:', env); // 'test' or 'live'- Complete Coverage - Every Stripe API endpoint implemented
- Zero Compromises - No shortcuts, all parameters properly typed
- Battle-Tested - Running in production
- Maintainable - Consistent patterns throughout
- Future-Proof - Easy to add new Stripe features
For issues or questions:
- Check Stripe API docs: https://docs.stripe.com/api
- Review function logs:
firebase functions:log - Verify Firestore config document exists
Built with ❤️ by Eric Wiedemann for the Firebase + Stripe developer community
Repository: github.com/Twizbee/firebase-typescript-stripe-api