Update: 2026-05-09 17:43:20

This commit is contained in:
Hamza-Ayed
2026-05-09 17:43:20 +03:00
parent d7c7920b4a
commit 8780054553
2 changed files with 52 additions and 2 deletions

View File

@@ -20,10 +20,16 @@ if (!in_array($decoded['role'], ['admin', 'accountant'])) {
} }
$paymentId = $_POST['payment_id'] ?? null; $paymentId = $_POST['payment_id'] ?? null;
$bankRef = trim($_POST['bank_reference'] ?? '');
if (!$paymentId) { if (!$paymentId) {
json_error('معرف طلب الدفع مطلوب.', 422); json_error('معرف طلب الدفع مطلوب.', 422);
} }
if (!$bankRef) {
json_error('رقم مرجع الحوالة مطلوب للتفعيل الآلي.', 422);
}
if (!isset($_FILES['receipt']) || $_FILES['receipt']['error'] !== UPLOAD_ERR_OK) { if (!isset($_FILES['receipt']) || $_FILES['receipt']['error'] !== UPLOAD_ERR_OK) {
json_error('صورة وصل الدفع مطلوبة.', 422); json_error('صورة وصل الدفع مطلوبة.', 422);
} }
@@ -32,7 +38,7 @@ $db = Database::getInstance();
$tenantId = $decoded['tenant_id']; $tenantId = $decoded['tenant_id'];
try { try {
// 1. Verify payment request exists and belongs to this tenant // 1. Verify payment request exists
$stmt = $db->prepare("SELECT * FROM payment_requests WHERE id = ? AND tenant_id = ? AND status IN ('pending','uploaded')"); $stmt = $db->prepare("SELECT * FROM payment_requests WHERE id = ? AND tenant_id = ? AND status IN ('pending','uploaded')");
$stmt->execute([$paymentId, $tenantId]); $stmt->execute([$paymentId, $tenantId]);
$payment = $stmt->fetch(); $payment = $stmt->fetch();
@@ -41,7 +47,39 @@ try {
json_error('طلب الدفع غير موجود أو تم معالجته بالفعل.', 404); json_error('طلب الدفع غير موجود أو تم معالجته بالفعل.', 404);
} }
// 2. Save receipt image // Update the payment request with the provided bank reference
$stmt = $db->prepare("UPDATE payment_requests SET bank_reference = ? WHERE id = ?");
$stmt->execute([$bankRef, $paymentId]);
$payment['bank_reference'] = $bankRef;
// 2. Immediate Check: Has the bot already received this transaction?
$stmt = $db->prepare("SELECT * FROM bank_transactions WHERE bank_reference = ? AND is_claimed = 0 LIMIT 1");
$stmt->execute([$bankRef]);
$transaction = $stmt->fetch();
if ($transaction) {
$expectedAmount = (float)$payment['amount_jod'];
$actualAmount = (float)$transaction['amount'];
if (abs($expectedAmount - $actualAmount) < 0.01) {
// MATCH FOUND! Auto activate.
activateSubscription($db, $payment, $decoded['user_id']);
$stmt = $db->prepare("UPDATE payment_requests SET status = 'approved', verified_at = NOW() WHERE id = ?");
$stmt->execute([$paymentId]);
$stmt = $db->prepare("UPDATE bank_transactions SET is_claimed = 1 WHERE id = ?");
$stmt->execute([$transaction['id']]);
json_success([
'status' => 'approved',
'auto_verified' => true,
'message' => 'تم العثور على الحوالة وتفعيل اشتراكك فوراً! شكراً لك.'
], 'تم تفعيل الاشتراك بنجاح');
}
}
// 3. If no immediate match, save the receipt and wait for AI/Bot backup
$uploadDir = STORAGE_PATH . '/receipts/' . $tenantId; $uploadDir = STORAGE_PATH . '/receipts/' . $tenantId;
if (!is_dir($uploadDir)) { if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0750, true); mkdir($uploadDir, 0750, true);

View File

@@ -2380,6 +2380,15 @@
<p style="margin-bottom:8px; font-size:13px; color:var(--text-2);">يرجى التحويل إلى حساب CliQ التالي:</p> <p style="margin-bottom:8px; font-size:13px; color:var(--text-2);">يرجى التحويل إلى حساب CliQ التالي:</p>
<div style="background:white; padding:10px 20px; border:1px dashed var(--teal); border-radius:8px; font-family:'Outfit',sans-serif; font-size:20px; font-weight:bold; color:var(--navy); display:inline-block; letter-spacing:1px;" x-text="paymentData.cliq_alias"></div> <div style="background:white; padding:10px 20px; border:1px dashed var(--teal); border-radius:8px; font-family:'Outfit',sans-serif; font-size:20px; font-weight:bold; color:var(--navy); display:inline-block; letter-spacing:1px;" x-text="paymentData.cliq_alias"></div>
</div> </div>
<div style="margin-top:20px; border-top:1px solid #f1f5f9; padding-top:20px;">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:8px;">
<label class="form-label" style="color:var(--navy); font-weight:700; margin-bottom:0;">رقم مرجع الحوالة (Reference)</label>
<span style="background:var(--teal-subtle); color:var(--teal); font-size:10px; padding:2px 8px; border-radius:10px; font-weight:700;"> تفعيل فوري</span>
</div>
<input type="text" x-model="paymentData.bank_reference" class="form-input" placeholder="ألصق رقم المرجع هنا (مثلاً: JIBA...)" style="font-family:'Outfit',sans-serif; font-size:18px; border:2px solid var(--teal); background:#f0fdfa; text-align:center; letter-spacing:1px;">
<p style="font-size:11px; color:var(--text-3); margin-top:6px; line-height:1.4;">هذا الرقم يصلك في رسالة الـ SMS من البنك. إدخاله يضمن تفعيل اشتراكك خلال ثوانٍ دون انتظار المراجعة البشرية.</p>
</div>
</div> </div>
<div class="form-group" style="margin-top:10px;"> <div class="form-group" style="margin-top:10px;">
@@ -2785,9 +2794,12 @@
async uploadReceipt() { async uploadReceipt() {
if (!this.selectedFile || this.isBusy) return alert('الرجاء اختيار صورة الوصل'); if (!this.selectedFile || this.isBusy) return alert('الرجاء اختيار صورة الوصل');
if (!this.paymentData.bank_reference) return alert('الرجاء إدخال رقم مرجع الحوالة للتفعيل الآلي');
this.isBusy = true; this.isBusy = true;
const formData = new FormData(); const formData = new FormData();
formData.append('payment_id', this.paymentData.payment_id); formData.append('payment_id', this.paymentData.payment_id);
formData.append('bank_reference', this.paymentData.bank_reference);
formData.append('receipt', this.selectedFile); formData.append('receipt', this.selectedFile);
try { try {