Вход в трепетание с API в качестве бэкэндаAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Вход в трепетание с API в качестве бэкэнда

Сообщение Anonymous »

Я сталкиваюсь с проблемой с моей страницей в записи, учетные данные правильны, а логика верна, но я все еще не могу войти или регистрироваться каждый раз, когда я пытаюсь.
Это бэкэнд API, который я использую, и его пример запроса и ответа. Я просто отправлю это из входа и зарегистрируюсь.curl --location -g '{{BASE_URL}}/api/v1/auth/signup/' \
--data-raw '{
"email": "dedreamteam20@gmail.com", //optional
"password": "adrenaline",
"confirm_password": "adrenaline",
"phone_number": "0272266444",
"first_name": "Mike",
"last_name": "Joojo"
}'
< /code>
Нет корпуса ответа < /p>
post regin request
Пример запроса: < /p>
curl --location 'https://emi-skeleton-ax7xk.ondigitaloce ... uth/login/' \
--data '{
"identifier": "0272266444",
"password": "adrenaline"
}'

Response:
{
"code": 1,
"message": "Login successful",
"data": {
"access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzQ3MjU3NjE4LCJpYXQiOjE3NDcyMTQ0MTgsImp0aSI6IjhhMzk1MWQzMDAwNzRhYWE4OWU2NDI2OGJlZThkZTUzIiwidXNlcl9pZCI6MTJ9.HG3af41aFsCAsiSjB8FGafscpdXaYksNZAR7pNQwKDg",
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTc0NzQ3MzYxOCwiaWF0IjoxNzQ3MjE0NDE4LCJqdGkiOiJkYmY1YjlmY2IzNDY0MGEyYWYzMzcyNTExY2YxNDYwMCIsInVzZXJfaWQiOjEyfQ.YflAMwpTYK0PuGUFO5NDMJ_Pyy2Yt2uaHr-UnfIk5PQ",
"user": {
"id": 12,
"email": "gyamfimichael613@gmail.com",
"first_name": "Mike",
"last_name": "Gyamfi",
"phone_number": "0272266444",
"email_verified": true,
"phone_verified": true,
"active": true,
"roles": [
"buyer",
"vendor"
],
"user_profile": {
"user_image": null
},
"vendor_profile": {
"display_name": "Cortex Electronics",
"bio": "Thinking about purchasing anything electronics? Think Cortex",
"is_verified": true,
"date_of_birth": null,
"region": {
"id": 1,
"name": "Greater Accra"
},
"district": {
"id": 1,
"name": "LEKMA"
},
"town": {
"id": 1,
"name": "Teshie"
}
}
}
}
}
< /code>
my auth.service от Flutter, показывающий регистрацию и подпись в логике: < /p>
///Sign Up///////////////////////////
Future signUp({
required String firstName,
required String lastName,
String? email,
required String phone,
required String password,
required String confirmPassword,
}) async {
final response = await http.post(
Uri.parse('$baseURL/auth/signup/'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'first_name': firstName,
'last_name': lastName,
'phone': phone,
'password': password,
'confirm_password': confirmPassword,
if (email != null) 'email': email,
}),
);
return _handleResponse(response);
}

///Login Request//////////////////////
Future login({
required String identifier,
required String password,
}) async {
final url = Uri.parse('$baseURL/auth/login/');
final response = await http.post(
url,
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'identifier': identifier,
'password': password,
}),
);

print('Login response status: ${response.statusCode}');
print('Login response body: ${response.body}');

final data = json.decode(response.body);
if (response.statusCode == 200 && data['code'] == 1) {
final access = data['data']['access'];
final refresh = data['data']['refresh'];
final user = UserModel.fromJson(data['data']['user']);
return {
'accessToken': access,
'refreshToken': refresh,
'user': user,
};
} else {
throw Exception(data['message'] ?? 'Login failed');
}
}
< /code>
Модель: < /p>
import 'package:emi_platform/models/vendor_profile_model.dart';

class UserModel {
final int id;
final String firstName;
final String lastName;
final String phone;
final String? email;
final bool emailVerified;
final bool phoneVerified;
final bool isActive;
final bool isVendor;
final String? userImage;
final VendorProfile? vendorProfile;

UserModel({
required this.id,
required this.firstName,
required this.lastName,
required this.phone,
this.email,
required this.emailVerified,
required this.phoneVerified,
required this.isActive,
required this.isVendor,
this.userImage,
this.vendorProfile,
});

factory UserModel.fromJson(Map json) {
List roles = json['roles'] ?? [];
bool isVendor = roles.contains("vendor");

return UserModel(
id: json['id'],
firstName: json['first_name'] ?? '',
lastName: json['last_name'] ?? '',
phone: json['phone_number'] ?? '',
email: json['email'],
emailVerified: json['email_verified'] ?? false,
phoneVerified: json['phone_verified'] ?? false,
isActive: json['active'] ?? false,
isVendor: isVendor,
userImage: json['user_profile']?['user_image'],
vendorProfile: json['vendor_profile'] != null
? VendorProfile.fromJson(json['vendor_profile'])
: null,
);
}

Map toJson() {
return {
'id': id,
'first_name': firstName,
'last_name': lastName,
'phone_number': phone,
'email': email,
'email_verified': emailVerified,
'phone_verified': phoneVerified,
'active': isActive,
'is_vendor': isVendor,
'user_image': userImage,
'vendor_profile': vendorProfile?.toJson(),
};
}
}
< /code>
Я использовал пакет провайдеров для моего управления штатом, это класс Authprovider, показывающий управление состоянием как для Signin, так и для регистрации. < /p>
///Register ////////////
Future signup({
required String firstName,
required String lastName,
String? email,
required String phone,
required String password,
required String confirmPassword,
}) async {
final response = await _authService.signUp(
firstName: firstName,
lastName: lastName,
email: email,
phone: phone,
password: password,
confirmPassword: confirmPassword,
);

return response['success'];
}

///Login /////////

Future login({required String phone, required String password}) async {
tempPassword = password;
try {
final response = await _authService.login(
identifier: phone,
password: password,
);

final token = response['accessToken'];
final user = response['user'];

_token = token;
_user = user;
_isAuthenticated = true;
_isGuest = false;

final prefs = await SharedPreferences.getInstance();
await prefs.setString('token', _token!);

notifyListeners();
return true;
} catch (e, stackTrace) {
print('Login exception: $e');
print(stackTrace);
rethrow;
}

/// logout //////////
Future logout() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove('token');
_user = null;
_token = null;
_isAuthenticated = false;
_isGuest = true;
notifyListeners();
}
< /code>
Теперь я использовал его на экране знака как так: < /p>
import 'package:emi_platform/screens/forgot_password/forgot_password_screen.dart';
import 'package:emi_platform/screens/sign_up_dir/register_page.dart';
import 'package:emi_platform/state_management/user_auth_provider.dart';
import 'package:emi_platform/utils/constants.dart';
import 'package:emi_platform/widgets/custom_elevated_button.dart';
import 'package:emi_platform/widgets/custom_text_field.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';

class LoginPage extends StatefulWidget {
static const String id = 'sign in';

const LoginPage({super.key});

@override
State createState() => _LoginPageState();
}

class _LoginPageState extends State {
final TextEditingController phoneController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
final _formKey = GlobalKey();
bool _isLoading = false;

@override
void dispose() {
phoneController.dispose();
passwordController.dispose();
super.dispose();
}

Future _handleLogin() async {
if (!_formKey.currentState!.validate()) return;

setState(() => _isLoading = true);

final authProvider = Provider.of(context, listen: false);
try {
final success = await authProvider.login(
phone: phoneController.text.trim(),
password: passwordController.text,
);

setState(() => _isLoading = false);
if (!success) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Login failed. Check credentials.')),
);
return;
}

final user = authProvider.user;
final phone = phoneController.text.trim();
final password = passwordController.text;

if (user != null && user.phoneVerified == false) {
if (!mounted) return;
Navigator.pushReplacementNamed(
context,
'otp_page',
arguments: {
'phone': phone,
'password': password,
},
);
} else {}
} catch (e) {
setState(() => _isLoading = false);
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Login error: $e')),
);
}
}

@override
Widget build(BuildContext context) {
final isDark = Theme.of(context).brightness == Brightness.dark;

return Scaffold(
body: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.only(left: 24, right: 24, top: 125),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 40),
Text(
'Welcome Back!',
style: AppTextStyle.withColor(
AppTextStyle.kHeadlineTextH1,
Theme.of(context).textTheme.bodyLarge!.color!,
),
),
const SizedBox(height: 8),
Text(
'Sign in to access your account and continue your journey with us.',
style: AppTextStyle.kBodyLarge,
selectionColor:
isDark ? Colors.grey[400] : Colors.grey[600],
),
const SizedBox(height: 40),

///PhoneNumber Field ///////
Text(
'Phone Number',
style: AppTextStyle.kLabelTextMedium,
selectionColor:
isDark ? Colors.grey[700] : Colors.grey[300],
),
CustomTextField(
controller: phoneController,
prefixIcon: Icons.phone_outlined,
hint: '0xxxxxxxxxx',
keyboardType: TextInputType.phone,
textInputAction: TextInputAction.done,
autoFillHints: const [AutofillHints.telephoneNumber],
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(11),
],
validator: (value) {
if (value == null || value.isEmpty) {
return 'Enter phone number';
}
if (!RegExp(r'^\d{10,}$').hasMatch(value)) {
return 'Invalid phone number';
}
return null;
},
),
const SizedBox(height: 20),

/// Password ////
Text(
'Password',
style: AppTextStyle.kLabelTextMedium,
selectionColor:
isDark ? Colors.grey[700] : Colors.grey[300],
),
CustomTextField(
controller: passwordController,
prefixIcon: Icons.lock_outline,
hint: '*******',
keyboardType: TextInputType.visiblePassword,
textInputAction: TextInputAction.done,
isPassword: true,
validator: (value) => value == null || value.isEmpty
? 'Enter password'
: null,
),
const SizedBox(height: 8),

///Forgot Password TextButton///
Align(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: () =>
Navigator.pushNamed(context, ForgotPasswordScreen.id),
child: Text(
'Forgot Password?',
style: AppTextStyle.kButtonMedium.copyWith(
color: const Color(0xff3471f6),
),
selectionColor:
Theme.of(context).textTheme.bodyLarge!.color!,
),
),
),

///Sign in Button ////////
CustomElevatedButton(
text: 'Sign In',
isLoading: _isLoading,
onPressed: _handleLogin,
),

///Sign Up TextButton///
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Don\'t have an account?',
style: AppTextStyle.withColor(
AppTextStyle.kBodyMedium,
isDark ? Colors.grey[400]! : Colors.grey[600]!,
),
),
TextButton(
onPressed: () =>
Navigator.pushNamed(context, SignUp.id),
child: Text(
'Sign Up',
style: AppTextStyle.withColor(
AppTextStyle.kButtonMedium,
Theme.of(context).primaryColor,
),
),
),
],
),
],
),
),
),
),
),
);
}
}
< /code>
Чтобы помочь решить мои проблемы и по запросу, я вышел сообщения об ошибках из моей консоли на Android Studio. < /p>
I/flutter ( 4710): Login response status: 401
I/flutter ( 4710): Login response body: {"code":0,"message":"Invalid credentials.","error_message":""}
I/flutter ( 4710): Login exception: Exception: Invalid credentials.
I/flutter ( 4710): #0 UserAuthService.login (package:emi_platform/services/user_auth_service.dart:77:7)
I/flutter ( 4710):
I/flutter ( 4710): #1 AuthProvider.login (package:emi_platform/state_management/user_auth_provider.dart:81:24)
I/flutter ( 4710):
I/flutter ( 4710): #2 _LoginPageState._handleLogin (package:emi_platform/screens/sign_in_dir/login_page.dart:44:23)
I/flutter ( 4710):


Подробнее здесь: https://stackoverflow.com/questions/796 ... as-backend
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»