TGViewer
Flutter Friendly Flutter Friendly @flutterfriendly · 995 subscribers
Post #40 613
Создаем Flutter-приложение для оплаты через СБП

В предыдущем посте рассказали о главных шагах, теперь разберем их подробнее. Начинаем с настройки получения списка банков.

🔸Создаем объект для полей bankName, logoURL и schema. (Для безопасного парсинга данных рекомендуем использовать паттерн проектирования DTO):

```dart
class BankItem {
const BankItem({
required this.bankName,
required this.logoURL,
required this.schema,
});

final String bankName;
final String logoURL;
final String schema;

static BankItem? fromJson(Map<String, dynamic> json) {
final bankName = json['bankName'] as String?;
final logoURL = json['logoURL'] as String?;
final schema = json['schema'] as String?;

if (bankName == null || logoURL == null || schema == null) {
return null;
}

return BankItem(
bankName: utf8.decode(bankName.codeUnits),
logoURL: logoURL,
schema: schema,
);
}
}
```

*Здесь используем utf8 из-за проблем с кодировкой. Если у банка нет схемы, имени или картинки, не считаем его валидным.

🔸Создаем абстрактный репозиторий SbpRepository для управления запросами СБП и реализуем метод getBankList в NewtorkSbpRepository, чтобы получить список банков-участников СБП:
class NewtorkSbpRepository implements SbpRepository {
Future<Iterable<BankItem>> getBankList() async {
try {
final response = await http.get(
Uri.parse('https://qr.nspk.ru/proxyapp/c2bmembers.json'),
);
final decodedMap = jsonDecode(response.body) as Map<String, dynamic>;
final rawBanks = decodedMap['dictionary'] as List;

final banks = rawBanks.map((e) => BankItem.fromJson(e)).whereNotNull();

return banks;
} catch (error, trace) {
/// Добавить обработку особых ошибок
rethrow;
}
}
}

Реализованный метод можно вызывать на любом этапе бизнес-логики, где нужно получить список банков.

Для управления состояниями можно использовать любой стейт-менеджер, который вам нравится (например flutter_bloc, riverpod).

Мы рассмотрим вариант без сторонних библиотек, используем FutureBuilder и InheritedWidget.

🔸Создаем экран для оплаты, который будет при инициализации запрашивать список банков из репозитория:


class SbpPayScreen extends StatefulWidget {
const SbpPayScreen({super.key});

@override
State<SbpPayScreen> createState() => _SbpPayScreenState();
}

class _SbpPayScreenState extends State<SbpPayScreen> {
late final Future<Iterable<BankItem>> bankList;

@override
void initState() {
bankList = SbpController.of(context).repository.getBankList();

super.initState();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Оплата СБП'),
),
body: FutureBuilder(
future: bankList,
builder: (context, snapshot) {
if (snapshot.hasData) {
final data = snapshot.data!;
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) => ListTile(
title: Text(data.elementAt(index).bankName),
),
);
}
if (snapshot.hasError) {
return const Text('Произошла ошибка');
}
return const Center(child: CircularProgressIndicator());
},
),
);
}
}
  • 🔥 8
  • ❤ 7
  • 👍 5
More from @flutterfriendly
  1. May 14, 2026👀Какой сложный вопрос или тема по Flutter вас сейчас беспокоят? Может, задача не идет, ба…
  2. Apr 17, 2026💭Привет! Это Роза, Flutter-разработчица Friflex! Уверена, многие из вас знакомы с Dart De…
  3. Apr 8, 2026Привет, друзья! Делимся нашей страничкой на Хабре, чтобы всегда оставаться на связи. Там е…
  4. Apr 3, 2026🌸Апрель в календаре и на экране Весна зовет обновлять визуальное: убирать темные темы и в…
  5. Apr 1, 2026Всегда с нетерпением ждем этого дня, чтобы сделать подборку ИТ-мемов Пусть поводов для улы…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →