- BIP20 已经被 BIP21 替换,看了下有些冗余,并且没有考虑到客户端实现不一致的情况
- BIP21 目前适用性最广的 payment URI
- BIP70 由于各种原因已经从 [email protected] 中被移除了,但感觉有一些参考价值
BIP21 是一个 URI Schema,目的是让用户只需要通过点击或者扫码就可以进行支付
最佳实践是针对每一笔支付,生成一个新地址,URI 是 payment 的 identity 而不是个体的 identity
bitcoinurn = "bitcoin:" bitcoinaddress [ "?" bitcoinparams ]
bitcoinaddress = *base58
bitcoinparams = bitcoinparam [ "&" bitcoinparams ]
bitcoinparam = [ amountparam / labelparam / messageparam / otherparam / reqparam ]
amountparam = "amount=" *digit [ "." *digit ]
labelparam = "label=" *qchar
messageparam = "message=" *qchar
otherparam = qchar *qchar [ "=" *qchar ]
reqparam = "req-" qchar *qchar [ "=" *qchar ]
这是一个向 Luke-Jr 支付 20.3 BTC 的例子,并附言 "Donation for project xyz"
bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=50&label=Luke-Jr&message=Donation%20for%20project%20xyz
有个需要留意的点是,由于客户端实现可能有不同用途,如果 req-
开头的 param 客户端无法识别,则视为这是一个无效的 URI
虽然 BIP70 被移除了,但里面提到的一些问题可能值得留意 BIP21 是一个简介的协议,在支付过程中还会遇到一些痛点,为了解决这些痛点
- BTC 地址是一串人类不可读的字符,这给中间人攻击留下了空间
- 可能与支付商家发生纠纷
- 支付可能发生退款的情况
BIP70 通过 X.509 来解决中间人攻击以及人类不可读的 BTC 地址的问题,并且在支付时就早早将退款地址作为支付请求发给了商户
发现 BTC 社区其实非常地在意去中心化, X.509 的引入相当于将国家或者政府机构作为信任中心了,猜测很大可能是因此废弃的
而且钱包的实现组织认为 BIP70 看起来更像是一个 加密数字货币钱包的协议,而不是 BTC 钱包协议,这给实现带来了更大的不确定性
package payments;
option java_package = "org.bitcoin.protocols.payments";
option java_outer_classname = "Protos";
// Generalized form of "send payment to this/these bitcoin addresses"
message Output {
optional uint64 amount = 1 [default = 0]; // amount is integer-number-of-satoshis
required bytes script = 2; // usually one of the standard Script forms
}
message PaymentDetails {
optional string network = 1 [default = "main"]; // "main" or "test"
repeated Output outputs = 2; // Where payment should be sent
required uint64 time = 3; // Timestamp; when payment request created
optional uint64 expires = 4; // Timestamp; when this request should be considered invalid
optional string memo = 5; // Human-readable description of request for the customer
optional string payment_url = 6; // URL to send Payment and get PaymentACK
optional bytes merchant_data = 7; // Arbitrary data to include in the Payment message
}
message PaymentRequest {
optional uint32 payment_details_version = 1 [default = 1];
optional string pki_type = 2 [default = "none"]; // none / x509+sha256 / x509+sha1
optional bytes pki_data = 3; // depends on pki_type
required bytes serialized_payment_details = 4; // PaymentDetails
optional bytes signature = 5; // pki-dependent signature
}
message X509Certificates {
repeated bytes certificate = 1; // DER-encoded X.509 certificate chain
}
message Payment {
optional bytes merchant_data = 1; // From PaymentDetails.merchant_data
repeated bytes transactions = 2; // Signed transactions that satisfy PaymentDetails.outputs
repeated Output refund_to = 3; // Where to send refunds, if a refund is necessary
optional string memo = 4; // Human-readable message for the merchant
}
message PaymentACK {
required Payment payment = 1; // Payment message that triggered this ACK
optional string memo = 2; // human-readable message for customer
}