Accept Payments with Paystack in Firebase Cloud Functions
Create a Firebase Cloud Function using onRequest (v2). Store your Paystack secret key with firebase functions:secrets:set PAYSTACK_SECRET_KEY. In the function, access it with process.env.PAYSTACK_SECRET_KEY, call the Paystack initialize endpoint using native fetch (Node 18+), and return the authorization URL to your frontend.
Setup: Secret and Project
# Initialize Cloud Functions if not already done
firebase init functions
# Choose TypeScript, Node 18
# Store Paystack secret key as a Firebase secret
firebase functions:secrets:set PAYSTACK_SECRET_KEY
# Install dependencies
cd functions
npm install cors
npm install --save-dev @types/cors
Initialize Transaction Function
// functions/src/index.ts
import { onRequest } from "firebase-functions/v2/https";
import { defineSecret } from "firebase-functions/params";
import * as cors from "cors";
const paystackSecretKey = defineSecret("PAYSTACK_SECRET_KEY");
const corsHandler = cors({ origin: true });
export const initializePayment = onRequest(
{ secrets: [paystackSecretKey] },
async (req, res) => {
corsHandler(req, res, async () => {
if (req.method !== "POST") {
res.status(405).send("Method not allowed");
return;
}
const secretKey = paystackSecretKey.value();
const { email, amount } = req.body;
if (!email || !amount) {
res.status(400).json({ error: "email and amount are required" });
return;
}
const reference = "fcn_" + Date.now() + "_" + Math.random().toString(36).slice(2, 8);
try {
const paystackRes = await fetch(
"https://api.paystack.co/transaction/initialize",
{
method: "POST",
headers: {
Authorization: "Bearer " + secretKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
email,
amount: Math.round(Number(amount) * 100),
reference,
}),
}
);
const data = await paystackRes.json();
if (!data.status) {
res.status(400).json({ error: data.message });
return;
}
res.json({
authorization_url: data.data.authorization_url,
access_code: data.data.access_code,
reference: data.data.reference,
});
} catch (error) {
res.status(500).json({ error: "Failed to initialize payment" });
}
});
}
);
Deploy and Call from Frontend
# Deploy the function
firebase deploy --only functions:initializePayment
# Get the function URL from the console or CLI output:
# https://<region>-<project-id>.cloudfunctions.net/initializePayment
// Frontend call
async function initializePayment(email: string, amount: number) {
var response = await fetch(
"https://<region>-<project-id>.cloudfunctions.net/initializePayment",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, amount }),
}
)
var data = await response.json()
// data.authorization_url — redirect or open in WebView
window.location.href = data.authorization_url
}
Learn More
This guide is part of the Paystack integration guides by language and framework series.
Key Takeaways
- ✓Use Firebase Cloud Functions v2 (onRequest) for Paystack backend. Node 18+ includes native fetch.
- ✓Store the secret key with: firebase functions:secrets:set PAYSTACK_SECRET_KEY
- ✓Declare the secret in your function: { secrets: ["PAYSTACK_SECRET_KEY"] }. Access with process.env.PAYSTACK_SECRET_KEY.
- ✓Handle CORS in the function using the cors npm package or manual header setting.
- ✓Deploy with: firebase deploy --only functions:initializePayment
- ✓Call the function URL from your frontend. Get it from the Firebase console or CLI output.
Frequently Asked Questions
- Should I use Firebase Cloud Functions v1 or v2 for Paystack?
- Use v2 (firebase-functions/v2/https). It has native secret management with defineSecret, runs on Node 18 with native fetch, and has better cold start performance. V1 is legacy. The code pattern is slightly different — v2 uses onRequest() as a named export, not functions.https.onRequest().
- How do I store the Paystack secret key in Firebase?
- Use Firebase Secrets: run firebase functions:secrets:set PAYSTACK_SECRET_KEY in your terminal and paste the key when prompted. In your function, declare it with defineSecret("PAYSTACK_SECRET_KEY") and pass it to the secrets array in onRequest options. Access the value with paystackSecretKey.value() inside the function.
- Do I need to install node-fetch in Firebase Cloud Functions?
- Not if you use Node 18 or above (the default for v2 functions). Node 18 includes native fetch. If your functions are still on Node 16, install node-fetch@2 (CommonJS compatible) with npm install node-fetch@2.
- How do I handle CORS for Paystack Cloud Functions called from a browser?
- Install the cors npm package and wrap your handler with corsHandler(req, res, async () => { ... }). For simple cases, you can also set headers manually: res.set("Access-Control-Allow-Origin", "*") before returning the response. Handle OPTIONS preflight by returning 204 with the CORS headers.
Ready to build real-world apps?
Join the McTaba Labs full-stack marathon (4 months full-time · 6 months part-time). Learn M-Pesa, USSD, and WhatsApp engineering while shipping 8 production apps.
Apply to the McTaba Marathon