4.8 KiB
4.8 KiB
币商列表 Flutter 对接
本文描述 Flutter App 获取当前用户所在区域启用币商列表的接口。币商身份、状态和区域过滤由 user-service 维护;App 只展示 gateway 返回的列表,不传 region_id,也不在本地缓存为跨区域通用数据。
接口
GET /api/v1/wallet/coin-sellers
登录接口,需要 Authorization: Bearer <access_token>。接口按当前登录用户的 users.region_id 查询同区域、状态为 active、资产类型为 COIN_SELLER_COIN 的币商。
请求头:
| Header | 必填 | 说明 |
|---|---|---|
Authorization |
是 | App 登录 access token。 |
X-App-Code |
否 | App 编码,默认 lalu。 |
X-Request-ID |
否 | 客户端链路 ID;服务端也会生成并在响应中返回。 |
Query:无。不要传 region_id、country_id 或 user_id。
示例:
GET /api/v1/wallet/coin-sellers
Authorization: Bearer <access_token>
X-App-Code: lalu
成功响应:
{
"code": "OK",
"message": "ok",
"request_id": "req_abc",
"data": {
"items": [
{
"user_id": "801",
"display_user_id": "900801",
"username": "Seller One",
"avatar": "https://cdn.example/avatar.png",
"country_id": 86,
"country_code": "CN",
"country_name": "China",
"country_display_name": "中国",
"region_id": 30,
"region_code": "east-asia",
"region_name": "East Asia",
"status": "active",
"merchant_asset_type": "COIN_SELLER_COIN",
"updated_at_ms": 1700000001000
}
],
"total": 1
}
}
字段规则:
| 字段 | 说明 |
|---|---|
user_id |
币商用户长 ID,JSON 中按字符串返回,避免 Dart/JS 大整数精度问题。 |
display_user_id |
当前展示短号,可用于转账页展示和输入确认。 |
username |
币商昵称;为空时客户端可展示短号。 |
avatar |
币商头像 URL;为空时展示默认头像。 |
country_id |
币商用户当前国家 ID。 |
country_code |
国家编码,例如 CN。 |
country_name |
英文或标准国家名。 |
country_display_name |
客户端展示优先使用的国家名。 |
region_id |
币商用户当前区域 ID;应与当前用户区域一致。 |
status |
当前只会返回 active。 |
merchant_asset_type |
当前固定为 COIN_SELLER_COIN。 |
updated_at_ms |
币商身份最近更新时间,Unix epoch milliseconds。 |
Flutter 解析示例
class CoinSellerList {
CoinSellerList({
required this.items,
required this.total,
});
final List<CoinSeller> items;
final int total;
factory CoinSellerList.fromJson(Map<String, dynamic> json) {
return CoinSellerList(
items: (json['items'] as List<dynamic>? ?? const [])
.map((item) => CoinSeller.fromJson(item as Map<String, dynamic>))
.toList(),
total: (json['total'] as num?)?.toInt() ?? 0,
);
}
}
class CoinSeller {
CoinSeller({
required this.userId,
required this.displayUserId,
required this.username,
required this.avatar,
required this.countryId,
required this.countryDisplayName,
required this.regionId,
required this.status,
required this.merchantAssetType,
required this.updatedAtMs,
});
final String userId;
final String displayUserId;
final String username;
final String avatar;
final int countryId;
final String countryDisplayName;
final int regionId;
final String status;
final String merchantAssetType;
final int updatedAtMs;
String get title => username.isNotEmpty ? username : displayUserId;
factory CoinSeller.fromJson(Map<String, dynamic> json) {
return CoinSeller(
userId: json['user_id'] as String? ?? '',
displayUserId: json['display_user_id'] as String? ?? '',
username: json['username'] as String? ?? '',
avatar: json['avatar'] as String? ?? '',
countryId: (json['country_id'] as num?)?.toInt() ?? 0,
countryDisplayName: json['country_display_name'] as String? ?? '',
regionId: (json['region_id'] as num?)?.toInt() ?? 0,
status: json['status'] as String? ?? '',
merchantAssetType: json['merchant_asset_type'] as String? ?? '',
updatedAtMs: (json['updated_at_ms'] as num?)?.toInt() ?? 0,
);
}
}
客户端处理
- 先解析外层 envelope,只有
code == "OK"时读取data.items。 - 空列表表示当前区域暂无启用币商;展示空状态,不切换到其他区域。
- 点击币商进入转账或联系流程时,使用
display_user_id做用户可见确认,实际后续接口仍以服务端解析结果为准。 - 用户切换国家或完成资料变更后重新拉取本接口,不复用旧区域列表。
- 请求失败时记录
request_id,按登录失效、参数错误、服务错误分别处理。