Langsung ke konten utama
Tutorial

Stripe Payments di Capacitor: Panduan Baru Apple

Pelajari cara implementasi Stripe Payment Links di aplikasi Capacitor Anda untuk memproses pembayaran produk digital sesuai panduan baru Apple yang berlaku mulai 1 Mei 2025.

Stripe Payments di Capacitor: ilustrasi blog Panduan Apple Baru Capgo

Implementasi Stripe Payment Links di Aplikasi Capacitor Sesuai Panduan Apple Baru

Per 1 Mei 2025, Apple telah menerapkan perubahan signifikan pada App Store Review Guidelines menyusul keputusan pengadilan di kasus Epic v. Apple. Perubahan ini secara khusus memungkinkan developer aplikasi di Amerika Serikat untuk menautkan ke metode pembayaran eksternal untuk barang dan layanan digital, membuka alternatif bagi sistem in-app purchase Apple.

Pertempuran Epik yang Mengubah Pembayaran Mobile Selamanya

Perjalanan menuju momen ini panjang dan penuh kontroversi. Semuanya dimulai pada Agustus 2020 ketika Epic Games, pencipta game yang sangat populer, Fortnite, sengaja melanggar panduan App Store Apple dengan menerapkan opsi pembayaran langsung yang melewati komisi 30% Apple. Apple langsung menghapus Fortnite dari App Store, dan Epic membalas dengan mengajukan gugatan yang menantang kendali Apple atas distribusi aplikasi iOS dan pembayaran in-app.

Setelah bertahun-tahun pertempuran hukum, banding, dan banding balik, pengadilan akhirnya memutuskan bahwa Apple harus mengizinkan developer mengarahkan pengguna ke metode pembayaran alternatif di luar aplikasi mereka. Keputusan ini secara fundamental mengubah ekonomi ekosistem App Store, yang telah beroperasi dengan model finansial dasar yang sama sejak awal berdirinya pada 2008.

Putusan Final - Tidak Ada Lagi Banding

Yang membuat putusan ini sangat signifikan adalah sifatnya yang final dan tidak bisa diajukan banding lagi. Mahkamah Agung menolak memeriksa banding Apple pada awal 2025, sehingga keputusan pengadilan tingkat bawah menjadi hukum yang berlaku. Artinya developer bisa menerapkan metode pembayaran eksternal dengan yakin bahwa Apple tidak dapat membatalkan keputusan ini lewat tantangan hukum lanjutan.

Perlakuan Setara Dijamin Hukum

Yang paling penting, putusan tersebut secara eksplisit menyatakan bahwa Apple tidak boleh mendiskriminasi aplikasi yang menggunakan metode pembayaran eksternal. Pengadilan secara khusus melarang Apple untuk:

  1. Mengenakan biaya tambahan atau persyaratan ekstra pada aplikasi yang menggunakan metode pembayaran eksternal
  2. Memberikan perlakuan istimewa pada hasil pencarian atau fitur untuk aplikasi yang eksklusif menggunakan sistem IAP Apple
  3. Menggunakan langkah teknis untuk membuat pengalaman pembayaran eksternal terasa lebih buruk dibanding sistem Apple
  4. Menerapkan persyaratan pengungkapan yang memberatkan di luar informasi dasar konsumen

Perlindungan eksplisit ini berarti developer dapat mengimplementasikan Stripe atau penyedia pembayaran eksternal lainnya tanpa takut adanya diskriminasi atau tindakan balasan dari Apple. Medan tempur kini telah setara secara hukum, dan Apple harus memperlakukan semua aplikasi secara adil tanpa memandang pilihan metode pembayarannya.

Keputusan ini merupakan salah satu tantangan paling signifikan terhadap pendekatan walled garden Apple dan menandai pergeseran penting dalam cara monetisasi aplikasi mobile. Bagi developer yang sudah lama mengeluhkan komisi 30% Apple (turun menjadi 15% untuk bisnis kecil), keputusan ini menawarkan jalan menuju margin profit yang lebih tinggi dan kontrol lebih besar atas pengalaman pelanggan.

Keuntungan Finansial Menggunakan Stripe Dibandingkan In-App Purchases Apple

Implikasi finansial dari perubahan ini sangat besar bagi developer:

  • Biaya Pemrosesan Pembayaran Lebih Rendah: Apple biasanya mengenakan komisi 30% pada in-app purchases (15% untuk bisnis kecil), sementara biaya Stripe hanya sekitar 2,9% + $0,30 per transaksi. Perbedaan ini dapat meningkatkan margin pendapatan Anda secara signifikan.

  • Payout Lebih Cepat: Dengan Apple, Anda biasanya harus menunggu 45-90 hari untuk menerima dana. Sebaliknya, Stripe menyetorkan pembayaran ke rekening bank Anda dalam 2-3 hari kerja.

  • Proses Refund Lebih Simpel: Kelola refund langsung melalui dashboard Stripe daripada melalui sistem refund Apple yang lebih rumit.

Penghematan biaya dan arus kas yang lebih baik ini bisa menjadi pengubah permainan, terutama bagi developer dan bisnis kecil.

Dalam artikel ini, kita akan mempelajari cara mengimplementasikan Stripe Payment Links di aplikasi Capacitor Anda untuk memanfaatkan aturan baru ini, sambil tetap mematuhi panduan terbaru Apple.

Implementasi ini berdasarkan dokumentasi resmi Stripe untuk Payment Links, yang diadaptasi khusus untuk aplikasi Capacitor.

Understanding the New Guidelines

App Store Review Guidelines yang diperbarui kini mengizinkan developer mengarahkan pengguna ke situs eksternal untuk pemrosesan pembayaran, khususnya untuk produk digital dan langganan. Perubahan ini saat ini hanya berlaku untuk aplikasi yang didistribusikan di App Store Amerika Serikat.

Poin penting yang perlu dipahami:

  1. Sekarang Anda bisa menautkan opsi pembayaran eksternal untuk produk digital di dalam aplikasi
  2. Ini hanya berlaku untuk aplikasi di U.S. App Store
  3. Anda tetap harus mematuhi persyaratan pengungkapan dari Apple
  4. Anda tetap bertanggung jawab atas semua dukungan pelanggan dan penanganan refund

Mari kita bahas implementasi teknisnya:

Pertama, buat payment link di Stripe Dashboard Anda:

  1. Buka bagian Payment Links di Stripe Dashboard Anda
  2. Klik “+ New” untuk membuat payment link baru
  3. Tentukan detail produk atau langganan Anda
  4. Di pengaturan “After payment”, pilih “Don’t show confirmation page”
  5. Atur universal link sebagai URL sukses Anda (akan dikonfigurasi nanti)
  6. Klik “Create Link” untuk membuat link pembayaran Anda

Untuk mengarahkan pengguna kembali ke aplikasi setelah pembayaran selesai, konfigurasi universal links:

  1. Buat file apple-app-site-association file di domain Anda:
{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appIDs": ["YOURTEAMID.com.yourdomain.yourapp"],
        "components": [
          {
            "/": "/checkout_redirect*",
            "comment": "Matches any URL whose path starts with /checkout_redirect"
          }
        ]
      }
    ]
  }
}
  1. Host file ini di https://yourdomain.com/.well-known/apple-app-site-association

  2. Pastikan file disajikan dengan MIME type yang benar application/json

  3. Konfigurasi aplikasi Capacitor Anda untuk menangani universal links dengan menambahkan entitlement yang sesuai. Pertama, di capacitor.config.ts:

import { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  // Your existing app configuration (appId, appName, etc.)
  plugins: {
    Geolocation: {
      // Request precise location access on iOS
      iosLocationAccuracy: 'reduced'
    }
  }
};

export default config;
  1. Tambahkan entitlement Associated Domains ke proyek Xcode Anda:
    • Buka proyek Xcode Anda
    • Pilih target aplikasi Anda
    • Buka “Signing & Capabilities”
    • Klik “+ Capability” dan pilih “Associated Domains”
    • Tambah applinks:yourdomain.com

Langkah 3: Buat Halaman Fallback

Buat halaman fallback di URL redirect untuk menangani kasus saat aplikasi belum terinstal:

<!DOCTYPE html>
<html>
<head>
  <title>Redirecting...</title>
  <meta http-equiv="refresh" content="0;url=https://yourdomain.com/app-download">
</head>
<body>
  <p>Redirecting to download page...</p>
</body>
</html>

Langkah 4: Terapkan Tombol Pembayaran di Aplikasi Capacitor Anda

Sekarang, tambahkan tombol pembayaran ke aplikasi Anda:

import { Capacitor } from '@capacitor/core';

export async function openPaymentLink(userEmail, userId) {
  // Use your actual Stripe payment link
  const baseUrl = 'https://buy.stripe.com/your_payment_link';
  
  // Add URL parameters to customize the experience
  const params = new URLSearchParams({
    prefilled_email: encodeURIComponent(userEmail),
    client_reference_id: userId
  });

  const fullUrl = `${baseUrl}?${params.toString()}`;
  
  // Simple window.open works in both web and Capacitor
  // Using _blank opens in Safari on iOS which is important for users with saved Stripe Link credentials
  window.open(fullUrl, '_blank');
}

Mengapa Safari Penting: Membuka link pembayaran di Safari (via window.open) alih-alih in-app browser sangat menguntungkan karena kredensial pengguna yang sebelumnya sudah menyimpan info pembayaran di Stripe Link akan otomatis tersedia. Ini menciptakan pengalaman checkout yang lebih mulus tanpa perlu memasukkan ulang info kartu kredit, sehingga secara signifikan mengurangi friction dan tingkat abandonment.

Konfigurasikan aplikasi Anda untuk menangani universal links saat pengguna diarahkan kembali:

  1. Pertama, instal plugin App:
npm install @capacitor/app
  1. Daftarkan plugin App di aplikasi Anda:
import { App } from '@capacitor/app';

// In your initialization code
App.addListener('appUrlOpen', (event) => {
  // Example URL: https://yourdomain.com/checkout_redirect?session_id=cs_test_...
  const url = new URL(event.url);
  
  if (url.pathname.startsWith('/checkout_redirect')) {
    // Extract any parameters you need
    const params = new URLSearchParams(url.search);
    const sessionId = params.get('session_id');
    
    // Handle successful payment
    if (sessionId) {
      // Verify the payment on your server if needed
      verifyPayment(sessionId);
      
      // Update UI to reflect successful purchase
      updatePurchaseStatus(true);
    }
  }
});

async function verifyPayment(sessionId) {
  // Call your backend to verify the payment
  // This is optional if you're relying on webhooks
}

function updatePurchaseStatus(success) {
  // Update your app UI to reflect purchase status
}

Langkah 6: Atur Webhook untuk Pemenuhan Pesanan

Terakhir, konfigurasi webhook di server Anda untuk menangani pembayaran yang berhasil:

// Using Express.js as an example
const express = require('express');
const stripe = require('stripe')('sk_test_your_stripe_secret_key');
const app = express();

// Use raw body parser for webhook signature verification
app.post('/webhook', express.raw({type: 'application/json'}), async (req, res) => {
  const sig = req.headers['stripe-signature'];
  const webhookSecret = 'whsec_your_webhook_secret';
  
  let event;
  
  try {
    event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret);
  } catch (err) {
    console.log(`Webhook Error: ${err.message}`);
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }
  
  // Handle the checkout.session.completed event
  if (event.type === 'checkout.session.completed') {
    const session = event.data.object;
    
    // Retrieve client_reference_id (your user ID)
    const userId = session.client_reference_id;
    
    // Grant access to the purchased content
    await grantAccess(userId, session.id);
  }
  
  res.status(200).send();
});

async function grantAccess(userId, sessionId) {
  // Your logic to grant access to the purchased content
  // This could be updating a database, sending a notification, etc.
}

app.listen(3000, () => console.log('Webhook server running on port 3000'));

Kompatibilitas Android

Mari kita perjelas: putusan Epic v. Apple telah mengubah lanskap pembayaran mobile secara fundamental. Hal ini tidak hanya berdampak langsung pada aplikasi iOS, tetapi juga memperkuat posisi developer Android yang selama ini memakai metode pembayaran eksternal.

Developer Android kini bisa mengimplementasikan solusi pembayaran eksternal dengan penuh percaya diri. Preseden dari putusan Apple ini secara efektif melindungi developer di berbagai platform dari potensi pembatasan di masa depan. Keputusan pengadilan ini memvalidasi apa yang sudah dilakukan banyak developer Android selama bertahun-tahun — menawarkan opsi pembayaran alternatif dengan biaya lebih rendah.

Google Play Store sejak dulu lebih longgar soal metode pembayaran eksternal dibanding Apple, dan kini dengan adanya preseden hukum, praktis tidak ada risiko mengimplementasikan Stripe atau penyedia pembayaran eksternal lain di aplikasi Android Anda. Anda bisa lanjut dengan tenang karena landasan hukumnya kuat.

Implementasi yang kita bahas untuk iOS bekerja hampir identik di perangkat Android. Karena Google Play Store tidak punya batasan yang sama untuk metode pembayaran eksternal, Anda bisa memakai pendekatan Stripe Payment Links yang sama persis tanpa perlu dialog pengungkapan khusus.

Untuk menangani deep linking (setara dengan universal links di iOS), Anda perlu:

  1. Siapkan App Links di AndroidManifest.xml untuk menangani URL redirect
  2. Buat file .well-known/assetlinks.json file di domain Anda dengan detail aplikasi Anda
  3. Gunakan yang sama appUrlOpen logika listener untuk memproses pembayaran sukses

Keunggulan Capacitor adalah setelah Anda menerapkan konfigurasi khusus platform, alur pembayaran code tetap sama di kedua platform.

Membuat UI pembayaran

Berikut contoh komponen tombol pembayaran di Vue yang bisa Anda tambahkan ke aplikasi Capacitor Anda:

<template>
  <div class="payment-container">
    <div class="pricing-card">
      <h2 class="mb-4 text-xl font-bold">{{ product.name }}</h2>
      <p class="mb-6 text-gray-600">{{ product.description }}</p>
      <div class="mb-6 price-tag">
        <span class="text-2xl font-bold">${{ product.price }}</span>
        <span v-if="product.isSubscription" class="text-sm text-gray-500">/month</span>
      </div>
      <button 
        @click="handlePayment" 
        class="py-3 w-full font-medium text-white bg-indigo-600 rounded-lg transition-colors hover:bg-indigo-700"
      >
        Purchase Now
      </button>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { Dialog } from '@capacitor/dialog';

const props = defineProps({
  product: {
    type: Object,
    required: true
  },
  userEmail: {
    type: String,
    default: ''
  },
  userId: {
    type: String,
    required: true
  }
});

const isLoading = ref(false);

async function showExternalPaymentDisclosure() {
  const { value } = await Dialog.confirm({
    title: 'Leaving App for Payment',
    message: 'You are about to leave this app to make a payment. Apple is not responsible for the privacy or security of payments that are not made through the App Store. All payment-related issues, including refunds, must be handled by our support team.',
    okButtonTitle: 'Continue',
    cancelButtonTitle: 'Cancel'
  });
  
  return value;
}

async function openPaymentLink() {
  // Use your actual Stripe payment link
  const baseUrl = 'https://buy.stripe.com/your_payment_link';
  
  // Add URL parameters to customize the experience
  const params = new URLSearchParams({
    prefilled_email: encodeURIComponent(props.userEmail),
    client_reference_id: props.userId
  });

  const fullUrl = `${baseUrl}?${params.toString()}`;
  
  // Simple window.open works in both web and Capacitor
  // Using _blank opens in Safari on iOS which is important for users with saved Stripe Link credentials
  window.open(fullUrl, '_blank');
}

async function handlePayment() {
  isLoading.value = true;
  try {
    // Only show the disclosure on iOS
    if (window.Capacitor?.getPlatform() === 'ios') {
      const userConfirmed = await showExternalPaymentDisclosure();
      if (!userConfirmed) return;
    }
    
    await openPaymentLink();
  } catch (error) {
    console.error('Payment error:', error);
    await Dialog.alert({
      title: 'Payment Error',
      message: 'There was an error initiating the payment. Please try again.'
    });
  } finally {
    isLoading.value = false;
  }
}
</script>

Menangani Berbagai Wilayah

Karena pedoman baru Apple hanya berlaku untuk aplikasi di App Store AS, Anda perlu strategi untuk mendeteksi wilayah pengguna dan menerapkan metode pembayaran yang sesuai. Berikut pendekatan yang lebih andal menggunakan IP geolocation:

import { Capacitor } from '@capacitor/core';

async function determinePaymentMethod() {
  // Always use Stripe for Android
  if (Capacitor.getPlatform() !== 'ios') {
    return 'external';
  }
  
  try {
    // Use a geolocation service to determine user's country
    const response = await fetch('https://ipapi.co/json/');
    const locationData = await response.json();
    
    // Check if the user is in the United States
    if (locationData.country_code === 'US') {
      return 'external'; // Can use Stripe Payment Links
    } else {
      return 'iap'; // Must use In-App Purchases
    }
  } catch (error) {
    console.error('Error detecting region:', error);
    return 'iap'; // Default to IAP to be safe
  }
}

export async function processPayment(product, userEmail, userId) {
  const paymentMethod = await determinePaymentMethod();
  
  if (paymentMethod === 'external') {
    // Use Stripe Payment Links
    await initiateExternalPayment(userEmail, userId);
  } else {
    // Use Apple's In-App Purchase
    await initiateInAppPurchase(product.appleProductId);
  }
}

Pendekatan ini menggunakan layanan gratis ipapi.co layanan untuk menentukan negara pengguna berdasarkan alamat IP mereka. Anda juga bisa menggunakan layanan geolokasi lain seperti MaxMind, atau menerapkan pengecekan ini di sisi server demi keamanan tambahan.

Catatan: Meskipun pendekatan ini berhasil, perlu diingat bahwa geolokasi IP tidak selalu 100% akurat. Untuk aplikasi yang bersifat mission-critical, pertimbangkan untuk menggunakan beberapa metode deteksi atau mengizinkan pengguna memilih wilayah mereka secara manual.

Deteksi Lokasi Lebih Akurat dengan Plugin Capacitor

Untuk deteksi lokasi yang lebih akurat, Anda dapat menggunakan plugin Capacitor Geolocation bersama dengan @capgo/capacitor-nativegeocoder guna menentukan negara pengguna dengan presisi lebih tinggi:

  1. Pertama, instal plugin yang diperlukan:
npm install @capacitor/geolocation @capgo/capacitor-nativegeocoder
  1. Konfigurasi plugin di proyek Capacitor Anda. Tambahkan hal berikut ke capacitor.config.ts:
import { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  // Your existing app configuration (appId, appName, etc.)
  plugins: {
    Geolocation: {
      // Request precise location access on iOS
      iosLocationAccuracy: 'reduced'
    }
  }
};

export default config;
  1. Implementasikan deteksi wilayah berbasis lokasi:
import { Capacitor } from '@capacitor/core';
import { Geolocation } from '@capacitor/geolocation';
import { NativeGeocoder } from '@capgo/capacitor-nativegeocoder';

async function isUserInUSA() {
  try {
    // Request permission first
    const permissionStatus = await Geolocation.requestPermissions();
    
    if (permissionStatus.location === 'granted') {
      // Get current position
      const position = await Geolocation.getCurrentPosition({
        timeout: 10000,
        enableHighAccuracy: false
      });
      
      // Use NativeGeocoder to reverse geocode the coordinates
      const results = await NativeGeocoder.reverseGeocode({
        latitude: position.coords.latitude,
        longitude: position.coords.longitude,
        useLocale: true,
        maxResults: 1
      });
      
      if (results.addresses.length > 0) {
        // Check if the user is in the USA
        return results.addresses[0].countryCode === 'US';
      }
    }
    
    // If we couldn't determine location or permission denied, fall back to IP detection
    return await isUserInUSAByIP();
  } catch (error) {
    console.error('Error detecting location:', error);
    // Fall back to IP detection on error
    return await isUserInUSAByIP();
  }
}

async function isUserInUSAByIP() {
  try {
    const response = await fetch('https://ipapi.co/json/');
    const data = await response.json();
    return data.country_code === 'US';
  } catch (error) {
    console.error('Error detecting IP location:', error);
    return false; // Default to false to be safe
  }
}

export async function determinePaymentMethod() {
  // Always use Stripe for Android
  if (Capacitor.getPlatform() !== 'ios') {
    return 'external';
  }
  
  // Check if user is in the USA
  const isUSA = await isUserInUSA();
  return isUSA ? 'external' : 'iap';
}

export async function processPayment(product, userEmail, userId) {
  const paymentMethod = await determinePaymentMethod();
  
  if (paymentMethod === 'external') {
    // Use Stripe Payment Links
    await initiateExternalPayment(userEmail, userId);
  } else {
    // Use Apple's In-App Purchase
    await initiateInAppPurchase(product.appleProductId);
  }
}

Implementasi ini memberikan cara yang lebih akurat untuk menentukan apakah pengguna benar-benar berada di Amerika Serikat. Sistem akan mencoba menggunakan GPS perangkat dan native geocoder terlebih dahulu. Jika gagal (karena masalah izin atau error lainnya), sistem akan beralih ke deteksi berbasis IP.

Jangan lupa tambahkan izin yang diperlukan ke file info.plist (iOS) dan AndroidManifest.xml (Android) file:

Untuk iOS (ios/App/App/Info.plist):

<key>NSLocationWhenInUseUsageDescription</key>
<string>We need your location to determine which payment method to use based on regional availability.</string>

Untuk Android (android/app/src/main/AndroidManifest.xml):

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Pendekatan ini adalah cara paling akurat untuk menentukan apakah pengguna memenuhi syarat untuk opsi pembayaran eksternal sesuai panduan baru Apple.

Mengelola Langganan

Salah satu keuntungan utama menggunakan Stripe untuk pembayaran adalah kemampuan untuk menawarkan dan mengelola langganan. Berikut cara menangani manajemen langganan di aplikasi Capacitor Anda:

1. Membuat Halaman Manajemen Langganan

Tambahkan halaman manajemen langganan di aplikasi Anda untuk menampilkan langganan aktif pengguna:

<template>
  <div class="subscription-manager">
    <div v-if="isLoading" class="loading-indicator">
      Loading subscription data...
    </div>
    
    <div v-else-if="subscription" class="subscription-info">
      <h2 class="mb-4 text-xl font-bold">Your Subscription</h2>
      
      <div class="mb-6 plan-details">
        <p><span class="font-medium">Plan:</span> {{ subscription.planName }}</p>
        <p><span class="font-medium">Status:</span> {{ subscription.status }}</p>
        <p><span class="font-medium">Renews:</span> {{ formatDate(subscription.currentPeriodEnd) }}</p>
      </div>
      
      <button 
        @click="manageSubscription" 
        class="py-3 w-full font-medium text-white bg-indigo-600 rounded-lg transition-colors hover:bg-indigo-700"
      >
        Manage Subscription
      </button>
    </div>
    
    <div v-else class="no-subscription">
      <p class="mb-4">You don't have an active subscription.</p>
      <button 
        @click="goToPricingPage" 
        class="py-3 w-full font-medium text-white bg-indigo-600 rounded-lg transition-colors hover:bg-indigo-700"
      >
        View Plans
      </button>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { getUserSubscription } from '../services/subscription';

const subscription = ref(null);
const isLoading = ref(true);

onMounted(async () => {
  try {
    const userData = await getUserSubscription();
    subscription.value = userData.subscription;
  } catch (error) {
    console.error('Failed to load subscription:', error);
  } finally {
    isLoading.value = false;
  }
});

function formatDate(timestamp) {
  return new Date(timestamp * 1000).toLocaleDateString();
}

function manageSubscription() {
  // Open Stripe Customer Portal
  window.open(subscription.value.portalUrl, '_blank');
}

function goToPricingPage() {
  // Navigate to pricing page
  // router.push('/pricing');
}
</script>

2. Customer Portal untuk Manajemen Langganan

Stripe menyediakan Customer Portal yang memungkinkan pengguna mengelola langganan mereka. Anda dapat membuat link ke portal ini dari server Anda:

// Server-side code (Node.js)
const stripe = require('stripe')('sk_your_stripe_secret_key');

async function createPortalSession(customerId) {
  const session = await stripe.billingPortal.sessions.create({
    customer: customerId,
    return_url: 'https://yourdomain.com/account',
  });
  
  return session.url;
}

Memastikan Kepatuhan App Store

Untuk memastikan implementasi Anda mematuhi panduan Apple:

  1. Sertakan pengungkapan yang sesuai mengenai pembelian eksternal
  2. Implement modal sheet untuk memberi tahu pengguna bahwa mereka akan keluar dari aplikasi (sesuai aturan Apple)
  3. Jangan mencoba mengakali komisi Apple untuk pembelian yang dilakukan di dalam aplikasi
  4. Sampaikan dengan jelas kepada pengguna bahwa Apple tidak bertanggung jawab atas transaksi tersebut

Berikut adalah contoh implementasi modal disclosure yang diperlukan:

import { Dialog } from '@capacitor/dialog';

async function showExternalPaymentDisclosure() {
  const { value } = await Dialog.confirm({
    title: 'Leaving App for Payment',
    message: 'You are about to leave this app to make a payment. Apple is not responsible for the privacy or security of payments that are not made through the App Store. All payment-related issues, including refunds, must be handled by our support team.',
    okButtonTitle: 'Continue',
    cancelButtonTitle: 'Cancel'
  });
  
  return value;
}

export async function initiateExternalPayment(userEmail, userId) {
  const userConfirmed = await showExternalPaymentDisclosure();
  
  if (userConfirmed) {
    await openPaymentLink(userEmail, userId);
  }
}

Menguji Implementasi Anda

Untuk menguji implementasi Anda:

  1. Klik tombol pembayaran di aplikasi Anda, yang akan menampilkan pengungkapan informasi lalu membuka halaman pembayaran Stripe
  2. Selesaikan pembayaran uji coba menggunakan kartu tes Stripe 4242 4242 4242 4242
  3. Setelah pembayaran, Anda seharusnya diarahkan kembali ke aplikasi melalui universal link
  4. Pastikan webhook Anda telah menerima checkout.session.completed event

Kesimpulan

Kemampuan menggunakan opsi pembayaran eksternal untuk produk digital di aplikasi iOS adalah perubahan besar yang memberi developer lebih banyak fleksibilitas. Meski saat ini hanya berlaku untuk aplikasi di U.S. App Store, ini menjadi alternatif penting bagi sistem in-app purchase milik Apple.

Dengan menggunakan Stripe Payment Links bersama Capacitor, Anda bisa cepat mengimplementasikan pengalaman checkout yang mulus sambil tetap mematuhi panduan Apple. Untuk pengguna di luar AS yang masih terkena sistem in-app purchase Apple, @capgo/native-purchases mengimplementasikan StoreKit dan Google Play Billing secara langsung. Pendekatan ini juga memberi Anda keuntungan dari infrastruktur pembayaran Stripe yang kuat, biaya pemrosesan lebih rendah (3% vs 30%), dan payout yang jauh lebih cepat (hitungan hari, bukan bulan) dibanding sistem in-app purchase Apple.

Ingat bahwa Anda harus menangani semua customer support dan masalah refund sendiri, karena transaksi ini terjadi di luar ekosistem Apple.

Sudahkah Anda mengimplementasikan Stripe Payment Links di aplikasi Capacitor Anda? Bagikan pengalaman Anda di kolom komentar di bawah!

FAQ

T: Apakah pendekatan ini sesuai dengan panduan Apple?
J: Ya, per 1 Mei 2025, Apple mengizinkan tautan ke metode pembayaran eksternal untuk produk dan layanan digital di aplikasi yang didistribusikan di U.S. App Store, asalkan Anda menyertakan pengungkapan yang diwajibkan.

T: Apakah saya tetap harus membayar komisi Apple saat menggunakan metode pembayaran eksternal?
J: Tidak, salah satu keuntungan utama dari aturan baru ini adalah pembayaran yang diproses di luar sistem Apple tidak dikenakan komisi mereka.

T: Apakah perusahaan saya harus berbasis di Amerika Serikat untuk memanfaatkan aturan baru ini?
J: Tidak, perusahaan mana pun dari seluruh dunia dapat menerapkan metode pembayaran eksternal selama aplikasi Anda tersedia di US App Store dan pengguna yang melakukan pembelian berada di Amerika Serikat. Aturan ini berlaku untuk marketplace (US App Store) dan lokasi pengguna, bukan lokasi perusahaan Anda. Ini berarti developer dari Eropa, Asia, Amerika Selatan, atau mana pun dapat menggunakan Stripe Payment Links untuk pelanggan mereka yang berbasis di AS.

T: Apa yang terjadi jika pengguna di luar AS mencoba menggunakan opsi pembayaran eksternal?
J: Anda harus menerapkan deteksi wilayah (seperti yang ditunjukkan dalam artikel) agar hanya menawarkan opsi pembayaran eksternal kepada pengguna di AS. Untuk wilayah lain, Anda harus tetap menggunakan sistem in-app purchase milik Apple.

T: Bisakah saya menggunakan ini untuk barang fisik atau layanan yang dikonsumsi di luar aplikasi?
J: Ya, Apple selalu mengizinkan metode pembayaran eksternal untuk barang fisik dan layanan yang dikonsumsi di luar aplikasi (seperti ride-sharing atau pengiriman makanan).

Lanjutkan dari Stripe Payments di Capacitor: Panduan Baru Apple

Jika Anda menggunakan Stripe Payments di Capacitor: Panduan Baru Apple untuk merencanakan keamanan dan kepatuhan, hubungkan dengan Enkripsi untuk detail implementasi pada Encryption, Kepatuhan untuk detail implementasi pada Compliance, Capgo Pemindai Keamanan untuk alur kerja produk di Capgo Security Scanner, Keamanan Capgo untuk alur kerja produk di Capgo Security, dan Capgo Pusat Kepercayaan untuk workflow produk di Capgo Trust Center.

Live updates untuk aplikasi Capacitor

Saat bug web-layer sudah live, kirim perbaikannya lewat Capgo alih-alih menunggu berhari-hari untuk persetujuan app store. Pengguna mendapat update di background, sementara perubahan native tetap mengikuti jalur review normal.

Terbaru dari Blog kami

Capgo memberikan insight terbaik yang Anda butuhkan untuk membuat aplikasi mobile yang benar-benar profesional.