Flujos de Pago
El paquete @solana-commerce/headless proporciona funciones independientes del
framework para construir flujos de pago de comercio electrónico. Estas
herramientas ayudan a crear objetos de solicitud de pago, generar URLs de Solana
Pay y verificar pagos en la cadena. El paquete está diseñado para funcionar en
cualquier entorno JavaScript: React, Vue, Svelte, JS vanilla, Node.js o
funciones serverless.
Instalación
pnpm add @solana-commerce/headless
Funciones de Solicitud de Pago
Estas funciones crean objetos de solicitud de pago estandarizados para diferentes patrones de comercio. No realizan ninguna operación de blockchain—simplemente estructuran datos para su uso en billeteras, URLs de Solana Pay o interfaces de pago personalizadas.
createBuyNowRequest()
Crea una solicitud de pago estandarizada para la compra de un solo producto.
function createBuyNowRequest(recipient: string,product: any,options?: {memo?: string;label?: string;message?: string;}): PaymentRequest;
Parámetros
-
recipient(string, obligatorio) - Dirección de la billetera del comerciante (clave pública de Solana codificada en base58) que recibirá el pago. -
product(any, obligatorio) - Objeto del producto que contiene:price(número, obligatorio) - Precio del producto. La unidad depende del contexto (ej., lamports para SOL, unidades menores para tokens).currency(cadena, obligatorio) - Moneda de pago. Puede ser'SOL'o una dirección mint de token.name(cadena, obligatorio) - Nombre del producto, usado para el memo/etiqueta predeterminado si no se proporciona.- Los campos adicionales (id, descripción, imagen, etc.) se transmiten en el
array
products.
-
options(objeto, opcional) - Opciones de personalización:memo(cadena) - Memo en cadena para la transacción. Predeterminado:"Purchase: {product.name}".label(cadena) - Etiqueta de visualización para la solicitud de pago (usada en Solana Pay). Predeterminado:product.name.message(cadena) - Mensaje de éxito mostrado después del pago. Predeterminado:"Thank you for purchasing {product.name}!".
Retorna
Un objeto PaymentRequest que contiene:
recipient- La dirección de la billetera del comercianteamount- El precio del producto (copiado deproduct.price)currency- Moneda de pago (copiado deproduct.currency)products- Array que contiene el único productomemo- Memo de transacción (opción o predeterminado: "Compra: (product.name)")label- Etiqueta de pago (opción o predeterminado: "product.name")message- Mensaje de éxito (opción o predeterminado: "Gracias por comprar (product.name)!")
Ejemplo:
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()
Crea una solicitud de pago para múltiples productos en un carrito de compras.
function createCartRequest(recipient: string,products: any[],options?: {memo?: string;label?: string;message?: string;currency?: string;}): PaymentRequest;
Parámetros
-
recipient(string, requerido) - Dirección de la billetera del comerciante que recibirá el pago. -
products(any[], requerido) - Array de objetos de productos. -
options(objeto, opcional) - Opciones de personalización:currency(cadena) - Moneda de pago para todo el carrito.memo(cadena) - Nota on-chain. Por defecto:"Cart purchase (products.length items)".label(cadena) - Etiqueta de pago. Por defecto:"Cart Checkout".message(cadena) - Mensaje de éxito. Por defecto:"Thank you for your purchase!".
Retorna
Un objeto PaymentRequest con:
recipient- La dirección de la billetera del comercianteamount- Suma de todos los precios de productos (products.reduce((sum, p) => sum + p.price, 0))currency- Moneda de pago (de las opciones, o indefinido)products- El array de productosmemo,label,message- Valores de opciones o por defecto
Ejemplo:
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()
Crea una solicitud de pago para propinas o donaciones con un monto definido por el usuario.
function createTipRequest(recipient: string,amount: number,options?: {currency?: string;memo?: string;label?: string;message?: string;}): PaymentRequest;
Parámetros
-
recipient(string, requerido) - Dirección de la billetera del destinatario de la propina (creador, streamer, organización benéfica, etc.). -
amount(number, requerido) - Monto de la propina. La unidad depende de la moneda (lamports para SOL, unidades menores para tokens). -
options(objeto, opcional) - Opciones de personalización:currency(cadena) - Moneda de pago. Por defecto: indefinido (típicamente tratado como SOL por los consumidores).memo(cadena) - Nota on-chain. Por defecto:"Thank you for your support!".label(cadena) - Etiqueta de pago. Por defecto:"Tip".message(cadena) - Mensaje de éxito. Por defecto:"Thanks for the tip!".
Retorna
Un objeto PaymentRequest con:
recipient- La dirección de la billetera del destinatario de la propinaamount- El monto de la propinacurrency- Moneda de pago (de las opciones, o indefinido)memo,label,message- Valores de opciones o por defecto
Ejemplo:
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!"});
Funciones de Verificación de Pagos
Estas funciones interactúan con Solana para verificar transacciones y esperar
confirmaciones. Requieren un cliente RPC de Solana de la biblioteca gill.
verifyPayment()
Verifica que una transacción exista en la cadena y, opcionalmente, valida el monto del pago, el destinatario y el token.
async function verifyPayment(rpc: SolanaClient["rpc"],signatureString: string,expectedAmount?: number,expectedRecipient?: string,expectedMint?: string): Promise<PaymentVerificationResult>;
Parámetros
-
rpc(SolanaClient['rpc'], requerido) - Cliente RPC degill. Crear concreateSolanaClient(rpcUrl).rpc. -
signatureString(string, requerido) - Firma de la transacción (codificada en base58) para verificar. -
expectedAmount(number, opcional) - Monto de pago esperado para validar. La unidad debe coincidir con la moneda:- Para SOL: lamports (1 SOL = 1,000,000,000 lamports)
- Para tokens SPL: unidades menores basadas en los decimales del token (por ejemplo, USDC utiliza 6 decimales)
Si no se proporciona, se omite la validación del monto.
-
expectedRecipient(string, opcional) - Dirección de la billetera del destinatario esperado. Si se proporciona (junto conexpectedAmount), la función valida que el destinatario haya recibido al menos esta cantidad. Si no se proporciona, se omite la validación. -
expectedMint(string, opcional) - Dirección mint del token SPL. Solo requerido para transferencias de tokens SPL. Si no se proporciona, la función asume una transferencia de SOL.
Retorna
Un objeto 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}
Lógica de Verificación
La función realiza estas comprobaciones:
-
Validez de la Firma: Verifica que la firma sea válida.
-
Existencia de la Transacción: Obtiene la transacción usando
rpc.getTransaction(). Si no se encuentra, retornaverified: false. -
Estado de Confirmación: Verifica que la transacción se haya registrado en la cadena.
-
Validación de Transferencia de SOL (si se proporcionan
expectedRecipientyexpectedAmount, y no hayexpectedMint):- Encuentra el índice de la cuenta del destinatario en la transacción
- Compara
preBalancesypostBalancespara calcular el delta del saldo - Verifica que el delta sea al menos
expectedAmount
-
Validación de Transferencia de Token SPL (si se proporciona
expectedMint):- Deriva la Cuenta de Token Asociada (ATA) del destinatario tanto para Token Program como para Token-2022 Program
- Verifica
postTokenBalancespara una ATA coincidente con el mint esperado - Verifica que la cantidad de tokens sea al menos
expectedAmount
Consideraciones de Seguridad
- Verificación del Lado del Cliente: Esta función obtiene datos de transacciones desde RPC. No expongas tu URL de RPC al cliente.
- Finalización: La función verifica transacciones confirmadas, pero para
pagos de alto valor, considera esperar el estado
finalized.
Ejemplo:
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()
Sondea la blockchain hasta que una transacción alcance el estado confirmado o finalizado, o se agote el tiempo de espera.
async function waitForConfirmation(rpc: SolanaClient["rpc"],signatureStr: string,timeoutMs?: number): Promise<boolean>;
Parámetros
-
rpc(SolanaClient['rpc'], obligatorio) - Cliente RPC degill. -
signatureStr(string, obligatorio) - Firma de transacción a esperar. -
timeoutMs(number, opcional) - Tiempo máximo de espera en milisegundos. Predeterminado:30000(30 segundos).
Retorna
Promise<boolean>- Retornatruesi la transacción alcanza el estadoconfirmedofinalizeddentro del tiempo de espera,falseen caso contrario.
Ejemplo:
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");}
Funciones de Solana Pay
Estas funciones generan URLs de Solana Pay y códigos QR estilizados para escaneo con billeteras móviles.
createSolanaPayRequest()
Crea una URL de Solana Pay y un código QR estilizado.
async function createSolanaPayRequest(request: TransferRequestURLFields,options: SolanaPayRequestOptions): Promise<{ url: URL; qr: string }>;
Parámetros
-
request(TransferRequestURLFields, obligatorio) - Campos de solicitud de transferencia de Solana Pay:recipient- Clave pública del destinatario (usacreateRecipient(address)de@solana-commerce/solana-pay)amount- (opcional) Monto del pago en unidades menores (lamports para SOL)splToken(opcional) - Clave pública del mint del token SPL (usacreateSPLToken(address))reference(opcional) - Clave pública de referencia para seguimientolabel(opcional) - Nombre del comerciantemessage(opcional) - Mensaje de éxitomemo(opcional) - Memo en cadena
-
options(SolanaPayRequestOptions, requerido) - Opciones de estilo del código QR:size(número) - Ancho/alto del código QR en píxeles. Por defecto:256.background(cadena) - Color de fondo (hex/rgb). Por defecto:'white'.color(cadena) - Color del código QR (hex/rgb). Por defecto:'black'.margin(número) - Margen alrededor del código QR en módulos.errorCorrectionLevel('L' | 'M' | 'Q' | 'H') - Nivel de corrección de errores. Niveles más altos permiten más daño pero crean códigos más densos.logo(cadena) - URL de la imagen del logo para incrustar en el centro del código QR.logoSize(número) - Tamaño del logo como porcentaje del tamaño del código QR.logoBackgroundColor(cadena) - Color de fondo detrás del logo.logoMargin(número) - Margen alrededor del logo.dotStyle('dots' | 'rounded' | 'square') - Forma de los módulos del código QR.cornerStyle('square' | 'rounded' | 'extra-rounded' | 'full-rounded' | 'maximum-rounded') - Forma de los marcadores de esquina.
Devuelve
Una Promise que se resuelve en un objeto:
url(URL) - URL de Solana Pay (por ejemplo,solana:recipient?amount=10&spl-token=...)qr(cadena) - URL de datos codificada en Base64 de la imagen del código QR (usar como<img src={qr} />)
Ejemplo:
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?