react-native-purchases のバージョン 9.7.6 以降、React Native で開発しているチームは、同じ SDK と同じ RevenueCat のエンタイトルメントシステムを使って、iOS・Android・Web のサブスクリプションを一元管理できるようになりました。すでにモバイルでアプリを展開していて Web へ拡張する場合でも、最初から共通コードベースで開発する場合でも、アーキテクチャを再設計することなく、すべてのプラットフォームでサブスクリプションをサポートできます。

Expo または React Native プロジェクトに react-native-purchases を追加するだけで、単一のコードベースから、3つのプラットフォームにわたる高度なサブスクリプション管理、アプリ内課金、エンタイトルメント管理を実現できます。

なぜこれを開発したのか

より多くの React Native アプリがモバイルの枠を超えて展開する中で、Web は単なるマーケティングの場ではなく、プロダクトの一部になっています。チームは、ユーザーがブラウザ上でサインアップやアップグレード、サブスクリプション管理を行いながら、iOS や Android アプリ内でも同じアクセス権を利用できることを求めています。これまでは、そのために Web 用の別個の課金システムを維持し、カスタムロジックで全体をつなぎ合わせる必要がありました。

React Native Web サポートは、その分断を解消します。Web での購入はネイティブ購入と同じ RevenueCat のバックエンドに流れるため、複数のデータソースを突き合わせる必要はありません。単一のエンタイトルメントシステムに依存することができます。

Webでの課金の仕組み

iOS と Android では、RevenueCat は App Store と Google Play に直接統合されています。一方、Web では購入は RevenueCat Web Billing を通じて処理され、Stripe または Paddle が決済プロセッサーとして利用されます。Web Billing はネイティブのアプリ内課金とは別の仕組みですが、同じエンタイトルメントシステムに接続されているため、共通の appUserID を使ってプラットフォーム間でアクセス権を付与できます。

アプリ側から見ると、ユーザーがどこでサブスクリプションを開始したかに関わらず、サブスクリプション状態は一貫しています。ユーザーが Web で登録した場合でも、特別なプラットフォーム別ロジックを書くことなく、すぐにモバイルでプレミアム機能へアクセスできます。

React Native Web の始め方

React Native Web サポートを有効にするには、まず各プラットフォームに対応する適切な API キーを使って RevenueCat を設定します。アプリが Web 上で動作する場合は Web Billing 用の公開 API キーで SDK を初期化し、iOS と Android では引き続きそれぞれのネイティブ用キーを使用します。

実際の設定は、次のようになります。

1import { Platform } from 'react-native';
2import Purchases from 'react-native-purchases';
3
4if (Platform.OS === 'web') {
5  Purchases.configure({ apiKey: '<public_web_billing_api_key>' });
6} else if (Platform.OS === 'ios') {
7  Purchases.configure({ apiKey: '<public_apple_api_key>' });
8} else if (Platform.OS === 'android') {
9  Purchases.configure({ apiKey: '<public_google_api_key>' });
10}

設定が完了すれば、エンタイトルメントの確認はすべてのプラットフォームで同じ方法で行えます。サブスクリプションがどのプラットフォームで購入されたかによって、アプリのロジックを分岐させる必要はありません。

1import Purchases from 'react-native-purchases'
2// all of the following methods work on iOS, Android, and Web
3
4// Check offerings
5try {
6  const offerings = await Purchases.getOfferings();
7  if (offerings.current !== null && offerings.current.availablePackages.length !== 0) {
8    // Display packages for sale
9  }
10} catch (e) {
11 
12}
13
14// Check entitlements
15const customerInfo = await Purchases.getCustomerInfo();
16if(typeof customerInfo.entitlements.active[<my_entitlement_identifier>] !== "undefined") {
17  // Grant user "pro" access
18}
19
20// Purchase a package
21try {
22  const { customerInfo } = await Purchases.purchasePackage(package);
23  if (
24    typeof customerInfo.entitlements.active["my_entitlement_identifier"] !==
25    "undefined"
26  ) {
27    // Unlock that great "pro" content
28  }
29} catch (e) {
30  if (!e.userCancelled) {
31    showError(e);
32}
33

Web 購入を有効にするには、RevenueCat ダッシュボードで Web Billing 用のアプリを作成し、Web 向けにプロダクトを設定する必要があります。これらは iOS や Android のプロダクトと並んで管理されますが、ネイティブストアではなく Web Billing を通じて課金されます。

Expo を利用する場合

Expo で開発している場合、React Native Web サポートは開発体験も向上させます。カスタムの開発用クライアントをすぐに作成しなくても、Web 上でサブスクリプション UI をプレビューし、エンタイトルメントロジックをテストし、統合フローを検証できます。これにより、初期段階での反復開発がしやすくなり、設定がエンドツーエンドで正しく動作しているかを確認しやすくなります。

iOS と Android で実際のアプリ内課金を完全にテストするには、引き続き Expo の開発ビルドが必要です。Web サポートはその要件を置き換えるものではありませんが、初期開発段階における多くの摩擦を取り除きます。

現在の制限事項

Web 課金はネイティブのアプリストアとは仕組みが異なるため、いくつか注意すべき制限があります。Web での購入には RevenueCat Web Billing が必要であり、iOS や Android のネイティブアプリ内課金を処理することはできません。また、ネイティブストアの API に依存する一部の操作( getProductspurchaseProductrestorePurchasesなど)は Web 環境ではサポートされていません。Expo Go や同様のサンドボックス環境でも、購入処理はサポートされていません。

1// this will not work on web, but works on iOS and Android:
2try {
3  const restore = await Purchases.restorePurchases();
4  // ... check restored purchaserInfo to see if entitlement is now active
5} catch (e) {
6
7}

ユーザーは、RevenueCat がホストするカスタマーポータルを通じて Web サブスクリプションを管理できます。これにより、ネイティブアプリストア外でも、サブスクリプションの更新や解約を一貫した方法で行うことができます。

今後について

サブスクリプションアプリがモバイルとWebの両方にまたがるケースが増える中、私たちはクロスプラットフォームでのサブスクリプション管理を、よりシンプルで信頼性の高いものにするための投資を続けています。React Native Web サポートはその基盤となる取り組みであり、チームが本番環境でさらに活用していく中で、体験を継続的に改善していきます。

すでにモバイルで React Native と RevenueCat を利用している場合、Web サポートの追加は自然な次のステップです。