209 lines
7.3 KiB
PHP
209 lines
7.3 KiB
PHP
<?php
|
|
|
|
namespace App\Repositories\Member;
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class EmailAuthRepository
|
|
{
|
|
/**
|
|
* 메일 발송 전 처리:
|
|
* - mem_auth upsert (email, N)
|
|
* - mem_auth_log insert (P)
|
|
* - mem_auth_info upsert (auth_info.email 세팅)
|
|
* return: ['email' => ..., 'auth_key' => ..., 'expires_at' => 'Y-m-d H:i:s']
|
|
*/
|
|
public function prepareEmailVerify(int $memNo, string $email, string $ip, int $expiresMinutes = 30): array
|
|
{
|
|
return DB::transaction(function () use ($memNo, $email, $ip, $expiresMinutes) {
|
|
|
|
// 1) mem_auth: row lock (없으면 생성, 있으면 N으로 초기화)
|
|
$row = DB::table('mem_auth')
|
|
->where('mem_no', $memNo)
|
|
->where('auth_type', 'email')
|
|
->lockForUpdate()
|
|
->first();
|
|
|
|
$today = now()->toDateString();
|
|
|
|
if (!$row) {
|
|
DB::table('mem_auth')->insert([
|
|
'mem_no' => $memNo,
|
|
'auth_type' => 'email',
|
|
'auth_state' => 'N',
|
|
'auth_date' => $today,
|
|
]);
|
|
} else {
|
|
DB::table('mem_auth')
|
|
->where('mem_no', $memNo)
|
|
->where('auth_type', 'email')
|
|
->update([
|
|
'auth_state' => 'N',
|
|
'auth_date' => $today,
|
|
]);
|
|
}
|
|
|
|
// 2) auth_key 생성
|
|
$authKey = now()->format('HisYmd') . $ip . '-' . bin2hex(random_bytes(8));
|
|
$expiresAt = now()->addMinutes($expiresMinutes)->format('Y-m-d H:i:s');
|
|
|
|
$emailInfo = [
|
|
'type' => 'mem_level',
|
|
'auth_hit' => 'n',
|
|
'user_email' => $email,
|
|
'auth_key' => $authKey,
|
|
'auth_effective_time' => $expiresAt,
|
|
'redate' => now()->format('Y-m-d H:i:s'),
|
|
];
|
|
|
|
// 3) mem_auth_log: P (Pending)
|
|
DB::table('mem_auth_log')->insert([
|
|
'mem_no' => $memNo,
|
|
'type' => 'email',
|
|
'state' => 'P',
|
|
'info' => json_encode($emailInfo, JSON_UNESCAPED_UNICODE),
|
|
'rgdate' => now()->format('Y-m-d H:i:s'),
|
|
]);
|
|
|
|
// 4) mem_auth_info upsert (auth_info JSON)
|
|
$authInfoRow = DB::table('mem_auth_info')
|
|
->where('mem_no', $memNo)
|
|
->lockForUpdate()
|
|
->first();
|
|
|
|
if (!$authInfoRow) {
|
|
DB::table('mem_auth_info')->insert([
|
|
'mem_no' => $memNo,
|
|
'auth_info' => json_encode(['email' => $emailInfo], JSON_UNESCAPED_UNICODE),
|
|
]);
|
|
} else {
|
|
$current = json_decode((string)$authInfoRow->auth_info, true) ?: [];
|
|
$current['email'] = $emailInfo;
|
|
|
|
DB::table('mem_auth_info')
|
|
->where('mem_no', $memNo)
|
|
->update([
|
|
'auth_info' => json_encode($current, JSON_UNESCAPED_UNICODE),
|
|
]);
|
|
}
|
|
|
|
return [
|
|
'email' => $email,
|
|
'auth_key' => $authKey,
|
|
'expires_at' => $expiresAt,
|
|
];
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 인증 완료 처리 (CI3 로직 동일):
|
|
* - 이미 Y면 예외
|
|
* - auth_info.email 존재/키/시간 체크
|
|
* - mem_auth: Y 업데이트
|
|
* - mem_auth_info: auth_hit=y + remote/agent/시간 merge
|
|
* - mem_auth_log: S insert
|
|
*/
|
|
public function confirmEmailVerify(int $memNo, string $encKey, string $ip, string $agent): array
|
|
{
|
|
return DB::transaction(function () use ($memNo, $encKey, $ip, $agent) {
|
|
|
|
// 1) mem_auth 상태 확인 (lock)
|
|
$auth = DB::table('mem_auth')
|
|
->where('mem_no', $memNo)
|
|
->where('auth_type', 'email')
|
|
->lockForUpdate()
|
|
->first();
|
|
|
|
if ($auth && $auth->auth_state === 'Y') {
|
|
return ['ok' => false, 'message' => '이미 인증이 완료되었습니다.'];
|
|
}
|
|
|
|
// 2) mem_auth_info 가져오기 (lock)
|
|
$infoRow = DB::table('mem_auth_info')
|
|
->where('mem_no', $memNo)
|
|
->lockForUpdate()
|
|
->first();
|
|
|
|
if (!$infoRow || empty($infoRow->auth_info)) {
|
|
return ['ok' => false, 'message' => '잘못된 접근입니다.'];
|
|
}
|
|
|
|
$authJson = json_decode((string)$infoRow->auth_info, true);
|
|
$emailAuth = $authJson['email'] ?? null;
|
|
|
|
if (!$emailAuth || empty($emailAuth['auth_hit'])) {
|
|
return ['ok' => false, 'message' => '정상적인 경로로 이용하세요.'];
|
|
}
|
|
if (($emailAuth['auth_hit'] ?? '') === 'y') {
|
|
return ['ok' => false, 'message' => '이미 인증되었습니다.'];
|
|
}
|
|
|
|
if (($emailAuth['auth_key'] ?? '') !== $encKey) {
|
|
return ['ok' => false, 'message' => '잘못된 접근입니다.'];
|
|
}
|
|
|
|
$effective = (string)($emailAuth['auth_effective_time'] ?? '');
|
|
if ($effective === '' || $effective < now()->format('Y-m-d H:i:s')) {
|
|
return ['ok' => false, 'message' => '인증시간이 초과되었습니다.'];
|
|
}
|
|
|
|
// 3) auth_hit = y + merge info
|
|
$emailAuth['auth_hit'] = 'y';
|
|
$emailAuth = array_merge($emailAuth, [
|
|
'remote_addr' => $ip,
|
|
'agent' => $agent,
|
|
'auth_redate' => now()->format('Y-m-d H:i:s'),
|
|
]);
|
|
|
|
$authJson['email'] = $emailAuth;
|
|
|
|
// 4) mem_auth: Y 업데이트 (없으면 insert)
|
|
$today = now()->toDateString();
|
|
if (!$auth) {
|
|
DB::table('mem_auth')->insert([
|
|
'mem_no' => $memNo,
|
|
'auth_type' => 'email',
|
|
'auth_state' => 'Y',
|
|
'auth_date' => $today,
|
|
]);
|
|
} else {
|
|
DB::table('mem_auth')
|
|
->where('mem_no', $memNo)
|
|
->where('auth_type', 'email')
|
|
->update([
|
|
'auth_state' => 'Y',
|
|
'auth_date' => $today,
|
|
]);
|
|
}
|
|
|
|
// 5) mem_auth_info 업데이트
|
|
DB::table('mem_auth_info')
|
|
->where('mem_no', $memNo)
|
|
->update([
|
|
'auth_info' => json_encode($authJson, JSON_UNESCAPED_UNICODE),
|
|
]);
|
|
|
|
// 6) mem_auth_log: S (Success)
|
|
$logInfo = [
|
|
'remote_addr' => $ip,
|
|
'agent' => $agent,
|
|
'auth_redate' => now()->format('Y-m-d H:i:s'),
|
|
];
|
|
|
|
DB::table('mem_auth_log')->insert([
|
|
'mem_no' => $memNo,
|
|
'type' => 'email',
|
|
'state' => 'S',
|
|
'info' => json_encode($logInfo, JSON_UNESCAPED_UNICODE),
|
|
'rgdate' => now()->format('Y-m-d H:i:s'),
|
|
]);
|
|
|
|
return [
|
|
'ok' => true,
|
|
'message' => '이메일 인증이 확인되었습니다.',
|
|
'email' => (string)($emailAuth['user_email'] ?? ''),
|
|
];
|
|
});
|
|
}
|
|
}
|