Console Error message: v3:1 Uncaught (in promise) IntegrationError: Invalid value for stripe.confirmCardPayment intent secret: value should be a client secret of the form ${id}_secret_${secret}. You specified: .
You can see the error yourself here: https://stormy-forest-38471.herokuapp.com/
Instructions to get error: From the main page, click on Menú Diari -> Demanar -> Any of the first 3 buttons -> Select one radio button from each category and then click on Afegeix i paga -> Pagar -> 1st input: 'Random Name', 2nd input: 'Recollida a tenda - Cabrera de Mar', 4th input: '123'...
Then, according to Stripe documentation, you could fill the payment element with the following data in order to achieve a successfull test payment.
Visa Number: '4242 4242 4242 4242'
MM/AA: '04/24'
CVC: '123'
Once you press Pagar, you will get the IntegrationError I'm asking for in the console.
I am trying to deploy a React.js + Node.js + Express web using Heroku.
I have been following this guide, although I am not sure if that's what I need.
https://blog.heroku.com/deploying-react-with-zero-configuration
The web is for a restaurant. They want to sell different lunch plans. I am trying to implement the payment using Stripe. When I test the app in my localhost, everything works fine. However, when I try to deploy it, something breaks.
I guess something must be wrong with my server.js or package.json files... The main problem being that I am a complete noob at Back End...
Everything works as expected (I still have some console logs here and there for development), until I start making requests to the server.
This is my server.js
const { createServer } = require('https');
const express = require('express');
const compression = require('compression');
const morgan = require('morgan');
const path = require('path');
const normalizePort = (port) => parseInt(port, 10);
const PORT = normalizePort(process.env.PORT || 5000);
const app = express();
const dev = app.get('env') !== 'production';
if (!dev) {
app.disable('x-powered-by');
app.use(compression()); // "Will handle a few things for us... (?)"
app.use(morgan('common'));
app.use(express.static(path.join(__dirname, 'build')));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'build', 'index.html'));
});
}
const server = createServer(app);
const { resolve } = require('path');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
app.use(express.json());
const calculateOrderAmount = (items) => {
console.log(items);
let drinksTotal = 0;
const { water, cola, colaZero, beer, lemonFanta, orangeFanta } = items.drinks;
drinksTotal += water * 100;
drinksTotal += (cola + colaZero + lemonFanta + orangeFanta) * 130;
drinksTotal += beer * 150;
let foodTotal = 0;
foodTotal += items.primerSegonCount * 895;
foodTotal += items.dosPrimersCount * 795;
foodTotal += items.platPostresCount * 695;
grandTotal = parseInt(drinksTotal + foodTotal);
console.log(grandTotal);
return grandTotal;
};
app.post('/create-payment-intent', async(req, res) => {
const { items } = req.body;
console.log(items);
// Create a PaymentIntent with the order amount and currency
const paymentIntent = await stripe.paymentIntents.create({
amount: calculateOrderAmount(items),
currency: 'eur'
});
res.send({
clientSecret: '123_secret_123' //paymentIntent.client_secret
});
});
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
server.listen(PORT, (err) => {
if (err) throw err;
console.log('Server started on port ' + PORT);
});
This is my package.json
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"engine": {
"node": "12.16.3",
"npm": "6.14.5"
},
"dependencies": {
"#stripe/react-stripe-js": "^1.1.2",
"#stripe/stripe-js": "^1.7.0",
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.5.0",
"#testing-library/user-event": "^7.2.1",
"axios": "^0.19.2",
"boostrap": "^2.0.0",
"bootstrap": "^4.5.0",
"compression": "^1.7.4",
"concurrently": "^5.2.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"emailjs-com": "^2.4.1",
"express": "^4.17.1",
"morgan": "^1.10.0",
"node-sass": "^4.14.1",
"nodemon": "^2.0.4",
"react": "^16.13.1",
"react-bootstrap": "^1.0.1",
"react-dom": "^16.13.1",
"react-redux": "^7.2.0",
"react-scripts": "3.4.1",
"react-scroll": "^1.7.16",
"react-stripe-checkout": "^2.6.3",
"reactstrap": "^8.5.1",
"stripe": "^8.67.0",
"uuid": "^8.2.0",
"uuidv4": "^6.1.1"
},
"scripts": {
"start": "react-scripts start",
"start-dev": "nodemon server.js",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"dev": "concurrently \"npm run-script start-dev\" \"npm run-script start\"",
"heroku-postbuild": "npm install && npm run build"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [">0.2%", "not dead", "not op_mini all"],
"development": ["last 1 chrome version", "last 1 firefox version", "last 1 safari version"]
},
"homepage": "."
}
This is the React.js file in charge of the payment
import React, { useState, useEffect } from 'react';
import { CardElement, useStripe, useElements } from '#stripe/react-stripe-js';
// Bootstrap
import { Container, Row, Col, Button, Spinner, Form } from 'react-bootstrap';
export default function CheckoutForm(props) {
const [ succeeded, setSucceeded ] = useState(false);
const [ error, setError ] = useState(null);
const [ processing, setProcessing ] = useState(false);
const [ disabled, setDisabled ] = useState(true);
const [ clientSecret, setClientSecret ] = useState('');
const stripe = useStripe();
const elements = useElements();
useEffect(() => {
console.log('inside use Effect');
// Create PaymentIntent as soon as the page loads
window
.fetch('/create-payment-intent', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
items: {
drinks: props.drinksOrdered,
primerSegonCount: props.primerSegonCount,
dosPrimersCount: props.dosPrimersCount,
platPostresCount: props.platPostresCount
}
})
})
.then((res) => {
console.log(res);
return res.json();
})
.then((data) => {
console.log(data.clientSecret);
console.log(data);
setClientSecret(data.clientSecret);
});
}, []);
const cardStyle = {
base: {
backgroundColor: 'white',
color: 'grey',
fontFamily: 'Montserrat, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#c6c6c6'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
},
complete: {
color: 'green',
iconColor: 'green'
}
};
const handleCardChange = async (event) => {
// Listen for changes in the CardElement
// and display any errors as the customer types their card details
setDisabled(event.empty);
setError(event.error ? event.error.message : '');
};
const handleSubmit = async (ev) => {
ev.preventDefault();
setProcessing(true);
const payload = await stripe.confirmCardPayment(clientSecret, {
payment_method: {
card: elements.getElement(CardElement),
billing_details: {
name: ev.target.name.value
}
}
});
// Handle Error
if (payload.error) {
setError(`Payment failed ${payload.error.message}`);
setProcessing(false);
} else if (payload.paymentIntent.status === 'succeeded') {
// If payment succeeded, send eMail with details
props.sendEmail();
setSucceeded(true);
setError(null);
setTimeout(() => {
window.location.replace('https://www.cateringroser.cat');
}, 10000);
}
};
Thank you so much in advance.
Gerard
Well, as I guessed, I had to figure this one out myself. :-)
If you go back to my original post, you will be able to see the code I had for my server.js, package.json and CheckoutForm.jsx files.
The CheckoutForm.jsx was ok. Below you can see the modified versions of the code for:
server.js
const express = require('express');
const path = require('path');
const app = express();
const { resolve } = require('path');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
app.use(express.static(path.join(__dirname, 'build')));
app.use(express.json());
// app.use(express.json());
const calculateOrderAmount = (items) => {
let drinksTotal = 0;
const { water, cola, colaZero, beer, lemonFanta, orangeFanta } = items.drinks;
drinksTotal += water * 100;
drinksTotal += (cola + colaZero + lemonFanta + orangeFanta) * 130;
drinksTotal += beer * 150;
let foodTotal = 0;
foodTotal += items.primerSegonCount * 895;
foodTotal += items.dosPrimersCount * 795;
foodTotal += items.platPostresCount * 695;
grandTotal = parseInt(drinksTotal + foodTotal);
console.log(grandTotal);
return grandTotal;
};
app.post('/create-payment-intent', async(req, res) => {
const { items } = req.body;
// Create a PaymentIntent with the order amount and currency
const paymentIntent = await stripe.paymentIntents.create({
amount: 100, //calculateOrderAmount(items),
currency: 'eur'
});
res.send({
clientSecret: paymentIntent.client_secret
});
});
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(process.env.PORT || 8080);
package.json
{
"name": "my-app",
"version": "1.0.0",
"description": "take away restaurant app",
"private": true,
"engines": {
"node": "12.x"
},
"dependencies": {
"#stripe/react-stripe-js": "^1.1.2",
"#stripe/stripe-js": "^1.7.0",
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.5.0",
"#testing-library/user-event": "^7.2.1",
"boostrap": "^2.0.0",
"bootstrap": "^4.5.0",
"concurrently": "^5.2.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"emailjs-com": "^2.4.1",
"express": "^4.17.1",
"node-sass": "^4.14.1",
"nodemon": "^2.0.4",
"react": "^16.13.1",
"react-bootstrap": "^1.0.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.1",
"react-scroll": "^1.7.16",
"react-stripe-checkout": "^2.6.3",
"reactstrap": "^8.5.1",
"stripe": "^8.67.0"
},
"scripts": {
"start": "node server.js",
"start-dev": "nodemon server.js",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"dev": "concurrently \"npm run-script start-dev\" \"npm run-script start\"",
"heroku-postbuild": "npm install && npm run build"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [">0.2%", "not dead", "not op_mini all"],
"development": ["last 1 chrome version", "last 1 firefox version", "last 1 safari version"]
}
}
I ended up using what I knew on server.js. I deleted everything I didn't understand and kept the original code.
One of the most important things was to understand what happens when you deploy an app using node/express (or at least I think I understand).
First, I thought I needed to deploy both the Front and Back End sepparately, and then link them somehow.
What (I think) I really needed to do was to serve the Front End files from the server. In my first attempts to deploy, I was really serving them from React directly, so all I was getting was an interactive painting, in which I could navigate, but hadn't the opportunity to communicate with the server (since it was not connected).
What was the solution?
Serve the /build folder and it's files as explained in React's documentation on deployment.
Remove the "proxy": "http://localhost:5000" from package.json. Also remove "homepage":"xxx" if you had so.
Add "start": "node server.js" to your package.json. You want to open your web through node.
I also added a Procfile as recommended in Heroku's best practices for deployment with Node.js. All I have in the file is the following code: web: node server.js.
It just makes sense now. I can accept payments and communicate with my server.
As a sidenote: I didn't delete any of the Stripe specific code in my server.js, since it might help other users using Stripe to handle payments.
use secret key instead of public key in index.js in functions folder.
I just started creating a chatbot and I want it to be multilingual. So, I am using i18n module for the same. I added it's dependency in the package.json but now it is showing an error:
The deployment of your Cloud Function failed:
Build failed: Build error details not available
This is my package.json file:
[{
"name": "dialogflowFirebaseFulfillment",
"description": "This is the default fulfillment for a Dialogflow agents using Cloud Functions for Firebase",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"engines": {
"node": "8"
},
"scripts": {
"start": "firebase serve --only functions:dialogflowFirebaseFulfillment",
"deploy": "firebase deploy --only functions:dialogflowFirebaseFulfillment"
},
"dependencies": {
"actions-on-google": "^2.2.0",
"firebase-admin": "^5.13.1",
"firebase-functions": "^2.0.2",
"dialogflow": "^0.6.0",
"dialogflow-fulfillment": "^0.5.0"
}
},
{
"name": "i18n",
"description": "lightweight translation module with dynamic json storage",
"version": "0.8.4",
"homepage": "http://github.com/mashpie/i18n-node",
"repository": {
"type": "git",
"url": "http://github.com/mashpie/i18n-node.git"
},
"author": "Marcus Spiegel <marcus.spiegel#gmail.com>",
"main": "./index",
"keywords": [
"template",
"i18n",
"l10n"
],
"directories": {
"lib": "."
},
"dependencies": {
"debug": "*",
"make-plural": "^6.0.1",
"math-interval-parser": "^2.0.1",
"messageformat": "^2.3.0",
"mustache": "*",
"sprintf-js": "^1.1.2"
},
"devDependencies": {
"async": "^3.1.0",
"cookie-parser": "^1.4.4",
"express": "^4.16.4",
"jshint": "*",
"mocha": "^6.2.2",
"should": "*",
"sinon": "*",
"url": "^0.11.0",
"zombie": "*"
},
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"jshint": "jshint --verbose .",
"test": "npm run jshint && mocha --exit",
"test-ci": "npm run jshint && istanbul cover mocha -- --exit"
},
"license": "MIT"
}]
And this is my index.js file:
// See https://github.com/dialogflow/dialogflow-fulfillment-nodejs
// for Dialogflow fulfillment library docs, samples, and to report issues
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
const i18n= require('i18n');
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
i18n.configure({
locales : ['en-IN','hi-IN-1'],
directory : '',
defaultLocale : 'en-IN'
});
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
function welcome(agent) {
agent.add(`Welcome to my agent!`);
}
function fallback(agent) {
agent.add(`I didn't understand`);
agent.add(`I'm sorry, can you try again?`);
}
function About(agent){
agent.add(`We are a company!`);
}
// // Uncomment and edit to make your own intent handler
// // uncomment `intentMap.set('your intent name here', yourFunctionHandler);`
// // below to get this function to be run when a Dialogflow intent is matched
// function yourFunctionHandler(agent) {
// agent.add(`This message is from Dialogflow's Cloud Functions for Firebase editor!`);
// agent.add(new Card({
// title: `Title: this is a card title`,
// imageUrl: 'https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png',
// text: `This is the body text of a card. You can even use line\n breaks and emoji! 💁`,
// buttonText: 'This is a button',
// buttonUrl: 'https://assistant.google.com/'
// })
// );
// agent.add(new Suggestion(`Quick Reply`));
// agent.add(new Suggestion(`Suggestion`));
// agent.setContext({ name: 'weather', lifespan: 2, parameters: { city: 'Rome' }});
// }
// // Uncomment and edit to make your own Google Assistant intent handler
// // uncomment `intentMap.set('your intent name here', googleAssistantHandler);`
// // below to get this function to be run when a Dialogflow intent is matched
// function googleAssistantHandler(agent) {
// let conv = agent.conv(); // Get Actions on Google library conv instance
// conv.ask('Hello from the Actions on Google client library!') // Use Actions on Google library
// agent.add(conv); // Add Actions on Google library responses to your agent's response
// }
// // See https://github.com/dialogflow/fulfillment-actions-library-nodejs
// // for a complete Dialogflow fulfillment library Actions on Google client library v2 integration sample
// Run the proper function handler based on the matched Dialogflow intent name
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
intentMap.set('Default Fallback Intent', fallback);
intentMap.set('About the company', About);
// intentMap.set('your intent name here', googleAssistantHandler);
agent.handleRequest(intentMap);
});
Most probably, the error is in the JSON file. Can anybody please help me with this?
You can add the npm package: i18n to your dependencies object in package.json like this:
"dependencies": {
"actions-on-google": "^2.2.0",
"firebase-admin": "^5.13.1",
"firebase-functions": "^2.0.2",
"dialogflow": "^0.6.0",
"dialogflow-fulfillment": "^0.5.0",
"i18n" : "^0.8.4"
}
You appear to be using multiple objects in a list inside your package.json file, I'm not sure if this is how package.json files are meant to work.
[{
},{
}]
Could you try compress all your sections down into a single object, eg.
{
}
ie, move dependencies into a single section etc.
I want to use Google's Docs API but am running into an issue. I followed https://developers.google.com/docs/api/quickstart/nodejs but am having trouble setting it up.
My index.js looks like this:
const functions = require('firebase-functions');
const {google} = require('googleapis');
const {WebhookClient} = require('dialogflow-fulfillment');
const {SimpleResponse, BasicCard, SignIn, Image} = require('actions-on-google');
const calendar = google.calendar('v3');
const people = google.people('v1');
const drive = google.drive('v3');
const docs = google.docs('v1');
process.env.DEBUG = 'dialogflow:*'; // Enable lib debugging statements
My package.json:
"name": "DialogflowFirebaseWebhook",
"description": "Firebase Webhook dependencies for a Dialogflow agent.",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"engines": {
"node": "6"
},
"scripts": {
"lint": "semistandard --fix \"**/*.js\"",
"start": "firebase deploy --only functions, node index.js",
"deploy": "firebase deploy --only functions"
},
"dependencies": {
"firebase-functions": "^2.0.2",
"firebase-admin": "^5.13.1",
"googleapis": "^27.0.0",
"actions-on-google": "2.2.0",
"dialogflow-fulfillment": "0.6.1",
"dialogflow": "0.6.0",
"client-oauth2": "4.2.5"
}
}
Showing only the relevant parts of my script, since it's pretty long, I get this error when I try to run the actual script.
Detailed stack trace: TypeError: google.docs is not a function
Any ideas what I am doing wrong?
Turning my comment into an answer...
It doesn't look like you have anywhere near the current version39 of google apis installed.
You have version 27.
Please run npm install googleapis#39 --save like the doc says.
I am developing cloud function that use the calendar API to list the event from the calendar and parse the response to get the summary
I test my function on the dialog flow console beside and it give me the result that I want but when I integrate it with actions on google It's always go to the catch
/----- read the description for event
//----- read the description for event
function getKeyPoint (agent) {
return fetchDescription(agent.parameters.date,agent.parameters.time).then(() => {
agent.add("The key point for the requiered event is "+keyPoint);
}).catch((err) => {
console.log("Error here "+err);
agent.add(`There is no description `);
});
}
function fetchDescription (date,time){
appointmentDuration = 1;// Define the length of the appointment to be one hour.
dateTimeStart = convertParametersDate(date,time);
dateTimeEnd = addHours(dateTimeStart, appointmentDuration);
return new Promise((resolve,reject)=>{
console.log("is listing now ");
calendar.events.list({
auth: serviceAccountAuth,
calendarId: calendarId,
timeMin: dateTimeStart.toISOString(),
timeMax: dateTimeEnd.toISOString()
},(err,calenderResponse)=>{
if (err || calenderResponse.data.items.length==0){
reject(err || new Error('No event at this time '));
}else {
var calenderResponseBody = calenderResponse.data;
var events=calenderResponseBody.items;
keyPoint = events[0].description;
resolve(keyPoint);
}
});
});
}
the package :
{
"name": "DialogflowFirebaseWebhook",
"description": "Firebase Webhook dependencies for a Dialogflow agent.",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"engines": {
"node": "6"
},
"scripts": {
"lint": "semistandard --fix \"**/*.js\"",
"start": "firebase deploy --only functions",
"deploy": "firebase deploy --only functions"
},
"dependencies": {
"firebase-functions": "^2.0.2",
"firebase-admin": "^5.13.1",
"googleapis": "^27.0.0",
"actions-on-google": "2.2.0",
"dialogflow-fulfillment": "^0.4.1"
}
}
I'm trying to use DeepLinks in Fulfillment Inline Editor in DialogFlow but I get error "DeepLink is not defined". The question is how to import DeepLink into project?
more info about deeplink class:
deeplink class
My index.js:
'use strict';
// Import the Dialogflow module from the Actions on Google client library.
const {dialogflow} = require('actions-on-google');
// Import the firebase-functions package for deployment.
const functions = require('firebase-functions');
// Instantiate the Dialogflow client.
const app = dialogflow({debug: true});
// Handle the Dialogflow intent named 'favorite color'.
// The intent collects a parameter named 'color'.
app.intent('favorite color', (conv, {color}) => {
here I have error "DeepLink is not defined"
conv.ask(new DeepLink({
destination: 'Google',
url: 'http://my.deep.link',
package: 'my.package.name',
reason: 'handle this for you',
}))
})
// Set the DialogflowApp object to handle the HTTPS POST request.
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
My package.json
{
"name": "dialogflowFirebaseFulfillment",
"description": "This is the default fulfillment for a Dialogflow agents using Cloud Functions for Firebase",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"engines": {
"node": "~6.0"
},
"scripts": {
"start": "firebase serve --only functions:dialogflowFirebaseFulfillment",
"deploy": "firebase deploy --only functions:dialogflowFirebaseFulfillment"
},
"dependencies": {
"actions-on-google": "^2.2.0",
"firebase-admin": "^4.2.1",
"firebase-functions": "^0.5.7",
"dialogflow": "^0.1.0",
"dialogflow-fulfillment": "^0.4.1"
}
}
Thanks!
I've go it! :)
The line 4 should looks like:
const {dialogflow, DeepLink} = require('actions-on-google');