#putte
1 messages ยท Page 1 of 1 (latest)
"evt_1MgtsaRXZxR2GEgiJtadW8xR"
Thanks looking
Alright sorry for the delay
I do see a bunch of payout.failed webhooks to your platform endpoint
But it looks like you are creating manual payouts yourself which are failing
For instance if you look at https://dashboard.stripe.com/test/connect/accounts/acct_1Mgs2jRXZxR2GEgi/activity you will see a ton of failed payouts for that Connected Account that you created
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 you should check what in your integration is initiating these payout API requests
Ok so the error is from my part
Yeah your code is making a lot of requests to our Create Payout (https://stripe.com/docs/api/payouts/create) endpoint somewhere
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
Ok I'm stopping the backend for now
To see what can cause this
I have. webhook for balance.available, that automatically triggers payout
But it should be triggered only once I guess?
That is the only thing I have in my backend that does trigger payouts
Sounds possible
Do you have a retry mechanism set up?
Wondering if you are just spamming payout creations when it fails the first time
Hmm let me have a look, its not done manually by me though
import express, { Response } from "express"
import stripe from '../../config/stripe';
import stripeSignature from '../../middleware/stripeSignature';
import { RequestCustom } from "../../types/types";
const router = express.Router();
router.use(express.raw({type: "application/json"}))
router.use(stripeSignature)
router.post('/', async (req: RequestCustom, res: Response) => {
const payload = req.jsonBody;
console.log(payload)
const balance_data = req.jsonBody.data.object
const account = await stripe.accounts.retrieve(payload.account);
if(!account.external_accounts || !account.metadata) return res.status(500).send("Account not found")
const user_id = account.metadata.user_id
const data = {
amount: balance_data.available[0].amount,
currency: balance_data.available[0].currency.toLowerCase(),
destination: account.external_accounts.data[0].id,
statement_descriptor: 'Cuberra',
metadata: {
user_id: user_id,
stripe_event_id: payload.id,
stripe_account_id: payload.account
},
}
try {
const payout = await stripe.payouts.create(data, { stripeAccount: payload.account})
return res.sendStatus(200)
} catch (error) {
return res.status(500).send(error)
}
})
export {router}
This is everything I have for payouts
await stripe.payouts.create(data, { stripeAccount: payload.account}) <- This code is creating a Payout manually
Yes true
But it has to recieve a balance.available webhook from stripe
Otherwise this code wont be triggered
Yes I'm correct here. I can see that there are a tons of balance.available webhooks sent to my server
For these thousands of payout tries and retries, there was a balance.available webhook sent to my server before
I actually think there's an issue from your side
You still there?
๐ Yup I'm here (sorry juggling a few different folks)
Was there a single balance.available webhook event, or is there a balance.available event for each failed payout?
It seems to be for each failed payout
I mean there are thousands of events here as well as I can see
Yeah, then that's expected right? You're attempting a payout for each balance.available event, but all the payouts you're making are failing
So why should that trigger balance.available multiple times?
Makes no sense
It should trigger once and thats it
Then there can be multiple events for transfers, once for created, updated and one for faile
But I dont see any reason to why I should recieve a balance available again, when I have already been notified once about it
The transfer.failed tells me that it failed, hence, no reason to send another webhook for balance.available
Ahhh I have a guess - I'll need to double check, but I believe once you create the payout we mark those funds as unavailable because we want to pay them out. Once the payout fails, we put those funds back in your available balance to indicate that their available
Ok that would make sense to be honest
If that is the case, I have to rewrite the logic somehow
yeah I think that's what's happening
Yeah that's definitely what's happening (I've confirmed on my end)
Something you could consider adding to your logic is that you pause payouts if you get a payout.failed event.
If the payout fails usually means that something has gone wrong and maybe the bank account needs to be fixed in some way
Ok I'll come up with something
Is there a status on transfer we can use? As in paid or something
Because then I can replace balance.available with transfer webhook for a success status or something
Are you just asking whether there's a webhook event for when a payout/transfer is complete?
There's the payout.paid event
Yeah but I thought perhaps one can replace balance.available webhook
What do you mean by that? I'm not fully following what you want instead
Well since you guys are using this logic for balance.available, which I believe does not make any sense is not user-friendly at all, I have to come up with a method to tell if the connected account has money that can be payed out
But to avoid this loop, I have to somehow replace the balance.available webhook, but I cant wrap my head around how
Let me take a step back
The balance.available event IS the event that tells you whether you have money that can be paid out
The issue is that there is not event that can tell you if the connect account has a bank account that will successfully be paid out to
So the balance.available event is working as intended - your code just didn't take into account that the bank account that's being paid out to isn't working