#MarcusStripe - tracking credit notes and refunds
1 messages ยท Page 1 of 1 (latest)
That link is working for me, can you summarize the state and any new question you have here please?
So I have read about transfer groups.
It seems it could help, but only under very special conditions:
- The transfer group must be build at the same time, so the transfer is made immediately.
- That means, the transfer is made IMMEDIATELY after the subscription charge was made.
- That again means the customer would get multiple small transfers, and for each transfer (that could be 300x 10 Euros/month!), I would have to create a commission credit invoice on my end. So it doesn't seem practical.
I think it is still the better approach to collect the refunds / list of partial refunds and to substract them on my end,
before I pay the commission, if any remains.
So I could have a status PENDING, PAID, REFUND and PARTIAL_REFUND, and for PARTIAL_REFUND I would show a list of all partial refunds below
the commission amount, and then pay out the remaining amount, if there is any.
So for this again, I am asking - what is the best approach for this:
A) Listening on the credit_note.created event, and adding the amount to a list of refunds to the related commission.
B) Retrieving, once per month or maybe once per day, for each of my affiliated-generated customers,
PaymentIntent.list - the charges and their related refunds -
this would give me the charge.getRefunded() boolean flag to know if the entire charge was refunded -
otherwise I would just add a negative partial amount, and later another one, if there are more over time.
Taking a step back, I agree with this:
I think it is still the better approach to collect the refunds / list of partial refunds and to substract them on my end, before I pay the commission, if any remains.
Generally it is better to aggregate in your own systems and take fewer actions
I would say that it really depends on your requirements and the complexity of the integration for your systems
I would err toward using webhooks to get notifications pushed to me and track those, but if both achieve your goals, then its really up to you.
ok, let's try it more concrete from my end:
- credit_note.created event - is that event the right one to use for my needs?
- iterating the payment intents for me has the super nice feature of seeing - at once - if the refund is a total refund - I could just directly switch the commission from PENDING to CANCELED / REFUNDED.
But it has the disadvantage of being batched and not just in time.
But I fear I could also loose some kind of refunds for the redit_note.created -
e.g. if several refunds are done for the same charge.. will this still appear as a new redit_note.created event?
there is "charge.refund.updated" after all.. and currently I am not listening to it.. so maybe it could happen that ther is some kind of update I am (currently) missing?
--
And.. it would be nice to link refunds to their related charges also
is there a way to get this info from the credit_note.created event?
If your needs are mapped to tracking creation of credit notes, then that sounds like the right event (I can't know all of your business requirements, really)
well, as far as I know.. refunds can be created in different ways in the stripe UI.
I do create then with a credit note, as this will trigger all the info needed for the credit invoice also.. if I remember correctly
can refunds also be executed by stripe or the bank of the customer or so???
--
And.. it would be nice to link refunds to their related charges also
is there a way to get this info from the credit_note.created event?
Yes, you can get that info from the refund by using expansion (the refund object has charge ID on it, also expandable)
https://stripe.com/docs/api/credit_notes/object#credit_note_object-refund
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
So you could do eg expand=['refund.charge'] when examining a credit note
Note that this is not in the webhook event itself (no expansion in webhooks), you'd need to retrieve it
MarcusStripe - tracking credit notes and refunds
expansion.. but an expansion is hardly available on an event
you mean by calling the refund api then?
"you'd need to retrieve it".. so you are basically already confirming just that.
So I could -
for every charge, store the related charge ID on my system, if related to a commission.
And then, for every credit_note, retreive the refund id:
stripeCreditNote.getRefund()
and then retrieve the refund.. and I assume I would not even need to expand it.. as the charge id would be present already
and then I could link the refund / the list of refunds to each related comission, yes?
If that's driven by the credit note, then yes
You can use expansion to get both at once (or yes, retrieve that refund object and expand the charge)
Many different variations, you'll have ot see what fits best
But yes, you cannot get that directly in the webhook data, there's no expansion there (its not supported)
well the charge I would have gotten earlier anyway.. is my point ๐
I would just need the ID for reference and then linking the two together
Sure, then just the refund object will do ๐
If you also get refund objects, you may alreayd have this, with clever event processing
ie, pair together the credit note event data wiht the refund event data
just be aware they may not always arrive in the same order
Wait.. thinking more..
So actually.. since I need the REFUND for the charge id...
Why not instead directly listening to the charge.refund event? Woulnt it most probably give me the charge ID directly?
Here I would not need any invoice related infos.. just the info of the amount of the refund and the id of the related charge
that would be in the refund info then, yes
Hm... I am rethinking now my entire process.
To know about commissions to be paid out.... I am currently listening on invoice_paid.
Wouldnt it be best to listen for both - a paid charge and a refunded charge to listen directly on the charge events?
I checked, here is the entire list:
charge.captured
charge.expired
charge.failed
charge.pending
charge.refunded
charge.succeeded
charge.updated
charge.dispute.closed
charge.dispute.created
charge.dispute.funds_reinstated
charge.dispute.funds_withdrawn
charge.dispute.updated
charge.refund.updated
From these, the relevant ones seem to be:
charge.succeeded
Occurs whenever a charge is successful.
charge.refunded
Occurs whenever a charge is refunded, including partial refunds.
charge.dispute.funds_reinstated
Occurs when funds are reinstated to your account after a dispute is closed.
charge.dispute.funds_withdrawn
Occurs when funds are removed from your account due to a dispute.
- So for every monthly subscription fee paid, I would get a charge.succeeded event, right?
- Will the charge.succeeded show me the amount charged? Including tax od excluding?
And for every refund, a charge.refunded event.
3) For the charge.refunded event, would there be the id of the original charge event, I assume?
4) Will it also show the (partial) amount charged? Including tax or excluding?
5)charge.dispute - Disputes are always full, never partial, right?
6) So I could potentially put on hold a commission when there is a "charge.dispute.created" I guess.
7) charge.dispute.funds_withdrawn shows me a "full refund" based on a dispute of a customer, right?
8) So I would then put the "ON_HOLD" charge on CANCELED in this case.
9) I would then put the "ON_HOLD" charge back on PENDINING in this case.
All correct? Any important event I forgot?
1/ assuming there was a payment yes (maybe there isn't due to discount or credit)
2/ yes
3/ yes
4/ it's the final charge amount, what the customer paid
5/ No, they can be partial: https://stripe.com/docs/disputes/how-disputes-work#disputed-amount
Dispute flows are another beast, dpends on your business setup and customer relationship etc. I'd suggest testing extensively (both the dispute and non-dispute bits) and making sure you have everything you need and cover your defined busines sprocesses
We can't tell you if you've missed anything, you own your processes
Please test extensively, if you find something is not working as you expect or you need help finding a particular bit of info, feel free to pop by again
But really the answer now is for you to test a lot with our various test cards for failures, disputes etc
Ok, so since disputes should be rare (~ 0.3% I am told), given that we have a 100% refund policy in case of any issues for 30 days...
I will for now just keep ignoring them.
As for the charges and refunds.. based on your feedback, I came up with this very simple logic:
public class ChargeHandler implements StripeEventHandler {
public void handle(StripeObject stripeObject) {
Charge charge = (Charge) stripeObject;
String customerId = charge.getCustomer();
if (isNotAquiredByAffiliatePartner(customerId)) {
return;
}
if (affiliateService.isDuplicateCharge(charge.getId())) {
return;
}
Affiliate affiliate = findAffiliatPartner(customerId);
assignChargeToAffiliatePartner(charge.getAmountCaptured(), affiliate);
}
public StripeEventType type() {
return CHARGE;
}
}
AND for refunds:
public class RefundHandler implements StripeEventHandler {
public void handle(StripeObject stripeObject) {
Charge charge = (Charge) stripeObject;
String customerId = charge.getCustomer();
if (isNotAquiredByAffiliatePartner(customerId)) {
return;
}
for (Refund refund : charge.getRefunds().getData()) {
if (isDuplicateRefund(refund.getId())) {
continue;
}
attachdRefundToCharge(refund.getAmount(), charge.getId());
}
}
public StripeEventType type() {
return REFUND;
}
}
--
as much as you can tell from my java code... does this make sense ?
๐ I'm hopping in since roadrunner has to head out - give me a few mi nutes to catch up
overall this seems to make sense, but it's hard to tell since I don't know what any of the functions you call (like assignChargeToAffiliatePartner and attachdRefundToCharge ) are doing
yeah well I named them in a way to tell as good as possible to you what I have in mind ๐
they are not implemented yet
So my thinking is - for the charge - add a commission value (30% of the charge in the average case)
and store the charge id with it
and IF a refund charge event comes - iterate over all no existing refunds of the event
and add any new refunds that were not yet existing
and then I would have a parent comission amount with an optional list of refunds on my end
and when I pay this out after 30 days, I would substract the refunds from the comissions and pay out the resulting amount
that should be good in 99.5% of the cases, i guess
--
the charge_updated event.. I would not need to care since I already listen on the charge_refund event, right?