1. 程式人生 > >比特幣開發者指南(8)--支付流程

比特幣開發者指南(8)--支付流程

支付流程

支付流程包括消費者和接收者為了交換產品或服務而做出和接受付款的步驟。從商業啟蒙開始,基本步驟並沒有改變,但技術在改變。本節將介紹接收者和消費者如何分別使用比特幣來請求和付款,以及如何處理諸如退款和迴圈付費等複雜情況。

Bitcoin Payment Processing

上圖顯示了從接收者的角度來看,使用比特幣進行支付處理,從新訂單開始。以下小節將分別介紹三個常見步驟和三個偶然或可選步驟。

值得一提的是,每個步驟都可以通過使用第三方API和服務進行外包。

價格訂單

由於satoshis與本國貨幣(fiat)之間的匯率變動性,許多Bitcoin訂單的價格為fiat,但在satoshis ,需要進行價格轉換。

匯率資料可以通過貨幣兌換提供的廣泛使用的基於HTTP的API得到。幾個組織還聚合來自多個兌換機構的資料,以建立索引價格,也可以使用基於HTTP的API。

任何使用匯率資料自動計算訂單總額的應用程式必須採取措施確保報價的價格反映了目前satoshis的一般市值,或者應用程式對於正在銷售的產品或服務可以接受太少的satoshis。或者,他們可以要求更多的satoshis,嚇跑潛在的消費者。

為了確保問題最小化,您的應用程式可能希望從至少兩個獨立的源收集資料,並將其進行比較,以檢視它們有多大差異。如果差異很大,您的應用程式可以進入安全模式,直到人們能夠評估情況。

如果匯率正在迅速增加或下降,您可能還希望對您的應用程式進行程式設計,以進入安全模式,這表明在比特幣市場可能會出現問題,這可能使得今天難以支付任何satoshis。

匯率不在Bitcoin和相關技術的控制範圍之內,因此沒有新的或計劃中的技術使您的程式更容易將訂單總數從fiat轉換為satoshis。

由於匯率隨時間而波動,與fiat掛鉤的訂單總額必須有過期時間,以防止消費者拖延付款來希望satoshis將降價。最廣泛使用的支付處理系統目前在10到20分鐘之後到期。

較短的到期期限會增加發票在收到付款之前到期的機會,可能需要手動干預以要求額外付款或發起退款。更長的到期期限增加匯款在收到付款之前顯著波動的機會。

要求付款

在請求付款之前,您的應用程式必須建立比特幣地址,或從另一個程式(如Bitcoin Core)獲取地址。比特幣地址在交易部分中有詳細描述。在該部分中也描述了避免多次使用同一個地址的兩個重要原因,但第三個原因特別適用於支付請求:

對於每個收到的付款,使用一個單獨的地址使得確定哪些客戶已經支付了他們的支付請求是不重要的。您的應用程式只需跟蹤特定的支付請求和其中使用的地址之間的關聯,然後掃描塊鏈以獲得匹配的交易的地址。

接下來的小節將詳細描述以下四種相容方式,以便提供給花費者地址並支付金額。為了提高方便性和相容性,建議您在付款請求中提供所有這些選項。

  1. 所有錢包軟體允許使用者貼上或手動輸入地址,並將其納入付款螢幕。這當然是不方便的 - 但是它有有效的回退選項。
  2. 幾乎所有桌面錢包可以與比特幣:URIs關聯,所以消費者可以點選連結預先填寫付款螢幕。這也適用於許多移動錢包,但是通常不支援基於Web的錢包,除非消費者安裝瀏覽器擴充套件或手動配置URI處理程式。
  3. 大多數移動錢包支援以QR碼編碼的掃描比特幣:URI,幾乎所有錢包可以顯示它們接受付款。雖然線上訂單方便,QR碼對於個人購買特別有用。
  4. 最近的錢包更新支援新的支付協議,提供更高的安全性,使用X.509證書對接收者的身份進行身份驗證,以及其他重要功能例如退款。
Warning icon 警告:必須特別注意避免收到的付款被盜。特別地,私鑰不應儲存在Web伺服器上,支付請求應通過HTTPS或其他安全方法傳送,以防止中間人攻擊使用攻擊者的地址替換比特幣地址。

純文字

要直接指定用於複製和貼上的金額,您必須提供地址,金額和麵額。也可以指定要約的到期時間。例如:

(注:本節中的所有示例都使用testnet 地址)

指示面額至關重要。在撰寫本文時,流行的比特幣錢包軟體預設為比特幣(BTC),毫比特幣(mBTC)或微比特幣(uBTC,“bits”)。廣泛支援每個單位之間的選擇,但是其他軟體也可以讓使用者從以下部分或全部選項中選擇面額:

比特幣:URI

在BIP21中定義的比特幣: URI方案消除了面額混淆,使消費者免於複製和貼上兩個單獨的值。它還允許支付請求向消費者提供一些附加資訊。一個例子:


只有地址是必需的,如果它是唯一指定的,錢包將預先填寫付款請求,然後讓付款人輸入金額指定的數量始終為十進位制比特幣(BTC)。

其他兩個引數得到了廣泛的支援。label引數通常用於將收款人的姓名提供給錢包軟體。message引數通常用於描述花費者的支付請求。標籤和訊息通常由銷售商的錢包軟體儲存,但是它們不會新增到實際的交易中,因此其他Bitcoin使用者看不到它們。標籤和訊息都必須是URI編碼的。

所有四個引數一起使用,具有適當的URI編碼,可以在下面的換行示例中看到。

可以擴充套件URI方案,如下面的支付協議部分所示,同時包含新的可選引數和必需的引數。在撰寫本文時,除了上述四個之外,唯一廣泛使用的引數是支付協議 r引數。

接受任何形式的URI的程式必須在付款之前要求使用者獲得許可,除非使用者明確禁用了提示(對於支付小額支付可能是這樣)。

QR碼

QR碼是個人,影象或視訊中交換比特幣:URIs的流行方式。大多數移動Bitcoin 錢包應用程式和一些桌面錢包,支援掃描QR碼預先填寫他們的付款螢幕。

下圖顯示了在四個不同的糾錯水平下,編碼為四種不同的比特幣QR碼的相同的比特幣:URI。QR碼可以包括label和message引數和任何其他可選引數 - 但是在這裡省略了可選引數以便使QR碼小,易於不穩定或低解析度的移動攝像頭掃描。

Bitcoin QR Codes

錯誤校正與校驗和相結合,以確保比特幣QR碼在資料丟失或意外更改時無法成功解碼,因此您的應用程式應根據您可用的空間選擇適當的糾錯級別顯示QR碼。當空間有限時,低級別的損壞修正功能很好,四分位數的損壞修正有助於確保在高解析度螢幕上顯示時快速掃描。

付款協議

Bitcoin Core 0.9支援新的支付協議。付款協議為付款請求添加了許多重要功能:
  • 支援X.509證書和SSL加密,以驗證接收者的身份,並幫助防止中間人攻擊。
  • 提供有關所需支付的更多細節給消費者。
  • 允許消費者直接向接收者提交交易,而無需通過P2P網路。這樣可以加快付款處理速度,並使用計劃功能(如child-pays-for-parent交易費用)和離線NFC或基於藍芽的付款。
諸如“mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN”的無意義的地址而不被要求,但要求消費者提供從接收方的X.509證書中支付公用名稱(CN)描述,如“www.bitcoin.org”。

要使用支付協議請求付款,您可以使用擴充套件(但向後相容)比特幣: URI。例如:

除了r之外,上述提供的引數都不是支付協議所必需的,但您的應用程式可能會包含它們與錢包程式的向後相容性其尚未處理支付協議。

r引數指示支付協議感知錢包程式忽略其他引數,並從提供的URL中獲取一個PaymentRequest。瀏覽器,QR碼閱讀器或處理URI的其他程式開啟URI上的花費者Bitcoin 錢包程式。

BIP70 Payment Protocol

在BIP70,BIP71和BIP72中深入描述了付款協議。開發者示例付款協議子節中提供了一個示例CGI程式和可在付款協議中使用的所有引數的描述。在本小節中,我們將以故事形式簡要介紹如何通常使用付款協議。

Charlie客戶,正在購買由Bob商人運營的網站。查理在購物車中添加了幾個物品,並點選了“用比特幣結帳”按鈕。

Bob的伺服器會自動將以下資訊新增到其發票資料庫中:
  • 查理訂單的細節,包括訂購和運送的商品地址。
  • satoshis中的訂單總數,可能是通過將fiat中的價格轉換為satoshis中的價格而建立的。
  • 該總計將不再可接受的到期時間。
  • Charlie應向其傳送付款的pubkey指令碼。通常這將是一個包含一個唯一的(從未使用過的)secp256k1公鑰的P2PKH或者P2SH pubkey指令碼。
在將所有資訊新增到資料庫之後,Bob的伺服器顯示Charlie的比特幣: URI以點選付款。

查理點選瀏覽器中的比特幣:URI。他的瀏覽器的URI處理程式將URI傳送到他的錢包程式。錢包知道付款協議,因此它解析了r引數,並向該URL傳送一個HTTP GET,查詢一個PaymentRequest訊息。

返回的PaymentRequest訊息可能包括私人資訊,例如Charlie的郵件地址,但是錢包必須能夠訪問它而不使用先前的身份驗證,例如HTTP Cookie,因此通常使用具有防猜測部件的可公開訪問的HTTPS URL。為支付請求建立的唯一公鑰可用於建立唯一識別符號。這就是為什麼在上面的示例URI中,PaymentRequest URL包含P2PKH地址:https://example.com/pay/mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN

在收到HTTP GET到上面的URL之後,Bob的Web伺服器上的PaymentRequest生成CGI程式從URL獲取唯一的識別符號,並在資料庫中查詢相應的詳細資訊。然後,使用以下資訊建立一個PaymentDetails訊息:
  • satoshis和pubkey指令碼中的訂單金額將被支付。
  • 一個包含訂購商品列表的備忘錄,所以查理知道他付的是什麼。它也可能包括查理郵寄地址,所以他可以仔細檢查。
  • PaymentDetails訊息的建立時間加上它到期的時間。
  • Charlie的錢包應傳送完成的交易的網址。

PaymentDetails訊息放在PaymentRequest訊息中。支付請求允許Bob的伺服器使用伺服器的X.509 SSL證書籤署整個請求。(付款協議旨在允許將來允許其他簽名方式。)Bob的伺服器在向HTTP GET的回覆中傳送付款請求到Charlie的錢包。

Bitcoin Core Showing Validated Payment Request

Charlie的錢包收到PaymentRequest訊息,檢查其簽名,然後從PaymentDetails訊息中顯示詳細資訊給Charlie 。Charlie同意支付,所以錢包構造了一個付款給pubkey指令碼提供的Bob的伺服器。與傳統的比特幣支付不同,Charlie的錢包不一定會自動將此付款廣播到網路。相反,錢包構造一個付款訊息,並將其作為HTTP POST傳送到PaymentDetails訊息中提供的URL。其中包括:付款資訊包含:
  • Charlie支付Bob的簽名交易。
  • 可選備忘錄Charlie可以傳送給Bob。(不能保證Bob會讀它。)
  • 如果他需要返回Charlie的satoshis中的一些或全部,那麼Bob可以支付的退款 地址(pubkey指令碼) 。
Bob的伺服器接收到付款訊息,驗證交易是否向所提供的地址支付請求的金額,然後將交易廣播到網路。它還使用PaymentACK訊息回覆HTTP POSTed Payment訊息,其中包括Bob的伺服器的可選備忘錄,感謝Charlie的贊助,並提供有關訂單的其他資訊,如預計到達日期。

Charlie的錢包看到了PaymentACK,並通知Charlie付款已傳送。PaymentACK並不意味著Bob已經驗證了Charlie的付款 - 請參閱下面的驗證付款部分,但這意味著Charlie可以在交易獲得確認時執行其他操作。在Bob的伺服器從塊鏈中驗證Charlie的事務已經被確認之後,它授權運送Charlie的訂單。

在出現爭議的情況下,Charlie可以從各種簽名或其他證明的資訊中生成經密碼證明的收據。
  • Bob的網路伺服器簽名的PaymentDetails訊息證明,Charlie收到了一個發票,用於為指定的satoshis指定的公鑰指令碼備忘錄欄位。
  • 比特幣塊鏈可以證明由Bob指定的pubkey指令碼支付指定數量的satoshis。
如果需要發出退款,Bob的伺服器可以安全地支付Charlie提供的退款 -to pubkey指令碼。有關詳細資訊,請參閱下面的退款部分。

驗證付款

如交易和塊鏈部分所述,將交易廣播到網路不能確保接收方得到報酬。一個惡意的支出者可以建立一個支付收款人的交易,另一個交易支付相同的輸入回到自己。只有其中一個交易將被新增到塊鏈,沒有人可以肯定地說明它將是哪一個。

花費相同輸入的兩個或多個交易通常被稱為雙重支出。

一旦交易被包含在塊中,雙重支出是不可能的,而不修改塊鏈歷史來替換交易,這是相當困難的。使用該系統,Bitcoin協議可以根據需要修改以替換交易的的數量,為每個交易提供更新置信度。對於每個塊,交易獲得一個確認。由於修改塊是相當困難的,所以較高的確認得分表示更大的保護。
  • 0 確認:交易已被廣播,但仍未包含在任何塊中。一般情況下,零價值確認的交易(未經確認的交易)一律不受信任。雖然礦工通常確認他們收到的第一個交易,但欺詐者可能可以操縱網路來包括其交易版本。
  • 1 確認:交易被包含在最新的塊中,雙重花費風險急劇下降。支付足夠的交易費用的交易平均需要10分鐘才能收到確認。然而,最近的塊被意外地更換,所以雙重支出仍然是一個真正的可能性。
  • 2 確認:最近的塊連結到包含交易的塊。截至2014年3月,兩個塊替換是非常罕見的,並且兩個塊替換攻擊是不切實際的,沒有昂貴的採礦裝置。
  • 6 確認:網路花了大約一個小時的時間來保護交易,避免了雙重支出,交易是埋在六塊之下。即使是一個相當幸運的攻擊者也需要大量的網路雜湊功率代替六個塊。雖然這個數字有些隨意,但處理高價值交易的軟體或以其他方式具有欺詐風險的軟體,在等待接受付款之前,應至少等待六次確認。
Bitcoin Core提供了幾個RPC,可以為您的程式提供錢包中的交易或任意交易的確認分數。例如,listunspent RPC提供了您可以與確認分數一起使用的每個satoshi的陣列。

儘管確認大部分時間都提供了優秀的雙重支出保護,但至少有三種情況需要雙重支出風險分析:

  1. 在程式或其使用者無法等待確認並希望接受未確認付款的情況下。
  2. 在程式或其使用者接受高價值交易並且不能等待至少六個確認或更多的情況下。
  3. 在實施bug或長時間攻擊Bitcoin的情況下,使系統的可靠性低於預期。
雙重花費風險分析的有趣來源可以通過連線大量的比特幣對等體獲取,以跟蹤交易和塊與每個其他。一些第三方API可以為您提供這種型別的服務。

例如,可以在所有連線的節點中比較未確認的交易,以檢視在多個未確認的交易中是否使用任何UTXO,表示雙重花費嘗試,在這種情況下,支付可以拒絕,直到確認。交易也可以通過他們的交易費用進行排名,以估計它們新增到塊之前的時間。

另一個例子可能是當多個對等體在相同塊高度之間報告不同的塊頭雜湊時,檢測fork。如果fork擴充套件了兩個以上的塊,則程式可以進入安全模式,表示塊鏈可能出現問題。有關詳細資訊,請參閱檢測叉子小節。

雙重支援保護的另一個好的來源可以是人類智慧。例如,欺詐者可能與合法客戶的行為不同,讓精明的商家手動將其標記為高風險。您的程式可以提供安全模式,可以在全球或每個客戶的基礎上停止自動付款驗收。

發起退款

偶爾使用您的應用程式的接收者將需要發出退款。這樣做非常不安全的明顯方法是將satoshis返回到他們來的pubkey指令碼。例如:
  • Alice想從鮑勃購買一個小部件,所以Bob給Alice一個價錢,比特幣地址。
  • Alice開啟錢包程式,並向地址傳送一些satoshis。她的錢包程式自動選擇從其未使用的輸出中的一個satoshis,相應於比特幣的輸出 地址 mjSk1Ny9spzU2fouzYgLqGUD8U41iR35QN。
  • Bob發現Alice支付太多satoshis。作為一個誠實的傢伙,Bob 將額外的satoshis退回給mjSk ... 地址。
這似乎應該起作用,但是Alice正在使用一個集中的多使用者網路錢包,它不向每個使用者提供唯一地址,所以沒有辦法知道Bob的退款適用於Alice。現在,退款是對集中的錢包背後的公司的無意捐贈,除非Alice開啟支援票,並證明那些satoshis是為她。

這使得接收方只有兩種正確的方式來發布退款:
  • 如果使用了地址,或者使用基本的比特幣: URI,請直接與投寄人聯絡,要求他們提供退款 地址。
  • 如果使用支付協議,請將退款傳送到付款資訊的refund_to欄位中列出的輸出 。
注意:如果退款在原始付款完成後很長時間才會直接與投寄人聯絡是明智的。這允許您確保使用者仍然可以訪問refund_to 地址的鍵或鍵。

支付收入(限制外匯風險)

許多接收者擔心,他們的satoshis將在未來比現在更少的價值,稱為外匯(外匯)風險。為了限制外匯風險,許多接收方選擇在收到新的收款後立即支付新收購的付款。

如果您的應用程式提供此業務邏輯,則需要首先選擇輸出。有幾種不同的演算法可以導致不同的結果。
  • 一個合併迴避演算法使得外部人員看到塊鏈資料變得更難以確定接收方獲得,花費和儲存了多少satoshis 。
  • 最先進先出(LIFO)演算法花費新獲得的satoshis,而仍然有雙重支出風險,可能會將風險推向別人。這可能對接收者的資產負債表有好處,但可能對他們的聲譽不利。
  • 先入先出(FIFO)演算法首先使用最早的satoshis,這有助於確保接收者的付款總是確認,儘管這隻能在幾個邊緣情況下實現。

合併迴避

當接收器在輸出中接收到satoshis時,花費者可以跟蹤(以粗略的方式)接收機如何花費那些satoshis。但是,只要接收方為每個事務使用唯一地址,花費者就不能自動檢視其他消費者向接收方支付的其他satoshis。

然而,如果接收方在同一個交易中從兩個不同的消費者那裡花費了satoshis,則這些消費者中的每一個都可以看到另一個付款人的付款。這被稱為合併,接收器合併輸出越多,外部人員越容易跟蹤接收機具有多少satoshis賺取,消耗和儲存。

合併迴避表示試圖避免在相同的事務中花費不相關的輸出。對於想要將交易資料保密的人和企業,可能是一個重要的策略。

粗略的合併迴避策略是嘗試始終以最小的輸出來支付您所要求的數量。例如,如果您有四個輸出保持,分別為100,200,500和900 satoshis,則您將支付300 satoshis t2 > 500- satoshi 輸出。這樣,只要您的輸出比您的帳單大,您可以避免合併。

更高階的合併迴避策略在很大程度上取決於支付協議的增強,這將允許付款人通過智慧地在多個輸出之間分配付款來合併由接收者。

後進先出(LIFO)

輸出即使在確認之前也可以一次收到。由於最近的輸出是雙重的最大風險,將它們花在較舊的輸出之前,可以讓花費者保持較舊的 輸出,這些不太可能是雙重。

LIFO有兩個緊密相關的缺點:
  • 如果在第二個事務中從一個未確認的事務中輸入輸出,則如果事務可擴充套件性更改了第一個事務,則第二個事務將變為無效。
  • 如果在第二個事務中從一個未確認事務中輸入輸出,並且第一個事務的輸出成功雙用了到另一個輸出,第二個事務變得無效。
在上述任何一種情況下,第二個事務的接收者將看到傳入的事務通知消失或變成錯誤訊息。

由於LIFO將次要交易的收件人作為主要交易的收件人,將雙重支出風險作為收款人,因此在次級收件人不關心風險時最佳使用,例如交換或其他將要等待六個確認的服務,無論您是否使用舊的輸出或新的輸出。

主要交易受益人的聲譽可能受到威脅,例如支付員工時,不應使用LIFO。在這種情況下,最好在使用這些交易進行付款之前等待交易完全驗證(參見上述驗證子)。

先進先出(FIFO)

最老的輸出是最可靠的,因為它們被接收到的時間越長,塊越多需要修改為雙重支出他們。然而,在僅僅幾個塊之後,達到快速遞減的回報點。假設攻擊者擁有總共網路中的30%雜湊功率,則原始的比特幣紙張預測攻擊者能夠修改舊的塊的機會:

當交易費用時,FIFO確實具有很小的優勢,因為較舊的輸出可能有資格包含在50,000位元組中,用於不需要的執行預設Bitcoin Core程式碼庫的礦工的高優先順序事務。但是,由於交易費用如此之低,這並不是一個顯著的優勢。

FIFO的唯一實際用途是接收者在幾個塊中花費所有或大部分收入,並希望減少他們的付款偶然無效的機會。例如,持有六個確認的每筆付款的接收方,然後以每兩小時的時間表向供應商和儲蓄賬戶支付100%的經過驗證的付款。

重新定期付款

使用分散的比特幣不可能實現自動定期付款。即使錢包支援自動傳送不可逆付款,使用者仍然需要在指定的時間啟動程式,或者一直執行不受加密保護。

這意味著自動重複的比特幣付款只能由代表其消費者處理satoshis的集中式伺服器進行。實際上,希望在法定價格條件下設定價格的接收方也必須讓同一集中式伺服器選擇合適的匯率。

非自動重新結算可以通過信用卡經常性付款變得普遍使用的相同機制來管理:聯絡付款人並要求他們再次付款 - 例如,通過傳送一個PaymentRequest bitcoin: URI。

在將來,支付協議和新的錢包功能的擴充套件可能允許一些錢包程式來管理定期交易的列表。花費者仍然需要定期啟動該計劃並授權付款 - 但是,通過點選電子郵件發票,可以更容易和更安全地支付費用,從而增加接收方按時獲得付款的機會。