#brookflok_api
1 messages ยท Page 1 of 1 (latest)
๐ 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.
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);
}
}
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
Well my problem is that I await for the payment, then I check if the status === paid
Do you have an example payment intent or invoice ID where you encountered this?
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
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
yes I know that, and that is my problem. Because as you can see in my code I check for status === "paid"
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?
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
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
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
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
as it says here
and it has status
Sure, and one of those things is the status you check
https://docs.stripe.com/api/invoices/object#invoice_object-status
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
yep, its an invoice object
Note that in the invoice pay request, the result is an error, not an invoice object
https://dashboard.stripe.com/logs/req_2kkSWeAz7fykaY
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
So whats the behaviour when payInvoice catches an error?
it just console.error(error);
in_1R4jmgJQTk4jQVYGYtgN3qjt
This is the new invoice I created with a credit card that gets declined
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
I get the error and it shows me the message
yes, this also looks like payment failed and the invoice is still open
yes, that is why I have the problem.
I don't understand
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
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
{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
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
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
Great! Glad that was helpful in identifiyng the issue here ๐