美文网首页
支付处理 - 比特币开发指南

支付处理 - 比特币开发指南

作者: terryc007 | 来源:发表于2018-03-09 21:53 被阅读316次

    支付处理 - 比特币开发指南

    原文链接: https://bitcoin.org/en/developer-guide#payment-processing

    翻译: terryc007

    版本:1.0


    比特币开发指南

    1. 区块链

    2. 交易

    3.合约

    4.钱包

    5.支付处理

    6.工作模式

    7.P2P网络

    8.挖矿


    支付处理包括了支付人,收款人在交换商品,服务中所涉及到的步骤。自有商业活动起,其基本的步骤一直没变过。但相关的技术则不停在变化。这个章节将会解释支付人,收款人各自通过比特币如何实现的 — 以及他们如何处理更为复杂的事情:比如退款,周期续费。

    上图从收款人的视角,从一个新订单,展示了使用比特币的支付流程。下面的小节将会讨论三个常用的步骤,以及三个偶尔会或者可选的步骤。

    价格订单

    因为比特币跟法币之间的汇率经常变换,很多比特订单都以法币计价,但是在支付的时,使用的是比特币,这就需要做价格转换。

    汇率数据可以通过各大交易所提供的HTTP API获取。 有好几个组织聚合了多个交易所的价格数据,也提供了基于HTTP的API。

    在使用汇率数据来自动计算订单总价时,任何应用程序都必须采用相关步骤保证比特币的价格反映的是个当前整个市场的的大致价格,或者应用程序对再卖的服务,商品收取小量的费用。或者,他们可以提高价格,赶走潜在的支付者。[?]

    为了最小化这个问题,你的应用程序至少从两个不断的汇率数据源收集数据,并比较他们的差额。如果相差太大,你的应用程序就进入一个安全模式直到用户能评估这种情况。

    如果汇率急剧变化,你也可以通过程序让应用程序进入安全模式,并提示用户: 比特币市场可能存在问题,今天支付比特币可能会有困难。

    因为汇率作假都不在比特币,以及相关技术可控之内,因此没有一个新的,或未来的技术使得你的程序非常容易,且正确把订单的价格从法币转化成比特币。

    因为汇率随着时间来回波动,锚定法币的订单总额必须有一个过期时间,以防止支付者延迟付款,因为他们想等以比特币计价的物品价格下跌,就可以少支付一下比特币。大多广泛使用的支付处理系统里,他们的单据会在10或20分钟后过期。

    在支付还未收到前,使用过短的过期时间会增加单据过期的机会,还有可能需要人工介入,重新再要求对方支付,或则退款。而过长的过期时间,会因汇率的波动增加价格上的大幅波动。

    请求支付

    在发起一个支付请求前,你的应用程序必须先创建一个比特币地址,或则从另外一个程序获取一个比特币地址(比如从比特币内核)。比特币地址我们已在交易章节详细讲解过。也讲到避免多次使用同一个比特币地址的原因 — 但是第三个原因则是支付请求:

    使用一个单独的地址来收取每笔付款,会使判断哪比支付来自哪个用户变的很繁琐。你的应用程序仅需要跟踪每个支付请求,使用的比特币地址,然后在区块链上扫描该地址上的交易。

    下一小节会详细介绍4种兼容的方式,把比特币地址,要支付的额度给到支付人。为了增加便利性,兼容性,建议你的支付请求中,提供所有选项。

    1. 所有的钱包软件允许用户在支付页面粘贴,手动输入比特币地址。当然,这很不方便 — 但是这可以让用户有修改的机会。

    2. 所有的桌面钱包能绑定bitcoin:URIs, 这样支付者通过点击一个链接就可以跳转到支付页面。这了在很多移动钱包里面也可以用,但是在web端钱包通常不能用,除非支付者装一个浏览器扩展或手动配置一个URI处理器。

    3. 很多移动钱包支付扫描QR二维码(里面编码了bitcoin: URIs),同时几乎所有的钱包都可以显示二维码来收款。 对于在线订单,QR二维码非常好用,特别对于个人购买而言,非常有用。

    4. 最近的钱包更新应支持:对于提升安全的新支付协议,使用[x.509]证书的收款者身份授权, 以及其他重要的功能,比如退款。

    警告: 特别注意避免收入被盗。实际上,私钥不应放在web服务器上,支付请求应通过HTTPS来发送,或者采用其他的安全措施防止中间人通过把你的比特币地址替换成攻击者的比特币地址。

    普通文本

    为指定一个数量来复制,粘贴,你必须提供一个比特币地址,数量,以及面额。可能还需要指定一个过期时间。比如:

    (注意: 本节所有例子使用的是比特币测试网络地址)

    Pay: mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN
    Amount: 100 BTC
    You must pay by:  2014-04-01 at 23:00 UTC
    

    指明面额是很重要的。到撰写本文时,主流比特币钱包软件默认面额使用bitcoins(BTC), 或 millibiticons(mBTC),或 microbitcoins(uBTC, "bits"). 在这些单位中选取你自己想要的单位这个功能已被大部分钱包支持,但是其他软件也支付让用户选择从下面所有选项中,选取面额数量。

    比特币数量 单位名(简写)
    1.0 bitcoin (BTC)
    0.01 bitcent (BTC 1分比特币)
    0.001 millibitcoin (mBTC 1毫秒比特币)
    0.000001 microbitcoin (uBTC, “bits” 1微比特币)
    0.00000001 satoshi

    bitcoin: URI

    在BIP21中定义bitcion: URI 方案,消除了面额带来的混乱,同时让支付者从复制,粘贴两个独立的数值中解脱出来。 它也让支付请求为支付者提供了一些额外的信息。如下面例子:

    bitcoin:mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN?amount=10

    仅需要一个地址,如果仅指定了地址,钱包会预先把它填充到支付请求,并让支付者输入数量。 其单位通常是十进制的bitcion(BTC) .

    其他两个参数也被广泛支持。 label参数通常被用来为钱包软件提供收款人的名字。 message参数通常用来对付款人描述支付请求。 label跟message数据通常会保存在付款人的钱包软件里— 但是他们永远不会加到实际的交易中,这样其他的比特币用户就看不到他们。label跟message必须用URI来编码

    下面的例子,包含了4个参数,并使用URI编码:

    bitcoin:mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN\
    ?amount=0.10\
    &label=Example+Merchant\
    &message=Order+of+flowers+%26+chocolates
    

    URI方案可以扩展为新可选参数和必需参数,这会在下面会支付协议章节讲到。 在撰写本文时,除了上面提到的4个参数外,还有一个被广泛支持的参数是支付协议里面的:r

    程序在接受任意形式的URI 时,在付款前,必需并获取用户的授权,除非用户自己关闭了授权提示(有可能是为支付)。

    二维码

    在个人之见,在图片,视频里面,用二维码交换bitcoin: URIs是一种非常流行的方式。很多移动比特币钱包App,一些桌面钱包都支持扫二维码进入支付页面。

    下图是4个不同的纠错级别的二维码,对同一个bitcoin: URI进行编码。这个二维码可以包含label,message参数 ,以及其他可选参数 — 但是在这为了让低分辨率手机相机,或不稳定镜头能够很容易扫描出二维码,就把它省略掉了。

    这个纠错跟一个校验和结合起来,确保因缺失数据或意外修改,让扫描比特币二维码失败。这样你的应用程序需要根据你可现实空间,来选择相应的纠错级别。

    支付协议

    比特币内核0.9支付新的支付协议。这个支付协议为支付请求新增了很多重要的功能:

    • 支持X.509证书和SSL加密,来验证收款人身份,并防止中间人攻击。

    • 为付款者提供更多有关支付的信息。

    • 允许付款者不通过P2P网络直接给收款付款。这可以加速支付处理,同时可以跟计划着的功能一起使用。比如 child-pays-for-parent交易费用和离线NFC,或基于蓝牙支付。

    支付者给一个无意义的地址支付,像 “mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN”。取而代之的是,支付者可以给一个通用名(比如 www.bitcoin.org)付款。这个通用名收款人可以从X.509证书获得。

    下面的例子:为使用支付协议发出支付请求,使用了一个扩展(但向后兼容)bitcoin: URI:

    bitcoin:mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN\
    ?amount=0.10\
    &label=Example+Merchant\
    &message=Order+of+flowers+%26+chocolates\
    &r=https://example.com/pay/mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN
    

    对于支付协议,上面的参数除了r,其他参数不是必须要的。 但是为了向后兼容那些还不能处理支付协议钱包,你的应用程序可以包含这些参数。

    r参数告诉那些支付支付协议的钱包程序,可以忽略其他参数,同时从提供的URL中获取一个支付请求。然后能处理URI的浏览器,二维码扫描器,或者其他程序,会打开付款者的比特币钱包程序来处理URI:

    支付协议在BIP70, BIP71,BIP72中有介绍。在支付协议开发者例子小节中,提供了一个CGI程序例子,里面包含了所有可以在支付协议中可以使用的参数。在这个小节中,我们会简单的使用故事的形式,介绍下通常如何使用支付协议。

    Charlie是客户,他了正在Bob运营的网站上购物。Charlie在自己的购物车里加了几个东西,然后点击“支付比特币”按钮。

    Bob服务器自动添加下面的信息到单据数据库:

    • Charlie订单详情,包含订购的东西,配送地址。

    • 账单总额(以比特币计价),假定是通过把法币转换成比特币得出总额。

    • 总额可接受的过期时间。

    • Charlie要支付的公钥脚本。 通常是P2PKH或是包含一个独一无二(从未被用过)secp256k1g公钥的 P2SH公钥脚本。

    添加完这些信息到数据库后,Bob的服务器会为Charlie显示一个bitcoin: URI, 他可以点击这个URI来付款。

    Charlie在浏览器中,点击这个bitcoin: URI。 他的浏览器URI处理器发送这个URI给他的钱包程序。这个钱包程序能处理支付协议,所以它会解释这个r参数,然后发送一个HTTP GET请求到那个URL,以便获取一个支付请求消息。

    这个支付请求消息回返回一些私人信息,比如Charlie的邮件地址,但是钱包必须能够在不需要授权的情况下,可以访问它,比如HTTP cookies,因为一个带来拒绝猜测的,可以公开可访问的HTTPS URL通常会用到它。为支付请求生成的独一无二的公钥,可以被用来创建一个第一无二的标识。这就是为什么,在上面的例子中,支付请求的URL里面包含一个P2PKH地址:

    https://example.com/pay/mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN

    收到上面URL的HTTP GET返回后,在Bob服务器上的,生成支付请求的CGI程序从URL中获取那个独一无二的标识,然后在数据中用它来查找相应的详情。 然后创建如下的支付详情消息:

    • 公钥脚本上支付的比特币数量。

    • 包含商品列表的备注,这样Charlie就知道他为哪些东西付款了。它也包含了Charlie的邮件地址,这样可以方便他再重新核对。

    • 一个时间:支付详情创建日期加上过期时间。

    • 一个让Charlie钱包发送它完成的交易的URL[?].

    支付详情消息会被放到支付消息里面。这个支付请求让Bob的服务器使用X.509 SSL证书签名整个请求。(在未来,支付协议被设计成可以允许其他签名方式)。为给HTTP GET返回,Bob的服务器发送支付请求到Charlie的钱包。

    Charlie的钱包收到这个支付请求消息,检查签名,然后把支付详情显示给Charlie。Charlie同意支付,这样钱包构建一个支付给Bob服务器提供的公钥脚本。跟其他传统比特币支付不一样,Charlie的钱包不需要自动广播这个支付到比特币网络。 而是构建一个支付消息,已HTTP POST方式,把它发送到支付消息里面提供的URL。除此之外,支付消息还包括:

    • Charlie支付给Bob的签名交易。

    • Charlie发送给Bob的备注(可选)(不保证Bob会看)。

    • 接收Bob退款的比特币地址(公钥脚本),如果Bob需要退款部分,或全部比特币给Charlie。

    Bob服务器收到付款消息后,会去地址上验证交易中的支付款,然后广播交易到网络。同时它会给HTTP POST 支付消息返回一个支付回应消息,里面包含一个可选备注。里面的内容可能是欢迎Charlie光顾,或其他有关订单信息,比如货达到日期。

    Charlie的钱包收到支付回应消息后,它告诉Charlie支付已经发送。这支付回应消息并不是意味着Bob已经验证Charlie的支付 — 请看下面验证交易小节。 但这意味着,在交易确认过程中,Charlie可以去做别的事情了。当Bob的服务器在区块链上验证: Charlie的交易已经适当的被确认,它就授权派送Charlie的订单。

    在碰到纠纷时,Charlie可以生成一个用各种签名的,可被加密证明的收据[?]或者其他反向证明信息:

    • Bob服务器签名的支付详情消息,可以证明Charlie收到一个单据,在备注里面,有为一个特定的物品,一个指定的公钥脚本支付过指定数量比特币的信息。

    • 在区块链上,可以证明在Bob提供的公钥上支付过一笔比特币。

    如果需退款,Bob的服务器能够安全的把钱退回到Charlie提供的公钥。 详情请看下面的退款章节。

    验证支付

    如在交易,区块链章节中所述,广播交易并不能确保收款人收到付款。恶意付款人能创建一个交易支付给收款人,同时再创建一个输入给自己。只有其中的一个交易能加到区块链中,但没有人能确定说到底是哪个会被加入。

    两个或多个交易花同一个输入就是我们常说的双花

    一但交易被加入到区块中,在不修改区块链历史记录的情况下,双花几乎是不可能的。因为替换历史交易是非常困难的。使用比特币这个系统,比特币协议能给你每个交易一个更新置信分数。它是基于为替换一个交易,需要修改多少个区块而算出来的。每增加一个区块,交易就获得一次确认。因为修改区块相当困难,更高的确认数意味着更多的保护。

    0 确认: 交易被广播但是仍旧没有被加入到区块。 0确认交易(未确认交易)不应给信任的。虽然矿工通常他们收到的第一个交易,但欺骗者可以操控网络,把他们的版本的交易加入进去。

    1确认: 交易被加入到最新的区块,双花的风险急剧下降。完成一次交易支付,平均大约需要10分钟才能收到一个确认。然而,最近的区块,偶尔也会有被替换的可能,所以还是有被双花的可能。

    2确认:包含最新交易的区块被加入到区块链。从2014.3月以来,两个区块交换是极少见的,因为在没有昂贵的挖矿设备的情况下,对两个区块实施交换攻击是不太可能的。

    6确认:比特币网络发了大约1个小时来保护交易避免被双花,此时交易上面已有6个区块。按理说一个幸运的攻击者需要掌握大量的算力,才有可能替换丢掉6个区块。虽然这个数字有点武断,但是当软件在处理高价值,或则高风险交易时,在确认支付是否完成,至少需要交易完成6个确认。

    虽然多个确认为防止双花提供了很多包含时间,但是仍然要对三种双花风险进行分析:

    1. 程序或用户在一个确认还未完成时,想接受非确认支付。

    2. 当程序或用户正在接收一个大额交易时,同时不能等待6个或更多确认。

    3. 程序bug或者比特币网络受到长时间攻击,导致比特币系统变得不怎么可靠。

    通过连接大量比特币节点,并跟踪彼此交易,区块的差异,来获取双花风险分析。有一些第三方 API 提供这样的服务。

    比如,通过对所有连接的节点中未确认交易,进行比较。 如果有UTXO在多个未确认交易中使用,那么这就是一个企图双花的交易,在这种情况支付可以被拒绝直到它被确认。 在交易被加入到区块前,对交易按交易费用排名,这样可以减少一些等待时间。[?]

    另外一个例子是,当多个节点报告说,同一个区块高度,有不同的区块头哈希,可以检测到分叉。 如果分叉出两个以上的区块时,你的程序可以进入安全模式,并提示用户区块链可能出问题了。想了解详情,请看分叉检测小节.

    另外一个从源头避免交易双花的人类智慧。比如,欺骗者跟普通消费者行为上是不一样的,可以让精明的商人手动把他们标识为高风险。你的程序可以提高一个安全模式:在全局上,或对于每个客户,停止自动确认支付。

    发起退款

    使用你程序的收款人偶尔也需要退款。最显而易见的方法就是把比特币简单的退回到付款方的公钥脚本,但是这个方法是非常不安全的。比如:

    • Alice想从Bob哪里买一个widget, 这样Bob给Alice一个价格跟比特币地址。

    • Alice打开她的钱包程序,发送比特币到Bob提供的地址。她的程序自动把未花掉的输出中支付给Bob提供的比特币地址。

    • Bob发现Alice多支付了一些比特币。作为一个诚实的人,Bob把额外的钱按原路退回给Alice。

    这看起来没什么问题,但是Alice使用一个中心化多用户的web钱包,这种钱包并不会给每个用户一个独立的地址,因此它就没法知道Bob的退款是给Alice的。除非Alice向这个公司提交一个工单,并证明退款是给Alice的,否则这钱算是捐给了这公司。

    这仅有两个正确的退款方式:

    • 如果是一个拷贝,粘贴或使用bitcon: URI的地址,直接跟付款人联系,并让他们提供一个退款地址。

    • 如果使用的是支付协议,把比特币退回到支付消息refund_to列表中的输出。

    注意: 在支付完成后,过很长一段时间后,再直接联系付款人,发起退款是明智的。因为这可以确保这个用户仍然有密钥访问refund_to中的地址。

    支出收入(规避汇率风险)

    很多收款人担心比特币在未来其价值相对于现在而言变少,这叫做汇率风险。为避免它,很多收款会立马把收到的比特币花掉,换成法币。

    如果你的程序提供了这样的业务,那么它需要选哪个输出先用来支付。不同的算法会有不同的结果:

    • 合并规避算法,让大家很难通过区块链上的数据,来了解付款人到底赚了多少,花了多少,还有多少余额。

    • 后进先出(LIFO)算法,通过花掉最新收到的比特币,但会有双花的风险,可能会把风险转移到其他人。这个算法对于方面生成收款人余额单,但是会对他们声誉不好。

    • 先进先出(FIFO)算法,先花掉最先收到的比特币,虽然这仅对几种边界情况有用,但它能确保,收款人的支付总是被确认了的。

    合并规避

    单收款人收到比特币后,付款人能够跟踪到收款人如何使用这些比特币。但是只要付款人为每个交易分配一个独一无二的比特币地址,付款人就不能看到其他人支付给收款人的比特币的使用情况。

    然而,如果收款人在一个交易中,同时花来自不断付款人的比特币时,每个付款人就能看到其他付款人的支付情况。这就叫做合并,付款人合并的输出越多,其他人就越容易知道收款人赚了多少,花了多少,存款多少。

    合并规避意味着在同一交易中,避免去花不相关的输出。对个人,商业来说,保密他们交易避免被其他人知道,是非常重要的一个策略。

    一个自然的合并规避策略是,尽量选取那些包含比特币数量最小的,同时了又大于所要支付数量的输出,来支付。比如,如果你一个4个输出,分别是100, 200,500 以及900 satoshis, 你可以用500-satoshi输出来支付一个需要300 satoshis的账单。用这种方法,只要有大于你账单费用的输出,就可以避免合并。

    更高级的合并规避策略则需要靠增强支付协议,它可以通过付款提供的多个输出,智能的分发他们的支付,从而避免付款人之间的交易合并。

    后进先出(LIFO)

    即使在交易被确认前,只要一收到输出,就可以把它花掉。因为最近的输出双花风险最大,在老的输出之前花掉最新的输出,可以让老的输出被双花的可能性更小。

    LIFO有两个密切相关的缺点:

    • 在第二个交易中,从一个未确认交易中花掉一个输出,如果交易延展性改变了第一个交易,那么第二个交易就会变成无效。

    • 在第二个交易中,从一个未确认交易中花掉一个输出,并且第一个交易的输出已经成功的被双花到另外一个输出,那么第二的交易会变成无效。

    在上面两种情况,收款人的第二个交易通知会消失掉或提示一个错误消息。

    因为LIFO使得第二接收到的交易的双花风险比第一个收到的要高,所以这种方式最好在不需要关系第二个交易风险的情况下使用,比如,一个交易所或其他服务,不管你是否花老的输出,还是新的输出,他们都会等待6个确认后,再认为交易成功。

    当主交易会影响到付款人声誉时,就不要使用LIFO。比如给员工支付工资。在这种情况,最好等待交易被完全的验证后(请看上面验证章节),再确认已完成支付。

    先进先出(FIFO)

    最老的输出最可靠,因为自从收到开始,其时间越久,要双花需要修改的区块就越多。然而,少许区块后,会达到一个快速减少返回的点[?]。 在比特币的白皮书中,假设攻击者拥有整个比特币网络30%的算力,对攻击者能修改老区块的机会,做了如下预测:

    区块数 成功修改的可能性
    5 17.73523%
    10 4.16605%
    15 1.01008%
    20 0.24804%
    25 0.06132%
    30 0.01522%
    35 0.00379%
    40 0.00095%
    45 0.00024%
    50 0.00006%

    FIFO在交易费用方面,有一点优势,因为运行默认的比特币内核的矿工,可能会把老的输出被包含到,用于存放无需交易费高优先级交易中去,其有50000字节可用。然而,手续费太低,这并不是一个大的优点。

    FIFO仅当收款人为降低他们支付偶尔失效的可能性,想把他们所有的收入,或大部分收入在少数区块中花掉时,才实用。比如,付款人持有所有6个确认的比特币,然后把100%被验证的付款支付给供应商,同时一个储蓄账户每两小时一次[?].

    续费

    去中心化的比特币钱包没法实现自动续费功能。即使钱包支持在日程安排中自动发送不可逆支付,用户仍需要在某个时间启动程序,或者一直在没有加密保护的情况下运行钱包。

    这意味着使用比特币自动续费,只能通过中心化的服务器来代理付款人处理比特币。在实际使用中,对于那些想使用法币支付的付款人,必须让中心化服务器选择相应的汇率。

    非自动记费可以通过现信用卡中很常用的续费方式来管理: 联系付款人,请求他们再付款 — 比如,通过给他们发送一个包含支付请求的bitcion: URI的HTML格式的email.

    在未来,支付协议的扩展功能和新的钱包功能可以允许一些钱包程序管理续费交易列表。付费者仍需要启动程序,对支付进行授权 — 但是对于付款人来说,相比于点击一个email账单,它会变的更加容易,更加安全,可以提高收款人及时收到付款的机会。


    声明:

    文中带有[?]的地方,表示我对此翻译明显感觉不太对的,后续会不断修正。

    有些地方可能会翻译的不好,不地道,甚至错误,如果有发现,还请留言,指出,以便我好修正,谢谢!

    相关文章

      网友评论

          本文标题:支付处理 - 比特币开发指南

          本文链接:https://www.haomeiwen.com/subject/lkqmfftx.html