# iOS でカスタマーポータルページでのサブスクリプションの管理を許可する カスタマーポータルを設定して、アプリからブラウザーで開きます。 アメリカまたは欧州経済領域 (EEA) で販売されるサブスクリプションを含むデジタル製品やコンテンツの場合、アプリは外部の支払いページにリダイレクトすることで Apple Pay を受け付けることができます。 このガイドでは、サブスクリプション管理用に [カスタマーポータル](https://docs.stripe.com/customer-management.md) を設定し、アプリから顧客をそのポータルにリダイレクトする方法について説明します。 ![1 回限りの支払い](https://b.stripecdn.com/docs-statics-srv/assets/subscriptions_hero.647ac1dba5270dbf75e15c456c6bcf0d.png) アプリからリンクしてサブスクリプションや決済手段を管理する ## 作成する内容 > このガイドでは、サブスクリプション管理についてのみ説明します。サブスクリプションの購入を設定する場合は、[事前構築された決済ページを使用して iOS でデジタル商品の決済を受け付ける](https://docs.stripe.com/mobile/digital-goods/checkout.md)をご覧ください。 このガイドでは以下の方法を説明します。 - 顧客がサブスクリプションの管理に使用できるカスタマーポータルページを設定する - *ユニバーサルリンク* (Use Universal links on iOS and macOS to link directly to in-app content. They're standard HTTPS links, so the same URL works for your website and your app)を使用して、ユーザーをカスタマーポータルからアプリにリダイレクトする - *Webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) を監視して、顧客のサブスクリプションステータスを更新する ## 対象範囲外の内容 このガイドでは、Stripe [カスタマーポータル](https://docs.stripe.com/customer-management.md)を設定し、アプリからポータルに接続する方法を説明します。以下は対象範囲に含まれません。 - **サブスクリプションの購入**: Stripe Checkout を使用してアプリ内の商品やサブスクリプションを販売するには、[iOS で事前構築された決済ページを使用してデジタル商品の決済を受け付ける](https://docs.stripe.com/mobile/digital-goods/checkout.md)をご覧ください。 - **ユーザー認証**: 既存の認証プロバイダーがない場合には、[Sign in with Apple (Apple でサインイン)](https://developer.apple.com/sign-in-with-apple/) や [Firebase Authentication](https://firebase.google.com/docs/auth) などのサードパーティプロバイダーを使用できます。 - **ネイティブのアプリ内購入**: StoreKit を使用してアプリ内購入を実装するには、[Apple のアプリ内課金](https://developer.apple.com/in-app-purchase/) ガイドをご覧ください。 ## ポータルを設定 まず、[Stripe アカウントを登録](https://dashboard.stripe.com/register/)する必要があります。 カスタマーポータルを実装する前に、ダッシュボードを使用して、ポータル内でユーザーに許可する操作を定義します。商品カタログと価格カタログに基づいて、*サンドボックス* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes)と本番環境の設定を選択します。 > Stripe Connect でカスタマーポータルを使用している場合は、連結アカウントではなく、プラットフォームのカスタマーポータルを設定してください。 顧客のセットごとに異なる複数のポータル設定を作成する場合、または *Connect* (Connect is Stripe's solution for multi-party businesses, such as marketplace or software platforms, to route payments between sellers, customers, and other recipients) プラットフォームとして連結アカウントの設定を管理する場合は、[API](https://docs.stripe.com/api/customer_portal/configurations/object.md) を使用して設定できます。 ```curl curl https://api.stripe.com/v1/billing_portal/configurations \ -u "<>:" \ -d "features[invoice_history][enabled]=true" ``` ### 商品カタログを設定する 顧客が定期支払いのアップグレード、ダウングレード、数量の変更を実行できるようにする場合は、商品カタログの設定も必要です。これには、顧客がアップグレードまたはダウングレードできる対象の商品と価格、および顧客が数量を更新できる定期支払いが掲載されます。商品と価格の作成について、詳細は[商品を作成する](https://docs.stripe.com/products-prices/manage-prices.md#create-product)方法をご覧ください。カスタマーポータルを請求処理にのみ使用している場合は、商品カタログを設定する必要はありません。 ポータルには、商品カタログの以下の属性が表示されます。 - **商品名と説明**: これらの属性は、ダッシュボードと API で編集できます。 - **商品ごとの数量制限**: これらの属性は、ダッシュボードで編集できます。 - **金額、通貨、請求期間**: これらの属性は固定されており、ダッシュボードと API で作成するときにのみ設定できます。 ### 納税者番号の収集を有効にする [Stripe Tax](https://docs.stripe.com/tax.md) を使用してサブスクリプションや請求書の税金を自動徴収する場合、カスタマーポータルで、顧客に納税番号の設定と更新を行ってもらえます。Stripe Billing はその顧客の*請求書* (Invoices are statements of amounts owed by a customer. They track the status of payments from draft through paid or otherwise finalized. Subscriptions automatically generate invoices, or you can manually create a one-off invoice)に納税者番号を追加します。顧客による納税者番号の設定を許可するには、[カスタマーポータルの設定](https://dashboard.stripe.com/settings/billing/portal)に移動して **納税者番号** をオンに切り替えます。詳細については、顧客の納税者番号が[サブスクリプション](https://docs.stripe.com/billing/customer/tax-ids.md)と[請求書](https://docs.stripe.com/invoicing/taxes/account-tax-ids.md)でどのように機能するかをご確認ください。 [Stripe Tax の設定](https://docs.stripe.com/tax/set-up.md)、[継続支払いの税金の徴収](https://docs.stripe.com/billing/taxes/collect-taxes.md)、[カスタムの決済フローでの税金の徴収](https://docs.stripe.com/tax/custom.md#existing-customer)、および[ラインアイテムと請求書の税率の設定](https://docs.stripe.com/tax/invoicing.md)の方法についてご紹介します。 ### プレビューしてテストする 設定を行う際に、**プレビュー** をクリックしてポータルをプレビューします。これにより、ポータルの読み取り専用バージョンが表示され、顧客がサブスクリプションや請求の詳細をどのように管理しているかを確認できます。 設定の保存後に、サンドボックスの顧客を使用してポータルを起動し、テストできます。ダッシュボードで顧客に移動し、**アクション**をクリックしてから、**カスタマーポータルを開く**を選択します。 ポータルを読み取り専用バージョンとしてプレビューできるのは、ダッシュボードをサンドボックス内で使用する場合のみです。ポータルをプレビューしてテストできない場合は、設定をチェックして、ポータル設定がサンドボックスに保存されていることを確認してください。プレビューとテストを有効にするには、ダッシュボードでの編集権限も変更する必要があります。 ## Stripe を設定する [サーバー側] ### サーバー側 #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` 次に、Stripe CLI をインストールします。CLI は必要な [Webhook](https://docs.stripe.com/webhooks.md#test-webhook) のテストを提供します。 その他のインストールオプションについては、[Stripe CLI を使ってみる](https://docs.stripe.com/stripe-cli.md)をご覧ください。 ### クライアント側 [Stripe iOS SDK](https://github.com/stripe/stripe-ios) はオープンソースです。[詳細なドキュメントが提供されており](https://stripe.dev/stripe-ios/index.html)、iOS 13 以降をサポートするアプリと互換性があります。 #### Swift Package Manager SDK をインストールするには、以下のステップに従います。 1. Xcode で、**File (ファイル)** > **Add Package Dependencies… (パッケージ依存関係を追加)** を選択し、リポジトリー URL として `https://github.com/stripe/stripe-ios-spm` を入力します。 1. [リリースページ](https://github.com/stripe/stripe-ios/releases)から最新のバージョン番号を選択します。 1. **StripePaymentSheet** 製品を[アプリのターゲット](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app)に追加します。 #### CocoaPods 1. まだインストールしていない場合は、[CocoaPods](https://guides.cocoapods.org/using/getting-started.html) の最新バージョンをインストールします。 1. 既存の [Podfile](https://guides.cocoapods.org/syntax/podfile.html) がない場合は、以下のコマンドを実行して作成します。 ```bash pod init ``` 1. この行を `Podfile` に追加します。 ```podfile pod 'StripePaymentSheet' ``` 1. 以下のコマンドを実行します。 ```bash pod install ``` 1. これ以降は、Xcode でプロジェクトを開く際に、`.xcodeproj` ファイルではなく、必ず `.xcworkspace` ファイルを使用するということを忘れないでください。 1. 今後、SDK の最新バージョンに更新するには、以下を実行します。 ```bash pod update StripePaymentSheet ``` #### Carthage 1. まだインストールしていない場合は、[Carthage](https://github.com/Carthage/Carthage#installing-carthage) の最新バージョンをインストールします。 1. この行を `Cartfile` に追加します。 ```cartfile github "stripe/stripe-ios" ``` 1. [Carthage のインストール手順](https://github.com/Carthage/Carthage#if-youre-building-for-ios-tvos-or-watchos)に従います。必ず、[こちら](https://github.com/stripe/stripe-ios/tree/master/StripePaymentSheet/README.md#manual-linking)にリストされている必要なフレームワークのすべてを埋め込んでください。 1. 今後、SDK の最新バージョンに更新するには、以下のコマンドを実行します。 ```bash carthage update stripe-ios --platform ios ``` #### 手動のフレームワーク 1. Stripe の [GitHub リリースページ](https://github.com/stripe/stripe-ios/releases/latest)に移動して、**Stripe.xcframework.zip** をダウンロードして解凍します。 1. **StripePaymentSheet.xcframework** を、Xcode プロジェクトの **General (一般) ** 設定の **Embedded Binaries (埋め込みバイナリー)** セクションにドラッグします。**Copy items if needed (必要に応じてアイテムをコピーする)** を必ず選択してください。 1. [こちら](https://github.com/stripe/stripe-ios/tree/master/StripePaymentSheet/README.md#manual-linking)にリストされている必要なフレームワークのすべてに対して、ステップ 2 を繰り返します。 1. 今後、Stripe の SDK の最新バージョンに更新するには、ステップ 1 から 3 を繰り返します。 > SDK の最新リリースおよび過去バージョンの詳細については、GitHub の [Releases (リリース)](https://github.com/stripe/stripe-ios/releases) ページをご覧ください。リポジトリの[リリースをウォッチ](https://help.github.com/en/articles/watching-and-unwatching-releases-for-a-repository#watching-releases-for-a-repository)して、新しいリリースの公開時に通知を受け取ることも可能です。 また、SDK が Stripe への API コールを実行できるように、[公開可能キー](https://dashboard.stripe.com/apikeys)を設定する必要もあります。すぐに開始するには、導入中にクライアント側でこれをハードコード化できますが、本番環境ではサーバーから公開可能キーを取得します。 ```swift // Set your publishable key: remember to change this to your live publishable key in production // See your keys here: https://dashboard.stripe.com/apikeys STPAPIClient.shared.publishableKey = "<>" ``` ## ポータルセッションを作成する [サーバー側] 顧客がサブスクリプションに変更を加えるには、portal session API で Stripe 顧客 ID を使用してポータルページの URL を生成します。 #### Node.js ```javascript // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. // Find your keys at https://dashboard.stripe.com/apikeys. const stripe = require('stripe')('<>'); app.get('/customer_portal_url', async (req, res) => { // Replace this with your actual customer lookup logic const customerId = 'cus_...'; // Get this from your database const billingSession = await stripe.billingPortal.sessions.create({ customer: customerId, return_url: 'https://example.com/portal_redirect', }); res.json({ url: billingSession.url }); }) ``` ## ユニバーサルリンクを設定する [クライアント側] [サーバー側] *ユニバーサルリンク* (Use Universal links on iOS and macOS to link directly to in-app content. They're standard HTTPS links, so the same URL works for your website and your app)を使用すると、カスタマーポータルをアプリにディープリンクできます。ユニバーサルリンクを設定するには、次の手順を行います。 1. ドメインに `apple-app-site-association` ファイルを追加します。 1. アプリに Associated Domains エンタイトルメントを追加します。 1. ポータルのリダイレクト URL のフォールバックページを追加します。 #### 関連ドメインを定義する **.well-known/apple-app-site-association** メインにファイルを追加し、アプリで処理する URL を定義します。アプリ ID の前にチーム ID を付加します。チーム IDは、[Apple Developer Portal のメンバーシップページ](https://developer.apple.com/account)にあります。 ```json { "applinks": { "apps": [], "details": [ { "appIDs": [ "A28BC3DEF9.com.example.MyApp1", "A28BC3DEF9.com.example.MyApp1-Debug" ], "components": [ { "/": "/checkout_redirect*", "comment": "Matches any URL whose path starts with /checkout_redirect" } ] } ] } } ``` このファイルは、MIME タイプ `application/json` で提供する必要があります。`curl -I` を使用してコンテンツタイプを確認します。 ```bash curl -I https://example.com/.well-known/apple-app-site-association ``` 詳細については、[関連ドメインのサポート](https://developer.apple.com/documentation/xcode/supporting-associated-domains)に関する Apple のページを参照してください。 #### アプリに Associated Domains エンタイトルメントを追加する 1. アプリのターゲットの、**Signing & Capabilities (署名とケイパビリティ)** ウィンドウを開きます。 1. **+ ケイパビリティ** をクリックし、**関連ドメイン** を選択します。 1. `applinks:example.com` のエントリーを **Associated Domains** リストに追加します。 ユニバーサルリンクの詳細については、Apple の [Universal Links for Developers (開発者のためのユニバーサルリンク) (英語)](https://developer.apple.com/ios/universal-links/) ページをご覧ください。 iOS は、`apple-app-site-association` ファイルで定義された URL へのリンクをインターセプトしますが、リダイレクトでアプリを開くことができないケースが発生することがあります。 `return_url` にフォールバックページを作成してください。たとえば、[アプリのカスタム URL スキームを定義](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app)して、ユニバーサルリンクが失敗した場合にそのスキームを使用してリンクし直すことができます。 ## Safari でカスタマーポータルを開く [クライアント側] アプリに、カスタマーポータルを開くボタンを追加します。このボタンは以下を行います。 1. サーバー側のエンドポイントを呼び出して、ポータルセッションを作成します。 1. ポータルページの URL をクライアントに返します。 1. Safari で URL を開きます。 ```swift import Foundation import SwiftUI import StoreKit struct SubscriptionManagementView: View { @EnvironmentObject var myBackend: MyServer var body: some View { // Check if payments are blocked by Parental Controls on this device. if !SKPaymentQueue.canMakePayments() { Text("Payments are disabled on this device.") } else { Button { myBackend.createCustomerPortalSession { url in UIApplication.shared.open(url, options: [:], completionHandler: nil) } } label: { Text("Manage subscriptions") }.onOpenURL { url in // Handle the universal link from the customer portal. // Implement any necessary behavior, such as refreshing the customer's subscription status. } } } } ``` ## 顧客のサブスクリプションステータスの変更を処理する [サーバー側] 顧客がカスタマーポータルを使用してサブスクリプションステータスを変更すると、`customer.subscription.created`、`customer.subscription.deleted`、`customer.subscription.updated` などの *Webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) が Stripe からお客様に送信されます。イベントの一覧とその情報については、[サブスクリプションで Webhook を使用する](https://docs.stripe.com/billing/subscriptions/webhooks.md)をご覧ください。設定したサブスクリプションのステータスを正確に監視するために必要な、すべてのイベントを処理していることを確認してください。 テスト目的の場合は、[ダッシュボード](https://dashboard.stripe.com/events)または [Stripe CLI](https://docs.stripe.com/webhooks.md#test-webhook) を使用してイベントをモニタリングします。本番環境では、Webhook エンドポイントを設定して適切なイベントタイプに登録します。`STRIPE_WEBHOOK_SECRET` キーが不明な場合は、ダッシュボードで [Webhook](https://dashboard.stripe.com/webhooks) リンクをクリックして表示します。 #### Node.js ```javascript const express = require('express'); const app = express(); // Set your secret key. Remember to switch to your live secret key in production. // See your keys here: https://dashboard.stripe.com/apikeys const stripe = require('stripe')('') app.post('/webhook', async (req, res) => { let data; let eventType; // Check if webhook signing is configured. const webhookSecret = "{{STRIPE_WEBHOOK_SECRET}}" // 例: whsec_c7681Dm if (webhookSecret) { // Retrieve the event by verifying the signature using the raw body and secret. let event; let signature = req.headers["stripe-signature"]; try { event = stripe.webhooks.constructEvent( req.body, signature, webhookSecret ); } catch (err) { console.log(`⚠️ Webhook signature verification failed.`); return res.sendStatus(400); } // Extract the object from the event. data = event.data; eventType = event.type; } else { // Webhook signing is recommended, but if the secret is not configured in `config.js`, // retrieve the event data directly from the request body. data = req.body.data; eventType = req.body.type; } switch (eventType) { case 'customer.subscription.created': { const subscription = event.data.object; const customerId = subscription.customer; myUserDB.setUserSubscriptionIsActive(customerId, true); break; } case 'customer.subscription.deleted': { const subscription = event.data.object; const customerId = subscription.customer; myUserDB.setUserSubscriptionIsActive(customerId, false); break; } // Add other relevant event types as needed } res.sendStatus(200); // Acknowledge receipt of the webhook }) ``` ## Optional: 特定のページへのディープリンク アプリと Stripe の間のワークフローをさらにカスタマイズできます。カスタマーポータルのディープリンクを使用すると、実行するアクションが指定されたページへの直接リンクが可能です。顧客がアクションを完了した後の、リダイレクト動作をカスタマイズできます。詳しくは、[カスタマーポータルのディープリンク](https://docs.stripe.com/customer-management/portal-deep-links.md)をご覧ください。 ## See also - [カスタマーポータルを使用した顧客向けセルフサービス](https://docs.stripe.com/customer-management.md) - [サブスクリプションのライフサイクル](https://docs.stripe.com/billing/subscriptions/overview.md#subscription-lifecycle) - [サブスクリプションをテストする](https://docs.stripe.com/billing/testing.md)