#kenny_code

1 messages ยท Page 1 of 1 (latest)

distant shaleBOT
#

๐Ÿ‘‹ 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/1344781092573679727

๐Ÿ“ Have more to share? Add more details, code, screenshots, videos, etc. below.

empty abyss
#
    // Prepare session options with proper typing
    const sessionOptions: Stripe.Checkout.SessionCreateParams = {
      ui_mode: "custom",
      line_items: lineItems.map((item) => ({
        price: item.price,
        quantity: item.quantity, // Already validated as a number by Zod
      })),
      mode: "payment",
      return_url:
        `${domain}/${teamSlug}/payments/return?session_id={CHECKOUT_SESSION_ID}`,
      automatic_tax: { enabled: false },
      invoice_creation: { enabled: true },
      payment_intent_data: {
        setup_future_usage: "off_session",
      },
    };

    // If we have an existing customer, use customer ID
    // Otherwise use customer_email for new customers
    if (billingStatus?.billing_customer_id) {
      sessionOptions.customer = billingStatus.billing_customer_id;
    } else {
      sessionOptions.customer_email = user.email;
    }

    const session = await stripeClient.checkout.sessions.create(sessionOptions);
#
"use client";
import { stripePromise } from "@/lib/stripe/client";
import { CheckoutProvider } from "@stripe/react-stripe-js";
import CheckoutForm from "./checkout-form";

export default function Checkout(props: {
    clientSecret: string;
    creditQuantity: number;
    amountTotal: number;
}) {
    return (
        <CheckoutProvider
            stripe={stripePromise}
            options={{
                clientSecret: props.clientSecret,
                elementsOptions: {
                    fonts: [{ cssSrc: "https://fonts.googleapis.com/css?family=Inter" }],
                    appearance: {
                        theme: "night",
                        variables: {
                            fontFamily: "Inter",
                            colorPrimary: "#EA580C",
                            colorBackground: "#09090B",
                            colorText: "white",
                        },
                    },
                },
            }}
        >
            <CheckoutForm
                creditQuantity={props.creditQuantity}
                amountTotal={props.amountTotal}
            />
        </CheckoutProvider>
    );
}
sage rover
#

Hello, we do have functionality for this, finding the doc

empty abyss
#

yes, i've tried that.

#

the payment method is saved as expected but isn't displayed

sage rover
#

If you retrieve the PaymentIntent in the API, what does it say for its allow_redisplay parameter

#

Also your example code would need to set saved_payment_method_options.allow_redisplay_filters which your example code does not have currently

empty abyss
#
    const sessionOptions: Stripe.Checkout.SessionCreateParams = {
      ui_mode: "custom",
      line_items: lineItems.map((item) => ({
        price: item.price,
        quantity: item.quantity,
      })),
      mode: "payment",
      return_url:
        `${domain}/${teamSlug}/payments/return?session_id={CHECKOUT_SESSION_ID}`,
      automatic_tax: { enabled: false },
      invoice_creation: { enabled: true },
      payment_intent_data: {
        setup_future_usage: "off_session",
      },
      saved_payment_method_options: {
        allow_redisplay_filters: ['always', 'limited', 'unspecified']
      }
    };
#

& the customer id is in fact passed in, just at a later step

#
    // If we have an existing customer, use customer ID
    // Otherwise use customer_email for new customers
    if (billingStatus?.billing_customer_id) {
      sessionOptions.customer = billingStatus.billing_customer_id;
    } else {
      sessionOptions.customer_email = user.email;
    }
#

i have confirmed that the correct customer id is being passed in

sage rover
#

Can you send the ID of the customer, payment method, and a checkout session that doesn't show the saved PM here? I am not immediately spotting anything in your code that would cause this

distant shaleBOT
sage rover
#

Also does this still happen if you turn on payment_method_save in saved_payment_method_options and run through another session to save a PM?

empty abyss
#

Yes

#

Yes, to both

chrome mortar
#

Hello! I'm taking over and catching up...

empty abyss
#

customer id: cus_RqsB4iPssFXjHm
payment method: pm_1QxARXB20I6m6e8n2pz2byqN

chrome mortar
#

Thanks! Looking...

empty abyss
#

checkout session id: cs_test_a1nir3IPMb9xLVva4RdhKMInLfAaDNqdJr77gPCWQl4Y7ZAGcCSj7C308t

empty abyss
chrome mortar
#

Ah, you're using the Custom Checkout public preview. I'm not sure this is supported with that approach. Let me see if I can find confirmation for that...

empty abyss
#

how do I set it to always?

chrome mortar
#

Also note that you'll need to implement that other code at the link I shared above.

#

This isn't built-in to an existing UI component.

empty abyss
#

thanks i'll try it out

#

gotcha, so I just need to style this now?

chrome mortar
#

Yep!

#

You'll also probably want to do something like, when that saved payment method is selected, hide the Payment Element.

#

But the basics are working now, so you can do whatever works best for your payment form from here.

empty abyss
#

Super, thanks for your help

chrome mortar
#

No problem! All credit to @sage rover, actually, who found that docs link behind the scenes when we were talking about this. ๐Ÿ™‚

empty abyss
#

Thanks @sage rover !

#

One last question before I lose you guys. I only want the user to have one payment method active at a time. How do you suggest that I handle this upsert operation so that a customer never has more than one payment method?

#

Or is there a way to set the used payment method to have a "default" tag that I can access from the backend so I don't actually have to remove any payment methods.

#

I think the latter would be even better

chrome mortar
#

You can do either.

#

For the latter, you can add metadata to either the Customer or Payment Method (or both) to determine a default (or anything else you want).

#

There's also a third option: Customers have an invoice_settings.default_payment_method property where you can set the current default Payment Method for Invoices for that Customer. You can decide to use that as the default for your custom integration as well.

empty abyss
#

yes, I think the third option is the best

#

well thanks for all of the help, I really appreciate it