找回密码
 register
搜索
查看: 57|回复: 0

洱海月 元宝交易市场修改价格漏洞和统一配置文件

[复制链接]
  • 打卡等级:本地老炮
  • 打卡总天数:533
  • 打卡月天数:22
  • 打卡总奖励:530
  • 最近打卡:2026-06-24 01:45:59
Waylee 发表于 2026-4-2 13:04 | 显示全部楼层 |阅读模式 | Google Chrome | Windows 10

修改目标

  • 价格范围不再散落硬编码,统一收进 ConfigInfo.ini
  • 上架、改价、成交到账统一走服务端校验
  • 改价链改成先校验、再扣费、失败回退
  • 售出元宝领取、取回、过期取回补空值防御,避免缓存失效直接炸服务
  • 客户端不改,服务端兜底

修改文件

  • /home/ubuntu/Game2/configs/ConfigInfo.ini
  • /home/ubuntu/Game2/lualib/ybmarket_helper.lua
  • /home/ubuntu/Game2/services/msgagent.lua
  • /home/ubuntu/Game2/services/scene/scenecore.lua
  • /home/ubuntu/Game2/services/ybexchange/ybexchange_core.lua
  • /home/ubuntu/Game2/services/scene/obj/human.lua

1. 配置收口

文件:/home/ubuntu/Game2/configs/ConfigInfo.ini

[YBMarket]                        ;元宝交易市场
MinPrice=2                        ;玩家最低上架价格
MaxPrice=200000                   ;玩家最高上架价格
SellerTaxRatePct=2                ;成交后卖家到账税率百分比
ListingFeeRate=30                 ;上架/改价手续费倍率(价格或差价*倍率)

说明:

  • MinPrice / MaxPrice 控制上架和改价范围
  • SellerTaxRatePct 控制卖家最终到账税率
  • ListingFeeRate 控制上架手续费、涨价补差手续费
  • 手续费规则:首次上架按价格收一次,涨价补差,降价不返还

2. 新增公共 helper

文件:/home/ubuntu/Game2/lualib/ybmarket_helper.lua

***付费内容***

3. 修正扣费函数

文件:/home/ubuntu/Game2/services/scene/obj/human.lua

function human:cost_money_with_priority(cost, reason, extra)
    assert(cost >= 1, cost)
    local money = self:get_money()
    local jiaozi = self:get_jiaozi()
    if money + jiaozi < cost then
        return false, 0, 0
    end
    local cost_jiaozi = 0
    local cost_money = 0
    if jiaozi >= cost then
        local ok = self:set_jiaozi(jiaozi - cost, reason, extra)
        if not ok then
            return false, 0, 0
        end
        cost_jiaozi = cost
    else
        local diff = cost - jiaozi
        local ok_jiaozi = self:set_jiaozi(0, reason, extra)
        if not ok_jiaozi then
            return false, 0, 0
        end
        local ok_money = self:set_money(money - diff, reason, extra)
        if not ok_money then
            self:set_jiaozi(jiaozi, reason, extra)
            return false, 0, 0
        end
        cost_jiaozi = jiaozi
        cost_money = diff
    end
    return true, cost_jiaozi, cost_money
end

4. 上架入口改成统一价格校验

文件:/home/ubuntu/Game2/services/msgagent.lua

function request:CGAuctionSell()
    ...
    local ok, err_msg = ybmarket_helper.validate_price(self.price)
    if not ok then
        ma_func:notify_tips(err_msg)
        return
    end
    ...
    local serial, err_msg = skynet.call(".Ybexchange", "lua", "sell", auction_request)
    if not serial then
        if err_msg then
            ma_func:notify_tips(err_msg)
        end
        return
    end
    ...
end

文件:/home/ubuntu/Game2/services/scene/scenecore.lua

function scenecore:auction_sell_before_check(who, auction_sell)
    local ret_args
    local human = self:get_obj_by_id(who)
    if not human then return end

    local ok, err_msg = ybmarket_helper.validate_price(auction_sell.price)
    if not ok then
        human:notify_tips(err_msg)
        return
    end
    ...
    local money = human:get_money() + human:get_jiaozi()
    local need_cost = ybmarket_helper.calc_listing_fee(auction_sell.price)
    if money < need_cost then
        human:notify_tips("手续费不足,上架失败")
        return
    end
    return table.unpack(ret_args)
end

function scenecore:auction_sell_after_remove(who, auction_sell)
    ...
    human:cost_money_with_priority(ybmarket_helper.calc_listing_fee(auction_sell.price), "交易行寄售上架手续")
    return index
end

文件:/home/ubuntu/Game2/services/ybexchange/ybexchange_core.lua

function ybexchange_core:sell(request)
    ...
    local ok, err_msg = ybmarket_helper.validate_price(request.price)
    if not ok then
        return false, err_msg
    end
    ...
end

5. 改价链重做

规则:

  • 涨价时补差价手续费
  • 降价时不返还手续费
  • 改价失败时,已扣的手续费必须回退

5.1 入口层

文件:/home/ubuntu/Game2/services/msgagent.lua
***付费内容***

5.2 场景层

文件:/home/ubuntu/Game2/services/scene/scenecore.lua

function scenecore:auction_modify_before_check(who, merchadise, new_price)
    local human = self:get_obj_by_id(who)
    if not human then
        return false, "角色不存在"
    end
    if not merchadise then
        return false, "寄售信息已失效,请刷新后重试"
    end
    if merchadise.status ~= "on_sale" then
        return false, "寄售信息已失效,请刷新后重试"
    end

    local ok, err_msg = ybmarket_helper.validate_price(new_price)
    if not ok then
        return false, err_msg
    end

    local diff = new_price - merchadise.price
    if diff <= 0 then
        return true
    end

    local need_cost = ybmarket_helper.calc_listing_fee(diff)
    if not human:check_money_with_priority(need_cost) then
        return false, "手续费不足,改价失败"
    end
    return true
end

function scenecore:auction_modify_after_do(who, old_price, new_price)
    local human = self:get_obj_by_id(who)
    if not human then
        return false, 0, 0
    end
    local diff = new_price - old_price
    if diff <= 0 then
        return true, 0, 0
    end
    return human:cost_money_with_priority(ybmarket_helper.calc_listing_fee(diff), "交易行寄售上架手续")
end

function scenecore:auction_modify_refund_after_fail(who, refund_jiaozi, refund_money)
    local human = self:get_obj_by_id(who)
    if not human then
        return false
    end
    refund_jiaozi = refund_jiaozi or 0
    refund_money = refund_money or 0
    if refund_jiaozi > 0 then
        local ok = human:set_jiaozi(human:get_jiaozi() + refund_jiaozi, "交易行寄售改价手续费回退")
        if not ok then
            return false
        end
    end
    if refund_money > 0 then
        local ok = human:set_money(human:get_money() + refund_money, "交易行寄售改价手续费回退")
        if not ok then
            return false
        end
    end
    return true
end

5.3 数据层

文件:/home/ubuntu/Game2/services/ybexchange/ybexchange_core.lua

function ybexchange_core:modify(merchadise, request)
    if not merchadise then
        return false, "寄售信息已失效,请刷新后重试"
    end
    if not request or request.price == nil then
        return false, "价格参数异常"
    end

    local ok, err_msg = ybmarket_helper.validate_price(request.price)
    if not ok then
        return false, err_msg
    end

    local coll_name = "ybmarket"
    local query_tbl = {seller_guid = merchadise.seller_guid, status = "on_sale"}
    ...
    local ok, err, result = skynet.call(".db", "lua", "safe_update", {
        collection = coll_name,
        selector = query_tbl,
        update = updater,
        upsert = false
    })
    ...
end

6. 领取售出元宝 / 取回 / 过期取回 防崩

6.1 统一处理本地缓存

文件:/home/ubuntu/Game2/services/msgagent.lua

local function get_auction_box_merchadise(auction_type, index, offset)
    if not auction_box_list then
        return nil
    end
    local merchadise_list
    local list_index
    if auction_type == 1 then
        merchadise_list = auction_box_list.pets
        list_index = offset and (index + offset) or (index - 10)
    else
        merchadise_list = auction_box_list.items
        list_index = offset and (index + offset) or index
    end
    if not merchadise_list or not list_index or list_index < 1 then
        return nil, merchadise_list, list_index
    end
    return merchadise_list[list_index], merchadise_list, list_index
end

local function remove_auction_box_merchadise(auction_type, index, offset)
    local merchadise, merchadise_list, list_index = get_auction_box_merchadise(auction_type, index, offset)
    if merchadise_list and list_index and list_index >= 1 and list_index <= #merchadise_list then
        table.remove(merchadise_list, list_index)
    end
    return merchadise
end

6.2 领取售出元宝

文件:/home/ubuntu/Game2/services/msgagent.lua

function request:CGAuctionGetYB()
    if not auction_box_list then
        ma_func:notify_tips("寄售信息已失效,请刷新后重试")
        return
    end
    local merchadise = get_auction_box_merchadise(self.type, self.index)
    if not merchadise then
        ma_func:notify_tips("寄售信息已失效,请刷新后重试")
        return
    end

    local item_name, yuanbao, err_msg = skynet.call(".Ybexchange", "lua", "get_sold_out_yuanbao", merchadise)
    if item_name == nil and yuanbao == nil then
        remove_auction_box_merchadise(self.type, self.index)
        ma_func:notify_tips(err_msg or "寄售信息已失效,请刷新后重试")
        return
    end

    local get_ok, get_err = skynet.call(my_scene, "lua", "auction_get_yb_after_do", my_obj_id, item_name, yuanbao)
    if not get_ok then
        ma_func:notify_tips(get_err or "领取售出元宝失败,请稍后重试")
        return
    end

    remove_auction_box_merchadise(self.type, self.index)
    ...
end

文件:/home/ubuntu/Game2/services/ybexchange/ybexchange_core.lua

local function build_auction_query(merchadise, status)
    if not merchadise or merchadise.seller_guid == nil or merchadise.item == nil then
        return nil, "寄售信息已失效,请刷新后重试"
    end
    ...
    return query_tbl
end

function ybexchange_core:get_sold_out_yuanbao(request)
    local coll_name = "ybmarket"
    local selector = {["_id"] = false}
    local query_tbl, err_msg = build_auction_query(request, "buyed")
    if not query_tbl then
        return nil, nil, err_msg
    end

    local merchadise = skynet.call(".db", "lua", "findOne", {
        collection = coll_name,
        query = query_tbl,
        selector = selector
    })
    if not merchadise then
        return nil, nil, "寄售信息已失效,请刷新后重试"
    end

    local sql = { collection = coll_name, selector = query_tbl, single = true}
    skynet.call(".db", "lua", "delete", sql)

    local price = tonumber(merchadise.price) or 0
    if price < 0 then
        price = 0
    end
    return merchadise.item_name or "商品", price
end

文件:/home/ubuntu/Game2/services/scene/scenecore.lua

function scenecore:auction_get_yb_after_do(who, item_name, yuanbao)
    local obj_me = self:get_obj_by_id(who)
    if not obj_me then
        return false, "角色不存在"
    end
    yuanbao = tonumber(yuanbao) or 0
    if yuanbao < 0 then
        yuanbao = 0
    end
    item_name = item_name or "商品"
    yuanbao = ybmarket_helper.calc_seller_income(yuanbao)
    ...
    obj_me:set_yuanbao(obj_me:get_yuanbao() + yuanbao, "元宝交易市场-出售商品")
    return true
end

6.3 取回 / 过期取回

文件:/home/ubuntu/Game2/services/msgagent.lua

CGAuctionTakeBack()CGAuctionExpireBack() 改成:

  • 先判 auction_box_list
  • 再取缓存项
  • DB 查不到时给提示,不崩
  • 成功或明确失效后,同步删本地缓存

文件:/home/ubuntu/Game2/services/ybexchange/ybexchange_core.lua

function ybexchange_core:take_back(merchadise)
    local coll_name = "ybmarket"
    local selector = {["_id"] = false}
    local query_tbl, err_msg = build_auction_query(merchadise, "on_sale")
    if not query_tbl then
        return nil, err_msg
    end
    merchadise = skynet.call(".db", "lua", "findOne", {
        collection = coll_name,
        query = query_tbl,
        selector = selector
    })
    if not merchadise then
        return nil, "寄售信息已失效,请刷新后重试"
    end
    ...
end

function ybexchange_core:expire_back(merchadise)
    local coll_name = "ybmarket"
    local selector = {["_id"] = false}
    local query_tbl, err_msg = build_auction_query(merchadise, "off")
    if not query_tbl then
        return nil, err_msg
    end
    merchadise = skynet.call(".db", "lua", "findOne", {
        collection = coll_name,
        query = query_tbl,
        selector = selector
    })
    if not merchadise then
        return nil, "寄售信息已失效,请刷新后重试"
    end
    ...
end

文件:/home/ubuntu/Game2/services/scene/scenecore.lua

function scenecore:auction_merchadise_take_back_before_check(who, merchadise)
    local obj_me = self:get_obj_by_id(who)
    if not obj_me then
        return false, "角色不存在"
    end
    if not merchadise or not merchadise.item then
        return false, "寄售信息已失效,请刷新后重试"
    end
    ...
end

7. 当前结果

  • 上架价格、改价价格统一从配置读取
  • 成交到账税率从配置读取
  • 上架/改价手续费从配置读取
  • 改价先校验、再扣费、失败回退
  • 领取售出元宝、取回、过期取回都补了缓存失效和空值防御
  • 客户端不改,服务端为准

实测重点:

  • 上架价格 1200001、正常价格
  • 改价改成 0、负数、超上限、正常价格
  • 改价失败后,交子/金币是否正确回退
  • 降价后不返还手续费是否符合预期
  • 售出后领取元宝,连续点两次是否只提示刷新,不再报错
  • 取回、过期取回连续点两次是否只提示刷新,不再报错
付费看帖
剩余 21% 内容需要支付 66.00 金币 后可完整阅读
支持付费阅读,激励作者创作更好的作品。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?register

×
您需要登录后才可以回帖 登录 | register

本版积分规则

QQ|雪舞知识库 ( 浙ICP备15015590号-1 | 萌ICP备20232229号|浙公网安备33048102000118号 )|天天打卡

GMT+8, 2026-6-24 05:55 , Processed in 0.078741 second(s), 33 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表