Langsung ke konten

Pedoman Review iOS App Store untuk IAP

GitHub

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.

Proses Review iOS App Store

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
Metadata listing App Store dengan link kebijakan dan dukungan
  • 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) dan 2048 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

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. :::

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

Do dan Don't dalam Desain UI

Paywall dengan restore purchases dan link legal

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

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>

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

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

Checklist Metadata

Pencegahan:

// Document exactly what's in each tier
const 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 description

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:

Teks izin yang terlalu ambigu untuk review Teks izin dengan penjelasan yang lebih 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>

Penyebab kegagalan:

  • Klaim seperti “aplikasi #1 di dunia” tanpa bukti
  • Fitur “Unlimited” yang ternyata punya batasan tersembunyi
  • Taktik urgensi palsu (“Sisa 2 slot lagi!”)

Contoh Panduan Deskripsi

Panduan Deskripsi Tambahan

Pencegahan:

  • Berikan deskripsi yang spesifik dan faktual
  • Hindari penggunaan kata superlatif tanpa bukti
  • Jangan menekan pengguna dengan kelangkaan palsu

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 cancellation
function 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 &#x26; Penggunaan Data (Bagian 5.1.1)

Bagian berjudul “Privasi &#x26; Penggunaan Data (Bagian 5.1.1)”

Apple memperketat persyaratan privasi secara signifikan pada 2025.

Pengungkapan yang diperlukan

Bagian berjudul “Required Disclosures”

Untuk Setiap Izin:

  1. Why you need it (specific use case)
  2. Kapan izin akan digunakan
  3. Bagaimana data disimpan/dibagikan
  4. Apakah bersifat opsional atau wajib
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';
}

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

  1. 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
  2. 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
  3. Review Semua Copy

    • Hapus teks placeholder
    • Pastikan klaim dapat diuji
    • Cek tata bahasa dan ejaan
    • Pastikan deskripsi sesuai build terbaru
    • Hapus penyebutan kompetitor
  4. 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
  5. 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
  6. 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
  7. Tulis Catatan Review yang Detail

    Contact:
    Name: Jane Developer
    Email: review@yourapp.com
    Phone: +1 555-0100
    Test Account:
    Email: reviewer@test.com
    Password: TestPass123!
    This account does not expire during review.
    Testing Instructions:
    1. Log in with test account above
    2. Tap "Upgrade to Premium" button
    3. Select "Monthly Premium" subscription
    4. Complete purchase (no charge in sandbox)
    5. Verify premium features unlock
    Note: Subscription pricing is clearly shown before purchase.
    Cancellation instructions are in Settings > Account.

Linimasa review App Store

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 Review
  • In Review
  • Pending Developer Release
  • Rejected

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
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.');
}
}
}
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>
);
}
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>
);
}
  1. Baca pesan penolakan dengan teliti

    • Catat guideline spesifik yang dikutip (misal: 3.1.1, 5.1.1)
    • Pahami detail masalah yang ditandai Apple
  2. Perbaiki masalah secara menyeluruh

    • Jangan sekadar patch - perbaiki root cause
    • Tes perbaikan secara menyeluruh
    • Dokumentasikan apa yang Anda ubah
  3. Balas melalui Resolution Center

    Thank you for your feedback. I have addressed the issue:
    Issue: Subscription pricing not clear upfront
    Fix: Added explicit pricing display on subscription selection
    screen showing "$9.99/month" before purchase button. Also added
    cancellation instructions on the same screen.
    The changes are in this submission and can be tested using the
    provided test account.
  4. Segera ajukan ulang

    • Pengajuan ulang biasanya ditinjau lebih cepat
    • Biasanya dalam 24 jam

Jika Anda merasa penolakan tersebut salah:

Proses Klarifikasi App Store

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

Contoh Permintaan Dokumen

Jika Anda masih mengalami kendala:

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.