PHP WebShell
Текущая директория: /var/www/bitcardoApp
Просмотр файла: bitgo_enterprise_status.php
<?php
// enterprises_pretty.php — Layman-friendly BitGo Enterprises page (with Plan & Billing note)
include 'config/bitgo_config.php';
/* ---------------- Helpers (no JSON shown to user) ---------------- */
function friendly_error($msg, $tip = null) {
return ['ok' => false, 'message' => $msg, 'tip' => $tip];
}
function fetch_enterprises() {
if (!defined('BITGO_API_BASE_URL') || BITGO_API_BASE_URL === '') {
return friendly_error('Your connection settings are incomplete.',
'Please set BITGO_API_BASE_URL in your config.');
}
if (!defined('BITGO_ACCESS_TOKEN') || BITGO_ACCESS_TOKEN === '') {
return friendly_error('Your access key is missing.',
'Please set BITGO_ACCESS_TOKEN in your config.');
}
$url = rtrim(BITGO_API_BASE_URL, '/') . '/enterprise'; // GET /api/v2/enterprise
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . BITGO_ACCESS_TOKEN,
'Content-Type: application/json'
]
]);
$res = curl_exec($ch);
if ($res === false) {
$err = curl_error($ch);
curl_close($ch);
return friendly_error('We couldn’t reach the service.', 'Network said: ' . $err);
}
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$decoded = json_decode($res, true);
if ($code < 200 || $code >= 300 || !is_array($decoded)) {
return friendly_error('The service responded, but not with usable data.',
'Status code: ' . $code . '. Please try again or check your credentials.');
}
// BitGo usually returns { enterprises: [...] }
$list = $decoded['enterprises'] ?? $decoded;
if (!is_array($list)) $list = [];
return ['ok' => true, 'items' => $list];
}
/** Make labels nice for humans: "createDate" -> "Create Date" */
function human_label($key) {
$key = preg_replace('/[_\-]+/', ' ', $key);
$key = preg_replace('/([a-z])([A-Z])/', '$1 $2', $key);
$key = ucwords(strtolower($key));
return $key;
}
/** Format any value safely into a short, readable string (no JSON). */
function human_value($val) {
if ($val === null || $val === '') return '—';
if (is_bool($val)) return $val ? 'Yes' : 'No';
if (is_numeric($val)) return (string)$val;
// Try to format common date strings
if (is_string($val)) {
$ts = strtotime($val);
if ($ts && $ts > 0) {
return date('M j, Y • H:i', $ts);
}
// Don’t print very long blobs
if (strlen($val) > 120) return substr($val, 0, 117) . '…';
return $val;
}
// Arrays/objects → short summaries
if (is_array($val)) {
$flat = [];
foreach ($val as $k => $v) {
if (is_scalar($v) && strlen((string)$v) <= 30) {
$flat[] = (is_string($k) ? human_label($k) . ': ' : '') . (is_bool($v) ? ($v ? 'Yes' : 'No') : $v);
}
if (count($flat) >= 4) break;
}
if ($flat) return implode(' • ', $flat);
$count = count($val);
return $count === 0 ? '(Empty list)' : "List with $count item" . ($count === 1 ? '' : 's');
}
return '(data)';
}
/** Pull top fields we expect, plus a few extras for the details section. */
function split_fields($item) {
$main = [];
$extra = [];
// Common field name variants
$main['ID'] = $item['id'] ?? $item['_id'] ?? null;
$main['Name'] = $item['name'] ?? null;
$main['Created'] = $item['created'] ?? $item['createDate'] ?? null;
$main['Plan'] = $item['pricingPlan'] ?? null; // <-- Plan shown to user
// Remove main keys from copy
$copy = $item;
unset($copy['id'], $copy['_id'], $copy['name'], $copy['created'], $copy['createDate'], $copy['pricingPlan']);
// Extras: pick up to ~8 simple fields for display
foreach ($copy as $k => $v) {
if (count($extra) >= 8) break;
$extra[human_label($k)] = $v;
}
return [$main, $extra];
}
$data = fetch_enterprises();
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My Enterprises</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap (CDN) -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body { background: #0b1220; color: #e6edf3; }
.navbar { background: #0f172a; }
.card { background: #111827; border-color: #1f2937; }
.muted { color: #94a3b8; }
.badge-soft { background: rgba(59,130,246,.15); color: #93c5fd; }
.kv dt { width: 160px; min-width: 160px; color: #cbd5e1; }
.kv dd { margin-left: 0; color: #e5e7eb; }
.kv { display: grid; grid-template-columns: 160px 1fr; row-gap: .35rem; column-gap: 1rem; }
.footer { color: #94a3b8; }
code { color: #cbd5e1; background: #0b1220; padding: .15rem .35rem; border-radius: .25rem; }
.chip { display:inline-block; padding:.15rem .5rem; border-radius:999px; font-size:.8rem; background:rgba(99,102,241,.15); color:#a5b4fc; border:1px solid rgba(99,102,241,.3); }
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark">
<div class="container">
<span class="navbar-brand">Enterprise Directory</span>
</div>
</nav>
<main class="container my-4">
<h1 class="h3 mb-3">Your Enterprises</h1>
<?php if (!$data['ok']): ?>
<div class="alert alert-warning">
<div class="h6 mb-1"><?= htmlspecialchars($data['message']) ?></div>
<?php if (!empty($data['tip'])): ?>
<div class="small"><?= htmlspecialchars($data['tip']) ?></div>
<?php endif; ?>
</div>
<?php else: ?>
<?php
$items = $data['items'];
$count = is_array($items) ? count($items) : 0;
?>
<div class="card mb-3">
<div class="card-body d-flex justify-content-between align-items-center">
<div>
<div class="h5 mb-1">Results</div>
<div class="muted">Found <strong><?= $count ?></strong> enterprise<?= $count === 1 ? '' : 's' ?>.</div>
</div>
<span class="badge badge-soft rounded-pill">Live Status</span>
</div>
</div>
<!-- Billing explainer card -->
<div class="card mb-4">
<div class="card-body">
<div class="h5 mb-2">Billing & Pricing</div>
<div class="muted">
Pricing depends on your contract and plan. Bills usually combine:
<ul class="mb-2">
<li><strong>Assets-Under-Custody</strong> fee (a small % of your average monthly USD balance)</li>
<li><strong>Per-transaction</strong> fees</li>
</ul>
For your exact rates, please check your service agreement or contact your account admin.
</div>
</div>
</div>
<?php if ($count === 0): ?>
<div class="alert alert-info">No enterprises available for this account.</div>
<?php else: ?>
<div class="row g-3">
<?php foreach ($items as $item): ?>
<?php list($main, $extra) = split_fields(is_array($item) ? $item : []); ?>
<div class="col-12">
<div class="card">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start">
<div>
<div class="h5 mb-1"><?= htmlspecialchars(human_value($main['Name'] ?? 'Untitled')) ?></div>
<div class="muted small">
<strong>ID:</strong> <code><?= htmlspecialchars(human_value($main['ID'] ?? '—')) ?></code>
•
<strong>Created:</strong> <?= htmlspecialchars(human_value($main['Created'] ?? '—')) ?>
<?php if (!empty($main['Plan'])): ?>
• <strong>Plan:</strong> <span class="chip"><?= htmlspecialchars(human_value($main['Plan'])) ?></span>
<?php endif; ?>
</div>
</div>
</div>
<?php if (!empty($extra)): ?>
<hr class="text-secondary">
<div class="kv">
<?php foreach ($extra as $label => $val): ?>
<dt><?= htmlspecialchars($label) ?></dt>
<dd><?= htmlspecialchars(human_value($val)) ?></dd>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php endif; ?>
</main>
<footer class="container my-5 text-center footer">
<small>No technical data is shown here. Everything is simplified for clarity.</small>
</footer>
</body>
</html>
Выполнить команду
Для локальной разработки. Не используйте в интернете!