솔라나 문서빠른 시작

헤드리스 결제 플로우

결제 플로우

@solana-commerce/headless 패키지는 커머스 결제 플로우를 구축하기 위한 프레임워크에 구애받지 않는 함수를 제공합니다. 이러한 도구는 결제 요청 객체 생성, Solana Pay URL 생성, 온체인 결제 검증에 도움을 줍니다. 이 패키지는 React, Vue, Svelte, 바닐라 JS, Node.js 또는 서버리스 함수 등 모든 JavaScript 환경에서 작동하도록 설계되었습니다.

설치

pnpm add @solana-commerce/headless

결제 요청 함수

이러한 함수는 다양한 커머스 패턴에 대한 표준화된 결제 요청 객체를 생성합니다. 블록체인 작업을 수행하지 않으며, 단순히 지갑, Solana Pay URL 또는 커스텀 결제 UI에서 사용할 데이터를 구조화합니다.

createBuyNowRequest()

단일 제품 구매를 위한 표준화된 결제 요청을 생성합니다.

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

매개변수

  • recipient (string, 필수) - 결제를 받을 판매자 지갑 주소(base58로 인코딩된 Solana 공개 키)입니다.

  • product (any, 필수) - 다음을 포함하는 제품 객체:

    • price (number, 필수) - 제품 가격. 단위는 맥락에 따라 다릅니다(예: SOL의 경우 lamport, 토큰의 경우 최소 단위).
    • currency (string, 필수) - 결제 통화. 'SOL' 또는 토큰 민트 주소일 수 있습니다.
    • name (string, 필수) - 제품 이름, 제공되지 않은 경우 기본 메모/레이블로 사용됩니다.
    • 추가 필드(id, description, image 등)는 products 배열에 전달됩니다.
  • options (object, 선택) - 사용자 정의 옵션:

    • memo (string) - 트랜잭션의 온체인 메모. 기본값: "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 - 트랜잭션 메모(옵션 또는 기본값: "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 lamports
currency: "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 (object, 선택) - 사용자 정의 옵션:

    • currency (string) - 전체 장바구니에 대한 결제 통화입니다.
    • memo (string) - 온체인 메모입니다. 기본값: "Cart purchase (products.length items)".
    • label (string) - 결제 라벨입니다. 기본값: "Cart Checkout".
    • message (string) - 성공 메시지입니다. 기본값: "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, 필수) - 팁 금액입니다. 단위는 통화에 따라 다릅니다(SOL의 경우 lamport, 토큰의 경우 최소 단위).

  • options (object, 선택) - 사용자 정의 옵션:

    • currency (string) - 결제 통화입니다. 기본값: undefined (일반적으로 소비자가 SOL로 처리함).
    • memo (string) - 온체인 메모입니다. 기본값: "Thank you for your support!".
    • label (string) - 결제 라벨입니다. 기본값: "Tip".
    • message (string) - 성공 메시지입니다. 기본값: "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와 상호작용하여 트랜잭션을 검증하고 컨펌을 기다립니다. gill 라이브러리의 Solana RPC 클라이언트가 필요합니다.

verifyPayment()

트랜잭션이 온체인에 존재하는지 확인하고, 선택적으로 결제 금액, 수신자 및 토큰을 검증합니다.

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

매개변수

  • rpc (SolanaClient['rpc'], 필수) - gill의 RPC 클라이언트. 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, 선택) - SPL 토큰 민트 주소. SPL 토큰 전송에만 필요합니다. 제공되지 않으면 함수는 SOL 전송으로 간주합니다.

반환값

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
}

검증 로직

함수는 다음 검사를 수행합니다:

  1. 서명 유효성: 서명이 유효한지 확인합니다.

  2. 트랜잭션 존재 여부: rpc.getTransaction()를 사용하여 트랜잭션을 가져옵니다. 찾을 수 없으면 verified: false를 반환합니다.

  3. 컨펌 상태: 트랜잭션이 온체인에 기록되었는지 확인합니다.

  4. SOL 전송 검증 (expectedRecipientexpectedAmount가 제공되고 expectedMint가 없는 경우):

    • 트랜잭션에서 수신자의 계정 인덱스를 찾습니다
    • preBalancespostBalances를 비교하여 잔액 변화량을 계산합니다
    • 변화량이 최소한 expectedAmount인지 확인합니다
  5. SPL 토큰 전송 검증 (expectedMint가 제공된 경우):

    • 토큰 프로그램과 Token-2022 프로그램 모두에 대한 수신자의 Associated Token Account(ATA)를 파생합니다
    • 예상되는 민트와 일치하는 ATA가 있는지 postTokenBalances를 확인합니다
    • 토큰 수량이 최소 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()

트랜잭션이 확인됨 또는 최종 확정 상태에 도달하거나 타임아웃될 때까지 블록체인을 폴링합니다.

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

매개변수

  • rpc (SolanaClient['rpc'], 필수) - gill의 RPC 클라이언트입니다.

  • signatureStr (string, 필수) - 대기할 트랜잭션 서명입니다.

  • timeoutMs (number, 선택) - 대기할 최대 시간(밀리초)입니다. 기본값: 30000 (30초).

반환값

  • Promise<boolean> - 트랜잭션이 타임아웃 내에 confirmed 또는 finalized 상태에 도달하면 true을 반환하고, 그렇지 않으면 false을 반환합니다.

예시:

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");
}

Solana Pay 함수

이 함수들은 모바일 지갑 스캔을 위한 Solana Pay URL과 스타일이 적용된 QR 코드를 생성합니다.

createSolanaPayRequest()

Solana Pay URL과 스타일이 적용된 QR 코드를 생성합니다.

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

매개변수

  • request (TransferRequestURLFields, 필수) - Solana Pay 전송 요청 필드:

    • recipient - 수신자 pubkey (@solana-commerce/solana-paycreateRecipient(address) 사용)
    • amount - (선택) 최소 단위의 결제 금액 (SOL의 경우 lamport)
    • splToken (선택) - SPL 토큰 민트 pubkey (createSPLToken(address) 사용)
    • reference (선택) - 추적을 위한 참조 pubkey
    • 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 (문자열) - QR 코드 중앙에 삽입할 로고 이미지 URL.
    • logoSize (숫자) - QR 코드 크기 대비 로고 크기 비율(백분율).
    • logoBackgroundColor (문자열) - 로고 뒤 배경색.
    • logoMargin (숫자) - 로고 주변 여백.
    • dotStyle ('dots' | 'rounded' | 'square') - QR 코드 모듈의 형태.
    • cornerStyle ('square' | 'rounded' | 'extra-rounded' | 'full-rounded' | 'maximum-rounded') - 코너 마커의 형태.

반환값

다음 객체로 해결되는 Promise:

  • url (URL) - Solana Pay URL (예: solana:recipient?amount=10&spl-token=...)
  • qr (문자열) - QR 코드 이미지의 Base64 인코딩된 데이터 URL (<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 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?

관리자

© 2026 솔라나 재단.
모든 권리 보유.
연결하기