Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

쟝이의 세상

**Project** Part2. DB수정 및 웹사이트 코딩 수정 본문

프로젝트

**Project** Part2. DB수정 및 웹사이트 코딩 수정

zyangee 2024. 10. 7. 15:41

💡 DB 변경사항

✔️ users 테이블

CREATE TABLE users ( /* 회원 테이블 */
    user_num INT AUTO_INCREMENT PRIMARY KEY,
    userid VARCHAR(20) NOT NULL UNIQUE,
    username VARCHAR(50) NOT NULL,
    password VARCHAR(255) NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE,
    phone_number VARCHAR(20) NOT NULL UNIQUE,
    /* date_of_birth CHAR(6) NOT NULL, */
    date_of_birth CHAR(14) NOT NULL,
    account_created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    last_login TIMESTAMP NULL
);
👉 date_of_birth CHAR(6) → CHAR(14) 로 변경
주민번호 -(하이픈) 포함 14자리로 입력될 수 있게 변경하였다

 

✔️ accounts 테이블

CREATE TABLE accounts ( /* 계좌 테이블 */
    account_id INT AUTO_INCREMENT PRIMARY KEY,
    user_num INT NOT NULL,
    account_number VARCHAR(20) NOT NULL UNIQUE,
    balance BIGINT NOT NULL DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
++    account_password VARCHAR(255) NOT NULL,
    FOREIGN KEY (user_num) REFERENCES users(user_num)
);
👉 account_password VARCHAR(255) NOT NULL
계좌 비밀번호 컬럼을 추가.
계좌 비밀번호의 경우 보안 적용 시에 해시값으로 저장될 수 있도록 VARCHAR(255)로 설정하였다.

 

 

💡 php 파일 변경사항

✔️ dbconn.php

if (($current_file != '#' && $current_file != '#') && !isset($_SESSION['userid'])) {
    echo "<script>alert('로그인이 필요합니다');</script>";
    echo "<script>location.href='#';</script>"; //로그인 후 이동할 페이지
    exit;
}

회원가입 페이지에서 중복체크 버튼 클릭 시 오류 발생

오류 내용: JSON으로 읽어오지 못하는 오류

echo의 script 태그에서 오류가 나는 것으로 추정하고 해당 코드를 주석처리하니 정상적으로 돌아가는 것을 확인

수정할 수 있었지만, 우선 주석처리하는 것으로 결정

 

✔️ 모든 파일 추가 내용

<div class="navbar">
        <span>00은행</span>
        <ul>
            <li><a href="index.php">홈</a></li>
            <li>|</li>
            <?php
            include "dbconn.php";
            if (isset($_SESSION['username'])): ?>
                <li><a href="users.php"><?php echo $_SESSION['username']; ?></a>님</li>
                <li>|</li>
                <li><a href="logout.php">로그아웃</a></li>
            <?php else: ?>
                <li><a href="login.php">로그인</a></li>
            <?php endif; ?>
        </ul>
</div>

로그인 한 사용자의 경우 "홈 | OOO님 | 로그아웃" 

로그인 하지 않은 사용자의 경우 "홈 | 로그인" 으로 뜰 수 있도록 상단바 설정

로그인 한 사용자와 하지 않은 사용자의 구분은 저장된 세션 값으로 받아와 처리해준다.

 

✔️ 계좌생성 페이지 추가 (account_add.php)

account_add.php
0.01MB

<?php
include "dbconn.php";
include "api/random_account.php";
?>

<!DOCTYPE html>
<html>

<head>
    <script src="javascript/accountAdd.js"></script>
    <link rel="stylesheet" href="css/back.css">
    <link rel="stylesheet" href="css/input.css">
    <link rel="stylesheet" href="css/input_account.css">
</head>

<body>
    <div class="navbar">
        <span>00은행</span>
        <ul>
            <li><a href="index.php">홈</a></li>
            <li>|</li>
            <?php
            include "dbconn.php";
            if (isset($_SESSION['username'])): ?>
                <li><a href="users.php"><?php echo $_SESSION['username']; ?></a>님</li>
                <li>|</li>
                <li><a href="logout.php">로그아웃</a></li>
            <?php else: ?>
                <li><a href="login.php">로그인</a></li>
            <?php endif; ?>
        </ul>
    </div>
    <div class="container">
        <h2 class="h2_pageinfo">계좌 생성</h2>
        <form class="form_css" action="" onsubmit="submitForm(event)" method="POST">
            <div id="section">
                <div>
                    <label class="input">이름</label> <!--DB에 있는 이름 그대로 가져오기-->
                    <input class="input_text" type="text" id="username" name="username"
                        value="<?php echo $_SESSION['username'] ?>" readonly>
                </div>

                <label class="input">주민번호</label>
                <div class="align-right-input">
                    <input type="text" id="resident-number1" name="resident-number1"
                        value="<?php echo ($resident_number1) ?>">
                    <span>-</span>
                    <input type="text" id="resident-number2" name="resident-number2" maxlength="7"
                        value="<?php echo !empty($resident_number2) ? htmlspecialchars($resident_number2) : ''; ?>"
                        <?php echo !empty($resident_number2) ? 'readonly' : ''; ?> required>
                    <div id="resident-error" class="error"></div><!--주민번호 에러메시지-->
                </div>
                <div>
                    <label class="input">초기 금액</label>
                    <input class="input_text" type="number" id="balance" name="balance" required>
                    <div id="balance-error" class="error"></div><!--초기금액 에러메시지-->
                </div>
                <div class="auth_num"><!--인증번호-->
                    <label class="input">인증번호</label>
                    <div id="memo">인증번호 발급받은 후 인증하기 버튼을 눌러야 계좌 생성이 가능합니다</div>
                    <input class="input_text next_button" type="text" id="auth-code" name="auth-code" maxlength="6">
                    <button class="input_button" type="button" onclick="addAuthCode()">인증번호 발급</button>

                    <div id="authentication" style="display:none;"> <!--발급 버튼을 눌러야 보임-->
                        <div id="authentication-code"></div><!--인증번호 보이는 부분-->
                        <button type="button" onclick="validAuthCode()">인증하기</button>
                    </div>
                    <div id="auth-error"></div>
                </div>

                <div> <!--숫자만 입력되게, 자리수는 4자리-->
                    <label class="input">통장 비밀번호</label>
                    <input class="input_text" type="password" id="account-password" name="account-password"
                        maxlength="4" required>
                    <div id="password-error" class="error"></div><!--통장 비밀번호 에러메시지-->
                </div>
                <div><!--계좌 사용용도-->
                    <label class="input">계좌 사용용도</label>
                    <select id="purpose" class="select" required>
                        <option>선택해주세요.</option>
                        <option>급여 및 아르바이트</option>
                        <option>생활비 관리</option>
                        <option>적금 자동이체</option>
                        <option>예금 가입</option>
                        <option>대출신청</option>
                    </select>
                    <div id="select-error" class="error"></div><!--select 옵션 선택 에러메시지-->
                </div>
                <div><!--체크 옵션-->
                    <div class="radio_check"> <!--체크옵션 1-->
                        <label class="input">타인으로부터 통장대여 요청을 받은 사실이 있나요?</label>
                        <div>
                            <input type="radio" name="check1" value="예">예
                            <input type="radio" name="check1" value="아니오">아니오
                        </div>
                    </div>
                    <div class="radio_check"> <!--체크옵션 2-->
                        <label class="input">타인으로부터 통장개설을 요청받은 사실이 있나요?</label>
                        <div>
                            <input type="radio" name="check2" value="예">예
                            <input type="radio" name="check2" value="아니오">아니오
                        </div>
                    </div>
                    <div id="check-error" class="error"></div><!--check 옵션 선택 에러메시지-->
                </div><!--체크 옵션 div-->
            </div>
            <input class="submit_button" type="submit" id="create-account" value="계좌 생성" disabled>
        </form>
    </div>
</body>

</html>

 

사용한 javascript

(accountAdd.js)

→ 계좌생성 페이지에서 사용하는 모든 함수

accountAdd.js
0.00MB

더보기
let add_auth_code = "";
//인증번호 생성 함수
function addAuthCode() {
  const chars =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  const authentication_code = document.getElementById("authentication-code");
  let auth_code = "";
  for (let i = 0; i < 6; i++) {
    auth_code += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  add_auth_code = auth_code; //생성된 인증번호 저장
  document.getElementById("authentication").style.display = "block";
  authentication_code.textContent =
    "인증번호가 발급되었습니다: " + add_auth_code;

  document.getElementById("memo").style.display = "none";
}

//인증번호 검증 함수
function validAuthCode() {
  const auth_code = document.getElementById("auth-code").value;
  const error = document.getElementById("auth-error");

  //인증번호가 입력되지 않았을 경우
  if (auth_code === "") {
    error.textContent = "인증번호를 입력해주세요.";
    error.style.color = "red";
    return false;
  }
  //인증번호가 맞지 않을 경우
  if (auth_code === add_auth_code) {
    error.textContent = "인증이 완료되었습니다.";
    error.style.color = "green";
    document.getElementById("create-account").disabled = false;
    return true;
  } else {
    error.textContent = "인증번호가 올바르지 않습니다. 다시 시도해주세요.";
    error.style.color = "red";
    addAuthCode();
    return false;
  }
}

//주민번호 뒷자리 7자리 숫자만
function validResident() {
  const resident_number2 = document.getElementById("resident-number2");
  const error = document.getElementById("resident-error");

  //readonly 속성일 경우
  if (resident_number2.hasAttribute("readonly")) {
    error.textContent = "";
    return true;
  }
  const resident_value = resident_number2.value;
  const resident = /^\d{7}$/;

  if (!resident.test(resident_value)) {
    error.textContent = "7자리 숫자로 입력해주세요.";
    return false;
  } else {
    error.textContent = "";
    return true;
  }
}

//초기금액 0원 이상
function validBalance() {
  const balance = document.getElementById("balance").value;
  const error = document.getElementById("balance-error");

  if (isNaN(balance) || balance < 0) {
    error.textContent = "0원 이상 입력해주세요.";
    return false;
  } else {
    error.textContent = "";
    return true;
  }
}

//통장비밀번호 숫자 4자리만 허용
function validPassword() {
  const account_password = document.getElementById("account-password").value;
  const error = document.getElementById("password-error");
  const password_check = /^\d{4}$/;
  if (!password_check.test(account_password)) {
    error.textContent = "4자리 숫자로 입력해주세요.";
    return false;
  } else {
    error.textContent = "";
    return true;
  }
}

//select 옵션 검증
function validSelect() {
  const select = document.getElementById("purpose").value;
  const error = document.getElementById("select-error");
  if (select === "선택해주세요.") {
    error.textContent = "계좌 사용 용도를 선택해주세요.";
    return false;
  } else {
    error.textContent = "";
    return true;
  }
}

//체크 옵션 검증
function validCheck() {
  const check1 = document.querySelector('input[name="check1"]:checked');
  const check2 = document.querySelector('input[name="check2"]:checked');
  const error = document.getElementById("check-error");
  if (!check1 || !check2) {
    error.textContent = "모두 체크 바랍니다.";
    return false;
  }
  if (check1.value === "예" || check2.value === "예") {
    error.textContent = "한번 더 확인 부탁드립니다.";
    return false;
  }
  error.textContent = "";
  return true;
}

function submitForm(event) {
  event.preventDefault();
  const isValidResident = validResident(
    document.getElementById("resident-number2")
  );
  const isValidAuthCode = validAuthCode();
  const isValidBalance = validBalance();
  const isValidPassword = validPassword();
  const isValidSelect = validSelect();
  const isValidCheck = validCheck();

  if (
    isValidAuthCode &&
    isValidResident &&
    isValidBalance &&
    isValidPassword &&
    isValidSelect &&
    isValidCheck
  ) {
    alert("계좌 생성이 완료되었습니다.");
    event.target.submit();
  } else {
    alert("모든 필수 항목을 올바르게 입력해주세요.");
  }
}

사용한 API

(random_account.php)

→ 계좌 생성 시 랜덤한 수로 계좌를 생성. **중복되지 않도록**

random_account.php
0.00MB

더보기
<?php
function randomAccountNumber($conn)
{
    $max = 1000;
    $tryagain = 0;
    do {
        $random_part1 = str_pad(rand(0, 999), 3, '0', STR_PAD_LEFT);
        $random_part2 = str_pad(rand(0, 9999), 4, '0', STR_PAD_LEFT);
        $account_number = "{$random_part1}-{$random_part2}";

        //DB에서 중복 확인
        $query = "SELECT count(*) FROM accounts WHERE account_number = :account_number";
        $stmt_random = $conn->prepare($query);
        $stmt_random->bindParam(":account_number", $account_number);
        $stmt_random->execute();
        $count = $stmt_random->fetchColumn(); //행의 개수 가져오기(account_number가 같은게 있는지 확인 작업)
        $tryagain++;
        if ($tryagain >= $max) {
            throw new Exception("계좌 생성번호 실패");
        }
    } while ($count > 0);
    return $account_number;
}

$user_num = $_SESSION['user_num'];

$sql = "SELECT * FROM users WHERE user_num = :user_num";
$stmt = $conn->prepare($sql);
$stmt->bindParam(":user_num", $user_num);
$stmt->execute();

$row = $stmt->fetch(PDO::FETCH_ASSOC);
$resident_num = $row['date_of_birth'];

//주민번호가 6자리 일 때와 아닐 때의 if-else문
if (strpos($resident_num, '-') !== false) {
    $resident_number1 = substr($resident_num, 0, 6);
    $resident_number2 = substr($resident_num, strpos($resident_num, '-') + 1);
} else {
    $resident_number1 = $resident_num;
    $resident_number2 = '';
}

if ($row > 0) {
    if ($_SERVER['REQUEST_METHOD'] === 'POST' && $resident_num) {
        //post요청 들어오는 값 저장
        $resident_number1 = $_POST['resident-number1'];
        $resident_number2 = $_POST['resident-number2'];
        $full_resident_number = $resident_number1 . '-' . $resident_number2;
        $balance = $_POST['balance'];
        $account_password = $_POST['account-password'];

        //account_number 랜덤지정
        $account_number = randomAccountNumber($conn);

        //값 insert
        $sql_insert = 'INSERT INTO accounts(user_num, account_number, balance, created_at, account_password)
        VALUES(:user_num, :account_number, :balance, NOW(), :account_password)';

        //bind parameter 사용
        $stmt_insert = $conn->prepare($sql_insert);
        $stmt_insert->bindParam(':user_num', $user_num);
        $stmt_insert->bindParam(':account_number', $account_number);
        $stmt_insert->bindParam(":balance", $balance);
        $stmt_insert->bindParam(":account_password", $account_password);

        //입력된 값이 있을 경우
        if ($stmt_insert->execute() === TRUE) {
            $sql_update = 'UPDATE users SET date_of_birth = :resident_number WHERE user_num = :user_num';
            $stmt_update = $conn->prepare($sql_update);
            $stmt_update->bindParam(':resident_number', $full_resident_number);
            $stmt_update->bindParam(':user_num', $user_num);
            if ($stmt_update->execute() === TRUE) {
                echo "<script>alert('계좌가 생성되었습니다.');</script>";
                echo "<script>location.href = '../users.php';</script>";
                exit;
            } else {
                echo "주민번호 업데이트 실패: " . implode(", ", $stmt_update->errorInfo()) . "";
            }
        } else {
            echo "계좌생성 실패: " . implode(", ", $stmt_insert->errorInfo());
        }
    } else {
        echo "<script>console.log('POST로 넘어온 값이 없음');</script>";
    }
} else {
    echo "<script>console.log('회원 정보가 조회되지 않았습니다.');</script>";
}
?>