diff --git a/doc/Battle.py b/doc/Battle.py index 729c7924..476df3e7 100644 --- a/doc/Battle.py +++ b/doc/Battle.py @@ -136,6 +136,7 @@ class Battle(object): ['parachute',0,'降落伞 item id'], ['hero_skin',0,'英雄皮肤 item id'], ['skill_id',0,'备战技能 item id'], + ['battle_times',0,'战斗次数'], ['chip_page',_common.Attr(),'铭文页属性'], ['hero_dto','','英雄详情'], ['weapon_dto1','','武器1详情'], diff --git a/webapp/bootstrap/constant.php b/webapp/bootstrap/constant.php index e38173bc..3d74705b 100644 --- a/webapp/bootstrap/constant.php +++ b/webapp/bootstrap/constant.php @@ -59,6 +59,9 @@ define('TN_WEEKLY_RECHARGE_UPGRADE_TIMES', 10004); define('TN_WEEKLY_SHARE_GAMES', 10005); define('TN_WEEKLY_END', 10005); +define('SHOP_BUY_MODE_NORMAL', 0); +define('SHOP_BUY_MODE_DAILY_SELECTION', 1); + const kHAT_Begin = 0; const kHAT_Hp = 1; const kHAT_HPRecover = 2; diff --git a/webapp/controller/ShopController.class.php b/webapp/controller/ShopController.class.php index 912318f3..014ef306 100644 --- a/webapp/controller/ShopController.class.php +++ b/webapp/controller/ShopController.class.php @@ -17,10 +17,16 @@ require_once('models/Gun.php'); require_once('models/GunSkin.php'); require_once('models/ShopBuyRecord.php'); require_once('models/Chip.php'); +require_once('models/BcOrder.php'); +require_once('models/Transaction.php'); require_once('services/AwardService.php'); require_once('services/PropertyChgService.php'); +require_once('services/BlockChainService.php'); +require_once('phpcommon/bignumber.php'); + +use phpcommon; use phpcommon\HttpClient; use phpcommon\SqlHelper; use models\User; @@ -34,10 +40,13 @@ use models\Chip; use mt\Shop; use mt\PayMethod; use mt\Dailyselection; +use models\Transaction; +use models\BcOrder; class ShopController extends BaseAuthedController { + const TOKEN_TYPE_GOLD = '0'; const TOKEN_TYPE_CEG = '1'; const TOKEN_TYPE_CEC = '2'; const TOKEN_TYPE_BCEG = '3'; @@ -801,6 +810,134 @@ class ShopController extends BaseAuthedController ); } + public function buyGoodsNormal() + { + $id = getReqVal('id', 0); + $token_type = getReqVal('token_type', ''); + $goods_num = getReqVal('goods_num', 0); + + $row = mt\ShopGoods::get($id); + + $desired_token_type = $row['token_type']; + $check_token_type = splitStr1($desired_token_type); + $token_pos = array_search($token_type, $check_token_type, true); + if (!in_array($token_type, $check_token_type)) { + $this->_rspErr(1, "token_type parameter error, desired_token_type: {$desired_token_type}"); + return; + } + + if ($goods_num > $row['max_amount']) { + $this->_rspErr(1, "goods_num parameter error, max_amount: {$row['max_amount']}"); + return; + } + + // 这里命名混乱了, 购买个数,一捆个数命名冲突 + $goods_count = $row['goods_num']; + + $buyRecordHash = ShopBuyRecord::allToHash(); + $boughtTimes = 1; + switch ($row['limit_type']) { + case ShopController::DAILY_BUY_LIMIT: { + $buyRecord = getXVal($buyRecordHash, $id); + $boughtTimes = $buyRecord ? $buyRecord['this_day_buy_times'] + 1 : 1; + if ($buyRecord && getXVal($buyRecord, 'this_day_buy_times', 0) >= $row['limit_num']) { + $this->_rspErr(2, 'Has reached the maximum number of purchase restrictions today'); + return; + } + if ($row['limit_num'] <= 0) { + $this->_rspErr(2, 'The maximum number of purchase restrictions has been reached'); + return; + } + } + break; + case ShopController::WEEKLY_BUY_LIMIT: { + $buyRecord = getXVal($buyRecordHash, $id); + $boughtTimes = $buyRecord ? $buyRecord['this_week_buy_times'] + 1 : 1; + if ($buyRecord && getXVal($buyRecord, 'this_week_buy_times', 0) >= $row['limit_num']) { + $this->_rspErr(2, 'The maximum number of purchase restrictions this week has been reached'); + return; + } + if ($row['limit_num'] <= 0) { + $this->_rspErr(2, 'The maximum number of purchase restrictions has been reached'); + return; + } + } + break; + case ShopController::TOTAL_BUY_LIMIT: { + $buyRecord = getXVal($buyRecordHash, $id); + $boughtTimes = $buyRecord ? $buyRecord['total_buy_times'] + 1 : 1; + if ($buyRecord && getXVal($buyRecord, 'total_buy_times', 0) >= $row['limit_num']) { + $this->_rspErr(2, 'The maximum number of purchase restrictions has been reached'); + return; + } + if ($row['limit_num'] <= 0) { + $this->_rspErr(2, 'he maximum number of purchase restrictions has been reached'); + return; + } + } + break; + default: { + } + break; + } + + $price_array = splitStr1($row['price']); + $discount_array = splitStr1($row['discount']); + + $need_price = $price_array[$token_pos]; + $discount = $discount_array[$token_pos]; + + $discount_begin = strtotime($row['discount_begin'] . ' UTC'); + $discount_end = strtotime($row['discount_end'] . ' UTC'); + $nowTime = $this->_getNowTime(); + + if ($nowTime >= $discount_begin && $nowTime < $discount_end) { + + $need_price = ceil($need_price * ($discount / 100.0)); + } + + $costItemId = $this->getCostItemIdByTokenType($token_type); + + switch ($token_type) { + case ShopController::TOKEN_TYPE_CEG: + case ShopController::TOKEN_TYPE_CEC: + + $price = $this->normalizeWeb3Price($goods_num * $need_price); + $item_id = $row['goods_id']; + $item_count = $goods_num; + + $response = services\BlockChainService::gameItemMallBuy( + Transaction::BUY_GOODS_ACTION_TYPE, + $price, + $item_id, + $item_count, + ); + + BcOrder::upsert( $response['trans_id'], array( + 'item_id' => $item_id, + 'item_num' => $item_count, + 'order_type' => 1, + 'ext_data' => json_encode(array( + 'mode' => SHOP_BUY_MODE_NORMAL, + )), + )); + + $this->_rspOK(); + break; + + case ShopController::TOKEN_TYPE_BCEG: + break; + + case ShopController::TOKEN_TYPE_USDT: + case ShopController::TOKEN_TYPE_USDC: + case ShopController::TOKEN_TYPE_BUSD: + case ShopController::TOKEN_TYPE_MATIC: + case ShopController::TOKEN_TYPE_BNB: + default: + $this->_rspErr(1, "token_type is unsupport, {$token_type}"); + } + } + public function buyGoodsDS() { $address = $this->_getAddress(); @@ -813,33 +950,73 @@ class ShopController extends BaseAuthedController $grid = getReqVal('grid', 0); $count = getReqVal('count', 0); - $address = $this->_getAddress(); - // $chk = $this->decDailySelectionItem($idx, $grid, $count); - // if (!$chk) { - // $this->_rspErr(1, 'goods not enough'); - // return; - // } + $conn = $this->_getMysql(''); - $url = "192.168.100.39:7672/webapp/index.php"; - $params = array( - 'c' => 'GameItemMall', - 'a' => 'buy', - 'address' => $address, - 'price' => 100, + $row = SqlHelper::selectOne( + $conn, + 't_shop_dailyselection', + array( + 'idx', + 'address', + 'grid_' . $grid, + 'count_' . $grid, + ), + array('idx' => $idx) ); - if (!phpcommon\HttpClient::get($url, $params, $response)) { - $this->_rspErr(500, 'GameItemMall buy failed'); + + if (!$row) { + $this->_rspErr(2, 'idx is invalid'); return; } - $response = ''; - error_log($response); + + if ($row['address'] != $address) { + $this->_rspErr(2, 'address is invalid'); + return; + } + + if ($row['grid_' . $grid] == 0) { + $this->_rspErr(2, 'grid is invalid'); + return; + } + + if ($row['count_' . $grid] < $count) { + $this->_rspErr(2, 'count is invalid'); + return; + } + + $sel_id = $row['grid_' . $grid]; + + $goods = mt\Dailyselection::get($sel_id); + + $price = $this->normalizeWeb3Price($goods['price'] * $count); + $item_id = $goods['goods_id']; + $item_count = $goods['goods_num'] * $count; + + $response = services\BlockChainService::gameItemMallBuy( + Transaction::BUY_GOODS_ACTION_TYPE, + $price, + $item_id, + $item_count, + ); + + BcOrder::upsert( $response['trans_id'], array( + 'item_id' => $item_id, + 'item_num' => $item_count, + 'order_type' => 1, + 'ext_data' => json_encode(array( + 'mode' => SHOP_BUY_MODE_DAILY_SELECTION, + 'idx' => $idx, + 'grid' => $grid, + 'count' => $count, + )), + )); $this->_rspData( array( 'idx' => $idx, 'grid' => $grid, 'count' => $count, - 'response' => $response, + 'trans' => $response, ) ); } @@ -1258,4 +1435,13 @@ class ShopController extends BaseAuthedController $row = $conn->execQueryOne('SELECT LAST_INSERT_ID() as lastId;', array()); return $row['lastId']; } + + private function normalizeWeb3Price($price) + { + $bn1 = phpcommon\bnInit($price * pow(10, 8)); + $bn2 = phpcommon\bnInit('1000000000000000000'); + $price = phpcommon\bnDiv(phpcommon\bnMul($bn1, $bn2), pow(10, 8)); + + return $price; + } } diff --git a/webapp/models/Transaction.php b/webapp/models/Transaction.php index 357a2349..b82cbaa4 100644 --- a/webapp/models/Transaction.php +++ b/webapp/models/Transaction.php @@ -20,6 +20,7 @@ class Transaction extends BaseModel { const BUY_EXP_ACTION_TYPE = 101; const BUY_PASS_ACTION_TYPE = 102; + const BUY_GOODS_ACTION_TYPE = 103; const BUY_END_ACTION_TYPE = 200; diff --git a/webapp/services/BlockChainService.php b/webapp/services/BlockChainService.php index 77f673ab..68bcefde 100644 --- a/webapp/services/BlockChainService.php +++ b/webapp/services/BlockChainService.php @@ -5,6 +5,7 @@ namespace services; require_once('models/Transaction.php'); use models\Transaction; +use phpcommon; class BlockChainService { @@ -83,6 +84,7 @@ class BlockChainService { private static function getWeb3ServiceUrl() { + return 'http://192.168.100.39:7672/webapp/index.php'; if (SERVER_ENV == _TEST) { return 'http://127.0.0.1:7672/webapp/index.php'; } diff --git a/webapp/services/callback/BuyShopGoodsCbService.php b/webapp/services/callback/BuyShopGoodsCbService.php index def4688d..289d8b1b 100644 --- a/webapp/services/callback/BuyShopGoodsCbService.php +++ b/webapp/services/callback/BuyShopGoodsCbService.php @@ -3,10 +3,94 @@ namespace services; +require_once('mt/Dailyselection.php'); + +define('V_ORDER_TYPE_BUY_SHOP_GOODS', 1); + +use phpcommon\SqlHelper; +use mt\Dailyselection; class BuyShopGoodsCbService { - public function process($order){ - + public function process($order) + { + switch ($order['order_type']) { + case V_ORDER_TYPE_BUY_SHOP_GOODS: { + $ext_data = json_decode($order['ext_data'], true); + switch ($ext_data['mode']) { + case SHOP_BUY_MODE_NORMAL: + $this->_buyNormal($order, $ext_data); + break; + case SHOP_BUY_MODE_DAILY_SELECTION: + $this->_buyDailySelection($order, $ext_data); + break; + } + } + break; + default: { + } + } } -} \ No newline at end of file + + private function _buyNormal($order, $ext_data) + { + $self = myself(); + if (!$self) { + return; + } + + $address = $order['address']; + $ext_data = $order['ext_data']; + $goods_id = $order['item_id']; + $goods_num = $order['item_num']; + + $this->_addGoods($address, array( + 'goods_id' => $goods_id, + 'goods_num' => $goods_num, + )); + } + + private function _buyDailySelection($order, $ext_data) + { + $self = myself(); + if (!$self) { + return; + } + + $order_id = $order['order_id']; + $item_id = $order['item_id']; + $item_num = $order['item_num']; + $address = $order['address']; + $idx = $ext_data['idx']; + $grid = $ext_data['grid']; + $count = $ext_data['count']; + + $conn = $self->_getMysql($address); + $sql = "SELECT count_$grid FROM t_shop_dailyselection WHERE idx = $idx"; + $chk = $conn->execQuery($sql); + if (!$chk) { + return; + } + if ($chk[0]['count_' . $grid] < $count) { + error_log("BuyShopGoodsCbService::_buyDailySelection() count not enough, address: $address, order_id: $order_id, idx: $idx, grid: $grid, count: $count"); + return; + } + + $sql = "UPDATE t_shop_dailyselection SET count_$grid = count_$grid - $count WHERE idx = $idx"; + $chk = $conn->execScript($sql); + + if ($chk) { + $this->_addGoods($address, array( + 'goods_id' => $item_id, + 'goods_num' => $item_num, + )); + } else { + error_log("BuyShopGoodsCbService::_buyDailySelection() decDailySelectionItem failed, address: $address, order_id: $order_id, idx: $idx, grid: $grid, count: $count"); + } + } + + private function _addGoods($address, $goods) + { + error_log("BuyShopGoodsCbService::_addGoods() address: $address, goods: " . json_encode($goods)); + } +}