giftcon_dev/app/Repositories/Member/EmailAuthRepository.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'] ?? ''),
];
});
}
}