Commit 3fa4f915 authored by rlgy's avatar rlgy

update

parent 3ada217b
...@@ -95,10 +95,51 @@ class Chain33Business ...@@ -95,10 +95,51 @@ class Chain33Business
public static function transToken($from, $to, $amount, $note = "", $isToken = true, $tokenSymbol = "") public static function transToken($from, $to, $amount, $note = "", $isToken = true, $tokenSymbol = "")
{ {
$service = new Chain33Service(); $service = new Chain33Service();
$result = $service->extractToken($from, $to, $amount, $note, $isToken, $tokenSymbol); $result = $service->transToken($from, $to, $amount, $note, $isToken, $tokenSymbol);
if ($result['code'] == 0) { if ($result['code'] == 0) {
return $result['result']['hash']; return $result['result']['hash'];
} }
return ['code' => -1, 'msg' => $result['msg']]; return ['code' => -1, 'msg' => $result['msg']];
} }
/**
* 获取最新的区块
*/
public static function getLastHeader()
{
$service = new Chain33Service();
$result = $service->getLastHeader();
return $result;
}
/**
* 获取区块hash
*
* @param integer $height
* @return array
*/
public static function getBlockHashByHeight($height)
{
$service = new Chain33Service();
return $service->getBlockHashByHeight($height);
}
/**
* 获取地址下的所有交易记录
*
* @param $addr
* @param integer $flag flag: 0:addr 的所有交易;1:当 addr 为发送方时的交易;2:当 addr 为接收
* 方时的交易。
* @param $count
* @param $direction
* @param integer $height height: 交易所在的 block 高度,-1:表示从最新的开始向后取;大于等于 0 的
* 值,从具体的高度+具体 index 开始取(不包括height)。
* @param integer $index 交易所在 block 中的索引,取值 0--100000
* @return array
*/
public static function getTxByAddr($addr, $flag, $count, $direction, $height, $index)
{
$service = new Chain33Service();
return $service->getTxByAddr($addr, $flag, $count, $direction, $height, $index);
}
} }
<?php
/**
* Created by PhpStorm.
* User: rlgyzhcn
* Date: 18-9-19
* Time: 上午11:44
*/
namespace common\models\psources;
/**
* Class CoinActivity
*
* @property int $id
* @property string $code
* @property string $name
* @property string $end_time
* @package common\models\psources
*/
class CoinActivity extends BaseActiveRecord
{
public static function tableName()
{
return 'coin_activity';
}
public static function isValiable($code)
{
$activity = self::findOne(['code' => strtoupper($code)]);
if ($activity) {
$time = time();
$end = strtotime($activity->end_time);
if ($end > $time) {
return $activity;
}
}
return false;
}
public static function isExists($code)
{
return self::findOne(['code' => $code]);
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: rlgyzhcn
* Date: 18-9-19
* Time: 下午4:37
*/
namespace common\models\psources;
/**
* Class CoinGuessResult
*
* @property integer $id
* @property integer $stage
* @property integer $start_height
* @property integer $end_height
* @property integer $result
* @property integer $is_award
* @package common\models\psources
*/
class CoinGuessResult extends BaseActiveRecord
{
public static function tableName()
{
return 'coin_guess_result';
}
/**
* 获取最后的一条记录(stage max)
*/
public static function getMaxStage()
{
return self::find()->orderBy(['stage' => SORT_DESC])->one();
}
/**
* 获取等待开奖的竞猜
*
* @return CoinGuessResult|null|array
*/
public static function getWaitingAward()
{
return self::find()->where(['is_award' => 0])->orderBy(['stage' => SORT_DESC])->one();
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: rlgyzhcn
* Date: 18-9-19
* Time: 上午11:46
*/
namespace common\models\psources;
/**
* Class CoinMidGuess
*
* @property int $id
* @property int $aid
* @property string $device_id
* @property string $address
* @property string $txhash
* @package common\models\psources
*/
class CoinMidGuess extends BaseActiveRecord
{
public static function tableName()
{
return 'coin_mid_guess';
}
public static function isExists($device_id, $address)
{
return self::findOne(['device_id' => $device_id, 'address' => $address]);
}
}
\ No newline at end of file
...@@ -35,8 +35,11 @@ class Chain33Service ...@@ -35,8 +35,11 @@ class Chain33Service
'jsonrpc' => '2.0', 'jsonrpc' => '2.0',
'id' => 0, 'id' => 0,
'method' => $method, 'method' => $method,
'params' => [$params], 'params' => [],
]; ];
if (!empty($params)) {
$data['params'][] = $params;
}
return json_encode($data); return json_encode($data);
} }
...@@ -126,4 +129,36 @@ class Chain33Service ...@@ -126,4 +129,36 @@ class Chain33Service
]; ];
return $this->send($params, 'Chain33.SendToAddress'); return $this->send($params, 'Chain33.SendToAddress');
} }
/**
* 获取最新的区块
*/
public function getLastHeader()
{
return $this->send([], 'Chain33.GetLastHeader');
}
/**
* 获取区块hash
*
* @param integer $height
* @return array
*/
public function getBlockHashByHeight($height)
{
return $this->send(['height' => $height], 'Chain33.GetBlockHash');
}
public function getTxByAddr($addr, $flag, $count, $direction, $height, $index)
{
$params = [
'addr' => $addr,
'flag' => $flag,
'count' => $count,
'direction' => $direction,
'height' => $height,
'index' => $index
];
return $this->send($params, 'Chain33.GetTxByAddr');
}
} }
<?php
/**
* Created by PhpStorm.
* User: rlgyzhcn
* Date: 18-9-19
* Time: 下午4:21
*/
namespace console\controllers;
use common\business\Chain33Business;
use common\business\CoinBusiness;
use Yii;
use yii\console\Controller;
use common\models\psources\CoinGuessResult;
/**
* Class AwardController
* 竞猜开奖
*
* @package console\controllers
*/
class AwardController extends Controller
{
/**
* 区块链开奖
*/
public function actionIndex()
{
//获取最新的区块高度
$last_header = Chain33Business::getLastHeader();
if ($last_header['code'] != 0) {
Yii::info('获取区块高度失败: ' . $last_header['msg'], __CLASS__);
return 0;
}
$last_header = $last_header['result'];
//获取最新竞猜期数以及区块高度
$last = CoinGuessResult::getMaxStage();
if ($last) {
$stage = $last->stage + 1;
$start_height = $last->end_height;
} else {
//第一次计算开奖
$stage = intval($last_header['height'] / 50);
$start_height = ($stage - 1) * 50;
}
$end_height = $start_height + 50;
//判断区块是否超前了
if ($end_height > $last_header['height']) {
return 0;
}
//获取中奖号码
$hash = Chain33Business::getBlockHashByHeight($end_height);
if ($hash['code'] != 0) {
Yii::info('获取区块hash失败: ' . $hash['msg'], __CLASS__);
return 0;
}
$hash = $hash['result']['hash'];
$hash = substr($hash, -2);
if (!ctype_digit($hash)) {
$hash = hexdec($hash) % 100;
$hash = sprintf("%02d", $hash);
}
//保存开奖结果到数据库
$guess_result = new CoinGuessResult();
$guess_result->stage = $stage;
$guess_result->start_height = $start_height;
$guess_result->end_height = $end_height;
$guess_result->result = $hash;
$guess_result->is_award = 0;
if ($guess_result->save()) {
//添加派奖任务到队列
Yii::info("竞猜开奖成功! [期数]: $stage", __CLASS__);
} else {
Yii::info("保存开奖记录失败! [期数]: $stage", __CLASS__);
}
return 0;
}
}
\ No newline at end of file
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
namespace console\controllers; namespace console\controllers;
use h5\job\JugdeAwardJob;
use Yii; use Yii;
use yii\base\BaseObject; use yii\base\BaseObject;
use backend\jobs\FreezeJob; use backend\jobs\FreezeJob;
...@@ -42,4 +43,10 @@ class DevController extends Controller ...@@ -42,4 +43,10 @@ class DevController extends Controller
$id = Yii::$app->queue->push(new ExtractTokenJob(['cid' => 1])); $id = Yii::$app->queue->push(new ExtractTokenJob(['cid' => 1]));
var_dump($id); var_dump($id);
} }
public function actionJugdeAward()
{
$id = Yii::$app->queue->push(new JugdeAwardJob());
var_dump($id);
}
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Time: 上午10:29 * Time: 上午10:29
*/ */
namespace api\base; namespace h5\base;
use yii\web\Controller; use yii\web\Controller;
...@@ -15,15 +15,25 @@ class BaseController extends Controller ...@@ -15,15 +15,25 @@ class BaseController extends Controller
public $start; public $start;
public $end; public $end;
/**
* @param $action
* @return bool
* @throws \yii\web\BadRequestHttpException
*/
public function beforeAction($action) public function beforeAction($action)
{ {
$this->start = microtime(true); $this->start = microtime(true);
return parent::beforeAction($action); // TODO: Change the autogenerated stub return parent::beforeAction($action);
} }
/**
* @param \yii\base\Action $action
* @param mixed $result
* @return mixed
*/
public function afterAction($action, $result) public function afterAction($action, $result)
{ {
$this->end = microtime(true); $this->end = microtime(true);
return parent::afterAction($action, $result); // TODO: Change the autogenerated stub return parent::afterAction($action, $result);
} }
} }
\ No newline at end of file
...@@ -6,40 +6,22 @@ ...@@ -6,40 +6,22 @@
* Time: 下午1:28 * Time: 下午1:28
*/ */
namespace api\base; namespace h5\base;
use Yii;
use yii\web\Response; use yii\web\Response;
class BaseResponse extends Response class BaseResponse extends Response
{ {
public function send() public function send()
{ {
//错误处理 /**
$excpetion = \Yii::$app->errorHandler->exception; * @var ResponseBuild $response
if ($excpetion !== null) { */
$this->data = [ $response = Yii::$app->response->data;
'code' => $excpetion->getCode(), Yii::$app->response->format = $response->format;
'msg' => $excpetion->getMessage(), Yii::$app->response->data = $response->format();
'line' => $excpetion->getLine(),
'file' => $excpetion->getFile(),
];
}
//TODO 在这里对数据进行format,这样控制器中可以直接return一个array,保存到数据域data中即可,eg:['code'=>0,'data'=>$data]
$data = \Yii::$app->response->data;
if (empty($data)) {
$return['code'] = 1;
$return['msg'] = '数据为空';
} elseif (is_array($data) && !isset($data['code'])) {
$return['code'] = 0;
$return['count'] = count($data);
$return['data'] = $data;
} else {
$return = $data;
}
if (YII_ENV_DEV) {
$return['time'] = \Yii::$app->controller->end - \Yii::$app->controller->start;
}
\Yii::$app->response->data = $return;
parent::send(); parent::send();
} }
} }
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: rlgyzhcn
* Date: 18-9-19
* Time: 上午10:29
*/
namespace h5\base;
use Yii;
use yii\web\Response;
use h5\constant\ResponseConstant;
class ResponseBuild
{
const STATUS_SUCCEED = 0;
const STATUS_PARAMS_NOT_VALIDATE = 1;
const STATUS_INTERNAL_ERROR = 2;
public $code = self::STATUS_PARAMS_NOT_VALIDATE;
public $msg = '';
public $data = [];
public $format;
public function __construct()
{
$this->format = Response::FORMAT_JSON;
}
public function build($code = 0, $msg = '', $data = [])
{
$this->code = $code;
$msgs = ResponseConstant::RESPONSE_MSG;
if (empty($msg)) {
$this->msg = $msgs[$code] ?? '';
} else {
$this->msg = $msg;
}
$this->data = $data;
}
public function format()
{
return ['code' => $this->code, 'msg' => $this->msg, 'data' => $this->data];
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: rlgyzhcn
* Date: 18-9-19
* Time: 上午10:47
*/
namespace h5\constant;
class ResponseConstant
{
const RESPONSE_MSG = [
0 => 'SUCCEED',
1 => 'PARAMS NOT VALIDATE',
2 => 'INTERNAL ERROR',
];
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: rlgyzhcn
* Date: 18-9-19
* Time: 上午10:23
*/
namespace h5\controllers;
use h5\constant\ResponseConstant;
use Yii;
use h5\base\ResponseBuild;
use h5\base\BaseController;
use common\models\psources\CoinMidGuess;
use common\models\psources\CoinActivity;
use common\business\Chain33Business;
class GuessController extends BaseController
{
/**
* 获取新手投注机会
*/
public function actionGetNewBeeChance()
{
$request = Yii::$app->request->post();
$field = ['guessNumber', 'address', 'deviceId', 'activity'];
$guessNumber = '';
$activity = '';
$deviceId = '';
$address = '';
$response = new ResponseBuild();
foreach ($field as $key => $value) {
if (isset($request[$value])) {
$$value = $request[$value];
} else {
$response->build(ResponseBuild::STATUS_PARAMS_NOT_VALIDATE, $value . ' can not be blank');
return $response;
}
}
$activity = strtoupper($activity);
$coin_activity = CoinActivity::isValiable($activity);
if ($coin_activity) {
if (CoinMidGuess::isExists($deviceId, $address)) {
$response->build(-1, '用户已经参与过该活动');
} else {
//打币,返回txhash
$config = Yii::$app->params['h5_activity'][$activity];
$from = $config['from'];
$to = $config['to'];
$isToken = $config['isToken'];
$token = $config['token'];
$amount = intval($config['amount'] * 1e8);
$note = $guessNumber . ' ' . $address;
$result = Chain33Business::transToken($from, $to, $amount, $note, $isToken, $token);
if (is_string($result)) {
//添加数据库记录
$model = new CoinMidGuess();
$model->device_id = $deviceId;
$model->address = $address;
$model->txhash = $result;
$model->aid = $coin_activity->id;
if ($model->save()) {
$response->build(ResponseBuild::STATUS_SUCCEED, '', $result);
}
} else {
$response->build($result['code'], $result['msg']);
}
}
} else {
$response->build(-1, '活动已经失效');
}
return $response;
}
public function actionGetVoteRecordByAddress()
{
$response = new ResponseBuild();
$post = Yii::$app->request->post();
$address = $post['address'] ?? '';
$activity = $post['activity'] ?? '';
if (empty($address) || empty($activity)) {
$response->build(ResponseBuild::STATUS_PARAMS_NOT_VALIDATE, '');
return $response;
}
$coin_activity = CoinActivity::isExists($activity);
if (!$coin_activity) {
$response->build(-1, '活动不存在!');
return $response;
}
$info = CoinMidGuess::findOne(['address' => $address, 'aid' => $coin_activity->id]);
if ($info) {
$txhash = $info->txhash;
$response->build(ResponseBuild::STATUS_SUCCEED, '', $txhash);
} else {
$response->build(1, '记录不存在');
}
return $response;
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: rlgyzhcn
* Date: 18-9-19
* Time: 上午10:08
*/
namespace h5\controllers;
use h5\base\BaseController;
class SiteController extends BaseController
{
public function actionIndex()
{
return "welcome to api!";
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: rlgyzhcn
* Date: 18-9-19
* Time: 下午4:02
*/
namespace h5\job;
use Yii;
use yii\queue\Queue;
use yii\queue\JobInterface;
use yii\base\BaseObject;
use common\business\Chain33Business;
/**
* Class AwardJob
* 发放奖励任务
*
* @package h5\job
*/
class AwardJob extends BaseObject implements JobInterface
{
public $from; //发币地址
public $to; //受币地址
public $is_token;//是否代币
public $token;//代币名称
public $amount;//数量 * 1e8
public $note; //备注
/**
* @param Queue $queue which pushed and is handling the job
*/
public function execute($queue)
{
$result = Chain33Business::transToken($this->from, $this->to, $this->amount, $this->note, $this->is_token,
$this->token);
if (is_string($result)) {
//派奖记录到数据库中
} else {
Yii::info("失败的派奖: [to]: {$this->to}, [amount]: {$this->amount}, [is_token] : {$this->is_token}, [token]: {$this->token}",
__CLASS__);
}
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: rlgyzhcn
* Date: 18-9-19
* Time: 下午6:11
*/
namespace h5\job;
use common\models\psources\CoinGuessResult;
use Yii;
use yii\base\BaseObject;
use yii\queue\Queue;
use yii\queue\JobInterface;
use common\business\Chain33Business;
/**
* Class JugdeAwardJob
* 查询区块交易信息, 分发奖励
*
* @package h5\job
*/
class JugdeAwardJob extends BaseObject implements JobInterface
{
/**
* @param Queue $queue which pushed and is handling the job
* @return integer
*/
public function execute($queue)
{
do {
$loop = true;
//获取最新的未开奖的竞猜
$guess_result = CoinGuessResult::getWaitingAward();
if ($guess_result) {
$config = Yii::$app->params['h5_activity']['ZWG_GUESS_NEWBEE'];
//获取区块间的所有交易(正常竞猜)
$trans_normal = Chain33Business::getTxByAddr($config['from_normal'], 2, 0, 0, $guess_result->end_height,
0);
$trans_normal = Chain33Business::getTxByAddr('1EZxpc1tnKtmQkUHcABXA6Dsn7e7zuhD2p', 2, 0, 0,
$guess_result->end_height,
0);
if ($trans_normal['code'] != 0) {
return 0;
} else {
$trans_normal = $trans_normal['result']['txInfos'];
var_dump($trans_normal);
die();
}
} else {
$loop = false;
}
} while ($loop);
return 0;
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment