how do I cancel Subscription in stripe inside react - javascript

I am using react. I want to delete old subscription when user changes his subscription plan.
this is my code.
import {loadStripe, useStripe} from '#stripe/stripe-js'
const loadCheckout = async (priceId) =>{
const docRef = await db
.collection('customers')
.doc(user.uid)
.collection('checkout_sessions')
.add({
price:priceId,
success_url:window.location.origin,
cancel_url: window.location.origin,
})
docRef.onSnapshot(async (snap) =>{
const {error, sessionId} = snap.data();
if(error){
alert(`an error occured ${error.message}`)
}
if(sessionId){
const stripe = await loadStripe("pk_test_51JG0BKLXYmn2IpSgISeCDbsCNllISGA3PvEbSzBz5bpo8WTvmqI6UKCbzpxX92LKiN0hftRrobm1J6wJZPCOWSTs0081pmQFJE")
const deleted = await stripe.subscriptions.del(
subscription.id
);
console.log(deleted)
stripe.redirectToCheckout({sessionId});
}
})
}
my code give an error saying stripe.subscriptions.del is not a function.
the code work if I remove this line the payment is successful and all.
In stripe API Docs its says to use .del() but it isnt working here.

Your React code uses Stripe.js which is a client-side library. It cannot modify Subscriptions, only secret key API calls can do that which Stripe.js does not use.
You need to make the request to update/delete the Subscription, you need to make the request server-side (in your Firebase app) using the stripe-node library and your secret API key: https://stripe.com/docs/api/subscriptions/cancel?lang=node.

You can use "customer portal" option inside Stripe to avoid backend coding.
It will generate a link to a page where your customer will be able to cancel the subscription.
Inside Stripe: Billing -> subscriptions -> Setup Customer portal

Related

Trying to block authentication if user is in the banned collection

I am building a chat app and I am trying to figure out the banning system. The idea if the user is in the banned collection becaused he used banned words, block authentication from his account. The problem is that for some reason it does execute the code but rather only does the signInWithRedirect() function. Take a look at my code:
const googleProvider = new GoogleAuthProvider();
const signInWithGoogle = async () => {
try {
const res = await signInWithRedirect(auth, googleProvider);
const user = res.user;
const q = query(collection(db, "banned"), where("uid", "==", user.uid));
const docs = await getDocs(q);
if (docs.exists()) {
//if exists ban the user
console.log('you cannot use this chat app , you are banned!)
Here is also the LoginPage.jsx
function LoginPage() {
const [user] = useAuthState(auth)
const navigate = useNavigate()
console.log(user)
return (
<div>
<div style={{'display': 'none'}}>
<Navbar />
</div>
<Welcome />
</div>
)
}
Here is also signOut
const navigate = useNavigate()
const signOutWithGoogle = () => {
signOut(auth)
navigate('/')
}
Here is firebase firestore
I tried this with promises but nothing happened , I used async , nothing happened
I would not implement such a "banning" system only based on front-end code. It would actually be quite easy for a malicious end-user to bypass your check based on a standard query to a collection.
I would use a Firebase Security Rule to enforce the banishment: Security Rules stand between your data and malicious users and are executed/checked in the back-end. To be complete, with this approach the user will still be authenticated and signed-in but will not be able to interact with the Firebase back-end services like Firestore or Cloud Storage.
Concretely you could as follows:
Write a security rule based on a specific collection in which you create a document per banned user with the user ID as document ID. Then you can use the exists() method to check if the user is banned or not.
Use a Cloud Function to ban (and maybe "un-ban") a user. Again, with Cloud Function the code is executed in the back-end and you therefore avoid the possibility that a malicious user writes a code that could "un-ban" him.

Vue 3 Firebase Auth get *any* user data by id? [duplicate]

This question already has an answer here:
How to get FirebaseUser from a uid?
(1 answer)
Closed 8 months ago.
New to vue/firebase. I was able to lookup how to pull up “current user” data from auth no problem but trying to write a js composable that I can pass in any user id (not necessarily current user) and it will return the user object or at least displayName.
All the docs/vids I can find on the topic reference getting info on *current user *only not another user. From the Google Docs it says I should be able to do this in the "Retrieve user data" section. Closest model to Vue code-wise seems to be “Node.Js” but it isn't working.
Here's what I've got in getUserById
import { getAuth } from 'firebase/auth'
const getUserById = (u) => { // u = user id
const userData = null
getAuth()
.getUser(u)
.then((userRecord) => {
// See the UserRecord reference doc for the contents of userRecord.
console.log(`Successfully fetched user data: ${userRecord.toJSON()}`);
userData = userRecord
})
.catch((error) => {
console.log('Error fetching user data:', error);
});
return { userData }
}
export default getUserById
The error I get is getUser is not a function. I tried adding getUser to the import but same error.
There is no way to look up information about just any user by their UID in the client-side APIs of Firebase as that would be a security risk. There is an API to look up a user by their UID in the Admin SDK, but that can only be used on a trusted environment (such as your development machine, a server you control, or Cloud Functions/Cloud Run), and not in client-side code.
If you need such functionality in your app, you can either wrap the functionality from the Admin SDK in a custom endpoint that you then secure, or have each user write information to a cloud database (such as Realtime Database or Firestore) and read it from there.
Also see:
How to get FirebaseUser from a uid?
Firebase get user by ID
Is there any way to get Firebase Auth User UID?

showing premium stripe subscription after trial ends

I have an app in which I have successfully set up stripe payments, with a trial, and then after the 60 day trial, a 9.99 per month fee. However, once the 60 days is up, I want to give the user an option to have a 99.99 per year one time fee instead.
I have done this, but the problem is, if I go into the manage subscriptions page in my app, it gives the option for the 99.99 plan even if the 60 days isnt up, and then if I click update to move to that plan, it doesn't cancel the original trial, and then pretty much breaks my code after that.
code (just incase needed)
export async function createCheckoutSession(){
let user = firebase.auth().currentUser;
const checkoutSessionRef = firestore
.collection('customers')
.doc(userID)
.collection('checkout_sessions')
.add({
price: 'price_1Iav0JKDPaWWeL1yBa9F7Aht',
success_url: "http://localhost:3000/successPage",
cancel_url: "http://localhost:3000/signup",
});
// Wait for the CheckoutSession to get attached by the extension
(await checkoutSessionRef).onSnapshot(function (snap) {
const { error, sessionId } = snap.data();
if (error) {
// Show an error to your customer and
// inspect your Cloud Function logs in the Firebase console.
console.log(`An error occured: ${error.message}`);
}
if (sessionId) {
// We have a session, let's redirect to Checkout
// Init Stripe
const stripe = window.Stripe('pk_test');
stripe.redirectToCheckout({sessionId})
console.log("logged stripe")
}
});
}
manage subscription function (firebase api)
export async function goToBilliingPortal(){
const functionRef = app
.functions('us-central1')
.httpsCallable('ext-firestore-stripe-subscriptions-createPortalLink');
const {data} = await functionRef({returnUrl : window.location.origin});
window.location.assign(data.url);
};
is there a way to hide the 99.99 plan until the trial is up?
You'll need to keep track of the trial status yourself and check it when generating Customer Portal links. While trialing, if you do not wish to allow the customer to change to another plan you need to create another Portal Configuration which disabled subscription updates (ref).
During the trial you'd use this configuration when creating portal links (ref). After the trial you can use another configuration when allows for changes.

Why am I unable to send the charge to Stripe and my Strapi.js backend using a try/catch in my React frontend?

I am trying to send a charge to stripe. I have a charge set up in my Strapi.js backend as well as a new order being created. I have created a function in my react frontend to create an entry to my 'orders' content type in strapi but it seems as though nothing in the function's try/catch is working, it is not even logging an error.
I've attempted to make change some variables here and there, but im honestly a little overwhelmed because this is the first time im using these technologies and I am somewhat of a beginner. I was somewhat watching a video for guidance through some things but this is where I faced issues. I am bringing in the script tag in the index.html file as well. I am using strapi sdk.
Here is what the create Orders function on the strapi backend looks like(stripe is being brought in at top of page using secret key):
create: async (ctx) => {
const { address, city, products, amount, token } = ctx.request.body;
// Stripe Charge
const charge = await stripe.charges.create({
amount: amount * 100,
currency: 'usd',
description: `Order ${new Date(Date.now())}`,
source: token
});
const order = await strapi.services.orders.add({
address,
city,
products,
amount,
});
return order;
}
Here is my submit function in react frontend checkout.js file
handleOrder = async () => {
const { checkOutItems, city, address } = this.state;
let token;
const amount = calculateTotalAmount(checkOutItems);
// console.log('working')
try {
// create token
const response = await this.props.stripe.createToken();
token = response.token.id;
await strapi.createEntry('order', {
address,
city,
products: checkOutItems,
amount,
token
});
} catch (error) {
console.log(error)
}
}
Well I am expecting that when i fill out the form as well as the chain of '4242' for stripe card element on the page, the charge will be sent and i can go to my stripe dashboard and see the charge, and also be able to go to my strapi admin dashboard and go to orders and see a new order created.
As of now, none of this happens. I fill the information, click submit, the form resets and then nothing. No error is logged, no console.logs within the try catch will work.

How to delete user with Vue.js Firebase UID

I am attempting to implement a function in my Vue.js Firebase app that deletes/removes users by UID. The app is set up to enable registration of users in Firebase authentication via email and password. Once logged in, the user should be able to click delete in order to remove his/her email and password from Firebase authentication, as well as user data. So far I have the following for the delete function:
async deleteProfile () {
let ref = db.collection('users')
let user = await ref.where('user_id', '==',firebase.auth().currentUser.uid).get()
user.delete()
}
...but I am getting user.delete() is not a function. How can I set up this function to delete the user in authentication and database? Thanks!
UPDATED FUNCTION
async deleteProfile () {
let ref = db.collection('users')
let user = await ref.where('user_id', '==', firebase.auth().currentUser.uid).get()
await user.ref.delete()
await firebase.auth().currentUser.delete()
}
In your code, user is a DocumentSnapshot type object. If you want to delete the document, you can use user.ref.delete(). It returns a promise, so you will need to await it.
Deleting a document will not also delete a user account in Firebase Authentication. If you want to delete the user account, you will have to use the Firebase Authentication API for that. firebase.auth().currentUser.delete().
try this
<button class="..." #click="deleteProfile(currentUser.uid)">Delete</button>
and
methods: {
async deleteProfile(dataId) {
fireDb.collection("yourCollection").doc(dataId).delete()
.then(() => {
alert('Deleted')
})
}
}
Building off Doug Stevenson's answer, this is the function that ultimately worked.
async deleteProfile (user) {
await db.collection("users").doc(user).delete()
await firebase.auth().currentUser.delete()
}
await db.collection("users").doc(user).delete() accepts "user" as an argument from the click event in the DOM, in order to target the doc of the specified user in the database (I don't know why I didn't think of that sooner!) await firebase.auth().currentUser.delete() removes currentUser from firebase authorization.

Categories