
Halo semuanya! Nama saya Denis, saya sedang mengembangkan Apphud , layanan untuk analisis langganan yang dapat diperbarui secara otomatis dalam aplikasi iOS.
Dalam artikel ini, saya akan memberi tahu Anda cara mengkonfigurasi, menerapkan, dan memvalidasi langganan yang dapat diperbarui secara otomatis di iOS 12 dan iOS 13. Sebagai bonus, saya akan berbicara tentang poin dan jebakan halus yang tidak semua pengembang pertimbangkan.
Siapkan langganan di App Store Connect
Jika Anda sudah memiliki Bundle ID dan aplikasi yang dibuat, maka Anda dapat melewati langkah-langkah ini. Jika Anda membuat aplikasi untuk pertama kalinya, maka lakukan hal berikut:
Anda harus membuat ID Bundel eksplisit (ID Aplikasi) di Portal Pengembang Apple . Dengan halaman yang disebut Sertifikat, Identifiers & Profil terbuka, buka tab Identifiers . Pada Juni 2019, Apple akhirnya memperbarui tata letak portal sesuai dengan ASC (kependekan dari App Store Connect).

Desain baru untuk Portal Pengembang Apple pada 2019

ID Bundel eksplisit biasanya ditentukan dalam gaya domain ( com.apphud.subscriptionstest
). Di bagian Kemampuan , Anda akan melihat bahwa tanda centang di sebelah Pembelian Dalam Aplikasi sudah dicentang. Setelah membuat Bundel ID ( ID Aplikasi ), pergi ke App Store Connect.
Pengguna uji (pengguna Sandbox)
Untuk menguji pembelian di masa mendatang, Anda harus membuat pengguna uji. Untuk melakukan ini, buka ASC di tab Pengguna dan Akses , lalu ke Penguji Sandbox.

Formulir Pembuatan Kotak Pasir Pengguna
Saat membuat tester, Anda dapat menentukan data yang tidak ada, yang paling penting, jangan lupa email dan kata sandi!
Saya akan berbicara tentang cara menguji pembelian dengan kredensial pengujian di dekat akhir artikel.
Langkah penting lainnya adalah menyiapkan kontrak dan data bank di bagian β Perjanjian, pajak, dan operasi perbankan β. Jika Anda tidak memiliki perjanjian untuk aplikasi berbayar, maka Anda tidak akan dapat menguji langganan yang dapat diperpanjang secara otomatis!
Setelah itu, Anda dapat membuat aplikasi baru di App Store Connect. Tentukan nama unik dan pilih ID Bundel Anda sebagai ID paket.

ID Paket adalah ID Bundel Anda
Segera setelah membuat aplikasi, buka tab Fitur.
Jika Anda sudah membuat aplikasi, maka Anda dapat terus membaca dari sini.
Proses pembuatan langganan yang dapat diperpanjang secara otomatis terdiri dari beberapa tahap:
1. Buat pengidentifikasi berlangganan dan buat grup berlangganan . Grup berlangganan adalah kumpulan langganan dengan periode dan harga berbeda, tetapi yang membuka fungsionalitas yang sama dalam aplikasi. Selain itu, dalam grup berlangganan, Anda hanya dapat mengaktifkan periode uji coba gratis satu kali, dan hanya satu langganan yang dapat aktif. Jika Anda ingin aplikasi Anda memiliki dua langganan yang berbeda secara bersamaan, maka Anda harus membuat dua grup langganan.
2. Mengisi data berlangganan: durasi, nama tampilan di App Store (jangan bingung hanya dengan nama) dan deskripsi. Jika Anda menambahkan langganan pertama ke grup, Anda harus menunjukkan nama tampilan grup langganan. Ingatlah untuk lebih sering menyimpan perubahan Anda, ASC dapat membeku kapan saja dan berhenti merespons.

Layar Berlangganan
3. Mengisi harga berlangganan. Ada dua tahap: menciptakan harga dan penawaran khusus. Tunjukkan harga riil dalam mata uang apa pun, secara otomatis dihitung ulang untuk semua negara lain. Penawaran pengantar: di sini Anda dapat menawarkan periode uji coba gratis atau diskon prabayar kepada pengguna. Promosi muncul di App Store baru-baru ini pada tahun 2019: promosi memungkinkan Anda untuk menawarkan diskon khusus kepada pengguna yang telah berhenti berlangganan dan yang ingin Anda kembalikan.
Generasi Kunci Rahasia Bersama
Pada halaman dengan daftar semua langganan yang Anda buat, Anda akan melihat tombol Shared untuk tombol aplikasi . Ini adalah jalur khusus yang diperlukan untuk memvalidasi cek di aplikasi iOS. Kami perlu memvalidasi cek untuk menentukan status langganan.
Kunci yang dibagi dapat terdiri dari dua jenis: kunci unik untuk aplikasi Anda atau satu kunci untuk akun Anda. Penting: dalam keadaan apa pun jangan membuat ulang kunci jika Anda sudah memiliki aplikasi di App Store, jika tidak, pengguna tidak akan dapat memvalidasi cek dan aplikasi Anda akan berhenti berfungsi seperti yang diharapkan.

Dalam contoh ini, tiga grup langganan dan 3 langganan tahunan dibuat.
Salin ID dari semua langganan Anda dan kunci bersama, ini akan berguna nanti dalam kode.
Bagian perangkat lunak
Mari kita turun ke bagian praktis. Apa yang diperlukan untuk membuat manajer belanja yang lengkap? Minimal, hal-hal berikut harus diterapkan:
Checkout
Periksa Status Langganan
Periksa pembaruan
Pemulihan transaksi (jangan bingung dengan memperbarui cek!)
Seluruh proses pembelian dapat dibagi menjadi 2 tahap: menerima produk (kelas SKProduct
) dan menginisialisasi proses pembelian (kelas SKPayment
). Pertama-tama, kita harus menentukan delegasi protokol SKPaymentTransactionObserver
.
Notifikasi IAP_PRODUCTS_DID_LOAD_NOTIFICATION
digunakan untuk memperbarui UI dalam suatu aplikasi.
Selanjutnya, kami menulis metode untuk menginisialisasi pembelian:
func purchaseProduct(product : SKProduct, success: @escaping SuccessBlock, failure: @escaping FailureBlock){ guard SKPaymentQueue.canMakePayments() else { return } guard SKPaymentQueue.default().transactions.last?.transactionState != .purchasing else { return } self.successBlock = success self.failureBlock = failure let payment = SKPayment(product: product) SKPaymentQueue.default().add(payment) }
Delegasi SKPaymentTransactionObserver
terlihat seperti ini:
extension IAPManager: SKPaymentTransactionObserver { public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { for transaction in transactions { switch (transaction.transactionState) { case .purchased: SKPaymentQueue.default().finishTransaction(transaction) notifyIsPurchased(transaction: transaction) break case .failed: SKPaymentQueue.default().finishTransaction(transaction) print("purchase error : \(transaction.error?.localizedDescription ?? "")") self.failureBlock?(transaction.error) cleanUp() break case .restored: SKPaymentQueue.default().finishTransaction(transaction) notifyIsPurchased(transaction: transaction) break case .deferred, .purchasing: break default: break } } } private func notifyIsPurchased(transaction: SKPaymentTransaction) { refreshSubscriptionsStatus(callback: { self.successBlock?() self.cleanUp() }) { (error) in
Setelah berhasil berlangganan, metode delegasi disebut di mana transaksi memiliki status yang purchased
.
Tetapi bagaimana cara menentukan tanggal kedaluwarsa berlangganan? Untuk melakukan ini, buat permintaan terpisah ke Apple.
Periksa Status Langganan
Pemeriksaan divalidasi menggunakan permintaan POST verifyReceipt
ke Apple, kami mengirimkan cek terenkripsi sebagai string yang di-encode base64 sebagai parameter, dan sebagai respons kami menerima cek yang sama dalam format JSON. Dalam array, key latest_receipt_info
akan mencantumkan semua transaksi dari setiap periode langganan, termasuk periode uji coba. Kami hanya dapat menguraikan jawabannya dan mendapatkan tanggal kedaluwarsa saat ini untuk setiap produk.
Di WWDC 2017, mereka menambahkan kemampuan untuk hanya menerima cek saat ini untuk setiap langganan menggunakan kunci exclude-old-transactions
dalam permintaan verifyReceipt
.
func refreshSubscriptionsStatus(callback : @escaping SuccessBlock, failure : @escaping FailureBlock){
Di awal metode, Anda dapat melihat bahwa ada cek untuk keberadaan salinan cek lokal. Pemeriksaan lokal mungkin tidak ada, misalnya, jika aplikasi diinstal melalui iTunes. Jika tidak ada pemeriksaan, kami tidak dapat menjalankan permintaan verifyReceipt
. Pertama-tama kita perlu mendapatkan cek lokal saat ini, dan kemudian mencoba memvalidasinya lagi. Memperbarui cek dilakukan menggunakan kelas SKReceiptRefreshRequest
:
private func refreshReceipt(){ let request = SKReceiptRefreshRequest(receiptProperties: nil) request.delegate = self request.start() } func requestDidFinish(_ request: SKRequest) {
Periksa pembaruan diimplementasikan dalam fungsi refreshReceipt()
. Jika pemeriksaan berhasil diperbarui, metode delegasi requestDidFinish(_ request : SKRequest)
dipanggil, yang memanggil metode refreshSubscriptionsStatus
.
Bagaimana penguraian informasi pembelian diterapkan? Kami dikembalikan objek JSON di mana ada array transaksi bersarang (dengan kunci latest_receipt_info
). Kami pergi melalui array, dapatkan tanggal kedaluwarsa menggunakan kunci expires_date
dan simpan jika tanggal ini belum tiba.
private func parseReceipt(_ json : Dictionary<String, Any>) {
Saya memberikan contoh sederhana tentang cara mengekstrak tanggal kedaluwarsa berlangganan saat ini. Tidak ada penanganan kesalahan dan, misalnya, tidak ada pemeriksaan untuk pengembalian pembelian ( tanggal pembatalan ditambahkan).
Untuk menentukan apakah langganan aktif atau tidak, cukup bandingkan tanggal saat ini dengan tanggal dari Default Pengguna berdasarkan kunci produk. Jika tidak ada atau kurang dari tanggal saat ini, maka langganan dianggap tidak aktif.
func expirationDateFor(_ identifier : String) -> Date?{ return UserDefaults.standard.object(forKey: identifier) as? Date } let subscriptionDate = IAPManager.shared.expirationDateFor("YOUR_PRODUCT_ID") ?? Date() let isActive = subscriptionDate > Date()
Pemulihan transaksi dilakukan dalam satu baris SKPaymentQueue.default().restoreCompletedTransactions()
. Fungsi ini mengembalikan semua transaksi yang telah diselesaikan dengan memanggil metode delegasi, func paymentQueue(**_** queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction])
.
Apa perbedaan antara memperbarui cek dari pemulihan transaksi?
Kedua metode membantu memulihkan data pembelian Anda. Tetapi apa perbedaan mereka? Ada tabel indah dengan video wwdc :

Tabel perbedaan dua cara untuk mengembalikan pembelian dari WWDC
Dalam kebanyakan kasus, Anda hanya perlu menggunakan SKReceiptRefreshRequest()
, karena kami hanya tertarik menerima cek untuk perhitungan selanjutnya dari tanggal kedaluwarsa.
Dalam hal langganan yang dapat diperpanjang secara otomatis, transaksi itu sendiri tidak menarik bagi kami, jadi cukup menggunakan pembaruan cek saja. Namun, ada beberapa kasus ketika Anda perlu menggunakan metode pemulihan transaksi: jika aplikasi Anda mengunduh konten setelah pembelian (konten yang diinangi Apple) atau jika Anda masih mendukung versi di bawah iOS 7.
Pengujian Belanja (Pengujian Kotak Pasir)
Sebelumnya, untuk menguji pembelian, Anda harus masuk dari App Store di pengaturan iPhone Anda. Ini sangat merepotkan (misalnya, seluruh Perpustakaan Musik Apple telah dihapus). Namun, ini tidak perlu dilakukan sekarang: akun kotak pasir sekarang ada secara terpisah dari akun utama.

Proses pembelian serupa dibandingkan dengan pembelian nyata di App Store, tetapi ada beberapa poin:
Anda akan selalu perlu memasukkan kata sandi masuk melalui jendela sistem. Pembelian menggunakan ID Sentuh / ID Wajah masih belum didukung.
Jika, setelah memasukkan login dan kata sandi dengan benar, sistem berulang kali meminta kata sandi login, klik "Batal" , perkecil aplikasi, lalu coba lagi. Itu terlihat seperti omong kosong, tetapi bekerja untuk banyak orang. Tetapi kadang-kadang setelah entri kata sandi kedua proses masih berjalan.
Anda tidak akan dapat menguji proses berhenti berlangganan dengan cara apa pun.
Durasi periode berlangganan jauh lebih rendah daripada yang sebenarnya. Dan mereka diperbarui tidak lebih dari 6 kali sehari.
Apa yang baru di StoreKit di iOS 13?
Yang baru - hanya kelas SKStorefront
, yang memberikan informasi tentang negara mana pengguna terdaftar di App Store. Ini mungkin berguna bagi para pengembang yang menggunakan langganan yang berbeda untuk negara yang berbeda. Sebelumnya, semua orang diperiksa oleh geolokasi atau berdasarkan wilayah perangkat, tetapi ini tidak memberikan hasil yang akurat. Sekarang sangat mudah untuk mengetahui negara di App Store: SKPaymentQueue.default().storefront?.countryCode
. Delegasi metode juga ditambahkan jika negara di App Store berubah selama proses pembelian. Dalam hal ini, Anda dapat melanjutkan atau membatalkan proses pembelian sendiri.
Jebakan saat bekerja dengan langganan
- Memeriksa cek langsung dari perangkat 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. Cara yang benar untuk memeriksa cek adalah validasi lokal baik menggunakan server Anda.
- Ada masalah dengan memeriksa tanggal kedaluwarsa. Jika Anda tidak menggunakan server Anda, maka waktu sistem pada perangkat dapat diubah menjadi yang lebih lama, dan kemudian kode kami akan memberikan hasil yang salah - langganan akan dianggap aktif. Jika ini tidak cocok untuk Anda, maka Anda dapat menggunakan layanan apa pun yang mengeluarkan waktu dunia yang akurat.
- Tidak semua pengguna dapat memiliki uji coba gratis. Pengguna dapat menginstal ulang aplikasi setelah beberapa waktu, dan aplikasi akan menunjukkan bahwa uji coba tersedia seperti biasa. Ini akan benar untuk memperbarui cek, memvalidasi itu dan memeriksa di JSON ketersediaan uji coba untuk pengguna ini. Banyak yang tidak.
- Jika pengguna meminta pengembalian dana, maka
cancellation_date
akan ditambahkan ke langganan JSON, tetapi expires_date
akan tetap tidak berubah. Oleh karena itu, penting untuk selalu memeriksa keberadaan bidang cancellation_date
, yang lebih disukai daripada expires_date
. - Tidak perlu memperbarui cek setiap kali aplikasi diluncurkan, karena, pertama, ini tidak ada gunanya, dan kedua, kemungkinan besar pengguna akan diberikan jendela entri kata sandi dari Apple ID. Layak memperbarui cek, misalnya, ketika pengguna sendiri mengklik tombol restore shopping.
- Bagaimana cara menentukan pada titik mana perlu memvalidasi cek untuk mendapatkan tanggal kedaluwarsa berlangganan saat ini? Anda dapat memvalidasi cek di setiap awal, atau hanya di akhir berlangganan. Namun, jika Anda memeriksa cek hanya di akhir berlangganan, pengguna yang telah mengeluarkan pengembalian dana akan dapat menggunakan aplikasi Anda secara gratis hingga akhir periode.
Kesimpulan
Semoga artikel ini bermanfaat bagi Anda. Saya mencoba untuk menambahkan tidak hanya kode, tetapi juga untuk menjelaskan titik-titik halus dalam pengembangan. Kode kelas lengkap dapat diunduh di sini . Kelas ini akan sangat berguna untuk berkenalan dengan pengembang pemula dan mereka yang ingin mempelajari lebih lanjut tentang bagaimana semuanya bekerja. Untuk aplikasi langsung, disarankan untuk menggunakan solusi yang lebih serius, misalnya, SwiftyStoreKit .
Ingin menerapkan langganan di aplikasi iOS Anda dalam 10 menit? Integrasikan Apphud dan:
- Lakukan pembelian hanya menggunakan satu metode;
- secara otomatis melacak status langganan setiap pengguna;
- Integrasikan Penawaran Langganan dengan mudah
- kirim acara berlangganan ke Amplitude, Mixpanel, Slack dan Telegram dengan mempertimbangkan mata uang lokal pengguna;
- mengurangi tingkat Churn dalam aplikasi dan mengembalikan pengguna yang tidak berlangganan.