One problem I see with Bitcoin URIs is that it's impossible, as a customer, to prove ex-post-facto that you made a payment (a) to a specific entity or (b) for a specific purpose. While you may trust that a Bitcoin address/URI belongs to a vendor based on the fact it was presented via SSL on that vendor's page, once you've made payment you have no mechanism to prove that (a) you saw that URI on the vendor's page, (b) you made payment for any specific purpose, or (c) you paid the amount in full. In short, there's nothing to enforce non-repudiation of a vendor's Bitcoin URI invoice once payment is made. In other words, it's easy to create an invoice, but how can a customer show a receipt that's provably from the invoice?
It occurs to me that we already have infrastructure in place to address this-- SSL. (SSL ain't perfect, but it's way better than nothing.)
Since the URI for a Bitcoin payment (BIP 0021) is intended to be extended, I propose this:
The vendor MAY append two (or three*) fields to the end of a URI: "sigdomain", and "sig". "sigdomain" indicates the DNS name where the SSL public key can be retrieved that verifies the signature of the transaction, and "sig" is the Base-64 encoded SHA1RSA signature of the URI up to and including the "=" sign after "sig". ("sig" MUST be the last field of the URI.) If "sig" is used, then "sigdomain" MUST also be included.
Example:
bitcoin:1NYTSZeZ6axJhnR41AfxxB4ks5fEgkjDQ8?sigdomain=darylb.net&sig=b9FUOZOmvlIYAMD6FH4mTw9fipCLi8WSnN9laSg%2BlRagU5EwHe9VFN0NlX1B%2FKKNtcKlbqBel1C4WOh9bH2uibg5eNKBwDXUWenLk%2BT3i5G5iUn0uG5SNtz69zOYAloFRn5E8CAFXElqoBFj24XcU6tgRJuFv7EwFMGiNhenaauHaohB8sYr8HNKqoeLC5zMbG9sB%2FCy%2F8N3Vj7QSFYh4bQt4W%2FJI%2Fai8Fq4E7U%2FEUHR%2BHINb%2FX%2FSwUxXMva6LuDRQq%2FzhhNUFmbtd1ahne%2FF%2FADm8UQMM1LPj%2FZMtbpE6EUEW5%2BVkFYiaK2tOIBauQb%2FbrstOcIkxZgS7VdC3%2BQgw%3D%3D
Or:
This address has been signed using the private key corresponding to the public key that's available by connecting to "
https://darylb.net". The client SHOULD store the public key cert along with the invoice, so that signature verification is replayable even if the server's key is replaced.
Granted, this makes for a rather dense QR code, but with a 4.2k hard limit for alphanumeric QR codes, it's not approaching the maximum.
Clients unaware of Bitcoin Invoice Signatures (BIS) will simply ignore the added data; but clients that are aware of BIS can present (a) all of the fields included, and (b) the value of sigdomain (or optionally the Distinguished Name that the cert was issued to) and (c) the fact that the vendor has signed the transaction AND that the client has validated that signature.
In the case of a payment dispute, the customer can present the original Bitcoin Invoice URI, and prove that their payment was made through the public blockchain. The URI in this case becomes both the invoice /and/ the receipt.
*Expiration: to limit the valid time for invoice's payment, a vendor MAY add a field labelled "sigexpiration" can be added before the "sig" field, which will be yyyymmddHHmmss encoded, and in the UTC time zone. (HH is using a 24-hour clock.) Clients SHOULD translate that time to the time zone of the user, and MUST NOT allow payment to be submitted after that cutoff. (Payments confirmed after the cutoff become a dispute outside the scope of this proposal.)
I'm aware of BIP 0070, but this is far more lightweight, is usable offline, can be implemented in a relatively short period of time, and won't break existing Bitcoin clients.
Java source code for this:
https://github.com/dbanttari/bitcoin-invoice