#juice-subscription-clientsecret
1 messages · Page 1 of 1 (latest)
Hi there
Yep tell me more about what is going on
Are you seeing a particular error?
hey, there is no error i think i implemented the workflow wrong im not too sure
my objective is for new users to sign up for a subscription
and then collect their information when they sign up but i think what its doing is creating the customer and then attaching the subscription to them instead of asking for their payment information
const { email = `test${Math.floor(Math.random() * 9999) + 1}@domain.com` } =
req.body;
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
apiVersion: '2020-08-27',
typescript: true,
});
let { plan } = req.body;
let { name } = req.body;
let sub_plan = '';
if (plan == 'Starter') {
sub_plan = 'price_1MmjhwAOi6IdtOdNWnMWqgkz';
} else if (plan == 'Premium') {
sub_plan = 'price_1MmjiDAOi6IdtOdNValIB02i';
} else {
sub_plan = 'price_1MmjhwAOi6IdtOdNWnMWqgkz';
}
const customer = await stripe.customers.create({
email,
name,
});
const ephemeralKey = await stripe.ephemeralKeys.create(
{ customer: customer.id },
{ apiVersion: '2020-08-27' }
);
const PRICE_ID = sub_plan;
const subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [{ price: PRICE_ID }],
metadata: { email, name, plan },
trial_period_days: 3,
});
if (typeof subscription.pending_setup_intent === 'string') {
const setupIntent = await stripe.setupIntents.retrieve(
subscription.pending_setup_intent
);
return res.json({
setupIntent: setupIntent.client_secret,
ephemeralKey: ephemeralKey.secret,
customer: customer.id,
});
} else {
throw new Error(
'Expected response type string, but received: ' +
typeof subscription.pending_setup_intent
);
}
});```
this is the server side function that i use, i added trial days because that prompted the user to enter their credit card information but i also believe thats the wrong way
initialisePaymentSheet();
}, []);
const initialisePaymentSheet = async () => {
const { setupIntent, ephemeralKey, customer } =
await fetchPaymentSheetParams();
const { error } = await initPaymentSheet({
customerId: customer,
customerEphemeralKeySecret: ephemeralKey,
setupIntentClientSecret: setupIntent,
merchantDisplayName: 'KOLO',
allowsDelayedPaymentMethods: true,
returnURL: 'https://kolo-server.herokuapp.com/paymentsuccess',
});
if (error) {
Alert.alert(`Error code: ${error.code}`, error.message);
} else {
setReady(true);
}
};
const fetchPaymentSheetParams = async () => {
const response = await fetch(
'https://kolo-server.herokuapp.com/payment-sheet-subscription',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: formData.email,
name: formData.name,
plan: formData.subscriptionPackage,
}),
}
);
const { setupIntent, ephemeralKey, customer } = await response.json();
return {
setupIntent,
ephemeralKey,
customer,
};
};``` this is the react native part
Okay let's back up
Before looking at the code
You want to take Subscription payments using Payment Sheet, correct?
Is there going to be a trial flow or no?
no trial
they press checkout, fill in their credit card information and get charged every month, thats all
Okay then yeah you don't want that nor to deal with SetupIntents at all
hmm then i followed the wrong thing i guess
When the customer presses your checkout button, you call your backend and create a Subscription
Then you pass the latest_invoice.payment_intent.client_secret to your front end
Along with the Ephemeral key and Customer ID
Then you init PaymentSheet with those 3 things from your backend
is there documentation with examples for this? i think i have an idea but i just want to make sure i do it right
so i init the payment sheet after i create the subscription and get those values back from the backend?
It is basically just the flow here: https://stripe.com/docs/payments/save-during-payment except that instead of creating the PaymentIntent directly, you create a Subscription which will then create an Invoice and that Invoice will have an associated PaymentIntent
Yes
let me try to see
Yep try it out and let me know if you run into issues
sorry i have a question, how do i init the payment sheet with the latest invoice, i cant seem to find it on the docs? And do i have to return anything from the subscription i created? this is the code so far ``` const customer = await stripe.customers.create({
email,
name,
});
const ephemeralKey = await stripe.ephemeralKeys.create(
{ customer: customer.id },
{ apiVersion: '2020-08-27' }
);
const PRICE_ID = sub_plan;
const subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [{ price: PRICE_ID }],
metadata: { email, name, plan },
});
return res.json({
latest_invoice: latest_invoice.paymentIntent.client_secret,
ephemeralKey: ephemeralKey.secret,
customer: customer.id,
});
});```
const { latest_invoice, ephemeralKey, customer } =
await fetchPaymentSheetParams();
const { error } = await initPaymentSheet({
customerId: customer,
customerEphemeralKeySecret: ephemeralKey,
merchantDisplayName: 'KOLO',
allowsDelayedPaymentMethods: true,
returnURL: 'https://kolo-server.herokuapp.com/paymentsuccess',
});
if (error) {
Alert.alert(`Error code: ${error.code}`, error.message);
} else {
setReady(true);
}
};
const fetchPaymentSheetParams = async () => {
const response = await fetch(
'https://kolo-server.herokuapp.com/payment-sheet-subscription',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: formData.email,
name: formData.name,
plan: formData.subscriptionPackage,
}),
}
);
const { latest_invoice, ephemeralKey, customer } = await response.json();
return {
latest_invoice,
ephemeralKey,
customer,
};
};```
I appreciate the help, im still learning how to make it work with react native
Should be latest_invoice.payment_intent.client_secret on your backend
Also I forgot to add that you need to expand latest_invoice.payment_intent to access this
That has an example of what your backend code should look like
ok one second i will do it
im getting an error that says i must provide a paymentIntentClientSecret, i did pass it in here
is it a different value?
That looks right. You are seeing that error on your frontend though, right?
yup
Okay have you logged out the clientsecret after receiving it from your backend?
do you mean log it to console?
one second i forgot to change to a test product, it might be that
Yes, you should add logs throughout your code and they will show up in Metro for your frontend
i see i get undefined for the clientsecret
Okay so now the next step is to debug why! Does your Subscription have a latest_invoice? Does that one have a PaymentIntent? etc.
as the developer you can debug this in second by adding clear logs
juice-subscription-clientsecret
yea im adding logs give me a second ill try to fix it
customer: customer.id,
items: [{ price: PRICE_ID }],
metadata: { email, name, plan },
});
``` this is your code, you never expanded anything, so you'll get `latest_invoice: 'in_123'` back. So there's no way to look at the underlying Invoice's PaymentIntent
You need to carefully read our docs on our Expand feature <https://stripe.com/docs/expand> first and then properly expand the object(s) your code needs
ah gotcha, so yeah my guess is either you didn't expand like you thought, or maybe the first Invoice is below the minimum and so there would be no PaymentIntent
Make sure you are using a Price high enough that there would be a payment, see https://stripe.com/docs/currencies#minimum-and-maximum-charge-amounts
yea its 10 euros, should be above the minimum, maybe i didnt expand properly, im going through the expand docs
i see what it could be, the customerId was a constant i had before, i needed to change that to customer.id
let me try to run it again
it works 😄 thank you very much
it did not set the credit card as default though, is that going to be a problem when it tries to withdraw the payment or does it go for any available payment method on the customers profile?
i thought this option auto set it as default
yes that option should do the right thing
Do you have a clear example I can look at?
i see here that its going to charge it
i guess it just doesnt show up as default on the stripe dashboard
Sorry it's just a picture, I have no idea what you need from me yet
If you can provide an exact subscription id though I can look
i think its working, i thought the payment method would be listed as default on the costumer thats all, the tests are all good its working, thank you for the help today
i appreciate it
have a good day
Ah so the PM is the default on the Subscription with that feature, not the Customer
We want to support making it the default on the Customer in the future though
i see, thats great to know thanks