#putte

1 messages ยท Page 1 of 1 (latest)

crimson egretBOT
mental hamlet
#

Hello

#

Can you provide me an example Event ID here that I can look at?

waxen tide
#

"evt_1MgtsaRXZxR2GEgiJtadW8xR"

mental hamlet
#

Thanks looking

mental hamlet
#

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

#

So you should check what in your integration is initiating these payout API requests

waxen tide
#

Ok so the error is from my part

mental hamlet
waxen tide
#

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

mental hamlet
#

Sounds possible

#

Do you have a retry mechanism set up?

#

Wondering if you are just spamming payout creations when it fails the first time

waxen tide
#

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

fading kraken
#

await stripe.payouts.create(data, { stripeAccount: payload.account}) <- This code is creating a Payout manually

waxen tide
#

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?

fading kraken
#

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

waxen tide
#

It seems to be for each failed payout

#

I mean there are thousands of events here as well as I can see

fading kraken
#

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

waxen tide
#

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

fading kraken
#

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

waxen tide
#

Ok that would make sense to be honest

#

If that is the case, I have to rewrite the logic somehow

fading kraken
#

yeah I think that's what's happening

waxen tide
#

Have you confirmed it?

#

And do you have any suggestions on a logic to prevent this?

fading kraken
#

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

waxen tide
#

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

fading kraken
#

Are you just asking whether there's a webhook event for when a payout/transfer is complete?

#

There's the payout.paid event

waxen tide
#

Yeah but I thought perhaps one can replace balance.available webhook

fading kraken
#

What do you mean by that? I'm not fully following what you want instead

waxen tide
#

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

fading kraken
#

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

waxen tide
#

Yeah so whenever it bounce back, I believe that it should NOT retrigger balance.available event

#

But I'll solve it, thanks for pointing out the issue