阅读时长:约 8 分钟
开篇快览
Solana Pay 是一款基于 Solana 区块链的 即时支付协议。利用其开源 JavaScript 库,开发者可在 5 分钟内集成“扫码-支付-确认”全套流程,支持 SOL 与所有 SPL Token。
本文用实战代码演示:
- 生成支付链接(模拟收银台)
- 用户扫码付款(链上交易)
- 商户校验收款(防掉单)
预备清单
- Node.js ≥16.15
- ts-node 已全局安装
- 已创建 Devnet 测试钱包(
.json私钥文件),钱包内至少 1 枚 Devnet SOL - 任意 IDE & 终端
Solana Pay 究竟是什么?
Solana Pay 并非钱包,而是一套“URL + SDK + 校验规则”的简单协议。
核心关键词:无托管、无中间商、秒级到账、0.5 cent 手续费。
4 步支付流程
- 用户在商户前端下单。
- 商户后端生成
solana:...协议链接并转 QR Code。 - 用户钱包扫描并签名,交易光速上链。
- 商户后台用 Reference Key 查链确认,防篡改。
实战 1:搭建开发环境
新建项目文件夹并安装依赖:
mkdir solana-pay-demo && cd solana-pay-demo
npm init -y
npm i @solana/web3.js@1 @solana/pay bignumber.js ts-node
tsc -init --resolveJsonModule true创建入口文件:
touch index.ts实战 2:读写常量与连接 Devnet
import { Connection, Keypair, PublicKey, NetworkConstants, SystemProgram } from '@solana/web3.js';
import { encodeURL, parseURL, findReference, validateTransfer } from '@solana/pay';
import BigNumber from 'bignumber.js';
// === 钱包与连接 ===
const secret = [...]; // 换成自己的 32 字节私钥
const payer = Keypair.fromSecretKey(new Uint8Array(secret));
const connection = new Connection('https://api.devnet.solana.com', 'confirmed');
// === 应用常量 ===
const destinationWallet = new PublicKey(payer.publicKey); // 自己发自己做测试
const amount = new BigNumber(0.1); // 0.1 SOL
const reference = Keypair.generate().publicKey; // 唯一订单号
const label = 'Solana Pay 体验店';
const message = '订单 #00001 - Solana Pay 指导';
const memo = 'Solana Pay 实战 Demo';实战 3:生成支付链接
async function generateUrl() {
const url = encodeURL({
recipient: destinationWallet,
amount,
reference,
label,
message,
memo,
});
console.log('生成的支付链接:', url.href);
return url;
}将链接转 QR Code(可用在线生成器测试)。
实战 4:链上付款函数
async function processPayment(url: URL) {
const { recipient, amount: amt, reference: ref, memo: mem } = parseURL(url);
if (!recipient || !amt) throw new Error('地址或金额缺失');
const tx = new SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: recipient,
lamports: amt.multipliedBy(1e9).toNumber(),
});
// 添加 memo
const memoIx = new TransactionInstruction({
programId: new PublicKey('MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'),
keys: [],
data: Buffer.from(mem, 'utf-8'),
});
const transaction = new Transaction().add(memoIx, tx);
const sig = await connection.sendAndConfirmTransaction(transaction, [payer]);
console.log('交易已广播:', `https://explorer.solana.com/tx/${sig}?cluster=devnet`);
}实战 5:验证收款
async function verify() {
const found = await findReference(connection, reference);
const info = await validateTransfer(connection, found.signature, {
recipient: destinationWallet,
amount,
reference,
memo,
});
if (!info || info.meta?.err) throw new Error('校验失败');
console.log('✅ 对方已收到 0.1 SOL');
}Pay Day:一次性运行
(async () => {
console.log('🔥 Solana Pay Demo 运行中');
const url = await generateUrl();
await processPayment(url);
await verify();
})();终端将打印交易哈希及浏览器查看链接。
进阶:支持自定义 SPL Token(USDC 等)
- 修改
encodeURL加入splToken字段(Token Mint)。 - 使用
createTransferCheckedInstruction替代SystemProgram.transfer,先getAssociatedTokenAddress再转账。 validateTransfer增加splToken参数即可。
安全与最佳实践
- 链上信息防篡改:永远在后端生成、签名并校验
reference与订单。 - 费控:确保客户端只签名,不做金额修改。
- 用户体验:付款后 3 秒内给出确认页面,减少焦虑。
常见问题 FAQ
Q1:付款一直 pending,没有成功?
A:检查 Devnet RPC 节点是否可用,或 faucet 领取新 SOL。
Q2:可以接入真实店面吗?
A:可以,只要把 encodeURL 输出转成 QR Code,前端用任何框架即可。
Q3:手续费会不会波动?
A:Solana 每笔基础手续费 0.000005 SOL,极端拥堵时日内低于 $0.01。
Q4:如何防止双花?
A:用 reference 作为订单号,后端秒级校验,查重即可。
Q5:能否替用户垫付矿工费?
A:已知 Solana 不支持元交易(meta-tx),只能在同一笔交易中由用户承担手续费。
资源索引
- Solana Pay 官方文档
- GitHub 仓库(示例完整源码)
- 🔗 若需高频调用节点,注册即可获取 Devnet 专线 RPC:OSS 协议文档
让每一笔付款 秒到账、低费用、无国界——这就是 Solana Pay 的魅力。