#paulc7053_api

1 messages ยท Page 1 of 1 (latest)

solid jungleBOT
#

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

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

molten ridgeBOT
#

Below are links to other discussions we've had with you in the past week in case you want to review that information. If your question is related to one of these previous discussions, please provide a comprehensive summary of the current state and what you need help with now. We help many users simultaneously, so a summary allows us to resolve your issue as soon as possible.

clever basalt
#

hi! there's some differences yes. What error did you get?

valid panther
#

Although the difference is that the ECE docs are for a normal payment

clever basalt
#

yeah the Billing docs are written for the use case where you use the PaymentElement and create the Subscription object when the page loads

#

ultimately it should work but requires a bit of manual work connecting the docs together

valid panther
#

So I only need to pass the elements, and the return url to an ECE subscription? (no subscriptionId, customerId, client_secret)?

clever basalt
#

well like for example the way it works is in the part of the ECE guide where it says

/ Create the PaymentIntent and obtain clientSecret
const res = await fetch('/create-intent', {

what you do at that point instead is call your "create Subscription" backend that creates a Subscription with default_incomplete and returns back the subscription.latest_invoice.payment_intent.client_secret (https://docs.stripe.com/billing/subscriptions/build-subscriptions?ui=elements#create-subscription) and that's what you use for the confirmPayment call.

valid panther
#

yes, but I don't see it passed anywhere

clever basalt
clever basalt
valid panther
#

the client secret obtained avter creating the subscription

#

I only see this const options = { clientSecret: '{{CLIENT_SECRET}}', // Fully customizable with appearance API. appearance: {/*...*/}, }; but it obviously refers to the PK key, right?

valid panther
#

This is my code now :`const onConfirm = async (data) => {
if (!stripe) {
return;
};

    const { error: submitError } = await elements.submit();
    if (submitError) {
        // setErrorMessage(submitError.message);
        return;
    };

    // create the customer
    const stripeCustomerIdRes = await fetch('/stripe/findOrCreateCustomer', {
        method: 'post',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            email: email ? email : 'test@test.com',
        }),
    });
    const stripeCustomerId = await stripeCustomerIdRes.json();
    // create the subscription
    const subscriptionRes = await fetch('/stripe/createSubscription', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            priceId: priceId,
            customerId: stripeCustomerId,
        }),
    });
    const { error } = await stripe.confirmPayment({
        elements,
        // clientSecret,
        confirmParams: {
            return_url: `${process.env.NEXT_PUBLIC_HOST}/payment-successful`,
        },
    });........}`
clever basalt
valid panther
#

Yep, that's why I didn;t think it was that

clever basalt
valid panther
#

I'm talking about passing it to the confirmPayment

clever basalt
#

sure

#

that is what I addressed above

#

well like for example the way it works is in the part of the ECE guide where it says
/ Create the PaymentIntent and obtain clientSecret
const res = await fetch('/create-intent', {

what you do at that point instead is call your "create Subscription" backend that creates a Subscription with default_incomplete and returns back the subscription.latest_invoice.payment_intent.client_secret (https://docs.stripe.com/billing/subscriptions/build-subscriptions?ui=elements#create-subscription) and that's what you use for the confirmPayment call

valid panther
#

okay, so I do pass the client secret from the subscription creation to the confirmPayment method

#

because in the docs it is not passed

#

(normal subscription docs)

clever basalt
#

yeah like I said you have to stitch the docs together, there is no one ECE+Subscription guide

clever basalt
#

but you should be able to do it the other way and create the Subscription on demand when the ECE needs it instead, yep

valid panther
#

got it! Also, may I ask where do I get the paymentMethodId?

clever basalt
#

could you expand on that? when you do need it, what context etc

valid panther
#

and wether it can be passed to the confirmPayment method

#

I want to store it for upgreades/downgrades

clever basalt
#

it will be saved to the Customer object involved in the Subscription automatically if it's used to confirm that subscription.latest_invoice.payment_intent

valid panther
#

Iv I understand correctly, this would be appropriate? const subscription = await stripe.subscriptions.create({ customer: stripeCustomerId, items: [{ price: priceId, }], payment_behavior: 'default_incomplete', payment_settings: { save_default_payment_method: 'on_subscription' }, expand: ['latest_invoice.payment_intent'], });

#

Ah okay, so when upgrading/downgrading I just pass the customerId to some method? Do I ned to store anything else besides the stripe customer id?

clever basalt
valid panther
#

sure

clever basalt
valid panther
# clever basalt let's take it one step a time I think and just get the subscription created/acti...

I thought this is everything, am I wrong? `const { error: submitError } = await elements.submit();
if (submitError) {
// setErrorMessage(submitError.message);
return;
};

    // create the customer
    const stripeCustomerIdRes = await fetch('/stripe/findOrCreateCustomer', {
        method: 'post',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            email: email ? email : 'test@test.com',
        }),
    });
    const stripeCustomerId = await stripeCustomerIdRes.json();
    // create the subscription
    const subscriptionRes = await fetch('/stripe/createSubscription', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            priceId: priceId,
            customerId: stripeCustomerId,
        }),
    });
    const clientSecret = (await subscriptionRes.json()).clientSecret;

    // confirm the payment
    const { error } = await stripe.confirmPayment({
        elements,
        clientSecret,
        confirmParams: {
            return_url: `${process.env.NEXT_PUBLIC_HOST}/payment-successful`,
        },
    });`
clever basalt
#

seems sensible, what happens when you try it?

valid panther
#

Can I use the 4242** credit card with GPay to test it?

#

I was just trying to understand it before testing it, but I'll do it rn

clever basalt
#

you can't add Stripe test card to Google Pay really, you generally just test on your normal browser with your real cards and logged into your Google account(they're not actually charged in test mode)

#

sorry I assumed you had the ECE at least showing and with wallets enabled in your browser, not sure how far in the journey you are

valid panther
#

I got the buttons to show

#

No worries, I'll be trying to set it up , 5 mins please

velvet sage
#

Hi there ๐Ÿ‘‹ I'm jumping in as my teammate needs to step away soon. I'll work on catching up on context while you test that.

valid panther
#

Hey! Sure

#

almost there

#

Hello?

velvet sage
#

No, you can't add Stripe test cards to non-Stripe systems, they aren't valid cards to providers like Google. As my teammate mentioned earlier, you typically use your real cards in Google Pay which are swapped for a test card behind the scenes when working in testmode.

valid panther
#

Back to the subsription upgrade/downgrade question: do I only need the cstomerId to do that (without showing the checkout page again)?

#

More precisely, I can retrieve the subs like this const subscriptions = await stripe.subscriptions.list({ customer: '{{CUSTOMER_ID}}', });, but in the expected output, I don;t see anything with sub_, whereas the .update is somethis like const subscription = await stripe.subscriptions.update( 'sub_xxxxxxxxx', { items: [ { id: '{{SUB_ITEM_ID}}', price: '{{NEW_PRICE_ID}}', }, ], } );

velvet sage
velvet sage
valid panther
#

{ "object": "list", "url": "/v1/subscriptions", "has_more": false, "data": [ { "id": "su_1NXPiE2eZvKYlo2COk9fohqA", "object": "subscription", "application": null, "application_fee_percent": null, "automatic_tax": { "enabled": false }, "items": { "object": "list", "data": [ { "id": "si_OK3pbS1dvdQYJP", "object": "subscription_item", "billing_thresholds": null, "created": 1690208774, "metadata": {}, "price": { "id": "price_1NOhvg2eZvKYlo2CqkpQDVRT", "object": "price" } } ] } } ] }

velvet sage
#

If you make a request to list Subscriptions for a Customer, the expected output is a list of Subscription objects if any exist.

valid panther
#

and the subsription id is the one with sub_, right?

#

Okay, so that's all I need to store in order to upgrade/downgrade the subscription? Because I thought your colleague said I only need the customerId?

velvet sage
#

Wasn't that when you were asking about retrieving a Payment Method?

valid panther
#

Hm, could be

#

So just to double check, storing this subscription's id const subscription = await stripe.subscriptions.create({ customer: stripeCustomerId, items: [{ price: priceId, }], payment_behavior: 'default_incomplete', payment_settings: { save_default_payment_method: 'on_subscription' }, expand: ['latest_invoice.payment_intent'], }); is the only thing I will need in the future in order to upgrade/downgrade a customer without asking for payment details again

velvet sage
#

Seems right

valid panther
#

Got it, thanks!

velvet sage
#

But let me know if your testing shows otherwise.

valid panther
#

I'll test it, but I'm not sure how long it'll take (need to have an SSL domain)

#

will have to dump it all in a codespace, so will take a bit of time!

#

Thanks a lot for your time, if there are any issues I'll open a new thread!

velvet sage
#

Any time!