#milan-connect-fundsflow

1 messages ยท Page 1 of 1 (latest)

candid cipherBOT
#

Hello! We'll be with you shortly. Below are links to other discussions we've had with you in the past week in case you want to review that information. If your question is related to one of these previous discussions, please provide a comprehensive summary of the current state and what you need help with now. We help many users simultaneously, so a summary allows us to resolve your issue as soon as possible.

rare flicker
#

I don't understand. You said the payment intent is 102 with a destination charge of 100 but you want to reverse 102 from the connect account?

#

By destination charge of 100, what does that mean?

#

You're transferring 100 to the connect account?

#

Why would you want to reverse 102 then?

copper harness
#

I'm sure I'm not using the right terms. The amount of the payment intent was $102 and we set TransferData.Amount to $100 (in pennies of course) with TransferData.Destination pointing to the connected account.

#

We want the connected account to be responsible for all fees in the event of a refund.

rare flicker
#

Oh then you shouldn't use destination charges in the first place

#

That's what direct charges is for

#

With destination charges, platform is liable for all fees

copper harness
#

Got it. So then we should use application fees?

#

The problem with the application fee is that when an ACH return (charge.failed) or a dispute occurs, we want the connected account responsible for the total amount of the original payment. However, Stripe seems to only debit the connected account for the amount minus the application fee.

#

And since we're on Custom Connect, I've been told that Stripe frowns upon using direct charges for some reason, so I'm trying to play by the book.

#

I'll do whatever you all recommend.

candid cipherBOT
sand ginkgo
#

yeah you really shouldn't use Direct Charges, that was incorrect advice

#

Ultimately it's not possible to do what you're after so you have to find either another business model or charge them fees separately

#

milan-connect-fundsflow

copper harness
#

Ok. So then I can just to a transfer reversal for $100 then?

#

And if so, which transfer Id should I be passing in?

#

I can find a way to do it separately.

sand ginkgo
#

What have you tried in the first place? I see you've been here asking about this in multiple threads. So it'd help if you did a clear summary with exact object ids, your code and what doesn't work

copper harness
#

In the other threads, I was trying to wrap my head around application fees vs using destination charges (maybe that's the wrong term). Now I'm actually trying to implement this without application fees.

When I execute the refund, I get back an Id from the refund operation and pass that into the transferReversalService (see below). However that Id is not the right one to pass in because the id needs to be a transfer Id.

                await transferReversalService.CreateAsync(refundResponse.Id,
                    options: new TransferReversalCreateOptions
                    {
                        Amount = Convert.ToInt32(amount * 100)
                    },
                    requestOptions: new RequestOptions
                    {
                        StripeAccount = merchantCredential.AccountId
                    });
sand ginkgo
#

Did you look at the docs? What id does it say it needs?

copper harness
#

It says it needs a transfer Id. But I don't know if that's a transfer Id from a payment intent, or if I'm supposed to find a way to walk from the refund to the transfer. I haven't seen documentation that specifically tells me which transfer Id to use or how to get it.

#

I always try to find the answer before jumping on Discord if that's what you're asking. I even went through and searched Discord.

#

I've tried walking from a PI to a charge to get the transfer Id as well, but that doesn't work.

sand ginkgo
#

That image shows all the objects involved in a Destination Charge. They show the links between all those objects too.

copper harness
sand ginkgo
#

What you are trying to do is reverse that Transfer with the tr_001

#

Why aren't you passing reverse_transfer: true when you refund by the way?

copper harness
#

Because we want the merchant to be on the hook for the full $102.

sand ginkgo
#

yeah that's what this is for

#

I mean it's impossible to reverse more than you sent them

#

so it does feel like you've set this up all wrong based on the flow of funds you really want

copper harness
#

That would do a proportional refund ($100 from the account and $2 from the platform). Then again, I guess we could then just turn around and charge the merchant in a separate charge later.

sand ginkgo
#

yeah sorry it's tough to grasp what you did ๐Ÿ˜ฆ

#

$102 Charge on the Customer, transfer $102 to the connected account and take an ApplicationFee for whatever you want

copper harness
#

Ok. So just let Stripe handle the reversal and then we'll charge the merchant later if we want to bill them for the fees.

sand ginkgo
#

yep there's no other way for that part

#

But I still honestly don't get your flow sadly I'm sorry

copper harness
#

Understood. Stripe's flow of funds is different than what we are used to coming from the PayFac world. Just getting used to the way things work here.

#

It's just two different philosophies of funds flow.

#

But thank you for your time.

sand ginkgo
#

Any chance you can try and explain the full funds flow in one paragraph with exact amounts for all the parts?

copper harness
#

Ideally -
Payer pays $102. $100 should go to the merchant and $2 to the platform. Stripe debits platform whenever for all fees.
Payer requests a refund. Merchant initiates a refund of $102. $102 is debited from the merchant and sent to the payer.

sand ginkgo
#

That is all doable with Stripe. That's why I am asking for a detailed paragraph with all exact amounts ๐Ÿ™‚

#

Do you have a clear example PaymentIntent id where it didn't work?

copper harness
#

I'm trying to find one quickly. I do have a charge.failed where we want the same flow. Would that work?

#

In other words, if the charge.failed (ACH return) occurred, we want the merchant to cover the $102.

sand ginkgo
#

well no

copper harness
#

Ok. Let me find a refund then.

sand ginkgo
#

you want them to cover the $102 + the Stripe fee for the failed debit right?

copper harness
#

No. Just the $102

sand ginkgo
#

or you're fine being on the hook for that extra fee

#

ah

#

then lol

#

Are you using ApplicationFees? Or transfer_data?

copper harness
#

transfer_data

sand ginkgo
#

(sorry I was certain you wanted that extra fee covered)

#

that's your problem ๐Ÿ™‚

#

Switch to application fees!

#

Let me write a clearer summary, will take a couple minutes

copper harness
#

The platform will cover all Stripe fees.

#

I've experimented with both transfer_data and applications fees and watched funds flow in the sandbox. I keep going back and forth on which approach to take.

sand ginkgo
#

With transfer_data:

  • Customer pays $100
  • Platform gets $100 minus Stripe fee $5 so net $95
  • Platform transfers $95 to connected account
  • Connected account gets $95 net
  • Platform gets $0 net.
    After a refund
  • Customer gets $100 back
  • Platform gets -$100
  • Platform reverses Transfer from connected account so gets back $95
  • Connected account nets 0
  • Platform is at -$5 (pays the Stripe fee that is not refunded

Does that make sense?

copper harness
#

Right. That's what I'm seeing with the transfer data approach.

sand ginkgo
#

cool and your problem here is that you want that fee to be covered by the connected account on refund right?

copper harness
#

Exactly

sand ginkgo
#

cool now give me 2 more minutes

copper harness
#

You're the best. I really appreciate this. I swear I'm learning from these conversations.

sand ginkgo
#

With ApplicationFees

  • Customer pays $100
  • Platform gets $100 minus Stripe fee $5 so net $95
  • Platform transfers the full $100 to connected account and asks for a $5 ApplicationFee back (application_fee_amount: 500)
  • Connected account gets $95 net ($100 in and -$5 for the fee back)
  • Platform gets -$100 for the Transfer to that account so they are at -5 and they get the ApplicationFee back for $5 so they are at net $0
    After a refund
  • Customer gets $100 back
  • Platform gets -$100
  • Platform reverses Transfer from connected account for the full amount (default) so they get +$100 back from the connected account
  • Connected account gets -$100 and they were at +$95 so they end up at net -$5
  • Platform got -$100, the + $100 back and are at net 0

Does that make sense?

copper harness
#

Yep. That's also what I witnessed.

sand ginkgo
#

ah so you already know all of this? If so what's the problem?

copper harness
#

Which is why application fees seemed like the right approach for our scenario. However, Stripe has recommended that we take the transfer_data approach since we are on custom so I've been trying to make it work.

sand ginkgo
#

I think you are mixing some words up

#

ApplicationFees work with Custom accounts, they are totally normal.

#

we do recommend transfer_data for most platforms, because they cover those fees. It's rare to cover the fee but not on refund

#

but based on your flow of funds, you want ApplicationFees that's for sure

copper harness
#

Ah ok. So I got lost in the terminology then. We'll move forward with application fees.

#

Thank you again

sand ginkgo
#

the only thing you can not do is take more money than you sent to those connected accounts. So if you wanted to cover that extra fee for failed debit, you're stuck ๐Ÿ˜ฆ

copper harness
#

That's fine. We don't want to take more than we sent in.

sand ginkgo
#

well as you grow those extra failed debit fee will add up ๐Ÿ™‚

copper harness
#

Yes. We'll do that on the monthly statement at the end of the month, but not on the individual transaction.

#

We're just tallying those.

sand ginkgo
#

๐Ÿ‘

copper harness
#

That's when I think the account debits link you sent may come into play.

#

Or some other options that we are exploring

sand ginkgo
#

yep!

copper harness
#

Ok...so now that we're on the same page (and I've already made the code change back to application fees), can I ask another question?

sand ginkgo
#

sure fire away!

copper harness
#

When a charge.failed happens for an ACH return, the debit of $102 hits the connected account and then there is another line item that credits them back for the $2 application fee. So you can see how this might feel inconsistent with refunds. Maybe we can be OK with this, but is there a way to stop that $2 credit back to that account?

#

If not, maybe we'll just eat that one and move on.

sand ginkgo
#

I don't really understand what you described at all sorry.

#

you said "the debit of $102" but you mean the TransferReversal?

#

Sorry I'm a strickler for core vocabulary as it's so fundamental to your Stripe integration

#

So okay re-reading a few times, I think what you meant is that when the ACH Debit fails, then we automatically do all the reversals for you and unfortunately we do refund the ApplicationFee automatically as part of this and there is no way that I know of to block this behaviour ๐Ÿ˜ฆ

copper harness
#

Payer pays $988 and we take $9.88 as the application fee.
The ACH transaction fails (charge.failed) for "insufficient funds". At this point, Stripe debits the connected account for $988 and then credits them for $9.88 (presumably from the platform).

Is there a way to prevent the $9.88 credit?

#

If not, no worries. But it would be nice to prevent this.

sand ginkgo
#

not possible. And sorry really really crucial to use the exact API vocabulary. You see how it's explicitly called an ApplicationFeeRefund in that screenshot which maps to a real API resource https://stripe.com/docs/api/fee_refunds/object

copper harness
#

Ah ok.

#

Thank you again for your time. I really appreciate the time and effort you took. Have a great day!

#

And I'll learn the terminology

#

It's a work in progress.

sand ginkgo
#

yep totally understandable. I spend my days here talking about it so I know this by heart ๐Ÿ™‚