giftcon_dev/app/Repositories/Member/MemberAuthRepository.php
2026-01-19 14:45:08 +09:00

258 lines
8.2 KiB
PHP

<?php
namespace App\Repositories\Member;
use App\Models\Member\MemAuth;
use App\Models\Member\MemAuthInfo;
use App\Models\Member\MemAuthLog;
use App\Models\Member\MemInfo;
use App\Models\Member\MemJoinFilter;
use App\Models\Member\MemJoinLog;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Carbon;
class MemberAuthRepository
{
/* =========================================================
* mem_auth (기존)
* ========================================================= */
public function upsertState(
int $memNo,
string $authType,
string $authState,
?string $authDate = null
): void {
$authDate = $authDate ?: Carbon::now()->toDateString();
DB::table('mem_auth')->updateOrInsert(
['mem_no' => $memNo, 'auth_type' => $authType],
['auth_state' => $authState, 'auth_date' => $authDate]
);
}
public function markRequested(int $memNo, string $authType, array $logInfo = []): void
{
$this->setStateWithLog($memNo, $authType, MemAuth::STATE_R, MemAuthLog::STATE_P, $logInfo);
}
public function markProcessing(int $memNo, string $authType, array $logInfo = []): void
{
$this->setStateWithLog($memNo, $authType, MemAuth::STATE_P, MemAuthLog::STATE_P, $logInfo);
}
public function markSuccess(int $memNo, string $authType, array $logInfo = []): void
{
$this->setStateWithLog($memNo, $authType, MemAuth::STATE_Y, MemAuthLog::STATE_S, $logInfo);
}
public function markFail(int $memNo, string $authType, array $logInfo = []): void
{
$this->setStateWithLog($memNo, $authType, MemAuth::STATE_N, MemAuthLog::STATE_F, $logInfo);
}
public function mergeAuthInfo(int $memNo, string $authType, array $payload): void
{
DB::transaction(function () use ($memNo, $authType, $payload) {
$row = MemAuthInfo::query()->find($memNo);
if (!$row) {
$row = new MemAuthInfo();
$row->mem_no = $memNo;
$row->auth_info = [];
}
$data = $row->auth_info ?: [];
$data[$authType] = array_merge($data[$authType] ?? [], $payload);
$row->auth_info = $data;
$row->save();
});
}
private function setStateWithLog(
int $memNo,
string $authType,
string $authState,
string $logState,
array $logInfo
): void {
DB::transaction(function () use ($memNo, $authType, $authState, $logState, $logInfo) {
$this->upsertState($memNo, $authType, $authState);
MemAuthLog::query()->create([
'mem_no' => $memNo,
'type' => $authType,
'state' => $logState,
'info' => $logInfo,
'rgdate' => Carbon::now()->toDateTimeString(),
]);
});
}
public function getState(int $memNo, string $authType): ?string
{
return DB::table('mem_auth')
->where('mem_no', $memNo)
->where('auth_type', $authType)
->value('auth_state');
}
public function isVerified(int $memNo, string $authType): bool
{
return $this->getState($memNo, $authType) === MemAuth::STATE_Y;
}
/* =========================================================
* Step0: phone check + join_filter + join_log
* ========================================================= */
public function normalizeKoreanPhone(string $raw): ?string
{
$digits = preg_replace('/\D+/', '', $raw ?? '');
if (!$digits) return null;
// 82 국제형 → 0 시작으로 변환
if (str_starts_with($digits, '82')) {
$digits = '0' . substr($digits, 2);
}
// 010/011/016/017/018/019 + 10~11자리
if (!preg_match('/^01[016789]\d{7,8}$/', $digits)) {
return null;
}
return $digits;
}
public function ipToCClass(string $ip): string
{
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
return '';
}
$p = explode('.', $ip);
return count($p) === 4 ? ($p[0] . '.' . $p[1] . '.' . $p[2] . '.0') : '';
}
public function isAlreadyMemberByPhone(string $phone): bool
{
return MemInfo::query()
->where('cell_phone', $phone)
->where('dt_out', '0000-00-00 00:00:00')
->exists();
}
/**
* filter 컬럼에 phone/ip/ip_c가 들어있다는 전제의 기본 구현.
* - join_block: A 차단 / S 주의(알림) / N 비활성
*/
public function checkJoinFilter(string $phone, string $ip4 = '', string $ip4c = ''): ?array
{
$targets = array_values(array_filter([$phone, $ip4, $ip4c]));
if (!$targets) return null;
$rows = MemJoinFilter::query()
->whereIn('filter', $targets)
->where(function ($q) {
$q->whereNull('join_block')->orWhere('join_block', '!=', 'N');
})
->orderByDesc('seq')
->get();
if ($rows->isEmpty()) return null;
foreach ($rows as $r) {
if ((string)$r->join_block === 'A') {
return ['hit' => true, 'block' => true, 'gubun' => $r->gubun ?? 'filter_block', 'row' => $r];
}
}
foreach ($rows as $r) {
if ((string)$r->join_block === 'S') {
return ['hit' => true, 'block' => false, 'gubun' => $r->gubun ?? 'filter_notice', 'row' => $r];
}
}
$r = $rows->first();
return ['hit' => true, 'block' => false, 'gubun' => $r->gubun ?? 'filter_hit', 'row' => $r];
}
public function writeJoinLog(array $data): void
{
MemJoinLog::query()->create([
'gubun' => $data['gubun'] ?? null,
'mem_no' => (int)($data['mem_no'] ?? 0),
'cell_corp' => $data['cell_corp'] ?? 'n',
'cell_phone' => $data['cell_phone'] ?? '',
'email' => $data['email'] ?? null,
'ip4' => $data['ip4'] ?? '',
'ip4_c' => $data['ip4_c'] ?? '',
'error_code' => $data['error_code'] ?? '',
'dt_reg' => Carbon::now()->toDateTimeString(),
]);
}
/**
* Step0 통합 처리
*/
public function step0PhoneCheck(string $rawPhone, string $ip4 = ''): array
{
$phone = $this->normalizeKoreanPhone($rawPhone);
if (!$phone) {
return [
'ok' => false,
'reason' => 'invalid_phone',
'message' => '휴대폰 번호 형식이 올바르지 않습니다.',
];
}
$ip4c = $this->ipToCClass($ip4);
// already member
if ($this->isAlreadyMemberByPhone($phone)) {
$this->writeJoinLog([
'gubun' => 'already_member',
'mem_no' => 0,
'cell_phone' => $phone,
'ip4' => $ip4,
'ip4_c' => $ip4c,
'error_code' => 'J2',
]);
return ['ok' => true, 'reason' => 'already_member', 'phone' => $phone];
}
// join filter
$filter = $this->checkJoinFilter($phone, $ip4, $ip4c);
if ($filter && ($filter['block'] ?? false) === true) {
$this->writeJoinLog([
'gubun' => $filter['gubun'] ?? 'filter_block',
'mem_no' => 0,
'cell_phone' => $phone,
'ip4' => $ip4,
'ip4_c' => $ip4c,
'error_code' => 'J1',
]);
return [
'ok' => false,
'reason' => 'blocked',
'phone' => $phone,
'filter' => $filter,
'message' => '현재 가입이 제한된 정보입니다. 고객센터로 문의해 주세요.',
];
}
// pass
$this->writeJoinLog([
'gubun' => $filter['gubun'] ?? 'ok',
'mem_no' => 0,
'cell_phone' => $phone,
'ip4' => $ip4,
'ip4_c' => $ip4c,
'error_code' => 'J0',
]);
return ['ok' => true, 'reason' => 'ok', 'phone' => $phone, 'filter' => $filter];
}
}