Files
Pay2Gateway/components/checkout/CryptoCheckout.tsx

180 lines
8.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import React, { useState, useEffect } from 'react';
import {
Coins,
Copy,
CheckCircle2,
ExternalLink,
RefreshCw,
AlertCircle,
QrCode
} from 'lucide-react';
interface CryptoCheckoutProps {
amount: number;
currency: string;
txId: string;
onSuccess: (txHash: string) => void;
}
export default function CryptoCheckout({ amount, currency, txId, onSuccess }: CryptoCheckoutProps) {
const [selectedCoin, setSelectedCoin] = useState('SOL');
const [depositAddress, setDepositAddress] = useState<string>('');
const [isVerifying, setIsVerifying] = useState(false);
const [copied, setCopied] = useState(false);
const [status, setStatus] = useState<'waiting' | 'verifying' | 'success' | 'error'>('waiting');
const [cryptoAmount, setCryptoAmount] = useState<string>('Hesaplanıyor...');
useEffect(() => {
async function fetchExchangeRate() {
if (currency === 'TL' || currency === 'TRY') {
try {
const symbol = selectedCoin === 'SOL' ? 'SOLTRY' : 'USDTTRY';
const res = await fetch(`https://api.binance.com/api/v3/ticker/price?symbol=${symbol}`);
const data = await res.json();
const rate = parseFloat(data.price);
setCryptoAmount((amount / rate).toFixed(selectedCoin === 'SOL' ? 4 : 2));
} catch (error) {
// Fallback rate if API fails
setCryptoAmount((amount / 5500).toFixed(selectedCoin === 'SOL' ? 4 : 2));
}
} else {
// If already USD or USDT, 1:1 ratio
setCryptoAmount(amount.toFixed(2));
}
}
fetchExchangeRate();
}, [amount, currency]);
useEffect(() => {
// Use a real valid Solana test wallet so Phantom doesn't say "Invalid Address"
setDepositAddress('5pLH1tqZhx8p8WpZ18yr28N42KXB3FXVPzZ9ceCtpBVe');
}, [selectedCoin]);
const handleCopy = () => {
navigator.clipboard.writeText(depositAddress);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
const verifyPayment = async () => {
setIsVerifying(true);
setStatus('verifying');
try {
const response = await fetch('/api/crypto-sweep', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
txId: txId,
merchantAddress: '5pLH1tqZhx8p8WpZ18yr28N42KXB3FXVPzZ9ceCtpBVe' // A placeholder valid Solana Devnet Wallet
})
});
const data = await response.json();
if (data.success) {
setStatus('success');
onSuccess(data.hashes.merchant);
} else {
setStatus('error');
}
} catch (err) {
setStatus('error');
} finally {
setIsVerifying(false);
}
};
return (
<div className="bg-white p-8 lg:p-12 rounded-[40px] border border-gray-100 shadow-sm space-y-8 animate-in fade-in zoom-in duration-500 w-full max-w-lg">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="p-3 bg-orange-50 rounded-2xl text-orange-600">
<Coins size={24} />
</div>
<div>
<h3 className="text-xl font-black text-gray-900 uppercase tracking-tight">Kripto Ödeme</h3>
<p className="text-[10px] text-gray-400 font-black uppercase tracking-widest">On-Chain Güvenli Transfer</p>
</div>
</div>
<div className="text-right">
<p className="text-2xl font-black text-gray-900">{cryptoAmount} <span className="text-xs text-gray-400">{selectedCoin}</span></p>
<p className="text-[10px] text-gray-400 font-bold uppercase">: Solana (Devnet)</p>
</div>
</div>
{status === 'success' ? (
<div className="py-10 text-center space-y-6">
<div className="w-20 h-20 bg-emerald-50 rounded-[32px] flex items-center justify-center text-emerald-500 mx-auto animate-bounce">
<CheckCircle2 size={40} />
</div>
<div className="space-y-2">
<h2 className="text-2xl font-black text-gray-900 uppercase tracking-tight">Ödeme Onaylandı!</h2>
<p className="text-gray-400 font-bold uppercase tracking-widest text-[10px]">İşleminiz başarıyla blokzincirine kaydedildi.</p>
</div>
</div>
) : (
<>
{/* QR Code Placeholder */}
<div className="bg-gray-50 aspect-square rounded-[32px] flex flex-col items-center justify-center border border-gray-100 relative group cursor-pointer">
<QrCode size={180} className="text-gray-200 group-hover:text-gray-400 transition-colors" />
<div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity">
<span className="bg-white px-4 py-2 rounded-xl text-[10px] font-black uppercase shadow-lg border border-gray-100">Büyüt</span>
</div>
</div>
<div className="space-y-4">
<div className="space-y-2">
<label className="text-[10px] font-black text-gray-400 uppercase tracking-widest pl-1">Cüzdan Adresi</label>
<div className="flex items-center gap-2">
<div className="flex-1 bg-gray-50 p-4 rounded-2xl border border-gray-100 font-mono text-[10px] text-gray-600 break-all leading-tight">
{depositAddress}
</div>
<button
onClick={handleCopy}
className="p-4 bg-gray-900 text-white rounded-2xl hover:bg-black transition-all shadow-lg shadow-gray-200 active:scale-95"
>
{copied ? <CheckCircle2 size={18} /> : <Copy size={18} />}
</button>
</div>
</div>
<div className="p-6 bg-blue-50/50 rounded-3xl border border-blue-100 space-y-2">
<div className="flex items-center gap-2 text-blue-600">
<AlertCircle size={14} />
<span className="text-[9px] font-black uppercase tracking-widest">Önemli Uyarı</span>
</div>
<p className="text-[10px] text-blue-800 leading-relaxed font-medium">
Lütfen sadece test amaçlı <b>Solana (Devnet)</b> ı üzerinden test SOL'ü gönderimi yapın. Gerçek ağ veya USDT bu ortamda kabul edilmez.
</p>
</div>
</div>
<button
onClick={verifyPayment}
disabled={isVerifying}
className="w-full py-5 bg-gray-900 text-white rounded-2xl font-black text-xs uppercase tracking-[0.2em] hover:bg-black transition-all shadow-xl shadow-gray-200 flex items-center justify-center gap-3 disabled:opacity-50"
>
{isVerifying ? (
<>
<RefreshCw size={18} className="animate-spin" />
Doğrulanıyor...
</>
) : (
'Ödemeyi Doğrula'
)}
</button>
<div className="flex justify-center gap-6">
<div className="flex items-center gap-2 text-gray-400 hover:text-gray-600 cursor-pointer transition-colors group">
<ExternalLink size={14} />
<span className="text-[9px] font-black uppercase tracking-widest group-hover:underline">Explorer'da Gör</span>
</div>
</div>
</>
)}
</div>
);
}