diff --git a/doc/InGameMall.py b/doc/InGameMall.py index 237c52a6..68f8ab9b 100644 --- a/doc/InGameMall.py +++ b/doc/InGameMall.py @@ -18,6 +18,8 @@ class InGameMall(object): ['order_method', 0, '排序方式 0:默认排序(当前指向1) 1:上架时间 2:价格'], ['order_asc', 0, '排序方向, 0:从小到大 1:从大到小'], ['price_filter', '', '价格过滤(用|分割)'], + ['type_filter', '', '类型过滤 1:英雄 2:芯片 3:碎片 4:宝箱'], + ['item_filter', '', 'itemId过滤'], ], 'response': [ _common.RspHead(), @@ -32,7 +34,8 @@ class InGameMall(object): 'url': 'webapp/index.php?c=InGameMall&a=sell', 'params': [ _common.ReqHead(), - ['item_id', '', '道具id'], + ['goods_uniid', '', '道具id'], + ['item_id', '', '道具itemId'], ['amount', '', '出售数量'], ['price', '', '出售价格'], ], diff --git a/doc/_common.py b/doc/_common.py index 23ee61f3..c4da1c12 100644 --- a/doc/_common.py +++ b/doc/_common.py @@ -1362,14 +1362,12 @@ class InGameMallGoods(object): self.fields = [ ['seller', '', '出售方账号'], ['seller_address', '', '出售方钱包地址'], + ['goods_uniid', '', '商品唯一id'], ['item_id', '', '商品道具id'], ['item_num', '', '道具数量'], - ['currency', '', "选用币种 目前只支持CEG USDC USDT"], ['price', '', '出售价格'], - ['selltime', 0, '上架时间'], - ['updatetime', 0, '修改时间(更新价格等)'], - ['cancel_countdown', 0, '可下架时间倒计时:-1不可下架'], - ['modify_countdown', 0, '可修改价格倒计时:-1不可修改价格'], + ['createtime', 0, '上架时间'], + ['last_modify_price_time', 0, '修改时间(更新价格等)'], ] class ComputingPowerCurr(object): diff --git a/sql/gamedb.sql b/sql/gamedb.sql index 0fbc6bdf..594c26bf 100644 --- a/sql/gamedb.sql +++ b/sql/gamedb.sql @@ -1419,7 +1419,7 @@ CREATE TABLE `t_mall` ( UNIQUE KEY `goods_uuid` (`goods_uuid`) ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; /*!40101 SET character_set_client = @saved_cs_client */; - + -- -- Table structure for table `t_ingame_mall` -- @@ -1430,17 +1430,17 @@ DROP TABLE IF EXISTS `t_ingame_mall`; CREATE TABLE `t_ingame_mall` ( `idx` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `order_id` varchar(255) NOT NULL DEFAULT '' COMMENT '订单id', + `order_type` int(11) NOT NULL DEFAULT '0' COMMENT '1:英雄 2:芯片 3:碎片 4:宝箱', `seller` varchar(60) NOT NULL DEFAULT '' COMMENT 'seller', `seller_address` varchar(60) NOT NULL DEFAULT '' COMMENT 'seller_address', - `item_id` int(11) NOT NULL DEFAULT '0' COMMENT '物品id', + `goods_uniid` varchar(50) NOT NULL DEFAULT '0' COMMENT '物品id', + `item_id` int(11) NOT NULL DEFAULT '0' COMMENT '物品itemId', `item_num` bigint NOT NULL DEFAULT '0' COMMENT '物品数量', `price` bigint NOT NULL DEFAULT '0' COMMENT '价格', `status` int(11) NOT NULL DEFAULT '0' COMMENT 'status', - `last_buy_time` int(11) NOT NULL DEFAULT '0' COMMENT '最后一次购买时间', - `last_buyer` varchar(60) NOT NULL DEFAULT '' COMMENT '最后一次购买者', - `last_modify_price_time` int(11) NOT NULL DEFAULT '0' COMMENT '最后一次修改价格事件', `buyer` varchar(60) NOT NULL DEFAULT '' COMMENT '购买成功者', `buy_ok_time` int(11) NOT NULL DEFAULT '0' COMMENT '购买成功时间', + `last_modify_price_time` int(11) NOT NULL DEFAULT '0' COMMENT '最后一次修改价格事件', `createtime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间', `modifytime` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间', PRIMARY KEY (`idx`), @@ -1450,7 +1450,7 @@ CREATE TABLE `t_ingame_mall` ( UNIQUE KEY `order_id` (`order_id`) ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; /*!40101 SET character_set_client = @saved_cs_client */; - + -- -- Table structure for table `t_market` @@ -1801,4 +1801,4 @@ CREATE TABLE `t_global_data` ( `modifytime` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间', PRIMARY KEY (`idx`), UNIQUE KEY `name` (`name`) -) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; +) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; diff --git a/sql/gamedb2006_migrate_240305_01.sql b/sql/gamedb2006_migrate_240305_01.sql index 07002226..4021de76 100644 --- a/sql/gamedb2006_migrate_240305_01.sql +++ b/sql/gamedb2006_migrate_240305_01.sql @@ -11,6 +11,30 @@ alter table t_hero drop column base_attr; alter table t_chip add column `wealth_attr` mediumblob COMMENT '财富值属性'; +CREATE TABLE `t_ingame_mall` ( + `idx` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', + `order_id` varchar(255) NOT NULL DEFAULT '' COMMENT '订单id', + `order_type` int(11) NOT NULL DEFAULT '0' COMMENT '1:英雄 2:芯片 3:碎片 4:宝箱', + `seller` varchar(60) NOT NULL DEFAULT '' COMMENT 'seller', + `seller_address` varchar(60) NOT NULL DEFAULT '' COMMENT 'seller_address', + `goods_uniid` varchar(50) NOT NULL DEFAULT '0' COMMENT '物品id', + `item_id` int(11) NOT NULL DEFAULT '0' COMMENT '物品itemId', + `item_num` bigint NOT NULL DEFAULT '0' COMMENT '物品数量', + `price` bigint NOT NULL DEFAULT '0' COMMENT '价格', + `status` int(11) NOT NULL DEFAULT '0' COMMENT 'status', + `buyer` varchar(60) NOT NULL DEFAULT '' COMMENT '购买成功者', + `buy_ok_time` int(11) NOT NULL DEFAULT '0' COMMENT '购买成功时间', + `last_modify_price_time` int(11) NOT NULL DEFAULT '0' COMMENT '最后一次修改价格事件', + `createtime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间', + `modifytime` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间', + PRIMARY KEY (`idx`), + KEY `seller` (`seller`), + KEY `seller_address` (`seller_address`), + KEY `price` (`price`), + UNIQUE KEY `order_id` (`order_id`) +) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + + insert into version (version) values(2024030501); commit; diff --git a/webapp/controller/BaseAuthedController.class.php b/webapp/controller/BaseAuthedController.class.php index 2879da8e..872d6934 100644 --- a/webapp/controller/BaseAuthedController.class.php +++ b/webapp/controller/BaseAuthedController.class.php @@ -620,7 +620,7 @@ class BaseAuthedController extends BaseController { { foreach ($items as $item) { //道具消耗埋点 - LogService::consumeItem($item); +// LogService::consumeItem($item); if ($this->_isVirtualItem($item['item_id'])) { $this->_decVirtualItem($item['item_id'], $item['item_num']); } else { diff --git a/webapp/controller/InGameMallController.class.php b/webapp/controller/InGameMallController.class.php index dfadf82f..2418b2c9 100644 --- a/webapp/controller/InGameMallController.class.php +++ b/webapp/controller/InGameMallController.class.php @@ -7,7 +7,11 @@ require_once('mt/Parameter.php'); require_once('models/BcOrder.php'); require_once('models/Mall.php'); +require_once('models/InGameMall.php'); require_once('models/OrderId.php'); +require_once('models/Hero.php'); +require_once('models/Chip.php'); +require_once('models/Bag.php'); require_once('services/BlockChainService.php'); require_once('services/LogService.php'); @@ -18,7 +22,11 @@ use phpcommon\SqlHelper; use models\BcOrder; use models\Mall; +use models\InGameMall; use models\OrderId; +use models\Hero; +use models\Chip; +use models\Bag; use services\LogService; use services\BlockChainService; @@ -43,6 +51,14 @@ class InGameMallController extends BaseAuthedController { if (!empty($seller)) { $queryData['seller'] = $seller; } + $type_filter = getReqVal('type_filter', ''); + if (!empty($type_filter)) { + $queryData['type_filter'] = $type_filter; + } + $item_filter = getReqVal('item_filter', ''); + if (!empty($item_filter)) { + $queryData['item_filter'] = $item_filter; + } $queryData['price_filter'] = getReqVal('price_filter', ''); $orderBy = ''; $orderAsc = 'ASC'; @@ -68,7 +84,7 @@ class InGameMallController extends BaseAuthedController { ); SqlHelper::rawQueryPage( myself()->_getMySql(''), - 'SELECT * FROM t_mall WHERE status=:status', + 'SELECT * FROM t_ingame_mall WHERE status=:status', array( ':status' => Mall::PENDING_STATE ), @@ -80,7 +96,7 @@ class InGameMallController extends BaseAuthedController { 'fields' => array( array( 'name' => 'seller', - 'field_name' => 'seller_address', + 'field_name' => 'seller', 'cond' => '=', 'ignore_empty' => true, ), @@ -98,11 +114,23 @@ class InGameMallController extends BaseAuthedController { . " AND (price >= '${priceLow}' AND price <= '${priceHigh}') "; } ), + array( + 'name' => 'item_filter', + 'field_name' => 'item_id', + 'cond' => '=', + 'ignore_empty' => true, + ), + array( + 'name' => 'type_filter', + 'field_name' => 'order_type', + 'cond' => '=', + 'ignore_empty' => true, + ) ) ), 'orderBy' => $orderBy, 'handle' => function ($row) use(&$out) { - array_push($out['rows'], Mall::toDto($row)); + array_push($out['rows'], $row); } ), $out['pagination'] @@ -112,41 +140,116 @@ class InGameMallController extends BaseAuthedController { public function sell() { - $address = myself()->_getAddress(); - if (!$address) { - $this->_rspErr(1, 'address not found'); - return; - } + $goodsUniid = getReqVal('goods_uniid', ''); $itemId = getReqVal('item_id', ''); $amount = intval(getReqVal('amount', ''), 10); - $currency = getReqVal('currency', ''); - $priceBn = phpcommon\bnInit(getReqVal('price', '')); - if ($itemId != V_ITEM_GOLD) { - $this->_rspErr(1, 'only support gold'); + $priceBn = intval(getReqVal('price', '')); + $itemMeta = \mt\Item::get($itemId); + if (!$itemMeta){ + $this->_rspErr(1, 'param item_id error'); return; } + if (! $this->_isGoodsType($itemMeta['type'])){ + $this->_rspErr(1, 'param item_id error'); + return; + } + switch ($itemMeta['type']){ + case \mt\Item::HERO_TYPE : { + $heroDb = Hero::find($goodsUniid); + if (!$heroDb || !empty($heroDb['token_id']) || $heroDb['hero_id']!= $itemId){ + $this->_rspErr(1, 'param goods_unnid error'); + return; + } + } + break; + case \mt\Item::CHIP_TYPE : { + $chipDb = Chip::find($goodsUniid); + if (!$chipDb || !empty($chipDb['token_id']) || $chipDb['item_id']!= $itemId){ + $this->_rspErr(1, 'param goods_unnid error'); + return; + } + } + } if ($amount <= 0) { $this->_rspErr(1, 'amount must > 0'); return; } - if (!$this->checkPrice($priceBn)) { + if (!$this->_isNumber($priceBn) || $priceBn < 0) { + $this->_rspErr(1, 'param price error'); return; } - if (!in_array( - $currency, - array( - BlockChainService::CURRENCY_CEG, - BlockChainService::CURRENCY_USDC, - BlockChainService::CURRENCY_USDT, - ) - )) { - $this->_rspErr(1, 'paramater error currency'); + $propertyChgService = new PropertyChgService(); + if (\mt\Item::isBagItem($itemMeta['type'],$itemMeta['sub_type'])){ + $costItems = array( + array( + 'item_id' => $itemId, + 'item_num' => $amount + ) + ); + $lackItem = null; + if (!$this->_hasEnoughItems($costItems, $lackItem)) { + $this->_rspErr(2, $this->_getLackItemErrMsg($lackItem)); + return; + } + $this->_decItems($costItems); + $propertyChgService->addBagChg(); + }elseif ($itemMeta['type'] == \mt\Item::HERO_TYPE){ + SqlHelper::update + (myself()->_getSelfMysql(), + 't_hero', + array( + 'idx' => $goodsUniid, + ), + array( + 'account_id' => InGameMall::SYSTEM_MALL_ACCOUNT + ) + ); + $propertyChgService->addHeroChg(); + }elseif ($itemMeta['type'] == \mt\Item::CHIP_TYPE){ + SqlHelper::update + (myself()->_getSelfMysql(), + 't_chip', + array( + 'idx' => $goodsUniid, + ), + array( + 'account_id' => InGameMall::SYSTEM_MALL_ACCOUNT + ) + ); + $propertyChgService->addChip(); + } + + $orderId = OrderId::gen(); + $orderType = $this->_getGoodsType($itemMeta['type']); + InGameMall::add( + $orderId, + $orderType, + $goodsUniid, + $itemId, + $amount, + $priceBn + ); + myself()->_rspData(array( + 'property_chg' => $propertyChgService->toDto(), + )); + } + + public function buy(){ + $orderId = getReqVal('order_id', ''); + $goodsDb = InGameMall::findByOrderId($orderId); + if (!$goodsDb) { + myself()->_rspErr(1, 'goods not found'); return; } + if ($goodsDb['status'] != InGameMall::PENDING_STATE){ + myself()->_rspErr(1, 'cannot cancel the goods'); + return; + } + $price = $goodsDb['price']; $costItems = array( array( - 'item_id' => $itemId, - 'item_num' => $amount + 'item_id' => V_ITEM_GOLD, + 'item_num' => $price ) ); $lackItem = null; @@ -155,111 +258,183 @@ class InGameMallController extends BaseAuthedController { return; } $this->_decItems($costItems); - if ($itemId == V_ITEM_GOLD) { - //埋点 - $event = [ - 'name' => LogService::MARKET_SELL_GOLD, - 'val' => $amount - ]; - LogService::consumeGold($event); - } - $orderId = OrderId::gen(); - Mall::Add( - $orderId, - $orderId, - $itemId, - $amount, - $currency, - phpcommon\bnToStr($priceBn) + SqlHelper::update + ($this->_getSelfMysql(), + 't_user', + array( + 'account_id' => $goodsDb['seller'] + ), + array( + 'gold' => function () use($price) { + return "gold + ${price}"; + } + ) ); - myself()->_rspOk(); + $propertyChgService = new PropertyChgService(); + switch ($goodsDb['order_type']){ + case InGameMall::HERO_TYPE :{ + SqlHelper::update + (myself()->_getSelfMysql(), + 't_hero', + array( + 'idx' => $goodsDb['goods_uniid'], + ), + array( + 'account_id' => myself()->_getAccountId() + ) + ); + $propertyChgService->addHeroChg(); + } + break; + case InGameMall::CHIP_TYPE:{ + SqlHelper::update + (myself()->_getSelfMysql(), + 't_chip', + array( + 'idx' => $goodsDb['goods_uniid'], + ), + array( + 'account_id' => myself()->_getAccountId() + ) + ); + $propertyChgService->addChip(); + } + break; + default : { + Bag::addItem($goodsDb['item_id'],$goodsDb['item_num']); + $propertyChgService->addBagChg(); + } + } + InGameMall::buyOk($orderId,myself()->_getAccountId()); + myself()->_rspData(array( + 'property_chg' => $propertyChgService->toDto(), + )); } public function cancel() { - $goodsUuid = getReqVal('goods_uuid', ''); - $goodsDb = Mall::findByGoodsUuid($goodsUuid); + $orderId = getReqVal('order_id', ''); + $goodsDb = InGameMall::findByOrderId($orderId); if (!$goodsDb) { myself()->_rspErr(1, 'goods not found'); return; } - $goodsDto = Mall::toDto($goodsDb); - if ($goodsDto['cancel_countdown'] != 0) { - myself()->_rspErr(1, 'cant cancel'); + if ($goodsDb['status'] != InGameMall::PENDING_STATE){ + myself()->_rspErr(1, 'cannot cancel the goods'); + return; + } + if ($goodsDb['seller'] != myself()->_getAccountId()){ + myself()->_rspErr(1, 'Not the seller'); return; } - $awardService = new AwardService(); $propertyChgService = new PropertyChgService(); - switch ($goodsDb['item_id']) { - case V_ITEM_GOLD: - { - $items = array( - array( - 'item_id' => $goodsDb['item_id'], - 'item_num' => $goodsDb['item_num'], - ) - ); - Mall::cancel($goodsDto['goods_uuid']); - myself()->_addItems($items, $awardService, $propertyChgService); - { - //埋点 - $event = [ - 'name' => LogService::MARKET_CANCEL_SELL_GOLD, - 'val' => $goods['amount'] - ]; - LogService::productGold($event); + switch ($goodsDb['order_type']){ + case InGameMall::HERO_TYPE :{ + SqlHelper::update + (myself()->_getSelfMysql(), + 't_hero', + array( + 'idx' => $goodsDb['goods_uniid'], + ), + array( + 'account_id' => myself()->_getAccountId() + ) + ); + $propertyChgService->addHeroChg(); + } + break; + case InGameMall::CHIP_TYPE:{ + SqlHelper::update + (myself()->_getSelfMysql(), + 't_chip', + array( + 'idx' => $goodsDb['goods_uniid'], + ), + array( + 'account_id' => myself()->_getAccountId() + ) + ); + $propertyChgService->addChip(); + } + break; + default : { + Bag::addItem($goodsDb['item_id'],$goodsDb['item_num']); + $propertyChgService->addBagChg(); } } - break; - default: - { - myself()->_rspErr(1, 'cant cancel'); - return; - } - break; - } + InGameMall::cancel($orderId); myself()->_rspData(array( - 'award' => $awardService->toDto(), 'property_chg' => $propertyChgService->toDto(), )); } public function modifyPrice() { - $goodsUuid = getReqVal('goods_uuid', ''); - $priceBn = phpcommon\bnInit(getReqVal('price', '')); - if (!$this->checkPrice($priceBn)) { + $orderId = getReqVal('order_id', ''); + $priceBn =intval(getReqVal('price', '')); + if (!$this->_isNumber($priceBn)) { + $this->_rspErr(1, 'param price error'); return; } - $goodsDb = Mall::findByGoodsUuid($goodsUuid); + $goodsDb = InGameMall::findByOrderId($orderId); if (!$goodsDb) { myself()->_rspErr(1, 'goods not found'); return; } - $goodsDto = Mall::toDto($goodsDb); - if ($goodsDto['modify_countdown'] != 0) { - myself()->_rspErr(1, 'cant modify price'); + if ($goodsDb['status'] != InGameMall::PENDING_STATE){ + myself()->_rspErr(1, 'cannot cancel the goods'); return; } - Mall::modifyPrice($goodsDto['goods_uuid'], phpcommon\bnToStr($priceBn)); + if ($goodsDb['seller'] != myself()->_getAccountId()){ + myself()->_rspErr(1, 'Not the seller'); + return; + } + InGameMall::modifyPrice($orderId, $priceBn); myself()->_rspOk(); } - private function checkPrice($priceBn) - { - if ($priceBn === false) { - myself()->_rspErr(1, 'price format error1'); - return false; + private function _isNumber($number){ + if (is_int($number) && $number > 0){ + return true; + }else{ + return false; } - if (phpcommon\bnCmp($this->priceLowBn, $priceBn) > 0) { - myself()->_rspErr(1, 'price format error2'); - return false; - } - if (phpcommon\bnCmp($this->priceHighBn, $priceBn) < 0) { - myself()->_rspErr(1, 'price format error3'); - return false; - } - return true; } + private function _isGoodsType($type){ + if (in_array($type,array( + \mt\Item::HERO_TYPE, + \mt\Item::CHIP_TYPE, + \mt\Item::FRAGMENT_TYPE, + \mt\Item::TREASURE_BOX, + ))){ + return true; + }else{ + return false; + } + } + + private function _getGoodsType($type){ + switch ($type){ + case \mt\Item::HERO_TYPE : { + return InGameMall::HERO_TYPE; + } + case \mt\Item::CHIP_TYPE : { + return InGameMall::CHIP_TYPE; + } + case \mt\Item::FRAGMENT_TYPE : { + return InGameMall::FRAGMENT_TYPE; + } + case \mt\Item::TREASURE_BOX : { + return InGameMall::BOX_TYPE; + } + default : { + return 0; + } + } + } + + + + } diff --git a/webapp/models/Hero.php b/webapp/models/Hero.php index a013b990..2e07d4a5 100644 --- a/webapp/models/Hero.php +++ b/webapp/models/Hero.php @@ -60,11 +60,6 @@ class Hero extends BaseModel { 'idx' => $heroUniId, ) ); - if ($row) { - if ($row['account_id'] != myself()->_getAccountId()) { - $row = null; - } - } return $row; } diff --git a/webapp/models/InGameMall.php b/webapp/models/InGameMall.php new file mode 100644 index 00000000..ff12e30b --- /dev/null +++ b/webapp/models/InGameMall.php @@ -0,0 +1,100 @@ +_getMysql(''), + 't_ingame_mall', + array( + 'order_id' => $orderId + ) + ); + return $row; + } + + public static function add($orderId, $orderType, $goodsUniid,$itemId, $itemNum, $price) + { + SqlHelper::insert + (myself()->_getMysql(''), + 't_ingame_mall', + array( + 'order_id' => $orderId, + 'order_type' => $orderType, + 'seller' => myself()->_getAccountId(), + 'seller_address' => myself()->_getAddress(), + 'goods_uniid' => $goodsUniid, + 'item_id' => $itemId, + 'item_num' => $itemNum, + 'price' => $price, + 'last_modify_price_time' => myself()->_getNowTime(), + 'createtime' => myself()->_getNowTime(), + 'modifytime' => myself()->_getNowTime(), + )); + } + + public static function modifyPrice($orderId, $price) + { + SqlHelper::update + (myself()->_getMysql(''), + 't_ingame_mall', + array( + 'order_id' => $orderId + ), + array( + 'price' => $price, + 'last_modify_price_time' => myself()->_getNowTime(), + ) + ); + } + + public static function cancel($orderId) + { + SqlHelper::update + (myself()->_getMysql(''), + 't_ingame_mall', + array( + 'order_id' => $orderId + ), + array( + 'status' => self::CANCEL_STATE, + 'modifytime' => myself()->_getNowTime(), + ) + ); + } + + public static function buyOk($orderId, $buyer) + { + SqlHelper::update + (myself()->_getMysql(''), + 't_ingame_mall', + array( + 'order_id' => $orderId + ), + array( + 'status' => self::BUY_OK_STATE, + 'buyer' => $buyer, + 'buy_ok_time' => myself()->_getNowTime() + ) + ); + } + + + +}