Lompat ke konten utama
Tutorial

Bayar dengan Stripe di Capacitor: Pedoman Baru Apple

Belajar cara mengimplementasikan Tautan Pembayaran Stripe di aplikasi Capacitor Anda untuk memproses pembayaran barang digital yang sesuai dengan pedoman baru Apple yang berlaku mulai 1 Mei 2025.

Bayar dengan Stripe di Capacitor: Pedoman Baru Apple

Implementasi Tautan Pembayaran Stripe di Capacitor Aplikasi Menurut Pedoman Baru Apple

Sejak 1 Mei 2025, Apple telah menerapkan perubahan signifikan pada Pedoman Ulasan App Store setelah putusan pengadilan dalam kasus Epic v. Apple Kasus Epic v. Apple. Perubahan ini secara khusus memungkinkan pengembang aplikasi di Amerika Serikat untuk menghubungkan ke metode pembayaran eksternal untuk barang dan jasa digital, membuka alternatif untuk sistem pembelian dalam aplikasi Apple

Perang Epic yang Mengubah Pembayaran Seluler Selamanya

Jalur menuju momen ini telah panjang dan kontroversial. Semua dimulai pada Agustus 2020 ketika Epic Games, pembuat permainan populer Fortnite, secara sengaja melanggar pedoman App Store Apple dengan mengimplementasikan opsi pembayaran langsung yang menghindari komisi 30% Apple. Apple kemudian menghapus Fortnite dari App Store, dan Epic bereaksi dengan mengajukan gugatan yang menantang kontrol Apple atas distribusi aplikasi iOS dan pembayaran dalam aplikasi.

Setelah bertahun-tahun berjuang di pengadilan, banding, dan banding balik, akhirnya pengadilan memutuskan bahwa Apple harus memungkinkan pengembang untuk mengarahkan pengguna ke metode pembayaran alternatif di luar aplikasi. Keputusan ini secara fundamental mengubah ekonomi ekosistem App Store, yang telah beroperasi di bawah model keuangan dasar yang sama sejak awalnya pada tahun 2008.

Keputusan Akhir - Tidak Ada Banding Lagi

Yang membuat keputusan ini sangat signifikan adalah bahwa itu adalah keputusan akhir dan tidak dapat dibandingkan lagi. Mahkamah Agung menolak mendengarkan banding Apple pada awal 2025, sehingga memastikan keputusan pengadilan tingkat bawah sebagai hukum tanah air. Ini berarti pengembang dapat mengimplementasikan metode pembayaran eksternal dengan percaya diri bahwa Apple tidak dapat membalikkan keputusan ini melalui tantangan hukum yang lebih lanjut.

Perlakuan Sama Sama Dibebaskan oleh Undang-Undang

Yang paling penting, keputusan ini secara eksplisit menyatakan bahwa Apple tidak dapat diskriminasi terhadap aplikasi yang menggunakan metode pembayaran eksternal. Pengadilan secara spesifik melarang Apple dari:

  1. Menambahkan biaya tambahan atau menetapkan syarat tambahan pada aplikasi yang menggunakan metode pembayaran eksternal
  2. Menghadiahi aplikasi yang eksklusif menggunakan sistem IAP Apple dalam hasil pencarian atau menampilkan aplikasi tersebut
  3. Menggunakan tindakan teknis untuk membuat pengalaman pembayaran eksternal menjadi kurang baik daripada sistem IAP Apple sendiri
  4. Menetapkan persyaratan diskusi yang berat melebihi informasi konsumen dasar

Ketentuan ini berarti bahwa pengembang dapat menerapkan Stripe atau penyedia pembayaran eksternal lainnya tanpa takut akan balasan atau diskriminasi dari Apple. Lapangan permainan telah diadakan secara hukum, dan Apple harus menganggap semua aplikasi sama tanpa memandang pilihan metode pembayaran mereka.

Putusan ini merupakan salah satu tantangan paling signifikan terhadap pendekatan taman Apple dan menandai perubahan penting dalam bagaimana aplikasi mobile dapat di monetisasi. Bagi pengembang yang telah lama mengeluh tentang komisi 30% Apple (diperkecil menjadi 15% untuk bisnis kecil), putusan ini menawarkan jalan untuk meningkatkan margin laba dan lebih banyak kontrol atas pengalaman pelanggan.

Manfaat Keuangan Menggunakan Stripe Atas Pembelian Dalam Aplikasi Apple

Implikasi keuangan dari perubahan ini sangat signifikan bagi pengembang:

  • Biaya Pengolahan Pembayaran yang Dikurangi: Apple biasanya mengenakan komisi 30% atas pembelian dalam aplikasi (15% untuk bisnis kecil), sedangkan biaya Stripe hanya sekitar 2,9% + $0,30 per transaksi. Perbedaan ini dapat meningkatkan signifikan laba Anda.

  • Pembayaran yang Lebih Cepat: Dengan Apple, Anda biasanya menunggu 45-90 hari untuk menerima dana Anda. Stripe, di sisi lain, mentransfer pembayaran ke rekening bank Anda dalam waktu 2-3 hari kerja.

  • Sistem Pengembalian Uang yang Sederhana: Tanganan pengembalian uang secara langsung melalui dashboard Stripe daripada melalui sistem pengembalian uang yang lebih kompleks dari Apple.

Penghematan biaya dan aliran kas yang lebih baik ini dapat berubah game, terutama bagi pengembang dan bisnis kecil.

In this article, we’ll explore how to implement Stripe Payment Links in your Capacitor app to take advantage of these new rules, while ensuring compliance with Apple’s petunjuk yang diperbarui.

Ini implementasi berdasarkan Dokumentasi Resmi Stripe untuk Link PembayaranDitambahkan secara spesifik untuk aplikasi Capacitor.

Understanding the New Guidelines

Pedoman Ulasan Aplikasi App Store yang diperbarui sekarang memungkinkan pengembang untuk mengarahkan pengguna ke situs web eksternal untuk pengolahan pembayaran, khususnya untuk barang digital dan langganan. Perubahan ini hanya berlaku untuk aplikasi yang didistribusikan di App Store Amerika Serikat.

Poin penting untuk dipahami:

  1. Kamu bisa sekarang menghubungkan opsi pembayaran eksternal untuk barang digital di dalam aplikasi kamu
  2. Hal ini hanya berlaku untuk aplikasi di App Store Amerika Serikat
  3. Kamu masih harus mematuhi persyaratan pengungkapan Apple
  4. Kamu tetap bertanggung jawab atas semua dukungan pelanggan dan pengelolaan pengembalian uang

Mari kita masuk ke implementasi teknis:

Buatlah terlebih dahulu tautan pembayaran di Dashboard Stripe Anda:

  1. Pertama, buatlah tautan pembayaran di Dashboard Stripe kamu
  2. Klik “+ Baru” untuk membuat tautan pembayaran baru
  3. Klik ‘+ Baru’ untuk membuat tautan pembayaran baru
  4. Di pengaturan "Setelah pembayaran", pilih "Tidak tunjukkan halaman konfirmasi"
  5. Setel tautan universal sebagai URL kesuksesan Anda (kami akan mengkonfigurasi ini nanti)
  6. Klik ‘Buat Tautan’ untuk menghasilkan tautan pembayaran Anda

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

  1. Buat sebuah 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. Tampilkan file ini di https://yourdomain.com/.well-known/apple-app-site-association

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

  3. Configure your Capacitor app to handle universal links by adding the proper entitlement. First, in your 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 entitik Domain Asosiasi ke proyek Xcode Anda:
    • Buka proyek Xcode Anda
    • Pilih target aplikasi Anda
    • Pergi ke "Signing & Capabilities"
    • Klik “+ Kemampuan” dan pilih “Domain yang Terkait”
    • Tambahkan applinks:yourdomain.com

Langkah 3: Buat Halaman Pengganti

Buatlah halaman fallback di URL redirect untuk mengatasi kasus di mana aplikasi tidak 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>

Step 4: Implement the Payment Button in Your Capacitor App

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

: Membuka tautan pembayaran di Safari (viaMembuka tautan pembayaran di Safari (melalui window.open) rather than an in-app browser is beneficial because users who have previously saved their payment information with Stripe Link will have their credentials automatically available. This creates a smoother checkout experience where users won’t need to re-enter their credit card information, significantly reducing friction and abandonment rates.

Konfigurasi aplikasi Anda untuk menangani tautan universal ketika pengguna diarahkan kembali:

  1. Terlebih dahulu, instal plugin Aplikasi:
npm install @capacitor/app
  1. Daftarkan plugin Aplikasi 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 Penukaran Pesanan

Terakhir, atur webhook di server Anda untuk mengolah pembayaran yang sukses:

// 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'));

Kemampuan Kompabilitas Android

Jelaslah: putusan Epic v. Apple telah mengubah secara fundamental peta pembayaran di perangkat seluler. Tidak hanya mempengaruhi aplikasi iOS, tetapi juga memperkuat posisi pengembang Android yang telah menggunakan metode pembayaran eksternal.

Pengembang Android dapat mengeksekusi solusi pembayaran eksternal dengan keyakinan yang lengkap. Putusan pengadilan yang ditetapkan telah melindungi pengembang di berbagai platform dari potensi pembatasan masa depan. Keputusan pengadilan ini telah memvalidasi apa yang banyak pengembang Android telah lakukan selama bertahun-tahun - menawarkan opsi pembayaran alternatif dengan biaya yang lebih rendah.

Google Play Store telah selalu kurang restriktif tentang metode pembayaran eksternal daripada Apple, dan sekarang dengan prinsip hukum yang ditetapkan, ada hampir tidak ada risiko dalam mengimplementasikan Stripe atau penyedia pembayaran eksternal lainnya di aplikasi Android Anda. Anda dapat melanjutkan dengan implementasi ini dengan yakin bahwa Anda berada di atas tanah hukum yang solid.

Implementasi yang telah kami bahas untuk iOS hampir identik untuk perangkat Android. Karena Google Play Store tidak memiliki restriksi yang sama tentang metode pembayaran eksternal, Anda dapat menggunakan pendekatan Pembayaran Link Stripe tanpa perlu dialog diskusi khusus.

Untuk mengatasi deep linking (setara dengan tautan universal di iOS), Anda akan perlu:

  1. Konfigurasi Tautan Aplikasi di dalam AndroidManifest.xml untuk mengolah URL pengalihan
  2. Buat sebuah .well-known/assetlinks.json berkas di domain Anda dengan detail aplikasi Anda
  3. Gunakan yang sama appUrlOpen logika pendengar untuk memproses pembayaran yang sukses

Keindahan dari Capacitor adalah bahwa setelah Anda telah menerapkan konfigurasi spesifik platform, aliran pembayaran code tetap sama di kedua platform.

Membuat Antarmuka Pembayaran

Contoh button pembayaran komponen di Vue yang dapat 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>

Mengatasi Perbedaan Wilayah

Since the new Apple guidelines only apply to apps in the U.S. App Store, you’ll need a strategy to detect user regions and apply the appropriate payment method. Here’s a more reliable approach using 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);
  }
}

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

Catatan: Meskipun pendekatan ini berfungsi, penting untuk diingat bahwa geolokasi IP tidak selalu akurat 100%. Untuk aplikasi mission-critical, pertimbangkan menggunakan metode deteksi yang lebih akurat atau memungkinkan pengguna untuk memilih wilayah secara manual.

Deteksi Lokasi yang Lebih Akurat dengan Plugin Capacitor

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

  1. Pertama, instal plugin yang diperlukan:
npm install @capacitor/geolocation @capgo/capacitor-nativegeocoder
  1. Konfigurasi plugin di project Capacitor Anda. Tambahkan kode berikut ke file 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. Mengimplementasikan deteksi wilayah berdasarkan 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 menyediakan cara yang lebih akurat untuk menentukan apakah pengguna berada di Amerika Serikat secara fisik. Pertama, mencoba menggunakan GPS perangkat dan geokoder native untuk menentukan negara. Jika gagal (disebabkan oleh masalah izin atau kesalahan lainnya), maka jatuh kembali ke deteksi berdasarkan IP.

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

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 Androidandroid/app/src/main/AndroidManifest.xml):

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

Menggunakan pendekatan ini memberikan cara yang paling akurat untuk menentukan apakah pengguna layak untuk opsi pembayaran eksternal di bawah pedoman baru Apple.

Menangani Langganan

Salah satu kelebihan menggunakan Stripe untuk pembayaran adalah kemampuan untuk menawarkan dan mengelola langganan. Berikut cara mengelola 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. Portal Pelanggan untuk Manajemen Langganan

Stripe menawarkan Portal Pelanggan yang memungkinkan pengguna mengelola langganan mereka. Anda dapat membuat tautan 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;
}

Menggunakan Pedoman App Store

Untuk memastikan implementasi Anda sesuai dengan pedoman Apple:

  1. Termasuk diskusi yang tepat tentang pembelian eksternal
  2. Tampilkan notifikasi bahwa pengguna akan meninggalkan aplikasi (seperti yang diharuskan oleh Apple)
  3. Tidak usah mencoba menghindari komisi Apple pada pembelian yang dilakukan di dalam aplikasi
  4. Jelaskan dengan jelas kepada pengguna bahwa Apple tidak bertanggung jawab atas transaksi

Contoh implementasi modal diskusi 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);
  }
}

Melakukan Pengujian Implementasi

Untuk melakukan pengujian implementasi:

  1. Klik tombol pembayaran Anda di aplikasi, yang harus menampilkan diskusi dan kemudian membuka halaman pembayaran Stripe
  2. Lakukan pembayaran uji menggunakan kartu uji Stripe 4242 4242 4242 4242
  3. Setelah pembayaran, Anda harus diarahkan kembali ke aplikasi melalui tautan universal
  4. Periksa bahwa webhook Anda menerima checkout.session.completed event

Kesimpulan

The ability to use external payment options for digital goods in iOS apps is a significant change that gives developers more flexibility. While this change currently only applies to apps in the U.S. App Store, it provides an important alternative to Apple’s in-app purchase system.

Dengan menggunakan Tautan Pembayaran Stripe bersama Capacitor, Anda dapat menerapkan pengalaman pembayaran yang terstruktur dengan cepat sambil mempertahankan konsistensi dengan pedoman Apple. @capgo/pembelian asli Mengimplementasikan StoreKit dan Google Play Billing secara langsung. Pendekatan ini juga memberikan keuntungan dari infrastruktur pembayaran yang kuat dari Stripe, biaya pengolahan yang lebih rendah (3% vs 30%), dan pembayaran yang lebih cepat (hari-hari bukan bulan-bulan) dibandingkan dengan sistem pembelian dalam aplikasi Apple.

Hati-hati bahwa Anda perlu menangani semua dukungan pelanggan dan masalah pengembalian uang secara langsung, karena transaksi ini terjadi di luar ekosistem Apple.

Apakah Anda telah menerapkan Tautan Pembayaran Stripe di aplikasi Capacitor Anda? Bagikan pengalaman Anda di komentar di bawah!

FAQs

Pertanyaan: Apakah pendekatan ini sesuai dengan pedoman Apple?
Jawaban: Ya, sejak tanggal 1 Mei 2025, Apple memungkinkan tautan ke metode pembayaran eksternal untuk barang digital dan layanan di aplikasi yang didistribusikan di App Store Amerika Serikat, selama Anda mencantumkan diskusi yang diperlukan.

Pertanyaan: Apakah saya perlu membayar komisi Apple ketika menggunakan metode pembayaran eksternal?
A: Tidak, salah satu keuntungan utama dari aturan baru adalah bahwa pembayaran yang diproses di luar sistem Apple tidak berlaku pada komisi mereka.

Apakah perusahaan saya harus berbasis di Amerika Serikat untuk memanfaatkan aturan-aturan baru ini?
A: Tidak, perusahaan dari mana saja di dunia dapat menerapkan metode pembayaran eksternal selama aplikasi Anda tersedia di App Store Amerika Serikat dan pengguna yang melakukan pembelian berada di Amerika Serikat. Keputusan ini berlaku untuk pasar (App Store Amerika Serikat) dan lokasi pengguna, bukan lokasi perusahaan Anda. Ini berarti pengembang dari Eropa, Asia, Amerika Selatan, atau mana saja dapat menerapkan Tautan Pembayaran Stripe untuk pelanggan Amerika Serikat mereka.

Q: Apa yang terjadi jika pengguna di luar Amerika Serikat mencoba menggunakan opsi pembayaran eksternal?
A: Anda harus menerapkan deteksi wilayah (seperti yang ditunjukkan dalam artikel) untuk hanya menawarkan opsi pembayaran eksternal kepada pengguna di Amerika Serikat. Untuk wilayah lain, Anda harus terus menggunakan sistem pembelian dalam aplikasi Apple.

Q: Dapatkah saya menggunakan ini untuk barang fisik atau jasa yang dikonsumsi di luar aplikasi?
A: Ya, Apple telah selalu memungkinkan metode pembayaran eksternal untuk barang fisik dan jasa yang dikonsumsi di luar aplikasi (seperti taksiran atau pengiriman makanan).

Teruskan dari Pembayaran Stripe di Capacitor: Panduan Baru Apple

Jika Anda menggunakan Pembayaran Stripe di Capacitor: Panduan Baru Apple untuk merencanakan keamanan dan kinerja, hubungkan dengan Enkripsi untuk detail implementasi di Pengenkripsi, Kepatuhan untuk detail implementasi di Kepatuhan, Capgo Scanner Keamanan untuk alur kerja produk di Capgo Scanner Keamanan, Capgo Keamanan untuk alur kerja produk di Capgo Keamanan, dan Capgo Pusat Kepercayaan untuk alur kerja produk di Capgo Pusat Kepercayaan.

Update Langsung untuk Aplikasi Capacitor

Ketika bug layer web masih aktif, kirimkan perbaikan melalui Capgo daripada menunggu hari-hari untuk persetujuan toko aplikasi. Pengguna mendapatkan update di latar belakang sementara perubahan native tetap dalam jalur review normal.

Terbaru dari Blog Kami

Capgo memberikan Anda wawasan terbaik untuk membuat aplikasi seluler profesional yang sebenarnya.