Aller au contenu principal
Tutoriel

Paiements Stripe dans Capacitor : les nouvelles directives d'Apple

Découvrez comment implémenter les Stripe Payment Links dans votre application Capacitor pour traiter les paiements de biens numériques, conformément aux nouvelles directives d'Apple applicables dès le 1er mai 2025.

Paiements Stripe dans Capacitor : les nouvelles directives d'Apple

Implémenter les Stripe Payment Links dans les apps Capacitor selon les nouvelles directives d'Apple

Depuis le 1er mai 2025, Apple a apporté des changements importants à ses directives d'examen de l'App Store suite au verdict de l'affaire Epic v. Apple. Ces changements permettent spécifiquement aux développeurs d'apps aux États-Unis de lier des méthodes de paiement externes pour les biens et services numériques, offrant ainsi des alternatives au système d'achat in-app d'Apple.

L'épique bataille qui a changé les paiements mobiles à jamais

Le chemin vers ce moment a été long et conflictuel. Tout a commencé en août 2020 lorsque Epic Games, le créateur du jeu ultra-populaire Fortnite, a délibérément enfreint les directives de l'App Store d'Apple en implémentant une option de paiement direct pour contourner la commission de 30 % d'Apple. Apple a immédiatement retiré Fortnite de l'App Store, et Epic a répliqué en déposant une plainte pour contester le contrôle d'Apple sur la distribution d'applications iOS et les paiements in-app.

Après des années de batailles juridiques, d'appels et de contre-appels, les tribunaux ont finalement statué qu'Apple doit permettre aux développeurs de diriger les utilisateurs vers des méthodes de paiement alternatives en dehors de leurs applications. Cette décision change fondamentalement l'économie de l'écosystème de l'App Store, qui fonctionne selon le même modèle financier de base depuis sa création en 2008.

La décision finale : plus d'appels possibles

Ce qui rend cette décision particulièrement significative, c'est qu'elle est définitive et ne peut plus faire l'objet d'un appel. La Cour suprême a refusé d'examiner l'appel d'Apple début 2025, confirmant la décision de la juridiction inférieure comme faisant foi. Cela signifie que les développeurs peuvent implémenter des méthodes de paiement externes avec la certitude qu'Apple ne pourra pas renverser cette décision par de nouveaux recours juridiques.

Un traitement équitable garanti par la loi

Plus important encore, la décision stipule explicitement qu'Apple ne peut pas discriminer les applications utilisant des méthodes de paiement externes. Le tribunal a spécifiquement interdit à Apple de :

  1. Facturer des frais supplémentaires ou imposer des exigences additionnelles aux apps utilisant des méthodes de paiement externes
  2. Accorder un traitement préférentiel dans les résultats de recherche ou la mise en avant aux apps utilisant exclusivement le système d'IAP d'Apple
  3. Utiliser des mesures techniques pour rendre les expériences de paiement externes inférieures au propre système d'Apple
  4. Imposer des exigences de divulgation contraignantes au-delà des informations de base sur le consommateur

Ces protections explicites signifient que les développeurs peuvent implémenter Stripe ou d'autres prestataires de paiement externes sans craindre de représailles subtiles ou de discrimination de la part d'Apple. Les règles du jeu sont désormais équitables sur le plan juridique, et Apple doit traiter toutes les apps de la même manière, quel que soit leur choix de méthode de paiement.

Cette décision représente l'un des défis les plus importants pour l'approche de l'écosystème fermé d'Apple et marque un tournant décisif dans la monétisation des apps mobiles. Pour les développeurs qui déplorent depuis longtemps la commission de 30 % d'Apple (réduite à 15 % pour les petites entreprises), cette décision offre une voie vers des marges bénéficiaires plus élevées et un meilleur contrôle de l'expérience client.

Avantages financiers de l'utilisation de Stripe par rapport aux achats in-app d'Apple

Les implications financières de ce changement sont considérables pour les développeurs :

  • Réduction des frais de traitement des paiements: Apple facture généralement une commission de 30 % sur les achats in-app (15 % pour les petites entreprises), tandis que les frais de Stripe ne sont que d'environ 2,9 % + 0,30 $ par transaction. Cette différence peut augmenter considérablement vos marges de revenus.

  • Paiements plus rapides: Avec Apple, il faut généralement attendre 45 à 90 jours pour recevoir vos fonds. Stripe, en revanche, verse les paiements sur votre compte bancaire sous 2 à 3 jours ouvrés.

  • Processus de remboursement simplifié: Gérez les remboursements directement via le dashboard Stripe plutôt que par le système de remboursement plus complexe d'Apple.

Ces économies et l'amélioration de la trésorerie peuvent changer la donne, surtout pour les développeurs et les entreprises de petite taille.

Dans cet article, nous allons explorer comment implémenter les Stripe Payment Links dans votre application Capacitor pour profiter de ces nouvelles règles, tout en garantissant la conformité avec les nouvelles directives d'Apple.

Cette implémentation est basée sur la documentation officielle de Stripe pour les Payment Links, adaptée spécifiquement pour les applications Capacitor.

Comprendre les nouvelles directives

Les directives révisées de l'App Store Review autorisent désormais les développeurs à diriger les utilisateurs vers des sites web externes pour le traitement des paiements, spécifiquement pour les biens numériques et les abonnements. Ce changement ne s'applique actuellement qu'aux applications distribuées sur l'App Store des États-Unis.

Points clés à comprendre :

  1. Vous pouvez désormais lier des options de paiement externes pour les biens numériques au sein de votre application
  2. Ceci s'applique uniquement aux apps de l'App Store aux États-Unis
  3. Vous devez toujours respecter les exigences de divulgation d'Apple
  4. Vous restez responsable du support client et de la gestion des remboursements

Passons à l'implémentation technique :

Tout d'abord, créez un lien de paiement dans votre dashboard Stripe :

  1. Accédez à la section Payment Links de votre dashboard Stripe
  2. Cliquez sur « + New » pour créer un lien de paiement
  3. Définissez les détails de votre produit ou de votre abonnement
  4. Dans les paramètres « After payment », sélectionnez « Don’t show confirmation page »
  5. Définissez un lien universel comme URL de succès (nous le configurerons plus tard)
  6. Cliquez sur « Créer le lien » pour générer votre lien de paiement

Pour rediriger les utilisateurs vers votre application après le paiement, configurez les universal links :

  1. Créez un fichier apple-app-site-association sur votre domaine :
{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appIDs": ["YOURTEAMID.com.yourdomain.yourapp"],
        "components": [
          {
            "/": "/checkout_redirect*",
            "comment": "Matches any URL whose path starts with /checkout_redirect"
          }
        ]
      }
    ]
  }
}
  1. Hébergez ce fichier sur https://yourdomain.com/.well-known/apple-app-site-association

  2. Assurez-vous qu'il est servi avec le bon type MIME application/json

  3. Configurez votre application Capacitor pour gérer les universal links en ajoutant l'entitlement approprié. D'abord, dans votre 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. Ajoutez l'entitlement Associated Domains à votre projet Xcode :
    • Ouvrez votre projet Xcode
    • Sélectionnez la cible de votre application
    • Allez dans « Signing & Capabilities »
    • Cliquez sur « + Capability » et sélectionnez « Associated Domains »
    • Ajouter applinks:yourdomain.com

Étape 3 : Créer une page de secours

Créez une page de secours à l'URL de redirection pour gérer les cas où l'application n'est pas installée :

<!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>

Étape 4 : Implémenter le bouton de paiement dans votre application Capacitor

Now, add the payment button to your app:

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

Pourquoi Safari est important: Ouvrir le lien de paiement dans Safari (via window.open) plutôt que dans un navigateur intégré est avantageux car les utilisateurs ayant déjà enregistré leurs informations de paiement avec Stripe Link verront leurs identifiants disponibles automatiquement. Cela crée une expérience de paiement plus fluide où les utilisateurs n'ont pas besoin de ressaisir leurs coordonnées bancaires, réduisant ainsi considérablement la friction et les taux d'abandon.

Configurez votre application pour gérer les Universal Links lors de la redirection vers celle-ci :

  1. Tout d'abord, installez le plugin App :
npm install @capacitor/app
  1. Enregistrez le plugin App dans votre application :
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
}

Étape 6 : Configurez le webhook pour l'exécution des commandes

Enfin, configurez un webhook sur votre serveur pour gérer les paiements réussis :

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

Compatibilité Android

Soyons clairs : la décision Epic v. Apple a fondamentalement changé le paysage des paiements mobiles. Cela n'impacte pas seulement directement les apps iOS, mais cela renforce également la position des développeurs Android qui utilisent des méthodes de paiement externes.

Les développeurs Android peuvent désormais implémenter des solutions de paiement externes en toute confiance. Le précédent établi par la décision d'Apple protège efficacement les développeurs sur toutes les plateformes contre d'éventuelles restrictions futures. Cette décision de justice a validé ce que de nombreux développeurs Android font depuis des années : proposer des options de paiement alternatives avec des frais réduits.

Le Play Store de Google a toujours été moins restrictif que l'App Store concernant les méthodes de paiement externes, et maintenant, avec le précédent juridique établi, il n'y a pratiquement aucun risque à implémenter Stripe ou d'autres prestataires de paiement externes dans vos apps Android. Vous pouvez avancer sereinement, sachant que vous reposez sur des bases juridiques solides.

L'implémentation que nous avons vue pour iOS fonctionne de manière quasi identique sur les appareils Android. Comme le Google Play Store n'a pas les mêmes restrictions sur les méthodes de paiement externes, vous pouvez utiliser exactement la même approche avec les Stripe Payment Links sans avoir besoin de boîtes de dialogue de divulgation spécifiques.

Pour gérer le deep linking (l'équivalent des universal links sur iOS), vous devrez :

  1. Configurez les App Links dans votre AndroidManifest.xml pour gérer l'URL de redirection
  2. Créez un .well-known/assetlinks.json fichier sur votre domaine avec les détails de votre app
  3. Utilisez la même appUrlOpen logique d'écouteur pour traiter les paiements réussis

L'avantage de Capacitor est qu'une fois les configurations spécifiques à la plateforme implémentées, le flux de paiement code reste identique sur les deux plateformes.

Créer une interface de paiement

Voici un exemple de composant de bouton de paiement en Vue que vous pouvez ajouter à votre app Capacitor :

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

Gérer les différentes régions

Comme les nouvelles directives d'Apple ne s'appliquent qu'aux apps de l'App Store des États-Unis, vous aurez besoin d'une stratégie pour détecter la région de l'utilisateur et appliquer la méthode de paiement appropriée. Voici une approche plus fiable utilisant la géolocalisation par IP :

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

Cette approche utilise le service gratuit ipapi.co service pour déterminer le pays de l'utilisateur via son adresse IP. Vous pouvez aussi utiliser d'autres services de géolocalisation comme MaxMind, ou implémenter cette vérification côté serveur pour plus de sécurité.

Note: Bien que cette approche fonctionne, n'oubliez pas que la géolocalisation par IP n'est pas toujours fiable à 100 %. Pour les applications critiques, envisagez d'utiliser plusieurs méthodes de détection ou de permettre aux utilisateurs de sélectionner manuellement leur région.

Détection de localisation plus précise avec les plugins Capacitor

Pour une détection de localisation plus précise, vous pouvez utiliser le plugin Geolocation Capacitor avec @capgo/capacitor-nativegeocoder afin de déterminer le pays de l'utilisateur avec une plus grande précision :

  1. Tout d'abord, installez les plugins requis :
npm install @capacitor/geolocation @capgo/capacitor-nativegeocoder
  1. Configurez les plugins dans votre projet Capacitor. Ajoutez ceci à votre 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. Implémentez la détection de région basée sur la localisation :
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);
  }
}

Cette implémentation offre un moyen plus précis de déterminer si un utilisateur se trouve physiquement aux États-Unis. Elle tente d'abord d'utiliser le GPS de l'appareil et le geocoder natif pour déterminer le pays. En cas d'échec (problème de permission ou autre erreur), elle bascule sur une détection par IP.

N'oubliez pas d'ajouter les permissions nécessaires à vos fichiers info.plist (iOS) et AndroidManifest.xml fichiers (Android) :

Pour 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>

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

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

Cette approche est la plus précise pour déterminer si un utilisateur est éligible aux options de paiement externes selon les nouvelles directives d'Apple.

Gérer les abonnements

L'un des grands avantages de Stripe est la possibilité de proposer et de gérer des abonnements. Voici comment gérer les abonnements dans votre application Capacitor :

1. Créer une page de gestion d'abonnement

Ajoutez une page de gestion d'abonnement dans votre application pour afficher les abonnements actifs de l'utilisateur :

<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. Portail client pour la gestion des abonnements

Stripe propose un portail client qui permet aux utilisateurs de gérer leurs abonnements. Vous pouvez créer un lien vers ce portail depuis votre serveur :

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

Assurer la conformité avec l'App Store

Pour garantir que votre implémentation respecte les directives d'Apple :

  1. Incluez les mentions appropriées concernant les achats externes
  2. Implémenter une feuille modale informant les utilisateurs qu'ils quittent l'application (requis par Apple)
  3. Ne tentez pas de contourner la commission d'Apple sur les achats effectués dans l'application
  4. Communiquer clairement aux utilisateurs qu'Apple n'est pas responsable de la transaction

Voici un exemple d'implémentation de la modale de divulgation requise :

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

Tester votre implémentation

Pour tester votre implémentation :

  1. Cliquez sur votre bouton de paiement dans l'application, ce qui devrait afficher la divulgation puis ouvrir la page de paiement Stripe
  2. Effectuez un paiement de test avec une carte de test Stripe 4242 4242 4242 4242
  3. Après le paiement, vous devriez être redirigé vers votre application via le lien universel
  4. Vérifiez que votre webhook a bien reçu l' checkout.session.completed événement

Conclusion

La possibilité d'utiliser des options de paiement externes pour les biens numériques dans les apps iOS est un changement majeur qui offre plus de flexibilité aux développeurs. Bien que ce changement ne s'applique actuellement qu'aux apps de l'App Store aux États-Unis, il constitue une alternative importante au système d'achats in-app d'Apple.

En utilisant les Stripe Payment Links avec Capacitor, vous pouvez rapidement implémenter un tunnel d'achat fluide tout en respectant les directives d'Apple. Pour les utilisateurs hors des États-Unis, où le système d'achats in-app d'Apple s'applique toujours, @capgo/native-purchases implémente StoreKit et Google Play Billing directement. Cette approche vous donne également l'avantage de l'infrastructure de paiement robuste de Stripe, des frais de traitement réduits (3 % contre 30 %) et des reversements beaucoup plus rapides (en quelques jours plutôt qu'en plusieurs mois) par rapport au système d'achats in-app d'Apple.

N'oubliez pas que vous devrez gérer directement tout le support client et les demandes de remboursement, car ces transactions s'effectuent en dehors de l'écosystème d'Apple.

Avez-vous implémenté les Stripe Payment Links dans votre app Capacitor ? Partagez votre expérience dans les commentaires ci-dessous !

FAQ

Q : Cette approche est-elle conforme aux directives d'Apple ?
R : Oui, depuis le 1er mai 2025, Apple autorise le lien vers des méthodes de paiement externes pour les biens et services numériques dans les apps distribuées sur l'App Store aux États-Unis, à condition d'inclure les informations obligatoires.

Q : Dois-je payer la commission d'Apple lorsque j'utilise des méthodes de paiement externes ?
R : Non, l'un des principaux avantages de ces nouvelles règles est que les paiements traités en dehors du système d'Apple ne sont pas soumis à leur commission.

Q : Mon entreprise doit-elle être basée aux États-Unis pour profiter de ces nouvelles règles ?
R : Non, n'importe quelle entreprise, peu importe où elle se trouve dans le monde, peut implémenter des méthodes de paiement externes, à condition que votre application soit disponible sur l'App Store US et que les utilisateurs effectuant les achats soient situés aux États-Unis. La décision s'applique à la marketplace (App Store US) et à la localisation des utilisateurs, et non à la localisation de votre entreprise. Cela signifie que les développeurs d'Europe, d'Asie, d'Amérique du Sud ou d'ailleurs peuvent utiliser les Stripe Payment Links pour leurs clients basés aux États-Unis.

Q : Que se passe-t-il si un utilisateur situé hors des États-Unis tente d'utiliser l'option de paiement externe ?
R : Vous devez implémenter une détection de région (comme illustré dans l'article) pour ne proposer les options de paiement externes qu'aux utilisateurs situés aux États-Unis. Pour les autres régions, vous devez continuer à utiliser le système d'achat in-app d'Apple.

Q : Puis-je utiliser cela pour des biens physiques ou des services consommés en dehors de l'application ?
R : Oui, Apple a toujours autorisé les méthodes de paiement externes pour les biens et services physiques consommés en dehors de l'application (comme le VTC ou la livraison de repas).

Continuez après Stripe Payments dans Capacitor : Nouvelles directives d'Apple

Si vous utilisez Stripe Payments dans Capacitor : Nouvelles directives d'Apple pour planifier la sécurité et la conformité, connectez-l’à Chiffrement pour les détails d'implémentation dans Chiffrement, Conformité pour le détail d’implémentation dans Compliance, Scanner de sécurité Capgo pour le workflow produit dans Capgo Security Scanner, Capgo Sécurité pour le workflow produit dans Capgo Security, et Capgo Centre de confiance pour le workflow produit dans Capgo Trust Center.

Live updates pour les apps Capacitor

Quand un bug de la couche web est en production, déployez le correctif via Capgo au lieu d'attendre des jours l'approbation des stores. Les utilisateurs reçoivent la mise à jour en arrière-plan, tandis que les changements natifs suivent le circuit de validation habituel.

Les derniers articles du blog

Capgo vous apporte les meilleures informations pour créer une application mobile vraiment professionnelle.