Outbound networking HTTP trigger to App store - javascript

const functions = require('firebase-functions');
import iapReceiptValidator from 'iap-receipt-validator';
const password = 'abcdefghijkac64beb900889e1'; // Shared Secret from iTunes connect
const production = false; // use sandbox or production url for validation
async validate(receiptData) {
try {
const validationData = await validateReceipt(receiptData);
// check if Auto-Renewable Subscription is still valid
validationData['latest_receipt_info'][0].expires_date > today
} catch(err) {
console.log(err.valid, err.error, err.message)
}
}
exports.validateReceipt = functions.https.onRequest((req, res) => {
const validateReceipt = iapReceiptValidator(password, production);
}
This is what I have so far. I am using this external library. I am using firebase cloud functions and I am on flame plan. I want to make POST request to send receipt JSON object to app store server for auto-renewable purchase verification. I am not sure how to go forward with this. Can i please get some help in regards to structuring my cloud function. The firebase documentation isn't very helpful.
Appreciate any help!

Related

Accessing a private Google sheet with a google cloud service account

I have a private Google Spreadsheet and I’m trying to access it programmatically using Google Visualization/Google Charts. I've created the service account, and I have tried using the google-auth-library and googleapis npm packages to create an access token that I can then use to access the spreadsheet. But, when I try to use that access token to read from the spreadsheet, the request fails with HTTP code 401 (Unauthorized). What do I need to do in order to make this work?
This is my code:
const { auth } = require('google-auth-library');
const keys = require('./jwt.keys.json');
const id = '{Spreadsheet ID}';
const sheetId = '{Sheet ID}';
const query = "{Query}";
async function getClient(){
const client = auth.fromJSON(keys);
client.scopes = ['https://www.googleapis.com/auth/spreadsheets.readonly'];
console.log(client);
return client;
}
async function main(){
const client = await getClient();
const token = await client.getAccessToken();
console.log(token);
console.log(token.token);
const url = `https://docs.google.com/spreadsheets/d/${id}/gviz/tq?tqx=out:csv&tq=${encodeURIComponent(query)}&access_token=${token.token}#gid=${sheetId}`;
const res = await client.request({url});
console.log(res);
}
main().catch(console.error);
When I saw your script, I thought that it is required modifying the scope. I had got the same situation as you (the status code 401 using your endpoint). Unfortunately, it seems that your endpoint cannot be used using the scope of https://www.googleapis.com/auth/spreadsheets.readonly. So, for example, how about changing it as follows, and testing it again?
From:
https://www.googleapis.com/auth/spreadsheets.readonly
To:
https://www.googleapis.com/auth/spreadsheets
or
https://www.googleapis.com/auth/drive.readonly
Note:
When I tested your endpoint using the modified scope, I confirmed that no error occurred. But if you tested it and when an error occurs, please check other part, again.

Can I send DescribeUserPoolClient commands for a user pool in another AWS account

looking for some AWS Javascript SDK help.
I am in the situation that my User Pool is defined in a separate account to my Lambda which needs to send a DescribeUserPoolClient command.
Code snippet below:
import {
CognitoIdentityProviderClient,
DescribeUserPoolClientCommand,
} from '#aws-sdk/client-cognito-identity-provider';
export async function describeUserPoolClient(userPoolClientId: string, userPoolId: string) {
const cognitoClient = new CognitoIdentityProviderClient({});
const describeUserPoolClientCommand = new DescribeUserPoolClientCommand({
ClientId: userPoolClientId,
UserPoolId: userPoolId,
});
const userPoolClient = await cognitoClient.send(describeUserPoolClientCommand);
return userPoolClient;
}
Since I can only provide a userPoolId and not a full ARN, I can't see a way to send this request cross-account without assuming a role in the other account which makes my local testing a nightmare with getting roles and policies set up.
Can anyone see another way of doing this? Thanks for your help.

Angular 8/Nodemailer - Contact Form function not logging errors, no email received

I'm using an Angular 8/Firebase stack and I have a contact form that writes to my Firestore collection. This works fine. I have also written a cloud function that triggers on write of the database and fires off a nodemailer email to my personal email.
The issue is that I never get any emails even though the cloud function logger seems to be going off every time I submit a test contact form. No errors logged, but none of my console.logs get recorded either.
I've allowed less secure apps and disabled captchas on the Gmail I'm using to send email (even though I don't use 2FA). Still nothing. Now, I'm at a loss as to what could be going on since I have no logs to work with.
Here's my cloud function index.js:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const nodemailer = require('nodemailer');
const smtpTransport = require('nodemailer-smtp-transport');
const gmailEmail = encodeURIComponent(functions.config().gmail.email);
const gmailPassword = encodeURIComponent(functions.config().gmail.password);
const mailTransport = nodemailer.createTransport(
smtpTransport({
service: 'gmail',
auth: {
user: `${gmailEmail}`,
pass: `${gmailPassword}`
}
})
);
exports.sendContactMessage = functions.database
.ref('/messages/{pushKey}')
.onWrite(event => {
const snapshot = event.data;
if (snapshot.previous.val() || !snapshot.val().name) {
return;
}
const val = snapshot.val();
const mailOptions = {
from: `${gmailEmail}`,
to: 'donotreply#something.com',
subject: `You've been contacted by ${val.name} ✨`,
text: `${val.message}`
};
return mailTransport.sendMail(mailOptions, (error, info) => {
if (error) {
console.log('Error occurred');
console.log(error.message);
}
});
});
The trigger itself seems to be working since I see Firebase logs (but not console.logs) in the console every time I hit submit on the contact form. I think it's an issue with SMTP or my mailTransport object. I've tried quite a few different formats for this object that I found across the web but nothing.
Note: The string interpolated variables for my Gmail and password I've set via the Firebase CLI and they log correctly when I run the command to retrieve them. It's not a credentials issue.
Apparently you are mixing-up a Cloud Function trigger for the Realtime Database with a trigger for Firestore. They are two different NoSQL Database services offered by Firebase.
exports.sendContactMessage = functions.database
.ref('/messages/{pushKey}')
.onWrite(...)
is for declaring a trigger for the Realtime Database, but you indicate in your question that you write to Firestore.
So you have to change your function declaration as follows:
exports.sendContactMessage = functions.firestore
.document('messages/{pushKey}')
.onCreate((snap, context) => {...})

Dialogflow fulfilment accessing entities in code

I am working on a chat bot in Dialogflow and want to validate someones age. A quick bit of context: I'm creating a chat bot for identifying care needs such as residential or dementia care. In the initial enquiry I want to be able to make sure that the user is 65 years or older by doing a quick IF statement in the fulfilment code in Dialogflow!
Here are my current intents:
Current Intents
Here is the getUserInfo intent:
getUserInfo intent
Here is the fulfilment code:
'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});
app.intent('careEqnuiry - yourself - getUserInfo', (conv, {age}) => {
const userAge = age;
if (userAge < 65) {
conv.add("You're not old enough to recieve care!");
}
});
// Set the DialogflowApp object to handle the HTTPS POST request.
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
This is all new to me.
The second argument to the callback of the intent handler is an object that contains all the parameters (entities) from Dialogflow.
In your current code you are deconstructing this object for the age parameter (i.e.: {age}).
I noticed you have two different parameters, age and given-name.
You can get these values by doing the following:
'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});
app.intent('careEqnuiry - yourself - getUserInfo', (conv, params) => {
const name = params['given-name'];
const age = params['age'];
if (age.amount < 65) {
conv.ask("You're not old enough to receive care!");
}
});
// Set the DialogflowApp object to handle the HTTPS POST request.
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
Also, the correct way to return a response from a conversation is to use the ask() or close() methods on the conversation object. ask() sends a response while allowing the conversation to continue, and close sends a response and ends the conversation.

Firebase HTTP Trigger Cloud Function to change users' values in realtime database

So I have written code which should change a certain value in the database. I would use cron-jobs to trigger it in every 24h, but there is something wrong with my code.
const functions = require('firebase-functions');
exports.resetPicksStatus = functions.https.onRequest((req, res) => {
.ref('/users/{userId}')
.onWrite(event => {
const status = event.data.val()
if (status.resetted) {
return true
}
console.log("Resetting status for " + event.paramas.userId)
status.resetted = true
status.picksDone = resetToNil(status.picksDone)
return event.data.ref.set(status)
})
})
function resetToNil(s) {
var resetValue = s
resetValue = resetValue.replace(/\b1\b/ig, "0")
return resetValue
}
It looks like you're trying to put a Realtime Database trigger inside your HTTP trigger, which won't have the outcome you're looking for. Instead of using a database trigger, use the Firebase Admin SDK to access the database from within the HTTP trigger.
In your code, add
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const ref = admin.database().ref();
And use ref to access the database.
Check out the Admin SDK documentation here.
Here are some samples of Cloud Functions, some of which show the Admin SDK.
Here's a video showing how to use the Admin SDK
Here's a video on timing Cloud Functions

Categories