15 KiB
15 KiB
Client Proxy Framework 使用指南
1. 框架概述
client_proxy_framework 是一个通用代理 API 框架,用于 Flutter 移动应用与后端 API 的通信。框架已封装好请求/响应的加密解密、字段映射等逻辑,换皮应用只需配置少量参数即可使用。
核心特性
- 自动加解密:请求体和响应体自动进行 AES 加密/解密
- 字段映射:框架自动将原始字段名转换为 V2 字段名,响应自动转换回来
- 强类型实体:返回强类型实体类,开发者直接使用映射后的字段
- 统一响应:
EntityResponse<T>提供强类型返回值
2. 快速开始
2.1 添加依赖
在 pubspec.yaml 中添加:
dependencies:
client_proxy_framework:
path: ../client_proxy_framework
2.2 实现配置
创建一个类继承 AppConfig:
import 'package:client_proxy_framework/client_proxy_framework.dart';
class MyAppConfig extends AppConfig {
@override
String get appId => 'YourAppId';
@override
String get packageName => 'com.yourapp.package';
@override
String get aesKey => 'your-16-char-key';
@override
String get preBaseUrl => 'https://pre-api.example.com';
@override
String get prodBaseUrl => 'https://api.example.com';
@override
String get proxyPath => '/quester/defender/summoner';
}
2.3 初始化
在 main.dart 中初始化:
void main() {
ApiClient.init(MyAppConfig());
runApp(const MyApp());
}
3. 设计理念
3.1 请求流程
调用层 (原始字段)
↓
ProxyClient.request()
↓
字段映射 (原始 → V2)
↓
AES 加密
↓
发送请求
3.2 响应流程
接收响应
↓
AES 解密
↓
字段映射 (V2 → 原始)
↓
转换为实体类
↓
调用层 (实体类)
4. 配置项详解
AppConfig 配置
| 配置项 | 必填 | 说明 |
|---|---|---|
appId |
是 | 应用标识,对应代理请求的 hero_class |
packageName |
是 | 应用包名,如 com.example.app |
aesKey |
是 | AES 加密密钥,长度需为 16 字符 |
preBaseUrl |
是 | 预发环境域名 |
prodBaseUrl |
是 | 生产环境域名 |
proxyPath |
是 | 代理入口路径 |
debugBaseUrlOverride |
否 | 调试时本地代理地址 |
fieldMapping |
否 | 字段映射表,默认使用 petsHeroAIFieldMapping |
5. API 服务
所有 API 方法使用原始字段名,返回强类型实体。
5.1 UserApi - 用户相关
5.1.1 fastLogin - 设备快速登录
final res = await UserApi.fastLogin(
deviceId: '设备ID',
sign: 'MD5(deviceId)大写',
referer: '归因来源', // 可选
ch: '渠道号', // 可选
type: '类型', // 可选
);
if (res.isSuccess) {
final loginInfo = res.data!;
final token = loginInfo.userToken;
final credits = loginInfo.credits;
final userId = loginInfo.userId;
}
返回实体: FastLoginResponse
userToken: 用户 TokenuserId: 用户 IDcredits: 积分avatar: 头像userName: 用户名countryCode: 国家码isVip: 是否 VIP- 等等...
5.1.2 getCommonInfo - 获取用户通用信息
final res = await UserApi.getCommonInfo(
app: '应用ID',
userId: '用户ID', // 可选
);
if (res.isSuccess) {
final info = res.data!;
}
返回实体: CommonInfoResponse
5.1.3 getAccount - 获取账户信息
final res = await UserApi.getAccount(
app: '应用ID',
userId: '用户ID', // 可选
);
if (res.isSuccess) {
final account = res.data!;
final credits = account.credits;
final isVip = account.isVip;
}
返回实体: AccountResponse
credits: 积分avatar: 头像userName: 用户名isVip: 是否 VIPfreeTimes: 免费次数
5.2 PaymentApi - 支付相关
5.2.1 getGooglePayActivities - 获取 Android 商品列表
final res = await PaymentApi.getGooglePayActivities(
app: '应用ID', // 可选
country: '国家', // 可选
);
if (res.isSuccess) {
final products = res.data!.productList;
for (final product in products ?? []) {
final id = product.productId;
final price = product.actualAmount;
final bonus = product.bonus;
}
}
返回实体: PaymentProductsResponse
productList: 商品列表productId: 商品 IDactivityId: 活动 IDactualAmount: 实际金额originAmount: 原价bonus: 赠送积分title: 标题
5.2.2 getPaymentMethods - 获取支付方式列表
final res = await PaymentApi.getPaymentMethods(
activityId: '活动ID',
country: '国家', // 可选
);
if (res.isSuccess) {
final methods = res.data!.paymentMethods;
for (final method in methods ?? []) {
final pm = method.paymentMethod;
final name = method.name;
final isRecommend = method.recommend;
}
}
返回实体: PaymentMethodsResponse
paymentMethods: 支付方式列表paymentMethod: 支付方式subPaymentMethod: 子支付方式name: 显示名称icon: 图标recommend: 是否推荐
5.2.3 createPayment - 创建支付订单
final res = await PaymentApi.createPayment(
app: '应用ID',
userId: '用户ID',
activityId: '活动ID',
paymentMethod: '支付方式',
paymentType: '支付子类型', // 可选
);
if (res.isSuccess) {
final order = res.data!;
final orderId = order.orderId;
final payUrl = order.payUrl;
}
返回实体: CreatePaymentResponse
orderId: 订单 IDpayUrl: 支付链接status: 状态
5.2.4 getOrderDetail - 获取订单详情
final res = await PaymentApi.getOrderDetail(
userId: '用户ID',
orderId: '订单ID',
);
if (res.isSuccess) {
final order = res.data!;
final status = order.status;
}
返回实体: OrderDetailResponse
orderId: 订单 IDstatus: 状态amount: 金额
5.2.5 googlepay - Google Pay 回调
final res = await PaymentApi.googlepay(
signature: '购买签名',
purchaseData: '购买数据',
orderId: '订单ID',
userId: '用户ID',
);
if (res.isSuccess) {
final result = res.data!;
final status = result.status;
}
返回实体: GooglePayCallbackResponse
orderId: 订单 IDstatus: 状态creditsAdded: 是否已加积分
5.3 ImageApi - 图片/视频相关
5.3.1 getCategoryList - 获取分类列表
final res = await ImageApi.getCategoryList();
if (res.isSuccess) {
final categories = res.data!.categories;
}
返回实体: CategoryListResponse
categories: 分类列表id: IDname: 名称icon: 图标
5.3.2 getImg2VideoTasks - 获取任务列表
final res = await ImageApi.getImg2VideoTasks(
categoryId: 123, // 可选
);
if (res.isSuccess) {
final tasks = res.data!.tasks;
}
返回实体: TasksResponse
5.3.3 getProgress - 查询任务进度
final res = await ImageApi.getProgress(
app: '应用ID',
taskId: '任务ID',
userId: '用户ID', // 可选
);
if (res.isSuccess) {
final progress = res.data!;
final status = progress.status;
final resultUrl = progress.resultUrl;
}
返回实体: ProgressResponse
taskId: 任务 IDstatus: 状态progress: 进度 (0-100)resultUrl: 结果 URL
5.3.4 createTask - 创建任务
final res = await ImageApi.createTask(
userId: '用户ID',
prompt: '提示词', // 可选
resolution: '1024x1024', // 可选
imgUrl: '图片URL', // 可选
allowance: false, // 可选
);
if (res.isSuccess) {
final taskId = res.data!.taskId;
}
返回实体: CreateTaskResponse
taskId: 任务 IDstatus: 状态
5.3.5 getMyTasks - 获取我的任务列表
final res = await ImageApi.getMyTasks(
app: '应用ID',
page: '1', // 可选
pageSize: '10', // 可选
cursor: '游标', // 可选
);
if (res.isSuccess) {
final tasks = res.data!.tasks;
final total = res.data!.total;
}
返回实体: MyTasksResponse
tasks: 任务列表total: 总数cursor: 游标
5.3.6 getCreditsPageInfo - 获取积分页面信息
final res = await ImageApi.getCreditsPageInfo(
app: '应用ID',
userId: '用户ID', // 可选
ch: '渠道', // 可选
);
if (res.isSuccess) {
final info = res.data!;
final credits = info.credits;
final freeTimes = info.freeTimes;
final isVip = info.isVip;
}
返回实体: CreditsPageInfoResponse
credits: 积分freeTimes: 免费次数isVip: 是否 VIPvipExpireTime: VIP 过期时间
5.4 FeedbackApi - 举报/反馈相关
5.4.1 getUploadPresignedUrl - 获取上传预签名 URL
final res = await FeedbackApi.getUploadPresignedUrl(
fileName: 'image.jpg',
);
if (res.isSuccess) {
final result = res.data!;
final uploadUrl = result.uploadUrl;
final filePath = result.filePath;
}
返回实体: FeedbackUploadPresignedUrlResponse
uploadUrl: 上传 URLfilePath: 文件路径
5.4.2 submit - 提交反馈
final res = await FeedbackApi.submit(
fileUrls: ['https://...'],
content: '反馈内容',
contentType: 'text/plain',
);
if (res.isSuccess) {
final success = res.data!.success;
}
返回实体: SubmitFeedbackResponse
success: 是否成功feedbackId: 反馈 ID
6. 响应处理
6.1 EntityResponse
所有返回实体类的方法都使用 EntityResponse<T>:
final res = await UserApi.fastLogin(...);
// 检查成功
if (res.isSuccess) {
// 访问实体
final data = res.data!;
final token = data.userToken;
} else {
// 处理错误
print('Error: ${res.msg}');
}
EntityResponse 属性
| 属性 | 类型 | 说明 |
|---|---|---|
code |
int | 响应码,0 表示成功 |
msg |
String | 响应消息 |
data |
T? | 实体数据 |
isSuccess |
bool | 便捷属性,code == 0 时为 true |
7. 设置用户 Token
登录成功后,调用以下方法设置用户 Token:
// 登录成功后
final res = await UserApi.fastLogin(...);
if (res.isSuccess) {
ApiClient.instance.setUserToken(res.data!.userToken);
}
// 登出时
ApiClient.instance.setUserToken(null);
8. 调试模式
框架会自动根据 kDebugMode 选择环境:
- 调试模式:使用
preBaseUrl(或debugBaseUrlOverride) - 发布模式:使用
prodBaseUrl
9. 字段映射
框架自动处理字段映射,调用层使用原始字段名。
请求字段映射(原始 → V2)
| 原始字段 | V2 字段 |
|---|---|
| app | sentinel |
| userId | asset |
| deviceId | origin |
| sign | resolution |
| referer | digest |
| activityId | warrior |
| country | vambrace |
| paymentMethod | resource |
| paymentType | ceremony |
| orderId | federation |
| signature | sample |
| purchaseData | merchant |
| taskId | tree |
| prompt | ledger |
| resolution | guild |
| srcImgUrls | commission |
| fileName1 | gateway |
| contentType | pauldron |
| expectedSize | stronghold |
响应字段映射(V2 → 原始)
| V2 字段 | 原始字段 |
|---|---|
| helm | code/响应码 |
| rampart | msg |
| sidekick | data |
| summon | productList |
| renew | paymentMethods |
| reveal | credits |
| reevaluate | userToken |
10. 代码示例
完整登录流程
import 'package:client_proxy_framework/client_proxy_framework.dart';
class AuthService {
static Future<bool> login() async {
final deviceId = await getDeviceId();
final sign = md5(deviceId).toUpperCase();
final res = await UserApi.fastLogin(
deviceId: deviceId,
sign: sign,
referer: 'organic',
);
if (res.isSuccess) {
final loginInfo = res.data!;
ApiClient.instance.setUserToken(loginInfo.userToken!);
UserState.setUserId(loginInfo.userId!);
UserState.setCredits(loginInfo.credits ?? 0);
return true;
}
return false;
}
}
完整支付流程
class PaymentService {
// 1. 获取商品列表
static Future<List<PaymentProductItem>> getProducts() async {
final res = await PaymentApi.getGooglePayActivities();
return res.data?.productList ?? [];
}
// 2. 获取支付方式
static Future<List<PaymentMethodItem>> getPaymentMethods(String activityId) async {
final res = await PaymentApi.getPaymentMethods(activityId: activityId);
return res.data?.paymentMethods ?? [];
}
// 3. 创建订单
static Future<String?> createOrder({
required String userId,
required String activityId,
required String paymentMethod,
}) async {
final res = await PaymentApi.createPayment(
app: ApiClient.instance.config.appId,
userId: userId,
activityId: activityId,
paymentMethod: paymentMethod,
);
if (res.isSuccess) {
return res.data?.orderId;
}
return null;
}
// 4. Google Pay 回调
static Future<bool> verifyGooglePay({
required String signature,
required String purchaseData,
required String orderId,
required String userId,
}) async {
final res = await PaymentApi.googlepay(
signature: signature,
purchaseData: purchaseData,
orderId: orderId,
userId: userId,
);
return res.isSuccess;
}
}
11. 常见问题
Q: 如何修改字段映射?
A: 覆盖 AppConfig.fieldMapping:
@override
FieldMapping get fieldMapping => const FieldMapping({
'deviceId': 'origin',
'userId': 'asset',
// ... 其他字段
});
Q: 响应 data 为空怎么办?
A: 检查以下几点:
ApiClient.init()是否已调用- 网络是否正常
appId、aesKey等配置是否正确
12. 文件结构
lib/
├── client_proxy_framework.dart # 入口文件
└── src/
├── api/
│ ├── api_client.dart # 全局客户端
│ ├── api_crypto.dart # 加解密工具
│ ├── api_response.dart # 响应对象
│ └── proxy_client.dart # 代理请求客户端(含实体转换)
├── config/
│ ├── app_config.dart # 应用配置抽象类
│ ├── default_field_mapping.dart # 默认字段映射
│ └── field_mapping.dart # 字段映射类
├── entities/
│ ├── entity.dart # 实体基类
│ ├── user_entities.dart # 用户相关实体
│ ├── payment_entities.dart # 支付相关实体
│ ├── image_entities.dart # 图片/视频实体
│ └── feedback_entities.dart # 反馈实体
├── log/
│ └── app_logger.dart # 日志工具
└── services/
├── user_api.dart # 用户 API
├── payment_api.dart # 支付 API
├── image_api.dart # 图片/视频 API
└── feedback_api.dart # 反馈 API