fixes
Some checks failed
Web App CI / test (push) Waiting to run
Web App CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Backend CI / test (push) Has been cancelled
Mobile App CI / test (push) Has been cancelled
Deploy Telegram Bot / Deploy Telegram Bot (push) Has been cancelled
Backend CI / build (push) Has been cancelled
Mobile App CI / build-android (push) Has been cancelled
Mobile App CI / build-ios (push) Has been cancelled
Some checks failed
Web App CI / test (push) Waiting to run
Web App CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Backend CI / test (push) Has been cancelled
Mobile App CI / test (push) Has been cancelled
Deploy Telegram Bot / Deploy Telegram Bot (push) Has been cancelled
Backend CI / build (push) Has been cancelled
Mobile App CI / build-android (push) Has been cancelled
Mobile App CI / build-ios (push) Has been cancelled
This commit is contained in:
parent
496aac9135
commit
ca2913ad55
8 changed files with 63 additions and 21 deletions
|
|
@ -12,6 +12,17 @@ import 'rustore/rustore_purchase_handler.dart';
|
|||
import 'yoo_money.dart';
|
||||
import '../../user/user_drift_extension.dart';
|
||||
|
||||
/// Result of creating YooKassa payment URL
|
||||
class YookassaPaymentResult {
|
||||
final String confirmationUrl;
|
||||
final String paymentId;
|
||||
|
||||
YookassaPaymentResult({
|
||||
required this.confirmationUrl,
|
||||
required this.paymentId,
|
||||
});
|
||||
}
|
||||
|
||||
@lazySingleton
|
||||
class PaymentManager {
|
||||
final AppDatabase _db;
|
||||
|
|
@ -318,7 +329,7 @@ class PaymentManager {
|
|||
}
|
||||
|
||||
/// Создать URL для оплаты через YooKassa
|
||||
Future<String> createYookassaUrl({
|
||||
Future<YookassaPaymentResult> createYookassaUrl({
|
||||
required String amount,
|
||||
required String description,
|
||||
required String userId,
|
||||
|
|
@ -357,8 +368,11 @@ class PaymentManager {
|
|||
await createPayment(paymentDto, userId);
|
||||
print('✅ PaymentManager.createYookassaUrl: Payment created in database');
|
||||
|
||||
print('✅ PaymentManager.createYookassaUrl: Returning confirmationUrl');
|
||||
return yookassaPayment.confirmationUrl!;
|
||||
print('✅ PaymentManager.createYookassaUrl: Returning confirmationUrl and paymentId');
|
||||
return YookassaPaymentResult(
|
||||
confirmationUrl: yookassaPayment.confirmationUrl!,
|
||||
paymentId: yookassaPayment.id,
|
||||
);
|
||||
}
|
||||
|
||||
/// Получить платежи пользователя
|
||||
|
|
|
|||
|
|
@ -137,26 +137,22 @@ class PurchasesApiV2 {
|
|||
|
||||
print('🔍 createPackPurchase: Creating YooKassa payment URL');
|
||||
// Create payment URL
|
||||
final confirmationUrl = await _paymentManager.createYookassaUrl(
|
||||
final paymentResult = await _paymentManager.createYookassaUrl(
|
||||
amount: price,
|
||||
description: 'Покупка пакета: ${pack.title}',
|
||||
userId: user.id!,
|
||||
products: products,
|
||||
);
|
||||
print('✅ createPackPurchase: Payment URL created: $confirmationUrl');
|
||||
|
||||
// Get payment by external token (we need to find it)
|
||||
// Since createYookassaUrl creates payment internally, we need to get it
|
||||
// For now, we'll create a simple response
|
||||
// TODO: Improve this to return proper YookassaPaymentDto
|
||||
print('✅ createPackPurchase: Payment URL created: ${paymentResult.confirmationUrl}, paymentId=${paymentResult.paymentId}');
|
||||
|
||||
// Build return URL for payment verification
|
||||
final baseUri = request.requestedUri;
|
||||
final checkUrl = '${baseUri.scheme}://${baseUri.host}${baseUri.hasPort ? ':${baseUri.port}' : ''}/api/v2/purchases/payments/verify?packId=$packId';
|
||||
final checkUrl = '${baseUri.scheme}://${baseUri.host}${baseUri.hasPort ? ':${baseUri.port}' : ''}/api/v2/purchases/payments/${paymentResult.paymentId}/verify?productId=$packId&productType=pack';
|
||||
|
||||
return _ok({
|
||||
'purchaseUrl': confirmationUrl,
|
||||
'purchaseUrl': paymentResult.confirmationUrl,
|
||||
'checkUrl': checkUrl,
|
||||
'paymentId': paymentResult.paymentId,
|
||||
});
|
||||
} catch (e, s) {
|
||||
print('❌ createPackPurchase ERROR: $e');
|
||||
|
|
@ -287,7 +283,7 @@ class PurchasesApiV2 {
|
|||
}
|
||||
|
||||
// Create payment URL
|
||||
final confirmationUrl = await _paymentManager.createYookassaUrl(
|
||||
final paymentResult = await _paymentManager.createYookassaUrl(
|
||||
amount: price,
|
||||
description: description,
|
||||
userId: user.id!,
|
||||
|
|
@ -296,11 +292,12 @@ class PurchasesApiV2 {
|
|||
|
||||
// Build return URL for payment verification
|
||||
final baseUri = request.requestedUri;
|
||||
final checkUrl = '${baseUri.scheme}://${baseUri.host}${baseUri.hasPort ? ':${baseUri.port}' : ''}/api/v2/purchases/payments/verify?productId=$productId&productType=$productTypeStr';
|
||||
final checkUrl = '${baseUri.scheme}://${baseUri.host}${baseUri.hasPort ? ':${baseUri.port}' : ''}/api/v2/purchases/payments/${paymentResult.paymentId}/verify?productId=$productId&productType=$productTypeStr';
|
||||
|
||||
return _ok({
|
||||
'purchaseUrl': confirmationUrl,
|
||||
'purchaseUrl': paymentResult.confirmationUrl,
|
||||
'checkUrl': checkUrl,
|
||||
'paymentId': paymentResult.paymentId,
|
||||
});
|
||||
} catch (e, s) {
|
||||
developer.log('Error in createPayment: $e', error: e, stackTrace: s);
|
||||
|
|
|
|||
|
|
@ -336,8 +336,15 @@ class AppDatabase extends _$AppDatabase {
|
|||
|
||||
// 2. Удаляем все старые вопросы (soft delete)
|
||||
print('Soft-deleting all existing test questions...');
|
||||
await customStatement(
|
||||
'UPDATE test_questions SET is_deleted = TRUE, deleted_at = NOW() WHERE is_deleted = FALSE',
|
||||
final now = PgDateTime(DateTime.now());
|
||||
await (update(testQuestions)
|
||||
..where((tq) => tq.isDeleted.equals(false)))
|
||||
.write(
|
||||
TestQuestionsCompanion(
|
||||
isDeleted: const Value(true),
|
||||
deletedAt: Value(now),
|
||||
updatedAt: Value(now),
|
||||
),
|
||||
);
|
||||
print(
|
||||
'All old questions marked as deleted. Create new questions via admin panel.',
|
||||
|
|
@ -365,7 +372,7 @@ class AppDatabase extends _$AppDatabase {
|
|||
|
||||
// 5. Удаляем всю старую статистику (она будет создаваться заново)
|
||||
print('Deleting old test statistics...');
|
||||
await customStatement('DELETE FROM test_statistics');
|
||||
await (delete(testStatistics)).go();
|
||||
print(
|
||||
'All old statistics deleted. New statistics will be collected automatically.',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,8 +8,13 @@ part 'yookassa_payment_dto.g.dart';
|
|||
class YookassaPaymentDto {
|
||||
final String purchaseUrl;
|
||||
final String checkUrl;
|
||||
final String paymentId;
|
||||
|
||||
YookassaPaymentDto({required this.purchaseUrl, required this.checkUrl});
|
||||
YookassaPaymentDto({
|
||||
required this.purchaseUrl,
|
||||
required this.checkUrl,
|
||||
required this.paymentId,
|
||||
});
|
||||
|
||||
factory YookassaPaymentDto.fromJson(Map<String, dynamic> json) =>
|
||||
_$YookassaPaymentDtoFromJson(json);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ abstract class _$YookassaPaymentDtoCWProxy {
|
|||
|
||||
YookassaPaymentDto checkUrl(String checkUrl);
|
||||
|
||||
YookassaPaymentDto paymentId(String paymentId);
|
||||
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `YookassaPaymentDto(...).copyWith.fieldName(value)`.
|
||||
///
|
||||
|
|
@ -18,7 +20,11 @@ abstract class _$YookassaPaymentDtoCWProxy {
|
|||
/// ```dart
|
||||
/// YookassaPaymentDto(...).copyWith(id: 12, name: "My name")
|
||||
/// ```
|
||||
YookassaPaymentDto call({String purchaseUrl, String checkUrl});
|
||||
YookassaPaymentDto call({
|
||||
String purchaseUrl,
|
||||
String checkUrl,
|
||||
String paymentId,
|
||||
});
|
||||
}
|
||||
|
||||
/// Callable proxy for `copyWith` functionality.
|
||||
|
|
@ -35,6 +41,9 @@ class _$YookassaPaymentDtoCWProxyImpl implements _$YookassaPaymentDtoCWProxy {
|
|||
@override
|
||||
YookassaPaymentDto checkUrl(String checkUrl) => call(checkUrl: checkUrl);
|
||||
|
||||
@override
|
||||
YookassaPaymentDto paymentId(String paymentId) => call(paymentId: paymentId);
|
||||
|
||||
@override
|
||||
/// Creates a new instance with the provided field values.
|
||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `YookassaPaymentDto(...).copyWith.fieldName(value)`.
|
||||
|
|
@ -46,6 +55,7 @@ class _$YookassaPaymentDtoCWProxyImpl implements _$YookassaPaymentDtoCWProxy {
|
|||
YookassaPaymentDto call({
|
||||
Object? purchaseUrl = const $CopyWithPlaceholder(),
|
||||
Object? checkUrl = const $CopyWithPlaceholder(),
|
||||
Object? paymentId = const $CopyWithPlaceholder(),
|
||||
}) {
|
||||
return YookassaPaymentDto(
|
||||
purchaseUrl:
|
||||
|
|
@ -57,6 +67,10 @@ class _$YookassaPaymentDtoCWProxyImpl implements _$YookassaPaymentDtoCWProxy {
|
|||
? _value.checkUrl
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: checkUrl as String,
|
||||
paymentId: paymentId == const $CopyWithPlaceholder() || paymentId == null
|
||||
? _value.paymentId
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
: paymentId as String,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -77,10 +91,12 @@ YookassaPaymentDto _$YookassaPaymentDtoFromJson(Map<String, dynamic> json) =>
|
|||
YookassaPaymentDto(
|
||||
purchaseUrl: json['purchaseUrl'] as String,
|
||||
checkUrl: json['checkUrl'] as String,
|
||||
paymentId: json['paymentId'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$YookassaPaymentDtoToJson(YookassaPaymentDto instance) =>
|
||||
<String, dynamic>{
|
||||
'purchaseUrl': instance.purchaseUrl,
|
||||
'checkUrl': instance.checkUrl,
|
||||
'paymentId': instance.paymentId,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ class _PurchasePageState extends State<PurchasePage> {
|
|||
|
||||
// Show dialog with verification option
|
||||
if (mounted) {
|
||||
_showPaymentVerificationDialog(payment.checkUrl);
|
||||
_showPaymentVerificationDialog(payment.paymentId);
|
||||
}
|
||||
} else {
|
||||
if (mounted) {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ void main() {
|
|||
final paymentDto = YookassaPaymentDto(
|
||||
purchaseUrl: 'https://example.com/pay',
|
||||
checkUrl: 'https://example.com/check',
|
||||
paymentId: paymentId,
|
||||
);
|
||||
when(
|
||||
() => httpRepository.createPackPurchase(packId),
|
||||
|
|
@ -59,6 +60,7 @@ void main() {
|
|||
final paymentDto = YookassaPaymentDto(
|
||||
purchaseUrl: 'https://example.com/pay',
|
||||
checkUrl: 'https://example.com/check',
|
||||
paymentId: paymentId,
|
||||
);
|
||||
when(
|
||||
() => httpRepository.createPayment(
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ void main() {
|
|||
final testPayment = YookassaPaymentDto(
|
||||
purchaseUrl: 'https://yookassa.ru/pay/payment-123',
|
||||
checkUrl: 'https://example.com/check/payment-123',
|
||||
paymentId: 'payment-123',
|
||||
);
|
||||
|
||||
test('returns null if pack info not loaded', () async {
|
||||
|
|
|
|||
Loading…
Reference in a new issue