Files
jyshd_mWtK2/application/api/controller/Market.php
T
li 1b24994e74 feat: 后端全量更新 - 含所有本次需求
- Contract.php: 返回合约账户余额(balance_contract)
- My.php: 地址管理增加BTC/ETH
- AppContract.php: 一键平仓(closeall)
- AppProxy.php: 代理专属注册链接 + 分级权限(L1/L2)
- site.php: 手续费减半(0.018→0.009)
- agent_permission_setup.sql: 代理权限SQL
- crypto_news_crawler.py: 新闻自动采集脚本
2026-03-30 20:16:32 +08:00

753 lines
29 KiB
PHP
Executable File

<?php
namespace app\api\controller;
use app\common\controller\Api;
use think\Db;
use think\Config;
use app\common\library\Sms;
use fast\Random;
/**
* 提现记录
*
* @icon fa fa-circle-o
*/
class Market extends Api
{
protected $noNeedLogin = ['get_coin','get_apt_kline','get_day_kline'];
protected $noNeedRight = '*';
public function _initialize()
{
parent::_initialize();
}
//获取支持交易的币种
public function get_coin()
{
$params = $this->request->post();
$data = Db::name('app_rate')
->where('is_bb','1')
->order('weigh','desc')->select();
//查询所有收藏
$sc_data = Db::name('app_rate_user')->where("user_id", $this->auth->id)->select();
$collect = [];
foreach ($sc_data as $key => $value) {
$collect[] = $value['symbol'];
}
$cesi = Db::name("app_curr_release")->where("status",2)->select();
foreach ($data as $key=>$value)
{
$user_arr = [];
foreach ($cesi as $kk => $vv) {
if($value['name'] == $vv['name']){
$user_arr = explode(",", $vv['cesi_user']);
}
}
if($user_arr && !in_array($this->auth->id, $user_arr)){
unset($data[$key]);
continue;
}
// if($value['id'] == 55 && !in_array($this->auth->id, [3728,3729,3736,3737,3738,3739,3740,3761,4107,3779])){
// unset($data[$key]);
// continue;
// }
if($this->auth->id){
$currency = Db::name('app_currency_user a')
->field('a.*,b.suffix,b.name')
->join('app_currency b','a.curr_id=b.id','left')
->where('b.suffix',$value['symbol'])
->where('a.user_id',$this->auth->id)
->find();
}else{
$currency['num'] = 0;
}
$value['logo_image'] = Config::get("site.image_url").$value['logo_image'];
$value['balance'] = $currency['num'];
$value['exchange_rate'] = Config::get("site.exchange_rate");
if(in_array($value['symbol'], $collect)){
$value['is_sc'] = true;
}else{
$value['is_sc'] = false;
}
$value['close'] = set_number($value['close'], $value['price_jd']);
$data[$key] = $value;
}
$setting = [
'fee' => 0.002,
'min_num' => 10,
'balance' => $currency['num'],
];
// if(isset($params['code']) && $params['code'] == 'sd') {
// $asks = Db::name('app_coin_trade')
// ->field('num,price')
// ->where('coin_id', 19)
// ->whereIn('status', '0,1')
// ->where('cart', 'limit')
// ->where('type', 'sell')
// ->group('price')
// ->order('price', 'asc')
// ->limit(20)->select();
// }else{
// $asks = Db::name('app_coin_trade')
// ->field('num,price')
// ->where('coin_id', 19)
// ->whereIn('status', '0,1')
// ->where('cart', 'limit')
// ->where('type', 'sell')
// ->group('price')
// ->order('price', 'desc')
// ->limit(20)->select();
// }
// foreach ($asks as $key=>$value)
// {
// $num1 = Db::name('app_coin_trade')
// ->where('coin_id',19)
// ->whereIn('status','0,1')
// ->where('cart','limit')
// ->where('type','sell')
// ->where('price',$value['price'])
// ->sum('num');
// $num2 = Db::name('app_coin_trade')
// ->where('coin_id',19)
// ->whereIn('status','0,1')
// ->where('cart','limit')
// ->where('type','sell')
// ->where('price',$value['price'])
// ->sum('have_num');
// $asks[$key]['num'] = sprintf('%.6f', $num1 - $num2);
// }
// $bids = Db::name('app_coin_trade')
// ->field('num,price')
// ->where('coin_id',19)
// ->whereIn('status','0,1')
// ->where('cart','limit')
// ->where('type','buy')
// ->group('price')
// ->order('price','desc')->limit(20)->select();
// foreach ($bids as $key=>$value)
// {
// $num1 = Db::name('app_coin_trade')
// ->where('coin_id',19)
// ->whereIn('status','0,1')
// ->where('cart','limit')
// ->where('type','buy')
// ->where('price',$value['price'])
// ->sum('amount');
// $num2 = Db::name('app_coin_trade')
// ->where('coin_id',19)
// ->whereIn('status','0,1')
// ->where('cart','limit')
// ->where('type','buy')
// ->where('price',$value['price'])
// ->sum('have_num');
// $bids[$key]['num'] = sprintf('%.6f', ($num1 - $num2)/$value['price']);
// }
//
//
// $depth = [
// 'asks' => $asks,
// 'bids' => $bids,
// ];
$this->success('ok',['coin'=>$data,'setting'=>$setting]);
}
//获取合约持仓列表
public function get_order()
{
$params = $this->request->post();
$size = (isset($params['size']))?$params['size']:10;
$symbol = $this->request->post("symbol");
$status = $this->request->post("status",0);
//火币与本土币表分离
$rete = Db::name("app_rate")->where("symbol",$symbol)->find();
if($symbol != 'ttdusdt'){
$table = "app_coin_trade";
$table_order = "app_coin_trade_order";
}else{
$table = "app_coin_trade_evt";
$table_order = "app_coin_trade_order_evt";
}
$w['a.user_id'] = array("eq",$this->auth->id);
if($symbol){
$w['b.symbol'] = array("eq",$symbol);
}
if($status != "all"){
$w['a.status'] = array("eq",$status);
}
$data = Db::name($table.' a')
->field('a.*,b.coinname,b.symbol,b.price_jd,b.market_jd')
->join('app_rate b','a.coin_id = b.id','left')
->where($w)
->order('id','desc')
->paginate($size,false,['query' => request()->param()]);
foreach ($data as $key=>$value)
{
if($value['status'] == '2' || $value['status'] == '1'){
$value['free'] = Db::name($table_order)->where("trade_id",$value['id'])->sum("fee");
$table_orders = Db::name($table_order)->where("trade_id",$value['id'])->find();
$value['price'] = set_number($table_orders['price'], $value['price_jd']);
}else{
$value['price'] = set_number($value['price'], $value['price_jd']);
}
$value['num'] = set_number($value['num'], $value['market_jd']);
$value['amount'] = set_number($value['amount'], $value['price_jd']);
$value['have_num'] = set_number($value['have_num'], $value['market_jd']);
$value['have_usdt'] = set_number($value['have_usdt'], $value['price_jd']);
if($value['have_num']>0 && ($value['status'] == '1' || $value['status'] == '2')){
$value['price'] = set_number(sprintf("%.6f",$value['have_usdt']/$value['have_num']),$value['price_jd']);
}
$value['createtime'] = date('Y-m-d H:i:s',$value['createtime']);
$value['finishtime'] = date('Y-m-d H:i:s',$value['finishtime']);
$value['canceltime'] = date('Y-m-d H:i:s',$value['canceltime']);
$data[$key] = $value;
}
$this->success('success',$data);
}
//币币交易
public function start_order()
{
$params = $this->request->post();
if(!isset($params['cart']) || empty($params['cart'])) //market市价 limit 限价
{
$this->error(__('请选择交易模式'));
}
//实名认证判断
if(!controller("Common")->get_auth()){
$this->error(__("请先完成实名认证"),['jump'=>1]);
}
if(!isset($params['coin_id']) || empty($params['coin_id']))
{
$this->error(__('请选择交易币种'));
}
//火币与本土币表分离
$coin = Db::name('app_rate')->where('id',$params['coin_id'])->find();
if(!$coin) $this->error(__('该交易币种已下架或不存在'));
if($coin['bb_type'] == 2){
$release = Db::name("app_curr_release")->where("rate_id",$coin['id'])->find();
if($release && $release['usdt'] == $coin['close']){
$this->error(__("网络错误,请稍后再试!"));
}
}
if($coin['name'] == "TTD"){
$table = "app_coin_trade_evt";
}else{
$table = "app_coin_trade";
}
if($params['cart'] == 'limit'){
$params['price'] = set_number($params['price'], $coin['price_jd']);
if(!isset($params['price']) || empty($params['price'])){
$this->error(__('限价模式,请输入价格'));
}
}else{
$params['price'] = $coin['close'];
}
if(!isset($params['type']) || empty($params['type'])) //more free
{
$this->error(__('请选择交易方向'));
}
$params['num'] = set_number($params['num'], $coin['market_jd']);
if(!isset($params['num']) || empty($params['num']) || $params['num']<=0)
{
$this->error(__('请输入交易数量'));
}
//redis防重复点击
$symbol = "coin_trade" . $this->auth->id;
$submited = pushRedis($symbol);
if (!$submited) {
$this->error(__("操作频繁"));
}
$coincu = Db::name('app_currency_user a')
->field('a.*,b.suffix,b.name')
->join('app_currency b','a.curr_id=b.id')
->where('a.user_id',$this->auth->id)
->where('b.suffix',$coin['symbol'])->find();
$usdtcu = Db::name('app_currency_user')
->field('num,id')
->where('user_id',$this->auth->id)
->where('curr_id',1)->find();
$market_usdt_num = Config::get("site.market_usdt_num");
if($params['type'] == 'buy')
{
if($params['num'] < $market_usdt_num){
$this->error("最低金额".$market_usdt_num."USDT");
}
if($usdtcu['num'] < $params['num'])
{
lopRedis($symbol);
$this->error(__('余额不足'));
}
$amount = $params['num'];
$params['num'] = set_number(sprintf('%.6f',$amount/$params['price']), $coin['market_jd']);
}else{
if($params['cart'] == 'limit'){
$market_usdt = sprintf("%.6f",$params['price']*$params['num']);
if($market_usdt < $market_usdt_num){
$this->error("最低金额".$market_usdt_num."USDT");
}
}else{
$market_usdt = sprintf("%.6f",$coin['close']*$params['num']);
if($market_usdt < $market_usdt_num){
$this->error("最低金额".$market_usdt_num."USDT");
}
}
if($coincu['num'] < $params['num'])
{
lopRedis($symbol);
$this->error(__('余额不足'));
}
$amount = $params['num'] * $params['price'];
}
$order = [
'order_sn' => 'C'.time().Random::build('numeric',6),
'user_id' => $this->auth->id,
'coin_id' => $coin['id'],
'type' => $params['type'],
'cart' => $params['cart'],
'price' => $params['price'],
'num' => $params['num'],
'amount' => $amount,
'status' => '0',
'createtime' => time(),
];
Db::startTrans();
try {
if($params['type'] == 'buy') {
$lostnum = $usdtcu['num'] - $amount;
$ret = Db::name('app_currency_user')
->where('id', $usdtcu['id'])->update(['num' => $lostnum, 'updatetime' => time()]);
if (!$ret) {
lopRedis($symbol);
Db::rollback();
$this->error(__('系统繁忙'));
}
$detailed[] = [
'user_id' => $this->auth->id,
'curr_id' => 1,
'price' => $amount,
'cart' => '2',
'type' => '7',
'serial_no' => 'C'.time().Random::build('numeric',4),
'order_result' => 'result',
'description' => '币币交易买入',
'createtime' => time(),
'notice' => '币币交易买入',
'before_num' => $usdtcu['num'],
'after_num' => $lostnum,
];
}else{
$lostnum = $coincu['num'] - $params['num'];
$ret = Db::name('app_currency_user')
->where('id', $coincu['id'])->update(['num' => $lostnum, 'updatetime' => time()]);
if (!$ret) {
lopRedis($symbol);
Db::rollback();
$this->error(__('系统繁忙'));
}
$detailed[] = [
'user_id' => $this->auth->id,
'curr_id' => $coincu['curr_id'],
'price' => $params['num'],
'cart' => '2',
'type' => '7',
'serial_no' => 'C'.time().Random::build('numeric',4),
'order_result' => 'result',
'description' => '币币交易卖出',
'createtime' => time(),
'notice' => '币币交易卖出',
'before_num' => $coincu['num'],
'after_num' => $lostnum,
];
}
$ret1 = Db::name($table)->insertGetId($order);
if(!$ret1)
{
lopRedis($symbol);
Db::rollback();
$this->error(__('系统繁忙'));
}
$ret2 = Db::name('app_detailed')->insertAll($detailed);
if(!$ret2)
{
lopRedis($symbol);
Db::rollback();
$this->error(__('系统繁忙'));
}
lopRedis($symbol);
Db::commit();
$return = $order;
$return['id'] = $ret1;
$return['createtime'] = date('Y-m-d H:i:s',$return['createtime']);
$this->success(__('提交成功'),$return);
} catch (Exception $e) {
Db::rollback();
$this->error(__('系统繁忙'));
}
}
//撤销
public function cancel_order()
{
$params = $this->request->post();
if (!isset($params['order_id']) || empty($params['order_id'])) {
$this->error(__('请选择交易单'));
}
if(isset($params['coin_id'])){
//火币与本土币表分离
$coin = Db::name('app_rate')->where('id',$params['coin_id'])->find();
if($coin['name'] == "TTD"){
$table = "app_coin_trade_evt";
}else{
$table = "app_coin_trade";
}
}else{
$table = "app_coin_trade";
}
$order = Db::name($table)
->where('user_id', $this->auth->id)
->where('id', $params['order_id'])
->whereIn('status', '0,1')
->find();
if (!$order) {
$this->error(__('交易单不存在或已完全成交'));
}
$currencys = Db::name('app_rate')->where('id',$order['coin_id'])->find();
//redis防重复点击
$symbol = "cointrade_cancel" . $this->auth->id;
$submited = pushRedis($symbol);
if (!$submited) {
$this->error(__("操作频繁"));
}
$coincu = Db::name('app_currency_user a')
->field('a.*,b.suffix,b.name')
->join('app_currency b','a.curr_id=b.id')
->where('a.user_id',$this->auth->id)
->where('b.suffix',$currencys['symbol'])->find();
$usdtcu = Db::name('app_currency_user')
->field('num,id')
->where('user_id',$this->auth->id)
->where('curr_id',1)->find();
Db::startTrans();
try {
if($order['type'] == 'buy')
{
$diffnum = $order['amount'] - $order['have_usdt'];
$lostnum = sprintf("%.6f",($usdtcu['num'] + $diffnum));
$detaileds = [
'user_id' => $this->auth->id,
'curr_id' => 1,
'price' => $diffnum,
'cart' => '1',
'type' => '7',
'serial_no' => 'C'. time().Random::build('numeric',4),
'order_result' => 'result',
'description' => '币币交易撤销买单',
'createtime' => time(),
'notice' => '币币交易撤销买单',
'before_num' => $usdtcu['num'],
'after_num' => $lostnum,
];
$ret = Db::name('app_currency_user')
->where('id',$usdtcu['id'])->update(['num'=>$lostnum,'updatetime'=>time()]);
if(!$ret)
{
lopRedis($symbol);
Db::rollback();
$this->error(__('系统繁忙'));
}
}else{
$diffnum = $order['num'] - $order['have_num'];
$lostnum = sprintf("%.6f",($coincu['num'] + $diffnum));
$detaileds = [
'user_id' => $this->auth->id,
'curr_id' => $coincu['curr_id'],
'price' => $diffnum,
'cart' => '1',
'type' => '7',
'serial_no' => 'C'. time().Random::build('numeric',4),
'order_result' => 'result',
'description' => '币币交易撤销买单',
'createtime' => time(),
'notice' => '币币交易撤销买单',
'before_num' => $coincu['num'],
'after_num' => $lostnum,
];
$ret = Db::name('app_currency_user')
->where('id',$coincu['id'])->update(['num'=>$lostnum,'updatetime'=>time()]);
if(!$ret)
{
lopRedis($symbol);
Db::rollback();
$this->error(__('系统繁忙'));
}
}
$ret1 = Db::name($table)->where('id',$order['id'])
->update(['status'=>'3','canceltime'=>time()]);
if(!$ret1)
{
lopRedis($symbol);
Db::rollback();
$this->error(__('系统繁忙'));
}
$ret2 = Db::name('app_detailed')->insert($detaileds);
if(!$ret2)
{
lopRedis($symbol);
Db::rollback();
$this->error(__('系统繁忙'));
}
lopRedis($symbol);
Db::commit();
$this->success(__('已撤销'));
} catch (Exception $e) {
Db::rollback();
$this->error(__('系统繁忙'));
}
}
/**
* 获取订单详情
*/
public function order_con()
{
$user_id = $this->auth->id;
$id = $this->request->post("id");
$coin_id = $this->request->post("coin_id");
$coin = Db::name('app_rate')->where('id',$coin_id)->find();
if($coin['name'] == "TTD"){
$table = "app_coin_trade_evt";
$order_table = "app_coin_trade_order_evt";
//APT交易
$order = Db::name($table." a")->field("a.id,a.order_sn,a.type,a.cart,a.num,a.price,a.amount,a.status,a.createtime,b.name as curr_name,b.symbol,b.market_jd,b.price_jd,b.bb_type")
->join("app_rate b","a.coin_id=b.id","left")
->where("a.id",$id)
->where("a.user_id",$user_id)
->find();
if(empty($order)){
$this->error("订单不存在");
}
$count_price = 0;$count_num = 0;$fee_num = 0;$junjia = "0";$fee_type = 1;
if($order['status'] != 0){
//订单详情
$order_deatil = Db::name($order_table)->field("id,price,amount,num,fee,fee_type,createtime")->where("trade_id",$order['id'])->select();
if($order_deatil){
foreach ($order_deatil as $key => $value) {
$count_price += $value['num'];
$count_num += $value['amount'];
$fee_num += $value['fee'];
$fee_type = $value['fee_type'];
$value['createtime'] = date("m-d H:i",$value['createtime']);
$value['num'] = set_number($value['num'], $order['market_jd']);
$value['price'] = set_number($value['price'], $order['price_jd']);
$value['amount'] = set_number($value['amount'], $order['price_jd']);
$order_deatil[$key] = $value;
}
$junjia = sprintf("%.6f",$count_num/$count_price);
}
if($fee_type == 1){
//手续费为交易币种
if($order['type'] == "sell"){
//卖
$fee_curr = "USDT";
}else{
$fee_curr = $order['curr_name'];
}
}else{
//手续费为平台币
$fee_curr = "APT";
}
$order['fee_curr'] = $fee_curr;
$order['detail'] = $order_deatil;
}
$order['createtime'] = date("m-d H:i",$order['createtime']);
$order['count_price'] = set_number(sprintf("%.6f",$count_price), $order['market_jd']);
$order['count_num'] = set_number(sprintf("%.6f",$count_num),$order['price_jd']);
$order['junjia'] = set_number($junjia, $order['price_jd']);
$order['num'] = set_number($order['num'],$order['market_jd']);
$order['amount'] = set_number($order['amount'],$order['price_jd']);
$order['price'] = set_number($order['price'],$order['price_jd']);
$order['fee_num'] = $fee_num;
}else{
//其他币种
$order = Db::name("app_coin_trade a")->field("a.id,a.order_sn,a.type,a.cart,a.num,a.price,a.amount,a.status,a.createtime,b.name as curr_name,b.symbol,b.market_jd,b.price_jd,b.bb_type")
->join("app_rate b","a.coin_id=b.id","left")
->where("a.id",$id)
->where("a.user_id",$user_id)
->find();
if(empty($order)){
$this->error("订单不存在");
}
$count_price = 0;$count_num = 0;$fee_num = 0;$junjia = "0";$fee_type = 1;
if($order['status'] != 0){
//订单详情
$order_deatil = Db::name("app_coin_trade_order")->field("id,price,amount,num,fee,fee_type,createtime")->where("trade_id",$order['id'])->select();
if($order_deatil){
foreach ($order_deatil as $key => $value) {
$count_price += $value['num'];
$count_num += $value['amount'];
$fee_num += $value['fee'];
$fee_type = $value['fee_type'];
$value['createtime'] = date("m-d H:i",$value['createtime']);
$value['num'] = set_number($value['num'], $order['market_jd']);
$value['price'] = set_number($value['price'], $order['price_jd']);
$value['amount'] = set_number($value['amount'], $order['price_jd']);
$order_deatil[$key] = $value;
}
$junjia = sprintf("%.6f",$count_num/$count_price);
}
if($fee_type == 1){
//手续费为交易币种
if($order['type'] == "sell"){
//卖
$fee_curr = "USDT";
}else{
$fee_curr = $order['curr_name'];
}
}else{
//手续费为平台币
$fee_curr = "APT";
}
$order['fee_curr'] = $fee_curr;
$order['detail'] = $order_deatil;
}
$order['createtime'] = date("m-d H:i",$order['createtime']);
$order['count_price'] = set_number(sprintf("%.6f",$count_price), $order['market_jd']);
$order['count_num'] = set_number(sprintf("%.6f",$count_num),$order['price_jd']);
$order['junjia'] = set_number($junjia, $order['price_jd']);
$order['fee_num'] = $fee_num;
$order['num'] = set_number($order['num'],$order['market_jd']);
$order['amount'] = set_number($order['amount'],$order['price_jd']);
$order['price'] = set_number($order['price'],$order['price_jd']);
}
$this->success("ok",$order);
}
//获取K线数据
public function get_apt_kline()
{
$params = $this->request->post();
$period = (!isset($params['period']))?'1min':$params['period'];
if($period == '60min') $period = '1h';
if($period == '1day') $period = '24h';
if($period == '1mon') $period = '1month';
$symbol = $this->request->post("symbol","aptusdt");
$coin = Db::name('app_rate')->where('symbol',$symbol)->find();
if($coin['name'] == "TTD"){
$table = "evt_k_".$period;
}else{
$table = "bb_k_".$period;
}
$data = Db::name($table)->limit(200)
->where('symbol',$symbol)
->order('ts','desc')
->select();
$last_names = array_column($data,'ts');
array_multisort($last_names,SORT_ASC,$data);
foreach ($data as $key=>$value)
{
$value['id'] = (float)$value['ts'];
// $value['time'] = (float)($value['ts']*1000);
// $value['ts'] = (float)($value['ts']*1000);
$value['open'] = (float)$value['open'];
$value['close'] = (float)$value['close'];
$value['high'] = (float)$value['high'];
$value['low'] = (float)$value['low'];
$value['amount'] = (float)$value['amount'];
$value['vol'] = (float)$value['vol'];
// $value['volume'] = (float)$value['vol'];
$value['count'] = (float)$value['count'];
unset($value['ts']);
// $value['isBarClosed'] = true;
// $value['isLastBar'] = false;
unset($value['symbol']);
$data[$key] = $value;
}
$plase = Db::name("app_curr_release")->where("name",$coin['name'])->find();
if($plase && $period="1min"){
$ress = json_decode(http_curl('https://api.huobi.pro/market/history/kline?period=1day&size=1&symbol='.$symbol,'get'),true);
if(!$ress || !isset($ress['data']) || empty($ress['data']))
{
//
}else {
$data1 = $ress['data'];
if($plase['is_tk'] == 1 && $data){
$price = $data1[0]['close'];
$trademulte_json = json_decode($coin['trademulte_json'],true);
$hour = date('H');
$minute = date('i');
if(!empty($trademulte_json)){
foreach ($trademulte_json as $key => $value) {
$time1 = explode('-', $key);
$time2 = explode(':', $time1[0]);
$time3 = explode(':', $time1[1]);
if ($hour >= $time2[0] && $hour <= $time3[0]) {
if (($hour == $time3[0] && $minute > $time3[1]) || ($hour == $time2[0] && $minute < $time2[1])) continue;
$price = $price*$value;
$data[count($data)-1]['close'] = $price;
break;
}
}
}
}
}
}
$this->success('ok',$data);
}
//获取K线数据
public function get_day_kline()
{
$params = $this->request->post();
$symbol = $this->request->post("symbol");
$coin = Db::name('app_rate')->where('symbol',$symbol)
->field('symbol,high,open,close,low')
->find();
$this->success('ok',$coin);
}
}