ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • REST API로 카카오톡 메세지 보내기 #02 - python 으로 인증하기
    개발 이야기/개발툴 및 기타 이야기 2021. 12. 8. 12:34
    728x90
    반응형

    오늘은 Python 으로 카톡 메세지를 보내 보겠습니다.

    메세지와 관련된 API 리스트는 공식 개발자 문서에서 "문서" -> "메세지" -> "카카오톡 메세지:REST API"의 "선택 조건에 따른 API" 항목에서 확인할 수 있습니다.

    여기서는 "나에게 보내기"를 샘플로 만들어 보겠습니다. API 리스트 하단에 "나에게 보내기" 항목을 보시면 Request와 Response, 그리고 Sample을 확인하실 수 있습니다. 이제 이 내용을 python 코드에서 requests 모듈을 사용해 적용해 보겠습니다. 작업을 위해서는 이전 글에서 언급된 REST API KEY와 REDIRECT_URI를 통해 인가 코드와 인증 토큰을 받아야 합니다. 관련 내용은 이 문서 중 "인가 코드 받기", "토큰 받기"에서 확인하실 수 있습니다.

    우선 인가 코드를 받아보겠습니다. 유저의 동의가 필요하기 때문에 terminal 혹은 prompt=none 옵션으로는 자동으로 발급받는 것이 불가능합니다. 발급된 인가 코드는 토큰 발급 시 무효화됩니다. https://kauth.kakao.com/oauth/authorize?response_type=code&client_id={REST_API_KEY}&redirect_uri={REDIRECT_URI} 형식으로 입력해서 직접 동의 절차를 거칩니다. 

    전체 동의 후 "동의 후 계속하기"를 누르면 404 에러가 나오는 화면에 나오는데, 주소창을 보면 redirect_uri 주소뒤에 code값이 포함되어 있는 것을 확인 할 수 있습니다. 추가된 이 값이 인가코드 입니다. "?code=" 뒤의 모든 텍스트를 복사해 주세요. 인가 코드를 받았다고 카카오 로그인이 완료된 것은 아니고, 토큰 받기까지 마쳐야 정상적으로 로그인 과정을 완료할 수 있습니다.

    이제 토큰을 발급받아 보겠습니다. "토큰 받기"에 대한 상세 내용은 문서를 참고하시면 됩니다. 아래는 python requests 모듈을 사용해 post로 token을 요청하여 출력하는 코드입니다.

    import requests
    import json
    
    rest_api_key = 'YOUR_REST_API_KEY'
    redirect_uri = 'https://example.com/oauth'
    url_token = 'https://kauth.kakao.com/oauth/token'
    authorize_code = 'YOUR_AUTH_CODE'
    
    data = {
        'grant_type':'authorization_code',
        'client_id':rest_api_key,
        'redirect_uri':redirect_uri,
        'code': authorize_code,
    }
    
    response = requests.post(url_token, data=data)
    tokens = response.json()
    print(tokens)

    이렇게 발급된 토큰은 최장 한 달을 사용할 수 있습니다. 그래서 전달받은 토큰 정보를 저장해서 계속 사용할 수 있으며, "토큰 정보 보기"로 해당 토큰이 유효한지, "토큰 갱신하기"로 인가 코드를 다시 받지 않고 계속 갱신하면서 사용할 수 있습니다.  이제 위 코드를 조금 수정해 보겠습니다. 처음 시작할 때 토큰 파일이 있는지 확인 후 없으면 새로 받고, 있다면 유효한지, 유효기간이 지났다면 갱신하는 과정을 추가해 보겠습니다.

    import requests
    import json
    
    rest_api_key = 'YOUR_REST_API_KEY'
    redirect_uri = 'https://example.com/oauth'
    url_token = 'https://kauth.kakao.com/oauth/token'
    authorize_code = 'YOUR_AUTH_CODE'
    
    try:
        with open("kakao_token.json","r") as fp: # 기존에 저장된 token 파일이 있는지 찾아봅니다.
            tokens = json.load(fp)
            if "error_code" in tokens:
                tokens={}
    except Exception as e:
        print(e)
        tokens={}
    
    if tokens == {}:
        # 신규 발급이 필요한 경우
        param = {
            'grant_type':'authorization_code',
            'client_id':rest_api_key,
            'redirect_uri':redirect_uri,
            'code': authorize_code, # 한번 발급되면 authorize_code는 무효화됩니다. 
        }
    
        response = requests.post('https://kauth.kakao.com/oauth/token', data=param)
        tokens = response.json() # token 발급 api로 발급된 정보들을 kakao_token.json 파일에 저장합니다.
        if "error_code" in tokens:
            print(tokens["error_code"])
        else:
            with open("kakao_token.json","w") as fp:
                json.dump(tokens, fp)
                print("파일로 토큰 정보 저장!")
    else:
    	# 기존 발급된 정보가 있을 경우
        headers = {
            "Authorization": "Bearer " + tokens["access_token"]
        }
        # access_token_info의 결과가 계속 -401로 돌아옵니다. 추후 수정할 예정입니다.
        response = requests.get('https://kapi.kakao.com/v1/user/access_token_info', headers=headers)
        result = response.json()
        if "error_code" in result:
        	# -401은 유효하지 않은 값 혹은 유효기간이 지난 토큰일 경우 발생하는 에러입니다.
            # api로 token 갱신을 요청합니다.
            param = {
                "grant_type":"refresh_token",
                "client_id" : rest_api_key,
                "refresh_token" : tokens["refresh_token"]
            }
            response = requests.post('https://kauth.kakao.com/oauth/token', data=param)
            new_token = response.json()
            
            # 새로 발급된 token을 다시 저장합니다.
            if "error_code" in new_token:
                print("ERROR :", new_token["error_code"])
            else:
                with open("kakao_token.json", "w") as fp:
                    json.dump(new_token, fp)
                    print("파일로 새로운 토큰 정보 저장!")
        else:
            print("정상 토큰")

    하다보니 오늘도 메세지를 보내지는 못했네요. 내일은 실제 메세지를 꼭 보내보겠습니다. :)

    반응형

    댓글 2

Designed by Tistory.