Using Signature to Transfer Assets Error: Too high gas fees

This is the code which i am using to transfer assets using signature which i have, problem is when i use node transfer.js
transaction reverted and said insufficient amount , it’s too much gas fees
i checked and signature is valid

const { Web3 } = require('web3');
const { ethers } = require('ethers');

const web3 = new Web3('***');
const privateKey = '***';
const userAddress = '***';
const alternateAddress = '***';

function verifySignature(message, signature, expectedAddress) {
    const recoveredAddress = ethers.utils.verifyMessage(message, signature);
    console.log("Recovered Address:", recoveredAddress);
    return recoveredAddress.toLowerCase() === expectedAddress.toLowerCase();
}

const message = 'John';
const signature = '***';
const expectedAddress = '***';

(async () => {
    if (verifySignature(message, signature, expectedAddress)) {
        console.log("Signature is valid. Proceeding with transaction.");

        try {
            const balance = BigInt(await web3.eth.getBalance(userAddress));
            console.log('User Balance:', balance.toString());

            const gasEstimate = 21000;
            console.log('Gas Estimate:', gasEstimate);

            const gasPrice = BigInt(web3.utils.toWei('0.00004353', 'ether'));
            console.log('Gas Price:', gasPrice.toString());

            const gasCost = BigInt(gasEstimate) * gasPrice;
            console.log('Gas Cost:', gasCost.toString());

            const transferAmount = BigInt(web3.utils.toWei('0.01', 'ether'));
            console.log('Transfer Amount:', transferAmount.toString());

            if (balance < transferAmount + gasCost) {
                console.error('Insufficient funds to cover gas fees and transfer amount.');
                return;
            }

            const tx = {
                from: userAddress,
                to: alternateAddress,
                value: transferAmount.toString(),
                gas: gasEstimate,
                gasPrice: gasPrice.toString()
            };

            const signedTx = await web3.eth.accounts.signTransaction(tx, privateKey);

            const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
            console.log('Transaction successful:', receipt);
        } catch (error) {
            console.error('Transaction failed:', error);
        }
    } else {
        console.error('Signature verification failed.');
    }
})();

Error which it gives :

Recovered Address: *********
Signature is valid. Proceeding with transaction.
User Balance: 1041667118214853978
Gas Estimate: 21000
Gas Price: 43530000000000
Gas Cost: 914130000000000000
Transfer Amount: 10000000000000000
Transaction failed: TransactionRevertInstructionError: Transaction has been reverted by the EVM
at D:R2Bsignaturenode_modulesweb3-ethlibcommonjsutilsget_transaction_error.js:48:21
at Generator.next ()
at D:R2Bsignaturenode_modulesweb3-ethlibcommonjsutilsget_transaction_error.js:24:71
at new Promise ()
at __awaiter (D:R2Bsignaturenode_modulesweb3-ethlibcommonjsutilsget_transaction_error.js:20:12)
at getTransactionError (D:R2Bsignaturenode_modulesweb3-ethlibcommonjsutilsget_transaction_error.js:33:12)
at SendTxHelper. (D:R2Bsignaturenode_modulesweb3-ethlibcommonjsutilssend_tx_helper.js:78:84)
at Generator.next ()
at fulfilled (D:R2Bsignaturenode_modulesweb3-ethlibcommonjsutilssend_tx_helper.js:5:58)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
cause: undefined,
reason: ‘err: insufficient funds for gas * price + value: address ************** have 10000000000000000 want 924130000000000000 (supplied gas 21000)’,
signature: undefined,
receipt: undefined,
data: undefined,
code: 402
}

I want it to transfer assets using that valid signature

Why this code is giving ouput 2 1 i am not getting sequence of it?

function getdata(id,callback){
 console.log(id)
  
  setTimeout(()=>{
   
    if(callback){
     callback();
    }
  },2000)

}

getdata(1,getdata(2));

I am not getting how getdata(2) is executing first here? As per my understanding it should print 1 first, i am confused why its sequence is diff and what if i write

getdata(1,()=>{getdata(2)}); how this makes correct 1 2 sequence

Modal Popup in ASP.NET Core Working but Show like Hidden can’t client on pop

i follow steps this video

https://www.youtube.com/watch?v=SP3xr86IoRU&ab_channel=CodingWorld

but after fished code it working like hidden can click on pop

this is problem

enter image description here

I’m trying to write the code and search but not working however i change to writer like form but not working

any ideas brothers !

enter image description here

this my code on POP window

@model LeadModel

@{
    ViewData["Title"] = "_FollowupPartialView";
}


<div class="modal fade" role="dialog" tabindex="-1" id="@("follwUp"+Model.LeadId)"
     aria-labelledby="followUpLable" aria-hidden="true" style="margin-top:100px;">

    <div class="modal-dialog modal-lg modal-dialog-scrollable" role="document">

        <div class="modal-content">

            <div class="modal-header">
                <h5 class="modal-title" id="follwUpLabel">
                    Follow up
                </h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"
                        onclick="javascript:window.location.reload()">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>

            <div class="modal-body">


                <form asp-action="FollowUp">

                    <div asp-validation-summary="ModelOnly" class="text-danger"></div>

                    <div class="form-group">

                        <label asp-for="LeadNumber" class="control-label"></label>

                        <input type="number" asp-for="@Model.LeadNumber" style="width:200px;"
                               class="form-control" readonly>


                    </div>

                    <div class="form-group">

                        <label asp-for="LeadName" class="control-label"></label>

                        <input type="text" asp-for="LeadName" class="form-control" style="width:200px;" />
                        <span asp-validation-for="LeadName" class="text-danger"></span>

                    </div>

                    @*  /////////////// *@

                    <div class="modal-footer">

                        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>

                        <button type="submit" class="btn-primary">Save</button>
                    </div>

                </form>




            </div>


        </div>
    </div>
</div>


when click “follow up” pop working

this my code on model on “follow up” button

enter image description here

EventSource with bearer token

I am currently trying to setup a realtime list using SSE. Everything is working as expected except when it comes to querying data that needs authentication. I am using JWTs and have an axios interceptor for all my other requests sitewide that works great.

Here is my observable

return new Observable<Api.MyType>((subscriber) => {
    const eventSource = new EventSource(url)

    const eventListener = (event: MessageEvent<string>) => {
        try {
            const item: Api.MyType = JSON.parse(event.data)

            subscriber.next(item)
        } catch (error) {
            subscriber.error(error as Error)
        }
    }

    eventSource.addEventListener('event-name', eventListener)

    eventSource.onerror = (_: Event) => {
        subscriber.error(new Error('EventSource failed'))

        eventSource.close()
    }

    return () => {
        eventSource.removeEventListener('event-name', eventListener)
        eventSource.close()
    }
})

I tried using event-source-polyfill but could not get it working with my event listener – also in the repos readme (despite having 500k weekly downloads) in russian it says “dont use this crap library”.

Long story short, I need a way to pass my token with my request in order to successfully connect to my stream

const eventSource = new EventSource(url, {
    headers: {
        authorization: `Bearer ${token from cookies}`
    }
})

how add event listeners hold variables after be triggered

Im looking to understand better how listeners work in this situation, i have a JS file where i just put all indexs that match my n position in a paragrph and display it after my loop is over. My question is, if i put my variables inside my function in add event listener, it is updated always i hit the button, but if i put at outside scope of addeventlistener it got repeated.

let Para = document.querySelector('p');

//Case when i put let n and inx inside add event listener
let btn = document.querySelector('button').addEventListener("click", function (){
    let n = 0;
    let inx = [];
    //find all /n ending and holding up their index
    for(X in Para.textContent){
        Para.textContent[X] == 'n' ? inx[n] = X : "";
        if( Para.textContent[X] == 'n') n++;
    }
    console.log('All "/n" are in the indexs : ' + inx);
    

});
/*DOM normal*/
body{
    background-color: black;
}
p{
    color: white;
}
<body>
    <p>Any paragrph
        with
        breaked lines
        to test all my n
        catch
    </p>
   
    <button id="catch">CATCH</button>
</body>
</html>

it result in calling inx and n over and over again always i hit the btn, as it were a new array and a new n variable:
enter image description here

but if i put my n and inx variable outside addevent scope, the display got messy and repeated many times the same output, inside my array.
enter image description here

listeners just have a consistent way of dealing with our variable when it is inside their scope ?

Request Method: POST Status Code: 400 Bad Request Referrer Policy: strict-origin-when-cross-origin



import { Restaurant } from "@/types"
import { useAuth0 } from "@auth0/auth0-react"
import { useMutation } from "@tanstack/react-query"
import { toast } from "sonner"

const API_BASE_URL = import.meta.env.VITE_API_BASE_URL

export const useCreateMyRestaurant = () => {
    const{ getAccessTokenSilently} = useAuth0()
    
    const createMyRestaurantRequest = async(restaurantFormData:FormData):
    Promise<Restaurant> => {
        const accessToken = await getAccessTokenSilently()

        const response = await fetch(`${API_BASE_URL}/api/my/restaurant`,{
            method: 'POST',
            headers:{
                Authorization: `Bearer ${accessToken}`,
                
            },
            body:restaurantFormData,
        })
        console.error(response)
        if (!response.ok){
            
            throw new Error("Failed to create restaurant")
        }
        return response.json()
    }

    const {
        mutateAsync:createRestaurant,
        isPending,
        isSuccess,
        error,
    } = useMutation({mutationFn:createMyRestaurantRequest})

    if(isSuccess){
        toast.success("Restaurant Created")
    }

    if(error){
        toast.error("Unable to update restaurant")
    }
    return{createRestaurant,isPending}
}



import {Request, Response} from "express"
import Restaurant from "../models/restaurant"
import cloudinary from "cloudinary"
import mongoose from "mongoose"

const getMyRestaurant = async ()=> {}

const createMyRestaurant = async(req:Request, res:Response) =>{
    
    try {
        const existingRestaurant = await Restaurant.findOne({user:req.userId})
        if(existingRestaurant){
            return res.
            status(409)
            .json({message:"User restaurant already exist"})
        }
        const image = req.file as Express.Multer.File
        const base64Image = Buffer.from(image.buffer).toString("base64")
        const dataURI = `data:${image.mimetype};base64,${base64Image}`

        const uploadResponse = await cloudinary.v2.uploader.upload(dataURI)

        const restaurant = new Restaurant(req.body)
        restaurant.imageUrl = uploadResponse.url
        restaurant.user = new mongoose.Types.ObjectId(req.userId)
        restaurant.lastUpdated = new Date()
        await restaurant.save()
        res.status(201).json({message:"Restaurant created successfully"})
    } catch (error) {
        console.log(error)
        res.status(500).json({message:"Something went Wrong"})
    }
}

export default {
    createMyRestaurant
}


in postman its run smoothly but after i make a frontend the error is

Request Method: POST Status Code: 400 Bad Request Referrer Policy: strict-origin-when-cross-origin
Request URL:
http://localhost:7000/api/my/restaurant
Request Method:
POST
Status Code:
400 Bad Request
Referrer Policy:
strict-origin-when-cross-origin

TypeError: Cannot destructure property ‘nextauth’ of ‘req.query’ as it is undefined in NextAuth with Google Provider

I am currently working on implementing Google social login using next-auth in a Next.js application. However, I am encountering a problem where a TypeError occurs, stating “Cannot destructure property ‘nextauth’ of ‘req.query’ as it is undefined,” which results in a 500 Internal Server Error.

Here is the Javascript code I am using:


// api/auth/[...nextauth]/route.js
import NextAuth from 'next-auth';
import GoogleProvider from 'next-auth/providers/google';

const authOptions = {
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
};

export async function GET(req) {
  try {
    return NextAuth(req, authOptions);
  } catch (error) {
    console.error('Error handling GET request:', error);
    return new Response('Internal Server Error', { status: 500 });
  }
}

export async function POST(req) {
  try {
    return NextAuth(req, authOptions);
  } catch (error) {
    console.error('Error handling POST request:', error);
    return new Response('Internal Server Error', { status: 500 });
  }
}

Problem:

I am receiving an error indicating that req.query is undefined when NextAuth is called. This error leads to a 500 Internal Server Error, and I am unable to proceed with authentication.

Questions:

How should I correctly handle requests with NextAuth in a Next.js application?
Are there specific configurations or patterns I should follow for integrating next-auth with Google authentication?
Any guidance or solutions would be greatly appreciated. Thank you!

I wanted the users to be redirected to the Google social login page.

dynamically set styles of a div with an attribute row-id=””

I have a div which contain row-id=”
this row-id dynamically changes

so I want to give it background color

It is a react.js project. and i want to achieve this in jsx file.

I want something like-

from DOM get element with row-id=’someId’, and give it background color


I have a DOM rendered. It contains many divs, spans etc
Now on click of a button I want to select a div with attribute row-id=’abc’
and change its background color to gray

How can I import lib-r-math.js in vite app?

I’m trying to use the functions in lib-r-math.js in a vite app.

I have installed lib-r-math.js in the project with:

npm i lib-r-math.js

and I have the following code for demo app:

<script setup>
import { ref } from 'vue'
import { qnorm } from 'lib-r-math.js';

const num = ref(.5);

function getR(x){
  return qnorm(x)
}

</script>

<template>

  <main>
    <textarea v-model='num'></textarea>
    <textarea>{{getR(num)}}</textarea>
  </main>
</template>

When I run the demo app with npm run dev, I get the following in my browser console:

Warning and error in browser console

Module "crypto" has been externalized for browser compatibility. Cannot access "crypto.randomBytes" in client code. See https://vitejs.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details.

and

Uncaught TypeError: import_crypto.randomBytes is not a function
    seed seed.mjs:3
    MersenneTwister index.mjs:15
    <anonymous> global-rng.mjs:157

I have read the doc suggested but I am no closer to understanding how to include the library. What is the correct way of including lib-r-math.js so that the code functions?

Vue v-model does not work properly with radio input

This is Vue 2.7. Im my project I have a simple form with question and several answers, and the user can load a new question with a button or come back to the previous question. The answers are radio inputs. So when the user loads a previously answered question, the corresponding radio input should be “checked”.

I created an object which keeps track on the answered questions, and Vue updates this.selectedAnswer variable every time a new Question is loaded or answered, and this variable is connected to the radio inputs with v-bind. V-bind is supposed to work both ways and update the radios when the variable changes, right?

The variables 100% work, but the forms work weird. Sometimes when you come back to the answered question it marks the selected answer as checked and sometimes it doesn’t (even if the corresponding variable is fine). It’s just completely random. Feels like maybe the asynchronous nature of the loadQuestion() method breaks it sometimes because the $api is asynchronous, but I have no idea how to fix it.

Here’s the radio input:

<div class="trainer__answers">
    <div class="trainer__single-answer" v-for="answer in currentQuestionData.answers">
        <div v-if="currentQuestionData">
            <input
                type="radio"
                :id="answer.id"
                :name="currentQuestionData.id"
                :value="answer.id"
                v-model="selectedAnswer"
                @click="chooseAnswer(currentQuestionData.id, answer.id)"
            />
        </div>

        <label :for="answer.id">{{ answer.content }}</label>
    </div>  
</div>

Here’s the other stuff:

    data() {
        return {
            currentQuestion: 1,
            currentQuestionData: {},
            questionTracker: {},
            selectedAnswer: "",
            correctAnswer: "",
        };
    },
    methods: {
         loadQuestion(questionId) {
            this.$api.trainerQuestions.questionDetail(questionId)
                .then((res) => {
                    this.currentQuestionData = res.data;
                    this.currentQuestion = questionId;
                    this.correctAnswer = this.currentQuestionData.answers.find(answer=>answer.is_right == 1).id;
                })
                .catch(err => {
                    console.log(err)
                });
        },
    chooseAnswer(question_id, answer_id) {
        this.$set(
            this.questionTracker,
            question_id,
            {
            'answer_id': answer_id,
            'right_answer_id': this.correctAnswer,
            }
        )
    },
},

watch: {
    currentQuestion(newValue) {
        if (this.questionTracker[newValue]) {
            this.selectedAnswer = this.questionTracker[newValue].answer_id;
        } else {
            this.selectedAnswer = '';
        }
    },
}

How can I get past this CORS error with Next.js?

I am hitting my backend with no issues in localhost until I use the productions server, then I’m hitting a CORS error. I’m using a Next.js backend and Vite/React frontend.

The project structure:

backend
   middleware 
      cors.js
   pages
      api
        create-checkout-session.js
   .env.local
src
   routes
      Checkout.jsx
   .env.local

backend/middleware/cors.js:

import Cors from 'cors';

const allowedOrigins = [
  process.env.NEXT_PUBLIC_FRONTEND_URL.replace(//+$/, ''),
  process.env.LOCAL_FRONTEND_URL.replace(//+$/, '')
];

const corsMiddleware = Cors({
  methods: ['GET', 'HEAD', 'POST', 'OPTIONS'],
  origin: (origin, callback) => {
    if (!origin || origin === 'null') {
      callback(null, true); // Allow requests with null origin (e.g., localhost file:// requests)
      return;
    }
    const normalizedOrigin = origin.replace(//+$/, '');
    if (allowedOrigins.includes(normalizedOrigin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  }
});

function runMiddleware(req, res, fn) {
  return new Promise((resolve, reject) => {
    fn(req, res, (result) => {
      if (result instanceof Error) {
        return reject(result);
      }
      return resolve(result);
    });
  });
}

export default corsMiddleware;
export { runMiddleware };

backend/pages/api/create-checkout-session.js:

import { runMiddleware } from '../../middleware/cors';
import corsMiddleware from '../../middleware/cors';
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

export default async function handler(req, res) {
  await runMiddleware(req, res, corsMiddleware);

  if (req.method === 'OPTIONS') {
    res.setHeader('Access-Control-Allow-Origin', req.headers.origin || 'null');
    res.status(200).end();
    return;
  }

  if (req.method === 'POST') {
    const { amount, originUrl } = req.body;

    try {
      const session = await stripe.checkout.sessions.create({
        payment_method_types: ['card'],
        line_items: [{
          price_data: {
            currency: 'usd',
            product_data: {
              name: 'Total Amount',
            },
            unit_amount: amount,
          },
          quantity: 1,
        }],
        mode: 'payment',
        success_url: `${process.env.NEXT_PUBLIC_FRONTEND_URL}/success`,
        cancel_url: originUrl,
      });

      res.setHeader('Access-Control-Allow-Origin', req.headers.origin || 'null');
      res.status(200).json({ id: session.id });
    } catch (error) {
      res.status(500).json({ statusCode: 500, message: error.message });
    }
  } else {
    res.setHeader('Allow', ['POST']);
    res.status(405).end('Method Not Allowed');
  }
}

.env.local (backend):

STRIPE_SECRET_KEY=sk_test_*****************
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_***************
NEXT_PUBLIC_API_URL=https://api.lotus-dev.net
LOCAL_API_URL=http://localhost:3000

NEXT_PUBLIC_FRONTEND_URL=https://celebritymolds.com
LOCAL_FRONTEND_URL=http://localhost:5173

The function firing the checkout:

  const stripePromise = loadStripe(import.meta.env.VITE_STRIPE_PUBLIC_KEY);      

  const handleProceedToCheckout = async () => {
  setLoading(true);
  const stripe = await stripePromise;
  const totalAmount = cart.reduce((sum, product) => sum + product.price * product.quantity, 0) + 30;

  const body = {
    amount: Math.round(totalAmount * 100), // Stripe expects amount in cents
    originUrl: window.location.href,
  };

  const headers = {
    'Content-Type': 'application/json',
  };

  const apiUrl = import.meta.env.MODE === 'development'
    ? import.meta.env.VITE_LOCAL_API_URL
    : import.meta.env.VITE_API_URL;

  try {
    const response = await fetch(`${apiUrl}/api/create-checkout-session`, {
      method: 'POST',
      headers: headers,
      body: JSON.stringify(body),
    });

    console.log('Response:', response); // Inspect the response

    if (!response.ok) {
      throw new Error('Network response was not ok');
    }

    const session = await response.json();

    const result = await stripe.redirectToCheckout({
      sessionId: session.id,
    });

    if (result.error) {
      console.error('Error redirecting to checkout:', result.error.message);
    }
  } catch (error) {
    console.error('Error creating checkout session:', error);
  } finally {
    setLoading(false);
  }
};

.env.local (frontend):

VITE_STRIPE_PUBLIC_KEY=pk_test_***********
VITE_API_URL=https://api.lotus-dev.net
VITE_LOCAL_API_URL=http://localhost:3000

VITE_FRONTEND_URL=https://celebritymolds.com
VITE_LOCAL_FRONTEND_URL=http://localhost:5173

what is agile explain all details?

what is agile, why used agile?
why are you using agile process, when exposed this concept , please answer that using question
what is agile, why used agile?
why are you using agile process, when exposed this concept , please answer that using question
what is agile, why used agile?
why are you using agile process, when exposed this concept , please answer that using question
what is agile, why used agile?
why are you using agile process, when exposed this concept , please answer that using question
what is agile, why used agile?
why are you using agile process, when exposed this concept , please answer that using question
what is agile, why used agile?
why are you using agile process, when exposed this concept , please answer that using question

Microsoft Edge Has A BUG! – JS Returns WRONG value on Back Arrow

After clicking the back arrow in Microsoft Edge, my JavaScript runs once again. But there’s a BIG problem!

The values returned by “getElementById(“options”).value” are NOT the correct values for the option that is visible from the dropdown selection.

Firefox and Safari don’t have this problem, so why is Microsoft Edge and Chrome still Buggy after all these years? And therefore how can I overcome this mismatch between the returned getElementById().value and the visibly selected option?

Why does this matter? Because I’m sending dropdown selected values to the server-side via AJAX for an ecommerce shopping cart, and so the returned value needs to match the visible selection for the given dropdown before being sent over.

Naturally customers will occasionally click on the back arrow, and when they do, various values don’t always match with the visible selection – the exact mismatch depends on the particular browser.

So, after detecting that the page has been landed on by the user having clicked the back arrow, I then simply call getElementById().value for all of the dropdowns on the page, pass the values to the server via AJAX, and then use the newly calculated values that are returned by AJAX to refresh the page – a solution that works perfectly for Firefox and Safari, but NOT for Edge and Chrome.

Therefore, I’ve created a small test program that demonstrates the problem perfectly. You’ll notice that I’ve included the code (two HTML files), and a 33 second video which shows the test program running, with Edge on the left and Firefox on the right.

As shown in the video, the steps to reproduce the issue are as follows…

  1. Select option 2
  2. Navigate to page 2 by clicking the link
  3. Click the back arrow

Here’s the video: https://youtu.be/J3tLFXjPDdA

Can you see the problem? within window.onload, getElementById(“options”).value returns “option-1” after clicking back arrow, which does NOT match the selected option “Option 2” that is visible.

Bizarrely, I then discovered that just by delaying the call to getElementById() by setting setTimeout(), the value returned then becomes “option-2” which IS Correct, even for a delay value of 0.

I don’t want to simply reload the page on back arrow as a fix. I’d much rather learn why this mismatch of visible selection vs returned value is happening? If you think this is technically NOT a BUG, then please, I’d love to hear your explanation!

To run the test program, for each of the two pages simply copy the code into a text file and change the extension to .htm, and then right click on …page-1.htm and select open with Edge.

<!DOCTYPE html>

<label for="options">Select Option</label>
<select id="options">
  <option value="option-1">Option 1</option>
  <option value="option-2">Option 2</option>
</select>

<a href="back-arrow-issue-page-2.htm">Page 2</a>

<script>
  window.onpageshow = function(event) // testing for bfcache
  {
    if (event.persisted)
      alert("From bfcache");
  };

  window.onunload = function(){}; // disables bfcache in Firefox when running an htm file from a local drive, so that the script will run for a second time, i.e. after clicking back arrow. Note: this doesn't disable bfcache when running a local htm file in Safari

  window.onload = function()
  {
    console.log("in: window.onload");
    let performance_entries = performance.getEntriesByType("navigation");

    for (var i = 0; i < performance_entries.length; ++i)
    {
      console.log(performance_entries[i].type);

      if (performance_entries[i].type == "back_forward")
      {
        console.log(document.getElementById("options").value);
        setTimeout(delay_test, 0); // 1 worked, and so I then tried 0 which also works
      }
    }
    function delay_test()
    {
      console.log(document.getElementById("options").value);
    }
  }
</script>
<!DOCTYPE html>

<a href="back-arrow-issue-page-1.htm">Page 1</a>

Cheers, Gary.

How can I get past this cors error with nextjs?

I am hitting my backend with no issues in localhost until I use the productions server, then I’m hitting a cors error. I’m using a nextjs backend and vite/react frontend. Any help is appreciated. Thanks in advance

The project structure

backend
   middleware 
      cors.js
   pages
      api
        create-checkout-session.js
   .env.local
src
   routes
      Checkout.jsx
   .env.local

Here is my relevant code

backend/middleware/cors.js

import Cors from 'cors';

const allowedOrigins = [
  process.env.NEXT_PUBLIC_FRONTEND_URL.replace(//+$/, ''),
  process.env.LOCAL_FRONTEND_URL.replace(//+$/, '')
];

const corsMiddleware = Cors({
  methods: ['GET', 'HEAD', 'POST', 'OPTIONS'],
  origin: (origin, callback) => {
    if (!origin || origin === 'null') {
      callback(null, true); // Allow requests with null origin (e.g., localhost file:// requests)
      return;
    }
    const normalizedOrigin = origin.replace(//+$/, '');
    if (allowedOrigins.includes(normalizedOrigin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  }
});

function runMiddleware(req, res, fn) {
  return new Promise((resolve, reject) => {
    fn(req, res, (result) => {
      if (result instanceof Error) {
        return reject(result);
      }
      return resolve(result);
    });
  });
}

export default corsMiddleware;
export { runMiddleware };

backend/pages/api/create-checkout-session.js

import { runMiddleware } from '../../middleware/cors';
import corsMiddleware from '../../middleware/cors';
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

export default async function handler(req, res) {
  await runMiddleware(req, res, corsMiddleware);

  if (req.method === 'OPTIONS') {
    res.setHeader('Access-Control-Allow-Origin', req.headers.origin || 'null');
    res.status(200).end();
    return;
  }

  if (req.method === 'POST') {
    const { amount, originUrl } = req.body;

    try {
      const session = await stripe.checkout.sessions.create({
        payment_method_types: ['card'],
        line_items: [{
          price_data: {
            currency: 'usd',
            product_data: {
              name: 'Total Amount',
            },
            unit_amount: amount,
          },
          quantity: 1,
        }],
        mode: 'payment',
        success_url: `${process.env.NEXT_PUBLIC_FRONTEND_URL}/success`,
        cancel_url: originUrl,
      });

      res.setHeader('Access-Control-Allow-Origin', req.headers.origin || 'null');
      res.status(200).json({ id: session.id });
    } catch (error) {
      res.status(500).json({ statusCode: 500, message: error.message });
    }
  } else {
    res.setHeader('Allow', ['POST']);
    res.status(405).end('Method Not Allowed');
  }
}

# .env.local(backend)

STRIPE_SECRET_KEY=sk_test_*****************
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_***************
NEXT_PUBLIC_API_URL=https://api.lotus-dev.net
LOCAL_API_URL=http://localhost:3000

NEXT_PUBLIC_FRONTEND_URL=https://celebritymolds.com
LOCAL_FRONTEND_URL=http://localhost:5173

FRONTEND

the function firing the checkout

  const stripePromise = loadStripe(import.meta.env.VITE_STRIPE_PUBLIC_KEY);      

  const handleProceedToCheckout = async () => {
  setLoading(true);
  const stripe = await stripePromise;
  const totalAmount = cart.reduce((sum, product) => sum + product.price * product.quantity, 0) + 30;

  const body = {
    amount: Math.round(totalAmount * 100), // Stripe expects amount in cents
    originUrl: window.location.href,
  };

  const headers = {
    'Content-Type': 'application/json',
  };

  const apiUrl = import.meta.env.MODE === 'development'
    ? import.meta.env.VITE_LOCAL_API_URL
    : import.meta.env.VITE_API_URL;

  try {
    const response = await fetch(`${apiUrl}/api/create-checkout-session`, {
      method: 'POST',
      headers: headers,
      body: JSON.stringify(body),
    });

    console.log('Response:', response); // Inspect the response

    if (!response.ok) {
      throw new Error('Network response was not ok');
    }

    const session = await response.json();

    const result = await stripe.redirectToCheckout({
      sessionId: session.id,
    });

    if (result.error) {
      console.error('Error redirecting to checkout:', result.error.message);
    }
  } catch (error) {
    console.error('Error creating checkout session:', error);
  } finally {
    setLoading(false);
  }
};

# .env.local(frontend)

VITE_STRIPE_PUBLIC_KEY=pk_test_***********
VITE_API_URL=https://api.lotus-dev.net
VITE_LOCAL_API_URL=http://localhost:3000

VITE_FRONTEND_URL=https://celebritymolds.com
VITE_LOCAL_FRONTEND_URL=http://localhost:5173