メインコンテンツへスキップ
チュートリアル

Capacitor での Stripe 決済:Apple の新ガイドライン

2025年5月1日から施行されるAppleの新しいガイドラインに準拠し、Capacitor アプリでデジタルコンテンツの決済を行うための Stripe Payment Links の実装方法を学びましょう。

Capacitor での Stripe Payments: 新しい Apple ガイドラインに関する Capgo ブログの図解

Apple の新ガイドラインに従った Capacitor アプリへの Stripe Payment Links 実装方法

2025年5月1日より、Apple は次の裁判判決を受けて App Store Review Guidelines に大幅な変更を加えました: Epic v. Apple 事件。これらの変更により、米国のアプリ開発者はデジタル商品やサービスについて外部決済手段へのリンクを貼ることが認められ、Apple のアプリ内課金に代わる選択肢が生まれました。

モバイル決済を永遠に変えたEpicとの激闘

この瞬間に至るまでの道のりは、長く、激しい争いの連続でした。すべては2020年8月、大ヒット作『Fortnite』の開発元であるEpic Gamesが、Appleの30%の手数料を回避するために直接決済オプションを導入し、App Storeのガイドラインに意図的に違反したことから始まりました。Appleは即座にApp StoreからFortniteを削除しましたが、Epicはこれに対し、iOSアプリの配信とアプリ内課金におけるAppleの支配権を問う訴訟を起こして対抗しました。

長年にわたる法廷闘争、控訴、反控訴を経て、裁判所はついに、Appleは開発者がアプリ外の代替決済手段へユーザーを誘導することを許可しなければならないとの判決を下しました。この決定は、2008年の誕生以来、基本的に同じ収益モデルで運営されてきたApp Storeエコシステムの経済性を根本から変えるものです。

最終判決 — 控訴の余地なし

今回の判決が特に重要なのは、これが最終的なものであり、これ以上の控訴ができない点にあります。2025年初頭、最高裁判所はAppleによる控訴の審理を棄却し、下級審の決定が確定しました。これにより、開発者はAppleがさらなる法的手段でこの決定を覆すことはできないという確信を持って、外部決済手段を実装できるようになります。

法律が保証する平等な扱い

最も重要な点は、判決の中で、Appleは外部決済手段を利用するアプリを差別してはならないと明記されていることです。裁判所は、Appleによる以下の行為を具体的に禁止しました。

  1. 外部決済手段を使うアプリに追加手数料を課したり、追加要件を課したりすること
  2. AppleのIAPシステムのみを使うアプリを検索結果で優遇したり、特集したりすること
  3. 技術的な手段を用いて、外部決済の体験をApple独自のシステムよりも劣るものにすること
  4. 基本的な消費者情報以外の、負担の大きい開示要件を課すこと

これらの明示的な保護策により、開発者はAppleからの目に見えない報復や差別を恐れることなく、Stripeなどの外部決済プロバイダーを導入できます。法の下で公平な競争環境が整い、Appleは決済手段の選択にかかわらず、すべてのアプリを平等に扱う必要があります。

この判決は、Appleの囲い込み戦略に対する最も重大な挑戦の一つであり、モバイルアプリの収益化のあり方に決定的な転換点をもたらします。Appleの30%手数料(小規模事業者は15%)に長年不満を抱えてきた開発者にとって、この判決は利益率の向上と顧客体験をより細かくコントロールする道を開くものです。

AppleのIn-App PurchasesではなくStripeを使う金銭面のメリット

この変更が開発者に及ぼす金銭面の影響は大きいです:

  • 決済手数料の削減Appleは通常、アプリ内課金に30%の手数料(小規模事業者は15%)を課しますが、Stripeの手数料は1取引あたり約2.9% + $0.30のみです。この差で収益マージンを大幅に高められます。

  • より迅速な入金: Appleの場合、通常、資金の受け取りまでに45〜90日かかります。一方、Stripeなら2〜3営業日以内に銀行口座へ入金されます。

  • 返金プロセスの簡素化: Appleの複雑な返金システムを通さず、Stripeのダッシュボードから直接返金処理を行えます。

こうしたコスト削減とキャッシュフローの改善は、特に小規模な開発者や企業にとって大きなメリットとなります。

この記事では、これらの新ルールを活用するために、Capacitor アプリに Stripe Payment Links を実装する方法を解説します。Appleの 更新されたガイドライン.

この実装方法は、 Stripe の Payment Links に関する公式ドキュメントをベースに、Capacitor アプリ向けに最適化したものです。

新しいガイドラインを理解する

更新された App Store Review Guidelines では、デジタル商品やサブスクリプションの決済処理のために、開発者がユーザーを外部サイトへ誘導することが許可されました。この変更は現在、米国の App Store で配信されるアプリにのみ適用されます。

重要なポイント:

  1. アプリ内でデジタル商品の外部決済オプションにリンクできるようになりました
  2. これは米国 App Store のアプリにのみ適用されます
  3. Apple の開示要件は引き続き遵守する必要があります
  4. カスタマーサポートと返金対応は引き続きすべて開発者の責任です

技術的な実装を見ていきましょう:

まず、Stripe Dashboard で Payment Link を作成します:

  1. Stripe Dashboard の Payment Links セクションに移動します
  2. 「+ New」をクリックして新しい Payment Link を作成します
  3. 商品またはサブスクリプションの詳細を設定します
  4. 「After payment」設定で「Don’t show confirmation page」を選択します
  5. ユニバーサルリンクを成功時のURLとして設定します(後ほど設定します)
  6. 「Create Link」をクリックして決済リンクを生成します

決済完了後にユーザーをアプリへリダイレクトするには、ユニバーサルリンクを設定します:

  1. 以下を作成: apple-app-site-association ドメイン上のファイル:
{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appIDs": ["YOURTEAMID.com.yourdomain.yourapp"],
        "components": [
          {
            "/": "/checkout_redirect*",
            "comment": "Matches any URL whose path starts with /checkout_redirect"
          }
        ]
      }
    ]
  }
}
  1. このファイルを以下でホストしてください: https://yourdomain.com/.well-known/apple-app-site-association

  2. 正しいMIMEタイプで配信されていることを確認してください application/json

  3. 適切なentitlementを追加して、Capacitor アプリがユニバーサルリンクを処理できるように設定します。まず、 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. XcodeプロジェクトにAssociated Domains entitlementを追加します:
    • Xcodeプロジェクトを開きます
    • アプリのターゲットを選択します
    • 「Signing & Capabilities」に移動します
    • 「+ Capability」をクリックし、「Associated Domains」を選択します
    • 追加 applinks:yourdomain.com

ステップ 3: フォールバックページを作成する

アプリがインストールされていない場合に備えて、リダイレクトURLにフォールバックページを作成します:

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

ステップ 4: Capacitor アプリに決済ボタンを実装する

次に、アプリに決済ボタンを追加します:

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

Safari が重要な理由: インアプリブラウザではなく Safari で( window.open)決済リンクを開くのが有利な理由は、Stripe Link に支払い情報を保存しているユーザーなら、認証情報が自動的に利用できるためです。これにより、クレジットカード情報を再入力する手間が省け、決済体験がスムーズになり、離脱率を大幅に下げることができます。

ユーザーがリダイレクトされて戻ってきた際に、Universal Links を処理できるようにアプリを設定します:

  1. まず、Appプラグインをインストールしてください:
npm install @capacitor/app
  1. アプリ内でAppプラグインを登録します:
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
}

ステップ6: 注文フルフィルメント用のWebhookを設定

最後に、決済成功を処理するためにサーバーにwebhookを設定します:

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

Androidの互換性

はっきりさせておきましょう。Epic 対 Apple の判決は、モバイル決済の状況を根本的に変えました。これはiOSアプリに直接影響するだけでなく、外部決済手段を利用してきたAndroid開発者の立場を強化するものでもあります。

Android開発者は、今や外部決済ソリューションを完全に安心して実装できます。 Appleの判決によって確立された先例は、プラットフォームを問わず、将来的な制限の可能性から開発者を実質的に保護します。この司法判断は、多くのAndroid開発者が長年行ってきた「より低い手数料で代替決済手段を提供する」という手法を正当化したのです。

Google Play StoreはAppleよりも外部決済手段への制限が緩く、今回法的先例が確立されたことで、AndroidアプリにStripeなどの外部決済プロバイダーを導入するリスクは事実上なくなりました。法的に確固たる根拠があると分かった上で、実装を進められます。

今回紹介したiOS向けの実装は、Androidデバイスでもほぼ同様に動作します。Google Play Storeには外部決済に関する同様の制限がないため、特別な開示ダイアログを用意することなく、まったく同じStripe Payment Linksの手法を利用できます。

ディープリンク(iOSのUniversal Linksに相当)を処理するには、以下が必要です:

  1. App Linksを AndroidManifest.xml リダイレクトURLを処理するために
  2. から、 .well-known/assetlinks.json アプリの詳細を含むドメイン上のファイルを
  3. 同じ appUrlOpen リスナーロジックを使用して決済完了を処理します

Capacitor の利点は、プラットフォーム固有の設定が完了すれば、実際の決済フローである code は両プラットフォームで共通のまま維持されることです。

決済UIの作成

Capacitor アプリに追加できる、Vueによる決済ボタンコンポーネントの例を以下に示します:

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

リージョンごとの対応

新しいAppleのガイドラインは米国のApp Storeにあるアプリにのみ適用されるため、ユーザーのリージョンを検出し、適切な決済方法を適用する戦略が必要です。ここでは、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);
  }
}

このアプローチでは、無料の ipapi.co IPアドレスに基づいてユーザーの国を特定するサービスです。MaxMindなどの他のジオロケーションサービスを使用したり、セキュリティを高めるためにサーバーサイドでこのチェックを実装したりすることも可能です。

注意: この手法は有効ですが、IPによるジオロケーションが常に100%正確とは限らない点に注意してください。ミッションクリティカルなアプリケーションでは、複数の検知方法を検討するか、ユーザーが手動でリージョンを選択できるようにすることを推奨します。

Capacitor プラグインによる、より正確な位置情報の検知

より正確な位置情報の検知を行うには、Capacitor Geolocation プラグインと @capgo/capacitor-nativegeocoder を組み合わせて使用することで、ユーザーの国をより高い精度で特定できます:

  1. まず、必要なプラグインをインストールします:
npm install @capacitor/geolocation @capgo/capacitor-nativegeocoder
  1. Capacitor プロジェクトでプラグインを設定します。以下を次に追加してください: 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. 位置情報に基づいたリージョン検知の実装:
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);
  }
}

この実装により、ユーザーが実際に米国に滞在しているかどうかを、より正確に判断できるようになります。まずデバイスのGPSとネイティブのジオコーダーを使用して国を特定しようと試みます。権限の問題やその他のエラーで失敗した場合は、IPベースの検知にフォールバックします。

必要な権限を以下に追加するのを忘れないでください: info.plist (iOS) と AndroidManifest.xml (Android) ファイル:

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>

Androidの場合(android/app/src/main/AndroidManifest.xml):

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

この手法を用いることで、新しいAppleのガイドラインに基づき、ユーザーが外部決済オプションを利用可能かどうかを最も正確に判断できます。

サブスクリプション管理

決済にStripeを使用する大きな利点の一つは、サブスクリプションの提供と管理ができる点です。Capacitor アプリでのサブスクリプション管理の手順は以下の通りです:

1. サブスクリプション管理ページの作成

ユーザーのアクティブなサブスクリプションを表示するために、アプリ内に管理ページを追加します:

<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. サブスクリプション管理用のカスタマーポータル

Stripeには、ユーザーが自身のサブスクリプションを管理できるカスタマーポータル機能があります。サーバー側からこのポータルへのリンクを作成できます:

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

App Storeのコンプライアンス確保

実装内容をAppleのガイドラインに準拠させるには:

  1. 外部購入に関する適切な開示事項を含める
  2. Appleの要件に従い、アプリを離脱することをユーザーに通知するモーダルシートを実装します
  3. アプリ内で行われる購入に対するAppleの手数料を回避しようとしないでください
  4. Appleは本取引に対して責任を負わないことをユーザーに明確に伝えます

必須となる開示モーダルの実装例は以下の通りです:

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

実装のテスト

実装を確認するには:

  1. アプリ内の決済ボタンをクリックし、開示メッセージが表示された後にStripeの決済ページが開くことを確認します
  2. Stripeのテストカードを使用してテスト決済を完了させます 4242 4242 4242 4242
  3. 決済後、ユニバーサルリンク経由でアプリにリダイレクトされることを確認します
  4. webhookが以下の checkout.session.completed event

まとめ

iOSアプリにおいて、デジタルコンテンツに外部決済オプションを利用できるようになったことは、開発者にさらなる柔軟性をもたらす大きな変化です。現在は米国のApp Storeに配信されるアプリのみが対象ですが、Appleのアプリ内課金システムに代わる重要な選択肢となります。

CapacitorでStripe Payment Linksを使用することで、Appleのガイドラインを遵守しながら、スムーズなチェックアウト体験を迅速に実装できます。Appleのアプリ内課金システムが適用される米国以外のユーザーに対しては、 @capgo/native-purchases StoreKitやGoogle Play Billingを直接実装します。このアプローチでは、Stripeの堅牢な決済インフラを活用できるほか、Appleのアプリ内課金と比較して、決済手数料が低く(30%に対し3%)、入金サイクルも大幅に早い(数ヶ月ではなく数日)というメリットがあります。

これらのトランザクションはAppleのエコシステム外で行われるため、カスタマーサポートや返金対応はすべて直接行う必要がある点に注意してください。

あなたのCapacitorアプリでStripe Payment Linksを実装しましたか?ぜひ下のコメント欄で体験をシェアしてください!

よくある質問

Q: この方法はAppleのガイドラインに準拠していますか?
A: はい。2025年5月1日より、米国App Storeで配信されるアプリにおいて、必要な開示事項を含めることを条件に、デジタルコンテンツやサービスへの外部決済手段へのリンクがAppleによって許可されています。

Q: 外部決済手段を使用する場合でも、Appleに手数料を支払う必要がありますか?
A: いいえ。新しいルールの大きなメリットの一つは、Appleのシステム外で処理される決済にはAppleの手数料がかからないことです。

Q: これらの新しいルールを活用するには、自社が米国に拠点を置いている必要がありますか?
A: いいえ、アプリがUS App Storeで提供されており、購入するユーザーが米国に所在している限り、世界中のどの企業でも外部決済方法を導入できます。この判決は、企業の所在地ではなく、マーケットプレイス(US App Store)とユーザーの所在地に適用されます。つまり、欧州、アジア、南米、その他の地域の開発者でも、米国在住の顧客向けにStripe Payment Linksを導入できます。

Q: 米国以外のユーザーが外部決済オプションを使おうとした場合はどうなりますか?
A: 米国のユーザーにのみ外部決済オプションを提供できるよう、(この記事で紹介しているような)リージョン判定を実装してください。その他の地域では、引き続きAppleのアプリ内課金システムを使用してください。

Q: アプリ外で消費される物理的な商品やサービスにもこれを使用できますか?
A: はい。Appleは以前から、アプリ外で消費される物理的な商品やサービス(配車サービスやフードデリバリーなど)に対しては、外部決済方法の使用を許可しています。

続きを読む: CapacitorのStripe Payments: Appleの新しいガイドライン

使用している場合 Capacitor での Stripe 決済:Apple の新ガイドライン セキュリティとコンプライアンスを計画するには、これを以下と連携させてください 暗号化 暗号化の実装詳細について コンプライアンス コンプライアンスの実装詳細について Capgo セキュリティスキャナー Capgo Security Scanner のプロダクトワークフローについて Capgo のセキュリティ Capgo Security のプロダクトワークフロー向け、および Capgo トラストセンター Capgo Trust Center のプロダクトワークフロー向け。

Capacitor アプリ向けの Live Updates

Web レイヤーのバグが本番で発生したら、App Store の審査を何日も待たずに Capgo で修正を配信しましょう。ネイティブの変更は通常の審査フローに残したまま、ユーザーはバックグラウンドでアップデートを受け取れます。

最新のブログ記事

Capgoは、真にプロフェッショナルなモバイルアプリを作るために必要な最高のインサイトを提供します。