// +---------------------------------------------------------------------- namespace App\Services; use App\Models\AccountLogModel; use App\Models\BalanceLogModel; use App\Models\ConfigModel; use App\Models\MemberModel; use App\Models\WalletLogModel; use App\Models\WalletModel; use App\Services\Api\FinanceService; use App\Services\Api\PledgeOrderService; use Illuminate\Support\Facades\DB; use Tighten\SolanaPhpSdk\Connection; use Tighten\SolanaPhpSdk\PublicKey; use Tighten\SolanaPhpSdk\SolanaRpcClient; /** * 钱包管理-服务类 * @package App\Services */ class WalletService extends BaseService { protected $apiUrl = ''; protected $bianUrl = 'http://p2p.binance.com/bapi/c2c/v2/public/c2c/adv/quoted-price'; protected $ouyiApi = 'https://okbs.dongerkj.com/priapi/v3/b2c/deposit/quotedPrice'; // protected $ouyiApi = 'https://www.okx.com/priapi/v3/b2c/deposit/quotedPrice'; protected $config = []; protected $tokenAddress = 'So11111111111111111111111111111111111111111'; // solana protected $usdtTokenAddress = 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'; // solana-usdt // 静态对象 protected static $instance = null; protected $apiUrls = [ // 代币账号 'tokenAccount' => '/v2.0/account/token-accounts', // 账户交易记录 'accountTransfer' => '/v2.0/account/transfer?address=%s&activity_type[]=%s&block_time[]=%s&page=%s&page_size=%s', // 代币账户 'tokenAccounts'=>'/v2.0/account/token-accounts?address=%s&type=%s&hide_zero=true', // 交易详情 'transactionDetail'=>'/v1.0/transaction/%s', ]; /** * 构造函数 */ public function __construct() { $this->config = ConfigService::make()->getConfigOptionByGroup(14); if (empty($this->config)) { return false; } } /** * 静态入口 * @return static|null */ public static function make() { if (!self::$instance) { self::$instance = (new static()); } return self::$instance; } /** * 获取平台钱包地址 * @param int $type 钱包类型:1-充值入账,2-提现出账,默认充值 * @param int $amount 提币时,提币金额验证,充值钱包可忽略 * @param int $coinType 币种:1-USDT * @param boolean $privateKey 是否返回解码的私钥 * @return array|false|mixed、 */ public function getWallet($type = 1, $amount = 0, $coinType = 1, $privateKey = false) { $cacheKey = "caches:wallet:platform:{$type}"; $wallets = RedisService::get($cacheKey); if (empty($wallets)) { $wallets = WalletModel::where(['type' => $type, 'status' => 1, 'mark' => 1])->select(['address', 'private_key'])->get(); $wallets = $wallets ? $wallets->toArray() : []; if ($wallets) { RedisService::set($cacheKey, $wallets, rand(300, 600)); } } if (empty($wallets)) { $this->error = $type == 1 ? 1036 : 1037; return false; } // 需要验证余额 if ($amount > 0) { foreach ($wallets as $item) { $address = isset($item['address']) ? trim($item['address']) : ''; $privateKey = isset($item['private_key']) ? trim($item['private_key']) : ''; $privateKey = $this->getAddressPrivateKey($privateKey, $address, 2); if ($coinType == 1) { $accountData = $this->getUsdtBalance($address); $balance = isset($accountData['amount'])? $accountData['amount'] : 0; } else { $accountData = $this->getUsdtBalance($address); $balance = isset($accountData['amount'])? $accountData['amount'] : 0; } if ($balance >= $amount) { $tokenAccount = isset($accountData['tokenAccount'])? $accountData['tokenAccount'] : ''; return ['address' => $address,'tokenAccount'=>$tokenAccount, 'private_key' => $privateKey]; } } $this->error = 1038; return false; } else { $rand = rand(0, count($wallets) - 1); $wallet = $wallets[$rand]; if ($privateKey) { $wallet['private_key'] = $this->getAddressPrivateKey($wallet['private_key'], $wallet['address'], 2); } return $wallet; } } /** * 获取所有钱包地址 * @return array|mixed */ public function getWalletList() { try { $cacheKey = "caches:wallet:platform:all"; $wallets = RedisService::get($cacheKey); if ($wallets) { return $wallets; } $wallets = WalletModel::where(['status' => 1, 'mark' => 1])->select(['id', 'address', 'type'])->get(); $wallets = $wallets ? $wallets->toArray() : []; if ($wallets) { RedisService::set($cacheKey, $wallets, rand(300, 600)); } return $wallets; } catch (\Exception $exception){ $this->error = $exception->getMessage(); return false; } } /** * 加解密密钥 * @param $key 密钥或加密密钥 * @param $address 地址 * @param $type 类型:1-加密,2-解密 * @return mixed|string|string[] */ public function getAddressPrivateKey($key, $address, $type) { // 加密 if ($type == 1) { $baseStr = base64_encode($key); $baseStr = str_replace(['==', '='], ['-2', '-1'], $baseStr); $str = substr($baseStr, -6, 7) . substr(md5($address), 2, 6) . substr($baseStr, 0, -6); return $str; } // 解密 else { $str1 = substr($key, 12) . substr($key, 0, 6); $str1 = str_replace(['-1', '-2'], ['=', '=='], $str1); return base64_decode($str1); } } /** * 验证地址 * @param $address * @return string */ public function checkAddress($address) { try{ $publicKey = new PublicKey($address); return PublicKey::isOnCurve($publicKey); } catch (\Exception $exception){ $this->error = $exception->getMessage(); return false; } } /** * solana余额 * @param $address * @return false|float|string */ public function getBalance($address, $cache = false) { if (empty($address)) { $this->error = '1018'; return false; } $cacheKey = "caches:wallet:balance:sol_{$address}"; if ($data = RedisService::get($cacheKey) && $cache) { return $data; } if (RedisService::get($cacheKey . '_lock') && $cache) { return false; } try { $sdk = new Connection(new SolanaRpcClient(SolanaRpcClient::MAINNET_ENDPOINT)); $publicKey = new PublicKey($address); $balance = $sdk->getBalance($publicKey); RedisService::set($cacheKey, $balance, rand(3, 5)); RedisService::set($cacheKey . '_lock', true, rand(3, 5)); return $balance; } catch (\Exception $exception) { $this->error = $exception->getMessage(); return false; } } /** * TRC20-USDT余额 * @param $address * @return false|float|string */ public function getUsdtBalance($address, $cache = false) { if (empty($address)) { $this->error = 1018; return false; } $cacheKey = "caches:wallet:balance:trc_usdt_{$address}"; $data = RedisService::get($cacheKey); if ($data && !$cache) { return $data; } try { $apiUrl = ConfigService::make()->getConfigByCode('solana_scan_api', ''); if (empty($apiUrl)) { $this->error = 1040; return false; } $token = ConfigService::make()->getConfigByCode('solana_scan_api_key', ''); if (empty($token)) { $this->error = 1039; return false; } $headers = [ "token: {$token}", ]; $url = $apiUrl . sprintf($this->apiUrls['tokenAccounts'],$address,'token'); $result = curl_get($url, '', $headers, 5); $data = $result ? json_decode($result, true) : []; RedisService::set($cacheKey.'_result', ['url'=>$url,'address'=>$address,'data'=>$data,'result'=>$result,'headers'=>$headers], 600); $accounts = isset($data['data']) ? $data['data'] : []; if(empty($accounts)){ $this->error = 2208; return false; } $balance = 0; $tokenAccount = ''; foreach ($accounts as $item){ if($item['token_address'] = $this->usdtTokenAddress){ $tokenAccount = $item['token_account']; $balance = moneyFormat($item['amount']/pow(10, $item['token_decimals']), 2); } } RedisService::set($cacheKey, ['amount'=> $balance,'tokenAccount'=>$tokenAccount], rand(5, 10)); return ['amount'=> $balance,'tokenAccount'=>$tokenAccount]; } catch (\Exception $exception) { $this->error = $exception->getMessage(); RedisService::set($cacheKey.'_error', ['error'=> $exception->getMessage(),'address'=>$address], 600); return false; } } /** * solana usdt 转账 * @param $to 进账账户 * @param $amount 转账金额 */ public function usdtTransfer($to, $amount, $from = '', $fromPrivateKey = '') { if ($amount <= 0) { $this->error = '2205'; return false; } } /** * 查询交易详情 * @param $txid * @return array|false|mixed */ public function getTradeDetail($txid) { $cacheKey = "caches:wallet:tradeDetail_{$txid}"; $data = RedisService::get($cacheKey); if($data){ return $data; } try { $apiUrl = ConfigService::make()->getConfigByCode('solana_scan_api', ''); if (empty($apiUrl)) { $this->error = 1040; return false; } $token = ConfigService::make()->getConfigByCode('solana_v1_api_key', ''); if (empty($token)) { $this->error = 1039; return false; } $headers = [ "token: {$token}", ]; $url = $apiUrl . sprintf($this->apiUrls['transactionDetail'],$txid); $result = curl_get($url, '', $headers, 5); $data = $result ? json_decode($result, true) : []; RedisService::set($cacheKey.'_result', ['url'=>$url,'txid'=>$txid,'data'=>$data,'result'=>$result,'headers'=>$headers], 600); $tradeData = isset($data['tokenTransfers'][0]) ? $data['tokenTransfers'][0] : []; if(empty($tradeData)){ $this->error = 2210; return false; } RedisService::set($cacheKey, $tradeData, rand(10, 20)); return $tradeData; } catch (\Exception $exception) { $this->error = $exception->getMessage(); RedisService::set($cacheKey.'_error', ['error'=> $exception->getMessage(),'txid'=>$txid], 600); return false; } } /** * 监听充值存币处理 * @param $address 钱包地址 * @param int $accountType 账户类型:1-USDT充值,2-USDT提现 * @param int $page 分页:默认0-轮询分页20页,每页100条记录 * @return array|false */ public function listenWallet($address, $accountType = 1, $page = 0) { // 获取钱包参数 try { $apiUrl = ConfigService::make()->getConfigByCode('solana_scan_api', ''); if (empty($apiUrl)) { $this->error = 1040; return false; } $token = ConfigService::make()->getConfigByCode('solana_scan_api_key', ''); if (empty($token)) { $this->error = 1039; return false; } $headers = [ "token: {$token}", ]; if ($page <= 0) { $page = RedisService::get('caches:wallet:listen_recharge_page_' . $address); $maxPage = ConfigService::make()->getConfigByCode('wallet_listen_max_page', 20); $page = $page > 0 && $page <= $maxPage ? $page : 1; } $limit = ConfigService::make()->getConfigByCode('wallet_listen_limit', 300); $limit = $limit > 10 && $limit <= 100 ? $limit : 100; $time = ConfigService::make()->getConfigByCode('wallet_listen_time', 48); $startTime = $time > 0 ? time() - $time * 3600 : time() - 7200; $url = $apiUrl . sprintf($this->apiUrls['accountTransfer'], $address, 'ACTIVITY_SPL_TRANSFER', $startTime, $page, $limit); $result = curl_get($url, [], $headers, 5); $result = $result ? json_decode($result, true) : []; $datas = isset($result['data']) && is_array($result['data']) ? $result['data'] : []; $status = isset($result['success']) ? $result['success'] : ''; $error = isset($result['error_message']) ? $result['error_message'] : ''; RedisService::set("caches:wallet:listen_{$address}", ['url' => $url, 'page' => $page, 'result' => $result], 7200); if ($status != true || empty($datas)) { $this->error = $error ? '第{$page}页接口错误-' . $error : "第{$page}页没有取到数据"; return false; } RedisService::set('caches:wallet:listen_recharge_page', $page + 1, rand(3600, 7200)); $coinInMin = ConfigService::make()->getConfigByCode('recharge_min_money'); $coinInMin = $coinInMin > 0 ? $coinInMin : 0; $cacheKey = "caches:wallet:listen:{$address}_{$accountType}:"; $dateTime = date('Y-m-d H:i:s'); $success = 0; if ($datas) { foreach ($datas as $v) { $amount = isset($v['amount']) ? intval($v['amount']) : 0; $tokenDecimals = isset($v['token_decimals']) && $v['token_decimals'] ? intval($v['token_decimals']) : 6; $amount = moneyFormat($amount / pow(10, $tokenDecimals), 6); $time = isset($v['block_time']) ? intval($v['block_time']) : 0; $txid = isset($v['trans_id']) ? $v['trans_id'] : ''; $ownerAddress = isset($v['from_address']) ? $v['from_address'] : ''; $toAddress = isset($v['to_address']) ? $v['to_address'] : ''; $tokenAddress = isset($v['token_address']) ? $v['token_address'] : ''; $coinType = 0; $coinName = ''; if ($tokenAddress == $this->tokenAddress) { $coinType = 2; $coinName = 'SOL'; } else if ($tokenAddress == $this->usdtTokenAddress) { $coinType = 1; $coinName = 'USDT'; } if($amount<=0){ echo "【{$dateTime} wallet】账户[{$ownerAddress}]到钱包[{$toAddress}]记录[{$txid}]金额[{$amount}]{$coinName},金额较小不处理\n"; RedisService::set($cacheKey . "{$txid}:error", ['error' => '金额较小不处理', 'data' => $v], 7200); continue; } // 处理交易记录 if (!WalletLogModel::checkExists($txid)) { $log = [ 'owner_address' => $ownerAddress, 'to_address' => $toAddress, 'token_address' => $tokenAddress, 'token_type' => $coinType, 'hash' => $txid, 'amount' => $amount, 'create_time' => $time ? $time : time(), 'update_time' => time(), 'status' => 1, 'mark' => 1, ]; WalletLogModel::insert($log); } // 充值处理(solana-usdt) if ($toAddress == $address && $ownerAddress && $accountType != 2) { if ($amount < $coinInMin) { echo "【{$dateTime} wallet】账户[{$ownerAddress}]到钱包[{$toAddress}]记录[{$txid}]金额[{$amount}]{$coinName},金额较小不处理\n"; RedisService::set($cacheKey . "{$txid}:error", ['error' => '金额较小不处理', 'data' => $v], 7200); continue; } if ($tokenAddress != $this->usdtTokenAddress) { echo "【{$dateTime} recharge】账户[{$ownerAddress}]充值到钱包[{$address}]记录[{$txid}]金额[{$amount}]{$coinName}币种不匹配\n"; RedisService::set($cacheKey . "{$txid}:error", ['error' => '币种不匹配', 'data' => $v], 7200); continue; } if (BalanceLogModel::checkExists($txid)) { echo "【{$dateTime} recharge】账户[{$ownerAddress}]充值到钱包[{$address}]记录[{$txid}]金额[{$amount}]{$coinName}交易已处理过\n"; RedisService::set($cacheKey . "{$txid}:error", ['error' => '交易已处理过', 'data' => $v], 7200); continue; } $memberInfo = MemberModel::where(['wallet_url' => $ownerAddress, 'mark' => 1]) ->select(['id', 'nickname', 'wallet_url', 'usdt', 'sbt']) ->orderBy('id', 'asc') ->first(); $trcUrl = isset($memberInfo['wallet_url']) ? trim($memberInfo['wallet_url']) : ''; $usdt = isset($memberInfo['usdt']) ? floatval($memberInfo['usdt']) : 0; $userId = isset($memberInfo['id']) ? intval($memberInfo['id']) : 0; if (empty($memberInfo)) { echo "【{$dateTime} recharge】账户[{$ownerAddress}]充值到钱包[{$address}]记录[{$txid}]金额[{$amount}]{$coinName}未绑定用户\n"; RedisService::set($cacheKey . "{$txid}:error", ['error' => '未绑定用户', 'data' => $v], 7200); continue; } // 入账 try { DB::beginTransaction(); $updateData = ['update_time' => time()]; $total = $amount; $updateData['usdt'] = DB::raw("usdt + {$total}"); if (!MemberModel::where(['id' => $userId])->update($updateData)) { DB::rollBack(); echo "【{$dateTime} recharge】账户[{$ownerAddress}]充值到钱包[{$address}]记录[{$txid}]金额[{$amount}]入账处理失败\n"; RedisService::set($cacheKey . "{$txid}:error", ['error' => '入账处理失败', 'update' => $updateData, 'member' => $memberInfo, 'data' => $v], 7200); continue; } // 充值明细 $data = [ 'user_id' => $userId, 'order_no' => get_order_num('SR'), 'type' => 1, 'coin_type' => 1, 'money' => $amount, 'actual_money' => $total, 'pay_type' => 20, 'pay_status' => 20, 'pay_at' => date('Y-m-d H:i:s', $time), 'hash' => $txid, 'wallet_url' => $trcUrl, 'pt_wallet_url' => $address, 'date' => date('Y-m-d'), 'create_time' => time(), 'update_time' => time(), 'status' => 2, 'mark' => 1, ]; if (!BalanceLogModel::insert($data)) { DB::rollBack(); echo "【{$dateTime} recharge】账户[{$ownerAddress}]充值到钱包[{$address}]记录[{$txid}]金额[{$amount}]充值明细处理失败\n"; RedisService::set($cacheKey . "{$txid}:error", ['error' => '充值明细处理失败', 'log' => $data, 'member' => $memberInfo, 'data' => $v], 7200); continue; } // 用户账户明细 $log = [ 'user_id' => $userId, 'order_no' => $data['order_no'], 'user_type' => 1, 'type' => 3, 'coin_type' => 1, 'hash' => $txid, 'money' => $amount, 'before_money' => $usdt, 'create_time' => time(), 'update_time' => date('Y-m-d H:i:s'), 'remark' => 'USDT充值', 'status' => 1, 'mark' => 1, ]; if (!AccountLogModel::insert($log)) { DB::rollBack(); echo "【{$dateTime} recharge】账户[{$ownerAddress}]充值到钱包[{$address}]记录[{$txid}]金额[{$amount}]账户明细处理失败\n"; RedisService::set($cacheKey . "{$txid}:error", ['error' => '账户明细处理失败', 'log' => $log, 'member' => $memberInfo, 'data' => $v], 7200); continue; } // 平台进账 FinanceService::make()->saveLog(0, $amount, 1); DB::commit(); $amount = moneyFormat($amount, 2); RedisService::set($cacheKey . "{$txid}:success", ['error' => '处理成功', 'log' => $data, 'member' => $memberInfo, 'data' => $v], 7200); echo "【{$dateTime} recharge】账户[{$ownerAddress}]充值到钱包[{$address}]记录[{$txid}]金额[{$amount}]充值成功\n"; RedisService::clear("caches:wallet:balanceLog:{$txid}"); RedisService::keyDel("caches:balanceLog:total*"); $success++; } catch (\Exception $exception) { DB::rollBack(); RedisService::clear("caches:wallet:balanceLog:{$txid}"); $this->error = "处理错误-" . $exception->getMessage(); echo "处理错误-" . $exception->getMessage(); continue; } } // 提现处理 else if ($ownerAddress == $address && $toAddress && $accountType == 2) { // 处理锁跳过 if (RedisService::get($cacheKey . "{$txid}:lock")) { echo "【{$dateTime} withdraw】提现记录[{$txid}]金额[{$amount}]间隔时间不处理\n"; RedisService::set($cacheKey . "{$txid}:error", ['error' => '间隔时间内不处理', 'data' => $v], 600); continue; } $info = BalanceLogModel::checkExists($txid); $logId = isset($info['id']) ? $info['id'] : 0; $userId = isset($info['user_id']) ? $info['user_id'] : 0; $money = isset($info['money']) ? $info['money'] : 0; $actualMoney = isset($info['actual_money']) ? $info['actual_money'] : 0; $payStatus = isset($info['pay_status']) ? $info['pay_status'] : 0; $status = isset($info['status']) ? $info['status'] : 0; $trcUrl = isset($info['wallet_url']) ? trim($info['wallet_url']) : ''; $walletUrl = isset($info['pt_wallet_url']) ? trim($info['pt_wallet_url']) : ''; if (empty($info) || $logId <= 0 || $userId <= 0) { echo "【{$dateTime} withdraw】账户[{$toAddress}]从[{$address}]提现记录[{$txid}]金额[{$amount}]提现记录不存在\n"; RedisService::set($cacheKey . "{$txid}:error", ['error' => '提现记录不存在', 'data' => $v], 7200); RedisService::set($cacheKey . "{$txid}:lock", ['error' => '提现记录不存在', 'data' => $v], rand(30, 60)); continue; } if ($status != 2) { echo "【{$dateTime} withdraw】账户[{$toAddress}]从[{$address}]提现记录[{$txid}]金额[{$amount}]提现记录未审核\n"; RedisService::set($cacheKey . "{$txid}:error", ['error' => '提现记录未审核', 'data' => $v], 7200); RedisService::set($cacheKey . "{$txid}:lock", ['error' => '提现记录未审核', 'data' => $v], rand(30, 60)); continue; } if ($payStatus == 20) { echo "【{$dateTime} withdraw】账户[{$toAddress}]从[{$address}]提现记录[{$txid}]金额[{$amount}]提现记录已打款\n"; RedisService::set($cacheKey . "{$txid}:error", ['error' => '提现记录已打款', 'data' => $v], 7200); RedisService::set($cacheKey . "{$txid}:lock", ['error' => '提现记录已打款', 'data' => $v], rand(30, 60)); continue; } if ($trcUrl != $toAddress || $walletUrl != $ownerAddress) { echo "【{$dateTime} withdraw】账户[{$toAddress}]从[{$address}]提现记录[{$txid}]金额[{$amount}],提现订单交易地址不匹配\n"; RedisService::set($cacheKey . "{$txid}:error", ['error' => '提现订单交易地址不匹配', 'info' => $info, 'data' => $v], 7200); continue; } // 金额验证 if (abs($actualMoney - $amount) > 1) { echo "【{$dateTime} withdraw】账户[{$toAddress}]从[{$address}]提现记录[{$txid}]金额[{$amount}],提现金额与交易金额不匹配\n"; RedisService::set($cacheKey . "{$txid}:error", ['error' => '提现金额与交易金额不匹配', 'info' => $info, 'data' => $v], 7200); RedisService::set($cacheKey . "{$txid}:lock", ['error' => '提现金额与交易金额不匹配', 'data' => $v], rand(30, 60)); continue; } // 更新状态 try { DB::beginTransaction(); if (!BalanceLogModel::where(['id' => $logId])->update(['pay_status' => 20, 'pay_at' => $dateTime, 'update_time' => time()])) { DB::rollBack(); echo "【{$dateTime} withdraw】账户[{$toAddress}]从[{$address}]提现记录[{$txid}]金额[{$amount}],提现状态更新失败\n"; RedisService::set($cacheKey . "{$txid}:error", ['error' => '提现状态更新失败', 'info' => $info, 'data' => $v], 7200); continue; } // 平台出账 FinanceService::make()->saveLog(0, $amount, 2); DB::commit(); $amount = moneyFormat($amount, 2); RedisService::set($cacheKey . "{$txid}:success", ['error' => '处理成功', 'log' => $log, 'info' => $info, 'data' => $v], 7200); echo "【{$dateTime} withdraw】账户[{$toAddress}]从[{$address}]提现记录[{$txid}]金额[{$amount}],提现成功\n"; RedisService::clear("caches:wallet:balanceLog:{$txid}"); $success++; } catch (\Exception $exception) { DB::rollBack(); RedisService::clear("caches:wallet:balanceLog:{$txid}"); $this->error = "处理错误-" . $exception->getMessage(); echo "处理错误-" . $exception->getMessage(); continue; } } } } $this->error = 1010; return ['success' => $success, 'total' => count($datas)]; } catch (\Exception $exception) { $message = $exception->getMessage(); $this->error = $message; RedisService::set("caches:wallet:listen_error_{$address}", ['error' => $exception->getMessage(), 'trace' => $exception->getTrace()], 600); return false; } } /** * USDT 汇率CNY买/卖价格 * @return string */ public function getUsdtPrice($side='sell',$refresh = true) { // USDT价格 $cacheKey ="caches:wallets:usdtPrice_{$side}"; $price = RedisService::get($cacheKey); if($price && !$refresh){ return $price; } $url = $this->ouyiApi.'?t=' . time() . "&side={$side}"eCurrency=CNY&baseCurrency=USDT"; $result = httpRequest($url, '', 'get', '', 10); $datas = isset($result['data']) ? $result['data'] : []; $datas = isset($datas[0]) ? $datas[0] : []; $price = isset($datas['price']) ? $datas['price'] : 0; if($price<=0){ $price = ConfigService::make()->getConfigByCode("usdt_cny_{$side}_price",7.2); }else{ $price1 = ConfigService::make()->getConfigByCode("usdt_cny_{$side}_price",7.2); $rate = ConfigService::make()->getConfigByCode("usdt_{$side}_rate",1); $price= $rate? moneyFormat($price*(1-$rate/100), 3) : $price; ConfigModel::where(['code'=>"usdt_cny_{$side}_price"])->update(['value'=> $price,'options'=>$price1]); } RedisService::set($cacheKey, $price, rand(30,60)); return $price>0? $price : 0; } }