How to check Stripe webhook signatures in firebase functions - node.js

Hi 👋đŸģI'm trying to verify a Stripe signature in Firebase functions. But when i try stripe.webhooks.constructEvent it catches an error saying:
No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe? https://github.com/stripe/stripe-node#webhook-signing 😔
I've logged out the raw body, and it looks fine 🤖
<Buffer 7b 0a 20 20 22 69 64 22 3a 20 22 65 76 74 5f 31 46 72 6b 4d 73 41 55 73 34 77 79 52 42 49 73 63 6d 66 72 43 39 7a 37 22 2c 0a 20 20 22 6f 62 6a 65 63 ... >
Here is the relevant code:
// A webhook called by stripe
const sig = req.headers['stripe-signature']
let event
// 1. construct event and validate
try {
event = stripe.webhooks.constructEvent(req.rawBody, sig, functions.config().stripe.mytestkey)
assert(event)
} catch (err) {
console.log(`Error when constructing Stripe event: ${err} - ${req.body}`)
res.status(400).send({ error: `Stripe webhook error: ${err}` })
return
}
// 2. Handle webhook
res.status(200).send(`successfully handled webhook ${hook}`)
})
Any thoughts? 💭

Doing
let sig = req.get('stripe-signature');
instead of
const sig = req.headers['stripe-signature']
should do the trick.
According to the Express documentation:
req.get(field)
Returns the specified HTTP request header field (case-insensitive
match).

Finally, I figured out I had to write req.rawBody.toString('utf8').
Source: https://github.com/stripe/stripe-node/issues/341

Related

Get the Blob Using Node Multer Buffer And Convert Blob To Base 64

I'm trying to get the Uint8Contents as Blob to convert to base64 and store it as PgSQL bytea coming from the ArrayBuffer/Buffer using multer middleware for Expressjs.
Most of the answers refer to saving it in a file system first, but how would you use the multer memory storage? (I've used it this way)
import { Router, Request, Response } from 'express'
import multer from 'multer'
const storage = multer.memoryStorage()
const upload = multer({ storage: storage })
const api = Router()
api.post('/customer/:customer_id/photo', upload.single('photo'),
async (req: Request, res: Response) => {
const customerId = req.params.customer_id
const photoBuffer = req?.file?.buffer as Buffer
const arrayBuffer = photoBuffer.buffer.slice(
photoBuffer.byteOffset,
photoBuffer.byteOffset + photoBuffer.byteLength
)
const uInt8Contents = photoBuffer.readUInt8(photoBuffer.byteOffset)
console.log("uInt8Contents",uInt8Contents)
// const arrayBuffer = Uint8Array.from(photoBuffer).buffer
// const photoBlob = Buffer.from(arrayBuffer).Blob([arrayBuffer])
console.log("bufferPhoto", arrayBuffer)
// TODO: Need a code for converting array buffer or buffer to be the correct image Blob
const base64Photo = Buffer.from(arrayBuffer).toString('base64')
// Store base 64 photo in PgSQL bytea
// ...
}
)
I just couldn't figure out how to get the correct Blob to be converted as base64 and store it in PgSQL as bytea.
So, the question is: On the second to the last line, how would I convert the file into a Blob?
I get this output, but it does not seem to be the Uint8Contentsof the blob because the image does not display at all.
ArrayBuffer {
[Uint8Contents]: <ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 48 00 48 00 00 ff e2 02 a0 49 43 43 5f 50 52 4f 46 49 4c 45 00 01 01 00 00 02 90 6c 63 6d 73 04 30 00 00 6d 6e 74 72 52 47 42 20 58 59 5a 20 07 dd 00 0a 00 08 00 17 00 2b 00 36 61 63 73 70 41 50 50 4c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... 2527 more bytes>,
byteLength: 2627
}
I found this issue:
https://github.com/dherault/serverless-offline/issues/464
It was basically a serverless-offline issue: When a server is running in serverless-offline and the image is uploaded, the binary image gets distorted like this:
Where the binary image should look like this, instead:
In short, the characters are being changed by serverless-offline. The link, however, suggests that if you are going to deploy the code in a non-serverless-offline environment, it will work.
So, this code will still work when deployed:
import { Router, Request, Response } from 'express'
import multer from 'multer'
const storage = multer.memoryStorage()
const uploadPhoto = multer({ storage: storage }).single('upload')
const api = Router()
v1Api.post('/user/:user_id/photo', uploadPhoto, async (req: Request, res: Response) => {
const userId = req.params.user_id
const photoBuffer = req?.file?.buffer as Buffer
const binaryPhoto = Buffer.from(photoBuffer).toString('binary')
const base64Photo = Buffer.from(binaryPhoto).toString('base64')
console.log(base64photo) // Save this base64photo as bytea
})
Otherwise, configure the serverless.yml to support binary using this plugin aws-serverless-express-binary.
Edit
We deployed it in an environment and it seems to work correctly.

child_process.spawn returning buffer object

const cp = require("child_process");
ls = cp.spawn("node", ["./scripts/test.js"]);
ls.stdout.on("data", (data) => {
console.log(`stdout": ${data}`);
const result = data.toString();
});
In ls.stdout.on i am getting data as buffer and if i do it to data.toString()
it gives me result like "{evenNumberSum :8, oddNumberSum:6}" but i want result as a JSON object i am not even able to parse this type of result can anyone give me a better way to get result from buffer
CurrentOutput:
<Buffer 7b 3a 6e 61 6d 65 3d 3e 22 4a 6f 68 6e 22 2c 20 3a 61 67 65 3d 3e 33 30 2c 20 3a 63 69 74 79 3d 3e 22 4e 65 77 20 59 6f 72 6b 22 7d 0a>
Required Output:
{evenNumberSum :8, oddNumberSum:6}
test.js
let result = {};
function add(val1, val2) {
return val1 + val2;
}
result.evenNumbersSum = add(2, 4);
result.oddNumbersSum = add(1, 3);
result.mixNumbersSum = add(1, 2);
console.log(result);
I am not sure what test.js looks like, but I was not able to reproduce this issue.
I am using the following code..
--EDIT/DISCLAIMER-- People are most likely downvoting this because the solution I provided uses eval. To summarize:
YOU SHOULD USE eval AS LITTLE AS POSSIBLE (in a perfect world, eval would never be used)
ONLY USE IT ON *TRUSTED* strings (aka DO NOT USE eval ON USER SUPPLIED DATA!!! EVER.)
Considering the disclaimer above, the only way I could get this to work was:
main.js:
const cp = require('child_process');
ls = cp.spawn('node', ['./test.js']);
ls.stdout.on('data', (data) => {
const dataString = data.toString();
const dataJson = eval(`(${dataString})`);
console.log('Data as JSON =', dataJson);
console.log('evenNumberSum =', dataJson.evenNumberSum);
console.log('oddNumberSum =', dataJson.oddNumberSum);
});
test.js:
console.log({ evenNumberSum: 8, oddNumberSum: 6 });
Which produces the following output:
Data as JSON = { evenNumberSum: 8, oddNumberSum: 6 }
evenNumberSum = 8
oddNumberSum = 6

Nodejs - webscoket set encoding for receiving data?

I have a websocket proxy to TCP setup. But the data I receive is HEX buffer. How I can I convert it to string readable format? I think I have to set it to utf-8 but I don't see a option for that in websocket.
Example of data recevied:
Received: <Buffer 3c 63 72 6f 73 73 2d 61 69 6e 272 6f 2a 27 ... 46 more bytes>
Client code:
const ws = new WebSocket('ws://example.com:1211');
ws.onmessage = message => {
console.log('Received: ', message.data)
};
Try this:
const convert = (from, to) => hexMessage => Buffer.from(hexMessage, from).toString(to);
const hexToUtf8 = convert('hex', 'utf8');
hexToUtf8('your hex msg here')
Also check out this post: Hex to String & String to Hex conversion in nodejs

How do I use npm forever-monitor to log to stdout

I have a simple nodejs docker service. I'm watching stdout in development and logging to AWS cloudwatch in production.
I've just added forever-monitor, but that breaks my logging. So I've started catching stdout on the child process,
const forever = require('forever-monitor');
const child = new (forever.Monitor)('server.js', {
max: 3,
silent: true,
args: []
});
child.on('stdout', function(data) {
console.log(data);
});
but that just gives me byte code out -
[nodemon] starting `node forever.js`
<Buffer 63 6f 6e 6e 65 63 74 65 64 20 74 6f 20 6c 69 76 65 20 64 62 0a>
How do I get my console.log statements back into std-out?
It looks like data is a stream (see node docs).
I've updated my code to -
child.on('stdout', function(data) {
console.log(data.toString());
});
And now it's working as expected. (I found this question useful).

NodeJS memcache get Buffer output

I'm trying to load data from memcached (EDIT: using the nodejs memcached package) but I keep getting back something like :
{ available_ads: <Buffer 5b 7b 22 69 64 22 3a 37 31 34 31 35 2c 22 74 69 74 6c
65 22 3a 22 44 6f 6c 6c 61 72 53 68 61 76 65 43 6c 75 62 2e 63 6f 6d 22 2c 22 73
75 62 74 69 74 6c ...>, cas: '2' }
I don't know much about memcached so maybe it's because of an invalid character. Here's the output from telnet:
[{"id":71415,"title":"DollarShaveClub.com","subtitle":"","body":"Our Blades Are F***ing Great","click_url":"http:\/\/b.v11media.com\/click?k=eeacbb44ecf52873acd8cfbe63ffdbea&uid=111&ip_list=%5B%2298.143.242.51%22%2C%2210.122.186.15%22%5D&o=71415&src=json","image_url":"http:\/\/img.youtube.com\/vi\/ZUG9qYTJMsI\/0.jpg","cpa":"1","engagement_type":1,"image_width":480,"image_height":360,"currency":"","gender":null,"max_age":null,"min_age":null,"is_vc_ok":true,"width":500,"height":311,"length":94,"is_autoplay":false,"is_responsive":true,"platforms":["web","mobile"],"supported_events":["play","complete"]},{"id":70799,"title":"Watch Settlers Online video!","subtitle":"","body":"Watch the entire video.","click_url":"http:\/\/b.v11media.com\/click?k=eeacbb44ecf52873acd8cfbe63ffdbea&uid=111&ip_list=%5B%2298.143.242.51%22%2C%2210.122.186.15%22%5D&o=70799&src=json","image_url":"http:\/\/img.youtube.com\/vi\/1sZKP0QnIIY\/0.jpg","cpa":"1","engagement_type":1,"image_width":480,"image_height":360,"currency":"","gender":null,"max_age":29,"min_age":21,"is_vc_ok":true,"width":520,"height":325,"length":50,"is_autoplay":false,"is_responsive":true,"platforms":["web","mobile"],"supported_events":["play","complete"]},{"id":70797,"title":"Watch this Samsung Memory - Meet Loading Ball Larry video!","subtitle":"","body":"Please watch the entire video.","click_url":"http:\/\/b.v11media.com\/click?k=eeacbb44ecf52873acd8cfbe63ffdbea&uid=111&ip_list=%5B%2298.143.242.51%22%2C%2210.122.186.15%22%5D&o=70797&src=json","image_url":"http:\/\/s3.amazonaws.com\/V11\/images\/982727944edee812a1a8c874a9abf65a.png","cpa":"1","engagement_type":1,"image_width":125,"image_height":79,"currency":"","gender":null,"max_age":34,"min_age":18,"is_vc_ok":true,"width":500,"height":310,"length":103,"is_autoplay":false,"is_responsive":true,"platforms":["web","mobile"],"supported_events":["play","complete"]},{"id":72006,"title":"Nike: No Cup is Safe","subtitle":"","body":"Please watch the entire video.","click_url":"http:\/\/b.v11media.com\/click?k=eeacbb44ecf52873acd8cfbe63ffdbea&uid=111&ip_list=%5B%2298.143.242.51%22%2C%2210.122.186.15%22%5D&o=72006&src=json","image_url":"http:\/\/img.youtube.com\/vi\/1jRoHGq9EoY\/0.jpg","cpa":"1","engagement_type":1,"image_width":480,"image_height":360,"currency":"","gender":null,"max_age":null,"min_age":null,"is_vc_ok":true,"width":300,"height":250,"length":63,"is_autoplay":false,"is_responsive":false,"platforms":["web"],"supported_events":["play","complete"]},{"id":72049,"title":"Behind the Cameras - by Rolex","subtitle":"","body":"Please watch the entire video.","click_url":"http:\/\/b.v11media.com\/click?k=eeacbb44ecf52873acd8cfbe63ffdbea&uid=111&ip_list=%5B%2298.143.242.51%22%2C%2210.122.186.15%22%5D&o=72049&src=json","image_url":"http:\/\/img.youtube.com\/vi\/k9o1lAq4zTw\/0.jpg","cpa":"1","engagement_type":1,"image_width":480,"image_height":360,"currency":"","gender":null,"max_age":null,"min_age":null,"is_vc_ok":true,"width":520,"height":325,"length":39,"is_autoplay":false,"is_responsive":false,"platforms":["web","mobile"],"supported_events":["play","complete"]},{"id":72055,"title":"Huggies - Meet the Squirmers!","subtitle":"","body":"Please watch the entire video.","click_url":"http:\/\/b.v11media.com\/click?k=eeacbb44ecf52873acd8cfbe63ffdbea&uid=111&ip_list=%5B%2298.143.242.51%22%2C%2210.122.186.15%22%5D&o=72055&src=json","image_url":"http:\/\/img.youtube.com\/vi\/tZnzHq3_xaQ\/0.jpg","cpa":"1","engagement_type":1,"image_width":480,"image_height":360,"currency":"","gender":null,"max_age":null,"min_age":null,"is_vc_ok":true,"width":300,"height":250,"length":33,"is_autoplay":false,"is_responsive":false,"platforms":["web","mobile"],"supported_events":["play","complete"]},{"id":70794,"title":"Open Days 2012","subtitle":"","body":"Please watch the entire video.","click_url":"http:\/\/b.v11media.com\/click?k=eeacbb44ecf52873acd8cfbe63ffdbea&uid=111&ip_list=%5B%2298.143.242.51%22%2C%2210.122.186.15%22%5D&o=70794&src=json","image_url":"http:\/\/img.youtube.com\/vi\/t4TnaVXQCa4\/0.jpg","cpa":"1","engagement_type":1,"image_width":480,"image_height":360,"currency":"","gender":"f","max_age":null,"min_age":null,"is_vc_ok":true,"width":520,"height":325,"length":58,"is_autoplay":false,"is_responsive":true,"platforms":["web","mobile"],"supported_events":["play","complete"]},{"id":70795,"title":"Samsung Memory - Loading Ball Larry","subtitle":"","body":"Please watch the entire video.","click_url":"http:\/\/b.v11media.com\/click?k=eeacbb44ecf52873acd8cfbe63ffdbea&uid=111&ip_list=%5B%2298.143.242.51%22%2C%2210.122.186.15%22%5D&o=70795&src=json","image_url":"http:\/\/img.youtube.com\/vi\/a5S668LyM5c\/0.jpg","cpa":"1","engagement_type":1,"image_width":480,"image_height":360,"currency":"","gender":null,"max_age":100,"min_age":30,"is_vc_ok":true,"width":520,"height":325,"length":103,"is_autoplay":false,"is_responsive":true,"platforms":["web","mobile"],"supported_events":["play","complete"]},{"id":71522,"title":"Huggies Snug & Dry","subtitle":"","body":"Watch the dads test out Huggies at the mall","click_url":"http:\/\/b.v11media.com\/click?k=eeacbb44ecf52873acd8cfbe63ffdbea&uid=111&ip_list=%5B%2298.143.242.51%22%2C%2210.122.186.15%22%5D&o=71522&src=json","image_url":"http:\/\/img.youtube.com\/vi\/Kthn6DkQVL4\/0.jpg","cpa":"1","engagement_type":1,"image_width":480,"image_height":360,"currency":"","gender":null,"max_age":null,"min_age":18,"is_vc_ok":true,"width":520,"height":325,"length":33,"is_autoplay":false,"is_responsive":true,"platforms":["web","mobile"],"supported_events":["play","complete"]}]
Can anyone tell me why the nodejs library would output a buffer tag?
EDIT: here's my code
var Memcached = require('memcached');
var memcached = new Memcached('localhost:11211');
memcached.gets('available_ads', function(err, data){
if(err){ console.log(err); }
console.log(data);
res.json({'click_url' : data});
});
try using:
data.toString();
and then you'll probably need to use JSON.parse:
JSON.parse(data.toString());
It is when you store/set you'll need to store as String.
Example:
mc.set('keyName', JSON.stringify(thisObj), {expires:0}, function(err, val){
if (err) {
callback(err);
} else {
callback(null, thisObj);
}
});
Then when you read it back, just read it as normal json.
Example:
mc.get('keyName', async function(err, data){
callback(null, JSON.parse(data));
}

Resources