Permintaan Transaksi
Permintaan transaksi membuka kekuatan penuh Solana Pay dengan memungkinkan transaksi dinamis yang disusun server yang dapat menangani segala jenis operasi Solana.
Tidak seperti permintaan transfer yang berisi semua informasi pembayaran dalam URL, permintaan transaksi menggunakan endpoint interaktif untuk membangun transaksi kustom berdasarkan data real-time dan logika bisnis.
Pendekatan ini mengubah Solana Pay dari sistem pembayaran sederhana menjadi platform perdagangan lengkap yang mampu menangani skenario bisnis kompleks, penetapan harga dinamis, dan alur transaksi yang canggih.
Cara Kerja Permintaan Transaksi
Permintaan transaksi mengikuti format URL sederhana yang mengarah ke endpoint server Anda:
solana:<link>
Nilai link
harus berupa URL ke endpoint API Anda yang menangani permintaan GET
dan POST
. Ketika pengguna memindai kode QR permintaan transaksi, dompet mereka memulai proses empat langkah:
- Permintaan GET Awal: Mengambil informasi tampilan seperti nama bisnis dan logo Anda
- Konfirmasi Pengguna: Dompet menampilkan informasi bisnis kepada pengguna
- Permintaan POST: Mengirim kunci publik pengguna ke endpoint Anda
- Respons Transaksi: Server Anda membangun transaksi kustom dan mengembalikannya sebagai string yang dikodekan base64
Dompet kemudian menampilkan transaksi ini kepada pengguna untuk persetujuan dan penandatanganan.
solana:https://myapi.com/pay?amount=100&product=premium&reference=abc123
Membangun Endpoint API
Membuat endpoint permintaan transaksi memerlukan penanganan permintaan GET dan POST pada URL yang sama. Berikut strukturnya menggunakan Next.js App Router:
import { NextRequest, NextResponse } from 'next/server';
// CORS headers for wallet compatibility
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
};
export async function OPTIONS() {
return new NextResponse(null, { status: 200, headers: corsHeaders });
}
export async function GET() {
// Implementation details below...
}
export async function POST(request: NextRequest) {
// Implementation details below...
}
Penangan Permintaan GET
Permintaan GET menyediakan informasi tampilan yang membantu pengguna memahami apa yang sedang mereka interaksikan:
export async function GET() {
return NextResponse.json({
label: "Coffee Shop Demo",
icon: "https://solana.com/src/img/branding/solanaLogoMark.svg",
}, { headers: corsHeaders });
}
Format Respons:
{
"label": "Coffee Shop Demo",
"icon": "https://solana.com/src/img/branding/solanaLogoMark.svg"
}
Informasi ini membantu pengguna memahami apa yang akan mereka interaksikan sebelum melanjutkan ke komposisi transaksi yang sebenarnya.
Penangan Permintaan POST
Permintaan POST adalah tempat permintaan transaksi benar-benar bersinar. Endpoint Anda menerima kunci publik pengguna dan membangun transaksi yang sepenuhnya kustom:
export async function POST(request: NextRequest) {
// Parse user's public key from request body
const body = await request.json();
const { account } = body;
// Connect to Solana network
const connection = new Connection(clusterApiUrl("devnet"));
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
// Create transaction with user as fee payer
const transaction = new Transaction({
feePayer: new PublicKey(account),
blockhash: blockhash,
lastValidBlockHeight: lastValidBlockHeight,
});
// ========================================
// ADD YOUR CUSTOM INSTRUCTIONS HERE
// ========================================
// This is where you build your transaction logic.
// You can add any combination of instructions:
// Example 1: Simple SOL transfer
// const transferInstruction = SystemProgram.transfer({
// fromPubkey: new PublicKey(account),
// toPubkey: new PublicKey("YOUR_MERCHANT_WALLET"),
// lamports: LAMPORTS_PER_SOL * 0.01, // 0.01 SOL
// });
// transaction.add(transferInstruction);
// Serialize the transaction for the wallet
const serializedTransaction = transaction.serialize({
requireAllSignatures: false,
verifySignatures: false,
});
return NextResponse.json({
transaction: serializedTransaction.toString('base64'),
message: "Transaction created successfully", // Customize this message
}, { headers: corsHeaders });
}
Kemampuan Lanjutan
Transaksi Terbatas
Permintaan transaksi memungkinkan kontrol akses yang canggih dengan memverifikasi kondisi sebelum membangun transaksi. Karena Anda mengendalikan endpoint, Anda dapat memeriksa kepemilikan NFT, keanggotaan whitelist, atau kriteria lainnya:
// Check NFT ownership before building transaction
const nfts = await metaplex.nfts().findAllByOwner({ owner: account }).run();
const hasRequiredNFT = nfts.some(nft =>
nft.collection?.address.toString() === requiredCollection
);
if (!hasRequiredNFT) {
return response.status(403).json({
error: "Access denied: Required NFT not found"
});
}
// Build transaction only for verified users
Penandatanganan Parsial untuk Keamanan yang Ditingkatkan
Untuk transaksi yang memerlukan persetujuan dari keypair admin atau autentikasi multi-pihak, Solana Pay mendukung penandatanganan parsial. Server Anda dapat menambahkan tanda tangannya sebelum mengirim ke pengguna:
const transaction = new Transaction({
feePayer: account,
blockhash,
lastValidBlockHeight,
});
// Add your instructions requiring admin signature
transaction.add(customInstruction);
// Partially sign with your admin keypair
transaction.partialSign(adminKeypair);
// Send to user for final signature
const serializedTransaction = transaction.serialize({
requireAllSignatures: false,
});
Contoh
Sebagai contoh lengkap, Anda dapat menggunakan Contoh Solana NFT Minter dari Solana Foundation