Update: 2026-05-09 18:00:43

This commit is contained in:
Hamza-Ayed
2026-05-09 18:00:43 +03:00
parent 8780054553
commit e1bdda3cbf
2 changed files with 81 additions and 61 deletions

View File

@@ -96,10 +96,41 @@ try {
// 3. AI Analysis of receipt image // 3. AI Analysis of receipt image
$aiResult = analyzeReceipt($filepath, $payment); $aiResult = analyzeReceipt($filepath, $payment);
// 4. Calculate match score // 4. Smart Match: Use AI-extracted reference to search bank_transactions
$aiExtractedRef = trim($aiResult['reference_number'] ?? '');
if (!empty($aiExtractedRef) && $aiExtractedRef !== 'unknown') {
$stmt = $db->prepare("SELECT * FROM bank_transactions WHERE bank_reference = ? AND is_claimed = 0 LIMIT 1");
$stmt->execute([$aiExtractedRef]);
$aiMatchTransaction = $stmt->fetch();
if ($aiMatchTransaction) {
$expectedAmount = (float)$payment['amount_jod'];
$actualAmount = (float)$aiMatchTransaction['amount'];
if (abs($expectedAmount - $actualAmount) < 0.1) {
// AI FOUND THE MATCH!
activateSubscription($db, $payment, $decoded['user_id']);
$stmt = $db->prepare("UPDATE payment_requests SET status = 'approved', bank_reference = ?, verified_at = NOW() WHERE id = ?");
$stmt->execute([$aiExtractedRef, $paymentId]);
$stmt = $db->prepare("UPDATE bank_transactions SET is_claimed = 1 WHERE id = ?");
$stmt->execute([$aiMatchTransaction['id']]);
json_success([
'status' => 'approved',
'auto_verified' => true,
'method' => 'ai_ref_matching',
'message' => 'تم العثور على الحوالة بنجاح وتفعيل الاشتراك آلياً!'
], 'تم تفعيل الاشتراك بنجاح');
}
}
}
// 5. Calculate match score (for legacy manual review fallback)
$matchScore = calculateMatchScore($aiResult, $payment); $matchScore = calculateMatchScore($aiResult, $payment);
// 5. Update payment request // 6. Update payment request with AI data
$newStatus = $matchScore >= 85.0 ? 'verified' : 'uploaded'; $newStatus = $matchScore >= 85.0 ? 'verified' : 'uploaded';
$stmt = $db->prepare(" $stmt = $db->prepare("
@@ -119,29 +150,24 @@ try {
$paymentId $paymentId
]); ]);
// 6. If high confidence match, auto-activate subscription // 7. Final attempt activation if high confidence match score
if ($matchScore >= 85.0) { if ($matchScore >= 90.0) {
activateSubscription($db, $payment, $decoded['user_id']); activateSubscription($db, $payment, $decoded['user_id']);
$stmt = $db->prepare("UPDATE payment_requests SET status = 'approved', verified_at = NOW() WHERE id = ?"); $stmt = $db->prepare("UPDATE payment_requests SET status = 'approved', verified_at = NOW() WHERE id = ?");
$stmt->execute([$paymentId]); $stmt->execute([$paymentId]);
json_success([ json_success([
'status' => 'approved', 'status' => 'approved',
'match_score' => $matchScore, 'match_score' => $matchScore,
'message' => 'تم التحقق من الدفع وتفعيل الاشتراك تلقائياً!', 'message' => 'تم التحقق من الوصل وتفعيل الاشتراك تلقائياً بنسبة مطابقة عالية.'
'extracted' => $aiResult, ], 'تم تفعيل الاشتراك');
], 'تم اعتماد الدفع وتفعيل الاشتراك');
} }
json_success([ json_success([
'status' => $newStatus, 'status' => $newStatus,
'match_score' => $matchScore, 'match_score' => $matchScore,
'message' => $matchScore >= 60 'message' => $matchScore >= 70 ? 'تم استلام الوصل بنجاح، جاري المراجعة النهائية.' : 'تم استلام الوصل، بانتظار تأكيد الحوالة من البنك.'
? 'تم رفع الوصل. جاري المراجعة من الإدارة.' ], 'تم رفع الوصل');
: 'لم نتمكن من التحقق التلقائي. تم إرسال الطلب للمراجعة اليدوية.',
'extracted' => $aiResult,
], 'تم رفع وصل الدفع');
} catch (\Exception $e) { } catch (\Exception $e) {
error_log("Payment Receipt Upload Error: " . $e->getMessage()); error_log("Payment Receipt Upload Error: " . $e->getMessage());
@@ -182,7 +208,7 @@ function analyzeReceipt(string $imagePath, array $payment): array
الاسم المستعار CliQ: {$payment['cliq_alias']} الاسم المستعار CliQ: {$payment['cliq_alias']}
PROMPT; PROMPT;
$model = env('GEMINI_MODEL', 'gemini-1.5-flash'); $model = env('GEMINI_MODEL');
$url = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent?key={$apiKey}"; $url = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent?key={$apiKey}";
$payload = [ $payload = [

View File

@@ -2347,63 +2347,57 @@
<!-- ── UPLOAD PAYMENT RECEIPT MODAL ─────────────────────────── --> <!-- ── UPLOAD PAYMENT RECEIPT MODAL ─────────────────────────── -->
<div x-show="showPaymentModal" x-cloak class="modal-backdrop"> <div x-show="showPaymentModal" x-cloak class="modal-backdrop">
<div class="modal-box"> <div class="modal-box" style="max-width:440px; padding:15px;">
<div class="modal-head"> <div class="modal-head" style="margin-bottom:12px;">
<div class="modal-head-icon gold">💳</div> <div class="modal-head-icon gold" style="width:36px; height:36px; font-size:18px;">💳</div>
<div style="flex:1;"> <div style="flex:1;">
<div class="modal-title">تأكيد دفع الاشتراك</div> <div class="modal-title" style="font-size:17px;">تأكيد دفع الاشتراك</div>
<div class="modal-subtitle">يرجى تحويل المبلغ ثم رفع وصل الدفع</div> <div class="modal-subtitle" style="font-size:11px;">يرجى تحويل المبلغ ثم رفع وصل الدفع</div>
</div> </div>
<button @click="showPaymentModal = false" class="modal-close-btn"></button> <button @click="showPaymentModal = false" class="modal-close-btn"></button>
</div> </div>
<div class="modal-divider"></div>
<div class="modal-body" style="display:flex; flex-direction:column; gap:14px;">
<div style="background:var(--teal-subtle); border:1px solid rgba(4,120,87,0.2); border-radius:10px; padding:16px; text-align:center; display:flex; flex-direction:column; gap:12px;">
<h4 style="color:var(--navy); font-weight:bold; margin-bottom:4px;">تفاصيل الدفع (CliQ)</h4>
<div style="display:flex; justify-content:space-between; font-size:14px; border-bottom:1px solid rgba(0,0,0,0.05); padding-bottom:8px;"> <div class="modal-body p-0">
<span style="color:var(--text-3);">الباقة المختارة:</span> <div style="background:var(--teal-subtle); border:1px solid rgba(4,120,87,0.15); border-radius:10px; padding:12px; margin-bottom:12px;">
<div style="display:flex; justify-content:space-between; font-size:13px; margin-bottom:6px;">
<span style="color:var(--text-3);">الباقة:</span>
<span style="font-weight:700; color:var(--navy);" x-text="paymentData.plan_name"></span> <span style="font-weight:700; color:var(--navy);" x-text="paymentData.plan_name"></span>
</div> </div>
<div style="display:flex; justify-content:space-between; font-size:13px; margin-bottom:6px;">
<div style="display:flex; justify-content:space-between; font-size:14px; border-bottom:1px solid rgba(0,0,0,0.05); padding-bottom:8px;"> <span style="color:var(--text-3);">المبلغ:</span>
<span style="color:var(--text-3);">المبلغ المطلوب:</span> <span style="font-weight:700; color:var(--teal);" x-text="paymentData.amount + ' JOD'"></span>
<span style="font-weight:700; color:var(--teal);" x-text="paymentData.amount + ' دينار أردني'"></span> </div>
<div style="display:flex; justify-content:space-between; font-size:13px; margin-bottom:10px; border-bottom:1px dashed rgba(0,0,0,0.1); padding-bottom:6px;">
<span style="color:var(--text-3);">Reference:</span>
<span style="font-weight:700; color:var(--amber);" x-text="paymentData.reference"></span>
</div> </div>
<div style="display:flex; justify-content:space-between; font-size:14px; border-bottom:1px solid rgba(0,0,0,0.05); padding-bottom:8px;"> <div style="text-align:center;">
<span style="color:var(--text-3);">رقم المرجع (Reference):</span> <p style="margin-bottom:5px; font-size:11px; color:var(--text-2);">التحويل عبر CliQ للحساب:</p>
<span style="font-weight:700; color:var(--amber); font-family:monospace;" x-text="paymentData.reference"></span> <div style="background:white; padding:6px 12px; border:1px solid var(--teal); border-radius:6px; font-family:'Outfit',sans-serif; font-size:17px; font-weight:bold; color:var(--navy); display:inline-block;" x-text="paymentData.cliq_alias"></div>
</div> </div>
<div style="margin-top:8px;"> <div style="margin-top:12px; background:white; padding:10px; border-radius:8px; border:1px solid var(--teal-subtle);">
<p style="margin-bottom:8px; font-size:13px; color:var(--text-2);">يرجى التحويل إلى حساب CliQ التالي:</p> <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:4px;">
<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> <label style="color:var(--navy); font-weight:700; font-size:11px;">رقم المرجع (من البنك)</label>
<span style="background:var(--teal); color:white; font-size:8px; padding:1px 5px; border-radius:4px; font-weight:700;">تفعيل فوري </span>
</div> </div>
<input type="text" x-model="paymentData.bank_reference" class="form-input" placeholder="ألصق رقم المرجع هنا..." style="font-family:'Outfit',sans-serif; font-size:14px; padding:6px; border:1px solid var(--teal); text-align:center;">
<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>
<div class="form-group" style="margin-top:10px;"> <div style="margin-bottom:12px;">
<label class="form-label">صورة وصل التحويل</label> <label style="font-size:12px; font-weight:600; color:var(--text-2); display:block; margin-bottom:4px;">صورة وصل التحويل (اختياري)</label>
<input type="file" @change="selectedFile = $event.target.files[0]" class="form-input" style="padding:8px;" accept="image/*,application/pdf" required> <input type="file" @change="selectedFile = $event.target.files[0]" class="form-input" style="padding:5px; font-size:12px;" accept="image/*,application/pdf">
<p style="font-size:12px; color:var(--text-3); margin-top:6px;">يرجى التأكد من وضوح رقم الحوالة والتاريخ.</p>
</div> </div>
</div>
<div class="modal-divider"></div> <div style="display:flex; gap:8px;">
<div class="modal-footer"> <button @click="showPaymentModal = false" class="btn btn-ghost" style="flex:1; height:40px; font-size:13px;">إلغاء</button>
<button @click="uploadReceipt" class="btn btn-navy" :disabled="isBusy" style="flex:1;"> <button @click="uploadReceipt()" class="btn btn-navy" :disabled="isBusy" style="flex:2; height:40px; font-size:13px;">
<span x-show="!isBusy">📤 إرسال الوصل للتدقيق</span> <span x-show="!isBusy">📤 إرسال الوصل للتفعيل</span>
<span x-show="isBusy"> جاري الإرسال...</span> <span x-show="isBusy"> جاري الإرسال...</span>
</button> </button>
<button type="button" @click="showPaymentModal = false" class="btn btn-ghost">إلغاء</button> </div>
</div> </div>
</div> </div>
</div> </div>