RFC 8905 – The 'payto' URI Scheme for Payments
tools.ietf.org
tools.ietf.org
• It allows commas, which will just be stripped on execution. This feels like it’s just inviting errors unnecessarily, especially given that some parts of the world use comma (,) as their decimal separator and full stop (.) for grouping, rather than the other way round. I see no compelling reason for allowing grouping at all.
• “The 'unit' value MUST be smaller than 2^53. If present, the 'fraction' MUST consist of no more than 8 decimal digits.” Both of these feel a mite surprising, and the combination of them far more surprising. The 2⁵³ limit is doubtless to allow it to be safely stored in a 64-bit floating point number, specifically for JavaScript’s sake; but (dealing with this part first) do you know how small 2⁵³ is? 9 quadrillion. That’s honestly not that large. I’ve handled a 100 trillion dollar note, and that’s hardly the highest any currency has ever gone. (Admittedly, the sorts of currencies where this is happening probably have limited use for a payto: URI scheme at the time.) But anyway, skipping onto the second part, a fraction of up to eight digits. Skipping over the apparent arbitrariness of the number (which happens to match Bitcoin’s division), if you’ve made concession to treat the unit as a Number, what about the fraction? If you wanted to retain eight decimal places of significance, you’d be limiting your unit to 2⁵³ ÷ 10⁸, about 90 million, which is obviously too low, so you clearly can’t be meant to be representing the whole thing as a Number, so why that restriction on the unit? So yeah, both of these limits simply feel weird to me.
But other than these quibbles, I say: finally! I’m really glad about this and hope it gets adopted by banking apps and the likes quickly, and added to the HTML spec’s safelisted schemes (https://html.spec.whatwg.org/#safelisted-scheme) so that banks’ web apps can also navigator.registerProtocolHandler("payto", "https://bank.example/payto-handler/%s") soon. And also that Australian banks either register some way of addressing their accounts as a payto payment target type, or adopt IBAN.
Omitting a comma turns an amount with Euro Cents to 100 times the amount here in Germany. I can both see this comma/dot problem be missed in development and can also imagine such a payment go through, as a few digit amount times one hundred still gives an amount that people can have in their bank accounts. Users clicking through confirmation dialogs and dismissing wrong information as 'computer problems' is not an unheard-of problem either.
This is really inviting trouble - without good reason? - as a payment 'API' having to deal with how a number was displayed to a user seems out of scope for it.
This reminds me of a bug I happened to come across with a cheap offshore company I had to deal with a while back (well, a very expensive consulting company that used a very cheap offshore company for development). We were dealing solely with Pound Sterling (100 pence make a pound). As part of the API requirements, they were asked to solely deal with pence in integers. They ignored the requirements and used pounds in floats.
This caused rounding errors here and there. We spotted the problem as soon as we heard about the rounding errors, and asked them to correct it. Later on, our customer asked us why the items that cost £1.85 were being charged correctly, but the items that cost £1.90 were being charged at 19p.
Turns out that rather than doing anything sensible, they took the float, converted it to a string, stripped out the period, then converted the string to an integer. So £1.85 became "1.85", then "185", then 185p, but £1.90 became "1.9", then "19", then 19p.
They managed to put this into production before we had a chance to see it. Yes, it was a dysfunctional project. But there’s lots of them out there. If you leave a footgun like this lying around, there’s no end of companies that will not only shoot themselves in the foot but happily reload while you are scrambling to stop them.
This simultaneously made my day much better, and much worse.
So no, practically speaking, this absolutely does not get caught right away. And if the specification is this sloppy, it should be thrown out and redone.
Just curious does any country use fractions of a bill other then 1/100 (ie cents)
https://www.marketplace.org/2018/10/11/why-do-gas-prices-end...
I'd be interested to hear if anyone else has seen any digit other than nine in the tenth-of-a-cent column though.
The whole concept involved here is called psychological pricing (https://en.wikipedia.org/wiki/Psychological_pricing). I wish it was illegal.
"Falsehoods programmers believe about prices"
Other currencies do not have a fractional part at all and use just one integer.
If you don’t need to work with the value, store it in a string. If you do, use a proper decimal type. (Your question may then apply to the internals of the decimal type, but the point is that that should be transparent to the developer accessing the decimal value.)
This RFC is woefully underspecified, and the fact that there's an amount of its already-small specification devoted to "7.5. Bitcoin Address" makes me question their priorities and destroys a lot of confidence in the proposal.
I think that is a far too generous read of the document. I think it's because they wanted you to be able to use a JS Number to store the value, which is the Wrong Thing To Do. In fact, using two BigInts to separately represent the fractional and whole pieces of the currency would be far better.
This is the kind of ambiguity that I refer to when I say this is underspecified.
IMHO if they had a choice between dropping Javascript support in preference of languages with BigInt support, or dropping support for payments larger than $45 trillion, they probably made the right decision.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
On the Bitcoin part: that’s just putting an entry in the registry, a perfectly reasonable and normal thing to do in such a specification. They’ve included entries for four of the main traditional banking systems, and two of the main new-generation systems that people are sure to want to combine this with.
1. It doesn't seem like there's any callback mechanism. Once I transfer money, the source has no knowledge of that. If this is used for an invoice, the invoice needs to wait for the transfer to happen on the back-end for the source page to become aware that it happened. There seems to be no possibility of a "thanks for paying" URI that can be triggered after payment. This limits practicality for non-donation payments.
2. Each payto URI represents one payment method. Any payee who wants to accept money in one of a few different payment methods must provide separate URIs. This offloads the burden of knowing _how_ to pay to the user. If there's a list of five payment methods (as five payto URIs), I need to be aware of which ones I have apps for that my user agent can interact with. Some may trigger an error. Versus another world where I click a single link (payto URI) representing five payment methods in one and my user agent asks which app/account/etc I want to pay from.
'opt-value' is specified as any amount of 'pchar'[0], which includes both '&' and '=' (the delimiters between opts, and between opt-key and opt-values, respectively).
So in order to parse a payto-link, you either go eager and have only one option in the string, or lazy and my valid opts 'description=Food & drinks' will error out on a missing value for the ' drinks' authority-specific option, or go nuts and have parser-specific behaviour.
[0] pchar as defined in https://tools.ietf.org/html/rfc3986#appendix-A
Well, the IETF is volunteer-based, so if you feel strongly enough, go submit a comment! :)
But as regards this particular RFC, the key details that are terribly easy to miss are right at the start:
• Independent Submission
• Category: Informational
In other words, the IETF is not “vouching for” this thing as they would be on standards track RFCs. (Another hint at this is that the registry the RFC establishes is established with GANA rather than IANA. And the URI format; I suspect that if it went through the full standardisation process it’d be pushed to payto:authority:path rather than payto://authority/path, the // style of URI being strongly linked with DNS resolution.)
(I completely forgot to check this when I first read the spec, and I’m used to reading these sorts of specs and checking their status. Read my earlier comments bearing this in mind.)
If you’re dealing with a web app registering itself as a protocol handler, the scheme is the highest precision you get: navigator.registerProtocolHandler("payto", "https://bank.example/payto-handler/%s"). So there, you only get the protocol level of granularity. You might therefore set up bank.example and bitcoin.example, and now when you click on a payto: link, the browser will say “do you want to open this link with bank.example or bitcoin.example?”
On mobile platforms, I’m not certain, but you may be able to have the bank app only register for payto://iban/ (and any other payment authorities it supports) and the Bitcoin app only register for payto://bitcoin/.
payto:stripe.com/pk_PU1qgJjo2yW1to?amount=USD:100.0&message=Box+of+chocolates
It seems weird to leave payment gateways out of consideration, but maybe I'm not understanding the purpose of this RFC.`<button data-payto="payto://iban/123456789">pay with stripe</button>
then you use stripes javacript library to handle it. if you do this you can trivially use multiple gateways at the same time in a flexible way.
For Stripe, this scheme is sort of irrelevant. If Stripe wants to offer the ability for someone to transfer money to an IBAN (or any other account identifier) through a webpage, they can just...do it. They don't need a URI, they just have a JS function which triggers a payment flow.
The pull model is where I provide you with my details, and you draw money from me. Credit card numbers are the best-known mechanism for this. Ecommerce uses the pull model almost exclusively, because it lets the retailer confirm the payment and start the next step (fulfilment of goods) immediately.
The push model is where you provide me with your details, and I send money to you. This is seldom used for ecommerce because it requires reconciliation, for you to observe that you have received the money (which may take a greater period of time, depending on the systems involved—a lot of the world still operates on nightly clearing) and correlate payments with orders. This is used for much more casual things like people sending money to one another, or for larger amounts of commerce where transaction fees are much lower this way and maybe you don’t actually need the payment to be confirmed today.
For the pull model, your payment provider needs to know how to take money from the account details I provide. Sometimes this doesn’t work out, e.g. if someone has an American Express card but the merchant only accepts Visa and Mastercard.
For the push model, each sender needs to be able to target money to the account details the recipient provides. For example, I may be able to send to an Australian bank account by BSB and account number, but if you give me an American bank account, I won’t be able to pay to it directly but will have to figure out some kind of international transfer, potentially involving routing it through a third party.
The payto: URI scheme is the push model. For payto://stripe.com/… to make sense, each person’s bank would need to know how to send money to the nominated Stripe account. But that’s not how Stripe works; Stripe payments operate by the pull model.
In the US, this is going to be used to print checks ;)
The ACH links will be opened by the check printing program to print the check and send it through the mail.
This varies by country - the majority of e-commerce retail transactions here in Finland operate on a push model - in checkout you get redirected to your bank or wallet provider where you login (2FA) and authorize the transaction.
The merchant usually gets confirmation of payment immediately.
In fact I am not sure if there's any other country that likes the "pull" model as much the United States does. Wherever it exists it's there mostly due to historical reasons - in the past it was not possible to quickly validate and push a transfer, so you needed credit card companies to underwrite a small amount of credit (between now and end of month settlement). Kind of similar like how the US is so backwards when it comes to regular bank transfers (good luck using SWIFT). And how the Fed dollar is not exactly the same as the eurodollar. Some countries just like to be special :)
The core design problem I see is that, in terms of the overall use case, it may in practice already often be the case that an existing identifier, not designed for payments, is used to identify the recipient (for example, an email address, phone number or nationally issued personal or corporate identifier) and that the actual settlement method (bank transfer, paypal, bitcoin, physical goods transfer, etc.) is not specified.
However, in this design you see that the settlement method must be specified along with the recipient, which is functionally nearly equivalent to providing (http://closed-system.com/method/specific/URI) thus largely devaluing the payto:// proposal.
A 'real world' use case for global payments: "I want to transfer some value over there": where there is defined, and some value is defined, but the potentially multiple means and steps to achieve the result may be many and varied and depend upon various additional criteria or preferences (cost, speed, trust, volume and asset type limitations, accounting or regulatory requirements, requirement for confirmation of delivery, error handling potential, day of week, time of day, holiday, reversibility, etc.).
Additional design problems are that there is no transaction or invoice identification system specified which will deeply frustrate customer service/auditing/reconciliation, temporal limits are not possible to specify, and that the approach of shoving all required metadata for a transaction in to generic fields without specifying their formatting is going to cause havoc with all sorts of use cases particularly the disparate allowable character ranges of thousands of banks' various AML/KYC field requirements for SWIFT transfers.
I also note that the proposal comes from Switzerland (home of SIX/SWIFT) and that its de-facto enforcement of ISO4217 effectively holds users of the protocol hostage to that central authority in terms of which currencies/asset types they are allowed to trade in.
I would further suggest that any good faith global payment schema proposal should at least include https://en.wikipedia.org/wiki/WeChat#WeChat_Pay_digital_paym... https://en.wikipedia.org/wiki/Alipay https://en.wikipedia.org/wiki/UnionPay
For a deeper exploration of the transaction area see the unfinished proposal IFEX @ https://raw.githubusercontent.com/globalcitizen/ifex-protoco...
For an alternative approach to internet based financial endpoint identification see IIBAN @ https://tools.ietf.org/html/draft-stanish-iiban-01
For a broader asset type identification system that does not bar innovation, see X-ISO4217-A3 @ https://tools.ietf.org/html/draft-stanish-x-iso4217-a3-01
Thinking about it it's also pointless to have multiple target types. Most traditional banks can only do IBAN or ACH. Although digital ones like Monese, Transferwise and Revolut can do any so maybe there's some merit for them.
This isn't hypothetical. It happens.
> In an attempt to prove that the public furore over the 2007 UK child benefit data scandal was unjustified, [Jeremy Clarkson] published his own bank account number and sort code, together with instructions on how to find out his address, in The Sun newspaper, expecting nobody to be able to remove money from his account. He later discovered that someone had set up a monthly direct debit for £500 to Diabetes UK.
However, you are certainly right in that the current ad-supported model is driving engagement, or, should I say, “enragement” clicks, which is certainly not doing much good.
One interesting follow up question in who covers the processing fee (e.g. the ~3% or so that Braintree or Paypal currently take)? Today, processing fees are mostly hidden to the user. If the user can chose their own payment processor, will they be required to cover the processing fee instead of the merchant?
To me, this sounds dangerously close to the argument for the W3C standardization of DRM in the browser. I remain wary.
For IAPs, you have the Payment Request API: https://developer.mozilla.org/en-US/docs/Web/API/Payment_Req...
Oh yeah, aren’t ACH numbers fraud risks too, if they’re public?
I remember a story about a major German bank who reused an IBAN for one of their treasury accounts and honoured direct debits for quite some time, so there are some risks with IBANs being known in some cases.
I think that removing friction will also make fraud much easier and prevalent.
Why is anyone attempting to put a _standard_ for fscking _payment_ on the _web_ again?
> Interactive applications handling the 'payto' URI scheme MUST NOT initiate any financial transactions without prior review and confirmation from the user and MUST take measures to prevent clickjacking.
Perhaps read the proposal before criticizing it?
You can criticize it for not being detailed enough or it not being realistic for someone to meet the requirements, but the point of an RFC is to say how it should work, not show it working that way.
> Please don't comment on whether someone read an article. "Did you even read the article? It mentions that" can be shortened to "The article mentions that."
I assumed the parent didn't read that part since I assumed that if they did they would comment on that section, but I should not have worded it that way.
But I don't see this solving the acceptance cost problem. At the end of the day, too many people are living on credit, whether due to personal preference (point collectors) or financial need. That means any new API is just going to have to be poured on top of the existing, expensive, complex wedding cake of firms that is credit card acceptance.
It might be nice to see something like FedNow arrive as a low-overhead option, but if you have to discard every customer who can't pay now, you'll also provide a link to a card acceptance option too.
[1]https://www.npci.org.in/sites/default/files/UPI%20Linking%20...
I guess fart app that pushes update to claim URI scheme cannot really do that anymore - only first come first served scheme is enabled. I guess if user uninstalled their banking app and clicked for payment and then fart app appears like your banking app and tries to steal your password...