game2006api/webapp/controller/MallController.class.php
aozhiwei 331fe8c65f 1
2023-08-03 20:52:00 +08:00

489 lines
13 KiB
PHP

<?php
require_once('mt/Item.php');
require_once('mt/Hero.php');
require_once('mt/Parameter.php');
require_once('models/Nft.php');
require_once('models/Hero.php');
require_once('models/Gun.php');
require_once('models/Chip.php');
require_once('models/Fragment.php');
require_once('models/BcOrder.php');
require_once('services/BlockChainService.php');
require_once('services/LogService.php');
require_once('phpcommon/bchelper.php');
use models\BcOrder;
use phpcommon\SqlHelper;
use models\Nft;
use models\Hero;
use models\Gun;
use models\Chip;
use models\Fragment;
use models\Transaction;
use services\LogService;
class MallController extends BaseAuthedController {
public function sell()
{
$address = $this->_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;
}
}