Процессы оплаты
Пакет @solana-commerce/headless предоставляет независимые от фреймворка
функции для создания процессов оплаты в электронной коммерции. Эти инструменты
помогают создавать объекты запросов платежей, генерировать URL-адреса Solana Pay
и проверять платежи в блокчейне. Пакет разработан для работы в любой
JavaScript-среде: React, Vue, Svelte, чистый JS, Node.js или serverless-функции.
Установка
pnpm add @solana-commerce/headless
Функции запроса платежей
Эти функции создают стандартизированные объекты запросов платежей для различных коммерческих шаблонов. Они не выполняют никаких операций с блокчейном — они просто структурируют данные для использования в кошельках, URL-адресах Solana Pay или пользовательских интерфейсах платежей.
createBuyNowRequest()
Создает стандартизированный запрос платежа для покупки одного товара.
function createBuyNowRequest(recipient: string,product: any,options?: {memo?: string;label?: string;message?: string;}): PaymentRequest;
Параметры
-
recipient(string, обязательный) - Адрес кошелька продавца (публичный ключ Solana в кодировке base58), который получит платеж. -
product(any, обязательный) - Объект товара, содержащий:price(number, обязательный) - Цена товара. Единица измерения зависит от контекста (например, lamport для SOL, минимальные единицы для токенов).currency(string, обязательный) - Валюта платежа. Может быть'SOL'или адресом минта токена.name(string, обязательный) - Название товара, используется для memo/метки по умолчанию, если не указано иное.- Дополнительные поля (id, description, image и т.д.) передаются в массиве
products.
-
options(object, необязательный) - Параметры настройки:memo(string) - Memo для транзакции в блокчейне. По умолчанию:"Purchase: {product.name}".label(string) - Отображаемая метка для запроса платежа (используется в Solana Pay). По умолчанию:product.name.message(string) - Сообщение об успехе, отображаемое после платежа. По умолчанию:"Thank you for purchasing {product.name}!".
Возвращаемое значение
Объект PaymentRequest, содержащий:
recipient- Адрес кошелька продавцаamount- Цена товара (скопирована изproduct.price)currency- Валюта платежа (скопирована изproduct.currency)products- Массив, содержащий единственный товарmemo- Memo транзакции (параметр или по умолчанию: "Purchase: (product.name)")label- Метка платежа (параметр или по умолчанию: "product.name")message- Сообщение об успехе (параметр или по умолчанию: "Thank you for purchasing (product.name)!")
Пример:
const payment = createBuyNowRequest("merchant-wallet-address",{id: "prod_123",name: "Premium Subscription",price: 50000000, // 0.05 SOL in lamportscurrency: "SOL"},{label: "Premium Subscription",message: "Thank you for subscribing!"});
createCartRequest()
Создает платежный запрос для нескольких товаров в корзине покупок.
function createCartRequest(recipient: string,products: any[],options?: {memo?: string;label?: string;message?: string;currency?: string;}): PaymentRequest;
Параметры
-
recipient(string, обязательный) - Адрес кошелька продавца, который получит платеж. -
products(any[], обязательный) - Массив объектов товаров. -
options(объект, необязательный) - Параметры настройки:currency(строка) - Валюта платежа для всей корзины.memo(строка) - Памятка в блокчейне. По умолчанию:"Cart purchase (products.length items)".label(строка) - Метка платежа. По умолчанию:"Cart Checkout".message(строка) - Сообщение об успехе. По умолчанию:"Thank you for your purchase!".
Возвращает
Объект PaymentRequest с:
recipient- Адрес кошелька продавцаamount- Сумма всех цен товаров (products.reduce((sum, p) => sum + p.price, 0))currency- Валюта платежа (из параметров или undefined)products- Массив товаровmemo,label,message- Значения параметров или значения по умолчанию
Пример:
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()
Создает платежный запрос для чаевых или пожертвований с суммой, определяемой пользователем.
function createTipRequest(recipient: string,amount: number,options?: {currency?: string;memo?: string;label?: string;message?: string;}): PaymentRequest;
Параметры
-
recipient(string, обязательный) - Адрес кошелька получателя чаевых (создателя контента, стримера, благотворительной организации и т. д.). -
amount(number, обязательный) - Сумма чаевых. Единица измерения зависит от валюты (lamport для SOL, минимальные единицы для токенов). -
options(объект, необязательный) - Параметры настройки:currency(строка) - Валюта платежа. По умолчанию: undefined (обычно воспринимается как SOL).memo(строка) - Памятка в блокчейне. По умолчанию:"Thank you for your support!".label(строка) - Метка платежа. По умолчанию:"Tip".message(строка) - Сообщение об успехе. По умолчанию:"Thanks for the tip!".
Возвращает
Объект PaymentRequest с:
recipient- Адрес кошелька получателя чаевыхamount- Сумма чаевыхcurrency- Валюта платежа (из параметров или undefined)memo,label,message- Значения параметров или значения по умолчанию
Пример:
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!"});
Функции проверки платежей
Эти функции взаимодействуют с Solana для проверки транзакций и ожидания
подтверждений. Они требуют клиента Solana RPC из библиотеки gill.
verifyPayment()
Проверяет, что транзакция существует в блокчейне, и опционально валидирует сумму платежа, получателя и токен.
async function verifyPayment(rpc: SolanaClient["rpc"],signatureString: string,expectedAmount?: number,expectedRecipient?: string,expectedMint?: string): Promise<PaymentVerificationResult>;
Параметры
-
rpc(SolanaClient['rpc'], обязательный) - RPC-клиент изgill. Создается с помощьюcreateSolanaClient(rpcUrl).rpc. -
signatureString(string, обязательный) - Подпись транзакции (base58-кодированная) для проверки. -
expectedAmount(number, опциональный) - Ожидаемая сумма платежа для валидации. Единица измерения должна соответствовать валюте:- Для SOL: lamport (1 SOL = 1 000 000 000 lamport)
- Для SPL-токенов: минимальные единицы в зависимости от количества десятичных знаков токена (например, USDC использует 6 десятичных знаков)
Если не указан, валидация суммы пропускается.
-
expectedRecipient(string, опциональный) - Ожидаемый адрес кошелька получателя. Если указан (вместе сexpectedAmount), функция валидирует, что получатель получил как минимум эту сумму. Если не указан, валидация пропускается. -
expectedMint(string, опциональный) - Адрес mint SPL-токена. Требуется только для переводов SPL-токенов. Если не указан, функция предполагает перевод SOL.
Возвращаемое значение
Объект Promise<PaymentVerificationResult>:
interface PaymentVerificationResult {verified: boolean; // True if payment is validsignature?: string; // Transaction signature (echoed back)amount?: number; // Expected amount (echoed back)recipient?: string; // Expected recipient (echoed back)error?: string; // Error message if verification failed}
Логика проверки
Функция выполняет следующие проверки:
-
Валидность подписи: Проверяет, что подпись действительна.
-
Существование транзакции: Получает транзакцию с помощью
rpc.getTransaction(). Если не найдена, возвращаетverified: false. -
Статус подтверждения: Проверяет, что транзакция зафиксирована в блокчейне.
-
Валидация перевода SOL (если указаны
expectedRecipientиexpectedAmount, и не указанexpectedMint):- Находит индекс аккаунта получателя в транзакции
- Сравнивает
preBalancesиpostBalancesдля вычисления изменения баланса - Проверяет, что изменение составляет как минимум
expectedAmount
-
Проверка SPL-токена (если предоставлен
expectedMint):- Получает Associated Token Account (ATA) получателя для Token Program и Token-2022 Program
- Проверяет
postTokenBalancesна наличие соответствующего ATA с ожидаемым mint - Проверяет, что сумма токенов составляет не менее
expectedAmount
Соображения безопасности
- Проверка на стороне клиента: Эта функция получает данные транзакции из RPC. Не раскрывайте ваш RPC URL клиенту.
- Финализация: Функция проверяет подтвержденные транзакции, но для платежей
с высокой стоимостью рекомендуется дождаться статуса
finalized.
Пример:
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()
Опрашивает блокчейн до тех пор, пока транзакция не достигнет статуса confirmed или finalized, или не истечет время ожидания.
async function waitForConfirmation(rpc: SolanaClient["rpc"],signatureStr: string,timeoutMs?: number): Promise<boolean>;
Параметры
-
rpc(SolanaClient['rpc'], обязательный) - RPC-клиент изgill. -
signatureStr(string, обязательный) - Подпись транзакции для ожидания. -
timeoutMs(number, необязательный) - Максимальное время ожидания в миллисекундах. По умолчанию:30000(30 секунд).
Возвращаемое значение
Promise<boolean>- Возвращаетtrue, если транзакция достигает статусаconfirmedилиfinalizedв пределах времени ожидания, в противном случаеfalse.
Пример:
import { waitForConfirmation } from "@solana-commerce/headless";import { createSolanaClient } from "gill";const client = createSolanaClient({urlOrMoniker: "mainnet"});// After sending transactionconst 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");}
Функции Solana Pay
Эти функции генерируют URL Solana Pay и стилизованные QR-коды для сканирования мобильными кошельками.
createSolanaPayRequest()
Создает URL Solana Pay и стилизованный QR-код.
async function createSolanaPayRequest(request: TransferRequestURLFields,options: SolanaPayRequestOptions): Promise<{ url: URL; qr: string }>;
Параметры
-
request(TransferRequestURLFields, обязательный) - Поля запроса перевода Solana Pay:recipient- Публичный ключ получателя (используйтеcreateRecipient(address)из@solana-commerce/solana-pay)amount- (необязательный) Сумма платежа в минимальных единицах (lamport для SOL)splToken(необязательный) - Публичный ключ mint SPL-токена (используйтеcreateSPLToken(address))reference(необязательный) - Референсный публичный ключ для отслеживанияlabel(необязательный) - Название продавцаmessage(необязательный) - Сообщение об успехеmemo(необязательный) - Заметка в блокчейне
-
options(SolanaPayRequestOptions, обязательный) - Параметры стилизации QR-кода:size(число) - Ширина/высота QR-кода в пикселях. По умолчанию:256.background(строка) - Цвет фона (hex/rgb). По умолчанию:'white'.color(строка) - Цвет QR-кода (hex/rgb). По умолчанию:'black'.margin(число) - Отступ вокруг QR-кода в модулях.errorCorrectionLevel('L' | 'M' | 'Q' | 'H') - Уровень коррекции ошибок. Более высокие уровни допускают большее повреждение, но создают более плотные коды.logo(строка) - URL изображения логотипа для встраивания в центр QR-кода.logoSize(число) - Размер логотипа в процентах от размера QR-кода.logoBackgroundColor(строка) - Цвет фона за логотипом.logoMargin(число) - Отступ вокруг логотипа.dotStyle('dots' | 'rounded' | 'square') - Форма модулей QR-кода.cornerStyle('square' | 'rounded' | 'extra-rounded' | 'full-rounded' | 'maximum-rounded') - Форма угловых маркеров.
Возвращаемое значение
Promise, разрешающийся в объект:
url(URL) - URL Solana Pay (например,solana:recipient?amount=10&spl-token=...)qr(строка) - URL данных изображения QR-кода в формате Base64 (используйте как<img src={qr} />)
Пример:
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 lamportssplToken: createSPLToken("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"), // USDClabel: "My Store",message: "Thank you for your purchase!"},{size: 400,background: "#FFFFFF",color: "#000000",logo: "/logo.png",logoSize: 20,errorCorrectionLevel: "H"});// Display QR codedocument.getElementById("qr").src = payment.qr;console.log(payment.url.toString()); // solana:merchant...?amount=10000000&spl-token=...
Is this page helpful?