Full Stack Web Developer.
Syaku (샤쿠)

Java, JS (ES6+), Spring, Spring security, jQuery, Reactjs, Bootstrap.

        

08-04 05:26


Spring Boot 2 보기 Front-end 보기 DevOps 보기 Spring 3 보기 Spring Security 3 보기

소셜네트워크 네이버 미투데이 API 개발 #5 Open API , Naver Me2day API , SNS

 

written by Seok Kyun. Choi. 최석균

"네이버 미투데이 API 개발"

[연결 포스팅]
2012/04/09 - [개발노트/JAVA] - 오픈API 시작하며 #1 OpenAPI , JSON , XML , HTTP , OAuth
2012/04/09 - [개발노트/JAVA] - 소셜네트워크 트위터 API 개발 #2 Open API , Twitter API , SNS , OAuth 

[필독]
1) 연결되는 포스팅입니다. 꼭 이전 포스팅을 참고하세요.
2) OAuth 와 SNS API 대해 기본적인 지식이 필요합니다.
3) 포함된 소스는 참고용이며, 그대로 사용할 경우 오류가 발생합니다. 직접 필요한 부분을 개발하세요.
- 직접 개발해야 할 부분은 임의적으로 주석처리 하였습니다.
4) 시간이 없어 급정리해서 올리는 글입니다. 부족한 부분이 많습니다. 이점 참고하세요.
5) 원문 그대로 사용하는 것을 방지하기 위해 소스파일은 제공하기 않습니다. 꼭 소스를 분석후 직접 개발하세요.

네이버 미투데이 API 사이트
http://dev.naver.com/openapi/apis/me2day/me2api_intro

소셜네트워크 대명사 미투데이에서 제공되는 API를 이용하여 특화된 소셜을 개발해보자.
네이버 미투데이는 자체 인증방식을 사용하고 있다. 

> 이미 앞 장에서 설명했던 내용은 생략함.

1. 미투데이 앱 에서 어플리케이션을 생성하자.
http://me2day.net/me2/app/get_appkey

2
. Http Classes (생략)

3. OAuth Classes (생략)

 4. 미투데이 API Classes
/*
 * Me2dayAPI.java 2011.11.16
 *
 * Copyright (c) 2010, MEI By Seok Kyun. Choi. (최석균)
 * http://syaku.tistory.com
 * 
 * GNU Lesser General Public License
 * http://www.gnu.org/licenses/lgpl.html
 */
package com.syaku.modules.snsauth;

import java.util.*;
import java.net.*;

import org.apache.log4j.Logger;
import org.apache.commons.lang.*;
import org.apache.commons.collections.*;

import oauth.signpost.*;
import oauth.signpost.basic.*;
import oauth.signpost.exception.*;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;

import net.sf.json.*;
/*
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;

import javax.servlet.*;
import javax.servlet.http.*;
import com.opensymphony.xwork2.*;
import org.apache.struts2.ServletActionContext;

import com.ibatis.sqlmap.client.SqlMapClient;
import org.apache.commons.configuration.Configuration;
import com.syaku.config.*;
import com.syaku.common.*;
import com.syaku.core.*;
import com.syaku.util.*;
*/
public class Me2dayAPI {
  //private Logger log = Logger.getLogger(Me2dayAPI.class);
  //public SqlMapClient sqlMap = SqlMapConfig.getSqlMapInstance();
  //public final Configuration MODULE_CONFIG = SyakuConfig.getInstance("com/syaku/modules/snsauth/info.properties");

  public HttpServletRequest request = ServletActionContext.getRequest();
  public HttpServletResponse response = ServletActionContext.getResponse();
  public HttpSession session = request.getSession();

  //private SnsAuthObject mSnsAuthObject = new SnsAuthObject();
  //private SnsAuthStored mSnsAuthStored = new SnsAuthStored();
  private SnsAuthHttp mSnsAuthHttp = new SnsAuthHttp();

  // user_id 변경이 가능한 계정이며, uid 고유한 값이다.
  private String uid,user_id,nickname,profile_cover,post_send;
  public String getUid() { return this.uid; } // id
  public String getUser_id() { return this.user_id; } // id
  public String getNickname() { return this.nickname; } // nickname
  public String getProfile_cover() { return this.profile_cover; } // 프로필 사진
  public void setPost_send(String post_send) { this.post_send = post_send; } // 글 전송여부
  public String getPost_send() { return this.post_send; }

  final String API_URL = "http://me2day.net/api";
  final String SNS_NAME = "ME2DAY";
  private String API_NONCE;
  private String API_AKEY;
  private String API_CALLBACK;
  final int TEXT_LENGTH = 150;

  public Me2dayAPI() {
    this.API_NONCE = "nonce");
    this.API_AKEY = "akey");
    this.API_CALLBACK = "callback_url");
  }

  // 싱크 처리
  public void getSignIn() throws Exception {

    try {

      String token = "쿠키에 저장된 access_token 을 읽어옴";

      if (StringUtils.isNotEmpty(token)) {

        if (mSnsAuthStored.getAuthSessValid(this.SNS_NAME) == false) {

          // 세션이 없다면 디비에서 정보 조회 (아래의 소스는 직접 구현하기)
          //Map mapSch = new HashMap();
          //mapSch.put("name",this.SNS_NAME);
          //mapSch.put("token",token);
          //SnsAuthBean objSns = (SnsAuthBean) mSnsAuthObject.getSnsAuthView(mapSch);

          if (objSns != null) {
            String access_token_secret = objSns.getAccess_token_secret();
            getAuthSync(access_token_secret,objSns.getUid());
          }

        }

        if (mSnsAuthStored.getAuthSessValid(this.SNS_NAME) == true) {
        Map<String,String> mapUser = this.getUserInfo(); // 계정 정보
        //mSnsAuthStored.setUserInfo(this.SNS_NAME,mapUser); // 세션 저장
        }

        //mSnsAuthStored.setAuthCookie(token); // 쿠키 갱신
      } else {
        //mSnsAuthStored.getSessRemove(this.SNS_NAME); //세션 삭제
      }

    } catch (Exception e) {
      //log.error(e.toString());
      //mSnsAuthStored.getSessRemove(this.SNS_NAME);
    }

  }

  public String getAccess(ParameterUtils param) throws Exception{
    String auth_url = null;

    String oauth_token = param.value("token","");
    String result = param.value("result","");
    String result_user_id = param.value("user_id","");
    String oauth_verifier = param.value("user_key","");

    //String token = mSnsAuthStored.getAuthCookie(); // 저장된 쿠키 호출

    String access_token = null;
    String access_token_secret = null;

    Map mapSch = new HashMap();

    if (StringUtils.isEmpty(result)) {

      if (StringUtils.isNotEmpty(token)) {

        // 디비에 저장된 페이스북 정보 조회
        //mapSch.clear();
        //mapSch.put("name",this.SNS_NAME);
        //mapSch.put("token",token);
        //SnsAuthBean objSns = (SnsAuthBean) mSnsAuthObject.getSnsAuthView(mapSch);

        if (objSns != null) {
          access_token_secret = objSns.getAccess_token_secret(); // ukey(md5)
        }

        //mSnsAuthStored.setAuthCookie(token); // 쿠키 갱신
      }

      if (access_token_secret != null) {

        // access token 을 이용하여 재인증 처리
        getAuthSync(access_token_secret,result_user_id);
        auth_url = "SUCCESS";
      } else {
        //mSnsAuthStored.getSessRemove(this.SNS_NAME); 세션삭제

        String json = mSnsAuthHttp.getHttpGet(API_URL + "/get_auth_url.json?akey=" + URLEncoder.encode(API_AKEY,"utf-8"));
        JSONObject objJson = JSONObject.fromObject(json);
        auth_url = objJson.getString("url");
        oauth_token = objJson.getString("token");
        //mSnsAuthStored.setSessCreate(this.SNS_NAME,oauth_token); // 세션 생성

      }

    } else {

      try {
        //sqlMap.startTransaction();
        
        if (StringUtils.isEmpty(token)) {
          // 임의의 토큰 생성 및 토큰 디비저장
          //token = DigestUtils.sha256Hex(DigestUtils.sha256("syaku" + DateUtils.date("yyyyMMddHHmmss") + "me"));
        }

        String ukey = API_NONCE + DigestUtils.md5Hex(API_NONCE + oauth_verifier);
        
        // access token 얻기
        access_token = oauth_verifier; // user_key
        access_token_secret = ukey;
        
        // 싱크처리
        getAuthSync(access_token_secret,result_user_id); // 세션
        Map<String,String> mapUser = this.getUserInfo(); // 계정 정보

        /* 디비에 저장할 정보를 기록
        String uid = this.uid;
        String ip = request.getRemoteAddr();
        String user_agent = request.getHeader("User-Agent");

        mSnsAuthObject.getSnsAuthMainResetUpdate(token);

        SnsAuthBean snsauthbean = new SnsAuthBean();
        snsauthbean.setToken(token);
        snsauthbean.setName(this.SNS_NAME);
        snsauthbean.setAccess_token(access_token);
        snsauthbean.setAccess_token_secret(access_token_secret);
        snsauthbean.setMain("Y");
        snsauthbean.setPost_send("Y");
        snsauthbean.setUid(uid);
        snsauthbean.setReg_date(DateUtils.date("yyyyMMddHHmmss"));
        snsauthbean.setIp(ip);
        snsauthbean.setUser_agent(user_agent);
        mSnsAuthObject.getSnsAuthInsert(snsauthbean);

        mSnsAuthStored.setAuthCookie(token); // 갱신
        mSnsAuthStored.setUserInfo(this.SNS_NAME,mapUser);
        mSnsAuthStored.setSessClean(oauth_token);
        */

        auth_url = "SUCCESS";

        //sqlMap.commitTransaction();

      } catch (Exception e) {
        //mSnsAuthStored.getSessRemove(this.SNS_NAME); // 세션 삭제
        //log.error(e.toString()); // 로그 출력

      } finally {
        //sqlMap.endTransaction();
      }

    }

    return auth_url;
  }

  // 인증 싱크 (재인증)
  public void getAuthSync(String access_tokensecret,String me2uid) throws Exception{
    if (access_tokensecret != null) {
      //mSnsAuthStored.setAuthSess(this.SNS_NAME,access_tokensecret); // 세션에 저장된 인증 토큰 가져옴
    }

    if (me2uid != null) {
      session.setAttribute("_MEI_" + this.SNS_NAME + "_UID",me2uid);
    }

  }

  // 계정 정보
  public Map<String,String> getUserInfo() throws Exception {
    //String access_tokensecret = (String) mSnsAuthStored.getAuthSess(this.SNS_NAME); // 세션에 저장된 인증 토큰
    String me2uid = (String) session.getAttribute("_MEI_" + this.SNS_NAME + "_UID");

    //Map<String,String> mapSS = (Map<String,String>) mSnsAuthStored.getUserInfo(this.SNS_NAME); // 세션에 저장된 계정 정보
    Map<String,String> mapRet = new HashMap();

    if (MapUtils.isNotEmpty(mapSS)) {
      this.uid = mapSS.get("uid");
      this.user_id = mapSS.get("user_id");
      this.nickname = mapSS.get("nickname");
      this.profile_cover = mapSS.get("profile_cover");

    } else {
      // 계정 정보 호출
      String result = mSnsAuthHttp.getHttpGet(API_URL + "/get_person/" + me2uid + ".json?ukey=" + URLEncoder.encode(access_tokensecret,"utf-8") + "&akey=" + URLEncoder.encode(this.API_AKEY,"utf-8"),null);

      try {
        JSONObject objJson = JSONObject.fromObject(result);
        String user_id = objJson.getString("id");
        String nickname = objJson.getString("nickname");
        String profile_cover = objJson.getString("face");

        String uid = user_id;
        
        // 정보 기록
        this.uid = uid;
        this.user_id = user_id;
        this.nickname = nickname;
        this.profile_cover = profile_cover;

      } catch (Exception e) {
        //mSnsAuthStored.getSessRemove(this.SNS_NAME); // 세션 삭제
        getException(result);
      }

    }

    if (this.user_id != null || this.nickname != null || this.profile_cover != null) {
      mapRet.put("uid",this.uid);
      mapRet.put("user_id",this.user_id);
      mapRet.put("nickname",this.nickname);
      mapRet.put("profile_cover",this.profile_cover);
    }

    return mapRet;

  }

  // 글 쓰기
  // getPost 메소드를 호출 후 msg_id 받아 글 내용과 같이 디비에 저장하자. msg_id 는 글을 나중에 삭제할때 필요하다.
  public String getPost(Map map) throws Exception {
    //String access_tokensecret = (String) mSnsAuthStored.getAuthSess(this.SNS_NAME);// 세션에 저장된 인증 토큰
    String me2uid = (String) session.getAttribute("_MEI_" + this.SNS_NAME + "_UID");

    String msg_id = null;
    String message = (String) map.get("message");
    String parent_msg_id = (String) map.get("parent_msg_id");
    String url = (String) map.get("url");
    String tag = "태그입력";

    message = FnUtils.getCutString(message,TEXT_LENGTH,"");

    List<NameValuePair> formparams = new ArrayList<NameValuePair>();
    if (StringUtils.isNotEmpty(url)) {
      message = "\"" + message +"\":" + url;
    }

    formparams.add(new BasicNameValuePair("uid", me2uid));
    formparams.add(new BasicNameValuePair("ukey", access_tokensecret));
    formparams.add(new BasicNameValuePair("akey", this.API_AKEY));
    formparams.add(new BasicNameValuePair("post[body]", message));
    formparams.add(new BasicNameValuePair("post[tags]", tag));

    UrlEncodedFormEntity formentity = new UrlEncodedFormEntity(formparams, "UTF-8");

    String result = mSnsAuthHttp.getHttpPost(API_URL + "/create_post/" + me2uid + ".json",formentity,null);
    log.debug("[MEI ME2DAY POST result]" + result);

    JSONObject objJson = JSONObject.fromObject(result);
    try {
      msg_id = objJson.getString("post_id");
    } catch (Exception e) {
      getException(result);
    }

    log.debug("[MEI ME2DAY POST ID]" + msg_id);
    return msg_id;
  }

  // 글 삭제
  public void getDelete(String msg_id) throws Exception {
    String access_tokensecret = (String) mSnsAuthStored.getAuthSess(this.SNS_NAME);
    String me2uid = (String) session.getAttribute("_MEI_" + this.SNS_NAME + "_UID");

    List<NameValuePair> formparams = new ArrayList<NameValuePair>();
    formparams.add(new BasicNameValuePair("uid", me2uid));
    formparams.add(new BasicNameValuePair("ukey", access_tokensecret));
    formparams.add(new BasicNameValuePair("akey", this.API_AKEY));
    formparams.add(new BasicNameValuePair("post_id", msg_id));
    UrlEncodedFormEntity formentity = new UrlEncodedFormEntity(formparams, "UTF-8");

    String result = mSnsAuthHttp.getHttpPost(API_URL + "/delete_post.json",formentity,null);
    JSONObject objJson = JSONObject.fromObject(result);
    getException(result);
  }

  // result json 익셉션 출력
  public void getException(String json) throws Exception {
    String msg_text = null;
    JSONObject objJson = JSONObject.fromObject(json);
    try {
      msg_text = objJson.getString("description");
    } catch (Exception e) {
    }

    if (StringUtils.isNotEmpty(msg_text)) {
      log.debug("ME2DAY : " + msg_text);
      //throw new Exception("ME2DAY : " + msg_text);
    }

  }

}


 5. 미투데이 프로그램

아래의 내용에서 SNS라는 대상은 미투데이를 말합니다.

SNS 뷰(JSP)단의 필요한 UI 항목은 아래와 같다. JSP와 자바스크립트를 적절하게 혼합하여 구현하면 된다.

- SNS 에 등록된 글 목록
- 글을 삭제하는 삭제 버튼
- 글을 등록하는 쓰기 폼
- SNS 에 로그인 하거나 로그아웃하는 버튼

1단계. 세션이나 쿠키 존재를 파악하여 계정을 연결한다.

// 객체생성
Me2dayAPI me2day = new Me2dayAPI();
String token = ID 쿠키가져오기;

if token 존재할 경우 {
  me2day.getSignIn(); // SNS 연결
  me2day.getUid(); // 고유 아이디 (숫자)
  me2day.getUser_id(); // 유동 아이디 (영문)
  me2day.getNickname(); // 별명
  me2day.getProfile_cover(); // 절대경로의 프로필 사진
}

2단계. SNS 글 목록

SNS에 연결하여 글을 가져오는 것이 아니라, 글을 쓸때마다 자신의 디비에 저장한다. 꼭 글 id도 함께 저장하여야 한다.
[참고] 프로필 사진는 id를 이용해 img 태그로 가져오면 된다.

3단계. SNS 로그인 , 로그아웃

1단계 SNS 계정이 연결되지 않을 경우 UI 상에서 로그인 버튼을 노출시켜 로그인을 유도한다.
로그인 버튼을 누를면 새 창이 뜬다. 이부분에 추가적인 UI 화면(JSP)이 필요하다.
이 화면에서 URL 이 SNS 애플리케이션(인증키 settings)의 콜백 URL이 되어야한다.
그래서 SNS 서버에 거친 후 다시 돌아오게 되고, oauth_token 파라미터 값을 얻을 수 있다.

Me2dayAPI me2day = new Me2dayAPI();
// 연결이 되지 않을 경우 (즉 토큰이나 세션이 없을 경우) auth_url 를 리턴받는 다.
auth_url = me2day.getAccess(request);

if (auth_url 값이 있을 경우) {
  auth_url 페이지로 이동하게 함
} else {
  자바스크립트를 이용하여 현재 창(팝업:새창)을 닫고 부모 페이지를 새로고침
}

로그아웃은 쿠키와 세션에 존재하는 해당 SNS 정보를 삭제하면 된다.


4단계. 글 쓰기 , 글삭제

Me2dayAPI me2day = new Me2dayAPI();
Map map = new HashMap();
map.put("message","글 내용");

이 외 필요한 기능은 해당 SNS DOCS 참고하여 추가하자.

String msg_id = me2day.getPost(map);
SNS에 정상적으로 등록되면 msg_id 와 message 를 서버 디비에 저장한다.

// 글 삭제
facebook.getDelete(msg_id);



http://syaku.tistory.com

댓글 남기기
◀ PREV 1···135136137138139140141142143···313 NEXT ▶