import 'package:dio/dio.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:networks_sdk/networks_sdk.dart'; import 'package:im_app/core/foundation/api_paths.dart'; import 'package:im_app/core/foundation/errors.dart'; import 'package:im_app/core/foundation/exceptions.dart'; part 'verify_otp_request.g.dart'; /// 校验验证码接口的响应(服务端 data 字段)。 /// /// `token` 是 vcode_token,用于后续 login-user 请求换取 access_token。 /// 纯 Dart 类,无需任何注解。`_$VerifyOtpResponseFromJson` 由生成器自动推导生成。 class VerifyOtpResponse { /// 验证令牌,传给登录接口换取 access_token final String token; const VerifyOtpResponse({required this.token}); factory VerifyOtpResponse.fromJson(Map json) => VerifyOtpResponse(token: json['token'] as String? ?? ''); } /// # /app/api/auth/vcode/check — 校验手机验证码 /// /// 校验成功后返回 [VerifyOtpResponse.token](即 vcode_token), /// 用于 [LoginRequest] 的 `vcode_token` 字段。 /// /// ## 数据流位置 /// /// ``` /// AuthRepositoryImpl.verifyOtp(countryCode, contact, code) /// → _client.executeRequest( ★ VerifyOtpRequest ★ ) ← 你在这里 /// → 服务端 POST /app/api/auth/vcode/check /// → SDK 拆包 {code, message, data} envelope /// ← ★ VerifyOtpResponse ★ — token 即 vcode_token /// ``` @ApiRequest( path: ApiPaths.authVerifyOtp, method: HttpMethod.post, responseType: VerifyOtpResponse, requestType: ApiRequestType.login, ) class VerifyOtpRequest extends ApiRequestable with _$VerifyOtpRequestApi { @JsonKey(name: 'country_code') final String countryCode; final String contact; /// 邮箱(手机号登录传空字符串) final String email; /// 用户输入的验证码 final String code; /// type=1 表示手机号验证 final int type; VerifyOtpRequest({ required this.countryCode, required this.contact, required this.code, this.email = '', this.type = 1, }); /// 拦截二级密码错误码 30164,将服务端 data 中的 vcode_token 等字段 /// 包装为 [SecondaryPasscodeRequiredException] 抛出,供上层导航至 /// 二级密码输入界面。其余情况委托给基类处理。 @override VerifyOtpResponse? decodeResponse(Response response) { if (response.data is Map) { final json = response.data as Map; final rawCode = json['code']; final code = rawCode is int ? rawCode : int.tryParse(rawCode?.toString() ?? '') ?? 0; if (code == ApiErrorCodes.secondaryPasscodeRequired) { final data = json['data'] as Map?; throw SecondaryPasscodeRequiredException( vcodeToken: data?['vcode_token'] as String? ?? '', recoveryEmail: data?['recovery_email'] as String? ?? '', hint: data?['hint'] as String? ?? '', resetStatus: data?['reset_status'] as bool? ?? false, ); } } return super.decodeResponse(response); } }