w3c / payment-request

Payment Request API
https://www.w3.org/TR/payment-request/
Other
489 stars 135 forks source link

Modifiers and [[serializedModifierData]] not actually used anywhere. #753

Closed marcoscaceres closed 5 years ago

marcoscaceres commented 6 years ago

Following on from #684, there are a bunch of huge issues in the spec relating to modifiers:

I'm again strongly inclined towards dropping modifiers in favor of something else. They are super broken, underspecified, and unnecessarily complicated.

marcoscaceres commented 6 years ago

Err... that should have been "serializedModifierData"

domenic commented 6 years ago

FWIW the serialization was evolved from an earlier revision that checked if the objects were "JSON serializable". Assuming that's still a desirable property in the abstract, I remain convinced that serializing and passing to the payment handler spec is the right way to spec that property.

I'm less informed about the general question as to whether modifiers are worth keeping.

marcoscaceres commented 6 years ago

I remain convinced that serializing and passing to the payment handler spec is the right way to spec that property.

I don't mind so much (specially if a payment handler JSON.parse()s on the other end) - but we still have the problem that you get the wrong data. That's fixable by using tuple(PMI, serializedData) - as it's done with [[serializedMethodData]].

But the larger question of conversion kinda remains, as does [[serializedModifierData]] not actually being applied.

marcoscaceres commented 6 years ago

I’ll send a patch to address some of the above.

stpeter commented 6 years ago

Receiving a jumble of all the data for all the payment methods is bad enough, but I'd agree that there are even bigger problems with modifiers - I wonder if the feature can even be implemented reliably, let alone interoperably...

marcoscaceres commented 6 years ago

From my testing today, Chrome Desktop does not seem to apply modifiers correctly. It seems to think a debit card is a credit card, and thus the modifiers applies the wrong total.

@zkoch, is this a known issue?

marcoscaceres commented 6 years ago

The test code is here: https://pastebin.com/Fjn9CK4P

The card I'm using is "debit" (identified as such via BinDB, and on the card itself). But still modified as a credit card.

rsolomakhin commented 6 years ago

Thank you for the pastebin link, @marcoscaceres. Did you add the card through chrome://settings/autofill or through https://payments.google.com? Only the latter has access to BinDB. If you add a card in chrome://settings/autofill, then it's marked as "unknown" card type, so it will not match the ["debit"] filter that you've specified. This is a quirk of Chrome's implementation.

adrianhopebailie commented 6 years ago

@marcoscaceres the whole purpose of modifiers was to preserve user privacy. It's possible that the feature, as specc'd has gotten very stale, and needs some love but I don't think we want to throw it out entirely.

The alternative is that the merchant must be provided with a lot of the user's data based on interactions the user has with the sheet.

It is difficult to assess the usefulness of modifiers when only using different variations of basic-card as the data used in the "filters" (credit vs debit) is proprietary and browsers will have varying degrees of accuracy in evaluating the modifers (as @rsolomakhin has pointed out).

The more relevant application of modifiers will be when a user has the option of paying with different methods entirely and these have different price implications, e.g. basic-card vs sepa-credit-transfer. The costs to the merchant of accepting these different forms of payment are highly competitive so it seems likely that merchants will want to pass some of that difference onto users to entice them to use cheaper payment methods.

stpeter commented 6 years ago

@adrianhopebailie Your point about different methods implies that we really need to clean up how modifiers work, because as @marcoscaceres points out "serializedModifierData gathers all the data from EVERY modifier" and sends them along as a big blob. We'll need to define things more cleanly so that merchants and users can truly compare costs across methods.

marcoscaceres commented 6 years ago

@marcoscaceres the whole purpose of modifiers was to preserve user privacy. It's possible that the feature, as specc'd has gotten very stale, and needs some love but I don't think we want to throw it out entirely.

Ok, but the problem remains that we can't distinguish between card types (only networks). So it makes the feature unreliable.

While it protects privacy, it's kinda useless because we can't guarantee that the total shown to the user is the total they will be charged. That seems like a deal breaker to me.

The core of the problem is that BIN databases are quite unreliable (~10% error rate). Our user research is telling us users can't reliably differentiate between their debit and credit cards, so this puts us in a bad position (where both users and BIN data still result in unacceptable error rates).

So, the only sensible solution seems to be to pass a card's BIN number back to the merchant, and for them to figure out what kind of card it is.

Open to other suggestions here, but, for basic card, this is a show stopper.

adrianhopebailie commented 6 years ago

The core of the problem is that BIN databases are quite unreliable (~10% error rate). Our user research is telling us users can't reliably differentiate between their debit and credit cards, so this puts us in a bad position (where both users and BIN data still result in unacceptable error rates).

@marcoscaceres I agree that the core problem is unreliable BIN data.

So, the only sensible solution seems to be to pass a card's BIN number back to the merchant, and for them to figure out what kind of card it is.

Unfortunately I don't think merchants will be any better at determining a card type than anyone else. They don't have access to any better data. The reality is that for many years this data has been treated as semi-private by the card networks and there are country-specific lists maintained by payment associations in each country with further granularity so unless you have special privileges and a global footprint you likely won't have anything better than what is in the public domain.

While it protects privacy, it's kinda useless because we can't guarantee that the total shown to the user is the total they will be charged. That seems like a deal breaker to me.

I think this is specific to the difficulty of determining card types and the basic-card payment method. If we design the payment handler spec correctly the data required to make an accurate price calculation should be provided by payment handlers at registration so there is no ambiguity.

By offering a "built-in" payment handler for basic-card, browsers have taken on the burden of needing to determine the characteristics of the cards they store (and offer as payment instruments).

In my opinion this is an implementor challenge. If the card networks want browsers to offer basic-card in a way that is reliable they need to find a way to provide them with the data to do that. That seems like an easier challenge than trying to provide that data to every merchant.

ianbjacobs commented 6 years ago

Hi @marcoscaceres and @adrianhopebailie,

I have pinged our card network friends to see what guidance they can provide here.

marcoscaceres commented 6 years ago

Agree that payment handler enrolment solves for this (Apple Pay does this beautifully, with full bank integration, etc.).

In my opinion this is an implementor challenge. If the card networks want browsers to offer basic-card in a way that is reliable they need to find a way to provide them with the data to do that.

I’ve reached the same conclusion - or we ditch the whole card type thing.

If merchants (or payment processors) really can’t process certain card types, then they do have a way of identifying card types that they cannot process. So, there is clearly some way for merchants to handle this, because otherwise they can’t get paid.

The above is ugly, but clearly it already works like this on the web. Hopeful we can find an interoperable solution.

adrianhopebailie commented 6 years ago

If merchants (or payment processors) really can’t process certain card types, then they do have a way of identifying card types that they cannot process. So, there is clearly some way for merchants to handle this, because otherwise they can’t get paid.

I suspect that in most cases they only find this out after submitting the payment

mountainhippo commented 6 years ago

This feature of filtering on specific card networks and card products is difficult and inconsistently implemented across the industry. As @marcoscaceres has pointed it, the place to solve for it is probably in privileged payment handlers where (in the case of ApplePay, for example) the payment instrument (card number) is being tokenised and in that process, there's a direct channel for that enrolment which allow extra data like card product identifiers to be passed. Even then, tokenisation has fragmented the established BIN ranges for card products and networks - there has been some discussion of doing essentially PAN level card product identification but in practice this might require an extra step in any card process (the simplest way of imagining this is by thinking about an additional call to the gateway/PSP/acquirer when a card is inserted in a terminal or a PAN is entered into a form, where the response is simply "this is the kind of card that is represented by the PAN").

IMO, the best we can do in the generic basic-card case is to check against static BIN tables (each browser or other payment handler implementing their own solution) and then to handle any errors gracefully, the two major cases being:

  1. False positive: filter prevents some card from being presented as a choice to the user (solved by a "where's my card?" flow in the browser/handler,
  2. False negative: card credential goes back in the payment response which the merchant cannot or will not accept (catered for on the merchant side with a payment failed, please try again message. The merchant may not actually know that they cannot accept that particular combination of network/product type - it depends on the richness of the API they are consuming from their provider)

As @adrianhopebailie already said, I think the broader feature of filters is useful but might have got lost a little in the focus on basic-card

stpeter commented 6 years ago

We talked about this topic in the working group meeting earlier today. What I heard is that it's really not possible to definitively determine the card type in real time. For instance, for Mastercard the card might be identified as Maestro first, debit second, credit third. The business logic dictates that an application run through those options in that order, where credit is the fallthrough if the others don't work out. However, this decision process might not occur in real time (e.g., it could happen overnight during clearing).

Given this information, we need to figure out if it is realistic to support card type matching and type-based modifiers. I tend to think it isn't - certainly not in a way that enables the browser or payment handler to show helpful UI hints before hitting "Pay" at the end of the workflow.

marcoscaceres commented 6 years ago

I tend to think it isn't

I agree. If we can't reliably show totals to our end-users, this is not a feature we would feel conformable supporting in Firefox (we will just throw an error if someone passed data along for basic-card).

ianbjacobs commented 6 years ago

Per my action item, I reached out to Stripe regarding Basic Card and demand for differential pricing. I heard back "Stripe hasn't had demand for differential pricing between debit/credit cards in Payment Request."

marcoscaceres commented 6 years ago

@ianbjacobs any idea who actually needs this then?

Krystosterone commented 6 years ago

Reporting in about my action item: https://www.w3.org/Payments/WG/track/actions/103

I'll split this into two sections:

  1. Amount management based on card brand / bin / networks, etc...
  2. Card brand filtering (not related to modifiers but might serve as context for some)

Amount management

We have two use cases for charging people on our platform: Shopify charges the Merchant and Merchant charges the Buyer. In both cases, we do not change the amount that is charged depending on BIN data information. Researching this a bit further (and if I remember correctly, this was mentioned on our last call for the EU), this might actually be illegal (see here)

Charging the merchant

Though we don't charge the merchant different amounts depending on their card, we do manage our own BIN data table in order to do some analysis on the card being used.

Charging the buyer

As mentioned, we don't allow the merchant to charge differently depending on the card's BIN data. We do however charge the merchant different fees depending on the card the buyer used.

Card brand filtering

For the buyer's purchase experience, we do need to filter out card brands that are either not accepted by the merchant or the payment processor. This is not done using BIN data, rather a set of regexp's akin to https://github.com/stripe/jquery.payment/blob/master/lib/jquery.payment.js#L21-L93. This is to say that modifiers would not be leveraged for us but supportedNetworks from the basic card spec would be necessary.

marcoscaceres commented 6 years ago

Ok, so it sounds like we could drop card type for Basic Card - but keep network. That seems reasonable.

ianbjacobs commented 6 years ago

@rsolomakhin, @zkoch, @adrianba, @rvm4, do you have a preference for:

Thanks!

rsolomakhin commented 6 years ago

This sounds like a purely product decision, so I will let @zkoch or @DurgaTheHutt to make the call for Chrome.

ianbjacobs commented 6 years ago

@marcoscaceres indicated that the current issue has several parts. Some of those parts involve a few PR API issues that can be fixed straightforwardly. We have called out separately [1] the question of whether to drop supportedTypes, which I anticipate we will discuss at TPAC.

[1] https://github.com/w3c/payment-method-basic-card/issues/59