Aller au contenu principal
Tutoriel

Stripe Payments dans Capacitor : nouvelles directives d'Apple

Découvrez comment intégrer les liens de paiement Stripe dans votre application Capacitor pour traiter les paiements de biens numériques conformément aux nouvelles directives d’Apple, en vigueur depuis le 1er mai 2025.

Paiements Stripe dans Capacitor : nouvelle illustration du blog sur les directives Apple Capgo

Depuis le 1er mai 2025, Apple a apporté des modifications importantes à ses directives de l’App Store à la suite de la décision de justice dans Epic c. Apple. Ces changements autorisent spécifiquement les développeurs d’applications aux États-Unis à renvoyer vers des méthodes de paiement externes pour les biens et services numériques, ouvrant ainsi la voie à des alternatives au système d’achat in-app d’Apple.

La bataille d’Epic qui a changé les paiements mobiles à jamais

Le chemin qui a mené à ce moment a été long et controversé. Tout a commencé en août 2020, lorsque Epic Games, créateur du jeu Fortnite, a délibérément enfreint les directives de l’App Store d’Apple en implémentant une option de paiement direct qui contournait la commission de 30 % d’Apple. Apple a immédiatement retiré Fortnite de l’App Store, et Epic a répondu en déposant une plainte contestant le contrôle d’Apple sur la distribution des 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 tranché : Apple doit autoriser les développeurs à orienter les utilisateurs vers des méthodes de paiement alternatives, en dehors de leurs applications. Cette décision bouleverse fondamentalement l’économie de l’écosystème App Store, qui fonctionnait 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 importante, 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 au début de 2025, entérinant ainsi la décision de la cour d’appel comme loi applicable. Cela signifie que les développeurs peuvent mettre en œuvre des méthodes de paiement externes en toute confiance, sachant qu’Apple ne pourra pas renverser cette décision par de nouvelles contestations juridiques.

Égalité de traitement garantie par la loi

Surtout, la décision stipule explicitement qu’Apple ne peut pas discriminer les applications qui utilisent des méthodes de paiement externes. La cour a spécifiquement interdit à Apple de :

  1. Facturer des frais supplémentaires ou imposer des conditions additionnelles aux applications utilisant des méthodes de paiement externes
  2. Accorder un traitement préférentiel dans les résultats de recherche ou mettre en avant les applications utilisant exclusivement le système d'IAP d'Apple
  3. Utiliser des mesures techniques pour dégrader les expériences de paiement externes par rapport au 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 intégrer 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'une des plus grandes remises en cause 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 ouvre la voie à de meilleures marges et à un contrôl’accru de l'expérience client.

Avantages financiers de Stripe face 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), alors que Stripe ne prend qu'environ 2,9 % + 0,30 $ par transaction. Cette différence peut augmenter sensiblement vos marges.

  • Versements plus rapides: Avec Apple, vous attendez généralement 45 à 90 jours pour recevoir vos fonds. Stripe, en revanche, dépose les paiements sur votre compte bancaire en 2 à 3 jours ouvrés.

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

Ces économies et cette amélioration du cash-flow peuvent faire toute la différence, surtout pour les petits développeurs et les PME.

Dans cet article, nous allons explorer comment implémenter les Payment Links de Stripe dans votre application Capacitor afin de tirer parti de ces nouvelles règles, tout en garantissant la conformité aux directives mises à jour.

Cette implémentation s’appuie sur la documentation officielle de Stripe pour les Payment Links, adaptée spécifiquement aux applications Capacitor.

Comprendre les nouvelles directives

Les App Store Review Guidelines mises à jour autorisent désormais les développeurs à rediriger les utilisateurs vers des sites web externes pour le traitement des paiements, en particulier pour les biens numériques et les abonnements. Cette modification ne s’applique actuellement qu’aux applications distribuées sur l’App Store américain.

Points clés à retenir :

  1. Vous pouvez désormais lier des options de paiement externes pour les biens numériques au sein de votre app
  2. Cela ne s'applique qu'aux applications de l'App Store américain
  3. Vous devez toujours respecter les exigences de divulgation d'Apple
  4. Vous restez responsable du support client et du traitement des remboursements

Plongeons dans l'implémentation technique :

Commencez par créer un lien de paiement dans votre dashboard Stripe :

  1. Rendez-vous dans la section Payment Links de votre dashboard Stripe
  2. Cliquez sur « + New » pour créer un nouveau 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 universal link 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
    • Rendez-vous dans « Signing & Capabilities »
    • Cliquez sur « + Capability » puis sélectionnez « Associated Domains »
    • Ajoutez 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 : intégrer 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 automatiquement disponibles. Cela crée une expérience de paiement plus fluide, où les utilisateurs n’ont pas besoin de ressaisir leurs informations de carte bancaire, réduisant ainsi considérablement la friction et les taux d’abandon.

Configurez votre application pour gérer les Universal Links lorsque les utilisateurs sont redirigés :

  1. Installez d’abord 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 : Configurer un webhook pour la confirmation de commande

Enfin, configurez un webhook sur votre serveur pour traiter 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 c. Apple a fondamentalement transformé le paysage des paiements mobiles. Elle n’affecte pas seulement les applications iOS, mais renforce aussi la position des développeurs Android qui utilisent déjà 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 créé par la décision Apple protège en pratique les développeurs de 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 qu'Apple sur les méthodes de paiement externes. Avec ce précédent juridique, il n'y a pratiquement aucun risque à implémenter Stripe ou d'autres prestataires de paiement externes dans vos applications Android. Vous pouvez avancer sereinement, en sachant que vous êtes 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'impose pas les mêmes restrictions sur les méthodes de paiement externes, vous pouvez utiliser exactement la même approche 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. Configurer les App Links dans votre AndroidManifest.xml pour gérer l'URL de redirection
  2. Créer un .well-known/assetlinks.json fichier sur votre domaine avec les détails de votre application
  3. Utilisez le même appUrlOpen logique de listener 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 application 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

Les nouvelles directives d’Apple ne s’appliquant qu’aux applications de l’App Store américain, vous devez mettre en place 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 pour déterminer le pays de l’utilisateur à partir de son adresse IP. Vous pouvez également utiliser d’autres services de géolocalisation comme MaxMind, ou implémenter cette vérification côté serveur pour plus de sécurité.

Remarque : Bien que cette approche fonctionne, il est important de rappeler que la géolocalisation par IP n’est pas toujours 100 % précise. 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 de Capacitor en combinaison avec @capgo/capacitor-nativegeocoder afin de déterminer le pays de l’utilisateur avec une précision accrue :

  1. D’abord, installez les plugins nécessaires :
npm install @capacitor/geolocation @capgo/capacitor-nativegeocoder
  1. Configurez les plugins dans votre projet Capacitor. Ajoutez ce qui suit à 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 une méthode plus précise pour déterminer si un utilisateur se trouve physiquement aux États-Unis. Elle tente d’abord d’utiliser le GPS de l’appareil et le géocodeur natif pour identifier le pays. En cas d’échec (problèmes de permissions ou autres erreurs), elle bascule sur la détection basée sur l’IP.

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

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 vous offre la méthode la plus précise pour déterminer si un utilisateur est éligible aux options de paiement externes conformément aux nouvelles directives d’Apple.

Gestion des abonnements

Un avantage clé de l’utilisation de Stripe pour les paiements est la possibilité d’offrir et de gérer des abonnements. Voici comment gérer les abonnements dans votre application Capacitor :

1. Créer une page de gestion des abonnements

Ajoutez une page de gestion des abonnements 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. Customer Portal pour la gestion des abonnements

Stripe propose un Customer Portal 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 vous assurer que votre implémentation respecte les directives d'Apple :

  1. Inclure les mentions appropriées concernant les achats externes
  2. Mettre en place une modale informant les utilisateurs qu'ils quittent l'application (comme exigé par Apple)
  3. Ne pas tenter de contourner la commission d'Apple sur les achats effectués dans l'application
  4. Indiquer clairement aux utilisateurs qu'Apple n'est pas responsable de la transaction

Voici un exemple d'implémentation de la modale d'information 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 mention requise puis ouvrir la page de paiement Stripe
  2. Effectuer 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 le 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 mettre en place un parcours de paiement 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, de frais de traitement réduits (3 % contre 30 %) et de reversements bien 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 vous-même le support client et les remboursements, car ces transactions ont lieu 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 les liens 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 mentions 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 à sa commission.

Q : Mon entreprise doit-elle être basée aux États-Unis pour bénéficier de ces nouvelles règles ?
R : Non, une entreprise, où qu'elle soit dans le monde, peut mettre en place des méthodes de paiement externes, à condition que votre application soit disponible sur l'App Store américain et que les utilisateurs qui effectuent les achats soient situés aux États-Unis. La décision s'applique à la marketplace (App Store américain) et à la localisation des utilisateurs, pas à celle de votre entreprise. Cela signifie que les développeurs d'Europe, d'Asie, d'Amérique du Sud ou d'ailleurs peuvent mettre en place des Stripe Payment Links pour leurs clients basés aux États-Unis.

Q : Que se passe-t-il si un utilisateur en dehors 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'achats intégrés 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 : les 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 du chiffrement, Conformité pour les détails d'implémentation de la conformité, Scanner de sécurité Capgo pour le workflow produit dans Capgo Security Scanner, Capgo et la 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

Lorsqu'un bug de la couche web est en ligne, 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 offre les meilleures informations pour créer une application mobile vraiment professionnelle.