Tài liệu SolanaBắt Đầu Nhanh

Luồng Thanh Toán Headless

Luồng Thanh Toán

Gói @solana-commerce/headless cung cấp các hàm độc lập framework để xây dựng luồng thanh toán thương mại. Những công cụ này giúp tạo các đối tượng yêu cầu thanh toán, tạo URL Solana Pay, và xác minh các khoản thanh toán trên chuỗi. Gói này được thiết kế để hoạt động trong bất kỳ môi trường JavaScript nào: React, Vue, Svelte, vanilla JS, Node.js, hoặc các hàm serverless.

Cài Đặt

pnpm add @solana-commerce/headless

Các Hàm Yêu Cầu Thanh Toán

Những hàm này tạo ra các đối tượng yêu cầu thanh toán chuẩn hóa cho các mô hình thương mại khác nhau. Chúng không thực hiện bất kỳ thao tác blockchain nào—chúng chỉ cấu trúc dữ liệu để sử dụng trong ví, URL Solana Pay, hoặc giao diện thanh toán tùy chỉnh.

createBuyNowRequest()

Tạo một yêu cầu thanh toán chuẩn hóa cho việc mua một sản phẩm đơn lẻ.

function createBuyNowRequest(
recipient: string,
product: any,
options?: {
memo?: string;
label?: string;
message?: string;
}
): PaymentRequest;

Tham Số

  • recipient (string, bắt buộc) - Địa chỉ ví merchant (khóa công khai Solana mã hóa base58) sẽ nhận khoản thanh toán.

  • product (any, bắt buộc) - Đối tượng sản phẩm chứa:

    • price (số, bắt buộc) - Giá sản phẩm. Đơn vị phụ thuộc vào ngữ cảnh (ví dụ: lamport cho SOL, đơn vị nhỏ cho token).
    • currency (chuỗi, bắt buộc) - Tiền tệ thanh toán. Có thể là 'SOL' hoặc địa chỉ mint token.
    • name (chuỗi, bắt buộc) - Tên sản phẩm, được sử dụng cho memo/nhãn mặc định nếu không được cung cấp.
    • Các trường bổ sung (id, description, image, v.v.) được truyền qua trong mảng products.
  • options (đối tượng, tùy chọn) - Các tùy chọn tùy chỉnh:

    • memo (chuỗi) - Memo trên chuỗi cho giao dịch. Mặc định: "Purchase: {product.name}".
    • label (chuỗi) - Nhãn hiển thị cho yêu cầu thanh toán (sử dụng trong Solana Pay). Mặc định: product.name.
    • message (chuỗi) - Thông báo thành công hiển thị sau khi thanh toán. Mặc định: "Thank you for purchasing {product.name}!".

Giá Trị Trả Về

Một đối tượng PaymentRequest chứa:

  • recipient - Địa chỉ ví merchant
  • amount - Giá sản phẩm (sao chép từ product.price)
  • currency - Tiền tệ thanh toán (sao chép từ product.currency)
  • products - Mảng chứa sản phẩm đơn lẻ
  • memo - Memo giao dịch (tùy chọn hoặc mặc định: "Purchase: (product.name)")
  • label - Nhãn thanh toán (tùy chọn hoặc mặc định: "product.name")
  • message - Thông báo thành công (tùy chọn hoặc mặc định: "Thank you for purchasing (product.name)!")

Ví dụ:

const payment = createBuyNowRequest(
"merchant-wallet-address",
{
id: "prod_123",
name: "Premium Subscription",
price: 50000000, // 0.05 SOL in lamports
currency: "SOL"
},
{
label: "Premium Subscription",
message: "Thank you for subscribing!"
}
);

createCartRequest()

Tạo yêu cầu thanh toán cho nhiều sản phẩm trong giỏ hàng.

function createCartRequest(
recipient: string,
products: any[],
options?: {
memo?: string;
label?: string;
message?: string;
currency?: string;
}
): PaymentRequest;

Tham số

  • recipient (string, bắt buộc) - Địa chỉ ví của người bán sẽ nhận thanh toán.

  • products (any[], bắt buộc) - Mảng các đối tượng sản phẩm.

  • options (object, tùy chọn) - Các tùy chọn tùy chỉnh:

    • currency (string) - Loại tiền thanh toán cho toàn bộ giỏ hàng.
    • memo (string) - Ghi chú trên chuỗi. Mặc định: "Cart purchase (products.length items)".
    • label (string) - Nhãn thanh toán. Mặc định: "Cart Checkout".
    • message (string) - Thông báo thành công. Mặc định: "Thank you for your purchase!".

Giá trị trả về

Một đối tượng PaymentRequest với:

  • recipient - Địa chỉ ví của người bán
  • amount - Tổng giá của tất cả sản phẩm (products.reduce((sum, p) => sum + p.price, 0))
  • currency - Loại tiền thanh toán (từ options, hoặc undefined)
  • products - Mảng các sản phẩm
  • memo, label, message - Giá trị tùy chọn hoặc giá trị mặc định

Ví dụ:

const cart = createCartRequest(
"merchant-wallet-address",
[
{ id: "1", name: "Product A", price: 25 },
{ id: "2", name: "Product B", price: 15 },
{ id: "3", name: "Product C", price: 10 }
],
{
currency: "USDC",
label: "My Store Checkout",
message: "Thank you for your order!"
}
);
// cart.amount === 50 (sum of prices)

createTipRequest()

Tạo yêu cầu thanh toán cho tiền boa hoặc quyên góp với số tiền do người dùng xác định.

function createTipRequest(
recipient: string,
amount: number,
options?: {
currency?: string;
memo?: string;
label?: string;
message?: string;
}
): PaymentRequest;

Tham số

  • recipient (string, bắt buộc) - Địa chỉ ví của người nhận tiền boa (người sáng tạo, streamer, tổ chức từ thiện, v.v.).

  • amount (number, bắt buộc) - Số tiền boa. Đơn vị phụ thuộc vào loại tiền (lamport cho SOL, đơn vị nhỏ cho token).

  • options (object, tùy chọn) - Các tùy chọn tùy chỉnh:

    • currency (string) - Loại tiền thanh toán. Mặc định: undefined (thông thường được xử lý là SOL bởi người tiêu dùng).
    • memo (string) - Ghi chú trên chuỗi. Mặc định: "Thank you for your support!".
    • label (string) - Nhãn thanh toán. Mặc định: "Tip".
    • message (string) - Thông báo thành công. Mặc định: "Thanks for the tip!".

Giá trị trả về

Một đối tượng PaymentRequest với:

  • recipient - Địa chỉ ví của người nhận tiền boa
  • amount - Số tiền boa
  • currency - Loại tiền thanh toán (từ options, hoặc undefined)
  • memo, label, message - Giá trị tùy chọn hoặc giá trị mặc định

Ví dụ:

const tip = createTipRequest(
"creator-wallet-address",
5_000_000, // 0.005 SOL in lamports
{
currency: "SOL",
label: "Tip for Content Creator",
message: "Thanks for the support!"
}
);

Các Hàm Xác Minh Thanh Toán

Các hàm này tương tác với Solana để xác minh giao dịch và chờ xác nhận. Chúng yêu cầu một RPC client của Solana từ thư viện gill.

verifyPayment()

Xác minh rằng một giao dịch tồn tại trên chuỗi và tùy chọn xác thực số tiền thanh toán, người nhận và token.

async function verifyPayment(
rpc: SolanaClient["rpc"],
signatureString: string,
expectedAmount?: number,
expectedRecipient?: string,
expectedMint?: string
): Promise<PaymentVerificationResult>;

Tham Số

  • rpc (SolanaClient['rpc'], bắt buộc) - RPC client từ gill. Tạo bằng createSolanaClient(rpcUrl).rpc.

  • signatureString (string, bắt buộc) - Chữ ký giao dịch (mã hóa base58) cần xác minh.

  • expectedAmount (number, tùy chọn) - Số tiền thanh toán dự kiến để xác thực. Đơn vị phải phù hợp với loại tiền tệ:

    • Đối với SOL: lamport (1 SOL = 1.000.000.000 lamport)
    • Đối với SPL token: đơn vị nhỏ nhất dựa trên số thập phân của token (ví dụ: USDC sử dụng 6 chữ số thập phân)

    Nếu không được cung cấp, việc xác thực số tiền sẽ bị bỏ qua.

  • expectedRecipient (string, tùy chọn) - Địa chỉ ví người nhận dự kiến. Nếu được cung cấp (cùng với expectedAmount), hàm sẽ xác thực rằng người nhận đã nhận được ít nhất số tiền này. Nếu không được cung cấp, việc xác thực sẽ bị bỏ qua.

  • expectedMint (string, tùy chọn) - Địa chỉ mint của SPL token. Chỉ yêu cầu cho các giao dịch chuyển SPL token. Nếu không được cung cấp, hàm sẽ giả định đó là giao dịch chuyển SOL.

Giá Trị Trả Về

Một đối tượng Promise<PaymentVerificationResult>:

interface PaymentVerificationResult {
verified: boolean; // True if payment is valid
signature?: string; // Transaction signature (echoed back)
amount?: number; // Expected amount (echoed back)
recipient?: string; // Expected recipient (echoed back)
error?: string; // Error message if verification failed
}

Logic Xác Minh

Hàm thực hiện các kiểm tra sau:

  1. Tính Hợp Lệ Của Chữ Ký: Kiểm tra rằng chữ ký hợp lệ.

  2. Sự Tồn Tại Của Giao Dịch: Lấy giao dịch bằng rpc.getTransaction(). Nếu không tìm thấy, trả về verified: false.

  3. Trạng Thái Xác Nhận: Kiểm tra rằng giao dịch đã được ghi nhận trên chuỗi.

  4. Xác Thực Giao Dịch Chuyển SOL (nếu có expectedRecipientexpectedAmount được cung cấp, và không có expectedMint):

    • Tìm chỉ số tài khoản của người nhận trong giao dịch
    • So sánh preBalancespostBalances để tính toán chênh lệch số dư
    • Xác minh rằng chênh lệch ít nhất bằng expectedAmount
  5. Xác thực chuyển SPL Token (nếu có expectedMint):

    • Tạo Associated Token Account (ATA) của người nhận cho cả Token Program và Token-2022 Program
    • Kiểm tra postTokenBalances để tìm ATA khớp với mint mong đợi
    • Xác minh số lượng token ít nhất là expectedAmount

Các cân nhắc về bảo mật

  • Xác minh phía Client: Hàm này lấy dữ liệu giao dịch từ RPC. Không để lộ URL RPC của bạn cho client.
  • Hoàn tất: Hàm kiểm tra các giao dịch đã xác nhận, nhưng đối với thanh toán có giá trị cao, hãy cân nhắc chờ trạng thái finalized.

Ví dụ:

import { verifyPayment } from "@solana-commerce/headless";
import { createSolanaClient } from "gill";
const client = createSolanaClient({
urlOrMoniker: "mainnet"
});
const result = await verifyPayment(
client.rpc,
"transaction-signature-here",
50_000_000, // 0.05 SOL in lamports
"merchant-wallet-address"
// No mint = SOL transfer
);
if (result.verified) {
console.log("Payment confirmed!");
} else {
console.error("Verification failed:", result.error);
}

waitForConfirmation()

Kiểm tra blockchain cho đến khi giao dịch đạt trạng thái đã xác nhận hoặc đã hoàn tất, hoặc hết thời gian chờ.

async function waitForConfirmation(
rpc: SolanaClient["rpc"],
signatureStr: string,
timeoutMs?: number
): Promise<boolean>;

Tham số

  • rpc (SolanaClient['rpc'], bắt buộc) - RPC client từ gill.

  • signatureStr (string, bắt buộc) - Chữ ký giao dịch cần chờ.

  • timeoutMs (number, tùy chọn) - Thời gian chờ tối đa tính bằng mili giây. Mặc định: 30000 (30 giây).

Trả về

  • Promise<boolean> - Trả về true nếu giao dịch đạt trạng thái confirmed hoặc finalized trong thời gian chờ, ngược lại trả về false.

Ví dụ:

import { waitForConfirmation } from "@solana-commerce/headless";
import { createSolanaClient } from "gill";
const client = createSolanaClient({
urlOrMoniker: "mainnet"
});
// After sending transaction
const signature = await wallet.sendTransaction(transaction);
// Wait for confirmation (30 second timeout)
const confirmed = await waitForConfirmation(client.rpc, signature, 30000);
if (confirmed) {
console.log("Transaction confirmed!");
} else {
console.log("Timeout - transaction not confirmed within 30 seconds");
}

Các hàm Solana Pay

Các hàm này tạo URL Solana Pay và mã QR có kiểu dáng để quét bằng ví di động.

createSolanaPayRequest()

Tạo một URL Solana Pay và mã QR có kiểu dáng.

async function createSolanaPayRequest(
request: TransferRequestURLFields,
options: SolanaPayRequestOptions
): Promise<{ url: URL; qr: string }>;

Tham số

  • request (TransferRequestURLFields, bắt buộc) - Các trường yêu cầu chuyển khoản Solana Pay:

    • recipient - Khóa công khai của người nhận (sử dụng createRecipient(address) từ @solana-commerce/solana-pay)
    • amount - (tùy chọn) Số tiền thanh toán theo đơn vị nhỏ nhất (lamport cho SOL)
    • splToken (tùy chọn) - Khóa công khai của SPL token mint (sử dụng createSPLToken(address))
    • reference (tùy chọn) - Khóa công khai tham chiếu để theo dõi
    • label (tùy chọn) - Tên người bán
    • message (tùy chọn) - Thông báo thành công
    • memo (tùy chọn) - Ghi chú trên chuỗi
  • options (SolanaPayRequestOptions, bắt buộc) - Các tùy chọn tạo kiểu mã QR:

    • size (number) - Chiều rộng/chiều cao của mã QR tính bằng pixel. Mặc định: 256.
    • background (string) - Màu nền (hex/rgb). Mặc định: 'white'.
    • color (string) - Màu mã QR (hex/rgb). Mặc định: 'black'.
    • margin (number) - Lề xung quanh mã QR tính bằng module.
    • errorCorrectionLevel ('L' | 'M' | 'Q' | 'H') - Mức độ sửa lỗi. Mức độ cao hơn cho phép chịu được nhiều hư hỏng hơn nhưng tạo mã dày đặc hơn.
    • logo (string) - URL hình ảnh logo để nhúng vào trung tâm mã QR.
    • logoSize (number) - Kích thước logo tính theo phần trăm kích thước mã QR.
    • logoBackgroundColor (string) - Màu nền phía sau logo.
    • logoMargin (number) - Lề xung quanh logo.
    • dotStyle ('dots' | 'rounded' | 'square') - Hình dạng của các module mã QR.
    • cornerStyle ('square' | 'rounded' | 'extra-rounded' | 'full-rounded' | 'maximum-rounded') - Hình dạng của các điểm đánh dấu góc.

Giá trị trả về

Một Promise phân giải thành một đối tượng:

  • url (URL) - URL Solana Pay (ví dụ: solana:recipient?amount=10&spl-token=...)
  • qr (string) - URL dữ liệu được mã hóa Base64 của hình ảnh mã QR (sử dụng làm <img src={qr} />)

Ví dụ:

import {
createSolanaPayRequest,
createRecipient,
createSPLToken
} from "@solana-commerce/solana-pay";
const payment = await createSolanaPayRequest(
{
recipient: createRecipient("merchant-wallet-address"),
amount: 10_000_000, // 0.01 SOL in lamports
splToken: createSPLToken("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"), // USDC
label: "My Store",
message: "Thank you for your purchase!"
},
{
size: 400,
background: "#FFFFFF",
color: "#000000",
logo: "/logo.png",
logoSize: 20,
errorCorrectionLevel: "H"
}
);
// Display QR code
document.getElementById("qr").src = payment.qr;
console.log(payment.url.toString()); // solana:merchant...?amount=10000000&spl-token=...

Is this page helpful?

Quản lý bởi

© 2026 Solana Foundation.
Đã đăng ký bản quyền.
Kết nối