Cara memverifikasi pembelian untuk aplikasi Android di sisi server (Google Play di App billing v3)

97

Saya memiliki aplikasi sederhana (perlu login pengguna dengan akun). Saya menyediakan beberapa fitur premium untuk pengguna berbayar, seperti lebih banyak konten berita.

Saya perlu mencatat jika pengguna telah membeli item ini di database server saya. Saat saya memberikan konten data ke perangkat pengguna, saya kemudian dapat memeriksa status pengguna, dan memberikan konten yang berbeda untuk pengguna berbayar.

Saya telah memeriksa sampel Trivialdrive resmi yang disediakan oleh Google, tidak memberikan kode sampel apa pun untuk verifikasi sisi server, ini pertanyaan saya.

  1. Saya menemukan sampel menggunakan kunci publik aplikasi saya di dalam untuk memverifikasi pembelian, tampaknya tidak bagus, saya pikir saya bisa memindahkan proses verifikasi ke server saya dikombinasikan dengan kredensial login pengguna untuk melihat apakah pembelian pengguna selesai, dan kemudian memperbarui database.
  2. Juga ada API pembelian yang dapat saya gunakan untuk melakukan kueri, yang saya butuhkan adalah meneruskan purchaseToken pengguna ke server.

Saya tidak yakin metode apa yang harus saya ambil untuk memverifikasi pembelian pengguna, dan menandai status pengguna di database saya, mungkin keduanya?

Dan saya khawatir ada situasi, jika pengguna membeli item ini dari google play, tetapi untuk beberapa alasan, tepat pada saat itu, ketika aplikasi saya meluncurkan verifikasi ke server saya, koneksi jaringan turun atau server saya sendiri mati , pengguna baru saja membayar uang di google play tetapi saya tidak mencatat pembelian di server saya? Apa yang harus saya lakukan, Bagaimana saya bisa menghadapi situasi ini.

virsir
sumber
Anda mungkin harus menghapus bendera ios dari pertanyaan ini.
Gustavo Guevara

Jawaban:

161

Sepertinya yang Anda cari adalah cara untuk memeriksa apakah pengguna mengaktifkan fitur premium di akun mereka, jadi di sinilah saya akan mulai;

Pastikan ada semacam bendera di database Anda yang menunjukkan apakah pengguna memiliki fitur premium dan menyertakannya dalam payload respons API saat meminta info akun. Bendera ini akan menjadi otoritas utama Anda untuk "fitur premium".

Saat pengguna melakukan pembelian dalam aplikasi, cache detailnya (token, id pesanan, dan id produk) secara lokal di klien (yaitu aplikasi) lalu kirimkan ke API Anda.

API Anda kemudian harus mengirimkan purchaseTokenke Google Play Developer API untuk validasi.

Beberapa hal mungkin terjadi dari sini:

  1. Tanda terima valid, API Anda merespons klien dengan kode status 200 Ok
  2. Tanda terima tidak valid, API Anda menanggapi klien dengan kode status 400 Permintaan Buruk
  3. Google Play API tidak aktif, API Anda merespons dengan kode status 502 Bad Gateway

Dalam kasus 1. atau 2. (kode status 2xx atau 4xx) klien Anda membersihkan cache dari detail pembelian karena tidak membutuhkannya lagi karena API telah menunjukkan bahwa itu telah diterima.

Setelah validasi berhasil (kasus 1.), Anda harus menyetel premiumflag ke true untuk pengguna.

Dalam kasus 3. (kode status 5xx) atau waktu tunggu jaringan, klien harus terus mencoba sampai menerima kode status 2xx atau 4xx dari API Anda.

Bergantung pada kebutuhan Anda, Anda dapat membuatnya menunggu beberapa detik sebelum mengirim lagi atau hanya mengirimkan detailnya ke API Anda ketika aplikasi diluncurkan lagi atau keluar dari latar belakang jika detail pembelian ada di cache aplikasi.

Pendekatan ini harus menangani waktu tunggu jaringan, server tidak tersedia, dll.

Sekarang ada beberapa pertanyaan yang perlu Anda pertimbangkan:

Apa yang harus terjadi segera setelah pembelian? Haruskah aplikasi menunggu sampai validasi berhasil sebelum memberikan konten premium atau haruskah aplikasi tersebut secara tentatif memberikan akses dan menghapusnya jika validasi gagal?

Memberikan akses tentatif ke fitur premium memperlancar proses untuk sebagian besar pengguna Anda, tetapi Anda juga akan memberikan akses ke sejumlah pengguna penipu saat API Anda memvalidasi purchaseToken.

Dengan kata lain: Pembelian valid sampai terbukti curang atau; curang sampai terbukti valid?

Untuk mengidentifikasi apakah pengguna masih memiliki langganan yang valid ketika periode langganan mereka tiba untuk perpanjangan, Anda perlu menjadwalkan validasi ulang di purchaseTokento run pada expiryTimeMillisyang dikembalikan dalam hasil .

Jika expiryTimeMillisada di masa lalu, Anda dapat menyetel premiumbenderanya ke false. Jika di masa mendatang, jadwalkan ulang lagi untuk yang baru expiryTimeMillis.

Terakhir, untuk memastikan pengguna memiliki akses premium (atau tidak), aplikasi Anda harus menanyakan API Anda tentang detail pengguna saat peluncuran aplikasi atau saat aplikasi tersebut keluar dari latar belakang.

Marc Greenstock
sumber
Untuk aplikasi berbayar, bagaimana saya mendapatkan tanda terima dari google?
Merbin Joe
2
Hai! Tidak ada cara untuk mengakses riwayat langganan di google? Bagaimana cara mencegah kehilangan fakta bahwa menggunakan cubscription yang sudah dibeli dalam kasus jika aplikasi macet pada saat menyimpan purchaseToken?
scythargon
2
Saya memiliki masalah yang sama .. alih-alih membiarkan aplikasi mengirim token ke api, bukankah lebih dapat diandalkan untuk menginstruksikan server pengembang google untuk melakukannya dengan pemberitahuan push langsung ke api saya?
Gianluca Ghettini
Untuk langganan yang dibatalkan, API Pengembang Google Play masih akan mengembalikan 200 setelah pembatalan, jika token pembelian lama yang sama digunakan untuk validasi.
Cezar Cobuz
Jadi untuk berlangganan, Anda menyarankan bahwa setelah panggilan pertama di server, kami menyimpan token pembelian, dan ID produk, dan menjadwalkan panggilan verifikasi lainnya (menjalankan kembali permintaan yang sama) ketika expiryTimeMillis terjadi? Begitukah cara kita memverifikasi validitas langganan? Apakah ada pedoman dari Android tentang cara melakukannya? Apple mendapat video WWDC tentang itu yang menjelaskan praktik yang baik dengan cukup jelas, tetapi tidak dapat menemukan banyak tentang Play Store.
schankam
28

Dokumentasi tentang hal ini membingungkan dan bertele-tele dengan hal-hal yang hampir tidak penting sementara dokumentasi yang sebenarnya penting hampir tidak ditautkan dan sangat sulit ditemukan. Ini seharusnya berfungsi dengan baik pada sebagian besar platform server populer yang dapat menjalankan pustaka klien google api, termasuk Java, Python, .Net, dan NodeJS, antara lain. Catatan: Saya hanya menguji klien Python api seperti yang ditunjukkan di bawah ini.

Langkah-langkah yang diperlukan:

  1. Buat proyek API, dari tautan Akses API di konsol Google Play Anda

  2. Buat akun layanan baru, simpan kunci pribadi JSON yang dihasilkan. Anda harus membawa file ini ke server Anda.

  3. Tekan Selesai di bagian akun layanan konsol Play untuk menyegarkan dan kemudian memberikan akses ke akun layanan

  4. Dapatkan pustaka klien google api untuk platform server Anda dari https://developers.google.com/api-client-library

  5. Gunakan pustaka klien platform khusus Anda untuk membuat antarmuka layanan dan langsung membaca hasil verifikasi pembelian Anda.

Anda tidak perlu repot dengan cakupan otorisasi, membuat panggilan permintaan khusus, menyegarkan token akses, dll. Pustaka klien api menangani semuanya. Berikut adalah contoh penggunaan pustaka python untuk memverifikasi langganan:

Pertama, instal klien google api di pipenv Anda seperti ini:

$ pipenv install google-api-python-client

Kemudian Anda dapat mengatur kredensial klien api menggunakan file json kunci pribadi untuk mengautentikasi akun layanan.

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

Sekarang Anda dapat memverifikasi pembelian langganan atau pembelian produk menggunakan perpustakaan, secara langsung.

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

Dokumentasi untuk antarmuka layanan platform untuk Play Developer API tidak ditautkan dengan cara yang mudah ditemukan, untuk beberapa hal ini benar - benar sulit ditemukan . Berikut ini tautan untuk platform populer yang saya temukan:

Python | Jawa | .NET | PHP | NodeJS (Github TS) | Pergi (Github JSON)

Dhiraj Gupta
sumber
5
Setuju, dokumentasi sangat buruk ... Ada ide tentang bagaimana melakukan ini dengan Firebase (Firestore) dan fungsi Cloud sebagai backend?
Jeff Padgett
Jika fungsi Cloud Anda ada di NodeJS, Anda mungkin dapat menggunakan tautan NodeJS di atas agar perpustakaan Klien API berfungsi?
Dhiraj Gupta
17

Contoh lengkap penggunaan Library Klien Google API untuk PHP :

  1. Siapkan Google Project Anda dan akses ke Google Play untuk akun layanan Anda seperti yang dijelaskan dalam jawaban Marc di sini https://stackoverflow.com/a/35138885/1046909 .

  2. Pasang perpustakaan: https://developers.google.com/api-client-library/php/start/installation .

  3. Sekarang Anda dapat memverifikasi tanda terima Anda dengan cara berikut:

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

    Setelah itu $ pembelian adalah instance dari Google_Service_AndroidPublisher_SubscriptionPurchase

    $purchase->getAutoRenewing();
    $purchase->getCancelReason();
    ...
MingalevME
sumber
Ini tidak berfungsi, saya terus mendapatkan (401) Login Diperlukan dan setAuthConfig tidak menerima kredensial akun layanan json
Raulnd
Yang ini berhasil untuk saya putenv ('GOOGLE_APPLICATION_CREDENTIALS = credentials.json'); $ client = new Google_Client (); $ client-> useApplicationDefaultCredentials (); $ client-> addScope (' googleapis.com/auth/androidpublisher' ); $ service = new Google_Service_AndroidPublisher ($ client); $ pembelian = $ layanan-> pembelian_produk-> dapatkan ($ packageName, $ productId, $ token); var_dump ($ pembelian);
Raulnd
Hal ini jika terjadi kesalahan penagihan. Bagaimana jika saya ingin memasukkan orderId ke database saya setiap kali pengguna membeli aplikasi saya dari play store alih-alih dari dalam aplikasi?
Ankesh kumar Jaisansaria
stackoverflow.com/questions/48662787/… Silakan lihat pertanyaan ini. Saya mencari jawaban untuk pertanyaan ini. Ini memiliki bounty aktif juga
Ankesh kumar Jaisansaria
@MingalevME Bagaimana jika format token tidak valid dan PHP mendapatkan kesalahan fatal, bagaimana cara menangkap kesalahan ini?
alexx0186
12

Anda dapat mencoba menggunakan Purchases.subscriptions: get server-side. Dibutuhkan packageName, subscriptionId dan token sebagai paramaters dan membutuhkan otorisasi .

Memeriksa apakah pembelian langganan pengguna valid dan mengembalikan waktu kedaluwarsanya.

Jika berhasil, metode ini mengembalikan resource Purchases.subscriptions di isi respons.

acak
sumber
9
Saya mengalami masalah serius untuk menjalankan otorisasi.
8
Sungguh. Mengenai seberapa pentingnya pembelian untuk beberapa aplikasi, dukungan dan dokumentasinya tidak masuk akal. Inilah yang perlu Anda lakukan di server: github.com/google/… . Info lebih lanjut di sini: stackoverflow.com/questions/35127086/…
pengguna
0

Saya menjawab kekhawatiran ini

koneksi jaringan terputus atau server saya tidak aktif, pengguna baru saja membayar uang di google play tetapi saya tidak mencatat pembelian di server saya? Apa yang harus saya lakukan, Bagaimana saya bisa menghadapi situasi ini.

Situasinya adalah:

Pengguna membeli item 'abc' menggunakan layanan google play -> kembali OK -> gagal memverifikasi dengan server karena beberapa alasan seperti tidak ada koneksi Internet.

Solusinya adalah:

Di sisi klien, sebelum menampilkan tombol 'Google Wallet', Anda memeriksa apakah item 'abc' sudah dimiliki.

  • jika ya, verifikasi dengan server lagi
  • jika tidak, tunjukkan tombol 'Google Wallet'.

Pembelian pembelian = 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

thanhbinh84.dll
sumber
4
Saya tidak mengerti mengapa memvalidasi di server lebih aman daripada memvalidasi di aplikasi. Pada akhirnya, itu adalah aplikasi yang membuka fitur sehingga masih mungkin untuk menghapus atau membalikkan kode di aplikasi yang memeriksa apakah respons server "OK"
Gianluca Ghettini
2
@GianlucaGhettini karena, terkadang server menyediakan layanan yang dibeli bukan aplikasi selain itu, aplikasi tersebut dapat direkayasa ulang dan kemudian dengan beberapa perjuangan proses verifikasi dapat diretas.
Mohyaddin Alaoddin