Home > Software design >  Stripe webhook to send data to Firebase not working
Stripe webhook to send data to Firebase not working

Time:05-08

It is showing no error but it is not reaching Firebase.

console.log(success: order ${session.id} had been added to db); this line never comes in the console.

the terminal shows everything created but it does not reach Firebase database I am thinking there is an error in the code

The stripe dashboard also says connected

I am using the forward to localhost line in git terminal

webhook code

import { buffer } from "micro";
import * as admin from 'firebase-admin'

//secure a connection to Firebase from backend
const serviceAccount = require('../../../permissions.json');
const app = !admin.apps.length ? admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
}) 
  : admin.app();

// establish connection to stripe
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

const endpointSecret = process.env.STRIPE_SIGNING_SECRET;
if (typeof endpointSecret !== "string") {
    console.error("Unexpected value for STRIPE_SIGNING_SECRET");
    // potentially throw an error here
  }

const fulfillOrder = async (session) => {
    //console.log('Fulfilling order', session)

    return app
    .firestore()
    .collection("user")
    .doc(session.metadata.email)
    .collection("orders")
    .doc(session.id)
    .set({
        amount: session.amount_total / 100,
        amount_shipping: session.amount_total_details.amount_shipping / 100,
        images: JSON.parse(session.metadata.images),
        timestamp: admin.firestore.FieldValue.serverTimestamp(),
    })
    .then(() => {
        console.log(`success: order ${session.id} had been added to db`);
    });
};

export default async (req, res) =>{
    if(req.method === 'post'){
        const requestBuffer = await buffer(req);
        const payload = requestBuffer.toString();
        const sig = req.headers["stripe-signature"];

        let event;

        // verify that the event posted came from stripe 
        try{
            event = stripe.webhooks.constructEvent(
                 payload,
                 sig,
                 endpointSecret);
        } catch (err) {
            console.log('ERROR', err.message)
            return res.status(400).send(`Webhook error: ${err.message}`)
        }

        //handle the checkout event 
        if (event.type === 'checkout.session.completed') {
            const session = event .data.object;

            //fulfill the order...
            return fulfillOrder(session)
            .then(() => res.status(200))
            .catch((err) => res.status(400).send(`Webhook error: ${err.message}`));
        }
    }
};

export const config = {
    api: {
        bodyParser: false,
        externalResolver: true,
    },
};

firebase rules

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow write: if false;
      allow read: if true;
    }
  }
}

file folder

console

CodePudding user response:

Trying to register default defeats the system, which deploys individual functions:

export default async (req, res) => {

The name of the function should rather be webhook (TypeScript example):

const functions = require("firebase-functions");
exports.webhook = functions.https.onRequest(async (request: any, response: Response) => {

Or NodeJS: https://cloud.google.com/functions/docs/calling/http#functions-calling-http-nodejs


But the problem is another: Maybe reconsider the directory structure, because there commonly are no "pages" and one doesn't need a separate file per function. These are supposed to be deployed independently, which means that trying to deploy a function from within a JS app may not work as expected. It's actually the idea of Cloud Functions, that the run on their own ...don't mix these applications (as the screenshot suggests). Better use a separate directory functions and an independent *.js or *.ts file.

That webhook code may interact with Firestore, but not with the rest of that JS application.

CodePudding user response:

This code:

if (event.type === 'checkout.session.completed') {
            const session = event .data.object;

            //fulfill the order...
            return fulfillOrder(session)
            .then(() => res.status(200))
            .catch((err) => res.status(400).send(`Webhook error: ${err.message}`));
        }

contains two errors:

  • wrong spelling (with space) event .data.object;
  • status is not sent res.status(200). Probably this is the reason of error Failed to POST: Post "http://localhost:3000/webhook": context deadline exceeded from ypur last picture.
  • Related