#syedhussain_code

1 messages ยท Page 1 of 1 (latest)

sonic basaltBOT
#

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

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

paper cosmos
#

๐Ÿ‘‹ happy to help

#

which SDK version are you using

lilac birch
#

^0.39.0

#
const initializePaymentSheet = async () => {
    const {error} = await initPaymentSheet({
      merchantDisplayName: 'Sarookh, Inc.',
      intentConfiguration: {
        mode: {
          currencyCode: 'AED',
          setupFutureUsage: 'OffSession',
        },
        confirmHandler: confirmHandler,
      },
    });
    if (error) {
      console.log({errorip: error});
      // handle error
    }
  };

  useEffect(() => {
    initializePaymentSheet();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const confirmHandler = async (
    paymentMethod: any,
    shouldSavePaymentMethod: any,
    intentCreationCallback: any,
  ) => {
    try {
      console.log({
        paymentMethod,
        shouldSavePaymentMethod,
        intentCreationCallback,
      });
      // Fetching client secret from server
      const res = await proceedSetupIntent(paymentMethod?.id);
      console.log('client secret', res?.clientSecret);
      if (res?.clientSecret) {
        const intentResponse = intentCreationCallback({
          clientSecret: res?.clientSecret,
        });
        console.log({intentResponse});
        navigation.navigate('AdSummary');
      } else {
        console.log('error in ICC');
        showToast('error', 'Error Occurred in saving Payment Method');
      }
    } catch (error) {
      console.log({error});
    }
  };

  const didTapCheckoutButton = async () => {
    console.log('check');
    const {error} = await presentPaymentSheet({timeout: 5000});
    console.log({error});
    if (error) {
      if (
        error.code === PaymentSheetError.Canceled ||
        PaymentSheetError.Timeout ||
        PaymentSheetError.Failed
      ) {
        // Customer canceled - you should probably do nothing.
        console.log('presentPaymentSheet errorrr');
      } else {
        showToast('error', error.message);
      }
    } else {
      // Setup completed - show a confirmation screen.
    }
  };

This is my complete code

paper cosmos
#

would you mind sharing a recording of what's happening or some screenshots? It would also help to see if you have any error logs

lilac birch
#

I have find a little workaround, that
const res = await proceedSetupIntent(paymentMethod?.id);
it gives undefined in res when error occurs, so can you tell me how to close payment sheet programatically, or maybe stop processing if gets undefined in response of createSetupIntent api?

raven wyvern
#

hi! I'm taking over this thread.

lilac birch
#

ok sure, waiting for response of above mentioned query

raven wyvern
#

it gives undefined in res when error occurs
can you clarify what exactly is the error?
how to close payment sheet programatically
not sure, having a look...

lilac birch
#

when we give the card which have insufficient balance, the error will occur

#

when that error occurs I need to close the payment sheet so that the user can input another card details

raven wyvern
#

so the PaymentSheet opens, the user enter their payment information, and there you get an error and the user is "stuck"? again, can you share a screenshot and also the exact error message you see in your logs?

sonic basaltBOT
lilac birch
#

client secret undefined
console.log('client secret', res)

winter current
#

That would imply that your backend code to create the intent is failing:
const res = await proceedSetupIntent(paymentMethod?.id);

#

Are there any logs in your server code that proceedSetupIntent calls?

winter current
lilac birch
#

it is not returning client secret because I am using a test card which is supposed to give insufficient balance error

#

now I need that what would I do if such error occurs because Payment sheet gets stuck on processing when this error occurs

#

I need something to close the sheet if error occurs or in other words need a method to stop processing or close payment sheet, if I do not receive client_secret

winter current
#

Not sure how you expect the callback to progress if your own if block expects a client_secret?

#

There's now way to programatically close the Payment Sheet, no

#

I don't understand why you wouldn't return a client_secret in the backend? What exactly does the proceedSetupIntent call do?

#

The confirmation should happen client side in the Payment Sheet, and there you'd see the 'insufficient funds' error and the sheet wouldn't be stuck

lilac birch
#

Yeah, confirmation is happening at client side

const initializePaymentSheet = async () => {
    const {error} = await initPaymentSheet({
      merchantDisplayName: 'Sarookh, Inc.',
      intentConfiguration: {
        mode: {
          currencyCode: 'AED',
          setupFutureUsage: 'OffSession',
        },
        confirmHandler: confirmHandler,
      },
    });
    if (error) {
      console.log({errorip: error});
      // handle error
    }
  };

with confirmHandler

const confirmHandler = async (
    paymentMethod: any,
    shouldSavePaymentMethod: any,
    intentCreationCallback: any,
  ) => {
    try {
      console.log({
        paymentMethod,
        shouldSavePaymentMethod,
        intentCreationCallback,
      });
      const res = await proceedSetupIntent(paymentMethod?.id);
      console.log('client secret', {res});
      if (res?.clientSecret) {
        const intentResponse = intentCreationCallback({
          clientSecret: res?.clientSecret,
        });
        console.log({intentResponse});
        navigation.navigate('AdSummary');
      } else {
        console.log('error in ICC');
        showToast('error', 'Error Occurred in saving Payment Method');
      }
    } catch (error) {
      console.log({error});
    }
 

In confirmHandler, I send payment?.id to my server, which return me client secret if successful and error if unsuccessful, if it gets unsuccessful I need to close the bottomSheet so that user caninput details again

winter current
#

OK, but then what is proceedSetupIntent actually doing and why isn't it returning a client_secret?

#

In confirmHandler, I send payment?.id to my server, which return me client secret if successful and error if unsuccessful, if it gets unsuccessful I need to close the bottomSheet so that user caninput details again
Successful and unsuccessful what? Can you please just share the code in your server and/or a request it makes to our API

#

Overall I think you're confused. You seem to try to confirm an intent server-side, and also client-side?

lilac birch
#
const proceedSetupIntent = async (paymentId: string) => {
    try {
      const res = await setupIntent({
        customerId: customerId,
        paymentMethod: paymentId,
        adId: adId,
        AdCreationStep: 6,
      });
      if (res?.data) {
        return res?.data;
      }
    } catch (error) {
      console.log({error});
    }
  };

Because I am using a test card which is supposed to give an error of insufficient funds, thats why it does not return client secret

#
async createSetupIntent(
    customerId: string,
    email: string,
    paymentMethod: string,
    adId: number,
    adCreationStep: number,
  ): Promise<{ clientSecret: string }> {
    const setupIntent = await this.stripe.setupIntents.create({
      customer: customerId,
      metadata: {
        email,
        adId,
        adCreationStep,
      },
      confirm: true,
      payment_method: paymentMethod,
      usage: 'off_session',
      payment_method_types: ['card'],
    });

    if (setupIntent.client_secret) {
      return { clientSecret: setupIntent?.client_secret };
    }
  }

  async getAllPaymentMethods(customerId: string, limit: number): Promise<any> {
    const paymentMethods = await this.stripe.customers.listPaymentMethods(
      customerId,
      {
        limit,
      },
    );

    if (paymentMethods.data.length === 0) {
      throw new HttpException(
        'No payment methods exist',
        HttpStatus.BAD_REQUEST,
      );
    }

    return paymentMethods;
  }
#

This is my server side code

#

unsuccessfu setupIntentCreation

winter current
#

I don't understand. You're creating a Setup Intent, passing confirm: true meaning we will immediately attempt confirmation โ€“ this is why it declines (with that test card) and you don't have a client_secret

If you're confirming server-side when why do you need the Payment Sheet?

#

IMO, you need to remove the confirm and payment_method parameters from your stripe.setupIntents.create and then you'll have a client_secret in the response than you can confirm client side in the Payment Sheet with whatever test details you input (simulating an actual customer flow)

#

Right now you've trying to create and confirm a Setup Intent with a pre-existing pm_xxx (paymentMethod) which is probably a test card that declines. Doesn't make any sense in a flow where your customer is inputting card details

lilac birch