Files
Pay2Gateway/app/api/crypto-sweep/route.ts

123 lines
4.8 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.
import { NextResponse } from 'next/server';
import { CryptoEngine } from '@/lib/crypto-engine';
import { db } from '@/lib/db';
export async function POST(request: Request) {
try {
const body = await request.json();
const { txId, network, token } = body;
if (!txId) {
return NextResponse.json({ success: false, error: "Transaction ID is required" }, { status: 400 });
}
const selectedNetwork = network || 'POLYGON';
const selectedToken = token || 'USDT';
console.log(`[API] Processing sweep for TX: ${txId} on ${selectedNetwork} with ${selectedToken}`);
// 1. Fetch the transaction from DB to get the temporary wallet private key
const result = await db.query('SELECT * FROM transactions WHERE stripe_pi_id = $1', [txId]);
if (result.rows.length === 0) {
return NextResponse.json({ success: false, error: "Transaction not found" }, { status: 404 });
}
const transaction = result.rows[0];
// 1.1 Check if already processed
if (transaction.status === 'succeeded') {
return NextResponse.json({
success: true,
message: "Transaction already processed",
status: 'succeeded'
});
}
const metadata = transaction.metadata || {};
const wallets = metadata.wallets || {};
// 2. Determine which wallet to use (EVM or SOLANA)
const walletType = selectedNetwork === 'SOLANA' ? 'SOLANA' : 'EVM';
const tempWalletConfig = wallets[walletType];
if (!tempWalletConfig || !tempWalletConfig.privateKey) {
return NextResponse.json({ success: false, error: `No temporary wallet found for ${walletType}` }, { status: 500 });
}
// 3. Define Platform Address (In production, load from env/settings)
const platformAddress = selectedNetwork === 'SOLANA'
? process.env.SOL_PLATFORM_ADDRESS || "5pLH1tqZhx8p8WpZ18yr28N42KXB3FXVPzZ9ceCtpBVe"
: process.env.EVM_PLATFORM_ADDRESS || "0x70997970C51812dc3A010C7d01b50e0d17dc79C8";
// 4. Define Merchant Address (Fetch from transaction's merchant)
const merchantResult = await db.query('SELECT * FROM merchants WHERE id = $1', [transaction.merchant_id]);
const merchantAddress = merchantResult.rows[0]?.wallet_address || platformAddress;
// 5. Initialize Engine and Verify Payment first
const cryptoEngine = new CryptoEngine(selectedNetwork);
const verification = await cryptoEngine.verifyPayment(
tempWalletConfig.address,
transaction.amount.toString(),
selectedToken
);
if (!verification.success) {
return NextResponse.json({
success: false,
error: "Henüz ödeme algılanmadı (On-chain bakiye yetersiz)",
status: 'waiting'
});
}
// 6. Proceed to Sweep
const sweepResult = await cryptoEngine.sweepFunds(
tempWalletConfig.privateKey,
merchantAddress,
platformAddress,
selectedToken
);
if (!sweepResult.success) {
throw new Error("Süpürme işlemi başarısız oldu.");
}
// 6. Update transaction status
await db.query(`UPDATE transactions SET status = 'succeeded' WHERE id = $1`, [transaction.id]);
// 7. Automated Webhook Notification
if (transaction.callback_url) {
console.log(`[Webhook] Notifying merchant at ${transaction.callback_url}`);
try {
// In production, sign this payload and use a more robust delivery system
fetch(transaction.callback_url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
status: 'success',
txId: transaction.stripe_pi_id,
orderRef: transaction.source_ref_id,
hashes: sweepResult
})
}).catch(e => console.error("Webhook fetch failed:", e.message));
} catch (webhookError: any) {
console.error("[Webhook Error]:", webhookError.message);
}
}
return NextResponse.json({
success: true,
message: `Ödeme ${selectedNetwork}ında ${selectedToken} ile başarıyla doğrulandı ve süpürüldü.`,
hashes: {
platform: sweepResult.platformTx,
merchant: sweepResult.merchantTx
}
});
} catch (error: any) {
console.error('[API Error]:', error.message);
return NextResponse.json({ success: false, error: error.message }, { status: 500 });
}
}