Closed ComputerDen closed 1 year ago
sorry im an idiot forgot to start the stripe webhook again
You do require the service role key for managing Stripe customer IDs. You can't use RLS to secure this as you can't allow the user to insert/update their own customer ID. This is something that you need to do in a secure server-side environment with a service role key. You need that secure server-side environment anyway for interacting with the Stripe API.
You do require the service role key for managing Stripe customer IDs. You can't use RLS to secure this as you can't allow the user to insert/update their own customer ID. This is something that you need to do in a secure server-side environment with a service role key. You need that secure server-side environment anyway for interacting with the Stripe API.
that makes sense thankyou, the way its currently being done with the setup through vercel. is that a secure enough environment, or should i be looking at setting up something different for the a live product? im just scared of having the service role key store anywhere and had hoped to not need it
@ComputerDen by not prefixing the env var with NEXT_PUBLIC
you can be assured that nextjs will not expose your secret API keys client side. This is why you never use that prefix for secret keys, e.g. see https://github.com/vercel/nextjs-subscription-payments/blob/main/.env.local.example#L4
And the nextjs docs: https://nextjs.org/docs/basic-features/environment-variables#exposing-environment-variables-to-the-browser
Hey, Im trying to set this up so that i dont have to use the service role key, i beleieve i have the rls set up properly(i get no errors) and the supabase client swapped to the regular one in the supabase-admin.ts file i am running it localy, is that an issue?
it lets me go through the process of adding my card and then returns me to the page but it does not insert a new customer or any of the rest of the functions, it does add the details into stripe but nothing on the other end. no errors i can track. i had to change the createOrRetrieveCustomer so that i could use the rls to can anyone point me in the right direction?
`import { supabaseClient, User } from '@supabase/auth-helpers-nextjs'; import { stripe } from './stripe'; import { toDateTime } from './helpers'; import { Customer, UserDetails, Price, Product } from 'types'; import Stripe from 'stripe';
export const supabase = supabaseClient;
const upsertProductRecord = async (product: Stripe.Product) => { const productData: Product = { id: product.id, active: product.active, name: product.name, description: product.description ?? undefined, image: product.images?.[0] ?? null, metadata: product.metadata };
const { error } = await supabase .from('products')
.upsert([productData]);
if (error) throw error;
console.log(
Product inserted/updated: ${product.id}
); };const upsertPriceRecord = async (price: Stripe.Price) => { const priceData: Price = { id: price.id, product_id: typeof price.product === 'string' ? price.product : '', active: price.active, currency: price.currency, description: price.nickname ?? undefined, type: price.type, unit_amount: price.unit_amount ?? undefined, interval: price.recurring?.interval, interval_count: price.recurring?.interval_count, trial_period_days: price.recurring?.trial_period_days, metadata: price.metadata };
const { error } = await supabase .from('prices')
.upsert([priceData]);
if (error) throw error;
console.log(
Price inserted/updated: ${price.id}
); };const createOrRetrieveCustomer = async ({ email, uuid }: { email: string; uuid: string; }) => { let { data, error } = await supabase .from('customers') .select('stripe_customer_id') if (error) { // No customer record found, let's create one. console.log(error); const customerData: { metadata: { supabaseUUID: string }; email?: string } = { metadata: { supabaseUUID: uuid } }; if (email) customerData.email = email; const customer = await stripe.customers.create(customerData); // Now insert the customer ID into our Supabase mapping table. const { error: supabaseError } = await supabase .from('customers') .insert([{ id: uuid, stripe_customer_id: customer.id }]); if (supabaseError) {console.log(supabaseError); throw supabaseError;} console.log(
New customer created and inserted for ${uuid}.
); return customer.id; } if (data) return data; };/**
const manageSubscriptionStatusChange = async ( subscriptionId: string, customerId: string, createAction = false ) => { // Get customer's UUID from mapping table. const { data: customerData, error: noCustomerError } = await supabase .from('customers')
.select('id')
.eq('stripe_customer_id', customerId)
.single();
if (noCustomerError) throw noCustomerError;
const { id: uuid } = customerData || {};
const subscription = await stripe.subscriptions.retrieve(subscriptionId, { expand: ['default_payment_method'] }); // Upsert the latest status of the subscription object. const subscriptionData = { id: subscription.id, user_id: uuid, metadata: subscription.metadata, status: subscription.status, price_id: subscription.items.data[0].price.id, //TODO check quantity on subscription // @ts-ignore quantity: subscription.quantity, cancel_at_period_end: subscription.cancel_at_period_end, cancel_at: subscription.cancel_at ? toDateTime(subscription.cancel_at) : null, canceled_at: subscription.canceled_at ? toDateTime(subscription.canceled_at) : null, current_period_start: toDateTime(subscription.current_period_start), current_period_end: toDateTime(subscription.current_period_end), created: toDateTime(subscription.created), ended_at: subscription.ended_at ? toDateTime(subscription.ended_at) : null, trial_start: subscription.trial_start ? toDateTime(subscription.trial_start) : null, trial_end: subscription.trial_end ? toDateTime(subscription.trial_end) : null };
const { error } = await supabase .from('subscriptions') .upsert([subscriptionData]); if (error) throw error; console.log(
Inserted/updated subscription [${subscription.id}] for user [${uuid}]
);// For a new subscription copy the billing details to the customer object. // NOTE: This is a costly operation and should happen at the very end. if (createAction && subscription.default_payment_method && uuid) //@ts-ignore await copyBillingDetailsToCustomer( uuid, subscription.default_payment_method as Stripe.PaymentMethod ); };
export { upsertProductRecord, upsertPriceRecord, createOrRetrieveCustomer, manageSubscriptionStatusChange }; `