PHP WebShell

Текущая директория: /var/www/bitcardoApp/backyard/user/webhooks

Просмотр файла: logs.php

<?php
// backyard/user/webhooks/logs.php
include '../common/header.php';

// Ensure DB is available
if (!isset($conn)) {
  include_once '../../config/db_config.php';
}
?>
<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">
          <div class="nk-block-head-content">
            <h4 class="nk-block-title fw-normal">Webhook Logs</h4>
            <div class="nk-block-des text-soft"><p>View and filter webhook events and responses.</p></div>
          </div>
        </div>
      </div>

      <div class="card card-bordered">
        <div class="card-inner">
          <form id="filterForm" class="row gy-2 gx-2 align-items-end">
            <div class="col-6 col-md-2">
              <label class="form-label small">TxID / Ref</label>
              <input type="text" name="txid" class="form-control" placeholder="txid/ref">
            </div>
            <div class="col-6 col-md-2">
              <label class="form-label small">Wallet ID</label>
              <input type="text" name="wallet_id" class="form-control" placeholder="wallet id">
            </div>
            <div class="col-6 col-md-2">
              <label class="form-label small">Status Code</label>
              <input type="text" name="status_code" class="form-control" placeholder="e.g. 200">
            </div>
            <div class="col-6 col-md-2">
              <label class="form-label small">Event Type</label>
              <input type="text" name="event_type" class="form-control" placeholder="event">
            </div>
            <div class="col-6 col-md-2">
              <label class="form-label small">From</label>
              <input type="date" name="from" class="form-control">
            </div>
            <div class="col-6 col-md-2">
              <label class="form-label small">To</label>
              <input type="date" name="to" class="form-control">
            </div>
            <div class="col-12 col-md-2">
              <button type="submit" class="btn btn-primary w-100 mt-1 mt-md-0">
                <i class="fa fa-search"></i> Filter
              </button>
            </div>
          </form>
        </div>
      </div>

      <div class="card card-bordered mt-3">
        <div class="card-inner p-0">
          <div class="table-responsive" id="logsTableWrapper">
            <table class="table table-striped table-hover mb-0">
              <thead class="small text-soft">
                <tr>
                  <th>ID</th>
                  <th>TxID / Ref</th>
                  <th>Wallet ID</th>
                  <th>Coin</th>
                  <th>Status</th>
                  <th>Event</th>
                  <th>Date</th>
                  <th class="text-end">Action</th>
                </tr>
              </thead>
              <tbody id="logsTableBody">
                <tr><td colspan="8" class="text-center py-3 text-soft">Loading...</td></tr>
              </tbody>
            </table>
          </div>
          <div id="pagination" class="p-3 text-center small text-soft"></div>
        </div>
      </div>

    </div>
  </div>
</div>

<!-- JSON View Modal -->
<div class="modal fade" id="viewModal" tabindex="-1">
  <div class="modal-dialog modal-xl modal-dialog-scrollable">
    <div class="modal-content">
      <div class="modal-header">
        <h6 class="modal-title">Webhook Log Details</h6>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>
      <div class="modal-body">
        <h6 class="mb-2">Payload</h6>
        <pre id="logPayload" class="bg-light p-3 rounded small text-dark" style="white-space:pre-wrap;"></pre>
        <hr>
        <h6 class="mb-2">Response</h6>
        <pre id="logResponse" class="bg-light p-3 rounded small text-dark" style="white-space:pre-wrap;"></pre>
      </div>
    </div>
  </div>
</div>

<script>
(function(){
  const tbody = document.getElementById('logsTableBody');
  const pagination = document.getElementById('pagination');
  const form = document.getElementById('filterForm');
  const modalEl = document.getElementById('viewModal');
  const modal = new bootstrap.Modal(modalEl);
  const payloadPre = document.getElementById('logPayload');
  const responsePre = document.getElementById('logResponse');

  async function fetchLogs(page = 1){
    const fd = new FormData(form);
    fd.append('page', page);
    const resp = await fetch('../../models/webhooks/webhook_logs.php', { method: 'POST', body: fd });
    let data; try { data = await resp.json(); } catch(e){ tbody.innerHTML = `<tr><td colspan="8" class="text-danger text-center">Bad JSON</td></tr>`; return; }
    renderTable(data);
  }

  function renderTable(data){
    if(!data.success){
      tbody.innerHTML = `<tr><td colspan="8" class="text-danger text-center">${data.message || 'Error'}</td></tr>`;
      pagination.innerHTML = '';
      return;
    }
    if(!data.logs || !data.logs.length){
      tbody.innerHTML = `<tr><td colspan="8" class="text-soft text-center">No results found.</td></tr>`;
      pagination.innerHTML = '';
      return;
    }

    tbody.innerHTML = data.logs.map(log=>`
      <tr>
        <td>${log.log_id}</td>
        <td>${log.txid || '—'}</td>
        <td>${log.wallet_id || '—'}</td>
        <td>${log.coin || '—'}</td>
        <td><span class="badge ${String(log.status_code)==='200' ? 'bg-success' : 'bg-danger'}">${log.status_code || '—'}</span></td>
        <td>${log.event_type || '—'}</td>
        <td>${log.received_at || '—'}</td>
        <td class="text-end">
          <button class="btn btn-sm btn-outline-secondary viewBtn" data-id="${log.log_id}">View</button>
        </td>
      </tr>
    `).join('');

    const {page, pages} = data.pagination;
    let html = '';
    if(pages>1){
      html += `<div>Page ${page} of ${pages}</div>`;
      html += `<div class="mt-2 d-flex justify-content-center gap-2 flex-wrap">`;
      for(let i=1;i<=pages;i++){
        html += `<button class="btn btn-sm ${i==page?'btn-primary':'btn-outline-primary'} pageBtn" data-page="${i}">${i}</button>`;
      }
      html += `</div>`;
    }
    pagination.innerHTML = html;
  }

  function tryPretty(s){
    if(!s) return '';
    try { return JSON.stringify(JSON.parse(s), null, 2); } catch(e){ return s; }
  }

  document.addEventListener('click', async e=>{
    if(e.target.classList.contains('pageBtn')){
      fetchLogs(e.target.dataset.page);
    }
    if(e.target.classList.contains('viewBtn')){
      const id = e.target.dataset.id;
      const resp = await fetch('../../models/webhooks/webhook_logs.php?id='+id);
      let data; try { data = await resp.json(); } catch(e){ alert('Error loading log'); return; }
      if(data.success && data.log){
        payloadPre.textContent  = tryPretty(data.log.raw_payload || '');
        responsePre.textContent = tryPretty(data.log.response || '');
        modal.show();
      } else {
        alert(data.message || 'Log not found');
      }
    }
  });

  form.addEventListener('submit', e=>{
    e.preventDefault();
    fetchLogs(1);
  });

  fetchLogs(1);
})();
</script>

<?php include '../common/footer.php'; ?>

Выполнить команду


Для локальной разработки. Не используйте в интернете!