hyapp-server/docs/flutter对接/金币流水对接.md

4.2 KiB
Raw Permalink Blame History

Flutter 金币流水对接

本文只描述 Flutter App 读取当前登录用户金币流水的接口。金币余额和流水事实由 wallet-service 维护;客户端只展示 gateway 返回的分录投影,不在本地推算余额。

接口

GET /api/v1/wallet/coin-transactions

登录接口,需要 Authorization: Bearer <access_token>。接口固定查询当前登录用户的 COIN 资产流水,不接受客户端传 user_idasset_type

请求头:

Header 必填 说明
Authorization App 登录 access token。
X-App-Code App 编码,默认 lalu

Query

字段 必填 默认 说明
page 1 页码,从 1 开始。
page_size 30 每页数量。首屏不传时返回最近 30 条。

排序固定为 created_at_ms DESC, entry_id DESC,即最新流水在前。分页字段使用通用 page / page_size,不要使用业务专属分页名。

示例:

GET /api/v1/wallet/coin-transactions?page=1&page_size=30
Authorization: Bearer <access_token>
X-App-Code: lalu

成功响应:

{
  "code": "OK",
  "message": "ok",
  "request_id": "req_abc",
  "data": {
    "items": [
      {
        "entry_id": 101,
        "transaction_id": "wtx_abc",
        "biz_type": "coin_seller_transfer",
        "asset_type": "COIN",
        "available_delta": 3000,
        "frozen_delta": 0,
        "available_after": 12800,
        "frozen_after": 0,
        "counterparty_user_id": 90001,
        "room_id": "",
        "created_at_ms": 1710000000000
      }
    ],
    "total": 48,
    "page": 1,
    "page_size": 30
  }
}

字段规则:

字段 说明
available_delta 本次可用金币变化;正数是收入,负数是支出。
available_after 本条流水落账后的可用金币余额,余额展示以该字段为准。
biz_type 业务类型,例如 coin_seller_transfergift_debittask_rewardgame_creditgame_debitgame_refundvip_purchase。客户端可本地映射展示文案。
counterparty_user_id 对手用户长 ID没有对手方时为 0
room_id 房间相关流水的房间 ID非房间流水为空字符串。
created_at_ms Unix epoch milliseconds展示层按用户本地时区格式化。

Flutter 解析示例

class CoinTransactionPage {
  CoinTransactionPage({
    required this.items,
    required this.total,
    required this.page,
    required this.pageSize,
  });

  final List<CoinTransaction> items;
  final int total;
  final int page;
  final int pageSize;

  factory CoinTransactionPage.fromJson(Map<String, dynamic> json) {
    return CoinTransactionPage(
      items: (json['items'] as List<dynamic>? ?? const [])
          .map((item) => CoinTransaction.fromJson(item as Map<String, dynamic>))
          .toList(),
      total: (json['total'] as num?)?.toInt() ?? 0,
      page: (json['page'] as num?)?.toInt() ?? 1,
      pageSize: (json['page_size'] as num?)?.toInt() ?? 30,
    );
  }
}

class CoinTransaction {
  CoinTransaction({
    required this.entryId,
    required this.transactionId,
    required this.bizType,
    required this.availableDelta,
    required this.availableAfter,
    required this.createdAtMs,
  });

  final int entryId;
  final String transactionId;
  final String bizType;
  final int availableDelta;
  final int availableAfter;
  final int createdAtMs;

  bool get isIncome => availableDelta > 0;
  int get amount => availableDelta.abs();

  factory CoinTransaction.fromJson(Map<String, dynamic> json) {
    return CoinTransaction(
      entryId: (json['entry_id'] as num).toInt(),
      transactionId: json['transaction_id'] as String? ?? '',
      bizType: json['biz_type'] as String? ?? '',
      availableDelta: (json['available_delta'] as num?)?.toInt() ?? 0,
      availableAfter: (json['available_after'] as num?)?.toInt() ?? 0,
      createdAtMs: (json['created_at_ms'] as num?)?.toInt() ?? 0,
    );
  }
}

接口调用时,先解析外层 envelope只有 code == "OK" 时读取 data;其他 code 按登录态、参数错误或服务错误处理,并把 request_id 记录到客户端日志。