Skip to content
buybitcoinsmart

Glossary / Developer reference

PaymentRequest

Definition
PaymentRequest is the outer BIP70 envelope: it wraps a serialized PaymentDetails blob together with a certificate chain and a signature, so the payer could check who was asking.

Specified in BIP-70.

PaymentRequest was the message that let a wallet show a company name instead of a string of characters. It had five fields, and the two that mattered were pki_type, one of none, x509+sha256 or x509+sha1, and signature over the serialized details. For anyone paying today the lesson survives the protocol: a name on a payment screen is only as trustworthy as whoever vouched for it.

How it works

Status: obsolete. Bitcoin Core carried PaymentRequest handling from 0.9.0 until 0.20.0 removed it on June 3, 2020, and no maintained wallet parses the message now.

Five fields, in order:

  • payment_details_version, a 32-bit integer defaulting to 1. It was never incremented.
  • pki_type, a string defaulting to "none". The alternatives were "x509+sha256" and "x509+sha1".
  • pki_data, holding an X509Certificates structure with the merchant's leaf certificate first and any intermediates after it.
  • serialized_payment_details, required, the opaque byte string described elsewhere in this glossary.
  • signature, the bytes proving the whole thing came from the certificate holder.

The signing procedure has a small trick in it. The merchant fills in every field, sets signature to empty, serializes the complete message, hashes that, signs the hash with the private key belonging to the leaf certificate, and then writes the signature into the field it had just left blank. A verifier blanks the field again, re-serializes, and checks. Simple, self-contained, and dependent on nothing except the certificate.

That dependency was the problem. Validating the chain required the wallet to hold a root certificate store, which desktop software inherited from the operating system and mobile software frequently got wrong. Even a correct implementation only proved that some certificate authority had attested to a domain name, and a root store contains hundreds of authorities, any of which can issue for any name. The weakest option on offer, x509+sha1, aged especially badly: a practical SHA-1 collision was published on February 23, 2017, four years after BIP70 was written.

Where you see it

Two places still use the name PaymentRequest, and only one of them involves bitcoin.

The first is archived code and documentation, where the BIP71 MIME type application/bitcoin-paymentrequest marked the response a merchant server returned. The second is the modern web platform, where PaymentRequest names a browser API for card and stored-payment checkout that has nothing to do with this protocol. A developer using the word today almost certainly means the browser one, and confusing the two is the single most common mistake in older bitcoin documentation searches.

For someone buying bitcoin, the takeaway is about how identity gets attached to payments. Exchanges solve it with accounts and KYC, so the platform knows who you are and you rely on the platform's reputation. Self-custody solves it by making you check the address yourself. BIP70 tried a third route, borrowing the web's certificate system, and that route is closed.

PaymentRequest vs PaymentDetails

PaymentRequest is the envelope; PaymentDetails is the letter inside it. Reading the envelope tells you who signed and which certificate they used, but not what is being asked for. The amounts, the scripts, the expiry and the memo all live in the inner message, which sits in the envelope as an unparsed byte string precisely so the signature cannot be invalidated by re-encoding. A wallet had to verify the first before trusting anything in the second.

Not to be confused with

Frequently asked questions

Is PaymentRequest the same as the browser Payment Request API?

No, they share a name and nothing else. The browser API handles card and stored-payment checkout on the web. The bitcoin message of the same name was part of BIP70, which Bitcoin Core removed in version 0.20.0 in June 2020.

Did a signed PaymentRequest prove a merchant was honest?

It proved only that a certificate authority had attested to a domain name. It said nothing about whether the goods existed or the price was fair, and any of the hundreds of authorities in a root store could issue a certificate for any name.

Related terms

More in Developer reference