优化:根据新的API优化框架代码

This commit is contained in:
ivan 2026-04-02 18:40:31 +08:00
parent e77f5f45b7
commit bdab80b2bd
16 changed files with 730 additions and 90 deletions

View File

@ -77,7 +77,7 @@ void main() {
``` ```
调用层 (原始字段) 调用层 (原始字段)
ProxyClient.request() ProxyClient.request()(自动加 `pkg`;默认加 `User_token`
字段映射 (原始 → V2) 字段映射 (原始 → V2)
@ -86,6 +86,10 @@ AES 加密
发送请求 发送请求
``` ```
**请求头**`ProxyClient` 会将 [AppConfig.packageName] 写入映射后的包名字段(原始名 `pkg`);若已设置用户 token默认还会写入 `User_token`。**`UserApi.fast_login` 等无需登录态接口**内部使用 `includeUserTokenInHeader: false`,避免把旧 token 打进 `filter_type`。其余请求也可在直接调用 `ProxyClient.request` 时传入该参数。
**请求体**:各 `*Api` 方法使用与《客户端指南》解密表一致的**原始字段名**(如 `referer``deviceId``fileUrls` / `contentType` / `content`)。
### 3.2 响应流程 ### 3.2 响应流程
``` ```
@ -131,9 +135,10 @@ AES 解密
final res = await UserApi.fastLogin( final res = await UserApi.fastLogin(
deviceId: '设备ID', deviceId: '设备ID',
sign: 'MD5(deviceId)大写', sign: 'MD5(deviceId)大写',
app: 'HAndroid', // 必填HIOS / HAndroid
referer: '归因来源', // 可选 referer: '归因来源', // 可选
ch: '渠道号', // 可选 ch: '渠道号', // 可选
type: '类型', // 可选 type: 'fb', // 可选;未传时默认 fb
); );
if (res.isSuccess) { if (res.isSuccess) {
@ -157,9 +162,17 @@ if (res.isSuccess) {
#### 5.1.2 getCommonInfo - 获取用户通用信息 #### 5.1.2 getCommonInfo - 获取用户通用信息
```dart ```dart
final config = ApiClient.instance.config;
final backendApp = defaultTargetPlatform == TargetPlatform.iOS
? config.backendAppTypeIOS
: config.backendAppTypeAndroid;
final res = await UserApi.getCommonInfo( final res = await UserApi.getCommonInfo(
app: '应用ID', app: backendApp, // 必填HIOS / HAndroid 等与后端约定
pkg: config.packageName, // 必填:包名
userId: '用户ID', // 可选 userId: '用户ID', // 可选
deviceId: '设备ID', // 可选
// client / ch / inviteBy / clientId 可选
); );
if (res.isSuccess) { if (res.isSuccess) {
@ -173,7 +186,7 @@ if (res.isSuccess) {
```dart ```dart
final res = await UserApi.getAccount( final res = await UserApi.getAccount(
app: '应用ID', app: 'HAndroid',
userId: '用户ID', // 可选 userId: '用户ID', // 可选
); );
@ -191,6 +204,46 @@ if (res.isSuccess) {
- `isVip`: 是否 VIP - `isVip`: 是否 VIP
- `freeTimes`: 免费次数 - `freeTimes`: 免费次数
#### 5.1.4 getAppLanguage - App 语言配置
`GET /v1/config/app-language`(需登录)
```dart
final res = await UserApi.getAppLanguage(
pkg: ApiClient.instance.config.packageName,
lang: 'en', // 可选
);
```
**返回实体**: `AppLanguageConfigResponse``config` 为语言配置 JSON 字符串)
#### 5.1.5 getCreditsPage - 积分分页流水
`ImageApi.getCreditsPageInfo` 相同,路径 `GET /v1/user/credits-page`
```dart
final res = await UserApi.getCreditsPage(page: '1', size: '10', type: '1');
```
#### 5.1.6 getUserPayments - 用户支付记录
```dart
final res = await UserApi.getUserPayments(
app: backendApp,
userId: '用户ID',
);
```
**返回实体**: `UserPaymentsListResponse``items`: `UserPaymentRecord` 列表)
#### 5.1.7 getUnreadMessageCount - 未读消息数
```dart
final res = await UserApi.getUnreadMessageCount(types: '类型列表'); // types 可选
```
**返回实体**: `UnreadMessageCountResponse`
--- ---
### 5.2 PaymentApi - 支付相关 ### 5.2 PaymentApi - 支付相关
@ -199,7 +252,8 @@ if (res.isSuccess) {
```dart ```dart
final res = await PaymentApi.getGooglePayActivities( final res = await PaymentApi.getGooglePayActivities(
app: '应用ID', // 可选 app: 'HAndroid', // 可选;默认 `AppConfig.backendAppTypeAndroid`
client: '客户端', // 可选
country: '国家', // 可选 country: '国家', // 可选
); );
@ -226,7 +280,7 @@ if (res.isSuccess) {
```dart ```dart
final res = await PaymentApi.getPaymentMethods( final res = await PaymentApi.getPaymentMethods(
activityId: '活动ID', activityId: 12345, // int与接口一致
country: '国家', // 可选 country: '国家', // 可选
); );
@ -252,7 +306,7 @@ if (res.isSuccess) {
```dart ```dart
final res = await PaymentApi.createPayment( final res = await PaymentApi.createPayment(
app: '应用ID', app: 'HAndroid', // HIOS / HAndroid
userId: '用户ID', userId: '用户ID',
activityId: '活动ID', activityId: '活动ID',
paymentMethod: '支付方式', paymentMethod: '支付方式',
@ -271,7 +325,24 @@ if (res.isSuccess) {
- `payUrl`: 支付链接 - `payUrl`: 支付链接
- `status`: 状态 - `status`: 状态
#### 5.2.4 getOrderDetail - 获取订单详情 #### 5.2.4 getPaymentDetailList - 支付订单列表
`GET /v1/payment/getPaymentDetailList`
```dart
final res = await PaymentApi.getPaymentDetailList(
app: 'HAndroid',
userId: '用户ID',
paymentMethod: 'GOOGLEPAY', // 可选
filterStatus: 'SUCCESS', // 可选
);
```
**返回实体**: `PaymentOrderListResponse``orders`: `PaymentOrderSummary` 列表)
#### 5.2.5 getOrderDetail - 获取订单详情
Query 使用原始字段 `id`(值为订单/支付 ID
```dart ```dart
final res = await PaymentApi.getOrderDetail( final res = await PaymentApi.getOrderDetail(
@ -290,7 +361,7 @@ if (res.isSuccess) {
- `status`: 状态 - `status`: 状态
- `amount`: 金额 - `amount`: 金额
#### 5.2.5 googlepay - Google Pay 回调 #### 5.2.6 googlepay - Google Pay 回调
```dart ```dart
final res = await PaymentApi.googlepay( final res = await PaymentApi.googlepay(
@ -410,26 +481,29 @@ if (res.isSuccess) {
#### 5.3.6 getCreditsPageInfo - 获取积分页面信息 #### 5.3.6 getCreditsPageInfo - 获取积分页面信息
对应 `GET /v1/user/credits-page`(与 `UserApi.getCreditsPage` 相同)。
```dart ```dart
final res = await ImageApi.getCreditsPageInfo( final res = await ImageApi.getCreditsPageInfo(
app: '应用ID', page: '1',
userId: '用户ID', // 可选 size: '10',
ch: '渠道', // 可选 type: '1',
); );
// 或UserApi.getCreditsPage(page: '1', size: '10', type: '1');
if (res.isSuccess) { if (res.isSuccess) {
final info = res.data!; final info = res.data!;
final credits = info.credits; final total = info.total;
final freeTimes = info.freeTimes; final records = info.records;
final isVip = info.isVip; final credits = info.credits; // 若后端仍返回单屏字段则可用
} }
``` ```
**返回实体**: `CreditsPageInfoResponse` **返回实体**: `CreditsPageInfoResponse`
- `credits`: 积分 - `total` / `current` / `pages` / `size` / `records`: 分页与流水(新接口)
- `freeTimes`: 免费次数 - `credits` / `freeTimes` / `isVip` / `vipExpireTime`: 兼容旧字段
- `isVip`: 是否 VIP - `records` 项见 `CreditRecordItem`
- `vipExpireTime`: VIP 过期时间
--- ---
@ -587,6 +661,7 @@ class AuthService {
final res = await UserApi.fastLogin( final res = await UserApi.fastLogin(
deviceId: deviceId, deviceId: deviceId,
sign: sign, sign: sign,
app: 'HAndroid', // 或 AppConfig.backendAppTypeAndroid / IOS
referer: 'organic', referer: 'organic',
); );
@ -613,7 +688,7 @@ class PaymentService {
} }
// 2. 获取支付方式 // 2. 获取支付方式
static Future<List<PaymentMethodItem>> getPaymentMethods(String activityId) async { static Future<List<PaymentMethodItem>> getPaymentMethods(int activityId) async {
final res = await PaymentApi.getPaymentMethods(activityId: activityId); final res = await PaymentApi.getPaymentMethods(activityId: activityId);
return res.data?.paymentMethods ?? []; return res.data?.paymentMethods ?? [];
} }
@ -625,7 +700,7 @@ class PaymentService {
required String paymentMethod, required String paymentMethod,
}) async { }) async {
final res = await PaymentApi.createPayment( final res = await PaymentApi.createPayment(
app: ApiClient.instance.config.appId, app: ApiClient.instance.config.backendAppTypeAndroid,
userId: userId, userId: userId,
activityId: activityId, activityId: activityId,
paymentMethod: paymentMethod, paymentMethod: paymentMethod,

View File

@ -47,15 +47,13 @@
### 4.1 接口 ### 4.1 接口
```dart ```dart
// Android // Androidapp 默认 backendAppTypeAndroid可传 client
final res = await PaymentApi.getGooglePayActivities( final res = await PaymentApi.getGooglePayActivities(
app: '应用ID', // 可选
country: '国家', // 可选 country: '国家', // 可选
); );
// iOS // iOSapp 默认 backendAppTypeIOS
final res = await PaymentApi.getApplePayActivities( final res = await PaymentApi.getApplePayActivities(
app: '应用ID', // 可选
country: '国家', // 可选 country: '国家', // 可选
); );
``` ```
@ -85,7 +83,7 @@ class PaymentProductItem {
```dart ```dart
final res = await PaymentApi.getPaymentMethods( final res = await PaymentApi.getPaymentMethods(
activityId: '活动ID', activityId: 12345, // int
country: '国家', // 可选 country: '国家', // 可选
); );
@ -104,7 +102,7 @@ if (res.isSuccess) {
```dart ```dart
final res = await PaymentApi.createPayment( final res = await PaymentApi.createPayment(
app: '应用ID', app: 'HAndroid', // HIOS / HAndroid
userId: '用户ID', userId: '用户ID',
activityId: '活动ID', activityId: '活动ID',
paymentMethod: '支付方式', paymentMethod: '支付方式',
@ -132,7 +130,7 @@ if (res.isSuccess) {
```dart ```dart
// 1. 创建订单(直接走谷歌支付) // 1. 创建订单(直接走谷歌支付)
final createRes = await PaymentApi.createPayment( final createRes = await PaymentApi.createPayment(
app: '应用ID', app: 'HAndroid',
userId: '用户ID', userId: '用户ID',
activityId: '活动ID', activityId: '活动ID',
paymentMethod: 'GooglePay', paymentMethod: 'GooglePay',
@ -232,6 +230,7 @@ class GooglePayCallbackResponse {
| `getApplePayActivities` | GET | `PaymentProductsResponse` | | `getApplePayActivities` | GET | `PaymentProductsResponse` |
| `getPaymentMethods` | POST | `PaymentMethodsResponse` | | `getPaymentMethods` | POST | `PaymentMethodsResponse` |
| `createPayment` | POST | `CreatePaymentResponse` | | `createPayment` | POST | `CreatePaymentResponse` |
| `getPaymentDetailList` | GET | `PaymentOrderListResponse` |
| `getOrderDetail` | GET | `OrderDetailResponse` | | `getOrderDetail` | GET | `OrderDetailResponse` |
| `googlepay` | POST | `GooglePayCallbackResponse` | | `googlepay` | POST | `GooglePayCallbackResponse` |
@ -250,7 +249,7 @@ class GooglePayCallbackResponse {
| 活动 ID | activityId | - | | 活动 ID | activityId | - |
| 支付方式 | paymentMethod | - | | 支付方式 | paymentMethod | - |
| 支付子类型 | paymentType | - | | 支付子类型 | paymentType | - |
| 订单 ID | orderId | orderId | | 订单 / 支付 ID(详情 query | `id`Dart 仍用参数名 orderId | orderId |
| 购买签名 | signature | - | | 购买签名 | signature | - |
| 购买数据 | purchaseData | - | | 购买数据 | purchaseData | - |
| 商品 ID | - | productId | | 商品 ID | - | productId |

View File

@ -102,12 +102,20 @@ class ProxyClient {
/// [headers][queryParams][body] 使**** /// [headers][queryParams][body] 使****
/// [AppConfig.fieldMapping] V2 /// [AppConfig.fieldMapping] V2
/// data V2 /// data V2
///
/// ****
/// - [AppConfig.packageName] `pkg` `stakeholder`
/// - [userToken] [includeUserTokenInHeader] true `User_token`
///
/// **** `includeUserTokenInHeader: false`
/// token `filter_type`
Future<ApiResponse> request({ Future<ApiResponse> request({
required String path, required String path,
required String method, required String method,
Map<String, String>? headers, Map<String, String>? headers,
Map<String, String>? queryParams, Map<String, String>? queryParams,
Map<String, dynamic>? body, Map<String, dynamic>? body,
bool includeUserTokenInHeader = true,
}) async { }) async {
final pk = config.proxyKeys; final pk = config.proxyKeys;
final mapping = config.fieldMapping; final mapping = config.fieldMapping;
@ -116,7 +124,9 @@ class ProxyClient {
if (config.packageName.isNotEmpty) { if (config.packageName.isNotEmpty) {
headersMap[mapping.headerPackageNameField] = config.packageName; headersMap[mapping.headerPackageNameField] = config.packageName;
} }
if (userToken != null && userToken!.isNotEmpty) { if (includeUserTokenInHeader &&
userToken != null &&
userToken!.isNotEmpty) {
headersMap[mapping.headerUserTokenField] = userToken!; headersMap[mapping.headerUserTokenField] = userToken!;
} }
headersMap = mapping.mapRequest(headersMap); headersMap = mapping.mapRequest(headersMap);
@ -168,6 +178,8 @@ class ProxyClient {
/// ///
/// [headers][queryParams][body] 使**** /// [headers][queryParams][body] 使****
/// [entityFactory] data /// [entityFactory] data
///
/// [request] [includeUserTokenInHeader]
Future<EntityResponse<T>> requestEntity<T extends Entity>({ Future<EntityResponse<T>> requestEntity<T extends Entity>({
required String path, required String path,
required String method, required String method,
@ -175,6 +187,7 @@ class ProxyClient {
Map<String, String>? headers, Map<String, String>? headers,
Map<String, String>? queryParams, Map<String, String>? queryParams,
Map<String, dynamic>? body, Map<String, dynamic>? body,
bool includeUserTokenInHeader = true,
}) async { }) async {
final response = await request( final response = await request(
path: path, path: path,
@ -182,6 +195,7 @@ class ProxyClient {
headers: headers, headers: headers,
queryParams: queryParams, queryParams: queryParams,
body: body, body: body,
includeUserTokenInHeader: includeUserTokenInHeader,
); );
if (response.isSuccess && response.data is Map<String, dynamic>) { if (response.isSuccess && response.data is Map<String, dynamic>) {

View File

@ -28,6 +28,9 @@ const FieldMapping petsHeroAIFieldMapping = FieldMapping({
// === === // === ===
'activityId': 'warrior', 'activityId': 'warrior',
'country': 'vambrace', 'country': 'vambrace',
'client': 'filter',
'id': 'timing',
'filterStatus': 'quest',
'orderId': 'federation', 'orderId': 'federation',
'payUrl': 'convert', 'payUrl': 'convert',
'productId': 'helm', 'productId': 'helm',
@ -51,6 +54,8 @@ const FieldMapping petsHeroAIFieldMapping = FieldMapping({
'cursor': 'platoon', 'cursor': 'platoon',
'declaration': 'declaration', 'declaration': 'declaration',
'quest': 'quest', 'quest': 'quest',
'imgCount': 'indicator',
'aspectRatio': 'caption',
'ext': 'nexus', 'ext': 'nexus',
'imgUrl': 'congregation', 'imgUrl': 'congregation',
'poseId': 'profit', 'poseId': 'profit',

View File

@ -368,13 +368,67 @@ class MyTasksResponse extends Entity {
}; };
} }
/// /// `/v1/user/credits-page` records
class CreditRecordItem extends Entity {
CreditRecordItem({
this.subBusinessType,
this.credits,
this.createTime,
this.businessId,
this.type,
this.businessType,
});
final String? subBusinessType;
final int? credits;
final int? createTime;
final String? businessId;
final int? type;
final String? businessType;
static int? _toInt(dynamic v) {
if (v == null) return null;
if (v is int) return v;
if (v is num) return v.toInt();
if (v is String && v.isNotEmpty) return int.tryParse(v);
return null;
}
@override
factory CreditRecordItem.fromJson(Map<String, dynamic> json) {
return CreditRecordItem(
subBusinessType: json['subBusinessType'] as String?,
credits: _toInt(json['credits']),
createTime: _toInt(json['createTime']),
businessId: json['businessId'] as String?,
type: _toInt(json['type']),
businessType: json['businessType'] as String?,
);
}
@override
Map<String, dynamic> toJson() => {
'subBusinessType': subBusinessType,
'credits': credits,
'createTime': createTime,
'businessId': businessId,
'type': type,
'businessType': businessType,
};
}
/// + `/v1/user/credits-page`
class CreditsPageInfoResponse extends Entity { class CreditsPageInfoResponse extends Entity {
CreditsPageInfoResponse({ CreditsPageInfoResponse({
this.credits, this.credits,
this.freeTimes, this.freeTimes,
this.vipExpireTime, this.vipExpireTime,
this.isVip, this.isVip,
this.total,
this.current,
this.pages,
this.size,
this.records,
}); });
final int? credits; final int? credits;
@ -382,13 +436,43 @@ class CreditsPageInfoResponse extends Entity {
final String? vipExpireTime; final String? vipExpireTime;
final bool? isVip; final bool? isVip;
///
final int? total;
///
final int? current;
///
final int? pages;
///
final int? size;
final List<CreditRecordItem>? records;
static int? _toInt(dynamic v) {
if (v == null) return null;
if (v is int) return v;
if (v is num) return v.toInt();
if (v is String && v.isNotEmpty) return int.tryParse(v);
return null;
}
@override @override
factory CreditsPageInfoResponse.fromJson(Map<String, dynamic> json) { factory CreditsPageInfoResponse.fromJson(Map<String, dynamic> json) {
final recList = json['records'] as List<dynamic>?;
return CreditsPageInfoResponse( return CreditsPageInfoResponse(
credits: json['credits'] as int?, credits: _toInt(json['credits']),
freeTimes: json['freeTimes'] as int?, freeTimes: _toInt(json['freeTimes']),
vipExpireTime: json['vipExpireTime'] as String?, vipExpireTime: json['vipExpireTime'] as String?,
isVip: json['isVip'] as bool?, isVip: json['isVip'] is bool ? json['isVip'] as bool? : null,
total: _toInt(json['total']),
current: _toInt(json['current']),
pages: _toInt(json['pages']),
size: _toInt(json['size']),
records: recList
?.map((e) => CreditRecordItem.fromJson(e as Map<String, dynamic>))
.toList(),
); );
} }
@ -398,5 +482,10 @@ class CreditsPageInfoResponse extends Entity {
'freeTimes': freeTimes, 'freeTimes': freeTimes,
'vipExpireTime': vipExpireTime, 'vipExpireTime': vipExpireTime,
'isVip': isVip, 'isVip': isVip,
'total': total,
'current': current,
'pages': pages,
'size': size,
'records': records?.map((e) => e.toJson()).toList(),
}; };
} }

View File

@ -169,10 +169,11 @@ class OrderDetailResponse extends Entity {
@override @override
factory OrderDetailResponse.fromJson(Map<String, dynamic> json) { factory OrderDetailResponse.fromJson(Map<String, dynamic> json) {
final idRaw = json['orderId'] ?? json['id'];
return OrderDetailResponse( return OrderDetailResponse(
orderId: json['orderId'] as String?, orderId: idRaw == null ? null : idRaw.toString(),
status: json['status'] as String?, status: json['status'] as String?,
amount: json['amount'] as String?, amount: json['amount'] == null ? null : json['amount'].toString(),
); );
} }
@ -198,8 +199,9 @@ class GooglePayCallbackResponse extends Entity {
@override @override
factory GooglePayCallbackResponse.fromJson(Map<String, dynamic> json) { factory GooglePayCallbackResponse.fromJson(Map<String, dynamic> json) {
final idRaw = json['orderId'] ?? json['id'];
return GooglePayCallbackResponse( return GooglePayCallbackResponse(
orderId: json['orderId'] as String?, orderId: idRaw == null ? null : idRaw.toString(),
status: json['status'] as String?, status: json['status'] as String?,
creditsAdded: json['creditsAdded'] as bool?, creditsAdded: json['creditsAdded'] as bool?,
); );
@ -212,3 +214,84 @@ class GooglePayCallbackResponse extends Entity {
'creditsAdded': creditsAdded, 'creditsAdded': creditsAdded,
}; };
} }
/// `getPaymentDetailList`
class PaymentOrderSummary extends Entity {
PaymentOrderSummary({
this.id,
this.status,
this.currency,
this.count,
this.activityId,
this.addCredits,
this.redirectUrl,
});
final String? id;
final String? status;
final String? currency;
final String? count;
final String? activityId;
final bool? addCredits;
final String? redirectUrl;
static String? _str(dynamic v) {
if (v == null) return null;
if (v is String) return v;
return v.toString();
}
@override
factory PaymentOrderSummary.fromJson(Map<String, dynamic> json) {
return PaymentOrderSummary(
id: _str(json['id']),
status: json['status'] as String?,
currency: json['currency'] as String?,
count: _str(json['count']),
activityId: _str(json['activityId']),
addCredits: json['addCredits'] is bool ? json['addCredits'] as bool? : null,
redirectUrl: json['redirectUrl'] as String?,
);
}
@override
Map<String, dynamic> toJson() => {
'id': id,
'status': status,
'currency': currency,
'count': count,
'activityId': activityId,
'addCredits': addCredits,
'redirectUrl': redirectUrl,
};
}
/// `/v1/payment/getPaymentDetailList` data
class PaymentOrderListResponse extends Entity {
PaymentOrderListResponse({required this.orders});
final List<PaymentOrderSummary> orders;
static PaymentOrderListResponse fromDataList(List<dynamic> list) {
return PaymentOrderListResponse(
orders: [
for (final e in list)
PaymentOrderSummary.fromJson(e as Map<String, dynamic>),
],
);
}
@override
factory PaymentOrderListResponse.fromJson(Map<String, dynamic> json) {
final raw = json['orders'] as List<dynamic>?;
if (raw == null) {
return PaymentOrderListResponse(orders: const []);
}
return PaymentOrderListResponse.fromDataList(raw);
}
@override
Map<String, dynamic> toJson() => {
'orders': orders.map((e) => e.toJson()).toList(),
};
}

View File

@ -290,3 +290,167 @@ class AccountResponse extends Entity {
'freeTimes': freeTimes, 'freeTimes': freeTimes,
}; };
} }
/// `/v1/config/app-language` data
class AppLanguageConfigResponse extends Entity {
AppLanguageConfigResponse({this.config});
/// JSON
final String? config;
@override
factory AppLanguageConfigResponse.fromJson(Map<String, dynamic> json) {
return AppLanguageConfigResponse(
config: json['config'] as String?,
);
}
@override
Map<String, dynamic> toJson() => {'config': config};
}
/// `/v1/user/payments`
class UserPaymentRecord extends Entity {
UserPaymentRecord({
this.amount,
this.payTime,
this.payMethod,
this.currency,
this.payId,
});
final int? amount;
final int? payTime;
final String? payMethod;
final String? currency;
final String? payId;
static int? _toInt(dynamic v) {
if (v == null) return null;
if (v is int) return v;
if (v is num) return v.toInt();
if (v is String && v.isNotEmpty) return int.tryParse(v);
return null;
}
@override
factory UserPaymentRecord.fromJson(Map<String, dynamic> json) {
return UserPaymentRecord(
amount: _toInt(json['amount']),
payTime: _toInt(json['payTime']),
payMethod: json['payMethod'] as String?,
currency: json['currency'] as String?,
payId: json['payId'] as String?,
);
}
@override
Map<String, dynamic> toJson() => {
'amount': amount,
'payTime': payTime,
'payMethod': payMethod,
'currency': currency,
'payId': payId,
};
}
/// `/v1/user/payments`
class UserPaymentsListResponse extends Entity {
UserPaymentsListResponse({required this.items});
final List<UserPaymentRecord> items;
static UserPaymentsListResponse fromDataList(List<dynamic> list) {
return UserPaymentsListResponse(
items: [
for (final e in list)
UserPaymentRecord.fromJson(e as Map<String, dynamic>),
],
);
}
@override
factory UserPaymentsListResponse.fromJson(Map<String, dynamic> json) {
final raw = json['items'] as List<dynamic>?;
if (raw == null) {
return UserPaymentsListResponse(items: const []);
}
return UserPaymentsListResponse.fromDataList(raw);
}
@override
Map<String, dynamic> toJson() => {
'items': items.map((e) => e.toJson()).toList(),
};
}
///
class UnreadCountItem extends Entity {
UnreadCountItem({this.count, this.type});
final int? count;
final String? type;
static int? _toInt(dynamic v) {
if (v == null) return null;
if (v is int) return v;
if (v is num) return v.toInt();
if (v is String && v.isNotEmpty) return int.tryParse(v);
return null;
}
@override
factory UnreadCountItem.fromJson(Map<String, dynamic> json) {
return UnreadCountItem(
count: _toInt(json['count']),
type: json['type'] as String?,
);
}
@override
Map<String, dynamic> toJson() => {
'count': count,
'type': type,
};
}
/// `/v1/user/unread-message-count` data
class UnreadMessageCountResponse extends Entity {
UnreadMessageCountResponse({
this.unreadCountList,
this.totalUnreadCount,
this.lastUpdateTime,
});
final List<UnreadCountItem>? unreadCountList;
final int? totalUnreadCount;
final int? lastUpdateTime;
static int? _toInt(dynamic v) {
if (v == null) return null;
if (v is int) return v;
if (v is num) return v.toInt();
if (v is String && v.isNotEmpty) return int.tryParse(v);
return null;
}
@override
factory UnreadMessageCountResponse.fromJson(Map<String, dynamic> json) {
final raw = json['unreadCountList'] as List<dynamic>?;
return UnreadMessageCountResponse(
unreadCountList: raw
?.map((e) => UnreadCountItem.fromJson(e as Map<String, dynamic>))
.toList(),
totalUnreadCount: _toInt(json['totalUnreadCount']),
lastUpdateTime: _toInt(json['lastUpdateTime']),
);
}
@override
Map<String, dynamic> toJson() => {
'unreadCountList':
unreadCountList?.map((e) => e.toJson()).toList(),
'totalUnreadCount': totalUnreadCount,
'lastUpdateTime': lastUpdateTime,
};
}

View File

@ -201,6 +201,9 @@ abstract class FrameworkAuthService {
if (uid.isEmpty) return; if (uid.isEmpty) return;
final config = ApiClient.instance.config; final config = ApiClient.instance.config;
final backendApp = defaultTargetPlatform == TargetPlatform.iOS
? config.backendAppTypeIOS
: config.backendAppTypeAndroid;
// Adjust // Adjust
final adjustReferer = await AttributionService.getAdjustReferrer(); final adjustReferer = await AttributionService.getAdjustReferrer();
@ -210,7 +213,7 @@ abstract class FrameworkAuthService {
: 'android_adjust'; : 'android_adjust';
try { try {
final rAdjust = await UserApi.referrer( final rAdjust = await UserApi.referrer(
app: config.appId, app: backendApp,
userId: uid, userId: uid,
referer: adjustReferer, referer: adjustReferer,
deviceId: deviceId, deviceId: deviceId,
@ -232,7 +235,7 @@ abstract class FrameworkAuthService {
if (playReferrer != null && playReferrer.isNotEmpty) { if (playReferrer != null && playReferrer.isNotEmpty) {
try { try {
final rGg = await UserApi.referrer( final rGg = await UserApi.referrer(
app: config.appId, app: backendApp,
userId: uid, userId: uid,
referer: playReferrer, referer: playReferrer,
deviceId: deviceId, deviceId: deviceId,
@ -252,8 +255,10 @@ abstract class FrameworkAuthService {
// //
try { try {
final commonRes = await UserApi.getCommonInfo( final commonRes = await UserApi.getCommonInfo(
app: config.appId, app: backendApp,
pkg: config.packageName,
userId: uid, userId: uid,
deviceId: deviceId,
); );
if (commonRes.isSuccess && commonRes.data != null) { if (commonRes.isSuccess && commonRes.data != null) {
_callbacks?.onCommonInfoLoaded(commonRes.data!); _callbacks?.onCommonInfoLoaded(commonRes.data!);

View File

@ -3,6 +3,8 @@ import '../api/proxy_client.dart';
import '../entities/feedback_entities.dart'; import '../entities/feedback_entities.dart';
/// / API使 /// / API使
///
/// **Body**`submit``fileUrls``contentType``content`
abstract final class FeedbackApi { abstract final class FeedbackApi {
static ProxyClient get _client => ApiClient.instance.proxy; static ProxyClient get _client => ApiClient.instance.proxy;
@ -31,8 +33,8 @@ abstract final class FeedbackApi {
entityFactory: SubmitFeedbackResponse.fromJson, entityFactory: SubmitFeedbackResponse.fromJson,
body: { body: {
'fileUrls': fileUrls, 'fileUrls': fileUrls,
'content': content,
'contentType': contentType, 'contentType': contentType,
'content': content,
}, },
); );
} }

View File

@ -3,6 +3,8 @@ import '../api/proxy_client.dart';
import '../entities/image_entities.dart'; import '../entities/image_entities.dart';
/// / API使 /// / API使
///
/// **** `pkg` `User_token` [ProxyClient.request]
abstract final class ImageApi { abstract final class ImageApi {
static ProxyClient get _client => ApiClient.instance.proxy; static ProxyClient get _client => ApiClient.instance.proxy;
@ -47,13 +49,20 @@ abstract final class ImageApi {
} }
/// ///
///
/// **Body**`imgCount` 1`aspectRatio``prompt`
static Future<EntityResponse<CreateTaskResponse>> createTxt2Img({ static Future<EntityResponse<CreateTaskResponse>> createTxt2Img({
required String app, required String app,
required String prompt, required String prompt,
String? ch, String? ch,
String? userId, String? userId,
int imgCount = 1,
String? aspectRatio,
/// [aspectRatio]
String? quest, String? quest,
}) async { }) async {
final ratio = aspectRatio ?? quest;
return _client.requestEntity( return _client.requestEntity(
path: '/v1/image/txt2img_create', path: '/v1/image/txt2img_create',
method: 'POST', method: 'POST',
@ -64,8 +73,8 @@ abstract final class ImageApi {
if (userId != null) 'userId': userId, if (userId != null) 'userId': userId,
}, },
body: { body: {
'declaration': 1, 'imgCount': imgCount,
if (quest != null) 'quest': quest, if (ratio != null && ratio.isNotEmpty) 'aspectRatio': ratio,
'prompt': prompt, 'prompt': prompt,
}, },
); );
@ -209,21 +218,27 @@ abstract final class ImageApi {
); );
} }
/// /// `UserApi.getCreditsPage` `GET /v1/user/credits-page`
///
/// [app][userId][ch]
static Future<EntityResponse<CreditsPageInfoResponse>> getCreditsPageInfo({ static Future<EntityResponse<CreditsPageInfoResponse>> getCreditsPageInfo({
required String app, String page = '1',
String size = '10',
String type = '1',
String? app,
String? userId, String? userId,
String? ch, String? ch,
}) async { }) async {
return _client.requestEntity( return _client.requestEntity(
path: '/v1/image/getCreditsPageInfo', path: '/v1/user/credits-page',
method: 'GET', method: 'GET',
entityFactory: CreditsPageInfoResponse.fromJson, entityFactory: CreditsPageInfoResponse.fromJson,
queryParams: { queryParams: {
'app': app, 'page': page,
if (userId != null) 'userId': userId, 'size': size,
if (ch != null) 'ch': ch, 'type': type,
}, },
); );
} }
} }

View File

@ -3,53 +3,61 @@ import '../api/proxy_client.dart';
import '../entities/payment_entities.dart'; import '../entities/payment_entities.dart';
/// API使 /// API使
///
/// **** `pkg` `User_token`
abstract final class PaymentApi { abstract final class PaymentApi {
static ProxyClient get _client => ApiClient.instance.proxy; static ProxyClient get _client => ApiClient.instance.proxy;
/// Google Android /// Google Android
///
/// `app` [AppConfig.backendAppTypeAndroid] [client][country]
static Future<EntityResponse<PaymentProductsResponse>> static Future<EntityResponse<PaymentProductsResponse>>
getGooglePayActivities({ getGooglePayActivities({
String? app, String? app,
String? shield, String? client,
String? country, String? country,
String? pkg, String? pkg,
}) async { }) async {
final cfg = ApiClient.instance.config;
return _client.requestEntity( return _client.requestEntity(
path: '/v1/payment/getGooglePayActivities', path: '/v1/payment/getGooglePayActivities',
method: 'GET', method: 'GET',
entityFactory: PaymentProductsResponse.fromJson, entityFactory: PaymentProductsResponse.fromJson,
queryParams: { queryParams: {
'app': app ?? ApiClient.instance.config.appId, 'app': app ?? cfg.backendAppTypeAndroid,
'pkg': pkg ?? ApiClient.instance.config.packageName, 'pkg': pkg ?? cfg.packageName,
if (shield != null) 'shield': shield, if (client != null && client.isNotEmpty) 'client': client,
if (country != null) 'country': country, if (country != null && country.isNotEmpty) 'country': country,
}, },
); );
} }
/// Apple iOS /// Apple iOS
///
/// `app` [AppConfig.backendAppTypeIOS]
static Future<EntityResponse<PaymentProductsResponse>> getApplePayActivities({ static Future<EntityResponse<PaymentProductsResponse>> getApplePayActivities({
String? app, String? app,
String? shield, String? client,
String? country, String? country,
String? pkg, String? pkg,
}) async { }) async {
final cfg = ApiClient.instance.config;
return _client.requestEntity( return _client.requestEntity(
path: '/v1/payment/getApplePayActivities', path: '/v1/payment/getApplePayActivities',
method: 'GET', method: 'GET',
entityFactory: PaymentProductsResponse.fromJson, entityFactory: PaymentProductsResponse.fromJson,
queryParams: { queryParams: {
'app': app ?? ApiClient.instance.config.backendAppTypeIOS, 'app': app ?? cfg.backendAppTypeIOS,
'pkg': pkg ?? ApiClient.instance.config.packageName, 'pkg': pkg ?? cfg.packageName,
if (shield != null) 'shield': shield, if (client != null && client.isNotEmpty) 'client': client,
if (country != null) 'country': country, if (country != null && country.isNotEmpty) 'country': country,
}, },
); );
} }
/// /// body [activityId] int
static Future<EntityResponse<PaymentMethodsResponse>> getPaymentMethods({ static Future<EntityResponse<PaymentMethodsResponse>> getPaymentMethods({
required String activityId, required int activityId,
String? country, String? country,
}) async { }) async {
return _client.requestEntity( return _client.requestEntity(
@ -64,6 +72,13 @@ abstract final class PaymentApi {
} }
/// ///
///
/// **Query**`app``userId`
/// **Body** +
/// `lastName``country``expireMonth``accountName``userInfoType`
/// `automaticRenewal``channel``cvcCode``channelType``firstName`
/// `subPaymentMethod``phone``tgOrderId``tgId``name``expireYear`
/// `card``status` `lineage``armor` [FieldMapping]
static Future<EntityResponse<CreatePaymentResponse>> createPayment({ static Future<EntityResponse<CreatePaymentResponse>> createPayment({
required String app, required String app,
required String userId, required String userId,
@ -72,6 +87,24 @@ abstract final class PaymentApi {
String? paymentType, String? paymentType,
String? lineage, String? lineage,
String? armor, String? armor,
String? lastName,
String? country,
String? expireMonth,
String? accountName,
String? userInfoType,
bool? automaticRenewal,
String? channel,
String? cvcCode,
String? channelType,
String? firstName,
String? subPaymentMethod,
String? phone,
String? tgOrderId,
String? tgId,
String? name,
String? expireYear,
String? card,
String? status,
}) async { }) async {
return _client.requestEntity( return _client.requestEntity(
path: '/v1/payment/createPayment', path: '/v1/payment/createPayment',
@ -85,13 +118,72 @@ abstract final class PaymentApi {
'paymentMethod': paymentMethod, 'paymentMethod': paymentMethod,
if (paymentType != null && paymentType.isNotEmpty) if (paymentType != null && paymentType.isNotEmpty)
'paymentType': paymentType, 'paymentType': paymentType,
if (lineage != null) 'lineage': lineage, if (lineage != null && lineage.isNotEmpty) 'lineage': lineage,
if (armor != null) 'armor': armor, if (armor != null && armor.isNotEmpty) 'armor': armor,
if (lastName != null && lastName.isNotEmpty) 'lastName': lastName,
if (country != null && country.isNotEmpty) 'country': country,
if (expireMonth != null && expireMonth.isNotEmpty)
'expireMonth': expireMonth,
if (accountName != null && accountName.isNotEmpty)
'accountName': accountName,
if (userInfoType != null && userInfoType.isNotEmpty)
'userInfoType': userInfoType,
if (automaticRenewal != null) 'automaticRenewal': automaticRenewal,
if (channel != null && channel.isNotEmpty) 'channel': channel,
if (cvcCode != null && cvcCode.isNotEmpty) 'cvcCode': cvcCode,
if (channelType != null && channelType.isNotEmpty)
'channelType': channelType,
if (firstName != null && firstName.isNotEmpty) 'firstName': firstName,
if (subPaymentMethod != null && subPaymentMethod.isNotEmpty)
'subPaymentMethod': subPaymentMethod,
if (phone != null && phone.isNotEmpty) 'phone': phone,
if (tgOrderId != null && tgOrderId.isNotEmpty) 'tgOrderId': tgOrderId,
if (tgId != null && tgId.isNotEmpty) 'tgId': tgId,
if (name != null && name.isNotEmpty) 'name': name,
if (expireYear != null && expireYear.isNotEmpty) 'expireYear': expireYear,
if (card != null && card.isNotEmpty) 'card': card,
if (status != null && status.isNotEmpty) 'status': status,
}, },
); );
} }
/// /// data
static Future<EntityResponse<PaymentOrderListResponse>>
getPaymentDetailList({
required String app,
String? userId,
String? paymentMethod,
String? filterStatus,
}) async {
final response = await _client.request(
path: '/v1/payment/getPaymentDetailList',
method: 'GET',
queryParams: {
'app': app,
if (userId != null && userId.isNotEmpty) 'userId': userId,
if (paymentMethod != null && paymentMethod.isNotEmpty)
'paymentMethod': paymentMethod,
if (filterStatus != null && filterStatus.isNotEmpty)
'filterStatus': filterStatus,
},
);
if (response.isSuccess && response.data is List) {
return EntityResponse<PaymentOrderListResponse>(
code: response.code,
msg: response.msg,
data: PaymentOrderListResponse.fromDataList(
response.data! as List<dynamic>,
),
);
}
return EntityResponse<PaymentOrderListResponse>(
code: response.code,
msg: response.msg,
data: null,
);
}
/// query 使 `id` / ID
static Future<EntityResponse<OrderDetailResponse>> getOrderDetail({ static Future<EntityResponse<OrderDetailResponse>> getOrderDetail({
required String userId, required String userId,
required String orderId, required String orderId,
@ -102,30 +194,35 @@ abstract final class PaymentApi {
entityFactory: OrderDetailResponse.fromJson, entityFactory: OrderDetailResponse.fromJson,
queryParams: { queryParams: {
'userId': userId, 'userId': userId,
'orderId': orderId, 'id': orderId,
}, },
); );
} }
/// Google /// Google
///
/// **Query**`app``userId`
/// **Body**`signature``purchaseData``id``userId`
static Future<EntityResponse<GooglePayCallbackResponse>> googlepay({ static Future<EntityResponse<GooglePayCallbackResponse>> googlepay({
required String signature, required String signature,
required String purchaseData, required String purchaseData,
required String orderId, required String orderId,
required String userId, required String userId,
String? app,
}) async { }) async {
final cfg = ApiClient.instance.config;
return _client.requestEntity( return _client.requestEntity(
path: '/v1/payment/googlepay', path: '/v1/payment/googlepay',
method: 'POST', method: 'POST',
entityFactory: GooglePayCallbackResponse.fromJson, entityFactory: GooglePayCallbackResponse.fromJson,
queryParams: { queryParams: {
'app': ApiClient.instance.config.appId, 'app': app ?? cfg.backendAppTypeAndroid,
'userId': userId, 'userId': userId,
}, },
body: { body: {
'signature': signature, 'signature': signature,
'purchaseData': purchaseData, 'purchaseData': purchaseData,
'orderId': orderId, 'id': orderId,
'userId': userId, 'userId': userId,
}, },
); );

View File

@ -1,26 +1,30 @@
import '../api/api_client.dart'; import '../api/api_client.dart';
import '../api/api_response.dart'; import '../api/api_response.dart';
import '../api/proxy_client.dart'; import '../api/proxy_client.dart';
import '../entities/image_entities.dart';
import '../entities/user_entities.dart'; import '../entities/user_entities.dart';
/// API使 /// API使
///
/// **** [UserApi.fastLogin] [ProxyClient]
/// `pkg` `User_token` token fast_login `pkg` token
///
/// ****使**** `referer``deviceId`
abstract final class UserApi { abstract final class UserApi {
static ProxyClient get _client => ApiClient.instance.proxy; static ProxyClient get _client => ApiClient.instance.proxy;
/// ///
/// [deviceId] ID () ///
/// [sign] MD5(deviceId)32 () /// **** `pkg` `User_token`
/// [referer] /// **Query**`app``type` `fb``pkg``ch`
/// [ch] /// **Body**`referer``sign``deviceId`
/// [type] referrer类型 (af/fb/gg/ios_adjust/android_adjust)
/// [app] (iOS: HIOS / Android: HAndroid)
static Future<EntityResponse<FastLoginResponse>> fastLogin({ static Future<EntityResponse<FastLoginResponse>> fastLogin({
required String deviceId, required String deviceId,
required String sign, required String sign,
required String app,
String? referer, String? referer,
String? ch, String? ch,
String? type, String? type,
String? app,
}) async { }) async {
final config = ApiClient.instance.config; final config = ApiClient.instance.config;
return _client.requestEntity( return _client.requestEntity(
@ -28,20 +32,25 @@ abstract final class UserApi {
method: 'POST', method: 'POST',
entityFactory: FastLoginResponse.fromJson, entityFactory: FastLoginResponse.fromJson,
queryParams: { queryParams: {
if (ch != null) 'ch': ch, if (ch != null && ch.isNotEmpty) 'ch': ch,
'pkg': config.packageName, 'pkg': config.packageName,
if (type != null) 'type': type, 'type': type ?? 'fb',
if (app != null) 'app': app, 'app': app,
}, },
body: { body: {
'referer': referer ?? '', 'referer': referer ?? '',
'sign': sign, 'sign': sign,
'deviceId': deviceId, 'deviceId': deviceId,
}, },
includeUserTokenInHeader: false,
); );
} }
/// ///
///
/// ****`pkg``User_token`
/// **Query**`app``userId``type` `fb``pkg`
/// **Body**`referer``deviceId`
static Future<ApiResponse> referrer({ static Future<ApiResponse> referrer({
required String app, required String app,
required String userId, required String userId,
@ -56,7 +65,7 @@ abstract final class UserApi {
queryParams: { queryParams: {
'app': app, 'app': app,
'userId': userId, 'userId': userId,
if (type != null) 'type': type, 'type': type ?? 'fb',
'pkg': pkg ?? ApiClient.instance.config.packageName, 'pkg': pkg ?? ApiClient.instance.config.packageName,
}, },
body: { body: {
@ -67,15 +76,20 @@ abstract final class UserApi {
} }
/// ///
///
/// query [AppConfig.fieldMapping]
/// - [app] iOS `HIOS` / Android `HAndroid` fast_login
/// - [pkg]
/// - [client][userId][ch][inviteBy][deviceId][clientId]
static Future<EntityResponse<CommonInfoResponse>> getCommonInfo({ static Future<EntityResponse<CommonInfoResponse>> getCommonInfo({
required String app, required String app,
String? shield, required String pkg,
String? client,
String? userId, String? userId,
String? ch, String? ch,
String? item, String? inviteBy,
String? deviceId, String? deviceId,
String? gauntlet, String? clientId,
String? pkg,
}) async { }) async {
return _client.requestEntity( return _client.requestEntity(
path: '/v1/user/common_info', path: '/v1/user/common_info',
@ -83,13 +97,29 @@ abstract final class UserApi {
entityFactory: CommonInfoResponse.fromJson, entityFactory: CommonInfoResponse.fromJson,
queryParams: { queryParams: {
'app': app, 'app': app,
if (shield != null) 'shield': shield, 'pkg': pkg,
if (userId != null) 'userId': userId, if (client != null && client.isNotEmpty) 'client': client,
if (ch != null) 'ch': ch, if (userId != null && userId.isNotEmpty) 'userId': userId,
if (item != null) 'item': item, if (ch != null && ch.isNotEmpty) 'ch': ch,
if (deviceId != null) 'deviceId': deviceId, if (inviteBy != null && inviteBy.isNotEmpty) 'inviteBy': inviteBy,
if (gauntlet != null) 'gauntlet': gauntlet, if (deviceId != null && deviceId.isNotEmpty) 'deviceId': deviceId,
if (pkg != null) 'pkg': pkg, if (clientId != null && clientId.isNotEmpty) 'clientId': clientId,
},
);
}
/// App
static Future<EntityResponse<AppLanguageConfigResponse>> getAppLanguage({
required String pkg,
String? lang,
}) async {
return _client.requestEntity(
path: '/v1/config/app-language',
method: 'GET',
entityFactory: AppLanguageConfigResponse.fromJson,
queryParams: {
'pkg': pkg,
if (lang != null && lang.isNotEmpty) 'lang': lang,
}, },
); );
} }
@ -110,6 +140,68 @@ abstract final class UserApi {
); );
} }
/// `GET /v1/user/credits-page`
static Future<EntityResponse<CreditsPageInfoResponse>> getCreditsPage({
String page = '1',
String size = '10',
String type = '1',
}) async {
return _client.requestEntity(
path: '/v1/user/credits-page',
method: 'GET',
entityFactory: CreditsPageInfoResponse.fromJson,
queryParams: {
'page': page,
'size': size,
'type': type,
},
);
}
/// `GET /v1/user/payments`data
static Future<EntityResponse<UserPaymentsListResponse>> getUserPayments({
required String app,
String? userId,
}) async {
final response = await _client.request(
path: '/v1/user/payments',
method: 'GET',
queryParams: {
'app': app,
if (userId != null && userId.isNotEmpty) 'userId': userId,
},
);
if (response.isSuccess && response.data is List) {
return EntityResponse<UserPaymentsListResponse>(
code: response.code,
msg: response.msg,
data: UserPaymentsListResponse.fromDataList(
response.data! as List<dynamic>,
),
);
}
return EntityResponse<UserPaymentsListResponse>(
code: response.code,
msg: response.msg,
data: null,
);
}
/// `types`
static Future<EntityResponse<UnreadMessageCountResponse>>
getUnreadMessageCount({
String? types,
}) async {
return _client.requestEntity(
path: '/v1/user/unread-message-count',
method: 'GET',
entityFactory: UnreadMessageCountResponse.fromJson,
queryParams: {
if (types != null && types.isNotEmpty) 'types': types,
},
);
}
/// ///
static Future<ApiResponse> deleteAccount({ static Future<ApiResponse> deleteAccount({
required String app, required String app,