#brookflok_api

1 messages ยท Page 1 of 1 (latest)

prisma ploverBOT
#

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

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

red harness
#
  async function payInvoiceAndAddGems(invoiceId: string, userId: number, gemAmount: number) {
    try {
      // Pay the invoice using the function from stripe.ts
      const paidInvoice = await payInvoice(invoiceId);

      // Check if the invoice is paid
      if (paidInvoice && paidInvoice.status === 'paid') {
        // If paid, add gems to the user's account
        const response = await postMoneyToken(userId, gemAmount);

        if (response.ok) {
          return {
            success: true,
            message: 'Payment successful and gems added to account',
            invoice: paidInvoice,
          };
        } else {
          throw new Error('Failed to add gems to user account');
        }
      } else {
        throw new Error('Invoice payment failed');
      }
    } catch (error) {
      console.error('Error in payInvoiceAndAddGems:', error);
      return { success: false, message: 'Payment process failed', error };
    }
  }
#
export async function payInvoice(invoiceId: string) {
  try {
    // Finalize the invoice
    await stripe.invoices.finalizeInvoice(invoiceId);

    // Pay the invoice
    const paidInvoice = await stripe.invoices.pay(invoiceId);
    return paidInvoice;
  } catch (error) {
    console.error(error);
  }
}
viscid cypress
#

payment is declined but the user gets the gems in the app
I can't speak to the logic in your app, but i can help you figure out why you might be mistakenly considering a failed payment as successful

red harness
#

Well my problem is that I await for the payment, then I check if the status === paid

viscid cypress
#

Do you have an example payment intent or invoice ID where you encountered this?

red harness
#

this is the payment: pi_3R4fguJQTk4jQVYG2I19A2P6

#

And I looked trough it all and it never gives the payment status paid

#

but the user was writing to our support team and he told them that he was trying to make the payment and he got the gems, and his money was not taken from his PayPal account

#

I don't have any logs of giving the gems to the user, our team is currently developing that function so we can track all giving and spending of the gems for the user. But currently I can't find a reason why this payment returned "paid"

And the best way to find out is to connect paypal account to my test account on sandbox and to have a declined payment, but I don't see a way of doing that.

#

When I test with a credit card that has decline payment I get the error and everything is working

viscid cypress
#

The invoice associated with that payment is not paid: in_1R4fgsJQTk4jQVYGrjCgrjUl

#

So i am not sure why your application logic would consider it as such

red harness
#

yes I know that, and that is my problem. Because as you can see in my code I check for status === "paid"

viscid cypress
#

You've abstracted over the invoice payment call with const paidInvoice = await payInvoice(invoiceId); so could your method possible be incorrectly mutating the results?

#

What does payInvoice do?

red harness
#
export async function payInvoice(invoiceId: string) {
  try {
    // Finalize the invoice
    await stripe.invoices.finalizeInvoice(invoiceId);

    // Pay the invoice
    const paidInvoice = await stripe.invoices.pay(invoiceId);
    return paidInvoice;
  } catch (error) {
    console.error(error);
  }
}
#

It is a simple functioin it finalize the invoice and then it pays it and return the paidInvoice

#

where I can read the status

viscid cypress
#

If you're just passing back the stripe invoice result, then it doesnt make sense how you'd get into a code path that checks the invoice status.paid

red harness
#

wait I don't understand you now.

#

I have the function payInvoice that finalize the invoice and try to make the payment with const paidInvoice = await stripe.invoices.pay(invoiceId);

And it reutrns a lot of things

#

as it says here

#

and it has status

viscid cypress
#

yep, its an invoice object

red harness
#

yes and then if it is status === "paid" I give the gems to the suer

#

user*

viscid cypress
#

but this invoice would still be open

#

not paid

red harness
#

yes that is my problem

#

I can't get it why is this happening

viscid cypress
#

So whats the behaviour when payInvoice catches an error?

red harness
#

it just console.error(error);

#

in_1R4jmgJQTk4jQVYGYtgN3qjt

#

This is the new invoice I created with a credit card that gets declined

#

I get the error and it shows me the message

viscid cypress
red harness
#

yes, that is why I have the problem.

viscid cypress
#

I don't understand

red harness
#

My user is telling me that he received gems and I can't figure out how he recieved it

#

Now after talking to you I'm starting to think he was lying but I can't understand why would he do that xD

viscid cypress
#

Unless there's other code operating here, your check seem pretty simple:

 if (paidInvoice && paidInvoice.status === 'paid') { ... }
#

and those conditions won't pass for an open invoice

#

so i suspect there must be another code path

red harness
#
              {isLoading ? <Loading /> : <ConfirmButton onClick={handleConfirm} buttonText="Confirm Order" disabled={isButtonDisabled} />}
#

My button

#

When pressed it does handleConfirm

#
const handleConfirm = async () => {
    if (quote) {
      setIsLoading(true);
      try {
        // Accept the quote
        const acceptedQuote = await acceptQuote(quote.id);

        if (!acceptedQuote || !acceptedQuote.invoice) {
          throw new Error('Failed to accept quote or generate invoice');
        }

        // Pay the invoice and add gems
        const result = await payInvoiceAndAddGems(acceptedQuote.invoice as string, user.id, selectedOption === 4 ? customValue : selectedOption);

        if (result.success) {
          const tax = (quote.amount_total - quote.amount_subtotal) / 100;
          sendPurchaseGemsEvent(acceptedQuote.invoice as string, [ecommerceItem!], quote.amount_subtotal / 100, '', tax);
          dispatch(refreshUser());
          setIsModalOpen(true); // Open the modal on successful payment
        } else {
          throw new Error(result.message);
        }
      } catch (error) {
        console.error('Payment failed', error);
        setAlertMessage('Payment failed. Please try again.');
        setAlertType('error');
      } finally {
        setIsLoading(false);
      }
    }
  };
#

and it takes the quoute accept it and then does

const result = await payInvoiceAndAddGems(acceptedQuote.invoice as string, user.id, selectedOption === 4 ? customValue : selectedOption);

#

Then when I recieve the result I do sendPurchaseGemsEvent this is just a google tag manager script

#

for tracking user payments in the app trough google analytics

#

it does nothing else

#

or it shows the alert message

#

Thx for the insight I will check with the user again and write again later, because I was thinking that I made some mistake but as I see all is good

prisma ploverBOT
red harness
#

Hi, I just found out that in the app there is one more way to buy the gems and it doesn't have all the checks

#

This code I sent is working as it should

viscid cypress
#

ok, that makes sense

#

so have you found the gap this gets through, then?

red harness
#

yes, I have some modal in the app that makes the problems It is done really bad, now I will fix it and check the problem again

viscid cypress
#

Great! Glad that was helpful in identifiyng the issue here ๐Ÿ™‚