Flutter Templates
Создание приложения электронной коммерции с использованием Flutter, Back4App и интеграцией Stripe через облачный код
49 мин
введение разработка приложения для электронной коммерции включает в себя несколько компонентов, включая списки продуктов, функциональность корзины покупок, безопасную обработку платежей, отслеживание заказов и отзывы пользователей сочетание мощного инструментария ui flutter с масштабируемыми бэкенд сервисами back4app упрощает процесс разработки кроме того, интеграция stripe для обработки платежей через back4app cloud code позволяет безопасно и профессионально обрабатывать транзакции в этом учебном пособии вы создадите приложение для электронной коммерции с следующими функциями списки продуктов отображение продуктов с изображениями, описаниями и ценами корзина покупок добавление и удаление продуктов из корзины пользовательские аккаунты управление профилями пользователей и адресами безопасная оплата обработка платежей безопасно с использованием stripe через back4app cloud code отслеживание заказов отслеживание статуса и истории заказов отзывы и рейтинги позволить пользователям оставлять отзывы и оценки предварительные требования чтобы следовать этому руководству, вам потребуется 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 для интеграции с back4app 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" в качестве имени класса добавьте следующие столбцы имя строка описание строка цена число изображение файл категория строка инвентарь число 2 2 2 класс заказа создайте класс "order" с следующими столбцами пользователь pointer< user> общаясумма число статус строка (значения "ожидание", "оплачено", "отправлено", "доставлено") paymentintentid строка (для отслеживания платежа stripe) адресдоставки строка 2 2 3 класс заказного элемента создайте "orderitem" класс со следующими столбцами заказ указатель продукт указатель количество число цена число 2 2 4 класс отзыва создайте "review" класс со следующими столбцами продукт указатель пользователь pointer< user> рейтинг число комментарий строка 2 3 получение учетных данных приложения перейдите к настройки приложения > безопасность и ключи запишите ваш идентификатор приложения и ключ клиента шаг 3 – реализация управления продуктами 3 1 инициализация parse в flutter откройте 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 обновите main, чтобы включить 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 создать экран корзины добавить 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 через cloud code 6 1 настройка учетной записи stripe зарегистрируйтесь для получения учетной записи stripe https //dashboard stripe com/register получите ваш публикуемый ключ и секретный ключ в панели управления stripe в разделе разработчики > api ключи 6 2 установите sdk stripe в cloud code back4app поддерживает функции cloud code, написанные на javascript мы напишем функции 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 примечание cloud code от 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 инициализация stripe в flutter в main dart , после parse() initialize , добавьте import 'package\ flutter stripe/flutter stripe dart'; // inside main() async stripe publishablekey = 'your stripe publishable key'; замените 'ваш публичный ключ stripe' на ваш публичный ключ 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, интегрированное со stripe для безопасной обработки платежей через cloud code вы реализовали ключевые функции, такие как списки продуктов, функциональность корзины покупок, аутентификация пользователей, отслеживание заказов и отзывы ключевые выводы интеграция с back4app упрощает управление бэкендом для вашего приложения на flutter интеграция с stripe через cloud code безопасно обрабатывает платежи, не раскрывая конфиденциальные ключи модульная архитектура разделение сервисов и моделей улучшает поддерживаемость следующие шаги улучшение безопасности реализуйте правильную обработку ошибок и валидацию ввода улучшения ui/ux усовершенствуйте пользовательский интерфейс для лучшего пользовательского опыта управление запасами обновляйте запасы продуктов после покупки email уведомления отправляйте пользователям электронные письма с подтверждением заказа админ панель создайте интерфейс администратора для управления продуктами и заказами дополнительные ресурсы документация back4app https //www back4app com/docs руководство по parse server https //docs parseplatform org/ официальная документация flutter https //flutter dev/docs справочник api stripe https //stripe com/docs/api пакет flutter stripe https //pub dev/packages/flutter stripe счастливого кодирования!