Bagaimana cara memeriksa ketersediaan penawaran pengantar di iOS

Jika Anda menggunakan penawaran pengantar dalam aplikasi berlangganan Anda (uji coba, membayar sesuai penggunaan atau prabayar), maka sebelum Anda menunjukkan harga pada layar pembayaran, Anda perlu menentukan ketersediaan penawaran pengantar kepada pengguna. Jika pengguna telah menyusun uji coba, maka Anda harus menampilkan harga penuh untuk itu.


gambar


Hai semuanya, saya menghubungi Renat dari Apphud - layanan yang menyederhanakan pekerjaan dengan langganan di aplikasi iOS. Hari ini saya akan memberi tahu Anda cara menentukan apakah pengguna tunggal memiliki hak untuk mengaktifkan kalimat pengantar atau tidak.


Tawaran pengantar valid dalam kelompok berlangganan yang sama. Ini berarti bahwa pengguna dapat mengeluarkan langganan mingguan reguler tanpa uji coba, berhenti berlangganan, dan kemudian menerbitkan uji coba untuk berlangganan bulanan.


Dokumentasi Apple memiliki diagram yang menunjukkan kapan kalimat pengantar tersedia untuk pengguna:



Ternyata pengguna dapat menggunakan kalimat pengantar jika:


  • dia belum pernah menggunakan kalimat pengantar sebelumnya

Dan


  • berlangganan belum diterbitkan atau telah kedaluwarsa

Untuk memeriksa ketersediaan kalimat pengantar, Anda perlu melakukan 3 langkah:


1) Validasi App Store-cek dan tarik keluar array transaksi. Jika tidak ada transaksi, maka kami tidak memeriksa apa pun, tersedia kalimat pengantar. Jika ada transaksi, maka lakukan dua langkah berikut.


2) Periksa apakah kalimat pengantar sebelumnya digunakan


3) Periksa status berlangganan saat ini


Mari kita pertimbangkan langkah-langkah ini secara lebih rinci.


1. Validasi cek App Store


Untuk memvalidasi cek, Anda harus mengirim permintaan ke Apple, melewati receiptData dan sharedSecret . Ganti nilai sharedSecret dengan milik Anda. Jika Anda tidak tahu sharedSecret Anda, maka dijelaskan di sini tempat untuk mendapatkannya.


 func isEligibleForIntroductory(callback: @escaping (Bool) -> Void){ guard let receiptUrl = Bundle.main.appStoreReceiptURL else { callback(true) return } #if DEBUG let urlString = "https://sandbox.itunes.apple.com/verifyReceipt" #else let urlString = "https://buy.itunes.apple.com/verifyReceipt" #endif let receiptData = try? Data(contentsOf: receiptUrl).base64EncodedString() let sharedSecret = "YOUR_SHARED_SECRET" let requestData = ["receipt-data" : receiptData ?? "", "password" : sharedSecret, "exclude-old-transactions" : false] as [String : Any] var request = URLRequest(url: URL(string: urlString)!) request.httpMethod = "POST" request.setValue("Application/json", forHTTPHeaderField: "Content-Type") let httpBody = try? JSONSerialization.data(withJSONObject: requestData, options: []) request.httpBody = httpBody URLSession.shared.dataTask(with: request) { (data, response, error) in // continue here }.resume() } 

Contoh di atas menggunakan makro #if DEBUG untuk menentukan jenis langganan: sandbox atau production . Jika Anda menggunakan makro lain, maka Anda harus memperbarui kode di tempat ini.

2. Periksa apakah kalimat pengantar telah digunakan sebelumnya


Setelah menerima respons dari Apple, kami menerjemahkannya ke dalam Dictionary dan mendapatkan berbagai transaksi:


 // paste this code after "continue here" comment guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String : AnyHashable], let receipts_array = json["latest_receipt_info"] as? [[String : AnyHashable]] else { callback(true) return } // continue here 

Kami pergi melalui array transaksi dan melihat nilai-nilai is_trial_period dan is_in_intro_offer_period . Jika salah satu dari nilai-nilai itu true , maka pengguna telah menyusun kalimat pengantar. Nilai-nilai ini datang sebagai string, jadi untuk keandalan kami akan mencoba untuk mengkonversi nilai di Bool dan string.


 // paste this code after "continue here" comment var latestExpiresDate = Date(timeIntervalSince1970: 0) let formatter = DateFormatter() for receipt in receipts_array { let used_trial : Bool = receipt["is_trial_period"] as? Bool ?? false || (receipt["is_trial_period"] as? NSString)?.boolValue ?? false let used_intro : Bool = receipt["is_in_intro_offer_period"] as? Bool ?? false || (receipt["is_in_intro_offer_period"] as? NSString)?.boolValue ?? false if used_trial || used_intro { callback(false) return } // continue here 

3. Memeriksa status langganan saat ini


Untuk mengetahui status langganan saat ini, kami perlu menemukan tanggal expires_date terbaru dan bandingkan dengan tanggal saat ini. Jika langganan belum kedaluwarsa, penawaran pengantar tidak tersedia:


 // paste this code after "continue here" comment formatter.dateFormat = "yyyy-MM-dd HH:mm:ss VV" if let expiresDateString = receipt["expires_date"] as? String, let date = formatter.date(from: expiresDateString) { if date > latestExpiresDate { latestExpiresDate = date } } } if latestExpiresDate > Date() { callback(false) } else { callback(true) } 

Anda dapat menemukan tautan ke kode lengkap metode ini di akhir artikel, namun, ada banyak "Tapi" dalam metode ini.


Perangkap


  • Dalam contoh ini, kami hanya melihat kasus satu grup berlangganan. Jika Anda menggunakan lebih dari satu grup berlangganan dalam aplikasi, maka Anda harus memberikan pengenal grup berlangganan ke metode ini dan memverifikasinya dengan nilai subscription_group_identifier sebagai receipt .


  • Dalam contoh ini, kasus pengembalian uang berlangganan tidak diperhitungkan. Untuk melakukan ini, periksa keberadaan bidang cancellation_date :


     if receipt["cancellation_date"] != nil{ // if user made a refund, no need to check for eligibility callback(false) return } 

  • Dan di sini masa tenggang (Billing Grace Period) tidak diperhitungkan. Jika pengguna dalam masa tenggang pada saat cek divalidasi, maka pending_renewal_info akan memiliki bidang grace_period_expires_date . Dalam hal ini, Anda sebagai pengembang harus memberikan fungsionalitas premium kepada pengguna tanpa menampilkan layar pembayaran. Dan karenanya, tidak masuk akal untuk memeriksa ketersediaan kalimat pengantar.


  • Ada masalah dengan memeriksa tanggal kedaluwarsa. Waktu sistem pada perangkat iOS dapat dibuka dan kemudian kode kami akan memberikan hasil yang salah: langganan akan dianggap aktif.


  • Validasi cek pada perangkat itu sendiri tidak direkomendasikan oleh Apple. Mereka berbicara tentang ini beberapa kali di WWDC (dari 5:50) dan ini ditunjukkan dalam dokumentasi . Ini tidak aman karena penyerang dapat mencegat data menggunakan serangan man-in-the-middle. Apple merekomendasikan penggunaan server Anda untuk memvalidasi cek.



Memeriksa ketersediaan penawaran promosi


Syarat untuk ketersediaan penawaran promosi lebih sederhana - yang utama adalah bahwa pengguna memiliki langganan aktif atau kedaluwarsa. Untuk melakukan ini, cari keberadaan pending_renewal_info untuk grup berlangganan Anda.


Bagaimana itu diterapkan dalam Apphud SDK


Cukup memanggil satu metode, meneruskan product Anda ke dalamnya, yang akan mengembalikan hasilnya kepada Anda:


 Apphud.checkEligibilityForIntroductoryOffer(product: myProduct) { result in if result { // User is eligible to purchase introductory offer } } 

Dan juga untuk penawaran promosi:


 Apphud.checkEligibilityForPromotionalOffer(product: myProduct) { result in if result { // User is eligible to purchase promotional offer } } 

Ada juga metode untuk memeriksa ketersediaan beberapa produk sekaligus dalam satu panggilan:


 func checkEligibilitiesForIntroductoryOffers(products: [SKProduct], callback: ApphudEligibilityCallback) func checkEligibilitiesForPromotionalOffers(products: [SKProduct], callback: ApphudEligibilityCallback) 

Kesimpulan


Kode metode lengkap dapat diunduh di sini .


Kami di Apphud telah menerapkan pemeriksaan pada ketersediaan penawaran pengantar dan promosi di SDK open-source yang nyaman. Apphud juga membantu Anda melacak status berlangganan, menganalisis metrik kunci, secara otomatis menawarkan diskon kepada pengguna yang tidak berlangganan, dan banyak lagi. Jika Anda mengalami sakit saat bekerja dengan langganan, cobalah solusi kami secara gratis.

Source: https://habr.com/ru/post/id471492/


All Articles