지난번 팝업을 이용한 카카오로그인에 대해 간단한게 살펴보았다. 

이번에는 REST API 를 이용한 카카오로그인에 대해 알아보도록 하자 

 

기본적으로 REST API 를 이용하기 위해선 PHP 스크립트를 실행할 수 있는 서버가 있어야하며

해당 서버가 준비가 안되었다면 이번 샘플을 실행할 수 없다. CURL 통신의 경우 LIB 파일로 제공하니

해당 파일을 참고하여 실 운영서버 개발 시 수정하여 사용하면 된다. 

 

참고로 소스이외 샘플 파일로 다운로드할 경우 아래의 샘플파일을 먼저 다운로드 해보면된다. 

 

 

샘플파일 다운로드 - ZIP

 

라이브러리 파일(lib.php)
<?php 
/*
	@ 카카오 로그인 REST API 샘플
	© 2022 REDINFO <webmaster@redinfo.co.kr>
*/
session_start();
class kakaoRestAPI{


	// <수정필요> REST API 키값 : kakao developers > 내 애플리케이션 > 요약정보 > 앱 키 > REST API 키\
	var $restapi_key = ''; 

	// <수정필요> 리다렉트 URL : kakao developers > 내 애플리케이션 > 제품설정 > 카카오 로그인 > Redirect URI 
	var $redirect_uri = '';

	// <수정필요> 카카오 로그인 인증 후 이동할 페이지
	var $result_uri = '';

	// api 사용가능 여부
	var $auth_apply = false;

	// 디버깅시 결과 볼지 여부 (true or false)
	var $debug_view = true;

	// 디버깅시 결과 테스트 (true or false)
	var $debug_txt = '';

	// 요청 URL 정의
	var $request_url = array(
		'code'=>'https://kauth.kakao.com/oauth/authorize?response_type=code&client_id={REST_API_KEY}&redirect_uri={REDIRECT_URI}', // get
		'token'=>'https://kauth.kakao.com/oauth/token', // 토큰 받기 // (only post)
		'userInfo'=>'https://kapi.kakao.com/v2/user/me', // 사용자 정보 가져오기(get or post)
		'logout'=>'https://kapi.kakao.com/v1/user/logout', // 사용자 로그아웃 가져오기(only post)
	);


	/*생성자*/
	function __construct(){
		if( empty($this->restapi_key)){ return $this->debug('restapi_key 키값 누락',__LINE__); }
		if( empty($this->redirect_uri)){ return $this->debug('redirect_uri 값 누락',__LINE__); }

		// request code url 치환자 정의
		$this->request_url['code'] = str_replace(array('{REST_API_KEY}','{REDIRECT_URI}'),array($this->restapi_key,urlencode($this->redirect_uri)),$this->request_url['code']);

		// api 사용가능 여부
		$this->auth_apply = true;

	}

	/*token요청*/
	function getToken($code){
		// code 는 header 로 요청되기때문에 반드시 출력 전에 실행 
		if($this->auth_apply !== true){ return $this->debug("카카오 로그인 API를 호출할 수 없습니다.",__LINE__); }
		if(empty($code)){ return $this->debug("인가코드가 누락되었습니다.",__LINE__); }

		// URL에서 데이터를 추출하여 쿼리문 생성
		$postfields = array('grant_type'=>'authorization_code','client_id'=>$this->restapi_key,'redirect_uri'=>$this->redirect_uri,'code'=>$code);
		$url = $this->request_url['token']."?".http_build_query($postfields);
		$ch = curl_init(); 
		curl_setopt($ch, CURLOPT_URL, $url); 
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); 
		curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); 
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
		curl_setopt($ch, CURLOPT_POST, 1); 
		curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields); 
		$data = curl_exec($ch);
		if (curl_error($ch)){ return $this->debug('통신에러 ('.curl_errno( $ch ).') '.curl_error($ch),__LINE__);} 
		curl_close($ch); 
		return $data;
	}	


	/*사용자정보호출*/
	function getUserInfo($access_token){

		// code 는 header 로 요청되기때문에 반드시 출력 전에 실행 
		if($this->auth_apply !== true){ return $this->debug("카카오 로그인 API를 호출할 수 없습니다.",__LINE__); }
		if(empty($access_token)){ return $this->debug("인증코드가 누락되었습니다.",__LINE__); }

		// URL에서 데이터를 추출하여 쿼리문 생성
		$url = $this->request_url['userInfo'];
		$headers = array("Authorization: Bearer ".$access_token);
		$ch = curl_init(); 
		curl_setopt($ch, CURLOPT_URL, $url); 
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); 
		curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); 
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
		curl_setopt($ch, CURLOPT_POST, 1); 
		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 
		curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields); 
		$data = curl_exec($ch);
		if (curl_error($ch)){ return $this->debug('통신에러 ('.curl_errno( $ch ).') '.curl_error($ch),__LINE__);} 
		curl_close($ch); 
		return $data;		
	}

	/*로그아웃*/
	function getLogout($access_token){

		// code 는 header 로 요청되기때문에 반드시 출력 전에 실행 
		if($this->auth_apply !== true){ return $this->debug("카카오 로그인 API를 호출할 수 없습니다.",__LINE__); }
		if(empty($access_token)){ return $this->debug("인증코드가 누락되었습니다.",__LINE__); }

		// URL에서 데이터를 추출하여 쿼리문 생성
		$url = $this->request_url['logout'];
		$headers = array("Authorization: Bearer ".$access_token);
		$ch = curl_init(); 
		curl_setopt($ch, CURLOPT_URL, $url); 
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); 
		curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); 
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
		curl_setopt($ch, CURLOPT_POST, 1); 
		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 
		curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields); 
		$data = curl_exec($ch);
		if (curl_error($ch)){ return $this->debug('통신에러 ('.curl_errno( $ch ).') '.curl_error($ch),__LINE__);} 
		curl_close($ch); 
		return $data;		
	}


	/*디버깅*/
	function debug($msg,$code){
		ob_start();
		echo "[".$code."] ".$msg;
		$this->debug_txt = ob_get_clean();
		if( $this->debug_view === true){ echo $this->debug_txt; }
		return false;
	}
}

 

로그인 샘플 페이지(login.php)
<?php 
	include_once dirname(__FILE__)."/lib.php";
	$kakaologin = new kakaoRestAPI();
	if( $kakaologin->auth_apply !== true){ die("카카오로그인을 사용할 수 없습니다."); }

	$arrUserInfo = array('id'=>'','nickname'=>'','email'=>'','gender'=>'');
	if(!empty($_SESSION['auth_kakao_user_info'])){
		if( !empty($_SESSION['kakao_user_info']['id'])){ $arrUserInfo['id']= $_SESSION['kakao_user_info']['id'];  }
		if( !empty($_SESSION['kakao_user_info']['kakao_account']['profile']['nickname'])){ $arrUserInfo['nickname']= $_SESSION['kakao_user_info']['kakao_account']['profile']['nickname'];  }
		if( !empty($_SESSION['kakao_user_info']['kakao_account']['email'])){ $arrUserInfo['email']= $_SESSION['kakao_user_info']['kakao_account']['email']; }
		if( !empty($_SESSION['kakao_user_info']['kakao_account']['gender'])){ $arrUserInfo['gender']= $_SESSION['kakao_user_info']['kakao_account']['gender']; }
	}

?>
<div class="wrap-kakao-login">
	<h1>카카오톡 API를 이용한 로그인 샘플(REST API)</h1>
	<ul>
		<li><a href="/kakao-login.php">처음화면으로</a></li>
		<li><a href="<?php echo $kakaologin->redirect_uri; ?>?logout=true">로그아웃</a></li>
		<li><a href="<?php echo $kakaologin->request_url['code'] ?>"  class="kakao-login"><img src="//k.kakaocdn.net/14/dn/btroDszwNrM/I6efHub1SN5KCJqLm1Ovx1/o.jpg" width="180" alt="카카오 로그인 버튼"/></a></li>
	</ul>
	<h3>인증상태</h3>
	<ul>
		<li>토큰인증: <?php echo !empty($_SESSION['auth_kakao_token_info']) ? '<font color="blue">인증완료</font>':'<font color="red">인증대기</font>'; ?></li>
		<li>사용자인증: <?php echo !empty($_SESSION['auth_kakao_user_info']) ? '<font color="blue">인증완료</font>':'<font color="red">인증대기</font>'; ?></li>
	</ul>
	<h3>인증후 사용자 정보(아이디(고유번호),이메일,닉네임,성별)</h3>
	<ul>
		<li>아이디(고유번호): <input type="text" name="id" value="<?php echo $arrUserInfo['id'] ?>"></li>
		<li>닉네임: <input type="text" name="nickname" value="<?php echo $arrUserInfo['nickname'] ?>"></li>
		<li>이메일: <input type="text" name="email" value="<?php echo $arrUserInfo['email'] ?>"></li>
		<li>성별: <input type="text" name="gender" value="<?php echo $arrUserInfo['gender'] ?>"></li>
	</ul>
</div>
<style>
	.wrap-kakao-login{ padding:2%; }
	.wrap-kakao-login li{ margin:10px 0; }
</style>

 

 

콜백(Redirect URI) 파일 - callbak.php
<?php 
	include_once dirname(__FILE__)."/lib.php";

	$kakaologin = new kakaoRestAPI();
	if( $kakaologin->auth_apply !== true){ die("카카오로그인을 사용할 수 없습니다."); }

	// 로그아웃일경우
	if( !empty($_GET['logout'])){

		// 사용자 정보 호출 
		$userLogout =  @json_decode($kakaologin->getLogout($_SESSION['kakao_token_info']['access_token']),true);


		// 에러
		if( !empty($userLogout['msg']) ){
			echo '<h1>사용자 로그아웃 요청실패</h1><pre>'; print_r($userLogout); echo '</pre>';
			exit;
		}	

		if(!empty($_SESSION['auth_kakao_token_info'])) unset($_SESSION['auth_kakao_token_info'],$_SESSION['kakao_token_info']);
		if(!empty($_SESSION['auth_kakao_user_info'])) unset($_SESSION['auth_kakao_user_info'],$_SESSION['kakao_user_info']);


		die(header("Location:".$kakaologin->result_uri));
	}


	if(!empty($_SESSION['auth_kakao_token_info'])) unset($_SESSION['auth_kakao_token_info'],$_SESSION['kakao_token_info']);
	if(!empty($_SESSION['auth_kakao_user_info'])) unset($_SESSION['auth_kakao_user_info'],$_SESSION['kakao_user_info']);


	// 받은 코드로 처리
	$code = empty($_GET['code']) ? '': $_GET['code'];
	$token = @json_decode($kakaologin->getToken($code),true);

	// 에러
	if( !empty($token['error']) ){
		echo '<h1>인증토큰 요청 실패</h1><pre>'; print_r($token); echo '</pre>';
		exit;
	}

	// 세션에 토큰 정보를 저장
	$_SESSION['auth_kakao_token_info'] = true;
	$_SESSION['kakao_token_info'] = $token;



	// 사용자 정보 호출 
	$userInfo =  @json_decode($kakaologin->getUserInfo($token['access_token']),true);


	// 에러
	if( !empty($userInfo['msg']) ){
		echo '<h1>사용자 정보 요청실패</h1><pre>'; print_r($userInfo); echo '</pre>';
		exit;
	}	

	// 세션에 사용자 정보를 저장
	$_SESSION['auth_kakao_user_info'] = true;
	$_SESSION['kakao_user_info'] = $userInfo;

	// 사용자 정보 요청 
	die(header("Location:".$kakaologin->result_uri));