123 lines
4.8 KiB
TypeScript
123 lines
4.8 KiB
TypeScript
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} ağı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 });
|
||
}
|
||
}
|