Initial commit: Uruk Prize Platform architecture, backend core, mobile app, gateway caller & deployment pipeline
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
<?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,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user