Αιτήματα Συναλλαγών

Τα αιτήματα συναλλαγών επιτρέπουν διαδραστικές ροές πληρωμών δίνοντας τη δυνατότητα στα πορτοφόλια να επικοινωνούν με τον διακομιστή σας για τη σύνθεση οποιασδήποτε συναλλαγής Solana. Αυτό ξεκλειδώνει προηγμένες περιπτώσεις χρήσης όπως η δημιουργία NFT, η δυναμική τιμολόγηση, οι πολυβηματικές συναλλαγές DeFi και η προσαρμοσμένη επιχειρηματική λογική.

Επισκόπηση

Τα αιτήματα συναλλαγών ακολουθούν αυτή τη μορφή URL:

solana:<server-endpoint-url>

Το πορτοφόλι πραγματοποιεί δύο αιτήματα HTTP στο endpoint σας:

  1. Αίτημα GET - Ανάκτηση πληροφοριών πληρωμής (ετικέτα, εικονίδιο)
  2. Αίτημα POST - Λήψη της συναλλαγής προς υπογραφή

Βασική Ρύθμιση

1. Εγκατάσταση Εξαρτήσεων

pnpm add @solana/pay@beta @solana/kit @solana-program/system \
@solana/kit-plugin-rpc @solana/kit-plugin-payer @solana/kit-plugin-instruction-plan

2. Δημιουργία API Endpoint

Ρυθμίστε ένα API endpoint που διαχειρίζεται τόσο αιτήματα GET όσο και POST:

// pages/api/pay.ts (Next.js) or similar endpoint
import { address, createNoopSigner, lamports } from "@solana/kit";
import { getTransferSolInstruction } from "@solana-program/system";
import { createMerchantClient } from "@solana/pay";
const MERCHANT_WALLET = address(process.env.MERCHANT_WALLET);
export default async function handler(req, res) {
if (req.method === "GET") {
return handleGet(req, res);
}
if (req.method === "POST") {
return handlePost(req, res);
}
return res.status(405).json({ error: "Method not allowed" });
}
// GET request handler
async function handleGet(req, res) {
const label = "My Store";
const icon = "https://mystore.com/icon.png";
res.status(200).json({
label,
icon
});
}
// POST request handler
async function handlePost(req, res) {
try {
const { account } = req.body;
if (!account) {
return res.status(400).json({ error: "Missing account parameter" });
}
const buyerAddress = address(account);
// Create the merchant client for building the transaction
const merchant = createMerchantClient({
rpcUrl: process.env.SOLANA_RPC_URL
});
// Build transfer instruction (createNoopSigner because the wallet signs later)
const instruction = getTransferSolInstruction({
source: createNoopSigner(buyerAddress),
destination: MERCHANT_WALLET,
amount: lamports(100_000_000n) // 0.1 SOL
});
// Build a base64-encoded transaction
const transaction = merchant.pay.buildTransaction(buyerAddress, [
instruction
]);
res.status(200).json({
transaction,
message: "Thanks for your purchase!"
});
} catch (error) {
console.error("Transaction creation error:", error);
res.status(500).json({ error: "Failed to create transaction" });
}
}

3. Δημιουργία URL Πληρωμής

Δημιουργήστε το URL του αιτήματος συναλλαγής:

import { encodeURL } from "@solana/pay";
// Your API endpoint
const apiUrl = "https://yoursite.com/api/pay";
// Create transaction request URL
const url = encodeURL({
link: new URL(apiUrl)
});
console.log(url.toString());
// Output: solana:https://yoursite.com/api/pay

Πλευρά Πορτοφολιού: Ανάκτηση Αιτημάτων Συναλλαγών

Από την πλευρά του πορτοφολιού, χρησιμοποιήστε το fetchTransaction για να ανακτήσετε και να υπογράψετε μια συναλλαγή από ένα URL αιτήματος συναλλαγής:

import { createWalletClient } from "@solana/pay";
const wallet = createWalletClient({
rpcUrl: "https://api.mainnet-beta.solana.com",
payer: myWalletSigner
});
// Parse the Solana Pay URL
const parsed = wallet.pay.parseURL(url);
if ("link" in parsed) {
// This is a transaction request — fetch the transaction from the server
const transaction = await wallet.pay.fetchTransaction(
myWalletSigner.address,
parsed.link
);
// Sign and send the transaction...
}

Προηγμένα Παραδείγματα

Πληρωμή με SPL Token

Δημιουργήστε μια συναλλαγή για πληρωμή USDC:

import { address } from "@solana/kit";
import {
fetchMint,
findAssociatedTokenPda,
getTransferCheckedInstruction,
TOKEN_PROGRAM_ADDRESS
} from "@solana-program/token";
async function createTokenPaymentInstruction(rpc, buyer, amount) {
const USDC_MINT = address("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
// Get mint info for decimals
const mint = await fetchMint(rpc, USDC_MINT);
// Derive associated token accounts
const [buyerATA] = await findAssociatedTokenPda({
owner: buyer,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
mint: USDC_MINT
});
const [merchantATA] = await findAssociatedTokenPda({
owner: MERCHANT_WALLET,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
mint: USDC_MINT
});
// Calculate token amount with decimals
const tokenAmount = BigInt(Math.round(amount * 10 ** mint.data.decimals));
return getTransferCheckedInstruction({
source: buyerATA,
mint: USDC_MINT,
destination: merchantATA,
authority: buyer,
amount: tokenAmount,
decimals: mint.data.decimals
});
}

Δυναμική Τιμολόγηση με Εκπτώσεις

Εφαρμόστε δυναμική τιμολόγηση βάσει δεδομένων πελατών:

async function handlePost(req, res) {
const { account } = req.body;
const buyer = address(account);
// Check if customer holds discount NFT
const hasDiscountNFT = await checkForDiscountNFT(buyer);
// Calculate dynamic price
let price = 10; // $10 base price
if (hasDiscountNFT) {
price = price * 0.8; // 20% discount
}
const merchant = createMerchantClient({
rpcUrl: process.env.SOLANA_RPC_URL
});
const instruction = await createTokenPaymentInstruction(
merchant.rpc,
buyer,
price
);
const transaction = merchant.pay.buildTransaction(buyer, [instruction]);
const message = hasDiscountNFT
? `20% discount applied! Total: $${price.toFixed(2)}`
: `Total: $${price.toFixed(2)}`;
res.status(200).json({ transaction, message });
}

Ενσωμάτωση Διαχείρισης Παραγγελιών

Ενσωματώστε με το υπάρχον σύστημα παραγγελιών σας:

import { address, AccountRole, createNoopSigner, lamports } from "@solana/kit";
// Enhanced POST handler with order management
async function handlePost(req, res) {
const { account } = req.body;
const { orderId } = req.query;
if (!orderId) {
return res.status(400).json({ error: "Missing order ID" });
}
// Get order details
const order = await db.orders.findById(orderId);
if (!order || order.status !== "pending") {
return res.status(400).json({ error: "Invalid order" });
}
const buyer = address(account);
// Create payment instruction (createNoopSigner because the wallet signs later)
const instruction = getTransferSolInstruction({
source: createNoopSigner(buyer),
destination: MERCHANT_WALLET,
amount: lamports(BigInt(Math.round(order.total * 1e9)))
});
// Add reference for tracking (accounts is readonly, so spread into a new instruction)
const withRef = {
...instruction,
accounts: [
...(instruction.accounts ?? []),
{
address: address(order.referenceKey),
role: AccountRole.READONLY
}
]
};
const merchant = createMerchantClient({ rpcUrl: process.env.SOLANA_RPC_URL });
const transaction = merchant.pay.buildTransaction(buyer, [withRef]);
// Update order status
await db.orders.update(orderId, {
status: "processing",
walletAddress: account
});
res.status(200).json({
transaction,
message: `Order ${order.id} - ${order.items.length} items`
});
}

Επικύρωση Πληρωμής

Επικυρώστε τις ολοκληρωμένες συναλλαγές:

import { address } from "@solana/kit";
import { createMerchantClient } from "@solana/pay";
const merchant = createMerchantClient({
rpcUrl: "https://api.mainnet-beta.solana.com"
});
async function validatePayment(reference, recipient, amount) {
try {
const found = await merchant.pay.findReference(reference);
// findReference only locates a signature mentioning the reference address.
// validateTransfer checks recipient, amount, and token match.
await merchant.pay.validateTransfer(found.signature, {
recipient,
amount,
reference
});
return {
success: true,
signature: found.signature
};
} catch (error) {
console.error("Payment validation error:", error);
}
return { success: false };
}

Διαχείριση Σφαλμάτων

Εφαρμόστε ισχυρή διαχείριση σφαλμάτων:

async function handlePost(req, res) {
try {
const { account } = req.body;
if (!account) {
return res.status(400).json({
error: "Missing account parameter",
code: "MISSING_ACCOUNT"
});
}
let buyer;
try {
buyer = address(account);
} catch {
return res.status(400).json({
error: "Invalid account address",
code: "INVALID_ACCOUNT"
});
}
const instruction = getTransferSolInstruction({
source: createNoopSigner(buyer),
destination: MERCHANT_WALLET,
amount: lamports(100_000_000n)
});
const merchant = createMerchantClient({
rpcUrl: process.env.SOLANA_RPC_URL
});
const transaction = merchant.pay.buildTransaction(buyer, [instruction]);
res.status(200).json({
transaction,
message: "Payment ready"
});
} catch (error) {
console.error("Transaction request error:", error);
res.status(500).json({
error: "Internal server error",
code: "INTERNAL_ERROR"
});
}
}

Βέλτιστες Πρακτικές

Ασφάλεια

  • Επικυρώστε όλες τις παραμέτρους εισόδου
  • Υπολογίστε τα ποσά μόνο από την πλευρά του διακομιστή
  • Χρησιμοποιήστε HTTPS για όλα τα endpoints
  • Εφαρμόστε περιορισμό ρυθμού αιτημάτων
  • Αποθηκεύστε ευαίσθητα δεδομένα με ασφάλεια

Απόδοση

  • Χρησιμοποιήστε cache για συχνά προσπελαζόμενα δεδομένα
  • Χρησιμοποιήστε connection pooling
  • Εφαρμόστε χρονικά όρια για αιτήματα
  • Εξετάστε το ενδεχόμενο χρήσης webhooks για επιβεβαίωση πληρωμών

Εμπειρία Χρήστη

  • Παρέχετε σαφή μηνύματα σφάλματος
  • Εμφανίστε την πρόοδο της συναλλαγής
  • Διαχειριστείτε τα προβλήματα δικτύου με χάρη
  • Υποστηρίξτε επαναπροσπάθειες συναλλαγών

Is this page helpful?

Διαχειρίζεται από

© 2026 Ίδρυμα Solana.
Με επιφύλαξη παντός δικαιώματος.
Συνδεθείτε