#nftvon_api
1 messages Β· Page 1 of 1 (latest)
π Welcome to your new thread!
β²οΈ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.
β±οΈ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.
π This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1380540305383886930
π Have more to share? Add more details, code, screenshots, videos, etc. below.
Example request:
{
"client_reference_id": "90a5424c-f0ac-4d68-9052-d6538f8caecf",
"customer_account": "acct_1RWyziQFu2SLohjx",
"invoice_creation": {
"enabled": "true",
"invoice_data": {
"metadata": {
"community_id": "c43d1ae7-8ec5-492e-a3d7-d69db6047f92",
"purchase_type": "community_membership",
"user_id": "b73eb03e-fb7a-424d-84ff-18e2791ce0b4"
}
}
},
"line_items": {
"0": {
"price": "price_1RWz0F4fQOsUtt8kz1oxc6KD",
"quantity": "1"
}
},
"metadata": {
"community_id": "c43d1ae7-8ec5-492e-a3d7-d69db6047f92",
"community_slug": "knitting-and-crocheting",
"purchase_type": "community_membership",
"user_id": "b73eb03e-fb7a-424d-84ff-18e2791ce0b4"
},
"mode": "payment",
"return_url": "http://localhost:3000//knitting-and-crocheting/about?session_id={CHECKOUT_SESSION_ID}",
"ui_mode": "custom"
}
and the price is set to one-time $0
hey there, have you checked for browser console errors/warnings?
I'm not seeing any confirm attempts on the session, so i suspect Stripe.js is validating your session localy, finding something is missing, and not making the confirm request
Yes. I am not getting any errors in the browser
There should be warnings about eg, missing billing address or something of that sort
Nope nothing like that at all.
In the docs it says to not mount the payment element.
Caution
When rendering no-cost sessions, make sure that Payment Element and Express Checkout Element arenβt mounted on the page.
https://docs.stripe.com/payments/checkout/no-cost-orders?payment-ui=embedded-components
There is no credit card collected for no-cost.
Does the same integration work for non-zero amount sessions?
yes it does.
Can you share your code where you call confirm on the session?
Let me try to test this...
Well thats the catch, when I try to useCheckout.confirm() it says there is not mounted payment element, but in the docs it specifically says do not mount them.
Super confusing, been fighting with this for at least 8 hours. lol.
the docs don't clearly explain about the session completion.
when I try to useCheckout.confirm() it says there is not mounted payment element, but in the docs it specifically says do not mount them
oh, thats not good.
(Sorry, still trying to get my example running here)
But yea, thats the kind of error i was expecting
appreciate the help. i'm literally at complete brain dust now.
Are you using Stripe.js basil, or the beta version of custom checkout?
Using latest preview for Accounts v2, but I can easily change to v1 and test it with customers.
STRIPE_API_VERSION_V1='2025-05-28.basil'
STRIPE_API_VERSION_V2='2025-05-28.preview' <-- this is my default.
That would be on your server side -- what about client side?
How do you load/init Stripe.js?
I use my env to init the client as well.
Also just tried with v1 and its exact same outocme.
Request ID: req_5SHFfXUCoNgbD3
Can you show me the code for that?
the request is this:
{
"client_reference_id": "53e8d4d2-cbc4-47f3-8986-f1e9235dc79a",
"customer": "cus_SRsl2eWvYAczuo",
"invoice_creation": {
"enabled": "true",
"invoice_data": {
"metadata": {
"community_id": "c43d1ae7-8ec5-492e-a3d7-d69db6047f92",
"purchase_type": "community_membership",
"user_id": "b73eb03e-fb7a-424d-84ff-18e2791ce0b4"
}
}
},
"line_items": {
"0": {
"price": "price_1RWz0F4fQOsUtt8kz1oxc6KD",
"quantity": "1"
}
},
"metadata": {
"community_id": "c43d1ae7-8ec5-492e-a3d7-d69db6047f92",
"community_slug": "knitting-and-crocheting",
"purchase_type": "community_membership",
"user_id": "b73eb03e-fb7a-424d-84ff-18e2791ce0b4"
},
"mode": "payment",
"return_url": "http://localhost:3000//knitting-and-crocheting/about?session_id={CHECKOUT_SESSION_ID}",
"ui_mode": "custom"
}
Price is :
{
"id": "price_1RWz0F4fQOsUtt8kz1oxc6KD",
"object": "price",
"active": true,
"billing_scheme": "per_unit",
"created": 1749211447,
"currency": "usd",
"custom_unit_amount": null,
"livemode": false,
"lookup_key": null,
"metadata": {
"seller_type": "community"
},
"nickname": null,
"product": "prod_SRslZQ4xBLKP7I",
"recurring": null,
"tax_behavior": "unspecified",
"tiers_mode": null,
"transform_quantity": null,
"type": "one_time",
"unit_amount": 0,
"unit_amount_decimal": "0"
}
Can you show the code you use to initialize stripe.js?
I am creating the checkout.session via a Server Function, not in the client..
yes, but this error you're encountering is client cide validation in stripe js when you try to confirm
/**
* Creates a Stripe SDK instance synchronously
* This is used in compatibility functions where we can't use async/await
* @param versionType - The API version type to use (defaults to 'V1')
* @returns A Stripe instance
*/
export function createStripeSdk(versionType: StripeApiVersionType = 'V1') {
// We're using the static import for Stripe in synchronous contexts
// We're not validating the env vars here because this is a compatibility function
// The original code didn't validate them either in the sync version
const secretKey = process.env.STRIPE_SECRET_KEY;
if (!secretKey) {
throw new Error('STRIPE_SECRET_KEY is required');
}
// Get the API version from environment variables
const apiVersion = getApiVersionFromEnv(versionType);
// Throw error if the requested API version is not available
if (!apiVersion) {
const envVarName = `STRIPE_API_VERSION_${versionType}`;
throw new Error(`Missing environment variable: ${envVarName}`);
}
// Type assertion to handle beta version export structure changes
const StripeClass = Stripe as StripeConstructor;
return new StripeClass(secretKey, {
apiVersion,
});
}```
That's server side, seems reasonable
I am not getting that error any more as I am not mounting the paymentElement. Not it just does the request, and sits there. never completing.
And what is the equivalent client side?
/**
* Creates a Stripe SDK instance
* @param versionType - The API version type to use (defaults to 'V1')
* @returns A Stripe instance
*/
export async function createStripeClient(
versionType: StripeApiVersionType = 'V1',
) {
// Get the API version from environment variables
const apiVersion = getApiVersionFromEnv(versionType);
// Throw error if the requested API version is not available
if (!apiVersion) {
const envVarName = `STRIPE_API_VERSION_${versionType}`;
throw new Error(`Missing environment variable: ${envVarName}`);
}
// Parse the environment variables and validate them (only validate what we need)
const stripeServerEnv = StripeServerEnvSchema.parse({
secretKey: process.env.STRIPE_SECRET_KEY,
webhooksSecret: process.env.STRIPE_WEBHOOK_SECRET,
// Only include the API versions that are actually set
...(process.env.STRIPE_API_VERSION_V1 && {
apiVersionV1: process.env.STRIPE_API_VERSION_V1,
}),
...(process.env.STRIPE_API_VERSION_V1_BETA && {
apiVersionV1Beta: process.env.STRIPE_API_VERSION_V1_BETA,
}),
...(process.env.STRIPE_API_VERSION_V2 && {
apiVersionV2: process.env.STRIPE_API_VERSION_V2,
}),
});
// Type assertion to handle beta version export structure changes
const StripeClass = Stripe as StripeConstructor;
return new StripeClass(stripeServerEnv.secretKey, {
apiVersion,
});
}
I am using stripe everywhere in my app. only the no-cost thing is causing an issue.
I am not getting that error any more as I am not mounting the paymentElement. Not it just does the request, and sits there. never completing.
1/ I thought the error you share was saying a payment element was missing, indicating the validation is trying to find one but failing. Did I get that backward?
when I try to useCheckout.confirm() it says there is not mounted payment element, but in the docs it specifically says do not mount them
2/ Which request is hanging? Are you seeing a/confirmrequest in your browser dev tools network tab?
Not it just does the request, and sits there. never completing.
Ok taking a breath and a step back
π
There are two pieces here:
1/ Creating the session on your server with your secret key, that seems to be working fine
2/ Rendering a UI client side with Stripe.js and confirming the checkout session, that seems to be what is not working
- correct
You haven't shown me any client side Stripe.js code interacting with the checkout session
Only server code
its a big file. let me get it π
I'm asking for the client-side stripe.js initialization code, and also the checkout session confirm call
just snippets around those lines is all i need
where you call Stripe() or initStripe() etc, and where you call session.confirm()
yeah I removed the session.confirm() because it gives an error for the payment element not being mounted (which contradicts the docs)
I removed the session.confirm()
... well then this session will never complete, right? You have to call confirm to complete the session
ok. this is really confusing.
- The docs say do not mount PaymentElement
- When I do not mount then and try to:
const checkout = useCheckout()
checkout.confirm()
I get payment or checkout element not mounted error
-
It seems is no way to do
checkout.confirm()without mounting the paymentElement -
When I do mount the paymentElement it asks for Credit card input. Which is also contradictory to the docs:
If the total amount is 0, Checkout doesnβt collect a payment method from the customer.
That's the error/bug we need to sort out π
But not calling confirm() is not the right answer
yep. its an oddy.
So now we're back to, can you show me how you initialize stripe.js?
Are you using react, or html+js?
<CheckoutProvider
stripe={stripePromise}
options={{
fetchClientSecret: async () => {
console.log('π CheckoutProvider fetchClientSecret called');
return clientSecret;
},
elementsOptions: {
appearance: { theme: 'stripe' },
},
}}
>
via const stripePromise = loadStripe(publishableKey);
"stripe": "18.3.0-beta.1",
"@stripe/react-stripe-js": "^3.7.0",
"@stripe/stripe-js": "^7.3.1",
Ok, thanks. I've been able to complete my no cost flow without errors, suggesting it does in fact work, though I am not using React. I consider it highly unlikely that React is a factor here, but not impossible.
oh sweet.
So let's try to narrow down where your integration differs from mine
yeah react would not be the factor for sure.
Ok, can you show me your checkout.confirm() call code now?
As I mentioned I removed it.
but I can add it back again.
Does you flow show a paymentElement?
In my testing, mounting the payment element or ECE are non blocking for zero cost sessions, so i think this is just a reminder to avoid confusing customer flows.
I can confirm whether or not i mount payment element
Any chance you could share your code and I can try and match the flow on my side.
Or just give me a quick rundown of the steps.
- init stripe
- create session
- Checkout Provider
.... ect.
And what you ckeckout session params looked like.
It's crude html + js, but you can see mounting PE here: https://glitch.com/edit/#!/asi-custom-checkout-basil?path=public%2Fclient.js%3A80%3A43
and confirming here: https://glitch.com/edit/#!/asi-custom-checkout-basil?path=public%2Fclient.js%3A147%3A3
then I can go away, tinker and post back once I get it working.
I hate taking up all your time π€
No problem at all, i want to figure out where this is falling over because the fact this is so hard suggest there's a missing error message somewhere that we need to improve
Can you try adding explicit checks on the error result:
const confirmResult = await checkout.confirm()
if (confirmResult.error) {
console.log("checkout.confirm error:", confirmResult.error.message)
}
yeah. let me fiddle. and get it back to the paymentElment and confirm()
Did you get to any error there? Is it still saying something about a payment element?
It might be useful to also log your session.total at the same time to ensure the session Stripe.js sees is in fact zero-cost like you're creating on the server, and not something else for some reason.
I got checkout.confirm error: Your card number is incomplete.
Session.total, good idea.
checkout.confirm error: Your card number is incomplete
this suggests to me a payment element is mounted
and the card form is open
let me see what happens if i expanded the card form too
total:
amount: "$0.00"
minorUnitsAmount: 0
for me having the payment element mounted & card form open, even a deliberate partial entry of a card number with validation showing in the element, does not block confirming the no-cost session
I think there's an important missing piece going on here
Something doesnt add up
Strange
Without PaymentElement mounted I get this:
at Hm (stripe.js:1:504053)
at e.<anonymous> (stripe.js:1:513347)
at e._handleMessage (stripe.js:1:70059)
at stripe.js:1:511275
With I get
checkout.confirm error: Your card number is incomplete.
Could not find a mounted element to create a payment method from.
this sounds like an unexpectred error shape
Can you share the checkout.confirm() code snippet please?
(that line plus any relevant nearby scope)
const FreeConfirmationStep = ({
handleCancel,
}: {
handleCancel: () => void;
}) => {
const checkout = useCheckout();
const handleConfirmFreeMembership = async () => {
console.log('π Confirm free membership');
const checkoutTotal = await checkout.total;
console.log('π Checkout total:', checkoutTotal);
const confirmResult = await checkout.confirm();
if (confirmResult.error) {
console.log('checkout.confirm error:', confirmResult.error.message);
}
};
return (
<div className="flex justify-end gap-3">
<PaymentElementsSection />
<Button
variant="outline"
onClick={handleCancel}
data-test="cancel-free-join"
>
<Trans i18nKey="common:cancel" />
</Button>
<Button
onClick={handleConfirmFreeMembership}
data-test="confirm-free-membership"
className="bg-green-600 hover:bg-green-700"
>
<Trans i18nKey="communities:joinFreeCommunityButton" />
</Button>
</div>
);
};
/**
* Simple wrapper for the Stripe PaymentElement.
* No props needed as the checkout context is provided by the parent.
*/
export function PaymentElementsSection() {
return (
<div className="py-4" data-test="stripe-payment-element-container">
<div className="mb-2 font-medium">
<Trans i18nKey="common:creditCard" />
</div>
<PaymentElement />
</div>
);
}
I'll be honest, I'm stumped -- I'm also asking for some help internally from the team that builds this flow
Me too.
I still can't seem to get it working. also the glitch you sent not sure it works either. The session is still open on glitch and asks for a credit card. Not expected behavior according to docs. And not what I want either.
I think I will just tackle this tomorrow without checkout sessions for no-cost orders.
I don't want to force my user to input a credit card for zero cost price.
Would have liked to use checkout sessions for both paid & free so its a unified flow and webhooks.
Sad becuase the docs say don't mount, but not mounting give error.
Out of curiosity, can you add a log of the client secret that you get for CheckoutProvider here:
fetchClientSecret: async () => {
console.log('π CheckoutProvider fetchClientSecret called');
return clientSecret;
},
A react example would be amazing. π
Let me check one moment
i wonder if there's a bug happening higher up producing confusing errors
in that context, I don't see where clientSecret is coming from, I'd expect it to be undefined
yeah I get the clientSecret
π ~ clientSecret: cs_test_a1btGxAHtkU0rzQaDPf7ofxJ6SYW8P5tiKdkpxAS0rJoXreqVPHcHhS6dk_secret_fid2cGd2ZndsdXFsamtQa2x0cGBrYHZ2QGtkZ2lgYSc%2FY2RpdmApJ3BsSGphYCc%2FJ2ZwdnFqaCd4JSUl
I create the checkoutSesson on the join modal loading useEffect via a server action and return the client secret.
Anyway. i am crashing. nearly 11pm here. been at this since 9am.
I know its time to crash when I start hitting backspace too ofter because of typos. LOL.
ok, just a sec
i'm going to have our bot send you a link to create a case for me & my team
that way i can keep digging on our side and keep the context we have here
Hello @leaden linden, we tried to send you a direct message, but couldn't
- π We would like to send you a message that has instructions on how to open a direct support case with our Developer Support team, in order to help you more effectively.
- Please enable direct messages from members of this Discord server (please see the instructions here) and let us know so we can try again!
Ah, you have server member DMs disabled (honestly, a good move). Can you please enable that temporarily?
Hello @leaden linden, we tried to send you a direct message, but couldn't
- π We would like to send you a message that has instructions on how to open a direct support case with our Developer Support team, in order to help you more effectively.
- Please enable direct messages from members of this Discord server (please see the instructions here) and let us know so we can try again!
Hmm it still says no, did you get a message though?
try again. I enabled for all server but it was still disabled for this server. doh
Hello @leaden linden, we have sent you a direct message, please check it at https://discord.com/channels/@me/1380571930930974892
- πThe message has instructions on how to open a direct support case with our Developer Support team, in order to help you more effectively.
there we go
Ok so clikc that link, it'll take you to our support site and you can submit the case and i'll pick it up
I'll try spinning up a React example myself this afternoon and follow up once i get some help from the team here too
Cool beans.
Thanks for your patience and working on this with me -- we'll get it figured out!
Get some rest, and have a good weekend!
totally. I am glad i reached out.
Little context of the project.
I am making a creator platform to build communities on and monetize their followers.
Good stuff -- we'll keep at it until we get you up and running π
Removed my domain don't want that to be in the public when this goes to read-only.