결제 연동을 할 때 SDK로 하면 편하지만, 가끔 사용하는 모듈들과 충돌을 일으킬 때까 있습니다. 이럴 때를 대비한 REST API로 구현하는 것을 눈여겨 봐두면 좋을 것 같습니다.

저는 서버에서 결제 검증만 할 것 이므로, 토큰을 얻는 것과 클라이언트에서 결제 이후 넘어온 주문 번호를 확인해 결제 정보를 읽어오는 것만 할 것 입니다.

 

1. 결제 연동을 하는 공식 문서.

-> https://developer.paypal.com/docs/api/orders/v2/

이 페이지 하나에 모든 설명이 다들어 있으며,  cURL을 이용해 사용할 수 있도록 되어 있습니다. 맥 같은 경우 cURL이 설치되어 있으므로, 쉽게 사용하며, 윈도우에서는 직접 설치해야할 지도 모르겠습니다.

 

2. nodejs 리퀘스트 설치.

-> npm i request

node js가 설치되어 있다면 위 명령으로 리퀘스트가 설치 됩니다.

 

3. cURL 명령을 request로 바꿔주는 페이지.

-> https://curl.trillworks.com/#node

curl 명령을 node js에서 request로 바꿔 주려면 조금 귀찮은 면이 있는데 이 사이트를 이용하면, 쉽게 변경할 수 있습니다.

 

4. AccessToken 얻기

-> https://developer.paypal.com/docs/api/get-an-access-token-curl/

위 페이지에 cURL 명령에서 client_id와 시크릿을 바꿔 넣으면 access 토큰을 얻을 수 있습니다. 명령은 아래와 같습니다. \는 그냥 한줄로 계속 써야한다는 의미 입니다.

curl -v https://api.sandbox.paypal.com/v1/oauth2/token \
   -H "Accept: application/json" \
   -H "Accept-Language: en_US" \
   -u "client_id:secret" \
   -d "grant_type=client_credentials"

 

5. 결제 정보 얻기

-> https://developer.paypal.com/docs/api/orders/v2/

위 페이지에서 show order details 항목을 참고 하면 구매했던 상품의 정보를 확인할 수 있습니다. cURL 명령은 아래와 같습니다.

curl -v -X GET https://api.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T \
-H "Content-Type: application/json" \
-H "Authorization: Bearer Access-Token"

 

6. 예제 소스.

아래 소스를 그대로 가져가셔서 약간 수정해 페이팔 검증으로 사용하셔도 됩니다. 그래도 cURL로 잘되는 지 먼저 확인하시는 편이 좋습니다. (c_Util은 제가 응답을 json으로 보내기 위해, 만든 클래스 입니다.)

// 기본 모듈들 입니다.

// npm 으로 다운로드 받은 파일 입니다.
const request = require('request');

// ags에서 설정한 파일들 입니다.
const c_Util = require( './c_Util' );



//  --- --- --- ---     전역에 공개되는 값들 입니다.

// 전역 변수를 설정합니다.
let clientID = "";
let secret = "";



// 클래스를 초기화 하는 메소드 입니다.
module.exports.init = function(
    _isSandbox, _sandbox_client_id, _sandbox_secret, _live_client_id, _live_secret
){



    // 샌드 박스인 경우, 클라이언트와 시크릿을 설정합니다.
    if( _isSandbox )
    {

        console.log( "페이팔은 샌드박스로 동작합니다." );
        clientID = _sandbox_client_id;
        secret = _sandbox_secret;

    }

    // 라이브 인경우, 클라이언트와 시크릿을 설정합니다.
    else
    {

        console.log( "페이팔은 라이브로 동작합니다." );
        clientID = _live_client_id;
        secret = _live_secret;

    }


    console.log( "페이팔 클라이언트키:시크릿" + clientID + ":"+ secret );



}



// 클래스를 생성하는 메소드 입니다.
module.exports.create = function()
{



    //  --- --- --- ---     초기화 및 반환객체를 만들어 줍니다.
    let rINSTANCE = {};



    //  --- --- --- ---     에세스 토큰 획득 관련 메소드들 입니다.

    // 에세스 토큰을 가지고오는 메소드 입니다.
    rINSTANCE.getAccessToken = function()
    {

        return new Promise(function( resolve, reject ){

            let headers = {
                'Accept': 'application/json',
                'Accept-Language': 'en_US'
            };
            
            let dataString = 'grant_type=client_credentials';
            
            let options = {
                url: 'https://api.sandbox.paypal.com/v1/oauth2/token',
                method: 'POST',
                headers: headers,
                body: dataString,
                auth: {
                    'user': clientID,
                    'pass': secret
                }
            };

            
            function callback(error, response, body) {


                // 에러가 있다면 오류를 반환하고 종료합니다.
                if( error )
                {

                    let unknownError = c_Util.res_Message( {}, "에세스 토큰을 가지고 오던 중 알 수 없는 오류를 만났습니다.", 5 );
                    unknownError.detailError = error;
                    resolve( unknownError );

                }


                // 에러가 없다면 정상적인 결과를 반환합니다.
                else
                {

                    //  받은 값은 문자열 이므로, 객체로 바꿔 줍니다.
                    let resObj = JSON.parse( body );
                    resolve( resObj.access_token );
                    
                }


            }
            
            request(options, callback);
            

        });

    }



    //  --- --- --- ---      체크 아웃 관련 메소드들 입니다.

    // 상품 결제 정보가 유효한지 확인하는 메소드 입니다.
    rINSTANCE.getProduct = function( _accessToken, _orderId )
    {

        return new Promise( function( resolve, reject ){


            let headers = {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + _accessToken
            };

            let options = {
                url: 'https://api.sandbox.paypal.com/v2/checkout/orders/' + _orderId,
                headers: headers
            };

            function callback(error, response, body) {

                // 오류가 난 경우 오류를 처리하도록 합니다.
                if( error )
                {

                    let unknownError = c_Util.res_Message( {}, "결제 정보를 확인하던 중 오류를 만났습니다.", 5 );
                    unknownError.detailError = error;
                    resolve( unknownError );
                    return;
                    
                }

                else
                {

                    let successResult = JSON.parse( body );
                    resolve( successResult );
                    return;

                }

            }

            request(options, callback);

        } );

    }







    //  --- --- --- ---     마무리 및 인스턴스 객체를 반환합니다.

    return rINSTANCE;




}




















































// 문서의 끝 입니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Posted by 창업닉군
,

페이팔은 결제 연동이 매우 간단한 편이라, 따로 소스는 두지 않았고, 주의 사항만 메모를 해 두었습니다.

 

1. 개발 사이트

-> https://developer.paypal.com

페이팔은 테스트를 위한 SANDBOX 서버, 실제 거래를 위한 LIVE 서버를 운영하고 있습니다. SANDBOX 와 LIVE 서버는 같은 앱이라도 각각 다른 클라이언트 ID, 시크릿을 설정해 주어야 합니다.

 

2. 체크 아웃 예제 페이지.

-> https://developer.paypal.com/docs/checkout/integrate/#

클라이언트 아이디만 넣어 주고, 그냥 소스를 붙여 넣기만 해도 잘 동작합니다. 영수증 검증에 사용되는 값은, 결제 후 받는 data의 orderID, 혹은 details의 id 값을 넣으면 됩니다. (둘이 같은 값 입니다.). 이 페이지만 따라 하면 모든 연동이 끝이 납니다.

 

3. 클라이언트 SDK 설정.

클라이언트 SDK 설정에는 클라이언트 아이디만 넣어주면 기본적으로 설저이 끝이 나지만, 추가 옵션으로 통화 등을 설정할 수 있습니다.

 

4. 서버사이드 설정.

-> https://developer.paypal.com/docs/checkout/reference/server-integration/setup-sdk/

서버 사이드 설정의 SDK 설치 방법은 의외로 눈에 잘 띄지 않는데, 이 페이지에 있습니다.

 

5. 서버에서 결제 셋팅.

->  https://developer.paypal.com/docs/checkout/reference/server-integration/set-up-transaction/

서버에서 결제 처리를 할 이유는 잘 없지만, 페이팔에서 가능합니다. 일단 링크를 걸어 둡니다.

 

6. 결제.

-> https://developer.paypal.com/docs/checkout/reference/server-integration/capture-transaction/#on-the-server

capture는 실제 결제 처리를 하는 부분입니다. 만약 클라이언트에서 넘어온, 결제를 이 루틴으로 검증하려고 하면 오류를 만납니다. 결제는 아래 결제 확인 부분에서 처리하면됩니다.

 

7. 결제 확인.

-> https://developer.paypal.com/docs/checkout/reference/server-integration/get-transaction/

클라이언트에서 결제 하면 서버에서 주로 결제를 확인하는데 이 부분에서 하게 됩니다. 많이 쓰게 되니 소스 코드를 봐 두세요. 결제 확인 이후 res.json 등의 헤더 변경을 하는 방법으로 소스를 보내면 오류를 만납니다. res.end 메소드로 응답을 보내 주세요.

 

8. 예제.

-> https://github.com/paypal/Checkout-Nodejs-SDK/

문서에 있는 코드들을 보면, 쉽게 이해가 가지 않습니다. 생략된 것들이 많이서 인데, 일단 예제를 보면 쉽게 이해가 갑니다. 위 문서를 잘 읽어 보셨다면, 보자 마자 이해가 될 정도 입니다.

예제는 아래와 같이 들어 가면됩니다.

1. https://developer.paypal.com/docs/checkout/reference/server-integration/setup-sdk/#http-request-headers 문서로가서 화면 아래로 스크롤을 한뒤, Additional information에서 원하는 것을 선택하면됩니다.

 

9. 마지막으로 클라이언트에서 결제 소스.

제가 구현했던 결제 소스를 남겨 드립니다. 참고하시기 바랍니다.

// npm 모듈들.
const express = require( 'express' );
const paypal = require('@paypal/checkout-server-sdk');







module.exports.init = function(
    _isDebug, _client_id, _secret, _sandbox_client_id, _sandbox_secret
    ){

    //  --- --- --- ---     페이팔 설정 관련 메소드들 입니다.

    // 디버그 인지 여부에 따라 사용할 환경 설정 객체를 반환하는 메소드를 만들어 줍니다.
    let environment = "";

    if( _isDebug == "YES" )
    {

        console.log( "페이팔은 sandbox 모드로 동작합니다." );
        environment = function()
        {
            return new paypal.core.SandboxEnvironment(
                _sandbox_client_id, _sandbox_secret
            );
        }

    }

    else
    {

        console.log( "페이팔은 live 모드로 동작합니다." );
        environment = function()
        {
            return new paypal.core.SandboxEnvironment(
                _client_id, _secret
            );
        }

    }

    // 클라이언트를 설정합니다.
    let client = new paypal.core.PayPalHttpClient( environment() );



    // 영수증 가지고 오는 동작을 하는 메소드 입니다.
    let captureOrder =  async function(orderId) {
        // request = new paypal.orders.OrdersCaptureRequest(orderId);
        request = new paypal.orders.OrdersGetRequest(orderId);

        // request.requestBody({});
        // Call API with your client and get a response for your call
        let response = await client.execute(request);
        // console.log(`Response: ${JSON.stringify(response)}`);
        // If call returns body in response, you can get the deserialized version from the result attribute of the response.
        // console.log(`Capture: ${JSON.stringify(response.result)}`);

        return response;
    }
    
    


    //  --- --- --- ---     메일 라우터 및 전역에서 사용되는 메소드들 입니다.

    let mainRouter = express.Router();




    //  --- --- --- ---     라우터들 입니다.

    // 연결되었는지 확인을 위한 에코 처리를 합니다.
    mainRouter.use( "/echo", function( req, res, next ){

        
        
        // 입력 받은 값을 그대로 반환합니다.
        res.end( req.body.echo );
        return;


    } );


    // 페이팔 영수증 검증.
    mainRouter.use( "/receipt", async function( req, res, next ){


        console.log( req.body );


        // 2a. Get the order ID from the request body
        const orderID = req.body.receipt;
        let capture =  await captureOrder(orderID); 
        

        console.log( capture );


        return res.end("일단 연동 되었음.");


    } )




    //  --- --- --- ---     반환 및 후처리 메소드들 입니다.

    // 결과를 반환합니다.
    return mainRouter;


}
















































// 문서의 끝 입니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Posted by 창업닉군
,

html 은 일반 채팅과 같은 TCP/IP 프로토콜을 사용하지만, 클라이언에서 서버로 요청을 보내면, 요청에 대한 처리 후 접속을 끊어 버립니다. 그런 이유로 단방향 통신이라하며, 서버에서 원할 때 클라이언트로 메시지를 보낼 방법이 없습니다.

하지만, HTML5에서 웹소켓 개념이 추가되며, 이런 문제를 해결하였습니다. node.js에서 잘 알려진 웹소켓 지원 모듈은 ws 와 socket.io 입니다. 둘다 websocket을 이용할 수 있다는 점은 같지만, 특징이 뚜렸하기 때문에, 사용목적이 달라질 수 있습니다.

ws : 표준 웹소켓을 구현하였습니다. 그래서, 웹 브라우저, 게임을 포함한 앱, 윈도우 프로그램 모든 곳에서 사용할 수 있습니다. 하지만, 구형 웹브라우저나, 웹소켓이 모두 구현되지 않은 곳에서는 잘 동작하지 않을 수 있습니다.

socket.io : 브라우저만을 위한 특화된 방식으로 모듈이 구현되어 있습니다. 그래서 표준 웹소켓이 아니므로, 웹에서만 사용이 가능합니다. 하지만, 웹소켓을 지원하지 않는 브라우저는 polling을 이용해 연결합니다. 즉, 99.99% 브라우저에서 동작합니다.

이 문서는 socket.io의 내용만을 답고 있습니다.

 

[공식문서]

websocket org : https://www.websocket.org .
socket io : http://socket.io .

 

[참고문서]

express 구축 : https://nicgoon.tistory.com/234 .
javascript 웹 소켓 클라이언트 : https://nicgoon.tistory.com/227 .

 

 

1. express 구축.

이 부분은 따로 설명하지 않습니다. ws 사용법을 집중적으로 다루기 위함 입니다. express를 사용해 본 경험이 없으시다면, 참고 문서의 express 구축 ( 링크 ) 페이지를 따라 구축해 주시면 될 것 같습니다.

 

 

2. socek.io를 이용한 route 구축.

- socket.io 모듈을 설치 합니다.

$ npm i socket.io

 

- 웹소켓을 구현 합니다.

그리고 웹소켓을 처리할 모듈파일 webSocket.js 을 적당한 위치에 만들어 줍니다. 모듈 파일을 생성했다면, 아래와 같이 소스를 만들어 줍니다. (각 소스에 대한 설명은 주석을 달아 두었습니다.). socket.io의 특징은 connect, disconnect, error외에 이벤트를 직접 정의 한다는 것 입니다. 즉 어디로 받을 것인지 선택할 수 있으며, 아래소스에서는 ms라는 이벤트를 추가하였습니다.

const SocketIO = require("socket.io");

module.exports = function ( _server ) {

    // 소켓 io를 처리할 객체를 생성합니다.
    const io = SocketIO( _server, {path: '/socket.io'} );

    // 접속 처리 및 해당 클라이언트에 대한 모든 처리를 합니다.
    io.on( "connection", function( socket ){

        // 접속한 정보를 표시합니다.
        const req = socket.request;
        const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
        console.log( ip + "의 새로운 유저가 접속하였습니다." );

        // 접속이 끊어진 경우 처리를 하는 콜백 입니다.
        socket.on( "disconnect", function(  ){
            console.log("접속을 해제 하였습니다.");
        });

        // 오류가 난 경우 처리를 하는 콜백 입니다.
        socket.on( "error", function( error ){
            console.log( "error:" + error );
        });

        // 일반 메시지를 받은 경우의 처리 입니다. (ms 라는 이벤트로 클라이언트가 보낼 때 마다 이 메소드가 호출 됩니다.)
        socket.on( "ms", function( data ){

            // 클라이언트로 부터 받은 메시지를 표시합니다.
            console.log( "클라이언트로 부터 받은 메시지 : " + data );

            // 클라이언트에 구현된 echo 이벤트로 메시지를 보내어 줍니다.
            socket.emit( "echo", data );

        });
        
    });

}

 

- 구현한 웹소켓을 연결합니다.

그런다음 모듈을 http 서버에 연결해 줍니다. (express 같은 경우 listen을 통해 만들어진 서버, http의 경우 createServer 메소드로 만들어진 서버). 위에 링크된 express 구축을 따라했다면, /bin/www 파일속에 server 객체가 정의 되어 있습니다. 적당한 위치에 아래와 같이 웹소켓을 연결하도록 합니다.

const webSocket = require( "../routes/webSocket" );
webSocket( server );

 

 

3. 브라우저를 통해 웹소켓 서버에 접속해 보기.

- 지금까지 구현한 서버 실행.

$ npm start

 

- 클라이언트 만들고 호출 하기.

테스트할 웹브라우저에 아래 소스를 추가합니다. 웹에서 우리가 만든적 없는 js 파일 "/socket.io/socket.io.js" 파일을 추가하는데, express 서버에 socket.io를 구현하였다면, 자동으로 추가되어 다운로드 받을 수 있습니다. 그리고, 서버와 마찬가지로, 받는 이벤트명을 마음대로 정할 수 있습니다. 특징은 접속을 따로 하거나, 연결을 따로 하지 않습니다. 끊어지면 바로 자동으로 새 접속을 시도합니다. (언제나 연결을 유지 합니다.)

<!DOCTYPE html>
<meta charset="utf-8" />
<title>WebSocket Test</title>

<script src="/socket.io/socket.io.js"></script>
<script>

  // 웹소켓 서버를 설정합니다.
  var socket = io.connect( "http://localhost:3000" , {path: "/socket.io"} );
  socket.on( 'echo', function( data ){

    console.log( data );
    writeToScreen( "받은메시지:" + data )


  });

  // 서버로 데이터를 보내기 위한 메소드 입니다.
  function sendMessage( )
  {
    // 서버에 구현된 ms 이벤트로 메시지를 보냅니다.
    mss = document.getElementById( "message" ).value;
    socket.emit( "ms", mss );
    
  }
  // 받은 메시지를 출력합니다.
  function writeToScreen(message)
  {
    var pre = document.createElement("p");
    pre.style.wordWrap = "break-word";
    pre.innerHTML = message;
    output.appendChild(pre);
  }

</script>


<h2>소켓 io 동작을 테스트 하기 위한 node js 입니다.</h2>


<form>

    <input id="message" /> <button type="button" onclick="sendMessage();" >전송</button><br>

</form>


<div id="output"></div>

 

- 브라우저 호출.

브라우저에서 위의 소스를 실행하면, node.js에 아래와 같은 메시지를 볼 수 있습니다. (자동으로 바로연결됨)

 

- 메시지 보내기.

브라우저에서 적당한 메시지를 입력하고, 전송 버튼을 눌러 봅니다.

 

그러면 아래와 같이, 메시지를 되돌려 받았을 것 입니다.

 

서버의 상태를 보면, 아래와 같이 클라이언트가 접속했음을 확인할 수 있습니다.

 

그리고 브라우저를 닫으면, 서버에서 접속이 끊어진 메시지 또한 확인할 수 있습니다.

 

 

 

 

 

 

 

 

Posted by 창업닉군
,

그간의 html 통신은 요청에 대한 처리를 한 후 응답을 돌려주는 방식으로 동작했습니다. 우리가 흔히 챗팅 프로그램에서 사용하는 포로토콜인 TCP/IP를 사용했지만, [연결->요청에대한처리->응답->연결끊기] 사이클을 반복하며, 연결을 계속 끊기 때문에, 클라이언트의 요청은 언제든지 전달 할 수 있지만, 서버의 메시지는 클라이언트로 전달할 수 없었습니다.

그래서 나온 것이 웹소켓 이며, 서버의 구현도 간단하며 (직접 구현해도 될 정도), 클라이언트 또한 매우 간결하며, 요즘은 대부분은 웹브라우저에서 지원을 해 줍니다. 이 페이지는 ws 모듈을 이용해 웹브라우저와 node.js간의 간단한 통신을 구현한 예제를 설명하고 있습니다. 간단하지만, 이를 바탕으로 원하는 채팅 모듈을 구현할 수 있으리라 생각이 됩니다.

본 문서를 보려면, node.js 에서 express 서버의 구축 과정을 알고 있어야 합니다. (물론 아래에 관련 링크를 제공합니다.)

 

 

[공식문서]

websocket org :  https://www.websocket.org .
ws : http://www.npmjs.com/package/ws .

 

[참고문서]

express 구축 : https://nicgoon.tistory.com/234 .
javascript 웹소켓 클라이언트 : https://nicgoon.tistory.com/227 .

 

 

 

1. express 구축.

이 부분은 따로 설명하지 않습니다. ws 사용법을 집중적으로 다루기 위함 입니다. express를 사용해 본 경험이 없으시다면, 참고 문서의 express 구축 ( 링크 ) 페이지를 따라 구축해 주시면 될 것 같습니다.

 

 

 

2. ws를 이용한 route구축.

ws 모듈을 설치 합니다.

$ npm i ws

 

그리고 웹 소켓 통신을 처리할 모듈을 구현할 webSocket.js 파일을 만들어 줍니다.

모듈파일을 생성했다면, 아래와 같이 소스를 만들어 줍니다. (각 소스에 대한 설명은 주석을 달아 두었습니다.)

const wsModlue = require( "ws" );


module.exports = function( _server )
{


    // 웹소켓 서버를 생성합니다.
    const wss = new wsModlue.Server( {server:_server} );

    // 클리이언트가 접속했을 때 처리하는 이벤트 메소드를 연결합니다.
    wss.on( 'connection', function( ws, req ){

        // 사용자의 ip를 파악합니다.
        let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
        console.log( ip + "아이피의 클라이언트로 부터 접속 요청이 있었습니다." );

        // 메시지를 받은 경우 호출되는 이벤트 메소드 입니다.
        ws.on('message', function( message ){

            // 받은 메시지를 출력합니다.
            console.log( ip + "로 부터 받은 메시지 : " + message );

            // 클라이언트에 받은 메시지를 그대로 보내, 통신이 잘되고 있는지 확인합니다.
            ws.send( "echo:" + message );

        });

        // 오류가 발생한 경우 호출되는 이벤트 메소드 입니다.
        ws.on('error', function(error){
            console.log( ip + "클라이언트와 연결중 오류 발생:" + error );
        })

        // 접속이 종료되면, 호출되는 이벤트 메소드 입니다.
        ws.on('close', function(){
            console.log( ip + "클라이언트와 접속이 끊어 졌습니다." );
        })


    });


}

 

그런 다음 모듈을 http 서버에 연결해 줍니다. (express같은 경우 listen을 통해 만들어진 서버, http의 경우 createServer 메소드로 만들어진 서버). 위에 링크된  express 구축을 따라 했다면, /bin/www 파일 속에 server 객체가 정의 되어 있습니다. 적당한 위치에 아래와 같이 웹소켓을 연결하도록 합니다.

const webSocket = require("../routes/webSocket");
webSocket( server );

 

웹소켓은 익스프레스 서버와 port를 공유하므로, 따로 포트를 지정할 필요가 없습니다.

 

 

3. 브라우저를 통해 웹소켓 서버에 접속해 보기.

브라우저에서 웹소켓 이용 방법은 위의 참고 문서 [javascript 웹소켓 클라이언트 (링크)] 문서를 읽어 주세요. 이 페이지는 node js를 통한 웹소켓 서버 구축만 집중적으로 설명을 합니다.

웹소켓을 테스트하기 위한 웹 브라우저는 따로 만들지 websocket공식 사이트에 구현된 챗팅 클라이언트 페이지를 이용합니다. 웹소켓 기능을 구현할 때 일단 websocket 공식 사이트에 구헌된 챗팅 클라이언트 페이지를 이용해 구축하고, 클라이언트 부분은 이렇게 완성된 웹소켓 서버와 연결하는 식으로 구축합니다. 2가지를 한 꺼번에 구축하면, 오류 발생시 어느쪽이 문제인지 알 기 힘듭니다. 이렇게 단계별로 만든다면, 약간은 쉽게 구현이 가능합니다.

먼저 지금 까지 구현 한 서버를 동작 시켜 줍니다.

$ npm start

 

그 다음, 클라이언트로 이용할 https://www.websocket.org/echo.html 페이지로 접속합니다. 그러면 아래와 같은 화면을 볼 수 있습니다. 여기서, 로케이션 창에 주소를 입력하고 connect 버튼을 누릅니다. 이라고 입력 합니다.  위의 참고 문서 [express 구축] 을 보고 서버를 구축했다면, 주소는 ws://localhost:3000 이 됩니다.

그럼 아래와 같이 접속이 됩니다.

서버 또한 클라이언트로 부터 연결이 있었음을 알 수 있는 로그를 표시합니다.

 

다음 웹브라우저에서 서버로 메시지를 보내 보겠습니다. Message 항목에 적당한 메시지를 입력하고, Send 버튼을 누릅니다.

그럼 메시지가 가고, 서버로 부터 보낸 내용을 그대로 보낸 메아리를 받을 수 있습니다.

서버측에서도 클라이언트가 보낸 메시지의 로그를 확인할 수 있습니다.

 

마지막으로 접속을 끊어 보겠습니다. Disconnect 버튼을 누릅니다.

그리고 나면 접속이 끊어졌음을 로그로 확인할 수 있습니다.

 

물론 서버측에서도 클라이언트와 접속이 끊어졌음을 확인하는 로그를 볼 수 있습니다.

 

 

저는 웹소켓동작이 잘되었습니다. 여러분들도 잘 동작이 되었으면 좋겠습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

Posted by 창업닉군
,

nodejs 다양한 기능을 커스터마이징해 원하는 서버를 구축하거나, 원하는 앱을 만들 수 있습니다. 하지만 이 자유로움 이면에는 다른 서버 프로그램에 비해 약간(?) 많은 작업량이 존재합니다.

이 것을 보완하기 위해 Express-generator가 제공되는 데, 1분 이내에 express 서버의 셋팅이 완료됩니다. Express 서버를 구축할 때 매번 같은 모듈을 다운로드 받고 설치하는 작업을 반복하는 것 보다 Express-generator를 사용하는 것이 좋습니다.

이 문서는 기본 적으로 node js가 설치되어 있다고 가정하고 시작합니다.

 

1. Express-generator 설치

Express-generator는 다른 모듈 처럼 npm을 통해 설치되지만, 터미털(윈도우에서는 커맨드)에서 일반 명령처럼 사용되어야 하므로, 전역에 설치되어야 하며 명령은 다음 과 같습니다.

$ npm i -g express-generator

 

2. 프로젝트 폴더 만들기.

원하는 위치에 프로젝트 폴더를 만듭니다. 저는 nodejs_express_generator 라는 폴더를 만들었습니다. 저는 맥을 사용해 터미널 명령으로 만들었지만, 파인더로 만들어도 되며, 윈도에서는 command, 탐색기 뭐든 사용해도 좋습니다.

 

 

3. express 프로젝트 생성하기.

위에서 만든 폴더의 상위 폴더에서 다음과 같이 터미널 명령을 주면, express가 자동으로 셋팅됩니다. 이 때 자동으로 셋팅되었을 뿐, 관련 모듈들이 모두 설치된 상태는 아닙니다.

$ express <프로젝트폴더명> --view=pug

저는 위에서 ndejs_express_generator라는 프로젝트 폴더를 만들었으므로, [express ndejs_express_generator --view-pug]  라고 입력했습니다.

 

 

4. 관련 모듈 설치.

현재의 상태는 프로젝트 폴더속에 package.json 에 사용할 모듈 목록만 나열되어 있는 상태 입니다. npm i 명령을 주면, packag.json에 설정된 모듈을 모두 최신으로 업데이트를 자동으로 하게됩니다. 이 기능을 통해 필요한 모듈을 설치합니다.

일단 프로젝트 폴더로 이동합니다.

$ cd ndejs_express_generator

이 후 관련 모듈을 설치하기 위해 다음 명령을 입력해 줍니다.

$ npm i

설치된 모습은 아래와 같습니다.

 

5. 실행.

실행 방법은 아래와 같으며, package.json에 설정된 파일을 실행하게 되어 있으며 설정을 보면, /bin/www 파일을 실행하도록 되어 있습니다.

$ npm start

소스를 보면 시작 포트는 3000 번으로 되어 있습니다. 웹브라우저를 통해 http://localhost:3000 에 접속해 다음과 같은 화면을 볼 수 있다면 성공 입니다.

 

 

 

 

 

'Node.js' 카테고리의 다른 글

node.js socket.io 를 이용한 소켓 구현  (0) 2019.06.03
node.js ws 를 이용한 웹소켓 구현.  (6) 2019.06.02
node js 파일 업로드 multer (field)  (0) 2019.06.01
aws node js SMS 보내기  (0) 2019.05.26
node js 파일 업로드 multer  (0) 2019.05.24
Posted by 창업닉군
,

예전 multer를 이용한 파일 업로드 구현을 블로그에 게시했는데, 여러개의 필드도 업로드할 일이 있어, 사용해 보는 김에, 블로그에 남깁니다. 예전 페이지에 수정을 할 까도 생각해 봤지만, 따로 두는 것이 좋을 것 같아. (목적 별로 찾을 수 있도록) 블로그를 하나 더 남깁니다.

node js에 express 를 설치하고, multer를 이용해 업로드 처리를 하였습니다.

 

1. multer 설치.

$ npm i multer

 

2. multer 로드.

multer등 필요한 모듈을 아래와 같이 인스턴스화 해 줍니다.

var multer = require('multer');
var path = require('path');

 

 

3. multer를 초기화 합니다.

아래 코드를 참고해 multer를 생성합니다. 별 내용은 없고, 파일명을 지정하는 메소드등, 옵션 정도 설정해 초기화 합니다.
여기서는 업로드 폴더를 upload로 지정했으므로, express 서버를 시작하는 소스가 담긴 폴더에 upload 폴더를 생성해야 합니다.
대체로 "/upload" 폴더가 됩니다.

var multerNo = 1;
const uploader = multer({

  // 저장 위치 결정.
  storage: multer.diskStorage({

    destination( req, file, cb ){
      cb( null, "upload/" );
    },

    filename( req, file, cb )
    {

      const ext = path.extname( file.originalname );
      cb( null, path.basename( file.originalname, ext ) + "_" + multerNo++ + "_" + new Date().valueOf() + ext )

    }

  })


  // 저장 용량설정.
  , limit: { filesize: 5 * 1024 * 1024 }

});

 

 

4. 업로드 라우터 설정.

app.post( '/img', uploader.fields( [{name:"img_0"}, {name:"img_1"}, {name:"img_2"}, {name:"img_3"}, {name:"img_4"}] ), function( req, res, next ) {

  res.json( req.files );
  console.log( req.files );

});

 

 

5. 업로드하는 파일 폼의 html은 다음과 같습니다.

<html>

    <head>
        <title>파일 업로드 테스트를 합니다.</title>
    </head>

    <body>

        <form action="/img" method="POST" enctype="multipart/form-data">

            이미지 0 : <input type="file" name="img_0" /><br>
            이미지 1 : <input type="file" name="img_1" /><br>
            이미지 2 : <input type="file" name="img_2" /><br>
            이미지 3 : <input type="file" name="img_3" /><br>
            이미지 4 : <input type="file" name="img_4" /><br>


            <input type="submit" value="보내기" />


        </form>

    </body>

</html>

 

 

 

 

 

 

 

 

 

 

'Node.js' 카테고리의 다른 글

node.js ws 를 이용한 웹소켓 구현.  (6) 2019.06.02
Express-generator로 express 간단히 셋팅하기.  (0) 2019.06.02
aws node js SMS 보내기  (0) 2019.05.26
node js 파일 업로드 multer  (0) 2019.05.24
node.js nodemailer gmail  (0) 2019.05.24
Posted by 창업닉군
,

aws node js SMS 보내기

Node.js 2019. 5. 26. 02:37

aws를 통해 문자를 보내는 기능은 꽤나 복잡한 절차를 따릅니다. 문서는 잘 되어 있지만 선행해야할 작업이 많습니다. 구글 클라우드든 aws 든 사용방법은 매우 간단합니다. 하지만 설정을 하는데 매우 복잡합니다. 그리고 문자를 보내는 것은 무료는 아닙니다. 건당 대략 1~20원 가량 소요됩니다. 테스트를 위해 1달러 쯤 사용할 각오는 해야 하실 것 같습니다.

그럼 이제 부터 한 단계씩 차근 찬근 진행해 보도록 하겠습니다.

 

공식문서들:

인증자격받기 : https://docs.aws.amazon.com/ko_kr/sdk-for-javascript/v2/developer-guide/getting-your-credentials.html .
인증자격증명로드 : https://docs.aws.amazon.com/ko_kr/sdk-for-javascript/v2/developer-guide/loading-node-credentials-shared.html .
aws 리전 : https://docs.aws.amazon.com/ko_kr/sns/latest/dg/sms_supported-countries.html .
기본 설정 지정 : https://docs.aws.amazon.com/ko_kr/sns/latest/dg/sms_preferences.html .
Amazon SNS를 통한 SMS 메시지 전송 : https://docs.aws.amazon.com/ko_kr/sdk-for-javascript/v2/developer-guide/sns-examples-sending-sms.html .

 

1. aws 계정만들기.

여기서 계정 만드는 것에 대해서는 다루지 않고, 외국에서 결제되는 신용카드는 꼭 필요합니다. 잘 못하면 계정이 잘 만들어 지지 않을 수 있지만, 같은 카드로 계정을 여러개 만드는 것은 가능하기 때문에, 크게 걱정하실 필요는 없습니다.

 

2. 액세스 키 만들기

누구의 권한으로 SMS를 보낼 것인지 확인해야 하므로, 액세스 키를 만들어 권한 설정을 해야 합니다. 하는 방법은 클릭 몇 번으로 가능합니다. 이 작업은 공식 문서 중 인증 자격 받기를 참고 합니다.

먼저 AWS Management Console에 접근합니다. ( 링크 ). 로그인 되어 있다면, 아래와 같은 페이지가 표시될 것 입니다. 이 페이지에서 IAM을 클릭해 주도록 합니다.

Identity and Access Management 소개 페이지가 호출되면, 사용자를 선택해 줍니다.

사용자 페이지에서, 사용자를 추가할 수도 있고, 기존의 사용자를 선택할수 도 있습니다. 여기에 꼭 1명의 사용자는 존재하는 데 루트 사용자 입니다. 저는 사용자를 추가하지 않고 aws 가입시 생성된 루트 사용자를 선택했습니다. 여러분은 상황에 맞게 적당한 사용자를 클릭해 주세요.

요약 페이지가 호출되면, 보안자격증명 > 액세스 키 만들기를 차례로 눌러 줍니다.

그럼 에세스 키가 자동으로 만들어 지는데, 비밀 액세스 키는 단 1회만 확인 가능 하므로, 잊지 말고 적어두고, .csv 파일 다운로드를 눌러 다운로드 받아 주도록 합니다.

 

3. 공유 인증 파일에서 node.js에 인증 자격 증명 로드.

에세스 키를 공유인증 자격에 넣는 방법을 설정합니다. 공식 문서는, [인증자격증명로드] 을 참고하면 됩니다.

공유인증 자격 증명이 있어야할 위치는 윈도우는 C:\Users\USER_NAME\.aws\credentials 맥 또는 리눅스, 유닉스는 ~/.aws/credentials 입니다. 유닉스 시스템에서 . 문자로 시작하는 파일은 감춰 지기 때문에, 주의해야 하며, ~ 디렉터리는 로그인한 유저의 홈디렉터리를 의미합니다.

그리고 앞서 받았던 엑스키와 시크릿 액세스 키를 credentials 파일에 작성합니다.

[default]
aws_access_key_id = <YOUR_ACCESS_KEY_ID>
aws_secret_access_key = <YOUR_SECRET_ACCESS_KEY>

 

4. SNS 콜솔 열기.

SNS 콘솔을 열려면, (링크) 를 눌러도 바로 열 수 있지만, 아래와 같이 열 수도 있습니다. 콘솔 페이지에서, Simple Notification Service를 선택해 주도록 합니다.

Amazon Simple Notification Service 페이지가 열리면 개요로 시작을 선택해 콘솔로 들어 갑니다.

그리고, 대시 보드 페이지가 표시되면, 문자 보내기가 없을 것 입니다. (있을 수도 있음). 이유는 몇몇 리전만 지원을 하기 때문입니다. 리전을 한국과 가까운 일본으로 선택합니다.

그럼 문자 메시지(SMS) 항목이 나타날 텐데 눌러서 문자 메시지 대쉬 보드가 표시 될 수 있도록 합니다.

 

5. 기본 설정 지정

여기 까지 왔다면, 문자 메시지 기본 설정의 편집 버튼을 눌러 주도록 합니다.

여기서 주요한 사항은 메시지 유형과 지출 한도 입니다. 일단 트랜잭션이 고급진 보내기 인데, 저는 테스트용도 이므로 이렇게 했습니다. 여러분은 상황에 맞게 해 주시기 바랍니다.

모두 설정했다면 변경 사항 저장 버튼을 눌러 주도록 합니다.

 

6. 권한 설정.

SMS을 보낼 때, 계정에 권한을 주지 않으면, not authorized to perform: SNS:Publish 라는 오류를 만납니다. 권한만 추가해 주면 간단히 해결 되므로, 권한을 주도록 합니다.

콘솔에서 IAM 을 선택합니다. (위치는 다를 수 있습니다. 자주 사용하는 항목이 위에 표시되도록 되어 있습니다.).

사용자 탭을 눌러 위에서, 엑세스 키를 만들었던 유저를 선택해 줍니다.

여기서 권한 추가 버튼을 눌러 줍니다.

권한 추가 창이 뜨면 기존 정책 직접 연결을 선택합니다.

권한 부여 창이 뜨면 정책 필터에 sns 를 입력해 줍니다. 그럼 관련 권한 3개가 뜨는데 모두 선택해 줍니다. (하나씩 권한을 주고, 문자를 보내봤는데, 모두 오류가 났습니다. 아마 3개 다 필요한 듯 합니다.) 그 다음 검토 버튼을 눌러 줍니다.

다음 창이 뜨면 권한 추가 버튼을 눌러 권한을 추가하도록 합니다.

 

7. node js 파일 생성 및  aws-sdk 설치.

여기서 부터는 공식 문서, [Amazon SNS를 통한 SMS 메시지 전송] 을 참고해 주시면되겠습니다.

적당한 위치에 node.js를 위한 send_message.js 파일을 만들어 줍니다. 그리고, 아래와 같이 aws-sdk를 설치합니다.

$ npm i aws-sdk

 

 

8. 문자 보내기.

드디어 대망의 문자 보내기 입니다. 공식 문서의 가장 마지막의 문자 보내기를 참고해서 보내면 됩니다. (공식 문서의 옵트인 확인은, 문자를 받지 않겠다고 해당 스마트폰 사용자가 설정한 경우 입니다.)

소스는 아래와 같고, params 의 Message 항목에 보낼 메시지를 넣고, PhoneNumber에 보내는 전화 번호를 넣으면 됩니다. 주의할 점은, 전화번호는 국제 전화 번오를 넣어야 합니다. 한국같은 경우, 전화번호가 010-9999-8888 이라면, +8201099998888을 입력해야 합니다.

AWS.config.update 의 region 값은 이 문서 상단의 공식문서 [aws 리전] 을 참고해 넣으시면 되며, 이 문서는 일본에 설정하였으므로, 일본으로 넣어 테스트 했습니다.

// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set region
AWS.config.update({region: 'REGION'});

// Create publish parameters
var params = {
  Message: 'TEXT_MESSAGE', /* required */
  PhoneNumber: 'E.164_PHONE_NUMBER',
};

// Create promise and SNS service object
var publishTextPromise = new AWS.SNS({apiVersion: '2010-03-31'}).publish(params).promise();

// Handle promise's fulfilled/rejected states
publishTextPromise.then(
  function(data) {
    console.log("MessageID is " + data.MessageId);
  }).catch(
    function(err) {
    console.error(err, err.stack);
  });

저는 이 소스를 이용해 값을 알맞게 고쳐 제 폰으로 문자를 보내어 보니 아주 잘 왔습니다. 여러분은 어떠신가요?

'Node.js' 카테고리의 다른 글

Express-generator로 express 간단히 셋팅하기.  (0) 2019.06.02
node js 파일 업로드 multer (field)  (0) 2019.06.01
node js 파일 업로드 multer  (0) 2019.05.24
node.js nodemailer gmail  (0) 2019.05.24
node js OAuth 2.0 Login  (0) 2019.04.16
Posted by 창업닉군
,

node.js로 파일을 업로드 하려면 multer 라는 모듈을 다운로드 받아 사용하면 됩니다.

1. multer 설치.

$ npm i multer

 

2. multer 로드.

multer를 아래와 같이 모듈 로드해 줍니다. path는 파일 경로를 만들어 줍니다.

var multer = require('multer');
var path = require('path');

 

3. multer 초기화

아래 코드를 참고해 multer를 생성합니다. 별 내용은 없고, 저장 위치와, 파일명을 지정하는 메소드, 옵션 정도 설정해 초기화 합니다.

  const uploader = multer({

    // 저장 위치 설정.
    storage: multer.diskStorage({
      
      destination(req, file, cb){
        cb(null, "upload/");
      },

      filename( req, file, cb )
      {
        const ext = path.extname( file.originalname );
        cb( null, path.basename( file.originalname, ext ) + new Date().valueOf() + ext );
      }

    })


    // 저장 용량설정.
    , limits: { filesize: 5 * 1024 * 1024 }

  });

 

4. 업로드 라우터 설정.

위에서 설정했던 multer를 라우터에 설정하는 것 인데, single('img')는 html에서 업로드하는 필드중 img 가 파일을 업로드하는 것 임을 알려 줍니다. single은 하나의 파일만 업로드했음을 설정하는 메소드 입니다.

  app.post( '/img', uploader.single('img'), function( req, res, next ){

    // 파일 정보.
    console.log( req.file );

    // POST의 다른 정보.
    res.json( req.body );

  });

 

5. 업로드하는 파일 폼의 html은 다음과 같습니다.

<html>

    <head>
        <title>이미지 업로드</title>
    </head>


    <body>

        <form action="/img" method="POST" enctype="multipart/form-data" name="file_F" id="file_F" >

            <input type="file" name="img" />
            <input type="text" name="kkon" />

            <input type="submit" value="보내기" />

        </form>

    </body>


</html>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'Node.js' 카테고리의 다른 글

node js 파일 업로드 multer (field)  (0) 2019.06.01
aws node js SMS 보내기  (0) 2019.05.26
node.js nodemailer gmail  (0) 2019.05.24
node js OAuth 2.0 Login  (0) 2019.04.16
node.js를 이용한 iOS Push 구현하기 (requests to APNs)  (0) 2019.04.14
Posted by 창업닉군
,

node.js nodemailer gmail

Node.js 2019. 5. 24. 03:19

노드 메일러로 gmail 보내는 내용입니다. 웹상에 많이 있어 그냥 제가 해보고 되었던 웹페이지의 주소를 링크해 둡니다.

https://jizard.tistory.com/150

'Node.js' 카테고리의 다른 글

aws node js SMS 보내기  (0) 2019.05.26
node js 파일 업로드 multer  (0) 2019.05.24
node js OAuth 2.0 Login  (0) 2019.04.16
node.js를 이용한 iOS Push 구현하기 (requests to APNs)  (0) 2019.04.14
Android 결제 서버 개발  (0) 2019.04.09
Posted by 창업닉군
,

node js OAuth 2.0 Login

Node.js 2019. 4. 16. 11:10

node js는 패스포트를 이용하면, 거의 모든 SNS 로그인을 구현할 수 있습니다. 하지만, 새로운 SNS 사이트나 OAuth 2.0 기능을 가진 사이트의 요청을 필요로 할 때를 대비해 기능을 잘 알아 둘 필요가 있습니다. 그리고 모듈을 쓸 필요도 없을 만큼 매우 간단하고 쉽습니다.

[공식 문서]

구글 OAuth 2.0 OverView : https://developers.google.com/identity/protocols/OAuth2?hl=ko .
구글 OAuth 2.0 for Web Server Applications : https://developers.google.com/identity/protocols/OAuth2WebServer?hl=ko .
유저 프로필 요청 : https://developers.google.com/gmail/api/v1/reference/users/getProfile .


[주요 사이트]

Google APIs 콘솔 : https://console.developers.google.com .

 

[참고 문서]

php를 이용한 Google OAuth2.0 Login : https://nicgoon.tistory.com/208 . (전반부 구글 클라우드 콘솔 설정 숙지.).

 

1. 준비사항.

1) 본 문서를 보기전, 구글 클라우드 API에서 클라이언트 ID를 만들어야 합니다. 해당 내용은 위 참고 문서 php를 이용한 Google OAuth2.0 Login 부분을 참고 하시면됩니다. 

2) 익스프레스 서버 설정.

익스프레스를 이용해 서버를 설정하였다면, 웹을 처리를 할 라우트를 만들어 주세요 저는 아래와 같이 라우트 주소를 설정하였습니다.

구글 로그인 라우트 기본 주소 : http://localhost/oauth2
인증코드 요청 페이지 : 
http://localhost/oauth2/request_code
토큰 교환 페이지 : 
http://localhost/oauth2/exchange_token

3) 클라이언트 아이디 관련 값들.

클라이언트 아이디 : 107557211118-lpfm0l4gs5ffpas8cbjn5bp71f2hbag5.apps.googleusercontent.com
클라이언트 보안 비밀 : NaJSvmGdShGg1kkXkGdvHp4T
리디렉션 페이지 : http://localhost/oauth2/exchange_token

 

2. 라우트 기본 뼈대.

구글 로그인에서 사용되는 페이지는 최소 2개이고, 이 것을 저는 라우트를 하나 만들어 다음과 같은 코딩을 했습니다. request_code 는 인증코드 요청페이지, exchange_token 은 리디렉션 후 토큰 교환 입니다.

var express = require('express');
var router = express.Router();

/* GET home page. */
router.use('/:name', function(req, res, next) {
    


    // 요청한 파일명을 가지고 오는 메소드 입니다.
    let methodName = req.params.name;


    
    // 인증 코드를 요청한 경우 처리 분기 입니다.
    if( methodName == "request_code" )
    {
        request_code(req, res, next);
        return;                                     // 리턴 중요.
    }


    // 토큰 교환을 요청한 경우 처리 분기 입니다.
    else if( methodName == "exchange_token" )
    {
        exchange_token(req, res, next);
        return;                                     // 리턴 중요.
    }




    // 처리 방법을 확인하지 못한 경우. next 처리를 하도록 합니다.
    next();


});



// 인증 코드를 요청한 경우 처리 하는 메소드 입니다.
function request_code( req, res, next )
{
    res.setHeader( "Content-Type", "text/html; charset=UTF-8" );
    res.end( "코드 요청하는 메소드." );
}



// 토큰 교환 및 사용자 정보를 확인하는 경우 처리하는 메소드 입니다.
function exchange_token( req, res, next )
{
    res.setHeader( "Content-Type", "text/html; charset=UTF-8" );
    res.end("토큰을 교환하는 메소드.");
}





module.exports = router;

 

3. 유저 로그인 페이지 리디렉션하기.

주소를 만들때, 사용되는 옵션은 문서 처음에 있는 [구글 OAuth 2.0 for Web Server Applications] 링크를 참고 하시기 바립니다.

request_code 부분에 인증을 위한 주소를 만들어 리디렉션 하면, 사용자는 구글 로그인 창을 보게 됩니다. 코드는 아래와 같습니다.

// 인증 코드를 요청한 경우 처리 하는 메소드 입니다.
function request_code( req, res, next )
{

    // 공통적으로 사용하는 상수들 입니다.
    var scope = "https://mail.google.com/";
    var client_id = "107557211118-lpfm0l4gs5ffpas8cbjn5bp71f2hbag5.apps.googleusercontent.com";
    var client_secret = "NaJSvmGdShGg1kkXkGdvHp4T";
    var redriect_url = "http://localhost/oauth2/exchange_token";



    // 인증을 위한 주소를 만들어 줍니다.
    let reqAddr = "https://accounts.google.com/o/oauth2/v2/auth"
    + "?client_id=" + client_id
    + "&redirect_uri=" + encodeURIComponent( redriect_url )
    + "&scope=" + encodeURIComponent( scope )
    + "&state=OK"
    + "&access_type=offline"
    + "&include_granted_scopes=true"
    + "&response_type=code"
    ;

    

    res.redirect( reqAddr );


}

로그인 하고, 권한도 모두 주면, 리디렉션 페이지가 호출 됩니다. 우리는 여기서, 토큰 교환을 시도할 것 입니다.

 

4. 토큰 교환 처리.

정식 문서를 보면, 아래와 같은 값을 보내면, 토큰을 주는 것으로 되어 있습니다. 

POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https://oauth2.example.com/code&
grant_type=authorization_code

우리가 받은 토큰 값등을 활용해 위의 페이지를 만들 것 입니다.

1) 리퀘스트 설치.

페이지를 요청하는 데 리퀘스트 객체를 사용할 것 입니다. 아래와 같이 리퀘스트를 설치해 주도록 합니다.

npm i request

2) 토큰 교환.

보내야 할 데이터 중 헤더 부분은 request가 알아서 채워 줍니다. (POST로 보낼 때 당연히 적어야할 부분). 그래서 데이터부분만 적어 주면됩니다. exchange_token 메소드를 다음과 같이 변경해 보도록 합니다.

// 토큰 교환 및 사용자 정보를 확인하는 경우 처리하는 메소드 입니다.
function exchange_token( req, res, next )
{


    // 요청할 데이터를 만들어 줍니다.
    let requestOption = {
        url:'https://www.googleapis.com/oauth2/v4/token',
        method:'POST',
        form:{
            code:req.query.code,
            client_id:client_id,
            client_secret:client_secret,
            redirect_uri: redriect_url,
            grant_type: 'authorization_code'
        }
    };

    request.post( requestOption, function( err, httpResponse, body ){


        res.setHeader( "Content-Type", "text/html; charset=UTF-8" );
    

        // 오류가 난 경우 오류를 반환해 줍니다.
        if( err )
        {

            res.end("오류가 났습니다.<br>" + err);
            return;

        }

        res.end( body );


    });



}

그리고 실행하면 정상적인 경우 다음과 같은 응답을 화면에 뿌려 줍니다. (자세히 보면 Access Token을 받아 온 것을 확인할 수 있을 것 입니다.)

5. 사용자 정보 가지고 오기.

교환된 토큰으로 아래와 같이 함수를 만들어 body와 res 값을 넣어 주면, 화면에 사용자 정보를 표시해 줍니다.

// 토큰 교환 및 사용자 정보를 확인하는 경우 처리하는 메소드 입니다.
function exchange_token( req, res, next )
{


    // 요청할 데이터를 만들어 줍니다.
    let requestOption = {
        url:'https://www.googleapis.com/oauth2/v4/token',
        method:'POST',
        form:{
            code:req.query.code,
            client_id:client_id,
            client_secret:client_secret,
            redirect_uri: redriect_url,
            grant_type: 'authorization_code'
        }
    };

    request.post( requestOption, function( err, httpResponse, body ){


        res.setHeader( "Content-Type", "text/html; charset=UTF-8" );
    

        // 오류가 난 경우 오류를 반환해 줍니다.
        if( err )
        {

            res.end("오류가 났습니다.<br>" + err);
            return;

        }

        // res.end( body );
        bodyobj = JSON.parse( body );
        read_profile( res, bodyobj.access_token );


    });



}


// 유저 정보를 확인하는 메소드 입니다.
function read_profile( res, token )
{

    // 요청할 데이터를 만들어 줍니다.
    let requestOption = {
        url:'https://www.googleapis.com/gmail/v1/users/me/profile',
        headers:{
            'Authorization': 'Bearer ' + token
        },
        rejectUnauthorized:false
    };



    request.get( requestOption, function( err, httpResponse, body ){

        if( err )
        {

            res.end("사용자 정보를 확인하던 중 오류가 났습니다.<br>" + err);
            return;

        }

        // 사용자 정보를 출력합니다.
        res.end( body );

    });

}

별다은 오류가 없다면 다음과 같은 페이지를 볼 수 있을 것 입니다.

 

6. 전체 소스

익스프레서 서버에서 사용하기 위한 전체 소스 코드는 아래와 같습니다.

var express = require('express');
var router = express.Router();


var request = require('request');


// 공통적으로 사용하는 상수들 입니다.
var scope = "https://mail.google.com/";
var client_id = "107557211118-lpfm0l4gs5ffpas8cbjn5bp71f2hbag5.apps.googleusercontent.com";
var client_secret = "NaJSvmGdShGg1kkXkGdvHp4T";
var redriect_url = "http://localhost/oauth2/exchange_token";


/* GET home page. */
router.use('/:name', function(req, res, next) {
    


    // 요청한 파일명을 가지고 오는 메소드 입니다.
    let methodName = req.params.name;


    
    // 인증 코드를 요청한 경우 처리 분기 입니다.
    if( methodName == "request_code" )
    {
        request_code(req, res, next);
        return;                                     // 리턴 중요.
    }


    // 토큰 교환을 요청한 경우 처리 분기 입니다.
    else if( methodName == "exchange_token" )
    {
        exchange_token(req, res, next);
        return;                                     // 리턴 중요.
    }




    // 처리 방법을 확인하지 못한 경우. next 처리를 하도록 합니다.
    next();


});



// 인증 코드를 요청한 경우 처리 하는 메소드 입니다.
function request_code( req, res, next )
{



    // 인증을 위한 주소를 만들어 줍니다.
    let reqAddr = "https://accounts.google.com/o/oauth2/v2/auth"
    + "?client_id=" + client_id
    + "&redirect_uri=" + encodeURIComponent( redriect_url )
    + "&scope=" + encodeURIComponent( scope )
    + "&state=OK"
    + "&access_type=offline"
    + "&include_granted_scopes=true"
    + "&response_type=code"
    ;

    

    res.redirect( reqAddr );


}



// 토큰 교환 및 사용자 정보를 확인하는 경우 처리하는 메소드 입니다.
function exchange_token( req, res, next )
{


    // 요청할 데이터를 만들어 줍니다.
    let requestOption = {
        url:'https://www.googleapis.com/oauth2/v4/token',
        method:'POST',
        form:{
            code:req.query.code,
            client_id:client_id,
            client_secret:client_secret,
            redirect_uri: redriect_url,
            grant_type: 'authorization_code'
        }
    };

    request.post( requestOption, function( err, httpResponse, body ){


        res.setHeader( "Content-Type", "text/html; charset=UTF-8" );
    

        // 오류가 난 경우 오류를 반환해 줍니다.
        if( err )
        {

            res.end("오류가 났습니다.<br>" + err);
            return;

        }

        // res.end( body );
        bodyobj = JSON.parse( body );
        read_profile( res, bodyobj.access_token );


    });



}


// 유저 정보를 확인하는 메소드 입니다.
function read_profile( res, token )
{

    // 요청할 데이터를 만들어 줍니다.
    let requestOption = {
        url:'https://www.googleapis.com/gmail/v1/users/me/profile',
        headers:{
            'Authorization': 'Bearer ' + token
        },
        rejectUnauthorized:false
    };



    request.get( requestOption, function( err, httpResponse, body ){

        if( err )
        {

            res.end("사용자 정보를 확인하던 중 오류가 났습니다.<br>" + err);
            return;

        }

        // 사용자 정보를 출력합니다.
        res.end( body );

    });

}




module.exports = router;

 

 

 

 

 

 

 

 

Posted by 창업닉군
,