深入浅出 Solana Pay:手把手教你构建链上收银台

·

阅读时长:约 8 分钟

开篇快览

Solana Pay 是一款基于 Solana 区块链的 即时支付协议。利用其开源 JavaScript 库,开发者可在 5 分钟内集成“扫码-支付-确认”全套流程,支持 SOL 与所有 SPL Token。
本文用实战代码演示:

  1. 生成支付链接(模拟收银台)
  2. 用户扫码付款(链上交易)
  3. 商户校验收款(防掉单)

⚡👉 立刻体验 0.1 SOL 的真实链上转账示例!


预备清单


Solana Pay 究竟是什么?

Solana Pay 并非钱包,而是一套“URL + SDK + 校验规则”的简单协议。
核心关键词:无托管、无中间商、秒级到账、0.5 cent 手续费

4 步支付流程

  1. 用户在商户前端下单。
  2. 商户后端生成 solana:... 协议链接并转 QR Code。
  3. 用户钱包扫描并签名,交易光速上链。
  4. 商户后台用 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

⚡👉 跟着代码把钱包与 RPC 节点一次性配齐,零踩坑!

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 等)


安全与最佳实践

  1. 链上信息防篡改:永远在后端生成、签名并校验 reference 与订单。
  2. 费控:确保客户端只签名,不做金额修改。
  3. 用户体验:付款后 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 的魅力。