支付协议是用于指代BIP70,71,72和73中指定的协议的术语。支付协议旨在通过用可编码更复杂参数的小文件替换普遍存在的比特币地址来为比特币添加附加功能。它指定了直接在资金发送方和接收方之间流动的支付请求,付款和支付方式的格式。
支付协议对于比特币的各种重要功能的开发至关重要,因此,了解它如何使用比特币非常重要。本文介绍了基本功能,并显示了将其集成到钱包应用程序中的一些示例代码。
具体而言,该协议的第1版提供:
- 1.接收器/商家使用任意脚本请求多个输出的方式,而不仅仅是单个付费密钥哈希类型的输出。多个独立交易可以满足付款,允许将来实施基于规避合并的隐私技术。
- 2.自由文本备忘录字段,因此商家可以填写由钱包存储的购买细节,及用户在付款时附加消息。
- 3.到期时间,过期的付款请求可能会被视为无效。这允许接收器在服务器端绑定其资源使用并放弃从未付费的请求。
- 4.发行时间,付款请求知道何时发出——有利于记录保存。
- 5.二进制cookie-esque字段,在提交支付交易时将简单地回显给服务器,允许商家实现无状态后端。
- 6.用户指定的退款地址。
- 7.使用X.509数字证书对上述所有内容进行签名的可选功能,从而将付款请求绑定到某种经过验证的身份。
支付请求本身可以进行数字签名这一事实可以实现一些非常重要和有用的功能。中间的一个人不能重写输出来劫持付款。这对于像Trezor这样的硬件钱包来说尤其重要,因为Trezor会假设主机受到损害,否则用户无法知道他们授权的付款与商家要求的付款相同。
此外,数字签名的付款请求和在区块链上满足它的交易一起创建非常类似收据的付款证明。收据对于争议调解和证明购买是有用的,而商家不必保留他们曾经拥有的每个客户的详尽数据库——即使商家删除了有关你的数据,只需出示收据就足以证明你已进行购买。
协议缓冲区是一种可以轻松扩展的二进制数据序列化格式。因此,我们可以很容易地想象将来可能添加的许多其他功能。
你可以阅读付款协议的常见问题解答,详细说明其设计背后的基本原理。
协议概述
在正常的比特币支付中,该过程从用户点击比特币URI或复制并将文本地址粘贴到他们的钱包应用程序并手动指定金额开始。
在付款协议处理的付款中,该过程以两种方式之一启动:
- 用户单击具有新“r”参数的比特币URI,该参数包含解析为付款请求文件的(http)URL。
- 用户直接打开付款请求文件。
然后,用户的钱包解析作为协议缓冲区的支付请求数据,并开始正常请求确认的过程。单击比特币URI时,将忽略URI其余部分中的指令(它们仅用于向后兼容),并且在给定URL处找到的数据优先。
支付请求由外部“skin”消息组成,该消息包含(可选的)签名和证书数据,以及包含所请求支付的详细信息的内部“core”消息的嵌入式序列化。外部PaymentRequest
消息与所使用的数字签名基础结构的类型无关,但目前仅定义了X.509绑定。这与SSL中使用的系统相同。内部PaymentDetails
消息以二进制形式存储,而不像普通的protobuf消息那样被嵌入,以确保签名字节始终匹配。
一旦钱包创建了令人满意的比特币交易集,就会格式化付款消息并将其上传到PaymentDetails
指定的目标URL,一旦满意地接受付款,钱包就会收到PaymentACK
消息。
签名和证书
签名付款请求的目的是在用户钱包应用中替换此类消息:
Pay 10mBTC to 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa?
与这样的一个:
- 支付10mBTC到satoshin@gmx.com?
- 支付20mBTC到overstock.com?
- 向迈克尔赫恩支付30亿比特币?
- 向加利福尼亚州旧金山的Genius Widgets公司支付100 BTC
……当然,第一种形式是最无用的,因为在这种情况下,身份只是一个没有意义或稳定性的随机数。这导致了其他示例中的字符串来自何处的问题。
答案是它们包含在X.509数字证书中,该证书本身由证书颁发机构签名。尽管有这个名字,但CA只是签署证书的任何实体,唯一赋予它们权力的是人们对软件的信任。ID验证和证书颁发具有竞争市场,这意味着你可以免费获得非常容易验证的身份证书(如电子邮件地址或域名)的证书。更复杂的身份,例如人或公司的合法名称,需要更多的努力来验证,因此必须付费。
从技术上讲,证书只是关于公钥的声明,因此要求你必须首先生成私钥,然后是证书签名请求(CSR),然后选择CA并上传CSR,以及你想要的身份和任何验证所需的信息。然后,CA会发回一个签名证书,该证书可以嵌入到付款请求中,同时还可以嵌入到达到一组根证书所需的任何中间证书。然后使用私钥对PaymentDetails
消息进行签名,现在其他用户软件可以验证所有这些并在用户界面中显示经过验证的ID。它还充当你在指定时间实际发出给定付款请求的加密证明。
实际上,上述手动创建密钥,创建CSR,上传密码等过程通常会自动取消最终用户电子邮件地址证书:相反,任何支持HTML5的现代Web浏览器都可以用来自动完成整个过程。在访问发布Comodo等免费证书的CA后,用户输入所请求的电子邮件地址并单击按钮。然后他们的浏览器生成一个新的私钥并记录下来。当用户单击传递到其电子邮件地址的验证链接时,签名过程完成,证书将安装在本地密钥存储中,可以在其中使用或导出到其他设备。整个过程与注册网站没有太大区别。
bitcoinj中的支付协议API
在0.12中,bitcoinj中的支付协议支持是有限的。它支持钱包应用程序中基本支持所需的一切,用于签名和使用付款请求。但是,它不支持将它们存储在钱包中以供将来参考。bitcoinj也没有利用这个机会向收件人提交多个独立交易以规避合并。
尽管如此,这里还是我们如何使用新功能的演示。
String url = QRCodeScanner.scanFromCamera(.....);
ListenableFuture<PaymentSession> future;
if (url.startsWith("http")) {
// URL may serve either HTML or a payment request depending on how it's fetched.
// Try here to get a payment request.
future = PaymentSession.createFromUrl(url);
} else if (url.startsWith("bitcoin:")) {
future = PaymentSession.createFromBitcoinUri(new BitcoinURI(url));
}
PaymentSession session = future.get(); // may throw PaymentRequestException.
String memo = session.getMemo();
Coin amountWanted = session.getValue();
if (session.isExpired()) {
showUserErrorMessage();
}
PaymentSession.PkiVerificationData identity = null;
try {
identity = session.verifyPki();
} catch (Exception e) {
log.error(e);
// Don't show errors that occur during PKI verification to the user!
// Just treat such payment requests as if they were unsigned. This way
// new features and PKI roots can be introduced in future without
// being disruptive.
}
if (identity != null) {
showUserConfirmation(identity.domainName, identity.orgName);
} else {
showUserConfirmation();
}
// a bit later when the user has confirmed the payment
SendRequest req = session.getSendRequest();
wallet.completeTx(req); // may throw InsufficientMoneyException
// No refund address specified, no user specified memo field.
ListenableFuture<PaymentSession.Ack> ack = session.sendPayment(ImmutableList.of(req.tx), null, null);
Futures.addCallback(ack, new FutureCallback() {
@Override public onSuccess(PaymentSession.Ack ack) {
wallet.commitTx(req.tx);
displayMessage(ack.getMemo());
}
});
用户界面注意事项
以特定方式提交付款协议确认非常重要。
首先,如果签名的PKI数据可用,你应该以一些具有视觉意义的方式向用户表明,因此他们知道所呈现的字符串是由第三方验证的ID。第三方(即CA)的名称也应该是可见的,尽管默认情况下将其隐藏在切换/滑块后面是可以接受的。
其次,如果提供了签名的PKI数据但未能验证,则应以与完全丢失签名数据完全相同的方式呈现付款。打开错误签名的请求的经验永远不会比打开一个完全没有签名的请求更糟糕。这使我们可以灵活地引入新的证书颁发机构或签署系统。
二维码
如果你的应用程序集成了扫描QR码的支持,你应该注意BIP 73.它说如果钱包应用程序扫描QR码并找到HTTP URL而不是比特币URI,它应该执行HTTP [S] GET到具有特殊HTTP标头的URL,该标头要求服务器提供付款请求。
这种机制的目的是让商家和支付处理商可以提供可以在任何类型的QR扫描仪上工作的QR码,如果用户没有带有集成扫描仪的钱包,那么带有说明的一个漂亮的HTML发票页面和可以显示可点击的比特币链接。
操作系统集成
如果要编写钱包应用程序,你应该注册处理比特币URI,你还应注册处理类型为application/bitcoin-paymentrequest的文件,扩展名为.bitcoinpaymentrequest。
通过这样做,你可以确保你的应用可以处理附加到电子邮件的付款请求,通过IM应用程序发送等等。
理想情况下,你还可以允许用户创建付款请求。PaymentRequest
消息的pki_type可以为“none”,因此创建此类文件是有效的。为了简单的用户体验,我们建议:
- 在桌面上,允许用户拖放支付请求文件(将其表示为图标)。例如,用户可以将其拖动到电子邮件撰写窗口以将付款请求附加到电子邮件与手动复制/粘贴地址和金额。 Gmail支持将文件拖放到编辑器上,其他HTML5应用也可以接受拖放数据。
- 在移动设备上,允许用户“共享”支付请求文件,这将允许用户通过聊天应用程序发送,附加到电子邮件,通过DropBox/Google Drive等共享。
测试
Gavin在这里运行一个简单的付款请求生成器应用:
https://bitcoincore.org/~gavi…
你可以使用它来测试你的钱包实现。
分享一个java比特币开发教程,面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。
汇智网(专业区块链教程网站)原创翻译,转载请标明出处。这里是原文