Files
urukprize/backend/app/Services/SuperQiParserService.php
T

123 lines
4.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Services;
use Core\Database;
use PDO;
class SuperQiParserService
{
/**
* Ingests and processes a notification or parsed receipt from the Android listener bridge.
*/
public static function processIngestedNotification(array $data): array
{
$refNumber = trim((string)($data['reference_number'] ?? ''));
$amount = (float)($data['amount'] ?? 0);
$sender = trim((string)($data['sender'] ?? ''));
$recipient = trim((string)($data['recipient'] ?? ''));
$rawText = (string)($data['raw_text'] ?? '');
if (empty($refNumber) || $amount <= 0) {
return [
'success' => 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,
];
}
}