Why creating a Stripe customer.id fails within AWS Lambda? - node.js

I am using the Stripe/NodeJS library to generate a Stripe customer id when a user is created:
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
exports.handler = async (event, context) => {
const newUser = JSON.parse(event.body);
const customer = await stripe.customers.create({
email: newUser.emailAddress,
});
return customer.id;
};
I thought that the code is pretty straightforward and almost a duplicate to the library's README example, however, the lambda execution hits the stripe.customers.create and never completes, the lambda eventually times out (the lambda is NodeJS 12.x).
Thoughts on what I am missing in order to get this to work?

Related

cloud functions: trying to create user on firestore from cloud functions "failed to deploy"

I am trying to access my db upon http request.
in the api builder from google i use node.js 16 as a runtime.
I tried running this code:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firestore);
const firestoreDB = admin.firestore()
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase Cloud Functions!");
console.log("function triggered")
});
exports.createUser = functions.firestore.document('Users/asddsa')
.onCreate((snap, context) => {
const newValue = snap.data();
if (snap.data() === null) return null;
const uid = context.params.userId
let notificationCollectionRef = firestoreDB.collection('Users').doc(uid).collection('Notifications')
return notificationCollectionRef.add({
notification: 'Hello Notification',
notificationType: 'Welcome'
}).then(ref => {
return console.log('notification successful', ref.id)
})
});
But I cant even deploy it, it just states that "deployment failed".
Now this is usually when there is a typo in the code. But I am guessing that I didnt set up the connection to the firestore properley. (I never gave it a password or anything)
I assumed that as it is inside the same project, the connection would work either way, but maybe I am wrong?
How do I set up the connection to create the user and not have the deployment fail?
The instructions for Initial setup to configure and set up your Cloud Functions for Firebase project. you can check the Firebase documentation.
You can check the details in Cloud firestore trigger. Which describes Event triggers where you can trigger a function to fire any time a new document is created in a collection by using an onCreate(). This function calls createUser every time a new user profile is added.
Also You can have a look at Github link to create the user.

Get twilio usage data using an AWS Lambda (nodejs)

I would like to be able to get usage data from Twilio from within an AWS Lambda function. I am following the examples on twilio's REST API page but am not having any success. I am using version 3 of Twilio's Node Helper Library. Below is the code that I have in the handler:
'use strict';
exports.handler = async(request, context) => {
const accountSid = 'my account sid';
const authToken = 'my auth token';
const client = require('twilio')(accountSid, authToken);
client.usage.records.today.each(record => console.log(record.count));
};
The Lambda "feels" like it is at least trying to get the data from Twilio. It runs for ~10 seconds before ending without any errors. However I never get the 'here' message.
Thanks in advance, Scott
This is my Lambda code:
exports.handler = (event, context, callback) => {
// Your Account SID from www.twilio.com/console
const accountSid = process.env.TWILIO_ACCOUNT_SID;
// Your Auth Token from www.twilio.com/console
const authToken = process.env.TWILIO_AUTH_TOKEN;
// Import Twilio's Node Helper library
// Create an authenticated Twilio Client instance
const client = require('twilio')(accountSid, authToken);
client.usage.records.lastMonth.each(record => console.log('here'));
};
and this is what I see in the "Function code" section after I run the function (Status: Succeeded).

Timeout error awaiting promise in Lambda?

I am testing a Serverless lambda function and get a timeout error which I believe is due to an await promise().
module.exports.create = async (event) => {
const provider = event.requestContext.identity.cognitoAuthenticationProvider
....//stuff here where I split auth token to get ids...
const cognito = new AWS.CognitoIdentityServiceProvider({
apiVersion: "2016-04-18"
});
const getUserParams = {
UserPoolId: userPoolId,
Username: userPoolUserId
};
const data =JSON.parse(event.body)
const getUser = await cognito.adminGetUser(getUserParams).promise()
const params = {
Item:{
userId: event.requestContext.identity.cognitoIdentityId,
email: getUser, //!timeout issue probably here!
content: data
}
};
try {
const { Listing } = await connectToDatabase()
const listing = await Listing.create({userId: params.Item.userId, email: params.Item.email
In researching a solution, I have come across people splitting up the lambda into two functions so that they collectively pass the timeout. I do not know how to reference a lambda within a lambda, nor am I sure this is the correct approach.
You change the timeout for lambda function
default timeout for lambda function is 3 sec you can override in below the function code basic settings
For anyone googling this: turns out adminGetUser needs a NAT Gateway configured in order for it to be able to retrieve data from Cognito. I was getting a timeout error because it was not executing, period. Read here: https://aws.amazon.com/premiumsupport/knowledge-center/internet-access-lambda-function/.

Unable to handle multiple fulfillment responses

I am using the dialogflow enterprise edition bot,the issue is about receiving responses from rest api(node.js sdk).Recently we have shifted from dialogflow standard edition to Enterprise edition. We have referred and used the following code in this link
https://www.npmjs.com/package/dialogflow
We have created our own cloud function using rest Api which takes the user answer as the request and send the fulfillment text(questions in that particular intent) as the response to the user.When multiple request calls happen the the cloud function is not showing proper response which means
When user(Android/IOS) "A" started answering the bot then the cloud function triggering gets started and it send the questions as the response to the user but when the multiple users started answering the bot, due to multiple calls for the cloud function, the questions which are displayed to the one user are not going to be displayed to the other user say "B". Please help us in handling the multiple calls for node.js sdk
https://i.stack.imgur.com/BVAci.png
This is the view of an intent in dialogflow.
https://i.stack.imgur.com/aRAr6.png ,
https://i.stack.imgur.com/oMp0d.png
https://i.stack.imgur.com/T7Jo7.png
https://i.stack.imgur.com/7U3Rb.png
https://i.stack.imgur.com/EwWSo.png
Above five screenshots represent the first time when the user triggers
the cloud function, and the 1st question is displayed. When we answer the
first question and submit the answer, next question is not displayed.(I am
getting the empty response).
https://i.stack.imgur.com/rLI2I.png ,
https://i.stack.imgur.com/T5wZL.png
These screenshots represent the empty response after first question is answered.
const functions = require('firebase-functions');
const dialogflow = require('dialogflow');
const Firestore = require('#google-cloud/firestore');
const firestore = new Firestore();
admin.initializeApp();
var db = admin.firestore();
const {WebhookClient} = require('dialogflow-fulfillment');
exports.fulfillmenttext = functions.https.onRequest((req,res) =>{
runSample();
async function runSample() {
const projectId = 'bodha-192606';
const sessionId = uuid.v4();
const answer = req.body.Text;
console.log("Text said by the user",answer);
const languageCode = 'en-US';
const credentials = {
client_email: 'xxxx ',
Private_key:'xxxx ',
};
// Instantiate a DialogFlow client.
const dialogflow = require('dialogflow');
const sessionClient = new dialogflow.SessionsClient({
projectId,
credentials,
});
// Define session path
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: answer,
languageCode,
},
},
};
const responses = await sessionClient.detectIntent(request);
console.log('Detected intent');
const result = responses[0].queryResult;
let action = result.action;
console.log("action is"+action);
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
res.status(200).send({"question":result.fulfillmentText});
} else {
console.log(` No intent matched.`);
res.status(400).send("No Intent matched");
}
}
});
It looks like you are using the same session ID for all of your clients. I'm not certain, but I can certainly understand that if Dialogflow gets two requests for the same session at the same time, that it can mix up the replies.
You should be generating a new session for each of your clients - possibly by putting something into an HTTP session (aha!) cookie when they first connect and continuing to use that during the session.

Using AWS Cognito in a Lambda function with npm

I'm trying to use AWS Cognito in a Lambda function to authorize a user.
I have some sample code from a Udemy Course (no longer available): https://www.udemy.com/minimum-viable-aws-cognito-user-auth-in-javascript
The code uses the script files:
aws-cognito-sdk.min.js
amazon-cognito-identity.min.js
The second seems to available by npm as: amazon-cognito-identity-js
The first file is supposed to be a cut down version of the aws-sdk with just the Cognito api components. The full aws-sdk is available from npm as: aws-sdk but I cannot find the cutdown version in npm.
Is the cutdown file: aws-cognito-sdk.min.js available in npm?
EDIT:
According to Russell I should use the aws-sdk package.
So if I have code:
const AWS = require('aws-sdk');
var authenticationDetails = new AWS.AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
I get the error:
Cannot read property 'CognitoIdentityServiceProvider' of undefined
What is the correct path to AuthenticationDetails?
For Lambdas use the aws-sdk module as such:
const { CognitoIdentityServiceProvider } = require('aws-sdk')
//or
const CognitoIdentityServiceProvider = require('aws-sdk/clients/cognitoidentityserviceprovider') // Much smaller size
For authentication use the AdminInitiateAuth method.
const cognitoProvider = new CognitoIdentityServiceProvider({
apiVersion: '2016-04-18',
accessKeyId:...
secretAccessKey: ...
region:...
})
await cognitoProvider.adminInitiateAuth(...)
The amazon-cognito-identity-js package is meant for frontend clients (React, React Native, etc). It contains only the functionality necessary to connect to Cognito. It does not require the aws-sdk module (unless you need extra features).
While you may be able to use the amazon-cognito-identity-js for your use case it's far from ideal as you are just pretending to be an unauthenticated user with limited functionality compared to loading the admin method using your api key thereby providing you with much more functionality.
Got this working.
package.json needs dependencies:
"amazon-cognito-identity-js": "^1.31.0",
"aws-sdk": "^2.182.0",
AWS Lambda does not use Javascript ES6 and so you can't use the 'import' keyword.
const AWS = require('aws-sdk');
var AmazonCognitoIdentity = require('amazon-cognito-identity-js');
var CognitoUserPool = AmazonCognitoIdentity.CognitoUserPool;
var AuthenticationDetails = AmazonCognitoIdentity.AuthenticationDetails;
var CognitoUser = AmazonCognitoIdentity.CognitoUser;
var poolData = {
UserPoolId: 'THE USER POOL ID',
ClientId: 'THE CLIENT ID'
};
var userPool = new CognitoUserPool(poolData);
AWS.config.region = 'AWS_REGION';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'THE USERPOOL ID',
});
var email = "someone#somewhere.com";
var password = "password";
var authenticationData = {
Username: email,
Password: password
};
var authenticationDetails = new AuthenticationDetails(authenticationData);
var userData = {
Username: email,
Pool: userPool
};
var cognitoUser = new CognitoUser(userData);
console.log(result);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
console.log('access token + ' + result.getAccessToken().getJwtToken());
callback(null, result);
},
onFailure: function (err) {
console.log('Login error: ' + err);
callback(null, result);
}
});
I believe you are referring to the amazon-cognito-identity-js npm package here:
https://www.npmjs.com/package/amazon-cognito-identity-js
The NPM package includes both files.
The package includes the cognito SDK calls (aws-cognito-sdk). It also depends on the core AWS SDK.

Resources