false, 'message' => 'Invalid transaction reference or amount.', ]; } $pdo = Database::getConnection(); // 1. Check if transaction has already been recorded and verified $stmt = $pdo->prepare('SELECT id, status FROM transactions WHERE reference_number = :ref LIMIT 1'); $stmt->execute([':ref' => $refNumber]); $existing = $stmt->fetch(PDO::FETCH_ASSOC); if ($existing && $existing['status'] === 'VERIFIED_AUTO') { return [ 'success' => true, 'message' => 'Transaction already processed and verified previously.', 'transaction_id' => $existing['id'], ]; } // 2. Search for a pending subscription matching this reference or pending payment // First, check if any user submitted this reference number $stmt = $pdo->prepare(' SELECT t.id AS trans_id, t.subscription_id, s.user_id, s.plan_name, u.phone, u.full_name FROM transactions t JOIN subscriptions s ON s.id = t.subscription_id JOIN users u ON u.id = s.user_id WHERE t.reference_number = :ref AND t.status = "SUBMITTED" LIMIT 1 '); $stmt->execute([':ref' => $refNumber]); $matched = $stmt->fetch(PDO::FETCH_ASSOC); if ($matched) { $pdo->beginTransaction(); try { // Update transaction $updTrans = $pdo->prepare(' UPDATE transactions SET status = "VERIFIED_AUTO", amount = :amount, verified_at = NOW(), raw_webhook_payload = :raw WHERE id = :id '); $updTrans->execute([ ':amount' => $amount, ':raw' => json_encode($data, JSON_UNESCAPED_UNICODE), ':id' => $matched['trans_id'], ]); // Activate subscription $updSub = $pdo->prepare(' UPDATE subscriptions SET status = "ACTIVE", starts_at = CURDATE(), expires_at = DATE_ADD(CURDATE(), INTERVAL 2 YEAR) WHERE id = :sub_id '); $updSub->execute([':sub_id' => $matched['subscription_id']]); // Ensure user status is active $updUser = $pdo->prepare('UPDATE users SET status = "ACTIVE" WHERE id = :user_id'); $updUser->execute([':user_id' => $matched['user_id']]); $pdo->commit(); return [ 'success' => true, 'matched' => true, 'message' => 'Subscription activated automatically for ' . $matched['full_name'], 'user_id' => $matched['user_id'], 'phone' => $matched['phone'], ]; } catch (\Throwable $e) { $pdo->rollBack(); return ['success' => false, 'error' => $e->getMessage()]; } } // If no user has claimed it yet, record it in transactions as unassigned credit $insStmt = $pdo->prepare(' INSERT INTO transactions (subscription_id, user_id, method, reference_number, sender_account_or_phone, recipient_account, amount, currency, status, raw_webhook_payload, verified_at) VALUES (0, 0, "SUPER_QI", :ref, :sender, :recipient, :amount, "IQD", "VERIFIED_AUTO", :raw, NOW()) ON DUPLICATE KEY UPDATE amount = VALUES(amount), raw_webhook_payload = VALUES(raw_webhook_payload) '); $insStmt->execute([ ':ref' => $refNumber, ':sender' => $sender, ':recipient' => $recipient, ':amount' => $amount, ':raw' => json_encode($data, JSON_UNESCAPED_UNICODE), ]); return [ 'success' => true, 'matched' => false, 'message' => 'Transaction recorded. Awaiting user claim in app.', 'reference_number' => $refNumber, ]; } }