diff --git a/sql/gamedb.sql b/sql/gamedb.sql index 88b52b51..c76c7ce4 100644 --- a/sql/gamedb.sql +++ b/sql/gamedb.sql @@ -1346,7 +1346,7 @@ CREATE TABLE `t_market_transaction_record` ( `buyer` varchar(60) NOT NULL COMMENT '买家', `token_id` varchar(60) NOT NULL COMMENT 'tokenid', `item_id` int(11) DEFAULT NULL COMMENT '如果有,说明是中心化道具交易', - `amount` int(11) NOT NULL COMMENT '堆叠数量', + `amount` bigint(20) NOT NULL COMMENT '堆叠数量', `name` varchar(64) NOT NULL COMMENT '商品名称', `type` int(11) NOT NULL COMMENT '商品类型', PRIMARY KEY (`idx`), diff --git a/sql/gamedb2006_migrate_230713_01.sql b/sql/gamedb2006_migrate_230713_01.sql index 6bed84d0..47eb2225 100644 --- a/sql/gamedb2006_migrate_230713_01.sql +++ b/sql/gamedb2006_migrate_230713_01.sql @@ -49,7 +49,7 @@ CREATE TABLE `t_market_transaction_record` ( `buyer` varchar(60) NOT NULL COMMENT '买家', `token_id` varchar(60) NOT NULL COMMENT 'tokenid', `item_id` int(11) DEFAULT NULL COMMENT '如果有,说明是中心化道具交易', - `amount` int(11) NOT NULL COMMENT '堆叠数量', + `amount` bigint(20) NOT NULL COMMENT '堆叠数量', `name` varchar(64) NOT NULL COMMENT '商品名称', `type` int(11) NOT NULL COMMENT '商品类型', PRIMARY KEY (`idx`), diff --git a/webapp/bootstrap/constant.php b/webapp/bootstrap/constant.php index 98074b3d..3a9d6b17 100644 --- a/webapp/bootstrap/constant.php +++ b/webapp/bootstrap/constant.php @@ -63,6 +63,7 @@ define('TN_WEEKLY_END', 10005); define('SHOP_BUY_MODE_NORMAL', 0); define('SHOP_BUY_MODE_DAILY_SELECTION', 1); +define('MARKET_BUY_MODE_NORMAL', 2); const kHAT_Begin = 0; const kHAT_Hp = 1; diff --git a/webapp/controller/CallbackController.class.php b/webapp/controller/CallbackController.class.php index bd5e9178..04268a96 100644 --- a/webapp/controller/CallbackController.class.php +++ b/webapp/controller/CallbackController.class.php @@ -1,9 +1,15 @@ 'GameItemMallBuyOk', + 'gameItemMarketBuyOk' => 'GameItemMarketBuyOk', 'MarketSellOrderOk' => 'MarketSellOrderOk', 'MarketBuyOrderOk' => 'MarketBuyOrderOk', 'MarketCancelOrderOk' => 'MarketCancelOrderOk', diff --git a/webapp/controller/MarketController.class.php b/webapp/controller/MarketController.class.php index 1a674e1c..a0bc677a 100644 --- a/webapp/controller/MarketController.class.php +++ b/webapp/controller/MarketController.class.php @@ -43,19 +43,6 @@ use models\Transaction; class MarketController extends BaseAuthedController { - - public function _handlePre() - { - if ( - getReqVal('a', '') != 'eventSellOrder' && - getReqVal('a', '') != 'eventBuyOrder' && - getReqVal('a', '') != 'eventCancelOrder' && - getReqVal('a', '') != 'eventPriceUpdateOrder' - ) { - parent::_handlePre(); - } - } - private function getNftListByAccountAndType($account, $type, $order_method, $order_asc, $job, $search, $lv, $quality, $durability) { $sortByLevel = function ($a, $b) use ($order_asc) { @@ -249,7 +236,6 @@ class MarketController extends BaseAuthedController $job_filters = getReqVal('job_filters', ''); $job_filter_array = explode('|', $job_filters); $search_filters = getReqVal('search_filters', ''); - error_log('search_filters:' . $search_filters); if ($search_filters != '') { $search_filter_array = explode('|', $search_filters); } else { @@ -308,14 +294,12 @@ class MarketController extends BaseAuthedController }; $search_filter_fn = function ($f) { $str = ''; - error_log('search_filter ' . json_encode($f)); $arr_options = array(); foreach ($f as $v) { if (!empty($v)) { array_push($arr_options, 'c_name=\'' . $v . '\' OR token_id=\'' . $v . '\' '); } } - error_log('$$search_filter ' . json_encode($arr_options)); if (count($arr_options) > 0) { $str = implode('OR ', $arr_options); $str = 'AND (' . $str . ') '; @@ -446,7 +430,6 @@ class MarketController extends BaseAuthedController } $search_filters = getReqVal('search_filters', ''); - error_log('search_filters:' . $search_filters); if ($search_filters != '') { $search_filter_array = explode('|', $search_filters); } else { @@ -681,7 +664,12 @@ class MarketController extends BaseAuthedController public function buy() { - $account = strtolower(getReqVal('account', '')); + $address = $this->_getAddress(); + if (!$address) { + $this->_rspErr(1, 'address not found'); + return; + } + $idx = getReqVal('idx', ''); $goods = $this->getGoodsByIdx($idx); @@ -710,9 +698,11 @@ class MarketController extends BaseAuthedController 'item_id' => $item_id, 'item_num' => $item_count, 'order_type' => 1, - 'price' => $goods['s_price'], + 'price' => $this->Web3PriceLowFormat($goods['s_price']), 'ext_data' => json_encode(array( - 'mode' => SHOP_BUY_MODE_NORMAL, + 'mode' => MARKET_BUY_MODE_NORMAL, + 'idx' => $idx, + 'order_id' => $goods['order_id'], )), )); @@ -720,6 +710,12 @@ class MarketController extends BaseAuthedController 'block_chain' => $response, )); } + private function Web3PriceLowFormat($price) { + $bn2 = phpcommon\bnInit('1000000000000000000'); + $ret_price = phpcommon\bnDiv($price, $bn2); + return phpcommon\bnToStr($ret_price); + } + private function sellMyNft() { @@ -854,257 +850,6 @@ class MarketController extends BaseAuthedController )); } - private function addTransactionRecord($record) - { - $conn = myself()->_getMarketMysql(''); - - $r = SqlHelper::insert( - $conn, - 't_market_transaction_record', - $record - ); - if (!$r) { - $this->_rspErr(2, 'unknown error, orderId=' . $record['order_id']); - } - } - - public function eventSellOrder() - { - $tokenId = getReqVal('tokenId', ''); - $owner = strtolower(getReqVal('owner', '')); - $nftToken = getReqVal('nftToken', ''); - $amount = getReqVal('amount', 0); - $orderId = getReqVal('orderId', ''); - $currency = getReqVal('currency', ''); - $price = getReqVal('price', ''); - - error_log( - "eventSellOrder:" . json_encode( - array( - 'tokenId' => $tokenId, - 'owner' => $owner, - 'nftToken' => $nftToken, - 'amount' => $amount, - 'orderId' => $orderId, - 'currency' => $currency, - 'price' => $price, - ), - JSON_PRETTY_PRINT - ) - ); - - $conn = myself()->_getSelfMysql(); - - // 1. check order status - $chk = SqlHelper::selectOne($conn, 't_market_store', array('status'), array('o_link' => $orderId)); - if (!empty($chk)) { - $this->_rspErr(1, 'repeat sell order, orderId=' . $orderId); - return; - } - - // 2. insert sell order to t_market_store - $nftDb = Nft::findNftByOwner($owner, $tokenId); - if (empty($nftDb)) { - $nftDb = Nft::getNft($tokenId); - } - $nftDetail = Nft::toDto($nftDb); - $detail = $this->getNftGameData($nftDb); - $r = SqlHelper::insert( - $conn, - 't_market_store', - array( - 'token_id' => $tokenId, - 'o_link' => $orderId, - 'nft_token' => $nftToken, - 'status' => 0, - 'owner_address' => $owner, - 'token_type' => $nftDetail['type'], - 'amount' => $amount, - 'createtime' => myself()->_getNowTime(), - 'modifytime' => myself()->_getNowTime(), - 's_currency' => $currency, - 's_price' => $price, - 'c_name' => $nftDetail['info']['name'], - 'c_job' => isset($nftDetail['info']['job']) ? $nftDetail['info']['job'] - : (isset($detail['chip_type']) ? $detail['chip_type'] - : (isset($detail['type']) ? $detail['type'] - : 0)), - 'c_lv' => @$detail['gun_lv'] | @$detail['hero_lv'] | @$detail['chip_grade'], - 'c_quality' => isset($nftDetail['info']['quality']) ? $nftDetail['info']['quality'] : 0, - 'c_durability' => isset($nftDetail['info']['durability']) ? $nftDetail['info']['durability'] : (isset($detail['hero_tili']) ? $detail['hero_tili'] : 0), - 'c_type' => isset($detail['type']) ? $detail['type'] : 0, - 'c_id' => $nftDetail['item_id'], - ) - ); - if (!$r) { - $this->_rspErr(2, 'unknown error, orderId=' . $orderId); - } - - $this->_rspOk(); - } - - public function eventBuyOrder() - { - $tokenId = getReqVal('tokenId', ''); - $orderId = getReqVal('orderId', ''); - $nftToken = getReqVal('nftToken', ''); - $amount = getReqVal('amount', 0); - $seller = strtolower(getReqVal('seller', '')); - $buyer = strtolower(getReqVal('buyer', '')); - $erc20 = getReqVal('erc20', ''); - $price = getReqVal('price', ''); - - error_log( - "eventBuyOrder:" . json_encode( - array( - 'tokenId' => $tokenId, - 'orderId' => $orderId, - 'nftToken' => $nftToken, - 'amount' => $amount, - 'seller' => $seller, - 'buyer' => $buyer, - 'erc20' => $erc20, - 'price' => $price, - ), - JSON_PRETTY_PRINT - ) - ); - - // nft order id 统一改为 o_link 字段 - $o_link = $orderId; - - $conn = myself()->_getSelfMysql(); - - // 1. check order status - $chk = SqlHelper::selectOne($conn, 't_market_store', array('status', 'idx', 'c_name', 'token_type'), array('o_link' => $o_link)); - if (empty($chk)) { - $this->_rspErr(1, 'not found order, orderId=' . $o_link); - return; - } - if ($chk['status'] == '0') { - $r = SqlHelper::update( - $conn, - 't_market_store', - array( - 'o_link' => $o_link, - ), - array( - 'status' => 2, - ) - ); - if ($r) { - // 增加交易记录 - $record = array( - 'createtime' => myself()->_getNowTime(), - 'order_id' => $chk['idx'], - 'o_link' => $o_link, - 'seller' => $seller, - 'buyer' => $buyer, - 'tokenid' => $tokenId, - 'amount' => $amount, - 'name' => $chk['c_name'], - 'type' => $chk['token_type'], - ); - $this->addTransactionRecord($record); - $this->_rspOk(); - return; - } - } - $this->_rspErr(1, 'order status error, order=' . $orderId); - } - - public function eventCancelOrder() - { - $orderId = getReqVal('orderId', ''); - $nftToken = getReqVal('nftToken', ''); - $tokenId = getReqVal('tokenId', ''); - error_log( - "eventCancelOrder:" . json_encode( - array( - 'orderId' => $orderId, - 'nftToken' => $nftToken, - 'tokenId' => $tokenId, - ), - JSON_PRETTY_PRINT - ) - ); - - $conn = myself()->_getSelfMysql(); - - // 1. check order status - $chk = SqlHelper::selectOne($conn, 't_market_store', array('status'), array('o_link' => $orderId)); - if (empty($chk)) { - $this->_rspErr(1, 'not found order, orderId=' . $orderId); - return; - } - if ($chk['status'] == '0') { - $r = SqlHelper::update( - $conn, - 't_market_store', - array( - 'o_link' => $orderId, - ), - array( - 'status' => 1, - ) - ); - if ($r) { - $this->_rspOk(); - return; - } - } - $this->_rspErr(1, 'order status error, order=' . $orderId); - } - - public function eventPriceUpdateOrder() - { - $orderId = getReqVal('orderId', '');; - $nftToken = getReqVal('nftToken', ''); - $tokenId = getReqVal('tokenId', ''); - $priceOld = getReqVal('priceOld', ''); - $price = getReqVal('price', ''); - error_log( - "eventPriceUpdateOrder:" . json_encode( - array( - 'orderId' => $orderId, - 'nftToken' => $nftToken, - 'tokenId' => $tokenId, - 'priceOld' => $priceOld, - 'price' => $price, - ), - JSON_PRETTY_PRINT - ) - ); - - $conn = myself()->_getSelfMysql(); - - // 1. check order status - $chk = SqlHelper::selectOne($conn, 't_market_store', array('status'), array('o_link' => $orderId)); - if (empty($chk)) { - $this->_rspErr(1, 'not found order, orderId=' . $orderId); - return; - } - - if ($chk['status'] == '0') { - $r = SqlHelper::update( - $conn, - 't_market_store', - array( - 'o_link' => $orderId, - ), - array( - 's_price' => $price, - ) - ); - if ($r) { - $this->_rspOk(); - return; - } - } - - $this->_rspErr(1, 'price update failed, orderId=' . $orderId); - } - private function getNftGameData($nftRowInfo) { $t = $nftRowInfo['token_type']; @@ -1373,7 +1118,7 @@ class MarketController extends BaseAuthedController $row = SqlHelper::selectOne( myself()->_getSelfMysql(), 't_market_store', - array('item_id', 'amount', 's_price', 'owner_address'), + array('order_id', 'item_id', 'amount', 's_price', 'owner_address'), array( 'idx' => $idx, 'status' => 0, diff --git a/webapp/controller/ShopController.class.php b/webapp/controller/ShopController.class.php index e274fe31..1f922568 100644 --- a/webapp/controller/ShopController.class.php +++ b/webapp/controller/ShopController.class.php @@ -699,16 +699,16 @@ class ShopController extends BaseAuthedController { $address = $this->_getAccountId(); - $maxCount = mt\Parameter::getByName('daily_selection_refresh_time')['param_value']; + $costs = mt\Parameter::getByName('daily_selection_refresh_cost'); + $arrCosts = explode('|', $costs['param_value']); + $maxCount = count($arrCosts); + $count = $this->countTodayRefreshTimes($address); if ($count >= $maxCount) { $this->_rspErr(2, 'The maximum number of refreshes has been reached'); return; } - $count = $this->countTodayRefreshTimes($address); - $costs = mt\Parameter::getByName('daily_selection_refresh_cost'); - $arrCosts = explode('|', $costs['param_value']); $cost = $arrCosts[$count]; $costItemId = $this->getCostItemIdByTokenType(ShopController::TOKEN_TYPE_GOLD); $costItems = $this->makeCostItems($costItemId, $cost); @@ -1129,7 +1129,7 @@ class ShopController extends BaseAuthedController $token_type = $goods['token_type']; $costItemId = $this->getCostItemIdByTokenType($token_type); - $costItems = $this->makeCostItems($costItemId, $goods['goods_num'] * $count * $goods['price']); + $costItems = $this->makeCostItems($costItemId, $count * $goods['price']); $lackItem = null; if (!$this->_hasEnoughItems($costItems, $lackItem)) { $this->_rspErr(2, $this->_getLackItemErrMsg($lackItem)); @@ -1138,7 +1138,7 @@ class ShopController extends BaseAuthedController $item_id = $goods['goods_id']; - $item_num = $goods['goods_num'] * $count; + $item_num = $goods['goods_num']; $sql = "UPDATE t_shop_dailyselection SET count_$grid = count_$grid - $count WHERE idx = $idx"; $chk = $conn->execScript($sql); @@ -1149,7 +1149,7 @@ class ShopController extends BaseAuthedController $this->internalAddItem($propertyChgService, $itemMeta, $item_num, 0); } $awardService = new services\AwardService(); - $awardService->addItem($goods['goods_id'], $count); + $awardService->addItem($goods['goods_id'], $count * $item_num); $this->_decItems($costItems); $event = [ diff --git a/webapp/services/FormulaService.php b/webapp/services/FormulaService.php index f3af5026..08555d6f 100644 --- a/webapp/services/FormulaService.php +++ b/webapp/services/FormulaService.php @@ -7,6 +7,7 @@ require_once('mt/Item.php'); require_once('mt/FormulaPvp.php'); require_once('mt/HeroQuality.php'); require_once('mt/GunQuality.php'); +require_once('mt/Parameter.php'); require_once('models/RealtimeData.php'); use models\Chip; diff --git a/webapp/services/callback/BuyShopGoodsCbService.php b/webapp/services/callback/BuyShopGoodsCbService.php index 12c4965f..2431e741 100644 --- a/webapp/services/callback/BuyShopGoodsCbService.php +++ b/webapp/services/callback/BuyShopGoodsCbService.php @@ -59,6 +59,8 @@ class BuyShopGoodsCbService )), )); break; + case MARKET_BUY_MODE_NORMAL: + break; } } break; diff --git a/webapp/services/callback/GameItemMallBuyOk.php b/webapp/services/callback/GameItemMallBuyOk.php index 8faa6881..e4c34910 100644 --- a/webapp/services/callback/GameItemMallBuyOk.php +++ b/webapp/services/callback/GameItemMallBuyOk.php @@ -5,6 +5,7 @@ namespace services; require_once('phpcommon/bchelper.php'); require_once ('services/callback/BuyPassCbService.php'); require_once ('services/callback/BuyShopGoodsCbService.php'); +require_once ('services/callback/common/SignatureService.php'); use phpcommon\SqlHelper; @@ -12,6 +13,7 @@ class GameItemMallBuyOk { public function process() { + SignatureService::web3ServiceCheck(); $address = getReqVal('address', ''); $orderId = getReqVal('order_id', ''); diff --git a/webapp/services/callback/GameItemMarketBuyOk.php b/webapp/services/callback/GameItemMarketBuyOk.php new file mode 100644 index 00000000..ed5424bd --- /dev/null +++ b/webapp/services/callback/GameItemMarketBuyOk.php @@ -0,0 +1,167 @@ +_getMysql($address), + 't_bc_order', + array( + 'order_id' => $orderId + ) + ); + //1:已发货 2:订单不存在 + if (!$orderDb) { + echo json_encode(array( + 'errcode' => 2, + 'errmsg' => "Order does not exist", + )); + die; + } + if ($orderDb['status'] == 1) { + echo json_encode(array( + 'errcode' => 1, + 'errmsg' => "Order shipped", + )); + die; + } + // 修改订单状态 + $this->_updateOrderState($address, $orderId); + + $ext_data = json_decode($orderDb['ext_data'], true); + + switch ($ext_data['mode']) { + case MARKET_BUY_MODE_NORMAL: { + $order = $orderDb; + $itemService->addGameLog($order['address'], "shopBuyNormal", "begin", array( + 'param1' => $order['order_id'], + 'param2' => json_encode(array( + 'item_id' => $order['item_id'], + 'item_num' => $order['item_num'], + )), + )); + $this->buyFromMarket($order, $ext_data['idx']); + $itemService->addGameLog($order['address'], "shopBuyNormal", "end", array( + 'param1' => $order['order_id'], + 'param2' => json_encode(array( + 'item_id' => $order['item_id'], + 'item_num' => $order['item_num'], + )), + )); + } + break; + } + + echo json_encode(array( + 'errcode' => 0, + 'errmsg' => "callback success", + )); + } + + private function _isVirtualItem($itemId) + { + return in_array( + $itemId, + array( + V_ITEM_EXP, + V_ITEM_PASS, + V_ITEM_RESET_CARD, + ) + ); + } + + private function _updateOrderState($address, $transId) + { + SqlHelper::update( + myself()->_getMysql($address), + 't_bc_order', + array( + 'order_id' => $transId + ), + array( + 'status' => 1, + 'modifytime' => myself()->_getNowTime(), + ) + ); + } + + private function buyFromMarket($order, $idx) + { + $address = $order['address']; + $goods = $this->getMarketGoods($address, $idx); + $this->markMarketGoodsSold($address, $idx); + + $this->_addGoods($address, $goods); + } + + private function getMarketGoods($address, $idx) + { + $row = SqlHelper::selectOne( + myself()->_getMysql($address), + 't_market_store', + array('order_id', 'item_id', 'amount', 's_price', 'owner_address'), + array( + 'idx' => $idx + ) + ); + if (!$row) { + return null; + } + if (!$row['item_id']) { + return null; + } + return $row; + } + + private function markMarketGoodsSold($address, $idx) + { + SqlHelper::update( + myself()->_getMysql($address), + 't_market_store', + array( + 'idx' => $idx + ), + array( + 'status' => 2, + 'modifytime' => myself()->_getNowTime(), + ) + ); + } + + private function _addGoods($address, $goods) + { + $itemService = new ShopAddItemService(); + $item_id = $goods['item_id']; + $goods_num = $goods['amount']; + + $id = null; + if (!empty($goods['id'])) { + $id = $goods['id']; + } + + error_log(json_encode($goods)); + error_log('_addGoods ' . $address . ' item_id ' . $item_id . ' goods_num ' . $goods_num . ' id ' . $id); + $itemService->addItem($address, $item_id, $goods_num); + if ($id) { + ShopBuyRecord::addWithAddress($address, $id, $goods_num); + } + } + +} diff --git a/webapp/services/callback/MarketCallbackBase.php b/webapp/services/callback/MarketCallbackBase.php index b11702ee..423d9035 100644 --- a/webapp/services/callback/MarketCallbackBase.php +++ b/webapp/services/callback/MarketCallbackBase.php @@ -2,6 +2,7 @@ namespace services; +require_once('phpcommon/bignumber.php'); use phpcommon\SqlHelper; use phpcommon; diff --git a/webapp/services/callback/common/SignatureService.php b/webapp/services/callback/common/SignatureService.php index 155599d5..e4f4e0bc 100644 --- a/webapp/services/callback/common/SignatureService.php +++ b/webapp/services/callback/common/SignatureService.php @@ -4,8 +4,38 @@ namespace services; class SignatureService { - public static function web3ServiceCheck() { + const ERRCODE_SIGN_ERROR = 2001; + public static function web3ServiceCheck() + { + $cbUuid = getReqVal('_cb_uuid', ''); + $row = SqlHelper::ormSelectOne( + myself()->_getMarketMysql(), + 't_callback', + array( + 'cb_uuid' => $cbUuid + ) + ); + if (!$row) { + myself()-_rspErr(self::ERRCODE_SIGN_ERROR, 'not found cb info'); + die(); + } + $sign = self::normalMd5Sign($_REQUEST, $row['secret_key'], array('_sign')); + if ($sign != $row['signature']) { + myself()-_rspErr(self::ERRCODE_SIGN_ERROR, 'sign error'); + die(); + } + } + + public static function normalMd5Sign($params, $secretKey, $excludeKeys){ + ksort($params); + $paramsStr = ''; + foreach($params as $key => $val){ + if (!in_array($key, $excludeKeys)) { + $paramsStr = $paramsStr . $key . '=' . $val . $connStr; + } + } + return md5($paramsStr . $$secretKey); } }