Create a payment request link or QR code using Solana Pay that users can scan to pay you. This recipe shows how to use the Phantom SDK to get your wallet address and create payment requests.Documentation Index
Fetch the complete documentation index at: https://docs.phantom.com/llms.txt
Use this file to discover all available pages before exploring further.
- React
- Browser SDK
- React Native
import { PhantomProvider, useSolana, useAccounts, usePhantom, darkTheme } from "@phantom/react-sdk";
import { AddressType } from "@phantom/browser-sdk";
import { encodeURL, createQR } from "@solana/pay";
import { PublicKey, Keypair } from "@solana/web3.js";
import { useEffect, useRef } from "react";
import BigNumber from "bignumber.js";
// USDC mint address
const USDC_MINT = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
function App() {
return (
<PhantomProvider
config={{
providers: ["google", "apple", "injected"],
appId: "your-app-id",
addressTypes: [AddressType.solana],
authOptions: {
redirectUrl: "https://yourapp.com/auth/callback",
},
}}
theme={darkTheme}
appName="Your Store"
>
<PaymentRequest />
</PhantomProvider>
);
}
function PaymentRequest() {
const { solana } = useSolana();
const addresses = useAccounts();
const { isConnected } = usePhantom();
const qrRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!isConnected || !addresses?.[0]) return;
// Get your wallet address from the SDK
const recipient = new PublicKey(addresses[0].address);
const amount = new BigNumber(10); // 10 USDC
const reference = new PublicKey(Keypair.generate().publicKey); // Unique identifier
const label = "Your Store";
const message = "Thanks for your purchase!";
// Create the payment URL
const url = encodeURL({
recipient,
amount,
splToken: USDC_MINT,
reference,
label,
message,
});
// Generate QR code
const qr = createQR(url, 300, "transparent");
if (qrRef.current) {
qrRef.current.innerHTML = "";
qr.append(qrRef.current);
}
}, [isConnected, addresses]);
if (!isConnected) {
return <div>Please connect your wallet to generate a payment request</div>;
}
return (
<div>
<h2>Scan to pay 10 USDC</h2>
<p>Your wallet: {addresses?.[0]?.address}</p>
<div ref={qrRef} />
</div>
);
}
import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
import { encodeURL, createQR } from "@solana/pay";
import { PublicKey, Keypair } from "@solana/web3.js";
import BigNumber from "bignumber.js";
// USDC mint address
const USDC_MINT = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
const sdk = new BrowserSDK({
providers: ["google", "apple", "injected"],
appId: "your-app-id",
addressTypes: [AddressType.solana],
});
async function createPaymentRequest(amount: BigNumber) {
// Connect if not already connected
if (!sdk.solana.isConnected()) {
await sdk.connect({ provider: "google" });
}
// Get your wallet address from the SDK
const recipientAddress = await sdk.solana.getPublicKey();
const recipient = new PublicKey(recipientAddress);
const reference = new PublicKey(Keypair.generate().publicKey);
const label = "Your Store";
const message = "Thanks for your purchase!";
// Create the payment URL
const url = encodeURL({
recipient,
amount,
splToken: USDC_MINT,
reference,
label,
message,
});
// Generate QR code
const qr = createQR(url, 300, "transparent");
return { url, qr, reference };
}
// Usage
const { url, qr, reference } = await createPaymentRequest(new BigNumber(10));
qr.append(document.getElementById("qr-container"));
import { PhantomProvider, useSolana, useAccounts, usePhantom, AddressType, darkTheme } from "@phantom/react-native-sdk";
import { encodeURL } from "@solana/pay";
import { PublicKey, Keypair } from "@solana/web3.js";
import { View, Text, StyleSheet, Linking } from "react-native";
import { useEffect, useState } from "react";
import BigNumber from "bignumber.js";
// USDC mint address
const USDC_MINT = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
function App() {
return (
<PhantomProvider
config={{
providers: ["google", "apple"],
appId: "your-app-id",
scheme: "yourapp",
addressTypes: [AddressType.solana],
authOptions: {
redirectUrl: "yourapp://auth/callback",
},
}}
theme={darkTheme}
appName="Your Store"
>
<PaymentRequest />
</PhantomProvider>
);
}
function PaymentRequest() {
const { solana } = useSolana();
const addresses = useAccounts();
const { isConnected } = usePhantom();
const [paymentUrl, setPaymentUrl] = useState<string | null>(null);
useEffect(() => {
if (!isConnected || !addresses?.[0]) return;
const recipient = new PublicKey(addresses[0].address);
const amount = new BigNumber(10); // 10 USDC
const reference = new PublicKey(Keypair.generate().publicKey);
const label = "Your Store";
const message = "Thanks for your purchase!";
const url = encodeURL({
recipient,
amount,
splToken: USDC_MINT,
reference,
label,
message,
});
setPaymentUrl(url.toString());
}, [isConnected, addresses]);
if (!isConnected) {
return (
<View style={styles.container}>
<Text>Please connect your wallet to generate a payment request</Text>
</View>
);
}
return (
<View style={styles.container}>
<Text style={styles.title}>Payment Request</Text>
<Text>Your wallet: {addresses?.[0]?.address}</Text>
{paymentUrl && (
<Text
style={styles.link}
onPress={() => Linking.openURL(paymentUrl)}
>
Open Payment Link
</Text>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
justifyContent: "center",
},
title: {
fontSize: 24,
fontWeight: "bold",
marginBottom: 20,
},
link: {
color: "#0ea5e9",
marginTop: 20,
textDecorationLine: "underline",
},
});
Install dependencies
npm install @solana/pay bignumber.js @phantom/react-sdk
# or
npm install @solana/pay bignumber.js @phantom/browser-sdk
Verify payment
After a user pays, verify the payment on your backend:import { findReference, validateTransfer } from "@solana/pay";
import { Connection, PublicKey } from "@solana/web3.js";
import BigNumber from "bignumber.js";
const USDC_MINT = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
async function verifyPayment(reference: PublicKey, recipient: PublicKey, amount: BigNumber) {
const connection = new Connection("https://api.mainnet-beta.solana.com");
// Find the transaction
const signatureInfo = await findReference(connection, reference);
// Validate it matches our request
await validateTransfer(connection, signatureInfo.signature, {
recipient,
amount,
splToken: USDC_MINT,
});
return signatureInfo.signature;
}