game2006api/webapp/services/MarketService.php
aozhiwei 00b4310f06 1
2022-04-04 10:37:47 +08:00

303 lines
9.8 KiB
PHP

<?php
namespace services;
require_once('mt/MarketGoods.php');
require_once('mt/MarketBatch.php');
require_once('mt/Item.php');
require_once('mt/BlindBox.php');
require_once('mt/WhiteList.php');
require_once('mt/Currency.php');
require_once('mt/Hero.php');
require_once('mt/Parameter.php');
require_once('models/BoxOrder.php');
require_once('models/Nft.php');
require_once('models/BuyRecord.php');
require_once('phpcommon/bchelper.php');
use phpcommon;
use phpcommon\SqlHelper;
use models\BoxOrder;
use models\Nft;
use models\BuyRecord;
class MarketService extends BaseService {
const CURRENCY_DECIMALS = 8;
const PRICE_PAD = '0000000000';
const PRESALE_NOT_STARTED = 0;
const PRESALE_PREPARE = 1;
const PRESALE_STARTED = 2;
const PRESALE_SOLD_OUT = 3;
const FUNCID_PRESALE = 1;
const FUNCID_SHOP = 2;
const TOKEN_SALT = 'B8E6BD4F-FD7B-E2B8-6688-80A2D8632064';
public static function isTestMode()
{
return isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443 && SERVER_ENV == _TEST;
}
public static function isValidToken($account, $token)
{
$deToken = base64_decode($token);
if (empty($deToken)) {
return false;
}
if (empty($account)) {
return false;
}
$data = json_decode($deToken, true);
$sign = md5(self::TOKEN_SALT .
$data['account'] .
$data['rand'] .
$data['nonce'] .
$data['createtime']);
if ($sign == $data['sign']) {
return phpcommon\isSameAddress($data['account'], $account);
}
return false;
}
public static function buyBoxVerifySignature($buyerAddress,
$type,
$paymentTokenAddress,
$price,
$nonce,
$signature)
{
$params = array(
'c' => 'BcService',
'a' => 'buyBoxVerifySignature',
'type' => $type,
'paymentTokenAddress' => $paymentTokenAddress,
'price' => $price,
'nonce' => $nonce,
'signature' => $signature
);
$url = self::getWeb3ServiceUrl();
$response = '';
if (!phpcommon\HttpClient::get
($url,
$params,
$response)) {
phpcommon\sendError(500, 'server internal error');
die();
return;
}
error_log(json_encode(array(
'_REQUEST' => $_REQUEST,
'params' => $params,
'response' => $response
)));
$data = json_decode($response, true);
if (getXVal($data, 'errcode', 0) != 0) {
phpcommon\sendError(1, 'Signature verification failed');
die();
return;
} else {
$recovered = getXVal($data, 'recovered', '');
if (!phpcommon\isSameAddress($recovered, $buyerAddress)) {
phpcommon\sendError(1, 'Signature verification failed');
die();
return;
}
}
}
public static function auth($account, $tips, $nonce, $signature)
{
$params = array(
'c' => 'BcService',
'a' => 'authVerifySignature',
'tips' => $tips,
'nonce' => $nonce,
'signature' => $signature
);
$url = self::getWeb3ServiceUrl();
$response = '';
if (!phpcommon\HttpClient::get
($url,
$params,
$response)) {
myself()->_rspErr(500, 'server internal error');
die();
return;
}
error_log(json_encode(array(
'_REQUEST' => $_REQUEST,
'params' => $params,
'response' => $response
)));
$data = json_decode($response, true);
if (getXVal($data, 'errcode', 0) != 0) {
myself()->_rspErr(1, 'Signature verification failed');
die();
return;
} else {
$recovered = getXVal($data, 'recovered', '');
if (!phpcommon\isSameAddress($recovered, $account)) {
myself()->_rspErr(1, 'Signature verification failed');
die();
return;
} else {
myself()->_rspData(array(
'token' => self::genToken($account, $nonce)
));
}
}
}
private static function getWeb3ServiceUrl()
{
$web3ServiceCluster = require_once('../config/web3service.cluster.php');
return $web3ServiceCluster[rand() % count($web3ServiceCluster)];
}
private static function genToken($account, $nonce)
{
$data = array(
'account' => $account,
'rand' => uniqid(),
'nonce' => $nonce,
'createtime' => myself()->_getNowTime(),
);
$data['sign'] = md5(self::TOKEN_SALT .
$data['account'] .
$data['rand'] .
$data['nonce'] .
$data['createtime']);
return base64_encode(json_encode($data));
}
public static function getPreSaleInfo($account)
{
$currBatchMeta = mt\MarketBatch::getCurrentBatch();
if (!$currBatchMeta) {
return self::getDefaultPresaleInfo();
}
$countdown = mt\MarketBatch::getCountdown($currBatchMeta);
$soldNum = min(BoxOrder::getSoldNum($currBatchMeta['id']),
$currBatchMeta['number_of_props']);
$totalNum = $currBatchMeta['number_of_props'];
$buyed = self::isTestMode() ?
0 : BoxOrder::isBuyed($account, $currBatchMeta['id']);
$title = '';
$state = self::PRESALE_PREPARE;
if ($countdown > 0) {
$state = self::PRESALE_PREPARE;
} else {
if ($soldNum >= $totalNum) {
$title = self::escapeString($currBatchMeta['end_title']);
$state = self::PRESALE_SOLD_OUT;
} else {
$title = self::escapeString($currBatchMeta['begin_title']);
$state = self::PRESALE_STARTED;
}
}
$presaleInfo = array(
'batch_id' => $currBatchMeta['batch_id'],
'countdown' => $countdown,
'sold_num' => $soldNum,
'total_num' => $totalNum,
'state' => $state,
'title' => $title,
'hint' => self::escapeString($currBatchMeta['hint']),
'buyable_list' => array(),
//'buyed' => $buyed
);
$batchMetas = mt\MarketGoods::getBatchMetas($currBatchMeta['batch_id']);
if ($batchMetas) {
foreach ($batchMetas as $meta) {
$boxId = phpcommon\genBoxId($currBatchMeta['id'],
$meta['id'],
$meta['item_id']);
if (!$buyed) {
if ($currBatchMeta['white_list'] &&
!mt\WhiteList::inWhiteList($account)) {
continue;
}
array_push($presaleInfo['buyable_list'],
array(
'box_id' => $boxId
));
}
}
}
return $presaleInfo;
}
private static function getDefaultPresaleInfo()
{
$title = self::escapeString(
mt\Parameter::getVal('pre_sale_not_started_title', ''));
$hint = self::escapeString(
mt\Parameter::getVal('pre_sale_not_started_hint', ''));
$presaleInfo = array(
'batch_id' => 0,
'countdown' => 0,
'sold_num' => 0,
'total_num' => 0,
'state' => self::PRESALE_NOT_STARTED,
'title' => $title,
'hint' => $hint,
'buyable_list' => array(),
//'buyed' => 0
);
return $presaleInfo;
}
private static function escapeString($str)
{
return str_replace("\n", '\n', $str);
}
public static function openBox($itemMeta, &$items)
{
if ($itemMeta['type'] == mt\Item::BLIND_BOX_TYPE) {
//group1:100|group2:100|group3:100
$groups = StrHelper::parseList($itemMeta['param1'], array('|', ':'));
foreach ($groups as $tuple) {
$rndVal = rand() % 100;
if ($rndVal <= $tuple[1]) {
$boxMeta = mt\BlindBox::randItem($itemMeta['id'], $tuple[0]);
if ($boxMeta) {
$nftMeta = mt\Item::get($boxMeta['item_id']);
if ($nftMeta) {
$tokenType = Nft::getTokenType($nftMeta);
if ($tokenType != Nft::NONE_TYPE) {
$need = (empty($items) || $tuple[1] >= 100) ? 1 : 0;
array_push($items, array(
'need' => $need,
'item_id' => $nftMeta['id'],
'token_type' => $tokenType,
));
}
}
}
}
}
} else {
$tokenType = Nft::getTokenType($itemMeta);
if ($tokenType != Nft::NONE_TYPE) {
array_push($items, array(
'need' => 1,
'item_id' => $itemMeta['id'],
'token_type' => $tokenType,
));
}
}
}
}