この記事は、Flutter Advent Calendar 2022 23日目の記事です。
Flutterを利用してDartでiOS / Androidに対応したアプリケーションを開発できます。
この記事では、FlutterでStripeの決済情報入力画面を表示するためのライブラリ「flutter_stripe
」を利用して、サブスクリプションの申し込みを完了する方法を紹介します。
事前準備
Flutterを動かすために、DartとFlutter CLIをインストールしましょう。
Dartのインストール
Homebrewを利用して、Dartをインストールします。
$ brew tap dart-lang/dart
$ brew install dart
今回は、以下のバージョンを利用しています。
dart --version
Dart SDK version: 2.18.5 (stable) (Tue Nov 22 15:47:29 2022 +0000) on "macos_arm64"
Flutterのインストール
ドキュメントのガイドに従って、Flutterをインストールします。
今回は、以下のバージョンを利用しています。
$ flutter --version
Flutter 3.3.9 • channel stable • https://github.com/flutter/flutter.git
Framework • revision b8f7f1f986 (2 weeks ago) • 2022-11-23 06:43:51 +0900
Engine • revision 8f2221fbef
Tools • Dart 2.18.5 • DevTools 2.15.0
アプリのセットアップ
準備ができれば、アプリをセットアップします。
ここでは、flutter create
を実行しましょう。
$ flutter create first_app
Creating project first_app...
Running "flutter pub get" in first_app... 1,398ms
Wrote 127 files.
All done!
In order to run your application, type:
$ cd first_app
$ flutter run
Your application code is in first_app/lib/main.dart.
flutter run
でアプリを起動できます。
サブスクリプションデータを作成するAPIを用意しよう
Express.jsやNestJSなどで、サブスクリプションを作成するAPIを事前に用意しましょう。
app.post('/create_subscription', async (req, res) => {
const { id: customerId } = await stripe.customers.create()
const ephemeralKey = await stripe.ephemeralKeys.create({
customer: customerId,
}, {
apiVersion: '2022-08-01'
})
const subscription = await stripe.subscriptions.create({
customer: customerId,
items: [{
price: 'price_xxxx',
quantity: 1,
}],
payment_behavior: 'default_incomplete',
expand: ['latest_invoice.payment_intent'],
payment_settings: {
save_default_payment_method: 'on_subscription',
},
})
return {
clientSecret: subscription.latest_invoice.payment_intent.client_secret,
ephemeralKey: ephemeralKey.secret,
customerId
}
})
Stripeのカード登録フォームを追加する
サブスクリプションの契約に利用するための、カード情報登録フォームを追加しましょう。
flutter_stripeパッケージを追加する
まずはflutter_stripe
パッケージを追加します。
$ flutter pub get flutter_stripe
Downloading flutter_stripe 7.0.0...
Downloading stripe_platform_interface 7.0.0...
Downloading stripe_ios 7.0.0...
Downloading stripe_android 7.0.1...
Downloading json_annotation 4.7.0...
Downloading freezed_annotation 2.2.0...
Changed 7 dependencies!
pod installに失敗する場合
flutter run
を実行すると、次のようなエラーが出ることがあります。
Analyzing dependencies
[!] CocoaPods could not find compatible versions for pod "stripe_ios":
In Podfile:
stripe_ios (from `.symlinks/plugins/stripe_ios/ios`)
Specs satisfying the `stripe_ios (from `.symlinks/plugins/stripe_ios/ios`)` dependency were found, but they required a higher minimum deployment target.
ios/Podfile
と/ios/Runner.xcodeproj/project.pbxproj
のiOSバージョンを新しいバージョンに変更すると、解決することがあります。
+++ b/ios/Podfile
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
-# platform :ios, '11.0'
+platform :ios, '13.0'
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -272,7 +272,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AG
GRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
参考: https://stackoverflow.com/questions/72485674/error-with-flutter-stripe-3-0-2-for-ios-11394
M1/M2系のMacbookなどを利用されている場合は、こちらもお試しください。
https://github.com/flutter/flutter/wiki/Developing-with-Flutter-on-Apple-Silicon
また、サーバー側でサブスクリプションを作成して取得するため、httpモジュールも追加します。
$ flutter pub add http
...
Downloading http 0.13.5...
Downloading http_parser 4.0.2...
Changed 3 dependencies!
flutter_stripeをセットアップする
lib/main.dart
を変更して、ライブラリをセットアップします。
+import 'package:flutter_stripe/flutter_stripe.dart';
+import 'dart:developer' as developer;
import 'dart:convert';
+import 'package:http/http.dart' as http;
void main() {
WidgetsFlutterBinding.ensureInitialized();
+ Stripe.publishableKey =
'pk_test_から始まるStripeの公開可能キー';
runApp(const MyApp());
}
lib/main.dart
に決済画面を表示するボタンを追加する
決済画面(PaymentSheet
)を表示するためのボタンを追加しましょう。
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
+ ElevatedButton(
+ onPressed: () async {
+ try {
+ developer.log("Hello");
+ } catch (e) {
+ developer.log("error", error: e);
+ }
+ },
+ child: const Text("Show card form"),
+ )
],
ボタンが追加されました。
決済フォームを表示する
作成したElevatedButton
のonPressed
イベントに、フォームを表示するための処理を追加しましょう。
ElevatedButton(
onPressed: () async {
try {
+ final response =
+ await http.get(Uri.http("localhost:3100", "/stripe"));
+ final jsonResponse = jsonDecode(response.body);
+
+ await Stripe.instance.initPaymentSheet(
+ paymentSheetParameters: SetupPaymentSheetParameters(
+ customerEphemeralKeySecret:
+ jsonResponse['ephemeralKey'],
+ customerId: jsonResponse['customerId'],
+ paymentIntentClientSecret:
+ jsonResponse['clientSecret']),
+ );
+ await Stripe.instance.presentPaymentSheet();
} catch (e) {
developer.log("error", error: e);
}
},
child: const Text("Show card form"),
)
再読み込みに成功すると、ボタンクリックで決済フォームが表示されます。
すでにカード情報が登録されている顧客のIDをサーバー側で指定した場合、登録済みのカードを選ぶこともできます。
また、iOSではカードのスキャン機能も利用可能です。
Documents