payfrit-api/api/auth/verifyOTP.php
John Mizerek 1f81d98c52 Initial PHP API migration from CFML
Complete port of all 163 API endpoints from Lucee/CFML to PHP 8.3.
Shared helpers in api/helpers.php (DB, auth, request/response, security).
PDO prepared statements throughout. Same JSON response shapes as CFML.
2026-03-14 14:26:59 -07:00

60 lines
1.8 KiB
PHP

<?php
require_once __DIR__ . '/../helpers.php';
runAuth();
/*
Unified OTP Verify: Works for both login and signup
POST: { "uuid": "...", "otp": "123456" }
Returns: { OK: true, UserID: 123, Token: "...", NeedsProfile: true/false }
*/
$data = readJsonBody();
$userUUID = trim($data['uuid'] ?? '');
$otp = trim($data['otp'] ?? '');
if (empty($userUUID) || empty($otp)) {
apiAbort(['OK' => false, 'ERROR' => 'missing_fields', 'MESSAGE' => 'UUID and OTP are required']);
}
$user = queryOne(
"SELECT ID, FirstName, LastName, EmailAddress, IsContactVerified, IsEmailVerified, IsActive, MobileVerifyCode
FROM Users
WHERE UUID = ?
LIMIT 1",
[$userUUID]
);
if (!$user) {
apiAbort(['OK' => false, 'ERROR' => 'expired', 'MESSAGE' => 'Verification expired. Please request a new code.']);
}
// Check OTP (no magic OTP in PHP port — use DEV_OTP from send endpoint for dev testing)
if ((string) $user['MobileVerifyCode'] !== (string) $otp) {
apiAbort(['OK' => false, 'ERROR' => 'invalid_otp', 'MESSAGE' => 'Invalid verification code. Please try again.']);
}
$needsProfile = empty(trim($user['FirstName'] ?? ''));
if ($needsProfile) {
queryTimed("UPDATE Users SET MobileVerifyCode = '' WHERE ID = ?", [$user['ID']]);
} else {
queryTimed(
"UPDATE Users SET MobileVerifyCode = '', IsContactVerified = 1, IsActive = 1 WHERE ID = ?",
[$user['ID']]
);
}
$token = generateSecureToken();
queryTimed(
"INSERT INTO UserTokens (UserID, Token) VALUES (?, ?)",
[$user['ID'], $token]
);
jsonResponse([
'OK' => true,
'UserID' => (int) $user['ID'],
'Token' => $token,
'NeedsProfile' => $needsProfile,
'FirstName' => $user['FirstName'] ?? '',
'IsEmailVerified' => ((int) ($user['IsEmailVerified'] ?? 0)) === 1,
]);