안드로이드 인앱 결제 영수증 검증(Python)

옥영진·2020년 7월 10일
0

1. 구글 개발자 API 사용 설정

아래 링크를 통해 구글 개발자 API를 사용할 수 있도록 설정한다.
https://ndb796.tistory.com/309

서비스 계정을 생성하고, 재무 데이터 보기 권한까지 추가를 완료한다.

2. 인앱 상품 등록

Google Play Console에 접속하여 애플리케이션 등록 후 해당 애플리케이션 인앱 상품을 등록한다.(관리되는 제품, 구독)

3. 인앱 결제 영수증 검증 코드

다음은 앱에서 결제 후 구글에서 제공되는 영수증 데이터이다. 위는 관리되는 제품, 아래는 구독 상품 영수증이다.

{
  "orderId":"GPA.0000-...",
  "packageName":"com.앱 패키지 이름",
  "productId":"gas",
  "purchaseTime":1594086304413,
  "purchaseState":0,
  "purchaseToken":"tokenvalue.A1-bbbbb...",
  "acknowledged":false
}

 {
   "orderId":"GPA.1111-...",
   "packageName":"com.앱 패키지 이름",
   "productId":"subscription_1",
   "purchaseTime":1594343716114,
   "purchaseState":0,
   "purchaseToken":"tokenvalue.A0-aaaaa...",
   "autoRenewing":true,
   "acknowledged":false
 }

위 json 데이터를 서버로 전송하여 이를 검증하는 Python 코드이다. 검증할 때는 packageName, productId, purchaseToken 값만 있으면 가능하다.

from oauth2client.service_account import ServiceAccountCredentials
from httplib2 import Http
from googleapiclient.discovery import build

def verify(packageName, productId, purchaseToken):
    scopes = ['https://www.googleapis.com/auth/androidpublisher']

    credentials = ServiceAccountCredentials.from_json_keyfile_name(
    	# 사용자 계정 key 값 파일 경로(.json 파일),
        scopes)

    http_auth = credentials.authorize(Http())

    androidpublisher = build('androidpublisher', 'v3', http=http_auth)

    try:
        if # 관리되는 제품일 경우:
            product = androidpublisher.purchases().products().get(productId=productId,
                                                                  packageName=packageName,
                                                                  token=purchaseToken
                                                                  )
            purchase = product.execute()
            print(purchase)

        elif # 구독 상품일 경우:
            subscription = androidpublisher.purchases().subscriptions().get(packageName=packageName,
                                                                            subscriptionId=productId,
                                                                            token=purchaseToken
                                                                            )
            purchase = subscription.execute()
            print(purchase)

    except Exception as e:
        print('에러')

성공적으로 검증이 완료되면 HTTP 200 OK를 반환하며 purchase 변수에는 다음과 같은 json 데이터가 반환되어 저장되어 있다. 만약 위변조된 토큰 값을 가지고 검증 요청을 하면 400번대 에러 메세지를 응답 받는다.

{
  "acknowledgementState": 1,
  "consumptionState": 1,
  "developerPayload": "",
  "kind": "androidpublisher#productPurchase",
  "orderId": "GPA.0000-...",
  "purchaseState": 0,
  "purchaseTimeMillis":
  "1594086304413",
  "purchaseType": 0
}
 
{
  "acknowledgementState": 1,
  "autoRenewing": true,
  "cancelReason": 0,
  "countryCode": "KR",
  "developerPayload": "",
  "expiryTimeMillis": "1594345930858",
  "kind": "androidpublisher#subscriptionPurchase",
  "orderId": "GPA.1111-...",
  "priceAmountMicros": "1000000000",
  "priceCurrencyCode": "KRW",
  "purchaseType": 0,
  "startTimeMillis": "1594343716114"
}
profile
안녕하세요 함께 공부합시다

1개의 댓글

comment-user-thumbnail
2022년 6월 9일

product.execute()에서 제대로 처리가 안 되는데 이유를 알 수 있을까요?

답글 달기