diff --git a/doc/Shop.py b/doc/Shop.py index 7b36f76f..b94d0b26 100644 --- a/doc/Shop.py +++ b/doc/Shop.py @@ -96,6 +96,27 @@ class Shop(object): ['goods_chg', _common.NewGoods(), '购买后更新商品的最新信息(可能为null客户端需要做容错处理)'], ] }, + { + 'name': 'buyGoodsNormal', + 'desc': '购买商品(正式)', + 'group': 'Shop', + 'url': 'webapp/index.php?c=Shop&a=buyGoodsNormal', + 'params': [ + _common.ReqHead(), + ['id', 0, '商品唯一id,参见shopGoods表'], + ['token_type', '', "选用币种"], + ['goods_num', 0, '商品数量'], + ], + 'response': [ + _common.RspHead(), + ['ret', _common.Union([ + [_common.ShopTrans(), '链上交易结果'], + ]), '购买结果'], + ['award', _common.Award(), '奖励信息'], + ['property_chg', _common.PropertyChg(), '属性变更'], + ['goods_chg', _common.NewGoods(), '购买后更新商品的最新信息(可能为null客户端需要做容错处理)'], + ] + }, { 'name': 'buyGoodsDirect', 'desc': '直接购买(充值,gold)', diff --git a/doc/_common.py b/doc/_common.py index 88568f6c..f8a60368 100644 --- a/doc/_common.py +++ b/doc/_common.py @@ -1208,3 +1208,12 @@ class Sign(object): ['!award', [AwardItem()], '奖励信息'], ] +class ShopTrans(object): + + def __init__(self): + self.fields = [ + ['trans_id', '', 'trans_id'], + ['!params', [''], 'params'], + ['item_id', 0, 'item_id'], + ['item_num', 0, 'item_num'], + ] \ No newline at end of file diff --git a/webapp/controller/ShopController.class.php b/webapp/controller/ShopController.class.php index 014ef306..99056526 100644 --- a/webapp/controller/ShopController.class.php +++ b/webapp/controller/ShopController.class.php @@ -812,6 +812,11 @@ class ShopController extends BaseAuthedController public function buyGoodsNormal() { + $address = $this->_getAddress(); + if (empty($address)) { + $this->_rspErr(2, 'address is empty'); + return; + } $id = getReqVal('id', 0); $token_type = getReqVal('token_type', ''); $goods_num = getReqVal('goods_num', 0); @@ -874,6 +879,11 @@ class ShopController extends BaseAuthedController $this->_rspErr(2, 'he maximum number of purchase restrictions has been reached'); return; } + $sendingTimes = $this->countBuyGoodsRequestTimesByGoodsId($address, $row['goods_id']); + if ($sendingTimes >= $row['limit_num']) { + $this->_rspErr(2, 'The maximum number of purchase restrictions has been reached'); + return; + } } break; default: { @@ -899,6 +909,51 @@ class ShopController extends BaseAuthedController $costItemId = $this->getCostItemIdByTokenType($token_type); switch ($token_type) { + case ShopController::TOKEN_TYPE_GOLD: + $costItems = $this->makeCostItems($costItemId, $goods_num * $need_price); + $lackItem = null; + if (!$this->_hasEnoughItems($costItems, $lackItem)) { + $this->_rspErr(2, $this->_getLackItemErrMsg($lackItem)); + return; + } + + $itemMeta = mt\Item::get($row['goods_id']); + $propertyChgService = new services\PropertyChgService(); + for ($i = 0; $i < $goods_num; $i++) { + $this->internalAddItem($propertyChgService, $itemMeta, $goods_count); + } + $awardService = new services\AwardService(); + $awardService->addItem($row['goods_id'], $goods_num); + ShopBuyRecord::add($id, $goods_num); + $this->_decItems($costItems); + $goodsDto = array( + 'goods_id' => $id, + 'item_id' => $row['goods_id'], + 'price_info' => array( + 'item_id' => $row['goods_id'], + 'cost_list' => array(), + 'discount_begin_time' => phpcommon\datetimeToTimestamp($row['discount_begin']), + 'discount_end_time' => phpcommon\datetimeToTimestamp($row['discount_end']) + ), + 'flag_icon' => $row['tag'], + 'limit_type' => $row['limit_type'], + 'bought_times' => $boughtTimes, + 'total_buy_times' => $row['limit_num'], + ); { + $priceInfo = mt\Item::getPriceInfo($itemMeta); + if (!empty($priceInfo)) { + $goodsDto['price_info'] = $priceInfo['price_info']; + } + } + $propertyChgService->addUserChg(); + $this->_rspData( + array( + 'award' => $awardService->toDto(), + 'property_chg' => $propertyChgService->toDto(), + 'goods_chg' => $goodsDto + ) + ); + break; case ShopController::TOKEN_TYPE_CEG: case ShopController::TOKEN_TYPE_CEC: @@ -922,7 +977,11 @@ class ShopController extends BaseAuthedController )), )); - $this->_rspOK(); + $response['item_id'] = $item_id; + $response['item_num'] = $item_count; + $this->_rspData( + $response + ); break; case ShopController::TOKEN_TYPE_BCEG: @@ -1145,6 +1204,20 @@ class ShopController extends BaseAuthedController } } + private function countBuyGoodsRequestTimesByGoodsId($address, $goodsId) + { + $self = myself(); + if (!$self) return; + + $conn = $self->_getMysql(''); + + $sql = "SELECT COUNT(*) AS cnt FROM t_bc_order WHERE address = '$address' AND item_id = '$goodsId'"; + + $row = $conn->execQuery($sql); + + return $row[0]['cnt']; + } + private function outsideBuy($shopId, $itemId, $itemNum, $costItemId) { $propertyChgService = new services\PropertyChgService(); diff --git a/webapp/models/ShopBuyRecord.php b/webapp/models/ShopBuyRecord.php index 843a4576..ce8e9598 100644 --- a/webapp/models/ShopBuyRecord.php +++ b/webapp/models/ShopBuyRecord.php @@ -5,7 +5,8 @@ namespace models; use mt; use phpcommon\SqlHelper; -class ShopBuyRecord extends BaseModel { +class ShopBuyRecord extends BaseModel +{ public static function find($itemId) { @@ -29,7 +30,7 @@ class ShopBuyRecord extends BaseModel { 'account_id' => myself()->_getAccountId(), ) ); - return array_map(function($row) { + return array_map(function ($row) { $nowDaySeconds = myself()->_getNowDaySeconds(); if (!($row['last_buy_time'] >= $nowDaySeconds && $row['last_buy_time'] <= $nowDaySeconds)) { $row['this_day_buy_times'] = 0; @@ -46,7 +47,7 @@ class ShopBuyRecord extends BaseModel { { $rows = self::all(); $buyRecordHash = array(); - array_walk($rows, function ($row) use(&$buyRecordHash) { + array_walk($rows, function ($row) use (&$buyRecordHash) { $buyRecordHash[$row['item_id']] = $row; }); return $buyRecordHash; @@ -54,8 +55,7 @@ class ShopBuyRecord extends BaseModel { public static function toDto($row) { - return array( - ); + return array(); } public static function add($itemId, $itemNum) @@ -97,4 +97,56 @@ class ShopBuyRecord extends BaseModel { ); } + public static function addWithAddress($address, $itemId, $itemNum) + { + $account_id = ShopBuyRecord::getAccountId($address); + SqlHelper::upsert( + myself()->_getMysql($address), + 't_shop_buy_record', + array( + 'account_id' => $account_id, + 'item_id' => $itemId, + ), + array( + 'this_day_buy_times' => function () { + $nowDaySeconds = myself()->_getNowDaySeconds(); + $cond = " last_buy_time>=${nowDaySeconds} AND last_buy_time<=${nowDaySeconds} + 3600 * 24 "; + return "CASE WHEN (${cond}) THEN this_day_buy_times + 1 ELSE 0 END"; + }, + 'this_week_buy_times' => function () { + $mondaySeconds = myself()->_getMondaySeconds(); + $cond = " last_buy_time>=${mondaySeconds} AND last_buy_time<=${mondaySeconds} + 3600 * 24 * 7 "; + return "CASE WHEN (${cond}) THEN this_week_buy_times + 1 ELSE 0 END"; + }, + 'total_buy_times' => function () { + return 'total_buy_times + 1'; + }, + 'last_buy_time' => myself()->_getNowTime(), + 'modifytime' => myself()->_getNowTime(), + ), + array( + 'account_id' => $account_id, + 'item_id' => $itemId, + 'this_day_buy_times' => 1, + 'this_week_buy_times' => 1, + 'total_buy_times' => 1, + 'last_buy_time' => myself()->_getNowTime(), + 'createtime' => myself()->_getNowTime(), + 'modifytime' => myself()->_getNowTime(), + ) + ); + } + + private static function getAccountId($address) + { + $row = SqlHelper::ormSelectOne( + myself()->_getMysql($address), + 't_user', + array( + 'address' => $address + ) + ); + + return $row['account_id']; + } } diff --git a/webapp/services/BlockChainService.php b/webapp/services/BlockChainService.php index 68bcefde..245d60ba 100644 --- a/webapp/services/BlockChainService.php +++ b/webapp/services/BlockChainService.php @@ -56,7 +56,7 @@ class BlockChainService { die(); return; } - error_log($response); + error_log("gameItemMallBuy:" . $response); $rspObj = json_decode($response, true); if ($rspObj['errcode'] == 0) { $transId = $rspObj['trans_id']; diff --git a/webapp/services/callback/BuyShopGoodsCbService.php b/webapp/services/callback/BuyShopGoodsCbService.php index 289d8b1b..213a9b83 100644 --- a/webapp/services/callback/BuyShopGoodsCbService.php +++ b/webapp/services/callback/BuyShopGoodsCbService.php @@ -4,11 +4,15 @@ namespace services; require_once('mt/Dailyselection.php'); +require_once('ShopAddItemService.php'); +require_once('models/ShopBuyRecord.php'); define('V_ORDER_TYPE_BUY_SHOP_GOODS', 1); use phpcommon\SqlHelper; use mt\Dailyselection; +use mt\Shop; +use models\ShopBuyRecord; class BuyShopGoodsCbService { @@ -39,14 +43,17 @@ class BuyShopGoodsCbService return; } + $order_id = $order['order_id']; $address = $order['address']; - $ext_data = $order['ext_data']; - $goods_id = $order['item_id']; - $goods_num = $order['item_num']; + // $ext_data = $order['ext_data']; + $item_id = $order['item_id']; + $item_num = $order['item_num']; + + error_log("callback buynormal address: $address, order_id: $order_id, goods_id: $item_id, goods_num: $item_num"); $this->_addGoods($address, array( - 'goods_id' => $goods_id, - 'goods_num' => $goods_num, + 'goods_id' => $item_id, + 'goods_num' => $item_num, )); } @@ -65,6 +72,8 @@ class BuyShopGoodsCbService $grid = $ext_data['grid']; $count = $ext_data['count']; + error_log("callback buyDailySelection address: $address, order_id: $order_id, item_id: $item_id, item_num: $item_num, idx: $idx, grid: $grid, count: $count"); + $conn = $self->_getMysql($address); $sql = "SELECT count_$grid FROM t_shop_dailyselection WHERE idx = $idx"; $chk = $conn->execQuery($sql); @@ -72,7 +81,7 @@ class BuyShopGoodsCbService 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"); + error_log("BuyShopGoodsCbService::_buyDailySelection() count not enough, address: $address, order_id: $order_id, item_id: $item_id, item_num: $item_num, idx: $idx, grid: $grid, count: $count"); return; } @@ -85,12 +94,16 @@ class BuyShopGoodsCbService 'goods_num' => $item_num, )); } else { - error_log("BuyShopGoodsCbService::_buyDailySelection() decDailySelectionItem failed, address: $address, order_id: $order_id, idx: $idx, grid: $grid, count: $count"); + error_log("BuyShopGoodsCbService::_buyDailySelection() decDailySelectionItem failed, address: $address, order_id: $order_id, item_id: $item_id, item_num: $item_num, idx: $idx, grid: $grid, count: $count"); } } private function _addGoods($address, $goods) { - error_log("BuyShopGoodsCbService::_addGoods() address: $address, goods: " . json_encode($goods)); + $itemService = new ShopAddItemService(); + $item_id = $goods['goods_id']; + $goods_num = $goods['goods_num']; + $itemService->addItem($address, $item_id, $goods_num); + ShopBuyRecord::addWithAddress($address, $item_id, $goods_num); } }