유니티/구글 플레이 콘솔

[유니티] 구글 IAP 영수증 검증 서버 구현 feat. firebase 호스팅

VicGameStudio_Choi 2022. 12. 12. 01:31

영수증 검증 서버 구현 이슈가 추가되었다. 참고바란다.

아래 글을 보고 따라하다 보면 막히는 이슈가 아래 링크에 정리되어 있음.

 

https://victorygamestudio.tistory.com/22

 

[유니티] IAP 검증 서버 이슈

지난 번 IAP 검증 서버 구현에 이은 이슈를 정리해보려고 한다. https://victorygamestudio.tistory.com/20 [유니티] 구글 IAP 영수증 검증 서버 구현 feat. firebase 호스팅 IAP 로 구현까지 다 진행하고.. 영수증 검

victorygamestudio.tistory.com


 

IAP 로 구현까지 다 진행하고.. 영수증 검증을 하기 위해 이것저것 찾아보던 중..

제대로 된 글이 있어서 참고해서 진행하였다.

 

영수증 검증을 하기 위한 방법은 여러 가지가 있지만, 이 글에서는 검증 서버를 구현하는 방식으로 설명한다.

 

영수증 검증에 도대체 왜 서버가 필요한지 의문일 것이다.

사실 나도 굉장한 의문이었는데... 기본적으로 결제 시스템 로직상 구글 결제 서버를 통하지 않고 결제된다.

따라서.. 검증되지 않는 영수증으로 구매가 가능하다.

 

그렇다면.. 왜 결제 서버를 통하지 않는 것일까?? 

 

그 이유는 클라이언트 단에서 구글 결제 서버를 거치게 될 경우에 메모리 변조나 코드 변조에 의해서 오용될 가능성이 

크다는 것이 내 판단 이유다.

 

따라서, 서버 컴퓨터에 배포된 우리의 서버는 유저들에게 배포되는 클라이언트 게임보다 훨씬 보안상 안전할 것이다!!!

만약, 클라단에서 다이렉트로 구글 결제 서버를 통해 HTTP 로 통신하게 될 경우.. 얼마나 많은 오용이 될지 상상도 안된다...

 

더 자세한 내용은 아래 링크에 있다.

 

https://blog.totu.dev/2016/02/10/google-oauth/

 

구글 인앱 결제 검증 웹 서비스 만들기

Node.js로 구글 결제 검증 웹 서비스 구현

blog.totu.dev

 

위의 결제 검증 웹 서버의 경우에는 호스팅되지 않은 로컬 서버에서 진행된다.

하지만, 우리는 직접 앱을 배포해서 리얼 환경에서 결제 검증을 진행할 것이기 때문에 외부에서도 접근 가능한 서버 구현이 필요하다. 물론, 집 컴퓨터를 24시간 돌리면서 서버컴처럼 사용해도 되지만.. 솔직히 에바다.. ㅎㅎ

 

따라서 Firebase 웹 호스팅으로 진행한다.

 

1. 파이어베이스 호스팅

 

https://victorygamestudio.tistory.com/19

 

[Firebase] 파이어베이스 웹 호스팅

이번 시간에는 Firebase 웹 호스팅을 해보도록 하겠다... 갑자기 유니티 개발하다가 Firebase 웹 호스팅을 하는 이유는.. 구글 인앱 결제 시, 영수증 검증을 위해서 서버에서 별도의 권한을 얻어서, 구

victorygamestudio.tistory.com

 

nodejs 로 코딩을 진행하게 되는데.. 하나도 모른다는 것이 문제다..;;

하지만.. 진행할 수 있었던 이유는 위위에 있는 링크에서 코드 구현이 다 끝나있어서 복붙만하면 되었기 때문이다..

 

2.  API 구현

우리는 게임 클라이언트에서 HTTP 통신으로 영수증 검증을 요청해야한다.

파이에베이스에서는 해당 HTTP 를 받아서 처리하는 기능이 Functions 기능이다.

Functions 기능을 이용하기 위해서는 Blaze 로 요금제를 올려야한다.

따라서 만약, Firebase 호스팅을 이용해서 영수증 검증 서버를 구현하려면 Blaze 요금제 변경이 필요하다.

그런데.. 찾아보니 월 200만회의 요청이 들어와야 이후에 0.4 달러인가? 비용이 첨부된다.. ㄷㄷㄷ 결제를 200만회가 들어오면 어차피 부자이니 크게 상관 없을 듯?

 

먼저 내용이 길기 때문에 아래 링크를 그래도 따라해보자.

 

https://medium.com/boca-code/the-basic-process-is-that-we-will-use-firebase-cloud-functions-to-create-a-single-function-app-13ba3b852077

 

The basic process is that we will use Firebase cloud functions to create a single function, app…

We will use Firebase cloud functions to create a single function, app, which will run our Express API. We will redirect all routes to...

medium.com

 

위의 링크를 따라할 때 주의 사항은 모듈 설치를 Functions 에서 해야한다.

우리는 Firebase 호스팅을 이용하기 때문에 Functions 라는 항목을 선택해서 진행했다.

nodejs api 호출을 위해서는 다양한 모듈이 필요한데 이런 모듈들은 Functions 내부에서 설치를 진행해야 한다.

 

즉, npm install googleapis 등과 같은 모듈 설치는 cd functions 내부까지 들어와서 진행해야한다.

 

 

3. 코드 구현

2번 작업이 끝나면, 외부에서 api 처럼 호출되는 것에 응답을 보내줄 수 있게 됬다.

따라서 링크를 보며, 코드를 그대로 따라해보자!

 

https://blog.totu.dev/2016/02/10/google-oauth/

 

구글 인앱 결제 검증 웹 서비스 만들기

Node.js로 구글 결제 검증 웹 서비스 구현

blog.totu.dev

 

주의할 점은 코드내에서 사용하는 모듈들을 모두 설치해주어야 한다.. 

 

Functions 경로로 이동해서 모듈을 설치한다.

 

// functions 경로까지 들어가서 
// npm install request --save
// npm install readline --save
// npm install googleapis --save

Fuctions 내부에 node_modules 폴더 안에 설치한 모듈들이 있는지 꼭 체크한다!!!!

코드 구현 중에 아래의 이슈를 만날 수 있다.

 

https://stackoverflow.com/questions/49866493/google-oauth-typeerror-cannot-read-property-oauth2-of-undefined

 

Google OAuth TypeError: Cannot read property 'OAuth2' of undefined

I am trying to build an App using Google Calendar API. I am following the guide:https://developers.google.com/calendar/quickstart/nodejs. However, when, I run the project I am getting the below err...

stackoverflow.com

그렇다면 아래 사진처럼 const google 이 아니라 const {google} 로 수정해준다.

 

 

이렇게 했을 경우.. 구현은 끝났지만 영수증 검수 서버의 경우 영수증 검증을 위해 권한이 필요했다.

따라서, 해당 토큰을 Refresh 해주는 코드가 들어가있다.

 

setInterval 부분이 30분마다 RefershIABTokenInterval 메서드를 호출시켜준다.

하지만, 파이어베이스 호스팅에서는 이런 스케줄링은 사용할 수 없다.

직접 사용해보면 알겠지만;; 10분정도 반복하다가 스케줄링이 강제 종료되어버린다..;;

 

react native - Firebase Function stops interval after 10 min - Stack Overflow

 

Firebase Function stops interval after 10 min

I have a timer function on firebase functions. My code below exports.timecontroller = functions.region('europe-west1').firestore.document("DigitalTargets/{digitalTargetID}").onCreate((snap,

stackoverflow.com

 

스택 오버플로우에 똑같은 사례가 있다..

따라서 우리는

functions.pubsub.schedule

이라는 친구를 사용해야만 한다.

 

https://firebase.blog/posts/2019/04/schedule-cloud-functions-firebase-cron

 

The Firebase Blog

News, tutorials, and updates from the Firebase team.

firebase.blog

 

따라서 나는 위의 기존 코드의 interval 부분을 사용하지 않고, 그냥 웹 서비스가 시작할 때 스케줄링을 등록해버렸다.

하지만. 이렇게 할 경우 초기에 한 번은

/googleiab/token/request
 
 
경로로 호출해서 토큰을 받아줘야되지 싶다.
그 이유는 리프레쉬를 위해서는 tokenStorage 가 이미 초기화가 되어있어야하기 때문이다..
// 전역에 사용함.
// 기존 request 내부에 if 문에서 처리하는 것이 아님.
exports.scheduledFunction = functions.pubsub.schedule('every 30 minutes').onRun((context) => {
    console.log("RefreshIABTokenInterval Start");

    let url = 'https://www.googleapis.com/oauth2/v4/token';
    let payload = {
        refresh_token: tokenStorage.refresh_token,
        grant_type: 'refresh_token',
        client_id: client_id,
        client_secret: client_secret
    };

    request.post(url, { form: payload }, function (error, response, body) {
        console.log("RefreshIABTokenInterval Result");

        if (error) {
            console.log("RefreshIABTokenInterval Error!!");
            return;
        }

        console.log("RefreshIABTokenInterval Finish!!");

        let parseBody = JSON.parse(body);
        tokenStorage.access_token = parseBody.access_token;
        tokenStorage.token_type = parseBody.token_type;
        tokenStorage.expires_in = parseBody.expires_in;
    });
});

 

파이어베이스 프로젝트에 들어가면 로그를 볼 수 있다.

 

글을 쓰고 있는 현재 시간에도 30분마다 한번씩 토큰을 리프레쉬해주고 있다.