Yêu cầu chuyển khoản là hình thức tích hợp Solana Pay đơn giản nhất. Chúng tạo ra URL thanh toán không tương tác mà ví có thể sử dụng để trực tiếp soạn thảo và gửi giao dịch mà không cần máy chủ.
Tổng quan
URL yêu cầu chuyển khoản tuân theo định dạng sau:
solana:<recipient>?amount=<amount>&spl-token=<spl-token>&reference=<reference>&label=<label>&message=<message>&memo=<memo>
Chuyển SOL cơ bản
Tạo yêu cầu thanh toán SOL đơn giản:
import { address } from "@solana/kit";import { encodeURL } from "@solana/pay";// Recipient's Solana wallet addressconst recipient = address("FvJ8k8HhXp4a3zQyFMZd4FvEqcYdYE7gSZWxrEBRfBsB");// Create the payment URLconst url = encodeURL({recipient,amount: 0.01, // 0.01 SOLlabel: "My Store",message: "Thanks for your purchase!"});console.log(url.toString());// Output: solana:FvJ8k8Hh...?amount=0.01&label=My%20Store&message=Thanks%20for%20your%20purchase!
Chuyển token SPL
Tạo yêu cầu thanh toán USDC:
import { address } from "@solana/kit";import { encodeURL } from "@solana/pay";// USDC mint address on mainnetconst usdcMint = address("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");const url = encodeURL({recipient: address("FvJ8k8HhXp4a3zQyFMZd4FvEqcYdYE7gSZWxrEBRfBsB"),amount: 10.5, // $10.50 USDCsplToken: usdcMint,label: "Coffee Shop",message: "Grande Latte + Tip"});console.log(url.toString());
Tham số URL
Tham số bắt buộc
Người nhận
Địa chỉ ví Solana của người nhận (mã hóa base58):
const recipient = address("FvJ8k8HhXp4a3zQyFMZd4FvEqcYdYE7gSZWxrEBRfBsB");
Tham số tùy chọn
Số tiền
Số tiền thanh toán theo đơn vị thân thiện với người dùng (đơn vị SOL hoặc token):
// SOL amountsconst solAmount = 1.5; // 1.5 SOLconst smallAmount = 0.001; // 0.001 SOL// Token amounts (USDC example)const usdcAmount = 25.99; // $25.99 USDC
Nếu bỏ qua, ví sẽ nhắc người dùng nhập số tiền.
Token SPL
Đối với giao dịch chuyển token, chỉ định địa chỉ mint:
// Common SPL tokensconst USDC = address("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");const USDT = address("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB");// Omit splToken for native SOL transfers
Tham chiếu
Mã định danh duy nhất để theo dõi các khoản thanh toán. Tạo một địa chỉ để sử dụng làm khóa tham chiếu:
import { generateKeyPair, getAddressFromPublicKey } from "@solana/kit";// Generate a unique referenceconst keypair = await generateKeyPair();const reference = await getAddressFromPublicKey(keypair.publicKey);
Nhãn
Tên thương hiệu hoặc ứng dụng hiển thị cho người dùng:
const label = "Acme Coffee Shop";
Thông điệp
Mô tả về khoản thanh toán:
const message = "Order #12345 - 2x Americano";
Ghi chú
Ghi chú trên chuỗi (công khai hiển thị):
const memo = "OrderId:12345";
Tích hợp mã QR
Tạo mã QR bằng hàm createQR tích hợp sẵn:
import { address } from "@solana/kit";import { encodeURL, createQR } from "@solana/pay";const url = encodeURL({recipient: address("FvJ8k8HhXp4a3zQyFMZd4FvEqcYdYE7gSZWxrEBRfBsB"),amount: 0.05,label: "Donation",message: "Support our project"});// Generate a QR code elementconst qr = createQR(url);// Append to DOMconst element = document.getElementById("qr-code");qr.append(element);
Xác thực thanh toán
Sử dụng Merchant Client
Cách đơn giản nhất để tìm và xác thực các khoản thanh toán:
import { address } from "@solana/kit";import { createMerchantClient } from "@solana/pay";const merchant = createMerchantClient({rpcUrl: "https://api.mainnet-beta.solana.com"});const recipient = address("FvJ8k8HhXp4a3zQyFMZd4FvEqcYdYE7gSZWxrEBRfBsB");const reference = address("YOUR_REFERENCE_ADDRESS");// Find the transaction by referenceconst found = await merchant.pay.findReference(reference);// Validate the transfer matches expected fieldsawait merchant.pay.validateTransfer(found.signature, {recipient,amount: 0.1});console.log("Payment confirmed!", found.signature);
Sử dụng các hàm độc lập
import { createSolanaRpc, address } from "@solana/kit";import { findReference, validateTransfer } from "@solana/pay";const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");const reference = address("YOUR_REFERENCE_ADDRESS");// Find transaction by referenceconst found = await findReference(rpc, reference);// Validate transaction detailsawait validateTransfer(rpc, found.signature, {recipient: address("FvJ8k8HhXp4a3zQyFMZd4FvEqcYdYE7gSZWxrEBRfBsB"),amount: 0.1});console.log("Payment confirmed!", found.signature);
Theo dõi các khoản thanh toán (WebSocket)
Phương pháp được khuyến nghị — watchReference đăng ký qua WebSocket và trả về
ngay khi có giao dịch khớp. Không cần thăm dò.
async function waitForPayment(reference, recipient, amount) {const merchant = createMerchantClient({rpcUrl: "https://api.mainnet-beta.solana.com"});// Resolves on the first transaction mentioning this referenceconst result = await merchant.pay.watchReference(reference);if (result.err) {throw new Error(`Transaction failed: ${JSON.stringify(result.err)}`);}// Validate that the transaction matches the expected paymentawait merchant.pay.validateTransfer(result.signature, { recipient, amount });return { signature: result.signature };}
Thăm dó các khoản thanh toán (HTTP dự phòng)
Nếu đăng ký WebSocket không khả dụng (ví dụ: một số nhà cung cấp RPC), hãy dùng
phương pháp polling với findReference:
async function pollForPayment(reference, recipient, amount) {const merchant = createMerchantClient({rpcUrl: "https://api.mainnet-beta.solana.com"});const checkPayment = async () => {try {const found = await merchant.pay.findReference(reference);await merchant.pay.validateTransfer(found.signature, {recipient,amount});return { success: true, signature: found.signature };} catch {return { success: false };}};// Check every 2 secondsreturn new Promise((resolve) => {const interval = setInterval(async () => {const result = await checkPayment();if (result.success) {clearInterval(interval);resolve(result);}}, 2000);});}
Ví dụ Hoàn chỉnh
Đây là một ví dụ hoàn chỉnh với tạo mã QR và giám sát thanh toán:
import { address, generateKeyPair, getAddressFromPublicKey } from "@solana/kit";import { encodeURL, createQR, createMerchantClient } from "@solana/pay";const recipient = address("FvJ8k8HhXp4a3zQyFMZd4FvEqcYdYE7gSZWxrEBRfBsB");const amount = 0.1;// Generate unique reference for this paymentconst keypair = await generateKeyPair();const reference = await getAddressFromPublicKey(keypair.publicKey);// Create payment URL and QR codeconst url = encodeURL({recipient,amount,reference,label: "Demo Store",message: "Test Purchase"});const qr = createQR(url);qr.append(document.getElementById("qr-code"));// Monitor for paymentconst merchant = createMerchantClient({rpcUrl: "https://api.mainnet-beta.solana.com"});const interval = setInterval(async () => {try {const found = await merchant.pay.findReference(reference);await merchant.pay.validateTransfer(found.signature, {recipient,amount,reference});clearInterval(interval);console.log("Payment confirmed!", found.signature);} catch {// Payment not found yet, keep polling}}, 2000);
Thực hành Tốt nhất
Bảo mật
- Luôn xác thực thanh toán ở phía máy chủ
- Sử dụng tham chiếu duy nhất cho mỗi giao dịch thanh toán
- Xác minh số tiền và người nhận giao dịch
- Kiểm tra trạng thái thành công của giao dịch
Trải nghiệm Người dùng
- Hiển thị rõ ràng số tiền và mô tả thanh toán
- Cung cấp cập nhật trạng thái thanh toán
- Xử lý kết nối ví một cách mượt mà
- Hỗ trợ cả mã QR và liên kết trực tiếp
Xử lý Lỗi
- Xử lý lỗi kết nối ví
- Cung cấp giải pháp dự phòng cho các ví không được hỗ trợ
- Hiển thị thông báo lỗi hữu ích
- Triển khai thời gian chờ thanh toán
Các Trường hợp Sử dụng Phổ biến
Điểm Bán hàng
const posPayment = encodeURL({recipient: merchantWallet,amount: 15.99,label: "Local Coffee Shop",message: `Receipt #${receiptNumber}`,memo: `POS-${terminalId}-${Date.now()}`});
Quyên góp
// Flexible donation amount (user enters amount in wallet)const donationUrl = encodeURL({recipient: charityWallet,label: "Save the Ocean",message: "Support marine conservation"});
Thanh toán Thương mại Điện tử
const checkoutUrl = encodeURL({recipient: storeWallet,amount: cartTotal,reference: orderReference,label: storeName,message: `Order ${orderId}`,memo: `ORDER:${orderId}`});
Is this page helpful?