Flutter Templates
Flutter、Back4App、およびCloud Codeを介したStripe統合を使用したEコマースアプリの構築
48 分
はじめに eコマースアプリの開発には、商品リスト、ショッピングカート機能、安全な支払い処理、注文追跡、ユーザーレビューなど、複数のコンポーネントが含まれます。flutterの強力なuiツールキットとback4appのスケーラブルなバックエンドサービスを組み合わせることで、開発プロセスが簡素化されます。さらに、back4app cloud codeを介してstripeを統合することで、安全でプロフェッショナルな取引処理が可能になります。 このチュートリアルでは、次の機能を持つeコマースアプリを構築します 商品リスト 画像、説明、価格を表示します。 ショッピングカート カートに商品を追加および削除します。 ユーザーアカウント ユーザープロフィールと住所を管理します。 安全なチェックアウト back4app cloud codeを介してstripeを使用して安全に支払いを処理します。 注文追跡 注文のステータスと履歴を追跡します。 レビューと評価 ユーザーがレビューと評価を提出できるようにします。 前提条件 このチュートリアルを進めるには、次のものが必要です flutter sdk があなたのマシンにインストールされていること。 flutterインストールガイド https //flutter dev/docs/get started/install を参照してください。 flutterとdartの基本的な知識 が必要です。 ideまたはテキストエディタ (visual studio codeやandroid studioなど)が必要です。 back4appアカウント が必要です。 back4app https //www back4app com/ にサインアップしてください。 stripeアカウント が必要です。 stripe https //stripe com/ にサインアップしてapiキーを取得してください。 node jsとnpm がcloud code開発のためにインストールされていること。 ステップ1 – flutterプロジェクトの設定 1 1 新しいflutterプロジェクトを作成する ターミナルを開いて、次のコマンドを実行します flutter create ecommerce app プロジェクトディレクトリに移動します cd ecommerce app 1 2 依存関係を追加する 「 pubspec yaml 」を開いて、次の依存関係を追加します dependencies flutter sdk flutter parse server sdk flutter ^4 0 1 provider ^6 0 0 cached network image ^3 2 0 flutter stripe ^5 2 0 uuid ^3 0 6 「 flutter pub get 」を実行して、パッケージをインストールします。 注意 parse server sdk flutter バック4アプリ統合のため。 provider 状態管理のため。 cached network image 効率的な画像読み込みのため。 flutter stripe クライアント側のstripe統合のため。 uuid ユニーク識別子を生成するため。 ステップ2 – back4appの設定 2 1 新しいback4appアプリケーションを作成する あなたの back4appダッシュボード https //dashboard back4app com/ にログインします。 「 新しいアプリを作成 」をクリックします。 アプリケーション名に「 ecommerceapp 」と入力し、「 作成 」をクリックします。 2 2 データモデルの設定 back4appにいくつかのクラスを作成する必要があります 製品 ユーザー (組み込みクラス) 注文 注文アイテム レビュー 2 2 1 製品クラス 「 "database" 」セクションに移動します。 「 "create a class" 」をクリックします。 「 "custom" 」を選択し、クラス名として「 "product" 」を入力します。 次の列を追加します name string description string price number image file category string inventory number 2 2 2 注文クラス 次の列を持つ「 "order" 」クラスを作成します user pointer< user> totalamount number status string (値 "pending", "paid", "shipped", "delivered") paymentintentid string (stripeの支払いを追跡するため) shippingaddress string 2 2 3 orderitemクラス 次の列を持つ "orderitem" クラスを作成します 注文 ポインタ 製品 ポインタ 数量 数 価格 数 2 2 4 レビュークラス 次の列を持つ "review" クラスを作成します 製品 ポインタ ユーザー ポインタ< ユーザー> 評価 数値 コメント 文字列 2 3 アプリケーションの資格情報を取得する 次に進む アプリ設定 > セキュリティとキー あなたの アプリケーションid と クライアントキー をメモしてください。 ステップ3 – 製品管理の実装 3 1 flutterでのparseの初期化 次のファイルを開いてください lib/main dart そして修正します import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import 'package\ provider/provider dart'; import 'screens/home screen dart'; import 'services/product service dart'; void main() async { widgetsflutterbinding ensureinitialized(); const keyapplicationid = 'your application id'; const keyclientkey = 'your client key'; const keyparseserverurl = 'https //parseapi back4app com'; await parse() initialize( keyapplicationid, keyparseserverurl, clientkey keyclientkey, autosendsessionid true, debug true, ); runapp(myapp()); } class myapp extends statelesswidget { @override widget build(buildcontext context) { return changenotifierprovider\<productservice>( create ( ) => productservice(), child materialapp( title 'e commerce app', theme themedata( primaryswatch colors blue, ), home homescreen(), ), ); } } 次の内容を置き換えます 'your application id' と 'your client key' をあなたのback4appの資格情報に置き換えてください。 3 2 製品モデルの作成 ディレクトリを作成する models を lib の下に作成し、 product dart // lib/models/product dart class product { string id; string name; string description; double price; string imageurl; string category; int inventory; product({ required this id, required this name, required this description, required this price, required this imageurl, required this category, required this inventory, }); } 3 3 プロダクトサービスの実装 ディレクトリを作成する services を lib の下に作成し、 product service dart // lib/services/product service dart import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import ' /models/product dart'; class productservice with changenotifier { list\<product> products = \[]; future\<void> fetchproducts() async { final query = querybuilder\<parseobject>(parseobject('product')); final response = await query query(); if (response success && response results != null) { products = response results! map((data) { return product( id data objectid!, name data get\<string>('name')!, description data get\<string>('description')!, price data get\<num>('price')! todouble(), imageurl data get\<parsefilebase>('image')! url!, category data get\<string>('category')!, inventory data get\<num>('inventory')! toint(), ); }) tolist(); notifylisteners(); } } } 3 4 ホーム画面の作成 「 screens 」ディレクトリを「 lib 」の下に作成し、「 home screen dart 」を追加します。 // lib/screens/home screen dart import 'package\ flutter/material dart'; import 'package\ provider/provider dart'; import ' /services/product service dart'; import 'product detail screen dart'; class homescreen extends statefulwidget { @override homescreenstate createstate() => homescreenstate(); } class homescreenstate extends state\<homescreen> { late productservice productservice; @override void initstate() { super initstate(); productservice = provider of\<productservice>(context, listen false); productservice fetchproducts(); } @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('e commerce app'), actions \[ iconbutton( icon icon(icons shopping cart), onpressed () { // navigate to cart screen (to be implemented) }, ), ], ), body consumer\<productservice>( builder (context, productservice, child) { if (productservice products isempty) { return center(child circularprogressindicator()); } return gridview\ builder( padding edgeinsets all(8 0), itemcount productservice products length, griddelegate slivergriddelegatewithfixedcrossaxiscount( crossaxiscount 2, childaspectratio 0 75, ), itembuilder (context, index) { final product = productservice products\[index]; return gesturedetector( ontap () { navigator push( context, materialpageroute( builder ( ) => productdetailscreen(product product), ), ); }, child card( child column( children \[ expanded( child image network( product imageurl, fit boxfit cover, ), ), text(product name), text('\\$${product price tostringasfixed(2)}'), ], ), ), ); }, ); }, ), ); } } 3 5 商品詳細画面 作成する product detail screen dart の下に lib/screens/ // lib/screens/product detail screen dart import 'package\ flutter/material dart'; import ' /models/product dart'; import ' /services/cart service dart'; import 'package\ provider/provider dart'; class productdetailscreen extends statelesswidget { final product product; productdetailscreen({required this product}); @override widget build(buildcontext context) { final cartservice = provider of\<cartservice>(context); return scaffold( appbar appbar(title text(product name)), body column( children \[ expanded(child image network(product imageurl)), padding( padding const edgeinsets all(16 0), child text(product description), ), text('\\$${product price tostringasfixed(2)}'), elevatedbutton( onpressed () { cartservice addtocart(product); scaffoldmessenger of(context) showsnackbar( snackbar(content text('added to cart')), ); }, child text('add to cart'), ), ], ), ); } } ステップ 4 – ユーザーアカウントの実装 4 1 認証サービス 追加する auth service dart の下に lib/services/ // lib/services/auth service dart import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; class authservice with changenotifier { parseuser? user; future\<bool> signup(string username, string password, string email) async { user = parseuser createuser(username, password, email); final response = await user! signup(); if (response success) { notifylisteners(); return true; } else { user = null; return false; } } future\<bool> login(string username, string password) async { user = parseuser(username, password, null); final response = await user! login(); if (response success) { notifylisteners(); return true; } else { user = null; return false; } } future\<void> logout() async { if (user != null) { await user! logout(); user = null; notifylisteners(); } } bool get isauthenticated => user != null; } 4 2 認証画面 作成する login screen dart と signup screen dart の下に lib/screens/ ログイン画面 // lib/screens/login screen dart import 'package\ flutter/material dart'; import 'package\ provider/provider dart'; import ' /services/auth service dart'; import 'home screen dart'; import 'signup screen dart'; class loginscreen extends statelesswidget { final texteditingcontroller usernamecontroller = texteditingcontroller(); final texteditingcontroller passwordcontroller = texteditingcontroller(); void login(buildcontext context) async { final authservice = provider of\<authservice>(context, listen false); bool success = await authservice login( usernamecontroller text trim(), passwordcontroller text trim(), ); if (success) { navigator pushreplacement( context, materialpageroute(builder ( ) => homescreen()), ); } else { scaffoldmessenger of(context) showsnackbar(snackbar(content text('login failed'))); } } @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('e commerce app login'), ), body padding( padding const edgeinsets all(16), child column( children \[ textfield( controller usernamecontroller, decoration inputdecoration(labeltext 'username or email'), ), textfield( controller passwordcontroller, decoration inputdecoration(labeltext 'password'), obscuretext true, ), sizedbox(height 20), elevatedbutton( onpressed () => login(context), child text('login'), ), textbutton( onpressed () { navigator push( context, materialpageroute(builder ( ) => signupscreen()), ); }, child text('don\\'t have an account? sign up'), ) ], ), ), ); } } サインアップ画面 // lib/screens/signup screen dart import 'package\ flutter/material dart'; import 'package\ provider/provider dart'; import ' /services/auth service dart'; import 'home screen dart'; class signupscreen extends statelesswidget { final texteditingcontroller usernamecontroller = texteditingcontroller(); final texteditingcontroller emailcontroller = texteditingcontroller(); final texteditingcontroller passwordcontroller = texteditingcontroller(); void signup(buildcontext context) async { final authservice = provider of\<authservice>(context, listen false); bool success = await authservice signup( usernamecontroller text trim(), passwordcontroller text trim(), emailcontroller text trim(), ); if (success) { navigator pushreplacement( context, materialpageroute(builder ( ) => homescreen()), ); } else { scaffoldmessenger of(context) showsnackbar(snackbar(content text('signup failed'))); } } @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('e commerce app signup'), ), body padding( padding const edgeinsets all(16), child column( children \[ textfield( controller usernamecontroller, decoration inputdecoration(labeltext 'username'), ), textfield( controller emailcontroller, decoration inputdecoration(labeltext 'email'), ), textfield( controller passwordcontroller, decoration inputdecoration(labeltext 'password'), obscuretext true, ), sizedbox(height 20), elevatedbutton( onpressed () => signup(context), child text('sign up'), ), ], ), ), ); } } 4 3 authserviceを含めるためにmainを更新する 「 main dart 」で、 materialapp を multiprovider でラップします // in main dart class myapp extends statelesswidget { @override widget build(buildcontext context) { return multiprovider( providers \[ changenotifierprovider\<productservice>( create ( ) => productservice(), ), changenotifierprovider\<authservice>( create ( ) => authservice(), ), changenotifierprovider\<cartservice>( create ( ) => cartservice(), ), ], child materialapp( // ), ); } } 4 4 認証状態に基づくリダイレクト 「 main dart 」を修正して、認証状態を確認します // main dart // inside the build method home consumer\<authservice>( builder (context, authservice, child) { if (authservice isauthenticated) { return homescreen(); } else { return loginscreen(); } }, ), ステップ 5 – ショッピングカート機能 5 1 カートサービスを作成する 追加 cart service dart を lib/services/ // lib/services/cart service dart import 'package\ flutter/material dart'; import ' /models/product dart'; class cartitem { final product product; int quantity; cartitem({required this product, this quantity = 1}); } class cartservice with changenotifier { map\<string, cartitem> items = {}; void addtocart(product product) { if ( items containskey(product id)) { items\[product id]! quantity++; } else { items\[product id] = cartitem(product product); } notifylisteners(); } void removefromcart(string productid) { items remove(productid); notifylisteners(); } void clearcart() { items clear(); notifylisteners(); } map\<string, cartitem> get items => items; double get totalamount { double total = 0 0; items foreach((key, cartitem) { total += cartitem product price cartitem quantity; }); return total; } } 5 2 カート画面を作成する 追加する cart screen dart を lib/screens/ の下に // lib/screens/cart screen dart import 'package\ flutter/material dart'; import 'package\ provider/provider dart'; import ' /services/cart service dart'; import 'checkout screen dart'; class cartscreen extends statelesswidget { @override widget build(buildcontext context) { final cartservice = provider of\<cartservice>(context); final cartitems = cartservice items values tolist(); return scaffold( appbar appbar(title text('your cart')), body column( children \[ expanded( child listview\ builder( itemcount cartservice items length, itembuilder (context, index) { final cartitem = cartitems\[index]; return listtile( leading image network(cartitem product imageurl), title text(cartitem product name), subtitle text('quantity ${cartitem quantity}'), trailing text('\\$${(cartitem product price cartitem quantity) tostringasfixed(2)}'), ); }, ), ), text('total \\$${cartservice totalamount tostringasfixed(2)}'), elevatedbutton( onpressed () { navigator push( context, materialpageroute(builder ( ) => checkoutscreen()), ); }, child text('proceed to checkout'), ), ], ), ); } } ステップ6 – stripe統合による安全なチェックアウト 6 1 stripeアカウントの設定 「 stripeアカウント https //dashboard stripe com/register 」にサインアップします。 stripeダッシュボードの「 開発者 > apiキー 」から、 公開可能キー と 秘密キー を取得します。 6 2 cloud codeにstripe sdkをインストール back4appはjavascriptで書かれたcloud code関数をサポートしています。支払い処理を扱うcloud code関数を作成します。 6 2 1 cloud codeプロジェクトを作成 back4appアプリダッシュボードで、「 アプリ設定 > cloud code関数 」に移動します。 「 コードを編集 」をクリックして、cloud codeエディタを開きます。 6 2 2 npmを初期化し、stripeパッケージをインストール cloud codeターミナル(エディタ内に提供)で、次のコマンドを実行します npm init y npm install stripe\@8 174 0 注意 back4appのクラウドコードはnode jsバージョン14 xを使用しているため、互換性を確認してください。 6 3 支払い意図のためのクラウド関数を作成する クラウドコードエディタで main js を作成または修正します // main js const stripe = require('stripe'); const stripe = stripe('your stripe secret key'); parse cloud define('createpaymentintent', async (request) => { const { amount, currency } = request params; try { const paymentintent = await stripe paymentintents create({ amount amount, currency currency, }); return { clientsecret paymentintent client secret }; } catch (error) { throw new parse error(500, error message); } }); 'your stripe secret key'を実際のstripeシークレットキーに置き換えます。 セキュリティノート クライアント側でシークレットキーを公開しないでください。クラウドコードで安全に保管してください。 6 4 クラウドコードをデプロイする クラウドコードエディタで "デプロイ" をクリックして、関数をデプロイします。 6 5 flutterでの支払いの実装 6 5 1 flutterでのstripeの初期化 「 main dart 」の中で、 parse() initialize の後に、次を追加します import 'package\ flutter stripe/flutter stripe dart'; // inside main() async stripe publishablekey = 'your stripe publishable key'; 「 'your stripe publishable key' 」をあなたのstripeの公開可能キーに置き換えます。 6 5 2 チェックアウト画面の作成 「 checkout screen dart 」を「 lib/screens/ 」の下に追加します // lib/screens/checkout screen dart import 'package\ flutter/material dart'; import 'package\ provider/provider dart'; import ' /services/cart service dart'; import 'package\ flutter stripe/flutter stripe dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import 'order confirmation screen dart'; class checkoutscreen extends statelesswidget { future\<void> processpayment(buildcontext context) async { final cartservice = provider of\<cartservice>(context, listen false); final totalamount = (cartservice totalamount 100) toint(); // amount in cents // call cloud function to create payment intent final response = await parsecloudfunction('createpaymentintent') execute( parameters { 'amount' totalamount, 'currency' 'usd', }, ); if (response success) { final clientsecret = response result\['clientsecret']; // initialize payment sheet await stripe instance initpaymentsheet( paymentsheetparameters setuppaymentsheetparameters( paymentintentclientsecret clientsecret, merchantdisplayname 'your e commerce app', ), ); // display payment sheet await stripe instance presentpaymentsheet(); // payment successful // save order to back4app (to be implemented) cartservice clearcart(); navigator pushreplacement( context, materialpageroute(builder ( ) => orderconfirmationscreen()), ); } else { scaffoldmessenger of(context) showsnackbar( snackbar(content text('payment failed ${response error! message}')), ); } } @override widget build(buildcontext context) { final cartservice = provider of\<cartservice>(context); return scaffold( appbar appbar(title text('checkout')), body column( children \[ text('total \\$${cartservice totalamount tostringasfixed(2)}'), elevatedbutton( onpressed () => processpayment(context), child text('pay now'), ), ], ), ); } } 6 5 3 支払い確認の処理 作成する order confirmation screen dart の下に lib/screens/ // lib/screens/order confirmation screen dart import 'package\ flutter/material dart'; class orderconfirmationscreen extends statelesswidget { @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('order confirmed'), automaticallyimplyleading false, ), body center( child text('thank you for your purchase!'), ), ); } } 6 6 back4appに注文を保存する 次の processpayment メソッドを修正して、注文の詳細を保存します // after successful payment final authservice = provider of\<authservice>(context, listen false); final user = authservice user!; // create order object final order = parseobject('order') set('user', user) set('totalamount', cartservice totalamount) set('status', 'paid') set('paymentintentid', clientsecret); // save order final orderresponse = await order save(); if (orderresponse success) { final orderobject = orderresponse result; // save orderitems for (var cartitem in cartservice items values) { final orderitem = parseobject('orderitem') set('order', orderobject) set('product', parseobject('product') objectid = cartitem product id) set('quantity', cartitem quantity) set('price', cartitem product price); await orderitem save(); } // clear cart and navigate cartservice clearcart(); navigator pushreplacement( context, materialpageroute(builder ( ) => orderconfirmationscreen()), ); } else { scaffoldmessenger of(context) showsnackbar( snackbar(content text('failed to save order')), ); } ステップ7 – 注文追跡 7 1 注文サービスを作成する 次の order service dart の下に lib/services/ // lib/services/order service dart import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import ' /models/order dart'; class orderservice with changenotifier { list\<order> orders = \[]; future\<void> fetchorders(parseuser user) async { final query = querybuilder\<parseobject>(parseobject('order')) whereequalto('user', user) orderbydescending('createdat'); final response = await query query(); if (response success && response results != null) { orders = response results! map((data) { return order fromparseobject(data); }) tolist(); notifylisteners(); } } } ステップ7 – 注文追跡 7 2 注文モデルを作成する 次の場所に追加します order dart の下に lib/models/ // lib/models/order dart import 'package\ parse server sdk flutter/parse server sdk dart'; class order { string id; double totalamount; string status; datetime createdat; order({ required this id, required this totalamount, required this status, required this createdat, }); factory order fromparseobject(parseobject object) { return order( id object objectid!, totalamount object get\<num>('totalamount')! todouble(), status object get\<string>('status')!, createdat object createdat!, ); } } 7 3 注文画面を作成する 次の場所に追加します orders screen dart の下に lib/screens/ // lib/screens/orders screen dart import 'package\ flutter/material dart'; import 'package\ provider/provider dart'; import ' /services/order service dart'; import ' /services/auth service dart'; import ' /models/order dart'; class ordersscreen extends statefulwidget { @override ordersscreenstate createstate() => ordersscreenstate(); } class ordersscreenstate extends state\<ordersscreen> { late orderservice orderservice; @override void initstate() { super initstate(); orderservice = provider of\<orderservice>(context, listen false); final authservice = provider of\<authservice>(context, listen false); orderservice fetchorders(authservice user!); } @override widget build(buildcontext context) { return scaffold( appbar appbar(title text('your orders')), body consumer\<orderservice>( builder (context, orderservice, child) { if (orderservice orders isempty) { return center(child text('no orders found ')); } return listview\ builder( itemcount orderservice orders length, itembuilder (context, index) { final order = orderservice orders\[index]; return listtile( title text('order #${order id}'), subtitle text('status ${order status}'), trailing text('\\$${order totalamount tostringasfixed(2)}'), ); }, ); }, ), ); } } ステップ 8 – レビューと評価 8 1 レビューサービスを作成する 追加 review service dart の下に lib/services/ // lib/services/review service dart import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import ' /models/review\ dart'; class reviewservice with changenotifier { list\<review> reviews = \[]; future\<void> fetchreviews(string productid) async { final query = querybuilder\<parseobject>(parseobject('review')) whereequalto('product', parseobject('product') objectid = productid) includeobject(\['user']); final response = await query query(); if (response success && response results != null) { reviews = response results! map((data) { return review\ fromparseobject(data); }) tolist(); notifylisteners(); } } future\<void> submitreview(string productid, parseuser user, int rating, string comment) async { final review = parseobject('review') set('product', parseobject('product') objectid = productid) set('user', user) set('rating', rating) set('comment', comment); await review\ save(); await fetchreviews(productid); } } 8 2 レビューモデルの作成 追加 review\ dart の下に lib/models/ // lib/models/review\ dart import 'package\ parse server sdk flutter/parse server sdk dart'; class review { string id; int rating; string comment; parseuser user; review({ required this id, required this rating, required this comment, required this user, }); factory review\ fromparseobject(parseobject object) { return review( id object objectid!, rating object get\<num>('rating')! toint(), comment object get\<string>('comment')!, user object get\<parseuser>('user')!, ); } } 8 3 製品詳細画面の更新 「 product detail screen dart 」に、レビューを表示し、提出するセクションを追加します。 // at the end of the column in productdetailscreen expanded( child column( children \[ // display reviews expanded( child consumer\<reviewservice>( builder (context, reviewservice, child) { if (reviewservice reviews isempty) { return center(child text('no reviews yet ')); } return listview\ builder( itemcount reviewservice reviews length, itembuilder (context, index) { final review = reviewservice reviews\[index]; return listtile( title text(review\ user username ?? 'anonymous'), subtitle text(review\ comment), trailing text('${review\ rating}/5'), ); }, ); }, ), ), // submit review textfield( controller reviewcontroller, decoration inputdecoration(hinttext 'write a review'), ), row( children \[ text('rating '), dropdownbutton\<int>( value rating, onchanged (value) { setstate(() { rating = value!; }); }, items list generate(5, (index) => index + 1) map((e) => dropdownmenuitem(value e, child text('$e'))) tolist(), ), elevatedbutton( onpressed () { final authservice = provider of\<authservice>(context, listen false); reviewservice submitreview( product id, authservice user!, rating, reviewcontroller text trim(), ); reviewcontroller clear(); }, child text('submit'), ), ], ), ], ), ), 結論 この包括的なチュートリアルでは、flutterとback4appを使用してeコマースアプリを構築し、cloud codeを介して安全な支払い処理のためにstripeと統合しました。製品リスト、ショッピングカート機能、ユーザー認証、注文追跡、レビューなどの主要な機能を実装しました。 主なポイント back4app統合 flutterアプリのバックエンド管理を簡素化します。 cloud codeを介したstripe統合 機密キーを公開することなく、安全に支払いを処理します。 モジュラーアーキテクチャ サービスとモデルを分離することで、保守性が向上します。 次のステップ セキュリティの強化 適切なエラーハンドリングと入力検証を実装します。 ui/uxの改善 より良いユーザー体験のためにユーザーインターフェースを洗練させます。 在庫管理 購入時に製品の在庫を更新します。 メール通知 ユーザーに注文確認メールを送信します。 管理パネル 製品と注文を管理するための管理インターフェースを作成します。 追加リソース back4app ドキュメント https //www back4app com/docs parse server ガイド https //docs parseplatform org/ flutter 公式ドキュメント https //flutter dev/docs stripe api リファレンス https //stripe com/docs/api flutter stripe パッケージ https //pub dev/packages/flutter stripe 楽しいコーディングを!