File manager - Edit - /home/webapp69.cm.in.th/u69319090028/Shop/views/admin/payments/show.php
Back
<?php /** * Admin Payment Detail / Verification * Route: GET /admin/payments/{order_no} */ $m = $payment['payment_method']; if ($m === 'PromptPay') { $methodLabel = '<i class="bi bi-qr-code me-1 text-primary"></i>PromptPay'; } elseif ($m === 'BankTransfer') { $methodLabel = '<i class="bi bi-bank me-1 text-primary"></i>Bank Transfer'; } elseif ($m === 'COD') { $methodLabel = '<i class="bi bi-truck me-1 text-success"></i>COD'; } else { $methodLabel = e($m); } function adminPayStatusBadge(string $s): string { switch ($s) { case 'pending': return '<span class="badge bg-warning text-dark">รอชำระ</span>'; case 'awaiting_verification': return '<span class="badge bg-primary">รอตรวจสอบ</span>'; case 'confirmed': return '<span class="badge bg-success">ยืนยันแล้ว</span>'; case 'failed': return '<span class="badge bg-danger">ล้มเหลว</span>'; case 'expired': return '<span class="badge bg-secondary">หมดอายุ</span>'; case 'cancelled': return '<span class="badge bg-secondary">ยกเลิก</span>'; case 'refund_pending': return '<span class="badge" style="background:#f59e0b;color:#fff;">รอคืนเงิน</span>'; case 'refunded': return '<span class="badge bg-info text-dark">คืนเงินแล้ว</span>'; default: return '<span class="badge bg-light text-dark border">' . e($s) . '</span>'; } } ?> <!-- Back link --> <a href="<?= url('/admin/payments') ?>" class="text-primary text-decoration-none small fw-semibold d-inline-flex align-items-center gap-1 mb-4"> <i class="bi bi-arrow-left"></i> กลับรายการ </a> <div class="d-flex justify-content-between align-items-start mb-4 flex-wrap gap-2"> <div> <h4 class="fw-bold mb-1 text-dark">Payment Detail</h4> <p class="text-muted small mb-0">Order <code class="text-primary fw-bold">#<?= e($payment['order_no']) ?></code></p> </div> <?= adminPayStatusBadge($payment['payment_status']) ?> </div> <div class="row g-4"> <!-- Left: Payment Summary + Attempts --> <div class="col-lg-8"> <!-- Payment Summary Card --> <div class="card border-0 shadow-sm mb-4"> <div class="card-header bg-white border-bottom d-flex align-items-center gap-2"> <i class="bi bi-receipt text-primary"></i> <span class="fw-bold small text-dark">ข้อมูลการชำระเงิน</span> </div> <div class="card-body"> <div class="row g-3 small"> <div class="col-6 col-md-3"> <div class="text-muted mb-1">ยอดที่ต้องชำระ</div> <div class="fw-bold fs-5 text-primary">฿<?= number_format((float)$payment['amount'], 2) ?></div> </div> <div class="col-6 col-md-3"> <div class="text-muted mb-1">วิธีชำระเงิน</div> <div class="fw-medium"><?= $methodLabel ?></div> </div> <div class="col-6 col-md-3"> <div class="text-muted mb-1">หมดอายุ</div> <div class="fw-medium text-dark"><?= date('d/m/Y H:i', strtotime($payment['expires_at'])) ?></div> </div> <div class="col-6 col-md-3"> <div class="text-muted mb-1">จำนวน Attempt</div> <div class="fw-medium text-dark"><?= count($payment['attempts'] ?? []) ?></div> </div> <?php if (!empty($payment['confirmed_at'])): ?> <div class="col-6 col-md-4"> <div class="text-muted mb-1">ยืนยันเมื่อ</div> <div class="fw-medium text-success"><?= date('d/m/Y H:i', strtotime($payment['confirmed_at'])) ?></div> </div> <?php endif; ?> <?php if (!empty($payment['account_number'])): ?> <div class="col-12 border-top pt-2 mt-2"> <div class="text-muted mb-1"><i class="bi bi-bank me-1"></i>บัญชีรับเงินปลายทาง (Account Snapshot):</div> <div class="p-2 bg-light rounded border text-dark d-flex align-items-center justify-content-between flex-wrap gap-2"> <div> <strong><?= e($payment['bank_name'] ?? 'พร้อมเพย์') ?></strong> — เลขที่ <code><?= e($payment['account_number']) ?></code> <span class="text-muted ms-2">(<?= e($payment['account_name'] ?? 'บริษัท คาร์กู มาร์เก็ตเพลส จำกัด') ?>)</span> </div> <span class="badge bg-secondary-subtle text-secondary border">Active Account</span> </div> </div> <?php endif; ?> </div> </div> </div> <!-- Payment Attempts List --> <div class="card border-0 shadow-sm mb-4"> <div class="card-header bg-white border-bottom d-flex justify-content-between align-items-center"> <div class="d-flex align-items-center gap-2"> <i class="bi bi-images text-primary"></i> <span class="fw-bold small text-dark">สลิปที่อัปโหลด</span> </div> <span class="badge bg-light text-dark border"><?= count($payment['attempts'] ?? []) ?> attempts</span> </div> <div class="card-body p-0"> <?php if (empty($payment['attempts'])): ?> <div class="text-center py-4 text-muted small"> <i class="bi bi-inbox fs-4 d-block mb-2"></i>ยังไม่มีสลิปที่อัปโหลด </div> <?php else: ?> <?php foreach ($payment['attempts'] as $i => $att): ?> <?php $attStatus = $att['status']; if ($attStatus === 'approved') { $attBorderClass = 'border-success'; $attBadge = '<span class="badge bg-success">ยืนยันแล้ว</span>'; } elseif ($attStatus === 'rejected') { $attBorderClass = 'border-danger'; $attBadge = '<span class="badge bg-danger">ถูกปฏิเสธ</span>'; } else { $attBorderClass = 'border-warning'; $attBadge = '<span class="badge bg-warning text-dark">รอตรวจสอบ</span>'; } ?> <div class="p-3 border-bottom <?= $i > 0 ? '' : '' ?>"> <div class="d-flex justify-content-between align-items-start mb-2 gap-2"> <div class="fw-bold small text-dark"> <i class="bi bi-receipt me-1 text-muted"></i>ครั้งที่ <?= (int)$att['attempt_no'] ?> <span class="text-muted fw-normal ms-2" style="font-size:.75rem;"><?= date('d/m/Y H:i', strtotime($att['created_at'])) ?></span> </div> <?= $attBadge ?> </div> <div class="d-flex flex-wrap gap-3 align-items-start"> <!-- Slip Image Preview --> <div> <?php if (!empty($att['slip_image'])): ?> <a href="<?= asset('/uploads/slips/' . e($att['slip_image'])) ?>" target="_blank"> <img src="<?= asset('/uploads/slips/' . e($att['slip_image'])) ?>" alt="slip" class="rounded-2 border" style="width:140px;height:140px;object-fit:cover;cursor:pointer;"> </a> <div class="small text-primary mt-1"> <a href="<?= asset('/uploads/slips/' . e($att['slip_image'])) ?>" target="_blank" class="text-decoration-none"> <i class="bi bi-zoom-in me-1"></i>ขยายสลิป </a> </div> <?php else: ?> <div class="rounded-2 border bg-light d-flex align-items-center justify-content-center text-muted" style="width:140px;height:140px;"> <i class="bi bi-image fs-2"></i> </div> <?php endif; ?> </div> <!-- Info --> <div class="flex-grow-1"> <div class="small text-muted mb-1">ผู้อัปโหลด: <span class="text-dark"><?= e($att['submitted_by_name']) ?></span></div> <?php if (!empty($att['note'])): ?> <div class="small text-muted mb-1">หมายเหตุ: <span class="text-dark"><?= e($att['note']) ?></span></div> <?php endif; ?> <?php if (!empty($att['reject_reason'])): ?> <div class="alert alert-danger py-1 px-2 small mb-2"> <i class="bi bi-exclamation-circle me-1"></i>เหตุผลปฏิเสธ: <?= e($att['reject_reason']) ?> </div> <?php endif; ?> <!-- Verify Actions for pending attempts --> <?php if ($att['status'] === 'pending'): ?> <div class="d-flex gap-2 mt-2"> <button class="btn btn-sm btn-success px-3 fw-bold verify-btn" data-action="confirm" data-attempt-id="<?= (int)$att['id'] ?>" data-order-no="<?= e($payment['order_no']) ?>"> <i class="bi bi-check-lg me-1"></i>ยืนยันการชำระเงิน </button> <button class="btn btn-sm btn-outline-danger px-3 verify-btn" data-action="reject" data-attempt-id="<?= (int)$att['id'] ?>" data-order-no="<?= e($payment['order_no']) ?>"> <i class="bi bi-x-lg me-1"></i>ปฏิเสธ </button> </div> <?php endif; ?> </div> </div> </div> <?php endforeach; ?> <?php endif; ?> <!-- Direct Payment Confirmation / Override for pending payments without pending attempts --> <?php $hasPendingAttempt = false; foreach ($payment['attempts'] ?? [] as $att) { if ($att['status'] === 'pending') { $hasPendingAttempt = true; break; } } ?> <?php if (!$hasPendingAttempt && in_array($payment['payment_status'], ['pending', 'awaiting_verification', 'failed'], true)): ?> <div class="p-3 bg-light border-top d-flex justify-content-between align-items-center flex-wrap gap-2"> <div> <div class="fw-bold small text-dark"><i class="bi bi-shield-check text-primary me-1"></i>ดำเนินการยืนยันการชำระเงินโดยตรง (Direct Confirmation)</div> <div class="text-muted" style="font-size:0.75rem;">ยืนยันหรือปฏิเสธรายการชำระเงินนี้โดยตรง แม้ไม่มีสลิปรอดำเนินการ</div> </div> <div class="d-flex gap-2"> <button class="btn btn-sm btn-success px-3 fw-bold verify-btn" data-action="confirm" data-attempt-id="0" data-payment-id="<?= (int)$payment['id'] ?>" data-order-no="<?= e($payment['order_no']) ?>"> <i class="bi bi-check-lg me-1"></i>ยืนยันการชำระเงิน </button> <button class="btn btn-sm btn-outline-danger px-3 verify-btn" data-action="reject" data-attempt-id="0" data-payment-id="<?= (int)$payment['id'] ?>" data-order-no="<?= e($payment['order_no']) ?>"> <i class="bi bi-x-lg me-1"></i>ปฏิเสธ </button> </div> </div> <?php endif; ?> </div> </div> <!-- Payment History Timeline --> <?php if (!empty($payment['history'])): ?> <div class="card border-0 shadow-sm"> <div class="card-header bg-white border-bottom d-flex align-items-center gap-2"> <i class="bi bi-activity text-primary"></i> <span class="fw-bold small text-dark">Payment History</span> </div> <div class="card-body py-3"> <div class="d-flex flex-column gap-2"> <?php foreach ($payment['history'] as $h): ?> <div class="d-flex align-items-start gap-2 small"> <span class="text-muted mt-1" style="min-width:110px;"><?= date('d/m/Y H:i', strtotime($h['created_at'])) ?></span> <span class="badge bg-light text-dark border" style="white-space:nowrap;"><?= e($h['from_status']) ?></span> <i class="bi bi-arrow-right text-muted mt-1"></i> <span class="badge bg-primary"><?= e($h['to_status']) ?></span> <?php if (!empty($h['actor_name'])): ?> <span class="text-muted">โดย <strong class="text-dark"><?= e($h['actor_name']) ?></strong></span> <?php else: ?> <span class="text-muted">(ระบบ)</span> <?php endif; ?> <?php if (!empty($h['note'])): ?> <span class="text-muted">— <?= e($h['note']) ?></span> <?php endif; ?> </div> <?php endforeach; ?> </div> </div> </div> <?php endif; ?> </div> <!-- Right: Order Info --> <div class="col-lg-4"> <div class="card border-0 shadow-sm"> <div class="card-header bg-white border-bottom d-flex align-items-center gap-2"> <i class="bi bi-box-seam text-primary"></i> <span class="fw-bold small text-dark">ข้อมูล Order</span> </div> <div class="card-body small"> <div class="mb-2"><span class="text-muted">Order No: </span><code class="text-primary"><?= e($payment['order_no']) ?></code></div> <div class="mb-2"><span class="text-muted">ลูกค้า: </span><span class="text-dark fw-medium"><?= e($payment['customer_name'] ?? '—') ?></span></div> <div class="mb-3"><span class="text-muted">อีเมล: </span><span class="text-dark"><?= e($payment['customer_email'] ?? '—') ?></span></div> <a href="<?= url('/admin/orders/' . e($payment['order_no'])) ?>" class="btn btn-outline-primary btn-sm w-100"> <i class="bi bi-eye me-1"></i>ดูรายละเอียด Order </a> </div> </div> </div> </div> <!-- Verify Modal --> <div class="modal fade" id="verifyModal" tabindex="-1" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered"> <div class="modal-content"> <form id="verifyForm" method="POST" action="<?= url('/admin/payments/verify') ?>"> <?= Security::csrfField() ?> <input type="hidden" name="attempt_id" id="verifyAttemptId" value="0"> <input type="hidden" name="payment_id" id="verifyPaymentId" value="<?= (int)$payment['id'] ?>"> <input type="hidden" name="action" id="verifyAction" value=""> <input type="hidden" name="order_no" value="<?= e($payment['order_no']) ?>"> <div class="modal-header border-0 pb-0"> <h5 class="modal-title fw-bold" id="verifyModalTitle"></h5> <button type="button" class="btn-close" data-bs-dismiss="modal"></button> </div> <div class="modal-body pt-2"> <div id="verifyConfirmNote" class="mb-3"> <label class="form-label small fw-bold text-muted">หมายเหตุ (ถ้ามี)</label> <textarea name="note" class="form-control form-control-sm" rows="2" placeholder="บันทึกเพิ่มเติม..."></textarea> </div> <div id="verifyRejectReason" class="mb-3 d-none"> <label class="form-label small fw-bold text-danger">เหตุผลในการปฏิเสธ <span class="text-danger">*</span></label> <textarea name="reason" class="form-control form-control-sm" rows="3" placeholder="ระบุเหตุผลที่ชัดเจน..."></textarea> </div> <div id="verifyWarningConfirm" class="alert alert-success py-2 small d-none"> <i class="bi bi-check-circle me-1"></i>การยืนยันจะเปลี่ยน Order Status เป็น <strong>กำลังเตรียมสินค้า</strong> </div> <div id="verifyWarningReject" class="alert alert-warning py-2 small d-none"> <i class="bi bi-exclamation-triangle me-1"></i>ลูกค้าจะสามารถอัปโหลดสลิปใหม่ได้หลังจากนี้ </div> </div> <div class="modal-footer border-0 pt-0"> <button type="button" class="btn btn-outline-secondary btn-sm" data-bs-dismiss="modal">ยกเลิก</button> <button type="submit" class="btn btn-sm fw-bold px-4" id="verifySubmitBtn"></button> </div> </form> </div> </div> </div> <script> document.querySelectorAll('.verify-btn').forEach(btn => { btn.addEventListener('click', () => { const action = btn.dataset.action; const attemptId = btn.dataset.attemptId || 0; const paymentId = btn.dataset.paymentId || '<?= (int)$payment['id'] ?>'; document.getElementById('verifyAttemptId').value = attemptId; document.getElementById('verifyPaymentId').value = paymentId; document.getElementById('verifyAction').value = action; const isConfirm = action === 'confirm'; document.getElementById('verifyModalTitle').textContent = isConfirm ? 'ยืนยันการชำระเงิน' : 'ปฏิเสธสลิป'; document.getElementById('verifyConfirmNote').classList.toggle('d-none', !isConfirm); document.getElementById('verifyRejectReason').classList.toggle('d-none', isConfirm); document.getElementById('verifyWarningConfirm').classList.toggle('d-none', !isConfirm); document.getElementById('verifyWarningReject').classList.toggle('d-none', isConfirm); const submitBtn = document.getElementById('verifySubmitBtn'); submitBtn.textContent = isConfirm ? 'ยืนยันการชำระเงิน' : 'ปฏิเสธสลิป'; submitBtn.className = 'btn btn-sm fw-bold px-4 ' + (isConfirm ? 'btn-success' : 'btn-danger'); new bootstrap.Modal(document.getElementById('verifyModal')).show(); }); }); // AJAX form submit document.getElementById('verifyForm').addEventListener('submit', async function(e) { e.preventDefault(); const btn = document.getElementById('verifySubmitBtn'); btn.disabled = true; btn.textContent = 'กำลังดำเนินการ...'; try { const res = await fetch(this.action, { method: 'POST', headers: { 'X-Requested-With': 'XMLHttpRequest' }, body: new FormData(this) }); const data = await res.json(); if (data.success) { location.reload(); } else { alert(data.message || 'เกิดข้อผิดพลาด'); btn.disabled = false; } } catch { alert('เกิดข้อผิดพลาดในการเชื่อมต่อ'); btn.disabled = false; } }); </script>
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.24 |
proxy
|
phpinfo
|
Settings