#steven_link-statementdescriptors

1 messages ยท Page 1 of 1 (latest)

torpid coralBOT
#

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

๐Ÿ“ Have more to share? Add more details, code, screenshots, videos, etc. below.

regal gate
#

๐Ÿ‘‹ Can I ask for more details to help you? You gave one example and asserted something broke. Can you give a clear recent example where it worked so I can compare?
Can you also explain exactly what "billing descriptors via API" means? That is not a concept we have so I think you are referencing a feature named differently

stark rune
#

this used to have a string in it now it doesnt

regal gate
#

Okay so statement descriptor. Can you try and provide a clear summary beyond the picture? Like show me an exact PaymentIntent id where this displayed before so I can compare

#

steven_link-statementdescriptors

stark rune
#

Here's a payment-id: pi_3Re0EZDDdhNYBUte0ooVVe2Q

#

this was displayed on all stripe link payments before today

#

now none, even old ones return any data

#

it looks like Stripe made some changes to redact all statemetn descriptors on Link changes today not understanding what this field was being used for

regal gate
#

can you clarify what you are using it for? It's just the Dashboard UI so trying to grasp what is blocking you exactly. I'm investigating in parallel but I don't completely grasp what you are describing yet, especially since it's not easy to debug the "absence of information" since you say it was here before but isn't anymore.

stark rune
#

Ah yes, so it's nulled out in the API response as well - we have over 4000 Stripe connected merchant accounts and we rely on this field to perform part of our services - reconciling payment data with consumer complaints

#

Before today this field was available via API however due to some change it's now no longer available, both on new and old charges

#

A consumer may not know their email used for payment nor card details and the billing descriptor is the only field available, so removing the string from Stripe prevents merchants from reconciling complaints - it's quite bad - our clients are already experiencing an increase in disputes

regal gate
#

yeah sorry can I ask you to try and explain this more clearly? IT's really important. You say "it's nulled out in the API" but what exact part is nulled out. Can you share exact JSON response so we're aligned?
Statement descriptors are subtle and there are many different properties in the API across API Resource so I want to make sure we're talking about the same thing here.
I get you're worried about the change, but to help you I do need clear information

stark rune
#

Yes one moment

#
  "statement_descriptor_suffix": null,

in the /charges endpoint this field is now null for all Stripe Link charges

regal gate
#

thanks, sorry to push but you again said "billing descriptor" which isn't a thing. Now you're talking about an increase in disputes which seems completely unrelated to the ask about the Dashboard showing an empty value. Seems you imply we don't put the statement descriptor when charging the customer and so it's not on their bank statement

#

Those have always been null in the API unless your code explicitly forced the values in the API, which you aren't doing here since it's an Invoice right?

Do you have an example Event evt_1234 where this was set before so I can look? A few days ago is fine. I just want to compare. Those Events are snapshots and can never be mutated

stark rune
#

No, that's not what I'm implying. The statement_descriptor is not available via API (or dashboard) so if a cardholder opens a complaint and is unable to reconcile their account with card numbers etc (which are unavail via link) the descriptor is the only field that can be used

#

Yeah give me a moment

regal gate
#

Sure thing. And to be clear I am not saying we didn't change somethng. I just want to align on the vocabulary to find the discrepancy.
You mentioned "increase in disputes" which confused me

stark rune
#

These were never null until today or so

regal gate
#

sure, that's where having an exact example where they are not null in the Event will help me track it down

stark rune
#

Yes the merchant has no way to refund the cardholder in these cases - hence they will receive more chargebacks

#

pi_3RVoPBDDdhNYBUte1pzEM6p1
check out this payment

#

has the statement descriptor not null

regal gate
#

sure but I want proof that it was not null before. I need an exact object that has this set and the exact Event id proving it

stark rune
#

ok

regal gate
#

okay now I have what I need to piece things together. I can see internally that the PaymentIntent you just shared was explicitly confirmed with statement_descriptor: 'xxxxx' and the more recent one (first one) was not.

Trying to figure out the difference

stark rune
#

some change definitely went into Stripe - we have several merchant tickets related to the issue being openeed

regal gate
#

hum

#

Are you the developer? I have a hunch but I want to make sure I am talking to the right person

stark rune
#

Yes I am, I'm the CTO of Chargeblast

#

This is from a client's payment volume today - only ~5% of their Link volume have descriptor fields available via API. As of a few days ago it was every transaction

regal gate
#

Okay so this will be rapid fire back and forth if that works for you. Let's pause the "impact" for a sec and focus on the implementation

stark rune
#

Kk

regal gate
#

The PaymentIntent pi_3RVoPBDDdhNYBUte1pzEM6p1 that you mentioned is associated with the Invoice in_1RVnS5DDdhNYBUteaCnB9pSk.
That PaymentIntent and resulting Charge py_3RVoPBDDdhNYBUte1ePHlb9p do have statement_descriptor set (not sharing the value because this thread is public)

Now the value I see on the Charge was added explicitly by your own code as a Connect platform. That one you called the Updated Invoice API and explicitly passed statement_descriptor: 'xxxx'. You even did this multiple times in a row

So first question: does that ring a bell? Do you have code that does this?

stark rune
#

let me know if you want to hop on a call or prefer other method of comms.

Yes we do have code that does this

regal gate
#

Written text is all I can offer

#

Okay so you have code that does this. The example you gave me that has a statement descriptor had that code running

The other one you gave me did not

stark rune
#

The issue is related to the exposing of the charge data via API - all charge objects (including stripe link payments) will have some statement_descriptor field available in Stripe's internal database. The card holder has to see something on their banking app whether it was through a normal card or Link

regal gate
#

Try to focus on my question

stark rune
#

We have code that does this yes

regal gate
#

Sorry I know it's annoying, I have a weird way of working and I have done this for years. If we run around with alternative "what if" we won't get anywhere I think. Not quickly. But I will touch on all those threads if we get stuck

#

Okay so can you clarify why that logic/code was never done on the other Invoice that you started with?
To me, all is expected here. If you don't force a statement descriptor value in the API either on the Invoice or the PaymentIntent, the resulting Charge in the API will always have statement_descriptor: null to reflect nothing was passed/forced. It's separate from what we do send the bank, it's purely an API concept

stark rune
#

Ok, so I could provide payment ids for Stripe Link payments that have statement_descriptor passed in via non-null, that was set at the sub-account level, however currently have null exposed to us as the connected platform

#

Previously, Stripe would return the field actually shown to the bank

regal gate
#

I don't understand your words ๐Ÿ˜ฆ

#

You are mixing up concepts in our API so I'm confused

stark rune
#

So our client - the Stripe sub-merchant (connected account)

#

sends in their own value via API

#

it then appears blank when we query that charge

regal gate
#

pause here

#

Statement descriptors are really complex and there are many layers of "where it can be configured". And there's a real difference between what appears in our API in various places and what's sent to the bank.

So focusing purely on the API and code, clarify what you mean?
Do you mean a connected account goes in their Dashboard and configures their default statement descriptor + statement descriptor prefix and you do nothing in the API?
Something else?

stark rune
#

give me a moment

#

For example here:

pi_3RdIlQHCcS7hScp61GmIrH2e

#

There's a request to update the invoice id with a statement_descriptor however the charge has null value for the statement_descriptor field

#

Do you mean a connected account goes in their Dashboard and configures their default statement descriptor + statement descriptor prefix and you do nothing in the API?
Connected account can transmit their own statement_descriptor field via API, which is now being lost

regal gate
#

Connected account can transmit their own statement_descriptor field via API
what does that sentence mean?
Focus on exact code. What do you do in your code? really sorry this is so confusing to me

stark rune
#

yes apologies it's confusing as there's a few moving parts

#

we have implemented stripe as stripe connect

regal gate
#

pause

#

I understand Connect and your setup. I just need you to be crisp about what your code does. The connected account does nothing since you control all the code.

The PaymentIntent example you gave me was confirmed before the Invoice was updated with a statement descriptor

stark rune
#

Ok fair

#

Our code, and there's a race condition so it only works some % of the time, will set the descriptor for the charge to the merchants public shortened descriptor + a 6 to 8 digit hex cdoe

regal gate
#

Just to clarify what I think happens. I am not certain but I am as close to certain as I can be

The Charge object will always have statement_descriptor: null unless your code explicitly forced a statement descriptor on the PaymentIntent or Invoice.

stark rune
#

Is there any chance I could DM you non-public info?

regal gate
#

So right now, it looks to me like nothing is broken and there is something on your end not setting the statement descriptor properly

And I am not saying it's the case, I'm trying to summarize where we are. Until we find a clear example where it worked before and doesn't now I cant do much

#

and yes totally fine to DM. I'll talk here but I can read the DMs to piece things together

stark rune
#

kk

regal gate
#

Okay let me take a wild guess that will likely explain it all

#

Your code reads a completely different property on Charge called calculated_statement_descriptor and you didn't realize it is only ever set for normal card payments and never for other payment methods including Link.

Can you confirm that's what you do and what populates the data in your screenshots?

stark rune
#

one sec

#

the data populated in my screenshot is just our local db instance of what's in the stripe account under statement_descriptor (corresponds to descriptor in our DB)

regal gate
#

that makes no sense ๐Ÿ˜“

#

if it was on the Account it would have nothing to do with Link

stark rune
#

so we sync data from Stripe to our local database

#

let me DM you some more stuff

regal gate
#

Sorry you keep going on tangent that aren't relevant

#

I get it, you are trying to give info but none of that is what I need I am certain of that

#

You shared a screenshot of rows of payments. Some have an empty descriptor. It'd make no sense that this value came from the Account API Resource acct_12345
It must come from either the Charge, the PaymentIntent or the Invoice.

stark rune
#

give me a bit

#

the issue is the data for descriptors got wiped on our side because we sync state with stripe

#

so i have to hunt it down in a different silo thats hard to query

regal gate
#

I did go and look at one of those accounts and their Charges from a week ago. I spot-checked 20 Charges by hand by looking at the charge.succeeded Event that would not have been mutated in any way and they all have null

I am fairly confident you are mixing up statement_descriptor and calculated_statement_descriptor on Charge for now

stark rune
#

Are you able to see if changes went into how statement_descriptor is exposed via API for Link charges within the last 48 hours?

#

I can run a query that shows this definitely stopped getting exposed - I can show if the statement_descriptor field is null for charges where wallet == link over time

regal gate
#

Sadly with the currently description I have no idea where to look

#

Like this is subtle and you use really specific words but it's unclear if you mean them

#

Like for example wallet == link to me would mean that you have a Charge object where the PaymentMethod object (pm_123) that was used has type: 'card' and then inside that we model Link as a wallet.
This is completely different from a PaymentMethod that has type: 'link' and those are modeled differently in our API

stark rune
#

Okay could you explain the difference between these two?

#

Here's the query I'm running:

  DATE("transaction_date") AS day,
  COUNT(*) AS total_count,
  COUNT("descriptor") AS descriptor_not_null_count,
  COUNT(*) - COUNT("descriptor") AS descriptor_null_count
FROM "direct"."common_charge"
WHERE "wallet" = 'link' AND "status" = 'succeeded'
GROUP BY DATE("transaction_date")
ORDER BY day DESC
LIMIT 300 OFFSET 0;
#

My understanding is wallet=link would guarantee its a card payment and should have a statement_descriptor (as non-card links could be bank transfers with no descriptor)

regal gate
#

(typing, will take a while)

#

Link is our payment method. We have 3 modes

  • Link as a PaymentMethod type, where it has type: 'link' and abstracts the underlying payment instrument, you don't know if it's a card or a bank account or klarna, you just know they use Link, like with Klarna and such. In that case the Charge has payment_method_details[type]: 'link'
  • Link can also be used to prefill card details on websites/merchants that don't accept Link and only accept cards. So those integrations expect type: 'card' in the API so in that case we still use Link for the consumer paying you but to you it looks like they used their card to pay you. In that case the Charge has payment_method_details[type]: 'card' and payment_method_details[card][wallet][type]: 'link'
  • Link can also be used to pay with bank account details and make it look like a card payment to integrations that only expect cards. In that case the Charge has payment_method_details[type]: 'card' and payment_method_details[card][wallet][type]: 'link' and payment_method_details[card][brand]: 'link' . That one is rare and unlikely to be relevant here
#

So now in terms of statement descriptor

Option #1 will not have calculated_statement_descriptor
Option #2 will have calculated_statement_descriptor

#

At this point I would like to see your code that updates the database. I want to see the exact bit of code that reads the Charge API

stark rune
#

ok

#
        return CommonChargeDirect(id: id, transactionDate: created, amount: Double(amount ?? 0), currency: currency?.rawValue ?? "usd", refunded: refunded ?? false, descriptor: calculatedStatementDescriptor ?? statementDescriptor ?? "", customer: customer, status: status?.commonStatus ?? .Succeeded, last4: last4, bin: bin, wallet: wallet, source: .Stripe, chargeId: id, brand: brand ?? .Unknown, funding: funding, accountId: accountId, riskScore: riskScore, userId: user.id ?? "", issuer: issuer, customerEmail: customerEmail, authorizationCode: auth, streamId: stream.id,
#

we use calculatedStatementDescriptor and fallback to statementDescriptor when its null

#

is it possible that statementDescriptor got nuked?

regal gate
#

ding ding ding I was right

#

descriptor: calculatedStatementDescriptor ?? statementDescriptor ?? "" you are literally starting with calculatedStatementDescriptor which I tried to explain a couple times earlier

#

It might not be the exact answer and we still need to dig but it's the bit I kept asking about because it's so subtle

stark rune
#

ok

#

good find

regal gate
#
Option #2 will have calculated_statement_descriptor```
stark rune
#

how about for statement_descriptor?

torpid coralBOT
regal gate
#

hard to say, there's still really obvious questions not answered since the start

stark rune
#

ok

regal gate
#

It's okay we'll get there but that's wy I keep pushing to answer my exact questions and not look at "alternative/unrelated things"

stark rune
#
  if (paymentMethodDetails?.type == .link) {
            wallet = .Link
        }
#

thats how i define if it's link

regal gate
#

So your code literally looks at calculated_statement_descriptor by default. This value is always null for Charges that don't have payment_method_details[type]: 'card'.
Always always null.

Now your original question is not that. You are certain we removed the values from old Charges. That is possible though unlikely. And I need a real example that I can look at which for now has not been shared. All the examples you did share had a valid explanation as to why it's null.

stark rune
#

ok fair

#

I fallback to statement_descriptor in the event calculated is null. So I'm guessing calculated was always null and my fallback is no longer being populated

regal gate
#

So next step is to find a clear example Charge object that is not for a card and has statement_descriptor currently null but it was not null before.
I believe that is impossible based on this thread and it's more likely that what changed is that something caused your integration to suddenly get the new version of Link

stark rune
#

are you able to query a charge_id from the actual statement descriptor if I provide the account_id? That would give us an example

regal gate
#

not if it's not a card payment

stark rune
#

assuming it's a card payment but in category [1] where the actual method has been abstracted

regal gate
#

then no, because then it's not a card payment and I am fairly certain all 3 properties in the API would always be null
calculated_statement_descriptor
statement_descriptor
statement_descriptor_suffix

stark rune
#

Hmm, so you're saying all card payments that are Link should have one of these fields non-null, correct?

regal gate
#

what does "all card payments that are Link" mean?

stark rune
#

prefilled card via link

regal gate
#

then yes

stark rune
#
Link as a PaymentMethod type, where it has type: 'link' and abstracts the underlying payment instrument, you don't know if it's a card or a bank account or klarna, you just know they use Link, like with Klarna and such. In that case the Charge has payment_method_details[type]: 'link'
``` This with the method being card
regal gate
#

๐Ÿ˜“

#

you literally quote the one that says it's not card but saying it's card. Also you say "method" do you mean PaymentMethod?

stark rune
#

in this quote you are saying the actual funding method is abstracted

#

which means it could be Klarna, something else or a card

regal gate
#

you mean payment instrument not method or funding method? At least in my sentence?

stark rune
#

So by funding I mean the funding source of the underlying Link payment is a card (which has been abstracted)

regal gate
#

Sorry it's so subtle that I am extremely strict with the vocabulary because it's so hard otherwise since it's all a card to humans thinking about this

stark rune
#

In paypal parlance the funding method is what's used to fund the wallet - its abstracted and not exposed to customers

regal gate
#

If the Charge has payment_method_details[type]: 'link' then calculated_statement_descriptor will be null. Always has been like this

#

Yeah sorry I know other companies use different words, that's why I try to outline the exact ones I use so that we're aligned.

#

don't get me started on calling a payment method Link for example ๐Ÿ˜‚

#

To explain with more words what I was saying earlier

  • calculated_statement_descriptor is our own calculation of what was really sent to the card network. It's only set for real card payments where the Charge has payment_method_details[type]: 'card'. It will always be null for everything else, including payments via Link with payment_method_details[type]: 'link' even if the payment instrument (what you call a funding source) was a card. We just don't show the calculated value.
  • statement_descriptor this is only set if statement_descriptor was set explicitly either on the Charge creation, original PaymentIntent or Checkout Session or Invoice, whatever controls the Charge creation. Otherwise it is null, it doesn't inherit the account's default value, it's just null in the API
    statement_descriptor_suffix this is only set if statement_descriptor was set explicitly either on the Charge creation, original PaymentIntent or Checkout Session. Otherwise it is null, it doesn't inherit the account's default value, it's just null in the API. It also can't be controlled with an Invoice
stark rune
#
  "id": "py_3RdtHODDdhNYBUte1dzotX9E",
  "object": "charge",
  "amount": 4999,
  "amount_captured": 4999,
 
  "application_fee_amount": null,
  "balance_transaction": "txn_3RdtHODDdhNYBUte1IU8EfKr",
...
  "calculated_statement_descriptor": null,
 
  "fraud_details": {},
  "invoice": "in_1RdsKQDDdhNYBUtej6tcwLKE",
 
  "paid": true,
  "payment_intent": "pi_3RdtHODDdhNYBUte1g6K1b9r",
  "payment_method": "pm_1RbKz7DDdhNYBUtegW92fTBj",
  "payment_method_details": {
    "link": {
      "country": "TH"
    },
    "type": "link"
  },
 
  "source_transfer": null,
  "statement_descriptor": null,
  "statement_descriptor_suffix": null,
  "status": "succeeded",
  "transfer_data": null,
  "transfer_group": null
}```
#

So this is definitely a card here, I'm nearly certain

regal gate
#

Sure but that's what I keep explaining. It doesn't matter at all that the payment instrument, what you call a funding source, is a card. To the API this is a payment via Link so what I explained above (and said a few times) fully applies

stark rune
#

^ ok the above is helpful

#

so I see part of the "issue" here which makes this very confusing

regal gate
#

It is subtle. And at this point I can be candid: it is so frustrating we don't populate calculated_statement_descriptor. There are literally 3 or 4 jiras internally from me begging the product teams to finish this and add it but alas here we are

stark rune
#

an API request is made to update the descriptor after the charge is created and so all rebills even on these links will have calculated descriptors

regal gate
#

an API request is made to update the descriptor after the charge is created and so all rebills even on these links will have calculated descriptors
what does that mean "all rebills"?

stark rune
#

"subscription update"

#

"description": "Subscription update"

regal gate
#

You mean future Invoices for the Subscription?

stark rune
#

if the charge was created through a sub update rather than first time purchase the calculated_descriptor field populates

regal gate
#

Those future Invoices will also not have anything unless you properly set statement_descriptor on each Invoice before payment is attempted

stark rune
#

It is subtle. And at this point I can be candid: it is so frustrating we don't populate calculated_statement_descriptor. There are literally 3 or 4 jiras internally from me begging the product teams to finish this and add it but alas here we are
Anything I can do to push this forward let me know

regal gate
#

sadly no, I have a loud voice internally, it's just really hard

#

Let's refocus: you were certain earlier we nuked the data on existing/previous Charges. Are you mostly convinced that this was incorrect?

stark rune
#

It's hard to say

#

we have several tickets coming in today that were related to this so I assumed somethign chnaged and when I looked at the data it looked very differnt but im not convinced

#

I'm mostly convinced but not completely

regal gate
#

yep that's fair. That's where I am right now ๐Ÿ™‚

#

I'm happuy to debug this further. I just want to close down certain parts of the discussion

stark rune
#

yep can close this one out. I shot you a DM as well ๐Ÿ™‚

regal gate
#

Right now it could be either

  1. We changed something, to prove it we need a recent Charge object that is > 30 days old and I can compare the Event and what the API says
  2. Something changed in your integration and some merchants are now getting payment_method_details[type]: 'link' and never had that before

Is it easy for you to confirm if it's #2?
Happy to just drop it too if you prefer

stark rune
#

we can drop it for now - going to monitor closely

#

we can prove #1 at some point potentially

#

really appreciate your help on this. you know your stuff