안녕하세요.
구글 PlayStore에서 인앱결제를 구현하는 방법을 정리하고자 합니다.
요즘은 공식 문서가 워낙 잘 발달해서 별다른 구글링이 필요 없을 수도 있지만, 구글 쪽 인앱결제는 공식문서가 난잡하여 정리해보고자 합니다.
먼저, 인앱 결제의 간단한 flow부터 알아봅시다.
그러면 백엔드 서버 측에서 구글 서버로 호출하는 API를 기반으로 흐름을 정리하자면 아래와 같습니다.
- 사용자가 앱에서 아이템을 구매한다. (결제 완료까지 된 상황)
- 앱에서는 백엔드 서버 측으로 특정 정보를 백엔드 서버로 전달한다.
- 백엔드 서버는 앱 측으로부터 전달받은 정보를 가지고 구글 서버로 해당 결제 정보가 유효한지 확인한다.
- 유효한 결제 정보라면 해당 아이템을 소비시키며, DB에 해당 아이템의 액세스 권한을 부여한다. (단, 정기 구독과 같은 비소비성 품목은 X)
아주 간략하게 요약하면 위와 같습니다만, 이제 세부적으로 알아보도록 합시다!!!
먼저, 기본 설정은 모두 마친 상태라고 가정합시다 ㅎㅎ(Google Play Console 설정 혹은 인앱결제 상품 등록 등)
https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.products/get?hl=ko
먼저, 위 API를 연동해야 합니다.
위 API는 구글 서버로부터 해당 결제 정보가 유효한지 아닌지 체크하는 기본적인 API입니다.
packageName | string 인앱 제품이 판매된 애플리케이션의 패키지 이름입니다 (예: 'com.some.thing'). |
productId | string 인앱 상품 SKU (예: 'com.some.thing.inapp1')입니다. |
token | string 인앱 상품을 구매할 때 사용자 기기에 제공된 토큰입니다. |
여기서 token은 일반적인 JWT토큰이 아닙니다!!
자 위 API를 연동하면 앱 측에서 저희 서버 엔드포인트로 호출을 하겠죠?
그러면 구글 서버에서는 응답값으로 아래와 같은 정보를 줍니다.
{
"kind": string,
"purchaseTimeMillis": string,
"purchaseState": integer,
"consumptionState": integer,
"developerPayload": string,
"orderId": string,
"purchaseType": integer,
"acknowledgementState": integer,
"purchaseToken": string,
"productId": string,
"quantity": integer,
"obfuscatedExternalAccountId": string,
"obfuscatedExternalProfileId": string,
"regionCode": string
}
위가 따지면 일반적인 영수증(receipt)이 되겠죠?
어라.... 근데 왜 가격 정보가 없지요...?
구글은 영수증에 별도의 가격 정보가 없습니다 :(
따라서, 아래 API를 조회한 결과를 DB에 저장한다거나, 매번 호출(비효율적이라고 생각)을 해야겠죠?
HTTP 요청
https://developers.google.com/android-publisher/api-ref/rest/v3/inappproducts/list?hl=ko
GET https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/inappproducts
따라서 위 엔드포인트로 요청을 보내 우리 앱의 인앱 상품이 어떤 것이 있는지, 가격 정보를 GET 합시다!
위 API를 가지고 이제 내부 DB와 관련 있는 비즈니스 로직을 짤 수 있겠죠?
자 이제 구글에서는 여기서 끝이 아닙니다 ㅎㅎ
바로 소비성 제품과 같은 경우에는 직접 소비를 해줘야 합니다!
(단, 앱에서도 가능하나 구글 측에서는 백엔드 서버에서 하기를 권장)
엥? 근데 소비성 제품과 비소비성 제품의 차이가 뭔지 감이 안 잡히실까요?
- 소비성 제품
- 일반적인 아이템, 앱 내에서 사용되는 재화(캐시 등)
- 비소비성 제품
- 평생 구독(예를 들어 한번 결제하면 더 이상 광고 시청 X)
위와 같이 정리할 수 있을 것 같습니다! 웬만하면 소비성 제품이겠죠??
HTTP 요청
https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.products/consume?hl=ko
POST https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/products/{productId}/tokens/{token}:consume
URL은 gRPC 트랜스코딩 구문을 사용합니다.
경로 매개변수
packageName | string 인앱 제품이 판매된 애플리케이션의 패키지 이름입니다 (예: 'com.some.thing'). |
productId | string 인앱 상품 SKU (예: 'com.some.thing.inapp1')입니다. |
token | string 인앱 상품을 구매할 때 사용자 기기에 제공된 토큰입니다. |
자 이제 위 API를 호출을 하고 나면 드디어 사용자는 인앱결제 -> 아이템 획득과 같은 flow를 거칠 수 있게 됩니다!
저도 구글쪽 인앱결제 구현은 처음이라 잘못된 부분이 있을 수도 있습니다!
해당 글에서는 자세히 내용을 다루지 않았기에, 충분히 공식문서를 읽으시기를 권장합니다!
다음 글에서는 구글 인앱결제 환불에 대해 알아보겠습니다!