12 KiB
12 KiB
礼物打赏模块
模块概述
礼物打赏模块负责处理直播间内的虚拟礼物赠送功能,包括礼物列表、用户余额、礼物赠送、充值等功能。
相关文件
RoomDetailActivity.java- 直播间详情(礼物赠送)Gift.java- 礼物模型GiftAdapter.java- 礼物列表适配器GiftResponse.java- 礼物响应模型SendGiftRequest.java- 赠送礼物请求模型SendGiftResponse.java- 赠送礼物响应模型UserBalanceResponse.java- 用户余额响应模型RechargeOption.java- 充值选项模型RechargeAdapter.java- 充值选项适配器
接口列表
1. 获取礼物列表
接口地址: GET /api/front/gift/list
请求参数: 无
返回数据:
{
"code": 200,
"msg": "success",
"data": [
{
"id": "integer", // 礼物ID
"name": "string", // 礼物名称
"price": "integer", // 礼物价格(金币)
"icon": "string", // 礼物图标URL
"level": "integer", // 礼物等级(1-5)
"description": "string", // 礼物描述
"animation": "string", // 动画效果URL
"sort": "integer" // 排序
}
]
}
2. 获取用户余额
接口地址: GET /api/front/gift/balance
请求参数: 无
返回数据 (UserBalanceResponse):
{
"code": 200,
"msg": "success",
"data": {
"userId": "integer", // 用户ID
"coinBalance": "integer", // 金币余额
"totalRecharge": "integer",// 累计充值金币
"totalConsume": "integer", // 累计消费金币
"vipLevel": "integer" // VIP等级
}
}
3. 赠送礼物
接口地址: POST /api/front/gift/send
请求参数 (SendGiftRequest):
{
"giftId": "integer", // 礼物ID(必填)
"receiverId": "integer", // 接收者ID(必填)
"roomId": "string", // 直播间ID(必填)
"count": "integer", // 赠送数量(必填)
"message": "string" // 附加消息(可选)
}
返回数据 (SendGiftResponse):
{
"code": 200,
"msg": "赠送成功",
"data": {
"giftRecordId": "long", // 礼物记录ID
"giftId": "integer", // 礼物ID
"giftName": "string", // 礼物名称
"count": "integer", // 赠送数量
"totalPrice": "integer", // 总价格
"newBalance": "integer", // 赠送后的余额
"sendTime": "long" // 赠送时间戳
}
}
4. 获取充值选项
接口地址: GET /api/front/gift/recharge/options
请求参数: 无
返回数据:
{
"code": 200,
"msg": "success",
"data": [
{
"id": "string", // 选项ID
"coinAmount": "integer", // 金币数量
"price": "number", // 价格(元)
"discountLabel": "string",// 优惠标签(可选)
"isHot": "boolean", // 是否热门
"sort": "integer" // 排序
}
]
}
5. 创建充值订单
接口地址: POST /api/front/gift/recharge/create
请求参数 (CreateRechargeRequest):
{
"optionId": "string", // 充值选项ID(必填)
"coinAmount": "integer", // 金币数量(必填)
"price": "number" // 价格(必填)
}
返回数据 (CreateRechargeResponse):
{
"code": 200,
"msg": "订单创建成功",
"data": {
"orderId": "string", // 订单ID
"orderNo": "string", // 订单号
"coinAmount": "integer", // 金币数量
"price": "number", // 价格
"paymentUrl": "string", // 支付URL
"createTime": "long" // 创建时间
}
}
功能说明
礼物等级
| 等级 | 价格范围 | 说明 |
|---|---|---|
| 1 | 1-50金币 | 普通礼物 |
| 2 | 51-100金币 | 精美礼物 |
| 3 | 101-500金币 | 豪华礼物 |
| 4 | 501-1000金币 | 贵族礼物 |
| 5 | 1000+金币 | 至尊礼物 |
赠送流程
- 用户点击礼物按钮
- 显示礼物列表和当前余额
- 选择礼物和数量
- 检查余额是否足够
- 调用赠送接口
- 扣除金币,更新余额
- 在直播间显示礼物动画
- 通过WebSocket推送给其他观众
充值流程
- 用户点击充值按钮
- 显示充值选项列表
- 选择充值金额
- 创建充值订单
- 选择支付方式(支付宝/微信)
- 调用支付接口
- 支付成功后更新余额
使用场景
1. 加载礼物列表
private void loadGiftsFromBackend() {
ApiService apiService = ApiClient.getService(getApplicationContext());
Call<ApiResponse<List<GiftResponse>>> call = apiService.getGiftList();
call.enqueue(new Callback<ApiResponse<List<GiftResponse>>>() {
@Override
public void onResponse(Call<ApiResponse<List<GiftResponse>>> call,
Response<ApiResponse<List<GiftResponse>>> response) {
if (response.isSuccessful() && response.body() != null) {
ApiResponse<List<GiftResponse>> apiResponse = response.body();
if (apiResponse.getCode() == 200 && apiResponse.getData() != null) {
availableGifts = new ArrayList<>();
for (GiftResponse giftResponse : apiResponse.getData()) {
Gift gift = new Gift(
String.valueOf(giftResponse.getId()),
giftResponse.getName(),
giftResponse.getPrice().intValue(),
R.drawable.ic_gift_rose,
giftResponse.getLevel() != null ? giftResponse.getLevel() : 1
);
availableGifts.add(gift);
}
}
}
}
@Override
public void onFailure(Call<ApiResponse<List<GiftResponse>>> call, Throwable t) {
Log.e("Gift", "加载礼物列表失败: " + t.getMessage());
}
});
}
2. 获取用户余额
private void loadUserBalance(TextView coinBalanceView) {
ApiService apiService = ApiClient.getService(getApplicationContext());
Call<ApiResponse<UserBalanceResponse>> call = apiService.getUserBalance();
call.enqueue(new Callback<ApiResponse<UserBalanceResponse>>() {
@Override
public void onResponse(Call<ApiResponse<UserBalanceResponse>> call,
Response<ApiResponse<UserBalanceResponse>> response) {
if (response.isSuccessful() && response.body() != null) {
ApiResponse<UserBalanceResponse> apiResponse = response.body();
if (apiResponse.getCode() == 200 && apiResponse.getData() != null) {
userCoinBalance = apiResponse.getData().getCoinBalance().intValue();
coinBalanceView.setText(String.valueOf(userCoinBalance));
}
}
}
@Override
public void onFailure(Call<ApiResponse<UserBalanceResponse>> call, Throwable t) {
Log.e("Gift", "获取余额失败: " + t.getMessage());
}
});
}
3. 赠送礼物
private void sendGiftToBackend(Gift selectedGift, int count, int totalPrice) {
// 检查余额
if (userCoinBalance < totalPrice) {
Toast.makeText(this, "金币不足,请先充值", Toast.LENGTH_SHORT).show();
showRechargeDialog();
return;
}
ApiService apiService = ApiClient.getService(getApplicationContext());
SendGiftRequest request = new SendGiftRequest();
request.setGiftId(Integer.parseInt(selectedGift.getId()));
request.setReceiverId(room.getStreamerId());
request.setRoomId(roomId);
request.setCount(count);
Call<ApiResponse<SendGiftResponse>> call = apiService.sendGift(request);
call.enqueue(new Callback<ApiResponse<SendGiftResponse>>() {
@Override
public void onResponse(Call<ApiResponse<SendGiftResponse>> call,
Response<ApiResponse<SendGiftResponse>> response) {
if (response.isSuccessful() && response.body() != null) {
ApiResponse<SendGiftResponse> apiResponse = response.body();
if (apiResponse.getCode() == 200 && apiResponse.getData() != null) {
SendGiftResponse giftResponse = apiResponse.getData();
// 更新余额
userCoinBalance = giftResponse.getNewBalance().intValue();
// 显示赠送消息
String giftMessage = String.format("送出了 %d 个 %s",
count, selectedGift.getName());
addChatMessage(new ChatMessage("我", giftMessage, true));
Toast.makeText(RoomDetailActivity.this,
"赠送成功!", Toast.LENGTH_SHORT).show();
}
}
}
@Override
public void onFailure(Call<ApiResponse<SendGiftResponse>> call, Throwable t) {
Toast.makeText(RoomDetailActivity.this,
"网络错误: " + t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
4. 创建充值订单
private void createRechargeOrder(RechargeOption selectedOption) {
ApiService apiService = ApiClient.getService(getApplicationContext());
CreateRechargeRequest request = new CreateRechargeRequest();
request.setOptionId(selectedOption.getId());
request.setCoinAmount(selectedOption.getCoinAmount());
request.setPrice(selectedOption.getPrice());
Call<ApiResponse<CreateRechargeResponse>> call =
apiService.createRecharge(request);
call.enqueue(new Callback<ApiResponse<CreateRechargeResponse>>() {
@Override
public void onResponse(Call<ApiResponse<CreateRechargeResponse>> call,
Response<ApiResponse<CreateRechargeResponse>> response) {
if (response.isSuccessful() && response.body() != null) {
ApiResponse<CreateRechargeResponse> apiResponse = response.body();
if (apiResponse.getCode() == 200 && apiResponse.getData() != null) {
CreateRechargeResponse rechargeResponse = apiResponse.getData();
String orderId = rechargeResponse.getOrderId();
// 显示支付选择对话框
showPaymentMethodDialog(orderId, selectedOption);
}
}
}
@Override
public void onFailure(Call<ApiResponse<CreateRechargeResponse>> call, Throwable t) {
Toast.makeText(RoomDetailActivity.this,
"网络错误: " + t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
WebSocket推送
礼物赠送后会通过WebSocket推送给直播间内的所有用户,用于显示礼物动画。
推送消息格式:
{
"type": "gift",
"giftId": 1,
"giftName": "玫瑰",
"count": 10,
"senderId": 123,
"senderNickname": "张三",
"receiverId": 456,
"receiverNickname": "主播",
"roomId": "room123"
}
默认礼物列表
如果接口加载失败,可以使用以下默认礼物:
| ID | 名称 | 价格 | 等级 |
|---|---|---|---|
| 1 | 玫瑰 | 10 | 1 |
| 2 | 爱心 | 20 | 1 |
| 3 | 蛋糕 | 50 | 2 |
| 4 | 星星 | 100 | 2 |
| 5 | 钻石 | 200 | 3 |
| 6 | 皇冠 | 500 | 4 |
| 7 | 跑车 | 1000 | 5 |
| 8 | 火箭 | 2000 | 5 |
注意事项
- 所有接口都需要登录认证
- 赠送礼物前必须检查余额是否足够
- 礼物价格以金币为单位,不是人民币
- 充值需要集成第三方支付SDK(支付宝/微信)
- 礼物动画效果需要前端实现
- 建议缓存礼物列表,减少网络请求
- 余额变化后及时更新UI显示
- 赠送失败时不扣除金币