利用ライブラリについて ● https://pub.dev/packages/in_app_purchase (以下引用) ● A storefront-independent API for purchases in Flutter apps. This plugin supports in-app purchases (IAP) through an underlying store, which can be the App Store (on iOS and macOS) or Google Play (on Android). ● Features ○ Use this plugin in your Flutter app to: ○ Show in-app products that are available for sale from the underlying store. Products can include consumables, permanent upgrades, and subscriptions. ○ Load in-app products that the user owns. ○ Send the user to the underlying store to purchase products. ○ Present a UI for redeeming subscription offer codes. (iOS 14 only) 20
AndroidネイティブAPIとの対応 ● queryPurchases(params: QueryPurchasesParam) ○ プラン切り替えのために購入済みの PurchaseDetailsが欲しいんだけど……?? ○ 47 /// Githubのサンプルコード if (Platform.isAndroid) { // NOTE: If you are making a subscription purchase/upgrade/downgrade, // we recommend you to verify the latest status of you your subscription // by using server side receipt validation and update the UI accordingly. // The subscription purchase status shown inside the app may not be accurate. final GooglePlayPurchaseDetails? oldSubscription = _getOldSubscription(productDetails, purchases);
AndroidネイティブAPIとの対応 ● queryPurchases(params: QueryPurchasesParam) ○ プラン切り替えのために購入済みの PurchaseDetailsが欲しいんだけど……?? ○ 48 /// Githubのサンプルコード if (Platform.isAndroid) { // NOTE: If you are making a subscription purchase/upgrade/downgrade, // we recommend you to verify the latest status of you your subscription // by using server side receipt validation and update the UI accordingly. // The subscription purchase status shown inside the app may not be accurate. final GooglePlayPurchaseDetails? oldSubscription = _getOldSubscription(productDetails, purchases); 要約: サーバー上で保持してそれを取得すべき
購入/復元 ● PurchaseDetails自身が購入結果なのか復元結果なのかを知っている 80 class PurchaseDetails { /// The status that this [PurchaseDetails] is currently on. PurchaseStatus status; /// Status for a [PurchaseDetails]. enum PurchaseStatus { pending, purchased, error, restored, canceled, }
iOS特有の処理について ● startConnection成功時の処理 ○ 注) サンプルコードの実装ママ /// Example implementation of the /// [`SKPaymentQueueDelegate`] (https://developer.apple.com/documentation/storekit/skpaymentqueuedelegate?language=objc). /// The payment queue delegate can be implemented to provide information needed to complete transactions. class ExamplePaymentQueueDelegate implements SKPaymentQueueDelegateWrapper { /// https://developer.apple.com/documentation/storekit/skpaymentqueuedelegate/3242935-paymentqueue @override bool shouldContinueTransaction( SKPaymentTransactionWrapper transaction, SKStorefrontWrapper storefront, ) => true; /// https://developer.apple.com/documentation/storekit/skpaymentqueue/3521327-showpriceconsentifneeded @override bool shouldShowPriceConsent() => false; } 99
iOS特有の処理について ● startConnection成功時の処理 ○ 購入トランザクション中に StoreFrontが変更された際にトランザクションを続行するか否か /// Example implementation of the /// [`SKPaymentQueueDelegate`] (https://developer.apple.com/documentation/storekit/skpaymentqueuedelegate?language=objc). /// The payment queue delegate can be implemented to provide information needed to complete transactions. class ExamplePaymentQueueDelegate implements SKPaymentQueueDelegateWrapper { /// https://developer.apple.com/documentation/storekit/skpaymentqueuedelegate/3242935-paymentqueue @override bool shouldContinueTransaction( SKPaymentTransactionWrapper transaction, SKStorefrontWrapper storefront, ) => true; /// https://developer.apple.com/documentation/storekit/skpaymentqueue/3521327-showpriceconsentifneeded @override bool shouldShowPriceConsent() => false; } 100
iOS特有の処理について ● startConnection成功時の処理 ○ 定期購読の値上げに未応答の場合、価格同意シートを表示するか否か /// Example implementation of the /// [`SKPaymentQueueDelegate`] (https://developer.apple.com/documentation/storekit/skpaymentqueuedelegate?language=objc). /// The payment queue delegate can be implemented to provide information needed to complete transactions. class ExamplePaymentQueueDelegate implements SKPaymentQueueDelegateWrapper { /// https://developer.apple.com/documentation/storekit/skpaymentqueuedelegate/3242935-paymentqueue @override bool shouldContinueTransaction( SKPaymentTransactionWrapper transaction, SKStorefrontWrapper storefront, ) => true; /// https://developer.apple.com/documentation/storekit/skpaymentqueue/3521327-showpriceconsentifneeded @override bool shouldShowPriceConsent() => false; } 101
iOS特有の処理について ● ReceiptData取得処理 ○ StoreKitPlatformAdditionからVerificationDataを取得できる if (!Platform.isIOS) return null; final platformAddition = inAppPurchase.getPlatformAddition() as InAppPurchaseStoreKitPlatformAddition; final verificationData = await platformAddition.refreshPurchaseVerificationData(); final receipt = verificationData?.serverVerificationData; 103