Capacitor 앱에서 새로운 애플 지침에 따라 스트라이프 결제 링크를 구현하는 방법
2025년 5월 1일부터 애플은 에픽 대 애플 사례의 법정 판결을 따라 앱 스토어 리뷰 지침을 크게 변경했습니다. 에픽 대 애플.
이러한 변경 사항은 미국 앱 개발자에게 디지털 상품 및 서비스를 위한 외부 결제 방법에 대한 링크를 제공할 수 있도록 허용하여 애플의 내 앱 구매 시스템에 대한 대안을 열어주고 있습니다.
모바일 결제를 영원히 바꾼 에픽의 전투
이 순간에 이르기까지의 길은 길고 논쟁적이었습니다. 에픽 게임즈, 포트나이트의 만화적인 인기 게임의 제작자, 2020년 8월에 애플의 앱 스토어 지침을 위반하기 위해 직접 결제 옵션을 구현했습니다. 이 옵션은 애플의 30% 수수료를 피하기 위해 애플의 내 앱 구매 시스템을 우회했습니다. 애플은 포트나이트를 앱 스토어에서 제거하고 에픽은 애플의 iOS 앱 배포 및 내 앱 결제에 대한 통제를 도전하는 소송을 제기했습니다.
법정 판결이 나온 후 수년간의 법적 투쟁, 항소, 반항소가 끝나고, 법원은 애플이 개발자에게 사용자에게 외부 앱에서 대안적인 결제 방법에 대한 링크를 제공할 수 있도록 허용해야 한다고 판결했습니다. 이 판결은 2008년부터 시작된 앱 스토어 생태계의 경제를 완전히 바꾸고 있습니다. 이 생태계는 기본적인 금융 모델을 유지해 왔습니다.
이 판결이 특히 중요한 이유는 그것이 최종적이고 더 이상 항소할 수 없기 때문입니다. 2025년 초에 Apple의 항소가 미국 대법원에서 거부되면서, 하급 법원의 판결이 법률의 원칙이되었습니다. 따라서 개발자는 Apple이 이 결정에 대한 추가 법적 도전을 통해 거부할 수 없다는 확신으로 외부 결제 방법을 implement할 수 있습니다.
법률에 의해 평등한 대우를 보장합니다.
가장 중요한 것은 Apple이 외부 결제 방법을 사용하는 앱에 대해 차별하지 못한다는 판결이 명확히 밝혀졌다는 것입니다. 법원은 Apple이 다음과 같은 것을 금지했습니다:
- 외부 결제 방법을 사용하는 앱에 대해 추가 요금을 부과하거나 추가 요건을 부과하지 않습니다.
- Apple의 IAP 시스템만 사용하는 앱에만 선호하는 검색 결과 또는 특집을 제공하지 않습니다.
- Apple의 시스템보다 외부 결제 경험을 불리하게 하는 기술적 조치를 취하지 않습니다.
- 기본 소비자 정보 이외의 부담스러운 공개 요건을 부과하지 않습니다.
이러한 명확한 보호 조치로 인해 개발자는 Apple의 배후에서 조심스럽게 복수 또는 차별을 두지 않고 Stripe 또는 다른 외부 결제 제공자를 implement할 수 있습니다. 경쟁 장애가 법적으로 평준화되었으며 Apple은 앱의 결제 방법 선택에 관계없이 모든 앱을 동일하게 다루어야 합니다.
이 판결은 애플의 벽돌 가든 접근 방식에 대한 가장 큰 도전 중 하나를 대표하고 모바일 앱 수익화가 어떻게 작동할 수 있는지에 대한 전환의 중요한 지점을 표시합니다. 개발자들은 오랫동안 애플의 30% 수수료에 대해 불만을 표명해 왔는데 (작은 기업에 대한 경우 15%), 이 판결은 더 높은 수익 마진과 고객 경험에 대한 더 많은 통제를 제공하는 경로를 제공합니다.
스트리핑을 사용하는 데 따른 금전적 이익
이 변화의 금전적 영향은 개발자에게 다음과 같은 것들이 있습니다:
-
낮은 결제 처리 수수료: 애플은 일반적으로 30%의 수수료를 인앱 구매에 대해 청구합니다 (작은 기업의 경우 15%), 반면 스트리핑의 수수료는 거래당 약 2.9% + $0.30입니다. 이 차이는 수익 마진이 크게 증가할 수 있습니다.
-
빠른 지불: 애플에서는 일반적으로 45-90일 동안 지불을 받습니다. 스트리핑은 반면에 2-3일 이내에 지불을 받습니다.
-
단순화된 환불 처리: 환불을 스트리핑의 대시보드에서 직접 처리할 수 있습니다. 애플의 더 복잡한 환불 시스템을 통해 처리하는 대신.
이러한 비용 절감과 향상된 현금 흐름은 특히 작은 개발자와 기업에게 게임 체인저일 수 있습니다.
이 기사에서는 Capacitor 앱에서 스트리핑 결제 링크를 구현하는 방법을 설명합니다. 애플의 업데이트된 지침에 따라 이 새로운 규칙을 활용하는 동시에. 이 기사에서는 __CAPGO_KEEP_0__ 앱에서 스트리핑 결제 링크를 구현하는 방법을 설명합니다. 애플의 업데이트된 지침에 따라 이 새로운 규칙을 활용하는 동시에..
이 구현은 Stripe의 공식 Payment Links 문서Capacitor 앱을 위해 특별히 적응된
새로운 지침을 이해하는
업데이트된 App Store Review Guidelines는 개발자에게 사용자에게 외부 웹사이트로 결제 처리를 위한 링크를 제공할 수 있도록 허용합니다. 특히 디지털 상품 및 구독에 대한 결제입니다. 이 변경 사항은 현재 미국 App Store에 배포된 앱에만 적용됩니다.
중요한 점을 이해하세요:
- 디지털 상품 내에서 앱에서 외부 결제 옵션에 대한 링크를 제공할 수 있습니다.
- 이 규칙은 미국 App Store에 배포된 앱에만 적용됩니다.
- 애플의 disclosure 요구 사항을 준수해야 합니다.
- 고객 지원 및 환불 처리에 대한 모든 책임은 여전히 개발자에게 있습니다.
Capacitor 앱에서 Stripe Payment Links를 설정하는 방법
기술 구현에 대해 자세히 알아보겠습니다.
Step 1: Stripe 결제 링크를 Stripe 대시보드에서 생성하세요.
먼저 Stripe 대시보드에서 결제 링크를 생성하세요:
- Stripe 대시보드에서 결제 링크 섹션으로 이동하세요.
- ‘+ New’을 클릭하여 새로운 결제 링크를 생성하세요.
- 상품 또는 구독 정보를 정의하세요.
- ‘결제 후’ 설정에서 ‘결제 확인 페이지를 표시하지 않음’을 선택하세요.
- 성공 URL로 universal 링크를 설정하세요 (이후에 구성할 예정입니다).
- ‘결제 링크 생성’ 버튼을 클릭하여 결제 링크를 생성하세요.
Step 2: Set Up Universal Links in Your Capacitor App
결제 완료 후 사용자에게 앱으로 리다이렉트 하기 위해 universal 링크를 구성하세요:
- 도메인에 파일을 생성하세요:
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"
}
]
}
]
}
}
-
파일을 이곳에 호스팅하세요
https://yourdomain.com/.well-known/apple-app-site-association -
정확한 MIME 타입으로 서비스가 되는지 확인하세요
application/json -
Capacitor 앱을 구성하여 Universal 링크를 처리하도록 하세요. 첫 번째로, 다음을 추가하세요.
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;
- __CAPGO_KEEP_0__ 앱의 Associated Domains 권한을 추가하세요:
- __CAPGO_KEEP_0__ 프로젝트를 열어보세요
- __CAPGO_KEEP_0__ 앱 목표를 선택하세요
- ‘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');
}
Why Safari Matters: Safari를 통해 (via
window.open) 대신 앱 내 브라우저를 통해 결제 링크를 열 때, 사용자가 이전에 스티프 링크에서 결제 정보를 저장한 경우에는 자동으로 인증 정보가 제공됩니다. 이로 인해 사용자가 다시 신용 카드 정보를 입력하지 않아도 체크아웃 경험을 더 편리하게 사용할 수 있으며, 사용자 탈출률을 크게 줄일 수 있습니다.
Step 5: 앱에서 Universal Links를 처리하세요
사용자가 다시 리다이렉트 될 때 universal links를 처리하기 위해 앱을 구성하세요:
- 첫 번째로 App 플러그인을 설치하세요:
npm install @capacitor/app
- 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
}
Step 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 v. Apple 판결은 결제 모바일 랜드스케이프를根本적으로 바꾸었습니다. iOS 앱에 직접적인 영향을 미치는 것은 물론, Android 개발자에게도 외부 결제 방법을 사용하는 것을 강화했습니다.
안드로이드 개발자들은 이제 완전한 자신감으로 외부 결제 솔루션을 구현할 수 있습니다. 애플 판결의 전례는 개발자들이 플랫폼을 막론하고 미래의 제약으로부터 보호합니다. 이 법적 판결은 많은 안드로이드 개발자가 이미 몇 년 동안 수행해 왔던 것과 동일한 결과를 냈습니다 - 낮은 수수료의 대체 결제 옵션을 제공합니다.
구글 플레이 스토어는 항상 애플보다 외부 결제 방법에 대한 제약이 적었으며, 법적 전례가established되면서 이제는 Stripe 또는 다른 외부 결제 제공자들을 구현하는 데 virtually의 위험이 없습니다. 이 구현을 통해 안드로이드 앱에 대한 결제 링크를 구현할 수 있습니다.
iOS에 대한 구현은 안드로이드 기기에도 거의 동일하게 작동합니다. 구글 플레이 스토어는 외부 결제 방법에 대한 제약이 없기 때문에, Stripe Payment Links 접근 방식을 사용할 수 있습니다. 특별한 disclosure dialogs가 필요하지 않습니다.
깊이 연결 처리를 위해 (iOS의 universal links와 동일한 기능), 다음을 수행해야 합니다:
- App Links를 설정하여
AndroidManifest.xmlredirect URL을 처리하기 위해 - 도메인에 앱의 세부 정보를 포함하는
.well-known/assetlinks.json파일을 생성합니다. - 성공적인 결제를 처리하기 위해 동일한
appUrlOpenlistener logic을 사용합니다.
Capacitor의 아름다움은 플랫폼별 구성이 구현된 후 실제 결제 흐름 code이 두 플랫폼 모두에서 동일하게 유지됩니다.
결제 UI 만들기
Vue에서 사용할 수 있는 예시 결제 버튼 컴포넌트를 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>
다양한 지역을 처리하기
새로운 Apple 지침은 미국 앱 스토어에만 적용되므로 사용자 지역을 감지하고 적절한 결제 방법을 적용하는 전략이 필요합니다. 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% 정확하지 않습니다. mission-critical 애플리케이션의 경우, 여러 감지 방법을 사용하거나 사용자에게 지역을 수동으로 선택하도록 허용하는 것이 좋습니다.
더 정확한 위치 감지와 Capacitor 플러그인
더 정확한 위치 감지를 위해 Capacitor Geolocation 플러그인을 사용하여 @capgo/capacitor-nativegeocoder와 함께 사용하여 사용자의 국가를 더 높은 정확도로 결정하세요:
- 첫 번째로, 필요한 플러그인을 설치하세요:
npm install @capacitor/geolocation @capgo/capacitor-nativegeocoder
- Capacitor 프로젝트에서 플러그인을 구성하세요. 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;
- 위치 기반 지역 감지를 구현하세요:
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 파일에 추가하세요: AndroidManifest.xml iOS (
Android (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/app/src/main/AndroidManifest.xml):
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
구독 관리
Stripe를 사용하는 결제의 주요 이점 중 하나는 구독을 제공하고 관리할 수 있다는 것입니다. 다음은 __CAPGO_KEEP_0__ 앱에서 구독 관리를 처리하는 방법입니다:
One key advantage of using Stripe for payments is the ability to offer and manage subscriptions. Here’s how to handle subscription management in your Capacitor app:
앱에 구독 관리 페이지를 추가하여 사용자의 활성 구독을 표시하세요:
구독 관리
<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;
}
애플의 지침을 준수하기 위해 구현을 보장하는 방법
외부 구매에 대한 적절한 고지를 포함하십시오
- 사용자가 앱을 떠나는 것을 알리는 모달 시트를 implement하십시오 (애플에 의해 요구됨)
- 앱 내에서 구매한 경우 애플의 수수료를 circumvent하지 마십시오
- 사용자에게 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);
}
}
앱 내의 결제 버튼을 클릭하여, 고지를 표시하고 Stripe 결제 페이지를 열어보십시오
2. 구독 관리를 위한 고객 포털
- Stripe은 고객이 구독을 관리할 수 있는 고객 포털을 제공합니다. 서버에서 이 포털에 대한 링크를 생성할 수 있습니다:
- Stripe 테스트 카드를 사용하여 테스트 결제를 완료하세요.
4242 4242 4242 4242 - 결제 후, Universal Link를 통해 앱으로 돌아가야 합니다.
- 결제 후, 웹후크가 이벤트를 받았는지 확인하세요.
checkout.session.completed이벤트
결론
iOS 앱에서 디지털 상품에 대한 외부 결제 옵션을 사용할 수 있는 능력은 개발자에게 더 많은 유연성을 제공하는 중요한 변화입니다. 이 변화는 현재 미국 앱 스토어에만 적용되지만, 애플의 내 앱 구매 시스템에 대한 중요한 대안을 제공합니다.
Capacitor에서 Stripe Payment Links를 사용하여, Apple의 지침을 준수하면서도 streamlined checkout 경험을 빠르게 구현할 수 있습니다. 미국 밖의 사용자에게는 여전히 애플의 내 앱 구매 시스템이 적용되므로, @Capacitor/native-purchases는 StoreKit와 Google Play Billing을 직접 implement합니다. 이 접근 방식은 Stripe의 강력한 결제 인프라, 낮은 처리 수수료 (3% vs 30%), 빠른ayout (일주일대 vs 월대)와 같은 장점을 제공합니다. @capgo/native-purchases __CAPGO_KEEP_0__ 앱에서 Stripe Payment Links를 구현했나요? 아래 댓글에서 경험을 공유해 보세요!
FAQs
Have you implemented Stripe Payment Links in your Capacitor app? Share your experience in the comments below!
FAQs
Q: 이 방법은 애플의 지침에 부합합니까?
A: 2025년 5월 1일부터, 애플은 미국 앱 스토어에서 배포되는 앱에서 디지털 상품 및 서비스에 대한 외부 결제 방법에 대한 링크를 포함하는 경우, 미국 앱 스토어에서 배포되는 앱에서 디지털 상품 및 서비스에 대한 외부 결제 방법에 대한 링크를 포함하는 경우, 애플의 지침에 부합합니다. 필요한 고지 사항을 포함해야 합니다.
Q: 외부 결제 방법을 사용할 때 애플의 수수료를 지불해야 합니까?
A: 새로운 규칙의 주요 이점 중 하나는 애플의 시스템 외부에서 처리되는 결제는 애플의 수수료를 받지 않는다는 것입니다.
Q: 이 새로운 규칙을 사용하려면 회사 본사가 미국에 위치해야 합니까?
A: 미국 앱 스토어에서 앱을 배포하고 미국에 거주하는 사용자가 결제를 하는 경우, 세계 어디서나 회사가 이 새로운 규칙을 사용할 수 있습니다. 규정은 사용자의 위치와 시장 (미국 앱 스토어)뿐만 아니라 회사 위치와 관련이 없습니다. 유럽, 아시아, 남미, 또는 어디서든 개발자가 미국 고객을 위해 스트라이프 결제 링크를 구현할 수 있습니다.
Q: 미국 밖의 사용자가 외부 결제 옵션을 사용하려고 할 때 어떻게 되나요?
A: 미국 사용자만 외부 결제 옵션을 제공하기 위해 지역 감지 (이 기사에서 설명한 것)를 implement해야 합니다. 다른 지역의 경우 애플의 인앱 구매 시스템을 계속 사용해야 합니다.
Q: 이 방법을 물리적 상품 또는 앱 외부에서 소비되는 서비스에 사용할 수 있나요?
A: 예, 애플은 항상 앱 외부에서 소비되는 물리적 제품 및 서비스에 대한 외부 결제 방법을 허용했습니다 (예: 택시 타기나 음식 배달).
Keep going from Stripe Payments in Capacitor: New Apple Guidelines
이미 스트리프 결제를 사용 중이라면 Stripe Payments in Capacitor: New Apple Guidelines 보안 및 규정 준수 계획을 위해 보안을 계획하고 규정 준수를 계획하려면 암호화 암호화 구현 세부 정보에서 규정 준수 규정 준수 구현 세부 정보에서 Capgo 보안 스캐너 Capgo 보안 스캐너에서 제품 워크플로우 Capgo 보안 Capgo 제품 워크플로우에서 Capgo 보안에 대해 Capgo 신뢰 센터 Capgo 제품 워크플로우에서 Capgo 신뢰 센터에 대해