feat(sbp_payments): QR-код оплаты СБП с другого устройства

- Новый SbpQrBottomSheet: рендер checkout_url (qr.nspk.ru/{qrcId}) через qr_flutter,
  сумма, инструкция, автоопределение оплаты polling-ом статуса chosen_plan (3 сек)
  и автозакрытие с успехом
- Кнопка «Оплатить по QR-коду» в шите выбора банков — первичная, под заголовком,
  доступна сразу после получения checkout_url, не дожидаясь списка банков
  (важно для устройств без банковских приложений, iOS в РФ)
- Блок «Симуляция оплаты» (testpay.alfabank.ru/sbp-page?qrcId=...) показывается
  только когда base URL API не продуктовый: AppConfig.isProdApi/prodApiHosts
  (хост целиком — стенды-поддомены eatvio.ru продом не считаются)
- showBottomSheetWithBlur стал генериком — возвращает значение pop(result)
- showConsultationPaymentFlow: опциональная прокидка суммы в QR-шит
- Локализация ru/en, тесты (16 новых, всего 34 платёжных зелёные)
This commit is contained in:
Anatoliy Poloz
2026-11-02 14:03:56 +03:00
parent 7a456c2d9d
commit 1829ad611d
15 changed files with 935 additions and 12 deletions

View File

@@ -658,6 +658,9 @@ class MessageLookup extends MessageLookupByLibrary {
"В пароле должно быть минимум 6 символов",
),
"pay": MessageLookupByLibrary.simpleMessage("Оплатить"),
"pay_by_qr_code": MessageLookupByLibrary.simpleMessage(
"Оплатить по QR-коду",
),
"payment_failed": MessageLookupByLibrary.simpleMessage("Оплата не прошла"),
"pcs": MessageLookupByLibrary.simpleMessage("шт"),
"pending_payment": MessageLookupByLibrary.simpleMessage("Ожидается оплата"),
@@ -777,6 +780,34 @@ class MessageLookup extends MessageLookupByLibrary {
"sbp_payment_error": MessageLookupByLibrary.simpleMessage(
"Не удалось начать оплату. Попробуйте позже",
),
"sbp_qr_amount_label": MessageLookupByLibrary.simpleMessage(
"Сумма к оплате",
),
"sbp_qr_open_test_payment": MessageLookupByLibrary.simpleMessage(
"Открыть тестовую оплату",
),
"sbp_qr_paid_description": MessageLookupByLibrary.simpleMessage(
"Консультация оплачена. Можно вернуться в чат.",
),
"sbp_qr_paid_title": MessageLookupByLibrary.simpleMessage(
"Оплата прошла успешно!",
),
"sbp_qr_step1": MessageLookupByLibrary.simpleMessage(
"Откройте приложение банка на телефоне",
),
"sbp_qr_step2": MessageLookupByLibrary.simpleMessage(
"Выберите «Оплата по QR-коду»",
),
"sbp_qr_step3": MessageLookupByLibrary.simpleMessage(
"Наведите камеру на код",
),
"sbp_qr_test_hint": MessageLookupByLibrary.simpleMessage(
"Симуляция оплаты на тестовом стенде Альфа-Банка",
),
"sbp_qr_title": MessageLookupByLibrary.simpleMessage("Оплата по QR-коду"),
"sbp_qr_waiting_payment": MessageLookupByLibrary.simpleMessage(
"Ожидание оплаты…",
),
"send": MessageLookupByLibrary.simpleMessage("Отправить"),
"send_complain": MessageLookupByLibrary.simpleMessage("Отправить жалобу"),
"services": MessageLookupByLibrary.simpleMessage("Оказание услуг"),

View File

@@ -297,6 +297,9 @@ class MessageLookup extends MessageLookupByLibrary {
"password_short": MessageLookupByLibrary.simpleMessage(
"В пароле должно быть минимум 6 символов",
),
"pay_by_qr_code": MessageLookupByLibrary.simpleMessage(
"Оплатить по QR-коду",
),
"pcs": MessageLookupByLibrary.simpleMessage("шт"),
"personal": MessageLookupByLibrary.simpleMessage("Персональные"),
"personal_diet_state": MessageLookupByLibrary.simpleMessage("Персональная"),
@@ -354,6 +357,34 @@ class MessageLookup extends MessageLookupByLibrary {
"sbp_payment_error": MessageLookupByLibrary.simpleMessage(
"Не удалось начать оплату. Попробуйте позже",
),
"sbp_qr_amount_label": MessageLookupByLibrary.simpleMessage(
"Сумма к оплате",
),
"sbp_qr_open_test_payment": MessageLookupByLibrary.simpleMessage(
"Открыть тестовую оплату",
),
"sbp_qr_paid_description": MessageLookupByLibrary.simpleMessage(
"Консультация оплачена. Можно вернуться в чат.",
),
"sbp_qr_paid_title": MessageLookupByLibrary.simpleMessage(
"Оплата прошла успешно!",
),
"sbp_qr_step1": MessageLookupByLibrary.simpleMessage(
"Откройте приложение банка на телефоне",
),
"sbp_qr_step2": MessageLookupByLibrary.simpleMessage(
"Выберите «Оплата по QR-коду»",
),
"sbp_qr_step3": MessageLookupByLibrary.simpleMessage(
"Наведите камеру на код",
),
"sbp_qr_test_hint": MessageLookupByLibrary.simpleMessage(
"Симуляция оплаты на тестовом стенде Альфа-Банка",
),
"sbp_qr_title": MessageLookupByLibrary.simpleMessage("Оплата по QR-коду"),
"sbp_qr_waiting_payment": MessageLookupByLibrary.simpleMessage(
"Ожидание оплаты…",
),
"services": MessageLookupByLibrary.simpleMessage("Оказание услуг"),
"settings": MessageLookupByLibrary.simpleMessage("Настройки"),
"share": MessageLookupByLibrary.simpleMessage("Поделиться"),

View File

@@ -2689,6 +2689,116 @@ class S {
);
}
/// `Оплатить по QR-коду`
String get pay_by_qr_code {
return Intl.message(
'Оплатить по QR-коду',
name: 'pay_by_qr_code',
desc: '',
args: [],
);
}
/// `Оплата по QR-коду`
String get sbp_qr_title {
return Intl.message(
'Оплата по QR-коду',
name: 'sbp_qr_title',
desc: '',
args: [],
);
}
/// `Сумма к оплате`
String get sbp_qr_amount_label {
return Intl.message(
'Сумма к оплате',
name: 'sbp_qr_amount_label',
desc: '',
args: [],
);
}
/// `Откройте приложение банка на телефоне`
String get sbp_qr_step1 {
return Intl.message(
'Откройте приложение банка на телефоне',
name: 'sbp_qr_step1',
desc: '',
args: [],
);
}
/// `Выберите «Оплата по QR-коду»`
String get sbp_qr_step2 {
return Intl.message(
'Выберите «Оплата по QR-коду»',
name: 'sbp_qr_step2',
desc: '',
args: [],
);
}
/// `Наведите камеру на код`
String get sbp_qr_step3 {
return Intl.message(
'Наведите камеру на код',
name: 'sbp_qr_step3',
desc: '',
args: [],
);
}
/// `Ожидание оплаты…`
String get sbp_qr_waiting_payment {
return Intl.message(
'Ожидание оплаты…',
name: 'sbp_qr_waiting_payment',
desc: '',
args: [],
);
}
/// `Оплата прошла успешно!`
String get sbp_qr_paid_title {
return Intl.message(
'Оплата прошла успешно!',
name: 'sbp_qr_paid_title',
desc: '',
args: [],
);
}
/// `Консультация оплачена. Можно вернуться в чат.`
String get sbp_qr_paid_description {
return Intl.message(
'Консультация оплачена. Можно вернуться в чат.',
name: 'sbp_qr_paid_description',
desc: '',
args: [],
);
}
/// `Открыть тестовую оплату`
String get sbp_qr_open_test_payment {
return Intl.message(
'Открыть тестовую оплату',
name: 'sbp_qr_open_test_payment',
desc: '',
args: [],
);
}
/// `Симуляция оплаты на тестовом стенде Альфа-Банка`
String get sbp_qr_test_hint {
return Intl.message(
'Симуляция оплаты на тестовом стенде Альфа-Банка',
name: 'sbp_qr_test_hint',
desc: '',
args: [],
);
}
/// `Подробнее о заказе`
String get more_about_order {
return Intl.message(