#nftvon_api

1 messages Β· Page 1 of 1 (latest)

fiery torrentBOT
#

πŸ‘‹ 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.

leaden linden
#

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

silent cosmos
#

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

leaden linden
#

Yes. I am not getting any errors in the browser

silent cosmos
#

There should be warnings about eg, missing billing address or something of that sort

leaden linden
#

Nope nothing like that at all.

#

There is no credit card collected for no-cost.

silent cosmos
#

Does the same integration work for non-zero amount sessions?

leaden linden
#

yes it does.

silent cosmos
#

Can you share your code where you call confirm on the session?

#

Let me try to test this...

leaden linden
#

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.

silent cosmos
#

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

leaden linden
#

appreciate the help. i'm literally at complete brain dust now.

silent cosmos
#

Are you using Stripe.js basil, or the beta version of custom checkout?

leaden linden
#

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.

silent cosmos
#

That would be on your server side -- what about client side?

#

How do you load/init Stripe.js?

leaden linden
#

I use my env to init the client as well.

Also just tried with v1 and its exact same outocme.

#

Request ID: req_5SHFfXUCoNgbD3

silent cosmos
#

Can you show me the code for that?

leaden linden
#

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"
}
silent cosmos
#

Can you show the code you use to initialize stripe.js?

leaden linden
#

I am creating the checkout.session via a Server Function, not in the client..

silent cosmos
#

yes, but this error you're encountering is client cide validation in stripe js when you try to confirm

leaden linden
#
/**
 * 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,
  });
}```
silent cosmos
#

That's server side, seems reasonable

leaden linden
silent cosmos
#

And what is the equivalent client side?

leaden linden
#

/**
 * 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.

silent cosmos
#

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 /confirm request 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

leaden linden
#

πŸ™‚

silent cosmos
#

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

leaden linden
#
  1. correct
silent cosmos
#

You haven't shown me any client side Stripe.js code interacting with the checkout session

#

Only server code

leaden linden
#

its a big file. let me get it πŸ˜‰

silent cosmos
#

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()

leaden linden
#

yeah I removed the session.confirm() because it gives an error for the payment element not being mounted (which contradicts the docs)

silent cosmos
#

I removed the session.confirm()
... well then this session will never complete, right? You have to call confirm to complete the session

fiery torrentBOT
leaden linden
#

ok. this is really confusing.

  1. The docs say do not mount PaymentElement
  2. When I do not mount then and try to:
const checkout = useCheckout()
checkout.confirm()

I get payment or checkout element not mounted error

  1. It seems is no way to do checkout.confirm() without mounting the paymentElement

  2. 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.
silent cosmos
#

That's the error/bug we need to sort out πŸ™‚

#

But not calling confirm() is not the right answer

leaden linden
#

yep. its an oddy.

silent cosmos
#

So now we're back to, can you show me how you initialize stripe.js?

#

Are you using react, or html+js?

leaden linden
#
<CheckoutProvider
                stripe={stripePromise}
                options={{
                  fetchClientSecret: async () => {
                    console.log('πŸ” CheckoutProvider fetchClientSecret called');
                    return clientSecret;
                  },
                  elementsOptions: {
                    appearance: { theme: 'stripe' },
                  },
                }}
              >
#

via const stripePromise = loadStripe(publishableKey);

silent cosmos
#

Awesome, ty

#

and what version of stripe/stripe-js are you using?

leaden linden
#

"stripe": "18.3.0-beta.1",

#
    "@stripe/react-stripe-js": "^3.7.0",
    "@stripe/stripe-js": "^7.3.1",
silent cosmos
#

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.

leaden linden
#

oh sweet.

silent cosmos
#

So let's try to narrow down where your integration differs from mine

leaden linden
#

yeah react would not be the factor for sure.

silent cosmos
#

Ok, can you show me your checkout.confirm() call code now?

leaden linden
#

As I mentioned I removed it.

but I can add it back again.

#

Does you flow show a paymentElement?

silent cosmos
#

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

leaden linden
#

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.

  1. init stripe
  2. create session
  3. Checkout Provider
    .... ect.
#

And what you ckeckout session params looked like.

silent cosmos
leaden linden
#

then I can go away, tinker and post back once I get it working.

#

I hate taking up all your time πŸ€—

silent cosmos
#

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)
}
leaden linden
#

yeah. let me fiddle. and get it back to the paymentElment and confirm()

silent cosmos
#

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.

leaden linden
#

I got checkout.confirm error: Your card number is incomplete.

#

Session.total, good idea.

silent cosmos
#

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

leaden linden
#
total: 
amount: "$0.00"
minorUnitsAmount: 0
silent cosmos
#

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

leaden linden
#

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.
silent cosmos
#

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)

leaden linden
#
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>
  );
}
silent cosmos
#

I'll be honest, I'm stumped -- I'm also asking for some help internally from the team that builds this flow

leaden linden
#

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.

silent cosmos
#

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;
                  },
leaden linden
silent cosmos
#

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

leaden linden
#

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.

silent cosmos
#

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

fiery torrentBOT
#

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!
silent cosmos
#

Ah, you have server member DMs disabled (honestly, a good move). Can you please enable that temporarily?

leaden linden
#

yep let me enable

#

fire away

fiery torrentBOT
#

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!
silent cosmos
#

Hmm it still says no, did you get a message though?

leaden linden
#

try again. I enabled for all server but it was still disabled for this server. doh

fiery torrentBOT
#

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.
silent cosmos
#

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

leaden linden
#

Cool beans.

silent cosmos
#

Thanks for your patience and working on this with me -- we'll get it figured out!

#

Get some rest, and have a good weekend!

leaden linden
#

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.

silent cosmos
#

Good stuff -- we'll keep at it until we get you up and running πŸ™‚

leaden linden
#

Removed my domain don't want that to be in the public when this goes to read-only.

fiery torrentBOT