Pedoman Review iOS App Store untuk IAP
Copy prompt setup berisi langkah install dan panduan markdown lengkap untuk plugin ini.
Agar aplikasi Anda disetujui di App Store, Anda perlu memperhatikan panduan Apple dengan saksama, terutama saat menerapkan in-app purchases dan langganan. Panduan ini membahas semua yang perlu Anda ketahui agar lolos review pada pengajuan pertama.

Sebelum Submit
Bagian berjudul “Sebelum Anda Submit”Selesaikan Setup App Store Connect
Bagian berjudul “Selesaikan Setup App Store Connect”Sebelum Apple mereview alur pembelian Anda, pastikan data aplikasi sudah lengkap:
- Tambahkan URL Privacy Policy di App Store Connect
- Tambahkan URL Support yang berisi informasi kontak asli bagi pengguna
- Selesaikan rating usia agar aplikasi dapat dipublikasikan
- Tambah Detail kontak App Review dan catatan reviewer yang jelas
- Jika butuh login, berikan akun demo yang tidak kedaluwarsa saat review
Siapkan Screenshot Asli
Bagian berjudul “Siapkan Screenshot Asli”- Gunakan screenshot terbaru dari build asli yang sedang ditinjau
- Untuk iPhone,
1290 x 2796(6.7-inci) adalah ukuran default termudah - Jika aplikasi Anda berjalan di iPad, upload screenshot iPad juga
- Ukuran iPad besar yang saat ini diterima meliputi
2064 x 2752(13-inci) dan2048 x 2732(12.9-inci) - Jangan pernah menarik screenshot iPhone agar terlihat seperti mendukung iPad
Simulasikan Alur Reviewer di TestFlight
Bagian berjudul “Uji Coba Alur Reviewer di TestFlight”Jalankan alur persis yang akan diikuti Apple di perangkat fisik:
- Install build terbaru dari TestFlight
- Login dengan akun review yang akan Anda sediakan
- Akses paywall tanpa gesture tersembunyi atau menu debug
- Selesaikan flow purchase, restore, dan manage-subscription
- Verifikasi aplikasi tetap berjalan normal jika izin ditolak
Persyaratan In-App Purchase
Bagian berjudul “Persyaratan In-App Purchase”Transparansi Harga (Kritis)
Bagian berjudul “Transparansi Harga (Kritis)”Apple mewajibkan pengungkapan harga yang sangat jelas sebelum pembelian:
Elemen Wajib Ada:
- Tampilkan harga persis sebelum tombol purchase
- Tampilkan frekuensi penagihan (misal: “$9.99/bulan”)
- Jelaskan manfaat yang didapat pengguna dengan jelas
- Indikasikan kapan penagihan akan dilakukan
Penyebab Penolakan Umum:
“Harga langganan harus jelas dan transparan.”
:::caution Konsistensi Harga Semua harga harus sama di:
- Metadata listing App Store
- Layar in-app purchase
- Layar manajemen langganan
Selisih harga sebesar $1 saja antara daftar toko ($4.99) dan aplikasi ($5.99) akan memicu penolakan otomatis. :::
Presentasi Paket Langganan
Bagian berjudul “Presentasi Paket Langganan”Pengungkapan Wajib:
- Semua tier langganan yang tersedia ditampilkan bersamaan
- Perbandingan fitur tiap tier yang jelas
- Tidak ada trik UI yang otomatis menjadikan tier premium sebagai default
- Instruksi pembatalan yang mudah ditemukan

Contoh UI yang Patuh:
import { NativePurchases } from '@capgo/native-purchases';
function SubscriptionScreen() { return ( <div> <h2>Choose Your Plan</h2>
{/* Show all tiers equally */} <PlanCard title="Basic" price="$4.99/month" features={['Feature A', 'Feature B']} /> <PlanCard title="Premium" price="$9.99/month" features={['All Basic', 'Feature C', 'Feature D']} highlighted={false} // Don't force premium />
{/* Clear cancellation info */} <Text> Cancel anytime in Settings > Subscriptions. No refunds for partial periods. </Text> </div> );}Pulihkan Pembelian
Bagian berjudul “Pulihkan Pembelian”Implementasi Wajib:
Setiap app dengan IAP wajib menyediakan cara bagi pengguna untuk memulihkan pembelian sebelumnya tanpa harus menghubungi support.
import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';
async function restorePurchases() { try { await NativePurchases.restorePurchases();
const { purchases } = await NativePurchases.getPurchases({ productType: PURCHASE_TYPE.SUBS, });
const activeSub = purchases.find( (purchase) => purchase.isActive && purchase.expirationDate, );
if (activeSub) { unlockPremiumFeatures(); showMessage('Purchases restored successfully!'); return; }
const { purchases: iaps } = await NativePurchases.getPurchases({ productType: PURCHASE_TYPE.INAPP, }); const hasIap = iaps.some((purchase) => purchase.productIdentifier === 'premium_unlock');
showMessage( hasIap ? 'Premium purchase restored!' : 'No previous purchases found.', ); } catch (error) { showError('Failed to restore purchases. Please try again.'); }}
// Add a visible "Restore Purchases" button<Button onClick={restorePurchases}> Restore Purchases</Button>Alasan Penolakan Umum
Bagian berjudul “Alasan Penolakan Umum”1. App Crash atau Fungsi Rusak
Bagian berjudul “1. App Crash atau Fungsi Rusak”Penyebab kegagalan:
- App crash saat dijalankan
- Alur pembelian gagal diselesaikan
- Fitur di screenshot tidak berfungsi
Pencegahan:
- Tes di perangkat asli (bukan simulator)
- Tes seluruh alur langganan secara end-to-end
- Verifikasi validasi receipt berfungsi
- Cek penanganan error jaringan
2. Ketidaksesuaian Metadata
Bagian berjudul “2. Ketidaksesuaian Metadata”Penyebab kegagalan:
- Screenshot menampilkan fitur yang tidak ada di build saat ini
- Deskripsi menyebutkan fungsi yang tidak tersedia
- Harga di metadata berbeda dengan harga in-app

Pencegahan:
// Document exactly what's in each tierconst SUBSCRIPTION_FEATURES = { basic: ['Ad-free', 'Cloud sync', 'Basic themes'], premium: ['Ad-free', 'Cloud sync', 'All themes', 'Priority support']};
// Use these in both your app AND App Store description3. Penjelasan Izin yang Hilang
Bagian berjudul “3. Penjelasan Izin yang Hilang”Penyebab kegagalan:
- Meminta akses kamera/lokasi/kesehatan tanpa penjelasan
- Permintaan izin tersembunyi di dalam banyak layar
- Deskripsi izin yang tidak jelas atau terlalu umum
Pencegahan:
Perbarui Info.plist dengan penjelasan yang jelas:
<key>NSCameraUsageDescription</key><string>Camera access is needed to scan product barcodes for quick subscription upgrades.</string>
<key>NSLocationWhenInUseUsageDescription</key><string>Location helps us show relevant local content in your Premium subscription.</string>4. Pemasaran yang Menyesatkan
Bagian berjudul “4. Pemasaran yang Menyesatkan”Penyebab kegagalan:
- Klaim seperti “aplikasi #1 di dunia” tanpa bukti
- Fitur “Unlimited” yang ternyata punya batasan tersembunyi
- Taktik urgensi palsu (“Sisa 2 slot lagi!”)


Pencegahan:
- Berikan deskripsi yang spesifik dan faktual
- Hindari penggunaan kata superlatif tanpa bukti
- Jangan menekan pengguna dengan kelangkaan palsu
5. Proses pembatalan tersembunyi
Bagian berjudul “5. Proses pembatalan tersembunyi”Penyebab kegagalan:
- Tidak ada info cara membatalkan
- Tombol pembatalan tersembunyi atau tidak jelas
- Proses pembatalan multi-langkah tanpa flow native Apple
Pencegahan:
// Always inform users about cancellationfunction SubscriptionInfo() { return ( <div> <h3>How to Cancel</h3> <ol> <li>Open iPhone Settings</li> <li>Tap your name at the top</li> <li>Tap Subscriptions</li> <li>Select this app and tap Cancel</li> </ol>
<p>Or manage directly in the App Store app.</p>
<Button onClick={openSubscriptionManagement}> Manage Subscription in Settings </Button> </div> );}
async function openSubscriptionManagement() { // Direct link to iOS subscription management await NativePurchases.showManageSubscriptions();}Privasi & Penggunaan Data (Bagian 5.1.1)
Bagian berjudul “Privasi & Penggunaan Data (Bagian 5.1.1)”Apple memperketat persyaratan privasi secara signifikan pada 2025.
Pengungkapan yang diperlukan
Bagian berjudul “Required Disclosures”Untuk Setiap Izin:
- Why you need it (specific use case)
- Kapan izin akan digunakan
- Bagaimana data disimpan/dibagikan
- Apakah bersifat opsional atau wajib
Contoh: Alur Izin yang Benar
Bagian berjudul “Example: Proper Permission Flow”async function requestCameraPermission() { // Show explanation BEFORE requesting await showDialog({ title: 'Camera Access', message: 'We need camera access to let you scan barcodes for quick product lookup. Your photos are never uploaded or stored.', buttons: ['Not Now', 'Allow'] });
// Then request permission const result = await Camera.requestPermissions(); return result.camera === 'granted';}Label Privasi App Store
Bagian berjudul “Label Privasi App Store”Pastikan label privasi App Store Anda mencerminkan hal berikut dengan akurat:
- Pengumpulan riwayat pembelian
- Alamat email (untuk tanda terima)
- ID perangkat (untuk pencegahan fraud)
- Data penggunaan (untuk analitik)
Label privasi yang tidak akurat adalah alasan penolakan yang umum pada 2025. Audit pengumpulan data Anda dengan teliti.
Checklist Sebelum Submit
Bagian berjudul “Checklist Sebelum Submit”
-
Tes Semua Alur Pembelian
- Beli setiap tier langganan
- Tes free trial
- Verifikasi penawaran intro sudah benar
- Tes restore purchases
- Verifikasi Family Sharing (jika aktif)
- Tes di beberapa perangkat
-
Verifikasi Konsistensi Harga
- Cek metadata App Store sesuai harga in-app
- Verifikasi semua mata uang sudah benar
- Pastikan durasi free trial sesuai deskripsi
- Cek akurasi syarat penawaran intro
-
Review Semua Copy
- Hapus teks placeholder
- Pastikan klaim dapat diuji
- Cek tata bahasa dan ejaan
- Pastikan deskripsi sesuai build terbaru
- Hapus penyebutan kompetitor
-
Test Izin (Permissions)
- Minta izin yang diperlukan saja
- Tampilkan penjelasan jelas sebelum meminta
- Test alur “Deny” (app harus tetap jalan)
- Pastikan deskripsi Info.plist sudah jelas
-
Siapkan Akun Test
- Buat akun review yang tetap valid selama proses review
- Dokumentasikan kredensial login di informasi App Review
- Pastikan reviewer bisa mengakses paywall dan menyelesaikan flow pembelian
- Sertakan akun tambahan atau switch khusus aplikasi di kolom Notes jika perlu
-
Periksa Metadata
- Screenshot sesuai dengan UI saat ini
- URL Support menyertakan informasi kontak asli
- URL privacy policy sudah diisi
- Rating usia sesuai dengan konten di dalam build
- Video preview aplikasi (jika ada) menampilkan versi terbaru
- Deskripsi menjelaskan fitur secara akurat
- Privacy policy dapat diakses di dalam aplikasi dan dari store listing
-
Tulis Catatan Review yang Detail
Contact:Name: Jane DeveloperEmail: review@yourapp.comPhone: +1 555-0100Test Account:Email: reviewer@test.comPassword: TestPass123!This account does not expire during review.Testing Instructions:1. Log in with test account above2. Tap "Upgrade to Premium" button3. Select "Monthly Premium" subscription4. Complete purchase (no charge in sandbox)5. Verify premium features unlockNote: Subscription pricing is clearly shown before purchase.Cancellation instructions are in Settings > Account.
Linimasa review
Bagian berjudul “Linimasa review”
Review standar: 24-48 jam Periode sibuk: 3-5 hari (rilis saat libur App Store) Akhir pekan: Tidak ada review yang diproses Review dipercepat: Tersedia untuk perbaikan bug kritis (ajukan via App Store Connect)
Status umum yang akan Anda lihat di App Store Connect:
Waiting for ReviewIn ReviewPending Developer ReleaseRejected
Fokus Submission 2026
Bagian berjudul “Fokus Submission 2026”Area Fokus Saat Ini
Bagian berjudul “Area Fokus Saat Ini”1. Kejelasan Langganan
- Wajib menyertakan perbandingan paket secara berdampingan
- Tanpa “dark patterns” yang menyembunyikan opsi lebih murah
- Jalur downgrade/upgrade yang jelas
2. Akurasi Metadata
- Screenshot harus sesuai dengan build yang direview
- Screenshot iPad wajib ada jika dukungan iPad diaktifkan
- URL dukungan dan kebijakan privasi harus sudah live sebelum submit
3. Kualitas Privasi dan Detail Review
- Pengungkapan privasi harus sesuai dengan yang benar-benar dikumpulkan SDK Anda
- Info kontak dan catatan App Review harus lengkap pada submit pertama
- Kredensial demo harus tetap valid selama seluruh masa review
4. Kesiapan Submission
- Apple rutin memperbarui persyaratan minimum SDK, jadi pastikan deadline terbaru sebelum upload release build
- TestFlight adalah tempat teraman untuk memverifikasi alur reviewer yang tepat sebelum submit
Best Practices Plugin Native Purchases
Bagian berjudul “Best Practices Plugin Native Purchases”Implementasi Error Handling yang Tepat
Bagian berjudul “Implementasi Error Handling yang Tepat”import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';
async function handlePurchase(productId: string) { try { const transaction = await NativePurchases.purchaseProduct({ productIdentifier: productId, productType: PURCHASE_TYPE.SUBS, });
// Success await validateReceiptOnServer(transaction.receipt); showSuccess('Subscription activated!'); unlockFeatures();
} catch (error: any) { // Handle specific error cases if (error.code === 'USER_CANCELLED') { // User cancelled - don't show error console.log('Purchase cancelled by user'); } else if (error.code === 'PAYMENT_PENDING') { showInfo('Payment is pending. Please check back later.'); } else if (error.code === 'PRODUCT_ALREADY_PURCHASED') { // Restore instead await NativePurchases.restorePurchases(); } else { // Show user-friendly error showError('Unable to complete purchase. Please try again.'); } }}Tampilkan Loading State
Bagian berjudul “Tampilkan Loading State”function PurchaseButton({ productId }: { productId: string }) { const [loading, setLoading] = useState(false);
const handlePurchase = async () => { setLoading(true); try { await NativePurchases.purchaseProduct({ productIdentifier: productId }); } finally { setLoading(false); } };
return ( <button onClick={handlePurchase} disabled={loading}> {loading ? 'Processing...' : 'Subscribe Now'} </button> );}Tampilkan Ketentuan dengan Jelas
Bagian berjudul “Tampilkan Ketentuan dengan Jelas”function SubscriptionTerms() { return ( <div className="terms"> <p> Subscription automatically renews unless cancelled at least 24 hours before the end of the current period. </p> <p> Your account will be charged for renewal within 24 hours prior to the end of the current period. </p> <p> Subscriptions may be managed by the user and auto-renewal may be turned off in Account Settings after purchase. </p> <p> <a href="/terms">Terms of Service</a> | <a href="/privacy/">Privacy Policy</a> </p> </div> );}Jika Aplikasi Anda Ditolak
Bagian berjudul “Jika Aplikasi Anda Ditolak”Langkah Penyelesaian
Bagian berjudul “Langkah Penyelesaian”-
Baca pesan penolakan dengan teliti
- Catat guideline spesifik yang dikutip (misal: 3.1.1, 5.1.1)
- Pahami detail masalah yang ditandai Apple
-
Perbaiki masalah secara menyeluruh
- Jangan sekadar patch - perbaiki root cause
- Tes perbaikan secara menyeluruh
- Dokumentasikan apa yang Anda ubah
-
Balas melalui Resolution Center
Thank you for your feedback. I have addressed the issue:Issue: Subscription pricing not clear upfrontFix: Added explicit pricing display on subscription selectionscreen showing "$9.99/month" before purchase button. Also addedcancellation instructions on the same screen.The changes are in this submission and can be tested using theprovided test account. -
Segera ajukan ulang
- Pengajuan ulang biasanya ditinjau lebih cepat
- Biasanya dalam 24 jam
Proses Banding
Bagian berjudul “Proses Banding”Jika Anda merasa penolakan tersebut salah:

- Klik “Appeal” di App Store Connect
- Berikan bukti yang jelas:
- Screenshot yang menunjukkan kepatuhan
- Referensi ke guideline spesifik
- Penjelasan cara Anda memenuhi persyaratan
- Bersikap profesional dan faktual
- Sertakan akun uji jika fitur sulit ditemukan

Sumber Daya Tambahan
Bagian berjudul “Sumber Daya Tambahan”- Panduan Review Apple App Store
- Panduan In-App Purchase
- Best Practice Langganan
- Bantuan App Store Connect
- Spesifikasi Screenshot
- Informasi Versi Platform
Dukungan
Bagian berjudul “Support”Jika Anda masih mengalami kendala:
- Tinjau dokumentasi Native Purchases
- Cek masalah troubleshooting umum
- Hubungi Apple Developer Support untuk klarifikasi panduan
Butuh Bantuan Ahli?
Bagian berjudul “Need Expert Help?”Kesulitan dengan review aplikasi atau butuh bantuan personal? Jadwalkan sesi konsultasi dengan tim kami untuk dukungan khusus terkait:
- Review dan optimasi implementasi IAP
- Persiapan dan strategi review App Store
- Review checklist submisi
- Resolusi penolakan dan banding
- Testing dan validasi lengkap
Expert kami telah membantu ratusan aplikasi lolos review!
Lanjutkan ke iOS App Store Review Guidelines for IAP
Bagian berjudul “Lanjutkan ke iOS App Store Review Guidelines for IAP”Jika Anda menggunakan Panduan Review App Store iOS untuk IAP untuk merencanakan persetujuan store dan distribusi, hubungkan dengan Menggunakan @capgo/native-purchases untuk kapabilitas native di Menggunakan @capgo/native-purchases, @capgo/capacitor-in-app-review untuk detail implementasi di @capgo/capacitor-in-app-review, Menggunakan @capgo/capacitor-in-app-review untuk kapabilitas native di bagian Menggunakan @capgo/capacitor-in-app-review, @capgo/capacitor-native-market untuk detail implementasi di @capgo/capacitor-native-market, dan Menggunakan @capgo/capacitor-native-market untuk kapabilitas native di bagian Menggunakan @capgo/capacitor-native-market.