PHP WebShell
Текущая директория: /var/www/bitcardoApp/backyard/user/funding
Просмотр файла: paystack.php
<?
include '../common/header.php';
require_once '../../models/paystack/paystack_client.php';
$ps_ngn = null;
$ps_error = null;
try {
$ps_ngn = paystack_get_ngn_balance();
} catch (Throwable $e) {
$ps_error = $e->getMessage();
}
/**
* Helpers
*/
function dec_mul($a, $b, $scale = 18) {
$a = (string)$a;
$b = (string)$b;
// Prefer BCMath for precision
if (function_exists('bcmul')) {
return bcmul($a, $b, $scale);
}
// Fallback (less precise)
return (string)((float)$a * (float)$b);
}
/**
* Round a decimal string to N dp using BCMath (true rounding).
* If BCMath missing, falls back to float rounding.
*/
function round_decimal_str($num, $precision = 2) {
$num = (string)$num;
if ($num === '' || $num === null) return null;
if (function_exists('bcadd') && function_exists('bccomp')) {
$precision = (int)$precision;
$guardScale = max($precision + 3, 6);
// Determine sign
$isNeg = (bccomp($num, '0', $guardScale) < 0);
// 0.005 for 2dp, 0.0005 for 3dp, etc.
$half = '0.' . str_repeat('0', max(0, $precision - 1)) . '5';
// Add/subtract half unit then truncate to precision
$adjusted = $isNeg
? bcsub($num, $half, $guardScale)
: bcadd($num, $half, $guardScale);
// Truncate at precision
return bcadd($adjusted, '0', $precision);
}
// Float fallback
return number_format((float)$num, $precision, '.', '');
}
/**
* Display money with exactly 2 decimals (.00)
*/
function money_2dp($value) {
if ($value === null || $value === '') return '';
$rounded = round_decimal_str($value, 2);
if ($rounded === null || $rounded === '') return '';
// Ensure exactly 2dp string
if (strpos($rounded, '.') === false) return $rounded . '.00';
$parts = explode('.', $rounded, 2);
$dec = $parts[1] ?? '00';
$dec = substr($dec . '00', 0, 2);
return $parts[0] . '.' . $dec;
}
function coingecko_ids_for_coins(array $coins): array {
$map = [
'BTC' => 'bitcoin',
'ETH' => 'ethereum',
'SOL' => 'solana',
'TRX' => 'tron',
'USDT' => 'tether',
'USDC' => 'usd-coin',
'BNB' => 'binancecoin',
'XRP' => 'ripple',
'DOGE' => 'dogecoin',
'LTC' => 'litecoin',
];
$ids = [];
foreach ($coins as $c) {
$c = strtoupper(trim($c));
if (isset($map[$c])) $ids[$c] = $map[$c];
}
return $ids;
}
function coingecko_fetch_usd_rates(array $coinToId): array {
if (empty($coinToId)) return [];
$ids = implode(',', array_values($coinToId));
$url = "https://api.coingecko.com/api/v3/simple/price?ids=" . urlencode($ids) . "&vs_currencies=usd";
$ctx = stream_context_create([
'http' => [
'timeout' => 8,
'header' => "Accept: application/json\r\nUser-Agent: Bitcardo/1.0\r\n",
]
]);
$json = @file_get_contents($url, false, $ctx);
if (!$json) return [];
$data = json_decode($json, true);
if (!is_array($data)) return [];
$rates = [];
foreach ($coinToId as $coin => $id) {
if (isset($data[$id]['usd'])) {
// keep as string for BCMath
$rates[$coin] = (string)$data[$id]['usd'];
}
}
return $rates;
}
/**
* Load Central Wallets (platform wallets)
* - Prefer `central_wallets` if present, else fallback to `cwallet`
* - Display wallet address + raw balance (no formatting)
*/
$centralWallets = [];
$cwallet_error = null;
$cwallet_table = null;
try {
// Detect which table exists
$candidates = ['central_wallets', 'cwallet'];
foreach ($candidates as $tbl) {
$res = $conn->query("SHOW TABLES LIKE '" . $conn->real_escape_string($tbl) . "'");
if ($res && $res->num_rows > 0) {
$cwallet_table = $tbl;
break;
}
}
if ($cwallet_table) {
$sql = "SELECT * FROM `$cwallet_table` ORDER BY coin ASC";
$res = $conn->query($sql);
if ($res) {
while ($row = $res->fetch_assoc()) {
// Flexible column mapping (supports varying schemas)
$coin = $row['coin'] ?? $row['wallet_coin'] ?? $row['symbol'] ?? '';
// Wallet address (your logs suggest wallet_add)
$address =
$row['wallet_add'] ??
$row['address'] ??
$row['wallet_address'] ??
$row['wallet_address_id'] ??
'';
// Balance (raw)
$balance =
$row['wallet_balance'] ??
$row['balance'] ??
$row['available_balance'] ??
'0';
$centralWallets[] = [
'coin' => (string)$coin,
'address' => (string)$address,
'balance' => (string)$balance,
];
}
} else {
$cwallet_error = "Query failed: " . $conn->error;
}
} else {
$cwallet_error = "No central wallet table found (expected `central_wallets` or `cwallet`).";
}
} catch (Throwable $e) {
$cwallet_error = $e->getMessage();
}
/**
* Fetch USD rates and compute USD values (USD shown in 2dp)
* USD value is derived: raw_balance * live_usd_rate
*/
$coinsOnPage = [];
foreach ($centralWallets as $w) {
if (!empty($w['coin'])) $coinsOnPage[] = strtoupper(trim($w['coin']));
}
$coinsOnPage = array_values(array_unique($coinsOnPage));
$coinToId = coingecko_ids_for_coins($coinsOnPage);
$usdRates = coingecko_fetch_usd_rates($coinToId);
// Stablecoins fallback (optional)
$usdRates['USDT'] = $usdRates['USDT'] ?? '1';
$usdRates['USDC'] = $usdRates['USDC'] ?? '1';
foreach ($centralWallets as &$w) {
$coin = strtoupper(trim((string)$w['coin']));
$bal = (string)($w['balance'] ?? '0');
$rate = $usdRates[$coin] ?? null;
$w['usd_rate'] = $rate; // stored for internal use/debug if needed
$w['usd_value'] = ($rate === null) ? null : dec_mul($bal, $rate, 18);
}
unset($w);
?>
<div class="nk-content nk-content-fluid">
<div class="container-xl wide-lg">
<div class="nk-content-body">
<div class="nk-block-head">
<div class="nk-block-between-md g-4">
<div class="nk-block-head-content">
<h5 class="nk-block-title fw-normal">Paystack Funding</h5>
<div class="nk-block-des">
<p></p>
</div>
</div>
<div class="nk-block-head-content">
<ul class="nk-block-tools gx-3">
</ul>
</div>
</div>
</div>
<div class="row g-gs">
<!-- Paystack funding account (NUBAN) + live balance -->
<div class="col-lg-6">
<div class="card card-bordered h-100">
<div class="card-inner">
<h6 class="title mb-3">Paystack Payout Funding</h6>
<div class="alert alert-info small mb-3">
Use this account to top up your Paystack balance for Bitcardo NGN withdrawals.
</div>
<dl class="row mb-3">
<dt class="col-5 small text-soft">Bank</dt>
<dd class="col-7 fw-bold">
<?= htmlspecialchars(PAYSTACK_FUNDING_BANK_NAME) ?>
</dd>
<dt class="col-5 small text-soft">Account Name</dt>
<dd class="col-7 fw-bold">
<?= htmlspecialchars(PAYSTACK_FUNDING_ACCOUNT_NAME) ?>
</dd>
<dt class="col-5 small text-soft">Account Number</dt>
<dd class="col-7 fw-bold">
<span class="fs-5">
<?= htmlspecialchars(PAYSTACK_FUNDING_ACCOUNT_NO) ?>
</span>
</dd>
<?php if (PAYSTACK_FUNDING_NOTE): ?>
<dt class="col-5 small text-soft">Note</dt>
<dd class="col-7 small text-muted">
<?= htmlspecialchars(PAYSTACK_FUNDING_NOTE) ?>
</dd>
<?php endif; ?>
</dl>
<hr>
<h6 class="title mb-2">Current Paystack NGN Balance</h6>
<?php if ($ps_error): ?>
<div class="alert alert-danger small mb-0">
Could not fetch balance: <?= htmlspecialchars($ps_error) ?>
</div>
<?php elseif (!$ps_ngn): ?>
<div class="small text-soft">No NGN balance data returned.</div>
<?php else: ?>
<div class="d-flex justify-content-between align-items-center mb-1">
<span class="small text-soft">Available</span>
<span class="fw-bold fs-5">
₦<?= number_format($ps_ngn['available'], 2) ?>
</span>
</div>
<div class="d-flex justify-content-between align-items-center small text-soft">
<span>Pending</span>
<span>₦<?= number_format($ps_ngn['pending'], 2) ?></span>
</div>
<?php endif; ?>
</div>
</div>
</div>
<!-- Central Wallets (cwallet/central_wallets) -->
<div class="col-lg-6">
<div class="card card-bordered h-100">
<div class="card-inner">
<div class="d-flex justify-content-between align-items-center mb-2">
<h6 class="title mb-0">Central Wallets</h6>
<?php if ($cwallet_table): ?>
<span class="badge bg-outline-secondary">
Source: <?= htmlspecialchars($cwallet_table) ?>
</span>
<?php endif; ?>
</div>
<div class="alert alert-light small">
Platform wallets showing wallet address, raw balance, and USD value (2dp).
</div>
<?php if ($cwallet_error): ?>
<div class="alert alert-danger small mb-0">
<?= htmlspecialchars($cwallet_error) ?>
</div>
<?php elseif (empty($centralWallets)): ?>
<div class="small text-soft">No wallets returned.</div>
<?php else: ?>
<div class="table-responsive">
<table class="table table-sm table-middle mb-0">
<thead>
<tr class="small text-soft">
<th>Coin</th>
<th>Wallet Address</th>
<th class="text-end">Balance (raw)</th>
<th class="text-end">USD</th>
</tr>
</thead>
<tbody>
<?php foreach ($centralWallets as $w): ?>
<tr>
<td class="fw-bold">
<?= htmlspecialchars($w['coin'] ?: '-') ?>
</td>
<td class="small text-break" style="max-width: 320px;">
<?= htmlspecialchars($w['address'] ?: '-') ?>
</td>
<td class="text-end">
<?= htmlspecialchars($w['balance']) ?>
</td>
<td class="text-end">
<?php if ($w['usd_value'] !== null && $w['usd_value'] !== ''): ?>
$<?= htmlspecialchars(money_2dp($w['usd_value'])) ?>
<?php else: ?>
-
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<? include '../common/footer.php'; ?>
Выполнить команду
Для локальной разработки. Не используйте в интернете!