Flutter Templates
플러터, 백4앱, 클라우드 코드를 통한 스트라이프 통합으로 전자상거래 앱 구축하기
49 분
소개 전자상거래 앱 개발은 제품 목록, 쇼핑 카트 기능, 안전한 결제 처리, 주문 추적 및 사용자 리뷰를 포함한 여러 구성 요소를 포함합니다 flutter의 강력한 ui 툴킷과 back4app의 확장 가능한 백엔드 서비스를 결합하면 개발 프로세스가 간소화됩니다 또한 back4app cloud code를 통해 stripe를 결제 처리에 통합하면 안전하고 전문적인 거래 처리가 가능합니다 이 튜토리얼에서는 다음 기능을 갖춘 전자상거래 앱을 구축합니다 제품 목록 이미지, 설명 및 가격이 포함된 제품을 표시합니다 쇼핑 카트 카트에 제품을 추가하고 제거합니다 사용자 계정 사용자 프로필 및 주소를 관리합니다 안전한 체크아웃 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단계 – 백4앱 설정하기 2 1 새로운 백4앱 애플리케이션 만들기 당신의 백4앱 대시보드 https //dashboard back4app com/ 에 로그인하세요 "새 앱 만들기"를 클릭하세요 애플리케이션 이름으로 "ecommerceapp"을 입력하고 "생성" 을 클릭하세요 2 2 데이터 모델 설정하기 우리는 백4앱에서 여러 클래스를 만들어야 합니다 제품 사용자 (내장 클래스) 주문 주문 항목 리뷰 2 2 1 제품 클래스 "데이터베이스" 섹션으로 이동합니다 "클래스 생성" 을 클릭합니다 "사용자 정의" 를 선택하고 "제품" 을 클래스 이름으로 입력합니다 다음 열을 추가합니다 이름 문자열 설명 문자열 가격 숫자 이미지 파일 카테고리 문자열 재고 숫자 2 2 2 주문 클래스 다음 열로 "주문" 클래스를 생성합니다 사용자 pointer< user> 총 금액 숫자 상태 문자열 (값 "대기 중", "지불됨", "배송됨", "배달됨") 결제 의도 id 문자열 (stripe 결제를 추적하기 위해) 배송 주소 문자열 2 2 3 주문 항목 클래스 다음 열이 있는 "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 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 장바구니 화면 만들기 add cart screen dart under 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 클라우드 코드에 stripe sdk 설치 back4app은 javascript로 작성된 클라우드 코드 기능을 지원합니다 결제 처리를 위한 클라우드 코드 기능을 작성할 것입니다 6 2 1 클라우드 코드 프로젝트 생성 back4app 앱 대시보드에서 앱 설정 > 클라우드 코드 기능 으로 이동하세요 클릭하여 "코드 편집" 를 선택하여 클라우드 코드 편집기를 엽니다 6 2 2 npm 초기화 및 stripe 패키지 설치 클라우드 코드 터미널(편집기에서 제공됨)에서 다음을 실행하세요 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 제품 상세 화면 업데이트 in 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을 사용하여 전자상거래 앱을 구축하고, cloud code를 통해 stripe와 통합하여 안전한 결제 처리를 구현했습니다 제품 목록, 쇼핑 카트 기능, 사용자 인증, 주문 추적 및 리뷰와 같은 주요 기능을 구현했습니다 주요 요점 back4app 통합 flutter 앱의 백엔드 관리를 간소화합니다 cloud code를 통한 stripe 통합 민감한 키를 노출하지 않고 안전하게 결제를 처리합니다 모듈식 아키텍처 서비스와 모델을 분리하여 유지 관리성을 향상시킵니다 다음 단계 보안 강화 적절한 오류 처리 및 입력 유효성 검사를 구현합니다 ui/ux 개선 더 나은 사용자 경험을 위한 사용자 인터페이스를 개선합니다 재고 관리 구매 시 제품 재고를 업데이트합니다 이메일 알림 사용자에게 주문 확인 이메일을 보냅니다 관리자 패널 제품 및 주문 관리를 위한 관리자 인터페이스를 생성합니다 추가 리소스 back4app 문서 https //www back4app com/docs parse 서버 가이드 https //docs parseplatform org/ flutter 공식 문서 https //flutter dev/docs stripe api 참조 https //stripe com/docs/api flutter stripe 패키지 https //pub dev/packages/flutter stripe 행복한 코딩 되세요!