How to identify for which user the stripe webhook route has been called? - express

I am trying to implement a stripe subscription to my web app. I am using the stripe checkout session for this purpose.
I followed the stripe documentation https://stripe.com/docs/billing/subscriptions/build-subscriptions?ui=checkout
Whenever the checkout is completed checkout.session.completed event is fired. During this event I want to set subscriptionStatus from false to true in my database. But I am unable to identify for which user the /webhooks route has been called.
Here is my code:
export const postStripeWebhook = async (req: ExtendedRequest, res: Response) => {
let data;
let eventType;
let event = req.body;
const webhookSecret = "web hook secret provided by stripe";
if (webhookSecret) {
let signature = req.headers["stripe-signature"];
try {
event = stripe.webhooks.constructEvent(req.body, signature , webhookSecret);
} catch (err) {
console.log(`⚠️ Webhook signature verification failed.`); //This part is throwing the error
return res.sendStatus(400);
}
data = event.data;
eventType = event.type;
} else {
data = req.body.data;
eventType = req.body.type;
}
let subscription;
switch (eventType) {
case checkout.session.completed:
//Logic to update subscriptionStatus of the user in the database
break;
//other events are handles
}
res.sendStatus(200);
};
Please guide me on how to identify the user.

Under subscription mode, customer ID can be found under customer parameter in checkout.session.completed event. You can then use Customer Retrieval API to find the customer information.
Alternatively, you can create a Customer first, then set it in customer parameter when creating a Checkout Session. This allows you to identify the user with customer parameter in checkout.session.completed event afterwards.

Related

How to distinguish connected users in WebSocket?

I'm trying to create an event in express.js, where connected users will be sent to the client.
My goal is that in client side user can see who belongs that particular message sent from.
As it describes in docs and as I could also run in localhost, broadcasting messages works fine.
wss.on("connection", function connection(ws) {
ws.on("message", function message(data) {
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
});
});
So before sending messages to client, there should be another event where connected username should be sent, so that in client side can be defined who that particular message belongs.
My idea is to create users object which supposed to keep track of all connected users like here.
const users = {};
wss.on("connection", function connection(ws) {
ws.on("userName", function message(userName) {//this doesn't work
const user = {
name: userName,
id: uuid(), // some unique id, no idea if websocket has or not
};
users[id]= user
ws.send("user", user) // current user who belongs the message to
ws.send("users", users) // users to show connected users list
});
ws.on("message", function message(data) {
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
});
});
user event doesn't work, it is just my idea but not sure if how to do it correctly.
Any help will be appreciated.

How to store user session after signup in remix-auth?

I'm using https://github.com/sergiodxa/remix-auth-github.
I was wondering, if I have a signup screen, what is the correct method to store the user session once the signup is finished, so the user does not have to log in again?
To explain this more clearly. Imagine I have a function:
async function signup(userInfo) {
await DB.insertUser(userInfo)
}
Once this is finished, I would like to store the user's session information inside of the cookie instead of having them log in again. What's the best method to do this?
Author here, if your Authenticator stores the data returned by signup then you could do something like this:
export let action: ActionFunction = async ({ request }) => {
// get the user info from the formData, however you are doing it, this
// depends on your app
let userInfo = await getUserInfo(request)
// register the user with your function
let user = await signup(userInfo)
// get the session object from the cookie header, the getSession should
// be the same returned by the sessionStorage you pass to Authenticator
let session = await getSession(request.headers.get("cookie"))
// store the user in the session using the sessionKey of the
// Authenticator, this will ensure the Authenticator isAuthenticated
// method will be able to access it
session.set(authenticator.sessionKey, user)
// redirect the user somewhere else, the important part is the session
// commit, you could also return a json response with this header
return redirect("/somewhere", {
headers: { "Set-Cookie": await commitSession(session) },
});
}
This way, now when you call authenticator.isAuthenticated(request) it will work and return the user object.

Client app calling Stripe API after card form exit, for future payment

I am adding Stripe 3D secure to a React-Native app, following the document at https://stripe.com/docs/payments/save-and-reuse
-- save the card, and charge off-session later when the service is completed.
For saving card, my app uses a WebView component to load a HTML, using <script src="https://js.stripe.com/v3/"></script> .
It successfully saved the client secret and exited the card form.
Question: At payment time later, in case next action for strong customer authentication is required, how to get a stripe object again so as to call stripe.confirmCardPayment()?
I tried below but failed -- catch(error), and error is empty.
import {loadStripe} from '#stripe/stripe-js';
confirmPayment = async () => {
try {
const stripe = await loadStripe("pk_test_...");
// stripe
// .confirmPaymentIntent('{PAYMENT_INTENT_CLIENT_SECRET}', {
// payment_method: '{PAYMENT_METHOD_ID}',
// return_url: 'https://example.com/return_url',
// })
// .then(function(result) {
//
// });
} catch(error) {
console.error(`failed to load stripe ${JSON.stringify(error)}`);
}
You can use stripe.confirmCardPayment in a variety of ways. In your case you probably already have a PaymentMethod ID, meaning you can confirm the PaymentIntent client side with that PaymentMethod ID instead of an Elements object:
stripe
.confirmCardPayment('{PAYMENT_INTENT_CLIENT_SECRET}', {
payment_method: '{PAYMENT_METHOD_ID}',
})
.then(function(result) {
// Handle result.error or result.paymentIntent
});

React native firebase - facebook sign-in not triggering onAuthStateChanged listener

this is the second problem Im having with RNFB facebook login.
Im following the official code sample provided by RNFB....code below
Problem is with the line firebase().signInWithCredential(facebookCredential);....its not triggering the firebase listener auth().onAuthStateChanged
All other code is running as it should and facebookCredential variable is populated correctly
import { firebase } from '#react-native-firebase/auth';
onFacebookButtonPress = async () => {
// Attempt login with permissions
const result = await LoginManager.logInWithPermissions([
'public_profile',
'email',
]);
if (result.isCancelled) {
throw 'User cancelled the login process';
}
// Once signed in, get the users AccesToken
const data = await AccessToken.getCurrentAccessToken();
if (!data) {
throw 'Something went wrong obtaining access token';
}
// Create a Firebase credential with the AccessToken
//const facebookCredential = firebase.FacebookAuthProvider.credential(data.accessToken);
const facebookCredential = firebase.auth.FacebookAuthProvider.credential(
data.accessToken,
);
// Sign-in the user with the credential
firebase().signInWithCredential(facebookCredential);
};
I figured it out by putting a try/catch around the problematic line. Turned out was because I had already once signed in using Google.
An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address
You shouldn't wait till something goes wrong before you add try/ catch's. signInWithCredential returns many different types of errors, which you handle. From the docs:
firebase.auth().signInWithCredential(credential).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
if (errorCode === 'auth/account-exists-with-different-credential') {
alert('Email already associated with another account.');
// Handle account linking here, if using.
} else {
console.error(error);
}
});
Please handle the other error cases too 🙂:
auth/account-exists-with-different-credential
auth/invalid-credential
auth/operation-not-allowed
auth/user-disabled
and more.

FeatherJS - Get user information with hook?

So im trying out FeatherJS and i was able to register a new user, request a token and also request protected data (using Authorization in the header).
Very important: I am using HTTP Rest API only. The docs seem to point often times to the client feathers module, which i don't use.
So currently i have a super simple setup, i have a message service with a text. One before hook to process the message. Here i want to get back the user information:
module.exports = function (options = {}) {
return async context => {
const text = context.data.text
const user = context.params.user;
context.data = {
text,
userId: user._id
}
return context;
};
};
this doesn't work. In my mdb i only get back:
{
"_id": "5c35ce18523501803f6a8d8d",
"text": "123",
"createdAt": "2019-01-09T10:34:00.774Z",
"updatedAt": "2019-01-09T10:34:00.774Z",
"__v": 0
}
i've tried to add the token, that i always submit when i post a message via Authorization, like so:
module.exports = function (options = {}) {
return async context => {
const text = context.data.text
const user = context.params.user;
const token = context.params.accessToken
context.data = {
text,
userId: user._id,
tokId: token
}
return context;
};
};
but it seems like i always just get the same result back like shown above.
Any ideas how i can get the user information back of the current user by using the accessToken?
Never used FeathersJS before, so just trying to understand the ecosystem and how to approach this in FeathersJS.
Any advice is appreciated! Thanks in advance everyone!
Not quite sure what exactly went wrong, but i got it now working by just creating a new project.
Now i did recreate this project actually before and got the issue as above , but this time it somehow worked.
For anyone who wants to know the steps i did to 'fix' it:
1.Create a new folder
2. feathers generate app
3. feathers generate authentication
4. feathers generate service (name for the service: messages)
5. feathers generate hook (name: process-msg, before hook, model: messages)
6. Add this to the hook process-msg:
module.exports = function (options = {}) {
return async context => {
const user = context.params.user;
const text = context.data.text;
context.data = {
userId: user.email,
text,
dateTime: new Date().getTime()
}
return context;
};
};
Use postman, register a new account then authenticate to get the token. Save token and add it as Authoriztation Header inside Postman. You should then get also back the user email from the user that is registered, simply because of the token that was added to the Authorization Header.
Greetings!
go to authentication.js and find app.service definition. Right in there, create an after hook and add the details you want the client to receive
app.service('authentication').hooks({
before: {
...//as you currently have it
},
after: {
create: {
hook => {
// hook.result.accessToken is already provided
delete hook.params.user.password
hook.result.user = hook.params.user;
hook.result.token_type = 'Bearer';
hook.result.exp = 3600;
}
}
}
})
I hope this helps
So, if I understand it correctly, you want to get the user object from the hook?
You can just use const user = context.user;to accomplish this.