_getAddress(); if (!$address) { $this->_rspErr(1, 'address not found'); return; } $item_id = getReqVal('item_id', ''); if ($item_id != V_ITEM_GOLD) { $this->_rspErr(1, 'only support gold'); return; } $itemMeta = mt\Item::get($item_id); if (!$itemMeta) { $this->_rspErr(1, 'item_id not found'); return; } $s_price = getReqVal('s_price', ''); if (empty($s_price)) { $this->_rspErr(1, 's_price not found'); return; } if (!is_numeric($s_price)) { $this->_rspErr(1, 's_price must be number'); return; } if ($s_price <= 0) { $this->_rspErr(1, 's_price must > 0'); return; } $amount = getReqVal('amount', 1); if (empty($amount)) { $this->_rspErr(1, 'amount not found'); return; } if (!is_numeric($amount)) { $this->_rspErr(1, 'amount must be number'); return; } if ($amount <= 0) { $this->_rspErr(1, 'amount must > 0'); return; } $conn = myself()->_getSelfMysql(); // 检查是否有足够的物品 $costItems = $this->makeCostItems($item_id, $amount); $lackItem = null; if (!$this->_hasEnoughItems($costItems, $lackItem)) { $this->_rspErr(2, $this->_getLackItemErrMsg($lackItem)); return; } $this->_decItems($costItems); { //埋点 $event = [ 'name' => LogService::MARKET_SELL_GOLD, 'val' => $amount ]; LogService::consumeGold($event); } $c_name = $itemMeta['name']; $c_job = 0; $c_lv = 0; $c_quality = $itemMeta['quality']; $c_durability = 0; $c_type = 0; $c_id = $item_id; $r = SqlHelper::insert( $conn, 't_market_store', array( 'token_id' => '', 'item_id' => $item_id, 'status' => 0, 'owner_address' => $address, 'token_type' => 0, 'amount' => $amount, 'createtime' => myself()->_getNowTime(), 'modifytime' => myself()->_getNowTime(), 's_price' => $s_price, 'c_name' => $c_name, 'c_job' => $c_job, 'c_lv' => $c_lv, 'c_quality' => $c_quality, 'c_durability' => $c_durability, 'c_type' => $c_type, 'c_id' => $c_id, ) ); if (!$r) { $this->_rspErr(3, "sell failed"); return; } $lastId = $this->lastInsertId($conn); $order_id = $this->genOrderId($lastId); $test = SqlHelper::update($conn, 't_market_store', array('idx' => $lastId), array('order_id' => $order_id)); if (!$test) { $this->_rspErr(6, "sell failed"); return; } $this->_rspOk(); } private function genOrderId($id) { $order_id_base = date('YmdHis') . "10000000"; $divIdx = phpcommon\bnToStr(gmp_mod($id, 9999999)); $order_id = phpcommon\bnAdd_s($order_id_base, $divIdx); return $order_id; } private function lastInsertId($conn) { $row = $conn->execQueryOne('SELECT LAST_INSERT_ID() as lastId;', array()); return $row['lastId']; } private function makeCostItems($item_id, $num) { $costItems = array( array( 'item_id' => $item_id, 'item_num' => $num ) ); return $costItems; } public function sellCancel() { $idx = getReqVal('idx', ''); $address = $this->_getAddress(); if (!$address) { $this->_rspErr(1, 'address not found'); return; } $goods = $this->getGoodsByIdx($idx); if (!$goods) { $this->_rspErr(1, 'goods not found, idx:' . $idx); return; } if ($goods['owner_address'] != $address) { $this->_rspErr(1, 'not your goods, idx:' . $idx); return; } $conn = $this->_getSelfMysql(); $r = SqlHelper::update( $conn, 't_market_store', array( 'idx' => $idx, ), array( 'status' => 1, 'modifytime' => $this->_getNowTime(), ) ); if ($r) { $items = array( array( 'item_id' => $goods['item_id'], 'item_num' => $goods['amount'], ) ); $awardService = new services\AwardService(); $propertyChgService = new services\PropertyChgService(); $this->_addItems($items, $awardService, $propertyChgService); { //埋点 $event = [ 'name' => LogService::MARKET_CANCEL_SELL_GOLD, 'val' => $goods['amount'] ]; LogService::productGold($event); } $this->_rspData( array( 'idx' => $idx, 'property_chg' => $propertyChgService->toDto(), ) ); } else { $this->_rspErr(1, 'cancel failed'); } } public function sellUpdatePrice() { $idx = getReqVal('idx', ''); $s_price = getReqVal('s_price', ''); if (empty($s_price)) { $this->_rspErr(1, 's_price not found'); return; } if (!is_numeric($s_price)) { $this->_rspErr(1, 's_price must be number'); return; } $address = $this->_getAddress(); if (!$address) { $this->_rspErr(1, 'address not found'); return; } $goods = $this->getGoodsByIdx($idx); if (!$goods) { $this->_rspErr(1, 'goods not found, idx:' . $idx); return; } if ($goods['owner_address'] != $address) { $this->_rspErr(1, 'not your goods, idx:' . $idx); return; } $conn = $this->_getSelfMysql(); $r = SqlHelper::update( $conn, 't_market_store', array( 'idx' => $idx, ), array( 's_price' => $s_price, 'modifytime' => $this->_getNowTime(), ) ); if (!$r) { $this->_rspErr(1, 'update price failed'); return; } $this->_rspOk(); } public function buy() { $address = $this->_getAddress(); if (!$address) { $this->_rspErr(1, 'address not found'); return; } $idx = getReqVal('idx', ''); $s_price = getReqVal('s_price', ''); if (empty($s_price)) { $this->_rspErr(1, 's_price not found'); return; } if (!is_numeric($s_price)) { $this->_rspErr(1, 's_price not number'); return; } $goods = $this->getGoodsByIdx($idx); if (!$goods) { $this->_rspErr(1, 'goods not found, idx:' . $idx); return; } if ($s_price != $goods['s_price']) { $this->_rspErr(1, 'price not match, idx:' . $idx); return; } $response = services\BlockChainService::gameItemMarketBuy( Transaction::BUY_GOODS_FROM_MARKET_ACTION_TYPE, $goods['owner_address'], $goods['s_price'], $goods['item_id'], $goods['amount'] ); if (!$this->markOrderBuyStatus($idx)) { $this->_rspErr(1, 'buy failed, update order status failed, idx:' . $idx); return; } $item_id = $goods['item_id']; $item_count = $goods['amount']; BcOrder::upsert($response['trans_id'], array( 'item_id' => $item_id, 'item_num' => $item_count, 'order_type' => 1, 'price' => $this->Web3PriceLowFormat($goods['s_price']), 'ext_data' => json_encode(array( 'mode' => MARKET_BUY_MODE_NORMAL, 'idx' => $idx, 'order_id' => $goods['order_id'], )), )); $this->_rspData(array( 'block_chain' => $response, )); } private function Web3PriceLowFormat($price) { $bn2 = phpcommon\bnInit('1000000000000000000'); $ret_price = phpcommon\bnDiv($price, $bn2); return phpcommon\bnToStr($ret_price); } private function getNftGameData($nftRowInfo) { $t = $nftRowInfo['token_type']; $token_id = $nftRowInfo['token_id']; switch ($t) { case Nft::HERO_TYPE: { return $this->appendChipsInfo(Hero::toDtoInfo(Hero::findByTokenId2($token_id))); } break; case Nft::EQUIP_TYPE: { return $this->appendChipsInfo(Gun::toDtoInfo(Gun::findByTokenId2($token_id))); } break; case Nft::CHIP_TYPE: { return Chip::toDto(Chip::getChipByTokenId($token_id)); } break; case Nft::FRAGMENT_TYPE: { return Fragment::ToDto($nftRowInfo); } break; default: { } break; } return array('unknown' => 'unknown game data type, cannot find data'); } private function appendChipsInfo($detail) { $detail['chips_info'] = array(); if (!empty($detail['chip_ids'])) { $chips = explode('|', $detail['chip_ids']); foreach ($chips as $chip) { $chip_info = ""; if (!empty($chip)) { $chip_info = Chip::toDto(Chip::getChipByTokenId($chip)); } array_push($detail['chips_info'], $chip_info); } } return $detail; } private function attach_market_selling(&$row) { $conn = myself()->_getSelfMysql(); $rows = $conn->execQuery( 'SELECT * FROM t_market_store ' . 'WHERE token_id=:token_id AND owner_address=:owner_address AND status=:status', array( ':token_id' => $row['token_id'], ':owner_address' => $row['owner_address'], ':status' => 0, ) ); $count = 0; $link_array = array(); foreach ($rows as $r) { $count += $r['amount']; array_push($link_array, $r['o_link']); } $row['o_link'] = implode('|', $link_array); $row['selling'] = $count; } private function listMySelledNfts($account, $type) { // error_log('listMySelledNfts ' . $account . ' ' . $type); $conn = myself()->_getSelfMysql(); $rows = $conn->execQuery( 'SELECT * FROM t_market_store ' . 'WHERE owner_address=:account AND token_type=:token_type AND status=0 ', array( ':account' => $account, ':token_type' => $type, ) ); return $rows; } private function normalizeWeb3Price($price) { $bn1 = phpcommon\bnInit($price * pow(10, 8)); $bn2 = phpcommon\bnInit('1000000000000000000'); $ret_price = phpcommon\bnDiv(phpcommon\bnMul($bn1, $bn2), pow(10, 8)); // error_log('normalizeWeb3Price: ' . $ret_price . ' ' . $price * pow(10, 8)); return phpcommon\bnToStr($ret_price); } private function getGoodsByIdx($idx) { $row = SqlHelper::selectOne( myself()->_getSelfMysql(), 't_market_store', array('order_id', 'item_id', 'amount', 's_price', 'owner_address'), array( 'idx' => $idx, 'status' => 0, ) ); if (!$row) { return null; } if (!$row['item_id']) { return null; } return $row; } private function markOrderBuyStatus($idx) { $r = SqlHelper::update( myself()->_getSelfMysql(), 't_market_store', array( 'idx' => $idx, ), array( 'status' => 3, 'buytime' => myself()->_getNowTime(), ) ); if (!$r) { return false; } return true; } }