本文介绍了Solana Pay的工作原理和实现方案,提供了详细的参数解析和通过Next.js构建Solana Pay QR码的步骤。通过简单的URL来进行SOL或SPL Token的转账,该方法提升了支付的流畅性和用户体验,并附有完整的代码示例和图示,适合开发者参考和学习。
8分钟阅读
2023年8月29日
基于Solana区块链构建的Solana Pay是一种通用语言,用于简化URL中的交易。它提供即时交易和微小的交易费用,是一种让支付更为顺畅的新方式,旨在提升用户体验。
可以将这些URL视为特殊的网站地址,能够转化为二维码或NFC标签,或者在需要进行支付或设置交易时在个人及应用之间共享。这使得使用Solana交易的整个过程更加无缝和安全。
Solana Pay为用户与智能合约交互和转移代币提供了一种不同的方式。用户不再需要连接钱包,而是可以通过链接查看和签署交易。这消除了需要连接钱包进行交互的障碍。无论是简单的支付还是与应用的互动,都能够处理交易请求和转账请求。
Solana Pay的主要特性是转账请求,它是一种非互动的SOL或SPL Token转账请求。值得注意的是,并非所有的Solana钱包都接受这种格式,但大多数流行钱包都支持(Phantom、Solflare和Glow)。以下是Solana Pay转账请求URL的样子:
代码
solana:<recipient>?amount=<amount>&spl-token=<spl-token>&reference=<reference>&label=<label>&message=<message>&memo=<memo>
URL中的参数由钱包直接用来组成交易。在本指南中,我们将专注于转账请求,但重要的是要注意几乎任何Solana交易都可以转换为有效的Solana Pay URL。
现在让我们逐一分析每个参数:
收款人:
这是你发送SOL的人的公钥。对于SPL Token转账,你可以在spl-token字段中指定代币类型。钱包使用这些信息来确定转账的实际账户。
你正在发送的SOL或代币的数量。如果少于1,应该在小数点前加一个0。如果没有金额,钱包会要求你输入。如果转账SOL,则该金额单位为SOL,而不是lamports。
这个可选字段表示某种类型的SPL Token账户的铸造地址。如果不包含它,交易将只是正常的SOL转账。
交易中编码的唯一标识符。它用于帮助找到特定的交易并验证交易结果。
转账请求出处的简短描述。这可以是一个商店或一个应用。钱包向用户显示该信息,以提供关于交易的信息。
一个编码的URL,存储了关于转账原因的细节。这可以包括你在购买什么、订单ID或简单备注。它也被钱包用来提供更多的上下文信息给用户。
包含在支付交易中的注释。这不应该包含任何私人或敏感信息,因为这些信息是链上存储的。
这些细节使你对交易拥有全面的掌控能力,使你的钱包与接收人的互动变得简单明了。为确保安全,应用程序应在交易在链上得到确认后才处理交易。
发送0.5 SOL:
代码
solana:CckxW6C1CjsxYcXSiDbk7NYfPLhfqAm3kSB5LEZunnSE?amount=0.5&label=Amazon&message=Thanks%20for%20shopping%20at%20Amazon&memo=ID321
发送5 USDC:
代码
solana:CckxW6C1CjsxYcXSiDbk7NYfPLhfqAm3kSB5LEZunnSE?amount=5&spl-token=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
我们将构建什么?在本教程结束时,你应该有一个网络应用程序,它可以从用户输入的数据(钱包地址和SOL的数量)创建一个Solana Pay二维码。该应用还将通过在区块链上检查交易状态来显示支付状态。
按照这些步骤使用Solana Pay与Next.js。
首先确保已安装Node,然后创建 Next.js 应用。在终端输入以下命令:
代码
npx create-next-app@latest sol-pay-app
接下来会提示你几个问题,你可以选择以下选项:
创建完成后,你可以通过进入目录导航:
代码
cd sol-pay-app
进入目录后,你可以通过以下命令启动应用:
代码
npm run dev
你可以访问http://localhost:3000/来查看你的应用。
此应用需要安装两个包:Solana web3.js和Solana Pay。我们还将使用一个名为“react-qr-code”的包来生成交易链接的二维码版本。
要安装这些包,你可以运行:
代码
npm install @solana/pay @solana/web3.js bignumber.js react-qr-code --save
创建前端以显示Solana Pay二维码,并允许编辑接收SOL的地址和SOL的数量。出于安全原因,建议在后端执行所有逻辑(尤其是设置金额和接收者)。
然而,为了简化,我们还将在前端执行应用的逻辑。
代码
export default function Home() {
return (
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100">
<h1 className="mb-6 text-3xl font-bold text-orange-700">
Helius Solana Pay Demo
</h1>
</div>
);
}
代码
// imports
import {Cluster,clusterApiUrl,Connection,PublicKey,Keypair} from "@solana/web3.js";
import { encodeURL, createQR,findReference, FindReferenceError, validateTransfer } from "@solana/pay";
import BigNumber from "bignumber.js";
import { useState } from "react";
import QRCode from "react-qr-code";
代码
// get a free Helius RPC at helius.dev
const RPC="https://rpc.helius.xyz/?api-key="!
代码
console.log('Connecting to the Solana network\n');
const connection = new Connection(RPC, 'confirmed');
Home()
函数内部创建这些变量。代码
// URL Variables
const [address, setAddress] = useState("");
const [recipient, setRecipient] = useState(
new PublicKey("CckxW6C1CjsxYcXSiDbk7NYfPLhfqAm3kSB5LEZunnSE"));
const [amount, setAmount] = useState(new BigNumber(1));
const [message, setMessage] = useState("Helius Demo Order");
const reference = new Keypair().publicKey;
const label = "Helius Super Store";
const memo = "Helius#4098";
// for the QR code
const [qrCodeValue, setQrCodeValue] = useState('');
const [paymentStatus, setPaymentStatus] = useState('');
代码
async function createPayment() {
console.log("Creating a payment URL \n");
setRecipient(new PublicKey(address));
const url = encodeURL({
recipient,
amount,
reference,
label,
message,
memo,
});
setQrCodeValue(url.toString()); // 将URL对象转换为字符串
checkPayment();
}
createPayment
函数中,你可以看到我们在创建交易后调用此函数。代码
async function checkPayment() {
// 更新时间状态
setPaymentStatus('pending');
// 搜索交易
// 验证交易
}
这个函数将包含两个部分:搜索确认的交易和验证交易。
由于用户将从不同的设备与交易进行交互,因此没有办法确切知道交易何时发生。相反,我们将不断检查是否发生了与匹配引用的交易及其状态。这个过程是通过Solana Pay的findReference
方法完成的。
代码
// 搜索交易
console.log('Searching for the payment\n');
let signatureInfo;
const {signature} = await new Promise((resolve, reject) => {
const interval = setInterval(async () => {
console.count('Checking for transaction...'+reference);
try {
signatureInfo = await findReference(connection, reference, { finality: 'confirmed' });
console.log('\n Signature: ', signatureInfo.signature,signatureInfo);
clearInterval(interval);
resolve(signatureInfo);
} catch (error: any) {
if (!(error instanceof FindReferenceError)) {
console.error(error);
clearInterval(interval);
reject(error);
}
}
}, 250);
});
// 更新支付状态
setPaymentStatus('confirmed');
一旦找到交易,我们需要确保交易中的正确事项发生。
这包括检查正确的收款人是否收到了代币,以及正确数量的代币是否被发送。为此,我们将使用Solana Pay的validateTransfer
方法:
代码
// 验证交易
console.log('Validating the payment\n');
try {
await validateTransfer(connection, signature, { recipient: recipient, amount });
// 更新支付状态
setPaymentStatus('validated');
console.log('Payment validated');
return true;
} catch (error) {
console.error('支付失败', error);
return false;
}
createPayment
方法。代码
// 验证交易
return (
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100">
<h1 className="mb-6 text-3xl font-bold text-orange-700">
Helius Solana Pay Demo
</h1>
<div className="w-full max-w-md p-6 mx-auto bg-white rounded-xl shadow-md">
<div className="mb-4">
<label className="block mb-2 text-sm font-medium text-gray-700">
地址:
</label>
<input
type="text"
onChange={(e) => setAddress(e.target.value)}
className="w-full px-3 py-2 text-sm leading-tight text-gray-700 border rounded shadow appearance-none focus:outline-none focus:shadow-outline"
/>
</div>
<div className="mb-4">
<label className="block mb-2 text-sm font-medium text-gray-700">
数量:
</label>
<input
type="number"
onChange={(e) => setAmount(new BigNumber(e.target.value))}
className="w-full px-3 py-2 text-sm leading-tight text-gray-700 border rounded shadow appearance-none focus:outline-none focus:shadow-outline"
/>
</div>
<div className="flex justify-center items-center">
<button
className="px-4 py-2 font-bold text-white bg-blue-500 rounded hover:bg-blue-700"
onClick={createPayment}
>
创建二维码
</button>
</div>
<div>
{paymentStatus === 'validated' ? <p className="mt-4 text-green-500 text-center">支付验证</p> : <div className="flex justify-center mt-4">
{qrCodeValue && }
</div>}
</div>
</div>
</div>
);
完成所有这些步骤后,你应该会有一个外观和行为如下的应用:
无论你是在进行支付还是设置交易,Solana Pay的编码系统为用户和应用提供了无缝的体验。希望本指南能作为一个综合工具,帮助理解和实现Solana Pay,使你与Solana区块链的互动更加顺畅和高效。如需任何帮助,请随时加入Helius Discord或在Twitter上联系。
- 原文链接: helius.dev/blog/solana-p...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!