서버 측에서 Android 앱 구매를 확인하는 방법 (앱 결제 v3의 Google Play)


96

간단한 앱이 있습니다 (계정으로 로그인해야 함). 더 많은 뉴스 콘텐츠와 같은 유료 사용자에게 몇 가지 프리미엄 기능을 제공합니다.

사용자가 내 서버 데이터베이스에이 항목을 구입했는지 기록해야합니다. 사용자 기기에 데이터 콘텐츠를 제공 할 때 사용자의 상태를 확인하고 유료 사용자에게 다른 콘텐츠를 제공 할 수 있습니다.

Google에서 제공하는 공식 Trivialdrive 샘플을 확인했지만 서버 측 확인을위한 샘플 코드를 제공하지 않습니다. 여기 내 질문이 있습니다.

  1. 샘플이 내 앱의 공개 키를 사용하여 구매를 확인하는 것을 발견했지만 좋지 않은 것 같습니다. 사용자 로그인 자격 증명과 결합 된 내 서버로 확인 프로세스를 이동하여 사용자 구매가 완료되었는지 확인한 다음 데이터베이스를 업데이트 할 수 있습니다.
  2. 또한 쿼리에 사용할 수있는 구매 API 가 있는데 , 필요한 것은 사용자의 purchaseToken을 서버에 전달하는 것입니다.

사용자의 구매를 확인하고 데이터베이스에 사용자의 상태를 표시하기 위해 어떤 방법을 취해야하는지 잘 모르겠습니다.

그리고 사용자가 Google Play 에서이 항목을 구입 한 경우 상황이 두렵습니다.하지만 그 당시 내 앱이 내 서버에 대한 인증을 시작했을 때 네트워크 연결이 중단되거나 내 서버가 중단되었습니다 . 사용자가 방금 Google Play에서 돈을 지불했지만 내 서버에 구매를 기록하지 않았습니까? 어떻게해야합니까, 어떻게이 상황을 처리 할 수 ​​있습니까?


이 질문에서 ios 플래그를 제거해야 할 것입니다.
Gustavo Guevara 2015

답변:


161

사용자가 자신의 계정에서 프리미엄 기능을 사용하도록 설정했는지 확인하는 방법을 찾고 계신 것 같습니다. 여기서부터 시작하겠습니다.

사용자에게 프리미엄 기능이 있는지 여부를 나타내는 일종의 플래그가 데이터베이스에 있는지 확인하고 계정 정보를 요청할 때 API 응답 페이로드에 포함합니다. 이 플래그는 "프리미엄 기능"에 대한 기본 권한이됩니다.

사용자가 인앱 구매를 할 때 세부 정보 (토큰, 주문 ID 및 제품 ID)를 클라이언트 (즉, 앱)에 로컬로 캐시 한 다음 API로 보냅니다.

귀하의 API는 다음을 보내야 purchaseToken받는 구글 Play 개발자 API 검증을 위해.

여기에서 몇 가지 일이 발생할 수 있습니다.

  1. 영수증이 유효하고 API가 200 Ok 상태 코드로 클라이언트에 응답합니다.
  2. 영수증이 잘못되었습니다. API가 400 Bad Request 상태 코드로 클라이언트에 응답합니다.
  3. Google Play API가 다운되었으며 API가 502 잘못된 게이트웨이 상태 코드로 응답합니다.

1. 또는 2. (2xx 또는 4xx 상태 코드)의 경우 API가 수신되었음을 표시했기 때문에 더 이상 필요하지 않기 때문에 클라이언트가 구매 세부 정보 캐시를 지 웁니다.

유효성 검사가 성공하면 (케이스 1) premium사용자에 대해 플래그를 true로 설정해야합니다 .

3. (5xx 상태 코드) 또는 네트워크 시간 초과의 경우 클라이언트는 API에서 2xx 또는 4xx 상태 코드를받을 때까지 계속 시도해야합니다.

요구 사항에 따라 다시 보내기 전에 몇 초 동안 기다리거나 앱이 다시 시작될 때마다 세부 정보를 API로 보내거나 구매 세부 정보가 앱 캐시에있는 경우 백그라운드에서 벗어날 수 있습니다.

이 접근 방식은 네트워크 시간 초과, 사용할 수없는 서버 등을 처리해야합니다.

이제 고려해야 할 몇 가지 질문이 있습니다.

구매 직후에는 어떻게해야합니까? 앱은 프리미엄 콘텐츠를 제공하기 전에 유효성 검사가 성공할 때까지 기다려야합니까, 아니면 일시적으로 액세스 권한을 부여하고 유효성 검사에 실패하면 제거해야합니까?

프리미엄 기능에 대한 임시 액세스 권한을 부여하면 대다수 사용자의 프로세스가 원활 해지지 만 API가 purchaseToken.

다른 말로하면 : 구매는 사기가 입증 될 때까지 유효합니다. 유효한 것으로 입증 될 때까지 사기입니까?

갱신을 위해 구독 기간이 다가 왔을 때 사용자에게 유효한 구독이 있는지 확인 하려면 결과 에 반환 된에 purchaseToken실행되도록 에 대한 재 검증을 예약해야합니다 .expiryTimeMillis

(가) 경우 expiryTimeMillis과거에, 당신은 설정할 수 있습니다 premiumfalse로 플래그를. 미래인 경우 새 expiryTimeMillis.

마지막으로 사용자에게 프리미엄 액세스 권한이 있는지 여부를 확인하려면 앱이 앱 시작시 또는 백그라운드에서 벗어날 때 사용자 세부 정보를 API에 쿼리해야합니다.


유료 앱의 경우 Google에서 영수증을 받으려면 어떻게해야합니까?
Merbin 조

2
안녕하세요! Google에서 구독 내역에 액세스 할 수있는 방법이 없나요? buyToken을 저장하는 순간 앱이 다운되는 경우 이미 구매 한 cubscription을 사용했던 사실의 손실을 방지하는 방법은 무엇입니까?
scythargon

2
비슷한 문제가 있습니다. .. 앱이 API에 토큰을 보내는 대신 Google 개발자 서버가 내 API에 직접 푸시 알림을 보내도록 지시하는 것이 더 안정적일까요?
Gianluca Ghettini

대한 구독 (가) 취소 후 예전의 구매 토큰 유효성 검사에 사용되는 경우 여전히 200을 반환합니다 구글 Play 개발자 API를 취소했다.
Cezar Cobuz

따라서 구독의 경우 서버에서 첫 번째 호출 후 구매 토큰과 제품 ID를 저장하고 expiryTimeMillis가 발생할 때 다른 확인 호출을 예약 (동일한 요청을 다시 실행)하도록 제안합니다. 그것이 우리가 구독 유효성을 확인하는 방법입니까? 이를 수행하는 방법에 대한 Android 지침이 있습니까? Apple은 그 좋은 관행을 매우 명확하게 설명하는 WWDC 비디오를 얻었지만 Play Store에 대해 많이 찾을 수 없습니다.
schankam

28

이것에 대한 문서는 실제로 중요한 문서를 거의 연결되지 않고 찾기가 매우 어렵게 남겨 두면서 거의 중요하지 않은 것들과 혼란스럽고 이상하게 장황합니다. 이는 Java, Python, .Net 및 NodeJS를 비롯한 Google API 클라이언트 라이브러리를 실행할 수있는 가장 널리 사용되는 서버 플랫폼에서 잘 작동합니다. 참고 : 아래 표시된대로 Python api 클라이언트 만 테스트했습니다.

필요한 단계 :

  1. Google Play 콘솔의 API 액세스 링크에서 API 프로젝트를 만듭니다.

  2. 새 서비스 계정을 만들고 생성 된 JSON 비공개 키를 저장 합니다. 이 파일을 서버로 가져와야합니다.

  3. Play Console의 서비스 계정 섹션에서 완료를 눌러 새로 고침 한 다음 서비스 계정에 대한 액세스 권한을 부여하세요.

  4. https://developers.google.com/api-client-library 에서 서버 플랫폼 용 Google API 클라이언트 라이브러리를 가져옵니다.

  5. 특정 플랫폼의 클라이언트 라이브러리를 사용하여 서비스 인터페이스를 구축하고 구매 확인 결과를 직접 읽으십시오.

당신은 할 수 없습니다 API를 클라이언트 라이브러리가 모든 것을 돌봐 등, 액세스 토큰을 새로 고침, 사용자 요청 호출을, 권한 범위 귀찮게 할 필요가있다. 구독을 확인하기위한 Python 라이브러리 사용 예는 다음과 같습니다.

먼저 다음과 같이 pipenv에 Google API 클라이언트를 설치합니다.

$ pipenv install google-api-python-client

그런 다음 서비스 계정을 인증하기 위해 비공개 키 json 파일을 사용하여 API 클라이언트 사용자 인증 정보를 설정할 수 있습니다.

credentials = service_account.Credentials.from_service_account_file("service_account.json")

이제 라이브러리를 사용하여 구독 구매 또는 제품 구매를 직접 확인할 수 있습니다.

#Build the "service" interface to the API you want
service = googleapiclient.discovery.build("androidpublisher", "v3", credentials=credentials)

#Use the token your API got from the app to verify the purchase
result = service.purchases().subscriptions().get(packageName="your.app.package.id", subscriptionId="sku.name", token="token-from-app").execute()
#result is a python object that looks like this ->
# {'kind': 'androidpublisher#subscriptionPurchase', 'startTimeMillis': '1534326259450', 'expiryTimeMillis': '1534328356187', 'autoRenewing': False, 'priceCurrencyCode': 'INR', 'priceAmountMicros': '70000000', 'countryCode': 'IN', 'developerPayload': '', 'cancelReason': 1, 'orderId': 'GPA.1234-4567-1234-1234..5', 'purchaseType': 0}

Play 개발자 API의 플랫폼 서비스 인터페이스에 대한 문서는 찾기 쉬운 방법으로 링크되어 있지 않습니다. 일부는 찾기 가 매우 어렵습니다 . 내가 찾은 인기있는 플랫폼에 대한 링크는 다음과 같습니다.

파이썬 | 자바 | .NET | PHP | NodeJS (Github TS) | Go (Github JSON)


5
동의합니다. 문서는 끔찍합니다 ... Firebase (Firestore) 및 Cloud 기능을 백엔드로 사용하여이 작업을 수행하는 방법에 대한 아이디어가 있습니까?
Jeff Padgett

Cloud 함수가 NodeJS에있는 경우 위의 NodeJS 링크를 사용하여 API 클라이언트 라이브러리를 작동시킬 수 있습니까?
Dhiraj Gupta

17

PHP 용 Google API 클라이언트 라이브러리 사용의 전체 예 :

  1. Marc의 답변 ( https://stackoverflow.com/a/35138885/1046909)에 설명 된대로 Google 프로젝트를 설정 하고 서비스 계정에 대한 Google Play 에 액세스합니다 .

  2. 라이브러리 설치 : https://developers.google.com/api-client-library/php/start/installation .

  3. 이제 다음과 같은 방법으로 영수증을 확인할 수 있습니다.

    $client = new \Google_Client();
    $client->setAuthConfig('/path/to/service/account/credentials.json');
    $client->addScope('https://www.googleapis.com/auth/androidpublisher');
    $service = new \Google_Service_AndroidPublisher($client);
    $purchase = $service->purchases_subscriptions->get($packageName, $productId, $token);

    그 후 $ purchase는 Google_Service_AndroidPublisher_SubscriptionPurchase의 인스턴스입니다 .

    $purchase->getAutoRenewing();
    $purchase->getCancelReason();
    ...

이것은 작동하지 않습니다. (401) 로그인이 필요하며 setAuthConfig가 서비스 계정 자격 증명을 수락하지 않습니다. json
Raulnd

이것은 나를 위해 일했습니다 putenv ( 'GOOGLE_APPLICATION_CREDENTIALS = credentials.json'); $ client = new Google_Client (); $ client-> useApplicationDefaultCredentials (); $ client-> addScope ( ' googleapis.com/auth/androidpublisher' ); $ service = new Google_Service_AndroidPublisher ($ client); $ purchase = $ service-> purchases_products-> get ($ packageName, $ productId, $ token); var_dump ($ purchase);
Raulnd 2011

이것은 인앱 결제의 경우입니다. 사용자가 인앱 대신 Play 스토어에서 내 앱을 구매할 때마다 내 데이터베이스에 orderId를 가져 오려면 어떻게해야합니까?
Ankesh kumar Jaisansaria

stackoverflow.com/questions/48662787/… 이 질문을 참조하십시오. 이 질문에 대한 답을 찾고 있습니다. 이것은 또한 활성 현상금을 가지고
Ankesh 쿠마 Jaisansaria에게

@MingalevME 토큰 형식이 유효하지 않고 PHP에 치명적인 오류가 발생하면 어떻게이 오류를 포착합니까?
alexx0186

12

Purchases.subscriptions 를 사용해 볼 수 있습니다 : 서버 측 가져 오기 . packageName, subscriptionId 및 token을 매개 변수로 사용하며 인증이 필요합니다 .

사용자의 구독 구매가 유효한지 확인하고 만료 시간을 반환합니다.

성공하면이 메서드는 응답 본문에 Purchases.subscriptions 리소스 를 반환합니다 .


9
승인을받는 데 심각한 문제가 있습니다.

8
진지하게. 일부 앱에 대한 구매가 얼마나 중요한지에 대해서는 지원 및 문서가 부족합니다. 다음은 서버에서 수행해야하는 작업입니다 : github.com/google/… . 자세한 정보 : stackoverflow.com/questions/35127086/…
user

0

나는이 걱정에 대답한다

네트워크 연결이 끊어 졌거나 내 서버가 다운되었습니다. 사용자가 방금 Google Play에서 돈을 지불했지만 내 서버에 구매를 기록하지 않았습니까? 어떻게해야합니까, 어떻게이 상황을 처리 할 수 ​​있습니까?

상황은 다음과 같습니다.

사용자가 구글 플레이 서비스를 이용하여 'abc'아이템을 구매 한 경우-> 반품 확인-> 인터넷 연결이 안되는 등의 이유로 서버 확인에 실패합니다.

해결책은 다음과 같습니다.

클라이언트 측에서는 'Google Wallet'버튼을 표시하기 전에 'abc'항목이 이미 소유되어 있는지 확인합니다.

  • 그렇다면 서버에서 다시 확인하십시오.
  • 아니라면 'Google 지갑'버튼을 표시합니다.

구매 구매 = mInventory.getPurchase ( 'abc');

if (purchase != null) // Verify with server 

else // show Google Wallet button

https://developer.android.com/google/play/billing/billing_reference.html#getSkuDetails


4
서버에서 확인하는 것이 앱에서 확인하는 것보다 더 안전한 이유를 모르겠습니다. 그것을 제거하거나 서버의 응답이 "OK"가 여부 검사하는 응용 프로그램의 코드 반전 여전히 가능 그래서 하루의 끝에서이 기능을 해제 응용 프로그램입니다
지안루카 Ghettini

2
@GianlucaGhettini 왜냐하면 때로는 서버가 앱이 아닌 구매 한 서비스를 제공하는 것이기 때문에 앱이 리버스 엔지니어링 될 수 있고 약간의 어려움으로 인해 검증 프로세스가 해킹 될 수 있습니다.
Mohyaddin Alaoddin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.