Bitcoin jQuery 支付小部件





5.00/5 (11投票s)
编码 jQuery 小部件以接受比特币支付
引言
本文介绍了一个使用 Bitcoin 进行支付的 jQuery 小部件。
使用 Bitcoin 支付
那么,到底需要什么才能用 Bitcoin 支付呢?
与其他传统支付系统不同,Bitcoin 要求每笔交易都需要由存储在付款人钱包中的私钥预先签名。
此私钥不能公开,因此使用 Bitcoin 安全支付的唯一方法是通过商家提供的地址和金额,从付款人的钱包中发起支付。
付款人以 QR 码的形式扫描此信息。扫描信息并启动支付后,付款人应通知小部件开始监控交易。
当小部件从 Bitcoin 网络接收到交易后,支付即被视为成功。
自动更新
Bitcoin 的汇率变化非常频繁,而且目前非常不稳定。
因此,付款地址和金额(以 QR 码形式)应不断自动更新,以反映服务的最新价格。
注意:地址通常会随着金额一起更改,因为这是一种更安全的方法。
小部件要求
总而言之,小部件应能够做到以下几点:
- 以 QR 码形式向付款人显示最新的商家地址和金额信息
- 每 5 分钟自动更新一次 QR 码。在 QR 码过期前至少 1 分钟,通过计时器通知付款人。
- 提供一个按钮供付款人通知支付已提交。点击按钮后开始监控新交易。
- 收到交易后,执行必要的回调并通知付款人支付已成功。
使用此小部件
小部件需要 jQuery 和 jquery-qrcode 库。
以下是使用示例
HTML
<div class="bitcoin-payment-widget" id="widget">
<div class="border-cover">
<div class="header-logo"><img src="~/Content/bitcoin.png" /></div>
<div class="header-label">Bitcoin Payment</div>
<div class="qr-image-container">
<div class="qr-image" data-role="qr-image"></div>
</div>
<div class="update-label" data-role="update-label"></div>
<div class="check-payment-button-container">
<button class="check-payment-button"
data-role="check-payment-button"></button>
</div>
</div>
</div>
JavaScript
$(document).ready(function () {
$("#widget").bitcoinpayment({
getNewLinkUrl: "/Payment/GetNewLink",
getPaymentStatusUrl: "/Payment/GetPaymentStatus",
postPaymentUrl: "/Payment/PostPayment",
postPaymentCallback: function (result) {
alert("Payment received at " + result.paidAt + ",
transaction id: " + result.transactionId);
}
});
})
此小部件的前提条件是一个 REST 服务,该服务应与 Bitcoin(或上层)网络通信,并能够生成新的地址/金额对并检查其相应的交易状态。
以下是参数对象的描述
getNewLinkUrl
- 返回 Bitcoinlink
和与之对应的唯一paymentRequestId
的 REST 服务方法的 URL。Bitcoin 链接应为 URI 格式(请参阅 Bitcoin URI),并且应包含地址和金额。getPaymentStatusUrl
- 接受paymentRequestId
字符串作为参数并返回paymentSuccessful
布尔值的 REST 服务方法的 URL。此服务方法应请求 Bitcoin(或上层)网络并检查是否存在与特定paymentRequestId
相关的任何交易。如果为true
,则该方法应返回paymentSuccessful
为true
。可选地,还可以返回paidAt
和transactionId
。postPaymentUrl
- 成功支付后回传的 REST 服务的 URL。应将paymentRequestId
作为参数。postPaymentCallback
- 成功支付后触发的回调。
以下是可能的服务器端实现(使用 C# 和 ASP.NET)
[HttpPost]
public ActionResult GetNewLink()
{
var paymentInfo = new PaymentInfo()
{
Amount = 0.25M,
Currency = "USD"
};
var paymentRequest = BitcoinNetworkService.GenerateNewPaymentRequest(paymentInfo);
return Content("{ \"link\": \"" +
paymentRequest.BitcoinUri + "\", \"paymentRequestId\": \"" +
paymentRequest.PaymentRequestId + "\" }");
}
[HttpPost]
public ActionResult GetPaymentStatus(string paymentRequestId)
{
var paymentResult = BitcoinNetworkService.GetPaymentStatus(paymentRequestId);
return Content("{ \"paymentSuccessful\": " +
paymentResult.IsSuccessful.ToString().ToLowerInvariant() +
", \"paidAt\": \"" +
paymentResult.PaidAt + "\", \"transactionId\": \"" +
paymentResult.TransactionId + "\" }");
}
[HttpPost]
public ActionResult PostPayment(string paymentRequestId)
{
// Posting payments
return new EmptyResult();
}
演示项目
演示项目使用 Coinbase
实现服务器逻辑。要运行演示,请在 Coinbase
中创建一个 Merchant
帐户,并在 Web.Config 文件中指定凭据(CoinbaseApiKey
和 CoinBaseApiSecret
)。
小部件实现细节
让我们从初始化开始观察代码。
function init($container) {
$qrImage = $container.find("[data-role='qr-image']");
$checkPaymentButton = $container.find("[data-role='check-payment-button']");
$updateLabel = $container.find("[data-role='update-label']");
$checkPaymentButton.text("Check Payment");
$updateLabel.text("Pay QR in your wallet");
$checkPaymentButton.click(function () {
if (isMonitoringPayments) {
$updateLabel.text("Pay QR in your wallet");
$checkPaymentButton.text("Check Payment");
stopMonitoringPayments();
startAutoUpdater();
}
else {
startMonitoringPayments();
stopAutoUpdater();
$checkPaymentButton.text("Cancel");
$updateLabel.text("Checking payment...");
}
})
startAutoUpdater();
}
在初始化时,我们应该做几件事:初始化变量、启动自动更新器并根据“检查支付”按钮的当前状态(可以是“检查支付”或“取消检查支付”)来挂钩其逻辑。
首先,参数 $qrImage
、$checkPaymentButton
和 $updateLabel
使用具有特定 data-role
属性的 HTML 元素进行初始化。使用这些属性可以使 HTML 更加健壮,并在需要时使用不同的标记来表示元素。
然后,为 $checkPaymentButton
分配一个 click
事件,该事件有两个条件。如果此按钮在小部件未监控支付时被点击,则表示用户点击了检查支付按钮,小部件应开始监控支付并停止 QR 码的自动更新。否则,表示用户点击了取消按钮,在这种情况下,与之前的行为相反,小部件应中断支付监控并继续 QR 码的自动更新。相应地更新 $updateLabel
和 $checkPaymentButton
。
在方法结束时,执行 startAutoUpdater
来启动自动更新器并执行 QR 码的初始更新。
现在让我们更详细地看看主要函数。
function checkForUpdate() {
var minimumNotificationTime = 60000;
var currentTime = Date.now();
if (!timeToNextUpdate || timeToNextUpdate.getTime() < currentTime) {
timeToNextUpdate = new Date(currentTime + updateIntervalInMinutes * 60000)
$qrImage.empty();
$.post(options.getNewLinkUrl)
.done(function (r) {
var result = JSON.parse(r);
console.log("Received link: " + result.link);
paymentRequestId = result.paymentRequestId;
$qrImage.empty();
$qrImage.qrcode({
text: result.link,
width: $qrImage.width(),
height: $qrImage.height()
});
$updateLabel.text("Pay QR in your wallet");
})
.fail(function () {
console.error("Service " + options.getNewLinkUrl + " is not accessible.");
});
}
else if (timeToNextUpdate.getTime() - currentTime <= minimumNotificationTime) {
$updateLabel.text("Time before update: " +
fmtMMSS(timeToNextUpdate.getTime() - currentTime));
}
}
此函数在自动更新器循环的作用域内执行。其主要职责是使用最新的金额和支付地址更新 QR 码。
timeToNextUpdate
是每次生成 QR 码时生成的时间。它在此方法中使用 currentTime
和 updateIntervalInMinutes
的总和乘以 60000 来分配,因为所有这些值都以毫秒为单位。当 timeToNextUpdate
未设置(初始状态)或小于 currentTime
时,表示时间已到,需要更新 QR 码。在此更新中,小部件向选项中提供的 getNewLinkUrl
发送 POST
请求,该请求必须返回一个 JSON string
,其中包含 paymentRequestId
和 link
,格式为 Bitcoin
URI,包含支付和商家地址的信息。QR 码使用 qrcode
函数更新,该函数是 jquery.qrcode
库的一部分(请参阅 GitHub)。minimumNotificationTime
变量存储了用户何时需要被告知 QR 码即将过期的时间。当该时间到来时,用户将在 $updateLabel
中看到有关 QR 码即将过期的通知。
function checkPayment() {
$.post(options.getPaymentStatusUrl,
{
paymentRequestId: paymentRequestId
})
.done(function (r) {
var result = JSON.parse(r);
if (result.paymentSuccessful) {
console.log("Payment received")
stopMonitoringPayments();
stopAutoUpdater();
$updateLabel.text("Payment Succeeded!");
$checkPaymentButton.attr("disabled", "disabled")
$.post(options.postPaymentUrl, {
paymentRequestId: paymentRequestId
})
.done(function () {
if (options.postPaymentCallback) {
options.postPaymentCallback(result);
}
});
}
}).fail(function () {
console.error("Service " + options.getPaymentStatusUrl + " is not accessible.");
});
}
此函数的主要目的是检查服务器是否已收到付款。
系统使用 paymentRequestId
向 getPaymentStatusUrl
发送请求,并收到包含支付状态的 JSON 响应。当支付成功后,系统会停止进程并调用回调。首先,系统停止监控和自动更新。$updateLabel
会更新以通知付款人交易已成功。然后,$checkPaymentButton
会被禁用,以防止用户进行任何进一步操作,因为小部件上的所有操作都已停止。最后,在 postPaymentUrl
上执行回传,并在 postPaymentCallback
上调用以分别通知服务器和客户端成功的结果。
关注点
此小部件未涵盖用户支付金额大于或小于所需金额的边缘情况。但是,如果服务器端实现了适当的功能,则可以轻松添加。