ShanduiBonusServices.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. <?php
  2. namespace App\Service\Bus;
  3. use App\Model\Transit\TransitWalletBlack;
  4. use App\Model\Transit\TransitUserWallet;
  5. use App\Model\Transit\TransitWalletTradeList;
  6. use App\Service\Transit\TransitWalletCoinServices;
  7. use App\Service\RsaServices;
  8. use App\Library\Log;
  9. use Hyperf\DbConnection\Db;
  10. use App\Service\Bus\TronServices;
  11. class ShanduiBonusServices
  12. {
  13. // 转账逻辑处理
  14. public function handleGrant($data){
  15. $transitWalletCoin_services = new TransitWalletCoinServices();
  16. $transitWalletCoinList = $transitWalletCoin_services->IDList();
  17. // 黑钱包列表
  18. $black_list = TransitWalletBlack::pluck('black_wallet');
  19. if(empty($black_list)){
  20. $black_list = [];
  21. }else{
  22. $black_list = $black_list->toArray();
  23. }
  24. $success_count = 0;
  25. $rsa_services = new RsaServices();
  26. foreach ($data as $k => $v) {
  27. if(empty($transitWalletCoinList[$v->transit_wallet_id.strtolower($v->coin_name)])){
  28. $this->log('shanduibonus','----------闪兑钱包币种未设置,交易明细rid:'.$v->rid.',闪兑钱包ID:'.$v->transit_wallet_id.',转入币名:'.$v->coin_name.'----------');
  29. }else{
  30. if(in_array($v->sendback_address,$black_list)){
  31. $save_data = [];
  32. $save_data['process_status'] = 6; //黑钱包
  33. $save_data['process_comments'] = '黑钱包'; //处理备注
  34. TransitWalletTradeList::where('rid',$v->rid)->update($save_data);
  35. continue;
  36. }
  37. //币种设置
  38. $coin_data = $transitWalletCoinList[$v->transit_wallet_id.strtolower($v->coin_name)];
  39. if($v->amount < $coin_data['min_transit_amount']){
  40. $save_data = [];
  41. $save_data['process_status'] = 7; //金额不符合要求
  42. $save_data['process_comments'] = '转入金额小于最低转入金额:'.$coin_data['min_transit_amount']; //处理备注
  43. TransitWalletTradeList::where('rid',$v->rid)->update($save_data);
  44. continue;
  45. }
  46. if($v->amount > $coin_data['max_transit_amount']){
  47. $save_data = [];
  48. $save_data['process_status'] = 7; //金额不符合要求
  49. $save_data['process_comments'] = '转入金额大于最高转入金额:'.$coin_data['max_transit_amount']; //处理备注
  50. TransitWalletTradeList::where('rid',$v->rid)->update($save_data);
  51. continue;
  52. }
  53. // 未设置汇率
  54. if(empty($coin_data['exchange_rate']) || $coin_data['exchange_rate'] == 0){
  55. $this->log('shanduibonus','----------闪兑钱包币种未设置汇率,交易明细rid:'.$v->rid.',闪兑钱包ID:'.$v->transit_wallet_id.',转入币名:'.$v->coin_name.'----------');
  56. continue;
  57. }
  58. $amount = bcsub($v->amount * $coin_data['exchange_rate'],$coin_data['kou_out_amount'],2); //校验金额
  59. if($amount <= 0){
  60. $save_data = [];
  61. $save_data['process_status'] = 7; //金额不符合要求
  62. $save_data['process_comments'] = '计算汇率减去扣回款金额后为负数,汇率:'.$coin_data['exchange_rate'].'。扣回款金额:'.$amount; //处理备注
  63. TransitWalletTradeList::where('rid',$v->rid)->update($save_data);
  64. continue;
  65. }
  66. if($coin_data['exchange_rate'] > 10){
  67. $save_data = [];
  68. $save_data['process_status'] = 2; //交易失败
  69. $save_data['process_comments'] = '超过最大汇率10,当前:'.$coin_data['exchange_rate']; //处理备注
  70. TransitWalletTradeList::where('rid',$v->rid)->update($save_data);
  71. continue;
  72. }
  73. $address = $v->sendback_address; //接收钱包地址
  74. //查询是否有预支
  75. $userdata = TransitUserWallet::where('chain_type','trc')->where('wallet_addr',$address)->first();
  76. $huan_yuzhi_amount = 0;
  77. if(empty($userdata)){
  78. $userdata_exit = 1; //不存在,用于后面判断插入还是更新
  79. }else{
  80. $userdata_exit = 2; //存在,用于后面判断插入还是更新
  81. //如果预支未还
  82. if($userdata->need_feedback_sxf > 0){
  83. $huan_yuzhi_amount = min($amount,$userdata->need_feedback_sxf);
  84. $amount = max(bcsub($amount,$userdata->need_feedback_sxf,2),0);
  85. }
  86. }
  87. $time = nowDate();
  88. $OWNER_ADDRESS = $v->send_wallet; //出款钱包
  89. //解密-佣金钱包私钥
  90. $OWNER_PRIVATE_KEY = $rsa_services->privateDecrypt($v->send_wallet_privatekey);
  91. if(empty($OWNER_PRIVATE_KEY)){
  92. $this->log('shanduibonus','----------闪兑钱包私钥错误,交易明细rid:'.$v->rid.',闪兑钱包ID:'.$v->transit_wallet_id.',转入币名:'.$v->coin_name.'----------');
  93. continue;
  94. }
  95. $sendback_coin_name = $coin_data['out_coin_name']; //出款币名
  96. $success_status = 0;
  97. $balance = 0;
  98. $api_key = config('apikey.gridapikey');
  99. $apikeyrand = $api_key[array_rand($api_key)];
  100. //波场接口API
  101. $TronApiConfig = [
  102. 'url' => 'https://api.trongrid.io',
  103. 'api_key' => $apikeyrand,
  104. ];
  105. $tron = new TronServices($TronApiConfig,$OWNER_ADDRESS,$OWNER_PRIVATE_KEY);
  106. #方法一:tronweb方法,偶尔获取不成功,间隔1秒重试3次
  107. for($i=1; $i<=3; $i++){
  108. if($sendback_coin_name == 'trx'){
  109. $balance = $tron->getAccount($OWNER_ADDRESS);
  110. }else{
  111. // 获取TRC20余额
  112. $balance = $tron->newGetTrc20Balance($OWNER_ADDRESS,'USDT','TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t');
  113. }
  114. if($balance && $balance > 0){
  115. break;
  116. }
  117. sleep(1);
  118. }
  119. //如果还获取不成功,换接口获取
  120. if(empty($balance) || $balance == 0){
  121. $url = 'https://apilist.tronscanapi.com/api/accountv2?address='.$OWNER_ADDRESS;
  122. $tronapikey = config('apikey.tronapikey');
  123. $apikeyrand = $tronapikey[array_rand($tronapikey)];
  124. $heders = [
  125. "TRON-PRO-API-KEY:".$apikeyrand
  126. ];
  127. $res = Get_Pay($url,null,$heders);
  128. $balance = 0;
  129. if(empty($res)){
  130. $balance = 0;
  131. }else{
  132. $res = json_decode($res,true);
  133. if(isset($res['balance'])){
  134. //查询余额
  135. if(isset($res['withPriceTokens'])){
  136. $withPriceTokens = $res['withPriceTokens'];
  137. if($sendback_coin_name == 'trx'){
  138. $trxkey = array_search('_', array_column($withPriceTokens, 'tokenId'));
  139. if($trxkey >= 0){
  140. $balance = $withPriceTokens[$trxkey]['amount'];
  141. }
  142. }else{
  143. // 获取TRC20余额
  144. $usdtkey = array_search('TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t', array_column($withPriceTokens, 'tokenId'));
  145. if(is_bool($usdtkey)){
  146. $balance = 0;
  147. }else{
  148. $balance = calculationExcept($withPriceTokens[$usdtkey]['balance'] ,$withPriceTokens[$usdtkey]['tokenDecimal']);
  149. }
  150. }
  151. }
  152. }
  153. }
  154. }
  155. if($balance >= $amount){
  156. $save_data = [];
  157. $save_data['process_status'] = 8; //转帐中
  158. $save_data['process_comments'] = '转帐中'; //处理备注
  159. $save_data['sendback_coin_name'] = $sendback_coin_name; //出款币名
  160. $save_data['sendback_amount'] = $amount; //出款数额
  161. TransitWalletTradeList::where('rid',$v->rid)->update($save_data);
  162. if($sendback_coin_name == 'trx'){
  163. // TRX转账,默认是permission=0也就是owner,私钥需要为owner的私钥
  164. if($amount > 0){
  165. //如果金额超过了10汇率,检测不处理
  166. if(bcdiv($amount,$v->amount,2) > 10){
  167. $save_data = [];
  168. $save_data['process_status'] = 2; //交易失败
  169. $save_data['process_comments'] = '超过最大汇率10,当前:'.$coin_data['exchange_rate']; //处理备注
  170. TransitWalletTradeList::where('rid',$v->rid)->update($save_data);
  171. continue;
  172. }
  173. //php必须安装gmp扩展才能转账
  174. $res = $tron->trxTransaction($address,$amount);
  175. $trid = $res['data']['txid'];
  176. $troncode = $res['code'];
  177. //多签如果不是owner,调用下面这种api方式,注意要先查询私钥对应地址的permissionid
  178. // $apiparam = [
  179. // 'fromaddress' => $OWNER_ADDRESS,
  180. // 'toaddress' => $address,
  181. // 'sendamount' => $amount,
  182. // 'pri1' => $OWNER_PRIVATE_KEY,
  183. // 'permissionid' => 2,
  184. // ];
  185. // $res = Get_Pay('xxx/sendtrxbypermid',$apiparam);
  186. // if(empty($res)){
  187. // $troncode = 400;
  188. // }else{
  189. // $res = json_decode($res,true);
  190. // if(empty($res['code'])){
  191. // $troncode = 400;
  192. // }else{
  193. // if($res['code'] == 200){
  194. // $troncode = 200;
  195. // $trid = $res['data']['txid'];
  196. // }else{
  197. // $troncode = 400;
  198. // }
  199. // }
  200. // }
  201. }else{
  202. $trid = '扣预支后为0,不转账';
  203. $troncode = 200;
  204. }
  205. $type = 1;
  206. $success_status = 1;
  207. }else{
  208. // TRC20转账
  209. if($amount > 0){
  210. $res = $tron->trc20Transaction($address,$amount,'USDT');
  211. $trid = $res['data']['txid'];
  212. $troncode = $res['code'];
  213. }else{
  214. $trid = '扣预支后为0,不转账';
  215. $troncode = 200;
  216. }
  217. $type = 2;
  218. $success_status = 1;
  219. }
  220. }
  221. if($success_status == 1){
  222. if($troncode == 200){
  223. $save_data = [];
  224. $save_data['process_status'] = 9; //自动转账
  225. $save_data['process_comments'] = '转帐成功,扣预支:'.$huan_yuzhi_amount.',汇率:'.$coin_data['exchange_rate']; //处理备注
  226. $save_data['sendback_tx_hash'] = $trid; //出款交易hash
  227. $save_data['sendback_contract_ret'] = 'SUCCESS'; //出款交易hash
  228. $save_data['sendback_time'] = $time; //出款时间
  229. $save_data['current_exchange_rate'] = $coin_data['exchange_rate']; //当前汇率
  230. $save_data['current_huan_yuzhi_amount'] = $huan_yuzhi_amount; //扣预支金额
  231. TransitWalletTradeList::where('rid',$v->rid)->update($save_data);
  232. //记录会员汇总
  233. if($userdata_exit == 1){
  234. $save_data = [];
  235. $save_data['chain_type'] = 'trc';
  236. $save_data['wallet_addr'] = $address;
  237. $save_data['total_transit_usdt'] = $v->amount;
  238. $save_data['last_transit_time'] = $time;
  239. TransitUserWallet::insert($save_data);
  240. }else{
  241. $save_data = [];
  242. $save_data['total_transit_usdt'] = bcadd($userdata['total_transit_usdt'], $v->amount,2);
  243. $save_data['last_transit_time'] = $time;
  244. $save_data['need_feedback_sxf'] = bcsub($userdata['need_feedback_sxf'], $huan_yuzhi_amount,2);
  245. $save_data['send_feedback_sxf'] = bcadd($userdata['send_feedback_sxf'], $huan_yuzhi_amount,2);
  246. TransitUserWallet::where('rid',$userdata->rid)->update($save_data);
  247. };
  248. $success_count++;
  249. }else{
  250. $save_data = [];
  251. $save_data['process_status'] = 1; //待兑换
  252. $save_data['process_comments'] = '待兑换'; //处理备注
  253. TransitWalletTradeList::where('rid',$v->rid)->update($save_data);
  254. }
  255. }else{
  256. $save_data = [];
  257. $save_data['process_status'] = 10; //余额不足
  258. $save_data['process_comments'] = '余额不足,当前:'.$balance; //处理备注
  259. TransitWalletTradeList::where('rid',$v->rid)->update($save_data);
  260. // $this->log('shanduibonus','----------余额不足,需人工处理----------');
  261. }
  262. }
  263. }
  264. // $this->log('shanduibonus','----------结束执行:闪兑钱包逻辑处理。成功转账'.$success_count.'条----------');
  265. return ['code' => 200,'msg'=>'成功转账'.$success_count.'条'];
  266. }
  267. /**
  268. * 记入日志
  269. * @param $log_title [日志路径]
  270. * @param $message [内容,不支持数组]
  271. * @param $remarks [备注]
  272. */
  273. protected function log($log_title,$message,$remarks='info'){
  274. Log::get($remarks,$log_title)->info($message);
  275. }
  276. }