BIP: 70
Layer: Applications
Title: 支付协议
Author: Gavin Andresen <gavinandresen@gmail.com>
Mike Hearn <mhearn@bitcoinfoundation.org>
Comments-Summary: No comments yet.
Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0070
Status: Final
Type: Standards Track
Created: 2013-07-29
这个BIP描述了一个商家和他们的客户之间的通信协议,使客户更好的体验和更好的安全性,以抵抗付款过程中的中间人攻击。
当前,最小比特币支付协议的操作如下:
这个BIP扩展了上述协议,以支持几个新的功能:
这个BIP描述使用Google Protocol Buffers编码的支付协议消息,使用X.509证书进行验证,并通过http / https进行通信。 未来的BIP可能会将此支付协议扩展到其他编码,PKI系统或传输协议。
支付协议由三个消息组成; PaymentRequest,Payment和PaymentACK,并以某种方式从客户开始指示他们准备付款,商家的服务器用PaymentRequest消息响应:
Protocol Buffers消息在 paymentrequest.proto https://github.com/bitcoin/bips/blob/d2a8fb089d7010d839530f879e07edc4e48b84fa/bip-0070/paymentrequest.proto 中定义。
PaymentRequest消息中使用输出来指定应该发送付款(或付款的一部分)的位置。 它们也用于支付消息来指定退款的发送地点。
message Output {
optional uint64 amount = 1 [default = 0];
optional bytes script = 2;
}
字段 | 说明 |
---|---|
amount | satoshis的数量(0.00000001 BTC)将被支付 |
script | 应该发送付款的“TxOut”脚本。 这通常是标准的比特币交易脚本之一(例如pubkey OP_CHECKSIG)。 这是可选的,以便将来对这个协议进行扩展,从主公钥和PaymentRequest数据本身派生输出。 |
支付请求被分成两个消息以支持未来的可扩展性。 大部分信息都包含在PaymentDetails消息中。 它被包裹在PaymentRequest消息中,其中包含关于商家和数字签名的元信息。
message PaymentDetails {
optional string network = 1 [default = "main"];
repeated Output outputs = 2;
required uint64 time = 3;
optional uint64 expires = 4;
optional string memo = 5;
optional string payment_url = 6;
optional bytes merchant_data = 7;
}
字段 | 说明 |
---|---|
network | 在生产比特币网络上支付“主要”,或者在测试网络上支付“测试”。 如果一个客户端收到一个不支持网络的PaymentRequest,它必须拒绝这个请求。 |
outputs | 比特币将被发送的一个或多个输出。 如果outputs.amount的总和为零,则会询问客户需要付多少钱,比特币客户端可以选择任何或全部输出(如果有多个)以进行支付。 如果产出金额之和不为零,则要求客户支付金额,并将金额分配到非零金额的产出(如果有多于一个的产出;零金额的产出应 被忽略)。 |
time | 在创建PaymentRequest时,使用Unix时间戳(自UTC-Jan-1970 UTC以来的秒数)。 |
expires | Unix时间戳(UTC)之后,PaymentRequest应该被认为是无效的。 |
memo | UTF-8编码的纯文本(无格式)注释应该显示给客户,解释这个PaymentRequest的用途。 |
payment_url | 安全(通常是https)可能会发送付款消息(见下文)以获取PaymentACK的位置。 |
merchant_data | 商家可能使用的任意数据来标识PaymentRequest。 如果商家不需要将付款与PaymentRequest相关联,或者如果他们将每个PaymentRequest与单独的付款地址相关联,则可以省略。 |
PaymentDetails中指定的payment_url应至少保持有效,直到PaymentDetails过期(或者如果PaymentDetails没有过期,则尽可能长)。 请注意,这与基础支付请求中的任何状态更改无关; 例如取消订单不应该使payment_url无效,因为重要的是商家的服务器可以记录错误付款以便退还付款。
PaymentRequest是PaymentDetails(可选)绑定到商人的身份:
message PaymentRequest {
optional uint32 payment_details_version = 1 [default = 1];
optional string pki_type = 2 [default = "none"];
optional bytes pki_data = 3;
required bytes serialized_payment_details = 4;
optional bytes signature = 5;
}
字段 | 说明 |
---|---|
payment_details_version | 请参阅下面的版本/升级的讨论。 |
pki_type | 公钥基础设施(PKI)系统被用来识别商家。 所有的实现应该支持“none”,“x509 + sha256”和“x509 + sha1”。 |
pki_data | PKI系统数据,标识商家,可用于创建数字签名。 对于X.509证书,pki_data包含一个或多个X.509证书(请参见下面的证书部分)。 |
serialized_payment_details | 协议缓冲区序列化的PaymentDetails消息。 |
签名 | 数字签名在PaymentRequest消息的协议缓冲器序列化变体的散列上,所有序列化字段以数字顺序序列化(所有当前协议缓冲器实现以数字顺序序列化字段)并且使用与pki_data中的公钥对应的私钥进行签名。 未设置的可选字段不会被序列化(但是,将字段设置为其默认值将导致其被序列化并且会影响签名)。 序列化之前,必须将签名字段设置为空值,以便该字段包含在签名的PaymentRequest哈希中,但不包含数据。 |
当比特币钱包应用程序收到PaymentRequest时,它必须通过执行以下操作来授权付款:
大于50,000字节的PaymentRequest消息应该被钱包应用拒绝,以减轻拒绝服务攻击。
付款消息在客户授权付款后发送:
message Payment {
optional bytes merchant_data = 1;
repeated bytes transactions = 2;
repeated Output refund_to = 3;
optional string memo = 4;
}
字段 | 说明 |
---|---|
merchant_data | 从PaymentDetails.merchant_data复制。 商家可以使用发票号码或任何其他数据来将付款与PaymentRequests进行匹配。 请注意,恶意客户可能会修改merchant_data,因此应以某种方式进行身份验证(例如,使用仅商户密钥进行签名)。 |
transactions | 一个或多个有效的已签名比特币交易完全支付PaymentRequest |
refund_to | 如有必要,商户可以返回一个或多个输出资金。 商户可以在支付请求时间之后使用这些输出返还资金长达2个月。 在这段时间到期之后,各方必须商议是否需要返还资金。 |
memo | UTF-8编码,从客户到商家的纯文本注释。 |
如果客户授权付款,那么比特币客户端:
与payment_url服务器通信的错误应该传达给用户。 在商户的服务器接收到多个相同的支付消息的个人PaymentRequest的情况下,它必须承认每个。 从商家的服务器发送的第二个和另外的PaymentACK消息可以根据备注字段而变化以指示支付的当前状态(例如在网络上看到的确认的数量)。 这是必需的,以确保在传输过程中传输级别失败的情况下,比特币客户端可以通过重新发送付款消息来进行恢复。
PaymentDetails.payment_url应该是安全的,以防止可能改变Payment.refund_to的中间人攻击(如果使用HTTP,它必须是TLS保护的)。
通过HTTP发送付款消息的电子钱包软件必须设置适当的Content-Type和Accept头,如BIP 71中所述:
Content-Type: application/bitcoin-payment
Accept: application/bitcoin-paymentack
当商家的服务器收到付款消息时,必须确定交易是否满足付款条件。 当且仅当他们这样做,它应该在比特币p2p网络上广播交易。
大于50,000字节的支付消息应该被商家的服务器拒绝,以减轻拒绝服务攻击。
PaymentACK是支付协议中的最终消息。 它是从商家的服务器发送到比特币钱包以响应支付消息:
message PaymentACK {
required Payment payment = 1;
optional string memo = 2;
}
字段 | 说明 |
---|---|
payment | 触发此PaymentACK的付款消息的副本。 如果客户实现另一种将Payments与PaymentACK关联的方式,则客户可以忽略它。 |
memo | 应向客户显示UTF-8编码的注释,提供交易状态(例如“为接受处理的十一种纸币支付1 BTC”)。 |
大于60,000字节的PaymentACK消息应该被钱包应用拒绝,以减轻拒绝服务攻击。 这大于支付和PaymentRequest消息的限制,因为PaymentACK包含完整的支付消息。
支持多种语言的商家应该生成特定于语言的PaymentRequests,并将该语言与请求相关联,或者在请求的merchant_data中嵌入语言标签。 他们还应根据原始请求生成特定于语言的PaymentACK。
例如:希腊语客户浏览希腊语版本的商人网站时,会点击一个“Αγοράτώρα”链接,该链接会生成一个Paymentntquest,其中merchant_data设置为“lang = el&basketId = 11252”。 客户支付,他们的比特币客户端发送支付信息,而商家的网站用PaymentACK.message回答“σαςευχαριστούμε”。
默认的PKI系统是X.509证书(与用于验证Web服务器的系统相同)。 当pki_type是“x509 + sha256”或“x509 + sha1”时,pki_data的格式是协议缓冲器编码的证书链:
message X509Certificates { repeated bytes certificate = 1; }
如果pki_type是“x509 + sha256”,则使用SHA256算法对PaymentRequest消息进行散列,以产生经过签名的消息摘要。 如果pki_type是“x509 + sha1”,则使用SHA1算法。
每个证书都是DER [ITU.X690.1994] PKIX证书值。 包含数字签名PaymentRequest的实体的公钥的证书必须是第一个证书。 这必须附加额外的证书,每个后续证书是用于证明前一个证书的证书,直到(但不包括)受信任的根权威机构。 受信任的根权限可以包括在内。 收件人必须根据[RFC5280]验证证书链,如果发生验证失败,则拒绝PaymentRequest。
受信任的根证书可以从操作系统获得; 如果在没有操作系统的设备上进行验证,则推荐使用Mozilla根存储。
协议缓冲区序列化格式被设计为可扩展的。 特别是,可以将新的可选字段添加到消息中,并且将被旧的实现忽略(但是保存/重新传输)。
PaymentDetails消息可以用新的可选字段进行扩展,仍然被认为是“版本1”。 旧的实现将能够验证包含新字段的PaymentRequests的签名,但是(显然)将无法显示新的可选字段中包含的任何信息给用户。
如果商家在未来的某个时候有必要生成PaymentRequest消息,而这些消息只能被新的实现所接受,那么他们可以通过定义一个version = 2的新的PaymentDetails消息来实现。 旧的实现应该让用户知道他们需要升级他们的软件,当他们得到一个上传版本PaymentDetails消息。
在本规范中需要扩展消息的实现应使用从1000开始的标签,并通过pull-req更新扩展页面以避免与其他扩展冲突。
BIP 0071:支付协议MIME类型
BIP 0072:支付协议比特币:URI扩展
公钥基础设施(X.509)工作组:http://datatracker.ietf.org/wg/pkix/charter/
协议缓冲区:https://developers.google.com/protocol-buffers/
创建付款请求生成器:https://bitcoincore.org/~gavin/createpaymentrequest.php(源)
BitcoinJ https://bitcoinj.github.io/payment-protocol#introduction
Javascript对象签名和加密工作组:http://datatracker.ietf.org/wg/jose/
维基百科的发票页面:http://en.wikipedia.org/wiki/Invoice特别是电子发票标准清单
sipa的付款协议建议:https://gist.github.com/1237788
ThomasV的“签名别名”提案:http://ecdsa.org/bitcoin_URIs.html
同态付款地址和付款合同协议:http://arxiv.org/abs/1212.3257