Sunucu tarafında Android uygulaması satın alma işlemi nasıl doğrulanır (google play in app faturalandırma v3)


105

Basit bir uygulamam var (kullanıcının hesabıyla oturum açması gerekiyor). Ücretli kullanıcılar için daha fazla haber içeriği gibi bazı premium özellikler sağlıyorum.

Kullanıcının bu öğeyi sunucu veritabanımda satın alıp almadığını kaydetmem gerekiyor. Kullanıcının cihazına veri içeriği sağladığımda, kullanıcının durumunu kontrol edebilir ve ücretli kullanıcı için farklı içerik sağlayabilirim.

Google tarafından sağlanan resmi Trivialdrive örneğini kontrol ettim, sunucu tarafı doğrulama için herhangi bir örnek kod sağlamıyor, işte sorularım.

  1. Satın alma işleminin tamamlanıp tamamlanmadığını görmek için doğrulama işlemini kullanıcı oturum açma kimlik bilgileriyle birlikte sunucuma taşıyabileceğimi ve ardından veritabanını güncelleyebileceğimi düşünüyorum.
  2. Ayrıca sorgulamak için kullanabileceğim satın alma API'si var, ihtiyacım olan şey kullanıcının PurchToken'ı sunucuya iletmek.

Kullanıcının satın alma işlemini doğrulamak ve veritabanımdaki kullanıcının durumunu işaretlemek için hangi yöntemi kullanmam gerektiğinden emin değilim, belki her ikisi de?

Ve korkarım ki, bir kullanıcı bu öğeyi google play'den satın aldıysa, ancak nedense, tam o sırada, uygulamam sunucumda doğrulamayı başlattığında , ağ bağlantısı kesildi veya kendi sunucum çöktü , kullanıcı parayı google play'de ödedi ancak satın alma işlemini sunucuma kaydetmedim mi? Ne yapmalıyım, bu durumla nasıl başa çıkabilirim.


Yanıtlar:


163

Görünüşe göre aradığınız, kullanıcının hesabında premium özellikleri etkinleştirip etkinleştirmediğini kontrol etmenin bir yolu, bu yüzden başlayacağım yer burası;

Veritabanınızda, kullanıcının premium özelliklere sahip olup olmadığını gösteren bir bayrak olduğundan emin olun ve hesap bilgisi isterken bunu API yanıt yüküne dahil edin. Bu bayrak, "premium özellikler" için birincil yetkiniz olacaktır.

Bir kullanıcı bir uygulama içi satın alma yaptığında, ayrıntıları (jeton, sipariş kimliği ve ürün kimliği) istemcide (yani uygulama) yerel olarak önbelleğe alın ve ardından API'nize gönderin.

API sonra göndermelidir purchaseTokeniçin Google Play Geliştirici API'si doğrulama için.

Buradan birkaç şey olabilir:

  1. Makbuz geçerlidir, API'niz müşteriye 200 Ok durum koduyla yanıt verir
  2. Makbuz geçersiz, API'niz istemciye 400 Hatalı İstek durum kodu ile yanıt veriyor
  3. Google Play API çalışmıyor, API'niz 502 Hatalı Ağ Geçidi durum koduyla yanıt veriyor

1. veya 2. (2xx veya 4xx durum kodları) durumunda, istemciniz satın alma ayrıntılarının önbelleğini temizler çünkü API, alındığını belirttiğinden artık buna ihtiyaç duymaz.

Başarılı bir doğrulama (durum 1.) üzerine, premiumkullanıcı için bayrağı true olarak ayarlamalısınız .

3. (5xx durum kodu) veya bir ağ zaman aşımı durumunda, istemci API'nizden bir 2xx veya 4xx durum kodu alana kadar denemeye devam etmelidir.

Gereksinimlerinize bağlı olarak, tekrar göndermeden önce birkaç saniye bekletebilir veya uygulama yeniden başlatıldığında veya satın alma ayrıntıları uygulama önbelleğinde mevcutsa arka plandan çıktığında yalnızca ayrıntıları API'nize gönderebilirsiniz.

Bu yaklaşım, ağ zaman aşımlarına, sunucuların kullanılamaz olmasına vb. Dikkat etmelidir.

Şimdi göz önünde bulundurmanız gereken birkaç soru var:

Bir satın alma işleminden hemen sonra ne olmalı? Uygulama, premium içerik sağlamadan önce doğrulama başarılı olana kadar beklemeli mi yoksa geçici olarak erişim vermeli ve doğrulama başarısız olursa onu kaldırmalı mı?

Premium özelliklere geçici erişim izni vermek, kullanıcılarınızın çoğunluğu için süreci kolaylaştırır, ancak API'niz purchaseToken.

Başka bir şekilde ifade etmek gerekirse: Satın alma, sahtekarlık olduğu kanıtlanana kadar geçerlidir veya; geçerliliği kanıtlanana kadar hileli mi?

Yenileme için abonelik dönemi geldiğinde kullanıcının hala geçerli bir aboneliğe sahip olup olmadığını belirlemek için , sonuçta döndürülen bir purchaseTokençalıştırma için yeniden doğrulama planlamanız gerekecektir .expiryTimeMillis

Eğer expiryTimeMillisgeçmişte, sen ayarlayabilirsiniz premiumYANLıŞ olarak bayrak. Gelecekteyse, yeni için yeniden planlayın expiryTimeMillis.

Son olarak, kullanıcının premium erişime sahip olduğundan (veya olmadığından) emin olmak için uygulamanız, uygulamanın başlatılmasıyla ilgili kullanıcı ayrıntıları veya arka plandan çıktığında API'nizi sorgulamalıdır.


Ücretli uygulama için makbuzu google'dan nasıl alacağım?
Merbin Joe

2
Selam! Google'da abonelik geçmişine erişmenin bir yolu yok mu? PurchToken depolanma anında uygulama çökerse, halihazırda satın alınmış olan cubscription gerçeğinin kaybolması nasıl önlenir?
scythargon

2
Benzer bir sorunum var .. uygulamanın jetonu api'ye göndermesine izin vermek yerine, google geliştirici sunucusuna bunu doğrudan api'me bir push bildirimiyle yapması için talimat vermek daha güvenilir olmaz mı?
Gianluca Ghettini

İçin abonelikler iptal edildikten sonra aynı eski alım belirteci doğrulama için kullanılırsa hala 200 dönecektir Google Play Geliştirici API'si iptal edildi.
Cezar Cobuz

Dolayısıyla, bir abonelik için, sunucudaki ilk aramadan sonra satın alma jetonunu ve ürün kimliğini saklamamızı ve expiryTimeMillis olduğunda başka bir doğrulama çağrısı planlamamızı (aynı isteği yeniden çalıştırmamızı) öneriyorsunuz? Aboneliğin geçerliliğini bu şekilde mi doğrulamamız gerekiyor? Bunun nasıl yapılacağına dair Android'den herhangi bir yönerge var mı? Apple, bunun iyi uygulamasını oldukça açık bir şekilde açıklayan ancak Play Store hakkında fazla bir şey bulamayan bir WWDC videosu aldı.
schankam

31

Bu konudaki belgeler kafa karıştırıcı ve neredeyse önemsiz olan şeylerle garip bir şekilde ayrıntılıdır, ancak gerçekten önemli belgeleri neredeyse bağlantısız ve bulunması çok zor. Bu, diğerleri arasında Java, Python, .Net ve NodeJS dahil olmak üzere google api istemci kitaplıklarını çalıştırabilen en popüler sunucu platformunda harika çalışmalıdır. Not: Aşağıda gösterildiği gibi yalnızca Python api istemcisini test ettim.

Gerekli adımlar:

  1. Google Play konsolunuzdaki API Erişimi bağlantısından bir API projesi oluşturun

  2. Yeni bir hizmet hesabı oluşturun, oluşturulan JSON özel anahtarını kaydedin . Bu dosyayı sunucunuza götürmeniz gerekecek.

  3. Yenilemek ve ardından hizmet hesabına erişim vermek için Play konsolunun hizmet hesabı bölümünde Bitti'ye basın

  4. Https://developers.google.com/api-client-library adresinden sunucu platformunuz için bir Google api istemci kitaplığı edinin.

  5. Bir hizmet arayüzü oluşturmak için belirli platformunuzun müşteri kitaplığını kullanın ve satın alma doğrulamanızın sonucunu doğrudan okuyun.

Sen do not api istemci kütüphanesi her şeyi halleder, vb erişim belirteçleri, ferahlatıcı özel istekleri arama yapmak, yetki kapsamları ile rahatsız gerekir. Bir aboneliği doğrulamak için bir python kitaplığı kullanım örneği:

Öncelikle, google api istemcisini pipenv'inize şu şekilde yükleyin:

$ pipenv install google-api-python-client

Ardından, hizmet hesabının kimliğini doğrulamak için özel anahtar json dosyasını kullanarak api istemcisi kimlik bilgilerini ayarlayabilirsiniz.

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

Artık abonelik satın alımlarını veya ürün satın alımlarını kitaplığı kullanarak doğrudan doğrulayabilirsiniz.

#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}

Oyun geliştirici API'si için platform hizmeti arayüzü dokümantasyonu, bulması kolay bir şekilde bağlantılı değildir, bazıları için bulması düpedüz zor . İşte bulduğum popüler platformların bağlantıları:

Python | Java | .NET | PHP | NodeJS (Github TS) | Git (Github JSON)


7
Kabul ediyorum, dokümantasyon korkunç ... Bunun Firebase (Firestore) ve Cloud işlevleriyle arka uç olarak nasıl yapılacağına dair herhangi bir fikriniz var mı?
Jeff Padgett

Bulut işlevleriniz NodeJS'de ise, API İstemci kitaplığını çalıştırmak için yukarıdaki NodeJS bağlantısını kullanabilirsiniz.
Dhiraj Gupta

17

PHP için Google API İstemci Kitaplığı kullanımının tam örneği :

  1. Kurulum Google Project ve erişimin Google Play sizin için hizmet hesabı burada Marc'ın yanıt açıklandığı gibi https://stackoverflow.com/a/35138885/1046909 .

  2. Kitaplığı kurun: https://developers.google.com/api-client-library/php/start/installation .

  3. Artık makbuzunuzu aşağıdaki şekilde doğrulayabilirsiniz:

    $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);
    

    Bu $ satın alma işleminden sonra Google_Service_AndroidPublisher_SubscriptionPurchase örneği

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

Bu çalışmıyor, (401) Oturum Açma Gerekiyor mesajı almaya devam ediyorum ve setAuthConfig hizmet hesabı kimlik bilgilerini kabul
etmiyor

Bu benim için çalıştı putenv ('GOOGLE_APPLICATION_CREDENTIALS = kimlik bilgileris.json'); $ müşteri = yeni Google_Client (); $ istemci-> useApplicationDefaultCredentials (); $ istemci-> addScope (' googleapis.com/auth/androidpublisher' ); $ hizmet = yeni Google_Service_AndroidPublisher ($ müşteri); $ satın alma = $ hizmet-> satın alma_ürünleri-> get ($ paketAdı, $ ürün kimliği, $ belirteç); var_dump ($ satın alma);
Raulnd

Bu şey, uygulama içi faturalama durumunda. Kullanıcı uygulamamı inapp yerine play store'dan satın aldığında orderId'i veritabanıma almak istersem ne olur?
Ankesh kumar Jaisansaria

stackoverflow.com/questions/48662787/… Lütfen bu soruya bakın. Bu sorunun cevabını arıyorum.
Bunda

@MingalevME Ya belirteç biçimi geçersizse ve PHP ölümcül bir hata alırsa, bu hatayı nasıl yakalayabilirim?
alexx0186

12

Purchases.subscriptions: sunucu tarafını kullanmayı deneyebilirsiniz . Parametre olarak packageName, subscriptionId ve token'ı alır ve yetkilendirme gerektirir .

Bir kullanıcının abonelik satın alımının geçerli olup olmadığını kontrol eder ve sona erme süresini döndürür.

Başarılı olursa, bu yöntem yanıt gövdesinde bir Purchases.subscriptions kaynağı döndürür .


9
Yetkilendirmeyi çalıştırmak için ciddi sorunlar yaşıyorum.

9
Ciddi anlamda. Bazı uygulamalar için satın alımların ne kadar kritik olduğu konusunda destek ve belgeler anlamsızdır. Sunucuda yapmanız gereken şudur : github.com/google/… . Daha fazla bilgi burada: stackoverflow.com/questions/35127086/…
kullanıcı

0

Bu endişeye cevap veriyorum

ağ bağlantısı kesildi veya kendi sunucum arızalı, kullanıcı parayı google play'de ödedi ancak satın alma işlemini sunucuma kaydetmedim mi? Ne yapmalıyım, bu durumla nasıl başa çıkabilirim.

Durum şudur:

Kullanıcı google play hizmetini kullanarak 'abc' öğesini satın alır -> Tamam'a dön -> İnternet bağlantısı olmaması gibi bazı nedenlerden dolayı sunucuyla doğrulama başarısız olur.

Çözüm şudur:

İstemci tarafında, 'Google Cüzdan' düğmesini göstermeden önce, 'abc' öğesinin zaten sahip olup olmadığını kontrol edin.

  • evet ise, sunucuyla tekrar doğrulayın
  • hayır ise, "Google Cüzdan" düğmesini gösterin.

Satın alma satın alma = 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
Neden sunucuda doğrulamanın uygulamada doğrulamaktan daha güvenli olduğunu anlamıyorum. Günün sonunda, özelliklerin kilidini açan uygulama budur, böylece sunucu yanıtının "Tamam" olup olmadığını kontrol eden uygulamadaki kodu kaldırmak veya tersine çevirmek hala mümkündür
Gianluca Ghettini

3
@GianlucaGhettini, çünkü bazen satın alınan hizmeti sağlayan şey uygulama değil sunucu olabilir, uygulama tersine mühendisliğe tabi tutulabilir ve daha sonra bazı zorluklarla doğrulama süreci hacklenebilir.
Mohyaddin Alaoddin

0

Marc Greenstock'un cevabı kesinlikle aydınlatıcı, dikkat etmem gereken birkaç şey var ama bu da uzun zamanımı aldı (en azından beklediğimden çok daha fazla zaman aldı):

  1. Hizmet Hesabı ayarlarında "G Suite Alanı Genelinde Yetkilendirmeyi Etkinleştir" seçeneğini işaretlemem gerekiyordu. Bu olmadan şu hatayı almaya devam ettim: "Geçerli kullanıcının istenen işlemi gerçekleştirmek için yeterli izni yok" G Suite Alanı Genelinde Yetkilendirmeyi Etkinleştir seçeneğinin işaretli olduğu resim

  2. Test amacıyla burada hizmet hesabınız için bir JWT jetonu oluşturabilirsiniz , RS256 Algoritmasını seçmeyi unutmayın.

  3. Genel anahtar, indirdiğiniz JSON dosyasındaki "private_key_id" dir. Ayrıca aşağıdaki biçime sahiptir:

    ----- BAŞLANGIÇ KAMU ANAHTARI ----- {private_key_id} ----- GENEL ANAHTARIN SONU -----

  4. Özel anahtar, indirdiğiniz JSON dosyasındaki "private_key" dir

  5. JWT nesli için gerekli iddialar burada açıklanmaktadır .

  6. JWT Token'in tam olarak ne olduğu ve nasıl bir araya getirildiği konusunda kafanız mı karıştı? Utanmayın, bu bağlantıya bakın . Muhtemelen sen de benim gibisin ve tam olarak ne olduğunu aramakla uğraşmak uzun zaman aldı, göründüğünden (yol) daha basit.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.