WithDrawInfoController.php 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077
  1. <?php
  2. namespace App\Http\Controllers\Game;
  3. use App\Facade\TableName;
  4. use App\Game\GlobalUserInfo;
  5. use App\Http\helper\NumConfig;
  6. use App\Models\AccountsInfo;
  7. use App\Models\Treasure\GameScoreLocker;
  8. use App\Notification\TelegramBot;
  9. use App\Util;
  10. use App\Utility\SetNXLock;
  11. use GuzzleHttp\Client;
  12. use GuzzleHttp\Exception\RequestException;
  13. use Illuminate\Http\Request;
  14. use Illuminate\Support\Facades\DB;
  15. use Illuminate\Support\Facades\Hash;
  16. use Illuminate\Support\Facades\Log;
  17. use Illuminate\Support\Facades\Validator;
  18. class WithDrawInfoController
  19. {
  20. public function FreeWithDrawInfo(Request $request)
  21. {
  22. $user = $request->user();
  23. $userScoreData = GlobalUserInfo::getScoreDataByUserID($user->UserID);
  24. if(!$userScoreData['Recharge']){
  25. $totalWithdraw = max($userScoreData['InsureScore'],200);
  26. if($userScoreData['InsureScore']<200){
  27. //第一种状态,我免费领了10块钱,但是金额不足40,点进去页面填信息后点击提现,提示我去玩游戏
  28. return apiReturnSuc(['state' => 1, 'total' => $totalWithdraw,'InsureScore' => $userScoreData['InsureScore']]);
  29. }else{
  30. //第二种状态,我免费金额足够40,提现按钮会点亮,告知用户点击进去
  31. return apiReturnSuc(['state' => 2, 'total' => $totalWithdraw,'InsureScore' => $userScoreData['InsureScore']]);
  32. }
  33. }else{
  34. //第四种状态,VIP状态下,金额不足了,进度条颜色红色,按钮灰色(不可点击),次日整个消失
  35. if($userScoreData['InsureScore']<20){
  36. return apiReturnSuc(['state' => 4, 'total' => max($userScoreData['InsureScore'],200),'InsureScore' => max($userScoreData['InsureScore'],200)]);
  37. }else{
  38. //第三种状态,进去完成了充值未提现,提现按钮会高光,引导用户完成提现
  39. return apiReturnSuc(['state' => 3, 'total' => max($userScoreData['InsureScore'],200),'InsureScore' => max($userScoreData['InsureScore'],200)]);
  40. }
  41. }
  42. }
  43. public function WithDrawRecord(Request $request)
  44. {
  45. $user = $request->user();
  46. $UserID=$user->UserID;
  47. // $paypass = $request->input('paypass');
  48. // if (!empty($user->InsurePass)&&!Hash::check($paypass,$user->InsurePass)) {
  49. // return apiReturnFail(['web.user.paypass_fail', 'A senha original está errada, digite-a novamente.'], '', 2);
  50. // }
  51. $scoreType = intval($request->input('score_type', -1));
  52. if (!in_array($scoreType, [-1, 0, 1], true)) {
  53. return apiReturnFail(['web.withdraw.params_error', 'score_type must be -1, 0 or 1'], [], 422);
  54. }
  55. $sort = strtolower($request->input('sort', 'desc'));
  56. $sort = in_array($sort, ['asc', 'desc']) ? $sort : 'desc';
  57. $sortBy = strtolower($request->input('sort_by', 'createdate'));
  58. $pageSize = intval($request->input('page_size', 10));
  59. if ($pageSize <= 0) {
  60. $pageSize = 100;
  61. }
  62. $query = DB::table('QPAccountsDB.dbo.OrderWithDraw')
  63. ->where('UserID', $UserID);
  64. if ($scoreType !== -1) {
  65. $query->where('score_type', $scoreType);
  66. }
  67. $allowedSortColumns = [
  68. 'withdraw' => 'WithDraw',
  69. 'createdate' => 'CreateDate',
  70. ];
  71. $sortColumn = $allowedSortColumns[$sortBy] ?? 'CreateDate';
  72. $list = $query
  73. ->selectRaw("CreateDate,OrderId,[State],WithDraw,ServiceFee,PixType,score_type")
  74. ->where('CreateDate', '>=', date('Y-m-d', strtotime('-30 day')))
  75. ->orderBy($sortColumn, $sort)
  76. ->paginate($pageSize);
  77. return apiReturnSuc($list);
  78. }
  79. public function GetWithDrawBaseInfo(Request $request)
  80. {
  81. $user = $request->user();
  82. $UserID=$user->UserID;
  83. // $paypass = $request->input('paypass');
  84. //
  85. // if (empty($user->InsurePass)||!Hash::check($paypass,$user->InsurePass)) {
  86. // return apiReturnFail(['web.user.paypass_fail', 'A senha original está errada, digite-a novamente.'], '', 2);
  87. // }
  88. $dbh = DB::connection()->getPdo();
  89. $sql="DECLARE @return_value int
  90. set nocount on use QPAccountsDB
  91. EXEC @return_value = GSP_GR_GetWithDrawBaseInfo '$UserID'
  92. SELECT 'ReturnValue' = @return_value";
  93. // echo $sql;die;
  94. $stmt = $dbh->prepare($sql);
  95. $stmt->execute();
  96. $retval = $stmt->fetch(\PDO::FETCH_ASSOC);
  97. $retval['srate']=env('CONFIG_24680_RATE',1);
  98. return apiReturnSuc($retval);
  99. }
  100. public function GoWithDraw(Request $request)
  101. {
  102. $user = $request->user();
  103. $UserID=$user->UserID;
  104. // $paypass = $request->input('paypass');
  105. //
  106. // if (empty($user->InsurePass)||!Hash::check($paypass,$user->InsurePass)) {
  107. // return apiReturnFail(['web.user.paypass_fail', 'A senha original está errada, digite-a novamente.'], '', 2);
  108. // }
  109. $score=$request->input('score',0);
  110. if(!$score||is_float($score)||$score<=0){
  111. return apiReturnFail(['web.withdraw.score_fail', 'Amount must be an integer value.']);
  112. }
  113. $redisKey = 'withdraw_'.$UserID;
  114. if (!SetNXLock::getExclusiveLock($redisKey)) {
  115. return apiReturnFail(['web.withdraw.try_again_later','Tente novamente mais tarde']);
  116. }
  117. GameScoreLocker::where('UserID',$UserID)->delete();
  118. $dbh = DB::connection()->getPdo();
  119. // $score=$score*NumConfig::NUM_VALUE;
  120. $sql="DECLARE @return_value int
  121. set nocount on use QPAccountsDB
  122. EXEC @return_value = GSP_GR_GetWithDraw '$UserID','$score'
  123. SELECT 'ReturnValue' = @return_value";
  124. // echo $sql;die;
  125. $stmt = $dbh->prepare($sql);
  126. $stmt->execute();
  127. SetNXLock::release($redisKey);
  128. $retval = $stmt->fetch(\PDO::FETCH_ASSOC);
  129. try {
  130. // set @ret = 1 --可提额度不足
  131. // set @ret = 2 --低于最低可提现金额
  132. // set @ret = 3 --高于最高可提现金额
  133. // set @ret = 4 --超过每天提现次数上限
  134. // set @ret = 5 --身上钱不够
  135. // set @ret = 6 --开在游戏里面
  136. // set @ret = 7 --未充值的用户TX额度
  137. if (isset($retval['ReturnValue'])) {
  138. $ReturnValue = $retval['ReturnValue'];
  139. // set @ret = 1 -- Insufficient withdrawal amount
  140. // set @ret = 2 -- Lower than the minimum withdrawal amount
  141. // set @ret = 3 -- Higher than the maximum withdrawal amount
  142. // set @ret = 4 -- Exceeded the daily withdrawal limit
  143. // set @ret = 5 -- Not enough money on hand
  144. // set @ret = 6 -- Opened in the game
  145. // set @ret = 7 -- Undeposited user TX amount
  146. $errors = [
  147. [],
  148. ['web.withdraw.no_withdraw_value', "The withdrawable amount is not enough"],
  149. ['web.withdraw.too_low', 'Lower than the minimum withdrawal amount'],
  150. ['web.withdraw.too_high', 'Higher than the maximum withdrawal amount'],
  151. ['web.withdraw.day_max', 'Exceeded the daily withdrawal limit'],
  152. ['web.withdraw.no_enouth_score', 'Not enough money on hand'],
  153. ['web.withdraw.in_game', 'Sorry, You\'re in game for now'],
  154. ['web.withdraw.no_deposit', ' You need deposit first!'],
  155. ];
  156. return apiReturnFail($errors[$ReturnValue], [], $ReturnValue == 7 ? 777 : 301);
  157. }else{
  158. return apiReturnSuc($retval);
  159. }
  160. }catch (\Exception $e){
  161. TelegramBot::getDefault()->sendProgramNotify("WithDraw Error:", var_export($retval,true).':'.$e->getTraceAsString());
  162. return apiReturnSuc($retval);
  163. }
  164. }
  165. public function saveCpf(Request $request)
  166. {
  167. // $user = $request->user();
  168. // $UserID=$user->UserID;
  169. //
  170. // $account = $request->Account ?: '';
  171. // $phone = $request->Phone ?: '';
  172. // $email = $request->Email ?: '';
  173. // $PixNum = $request->PixNum ?: '';
  174. //
  175. // if(!Util::validateCpf($PixNum)){
  176. // return apiReturnFail(['withdraw.account.tip.cpf_error','Cpf error format']);
  177. // }
  178. //
  179. // $redisKey = 'Api_updateAccountsPayInfo_'.$UserID;
  180. // $lock = SetNXLock::getExclusiveLock($redisKey);
  181. // if (!$lock) {
  182. // return apiReturnFail(['web.withdraw.try_again_later','Tente novamente mais tarde']);
  183. // }
  184. // $exist = DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')->where('UserID', $UserID)->first();
  185. //
  186. // if ($exist) {
  187. // DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')->where('UserID', $UserID)->update(['PixNum' => $PixNum]);
  188. // } else {
  189. //
  190. // $data = ['BankUserName' => $account, 'PhoneNumber' => $phone, 'EmailAddress' => $email, 'UserID' => $UserID, 'PixNum' => $PixNum, 'Achieves' => '', 'HistoryWithDraw' => 0];
  191. // DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  192. // ->insert($data);
  193. // }
  194. // SetNXLock::release($redisKey);
  195. return apiReturnSuc();
  196. }
  197. public function MexWithDrawInfo(Request $request)
  198. {
  199. $user = $request->user();
  200. $UserID=$user->UserID;
  201. $paypass = $request->input('paypass');
  202. $PixType = $request->input('PixType');;
  203. $BankNO = $request->input('account');
  204. $AccountsBank = $request->input('account');
  205. $BankUserName = $request->input('userName');
  206. $PhoneNumber = $request->input('phone');
  207. $EmailAddress = $request->input('email');
  208. $IFSCNumber = $request->input('IFSCNumber');
  209. // $PANNumber = $request->input('PAN');
  210. // $AdhaarNumber = $request->input('adhaar');
  211. // $BranchBank = $request->input('branceBank');
  212. $BranchBank = $request->input('bank');//银行编号
  213. $PixNum = $request->input('account');
  214. Util::WriteLog("mexwithdraw",$request->all());
  215. if(isset($EmailAddress)&&!empty($EmailAddress)){
  216. $validator = Validator::make(
  217. ['email' => $EmailAddress],
  218. ['email' => 'required|email']
  219. );
  220. if ($validator->fails()) {
  221. return apiReturnFail(['web.user.email_fail','Wrong email format']);
  222. }
  223. }
  224. if (!$AccountsBank || $AccountsBank == 'undefined') {
  225. return apiReturnFail(['web.bank.account_empty', 'The bank account cannot be empty']);
  226. }
  227. if (!(strlen($AccountsBank) == 16 || strlen($AccountsBank) == 18)) {
  228. return apiReturnFail(['web.bank.account_invalid_length', 'The bank number must have 16 or 18 digits']);
  229. }
  230. if ($IFSCNumber && strlen($IFSCNumber) != 18) {
  231. return apiReturnFail(['web.bank.clabe_invalid_length', 'The Clabe number must have 18 digits']);
  232. }
  233. if (!$BankUserName || $BankUserName == 'undefined') {
  234. return apiReturnFail(['web.bank.username_empty', 'The name cannot be empty']);
  235. }
  236. if (!$BranchBank || $BranchBank == 'undefined') {
  237. return apiReturnFail(['web.bank.branch_empty', 'The branch code cannot be empty']);
  238. }
  239. if (strlen($AccountsBank) == 16) {
  240. $PixType = 2;
  241. }
  242. if (strlen($AccountsBank) == 18) {
  243. $PixType = 1;
  244. }
  245. $redisKey = 'withDrawInfo_withDrawInfo_' . $UserID;
  246. if (!SetNXLock::getExclusiveLock($redisKey)) {
  247. return apiReturnFail(['web.bank.try_again_later', 'Please try again later']);
  248. }
  249. if (!$UserID) {
  250. Log::info('miss UserID', $request->all());
  251. SetNXLock::release($redisKey);
  252. return apiReturnFail(['web.bank.missing_userid', 'params error']);
  253. }
  254. if (empty($PixType)) {
  255. SetNXLock::release($redisKey);
  256. return apiReturnFail(['web.bank.pix_type_missing', 'The PIX type is missing']);
  257. }
  258. // 验证PixNum绑定次数
  259. if (!empty($PixNum)) {
  260. $BindCount = DB::table(TableName::QPRecordDB() . 'RecordBankCardBind')
  261. ->where('BankCard', $PixNum)
  262. ->lock('WITH(NOLOCK)')
  263. ->count();
  264. if ($BindCount >= 3) {
  265. SetNXLock::release($redisKey);
  266. return apiReturnFail(['web.bank.cpf_used_multiple_times', 'The CPF number has been used multiple times and cannot be saved'], [], 302);
  267. }
  268. }
  269. // 验证玩家信息
  270. if (!empty($user->InsurePass)&&!Hash::check($paypass,$user->InsurePass)) {
  271. return apiReturnFail(['web.user.paypass_fail', 'A senha original está errada, digite-a novamente.'], '', 2);
  272. }
  273. if ($PixType < 10 && false) {
  274. $data = compact('PixType', 'BankUserName', 'PhoneNumber', 'EmailAddress', 'PixNum');
  275. } else {
  276. $data = compact('PixType', 'BankUserName','IFSCNumber', 'PhoneNumber', 'EmailAddress','BankNO', 'AccountsBank','BranchBank','PixNum');
  277. $PixNum = $BankNO;
  278. }
  279. foreach ($data as $key => &$val) {
  280. $data[$key] = trim($val);
  281. }
  282. unset($val);
  283. $AccountWithDrawInfo = DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  284. ->lock('WITH(NOLOCK)')
  285. ->where('UserID', $UserID)
  286. ->first();
  287. if (!$AccountWithDrawInfo) {
  288. $data['UserID'] = $UserID;
  289. $data['Achieves'] = 0;
  290. $data['HistoryWithDraw'] = 0;
  291. try {
  292. DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  293. ->where('UserID', $UserID)
  294. ->insert($data);
  295. } catch (\Exception $e) {
  296. Log::error('insert AccountWithDrawInfo failed', ['data' => $data]);
  297. }
  298. } else {
  299. DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  300. ->where('UserID', $UserID)
  301. ->update($data);
  302. }
  303. // 添加绑定记录
  304. if (empty($AccountWithDrawInfo->PixNum) || $AccountWithDrawInfo->PixNum != $PixNum) {
  305. try {
  306. DB::table(TableName::QPRecordDB() . 'RecordBankCardBind')
  307. ->insert([
  308. 'UserID' => $UserID,
  309. 'BankCard' => $PixNum ?: '',
  310. 'BindDate' => now()
  311. ]);
  312. } catch (\Exception $e) {
  313. Log::error('insert RecordBankCardBind failed', ['data' => $data]);
  314. }
  315. }
  316. SetNXLock::release($redisKey);
  317. return apiReturnSuc();
  318. }
  319. public function RuWithDrawInfo(Request $request)
  320. {
  321. $user = $request->user();
  322. $UserID=$user->UserID;
  323. $paypass = $request->input('paypass');
  324. $PixType = $request->input('PixType');;
  325. $BankNO = $request->input('account');
  326. $BankUserName = $request->input('userName');
  327. $PhoneNumber = $request->input('phone');
  328. // $EmailAddress = $request->input('email');
  329. // $IFSCNumber = $request->input('IFSCNumber');
  330. // $PANNumber = $request->input('PAN');
  331. // $AdhaarNumber = $request->input('adhaar');
  332. // $BranchBank = $request->input('branceBank');
  333. $BranchBank = $request->input('bank');//银行编号
  334. $PixNum = $BankNO;
  335. $AccountsBank = $BankNO;
  336. Util::WriteLog("ruwithdraw",$request->all());
  337. if (!$BankUserName || $BankUserName == 'undefined') {
  338. return apiReturnFail(['web.bank.username_empty', 'The name cannot be empty']);
  339. }
  340. if($PixType==1) {
  341. if (!$AccountsBank || $AccountsBank == 'undefined') {
  342. return apiReturnFail(['web.bank.account_empty', 'The bank account cannot be empty']);
  343. }
  344. if (!(strlen($AccountsBank) == 16 )) {
  345. return apiReturnFail(['web.bank.account_invalid_length', 'The bank number must have 16 digits']);
  346. }
  347. // if (!(strlen($IFSCNumber) == 11 && $IFSCNumber)) {
  348. // return apiReturnFail(['web.bank.clabe_invalid_length', 'The Clabe number must have 18 digits']);
  349. // }
  350. }else{
  351. // 墨西哥 +52 手机号 10 位(可带区号总长 12 位);其他地区 11 位
  352. $digits = preg_replace('/\D/', '', $PhoneNumber ?? '');
  353. $isMexico = (env('COUNTRY_CODE', '52') === '52');
  354. $valid = $isMexico
  355. ? (strlen($digits) === 10 || strlen($digits) === 12)
  356. : (strlen($digits) === 11);
  357. if (!$PhoneNumber || !$valid) {
  358. return apiReturnFail(['withdraw.account.tip.phone_error', $isMexico ? 'The phone number must be 10 digits (Mexico)' : 'The phone number is error']);
  359. }
  360. if (!$BranchBank || $BranchBank == 'undefined') {
  361. return apiReturnFail(['web.bank.branch_empty', 'The branch code cannot be empty']);
  362. }
  363. }
  364. $redisKey = 'withDrawInfo_withDrawInfo_' . $UserID;
  365. if (!SetNXLock::getExclusiveLock($redisKey)) {
  366. return apiReturnFail(['web.bank.try_again_later', 'Please try again later']);
  367. }
  368. if (!$UserID) {
  369. Log::info('miss UserID', $request->all());
  370. SetNXLock::release($redisKey);
  371. return apiReturnFail(['web.bank.missing_userid', 'params error']);
  372. }
  373. if (empty($PixType)) {
  374. SetNXLock::release($redisKey);
  375. return apiReturnFail(['web.bank.pix_type_missing', 'The PIX type is missing']);
  376. }
  377. // 验证PixNum绑定次数
  378. if (!empty($PixNum)) {
  379. $BindCount = DB::table(TableName::QPRecordDB() . 'RecordBankCardBind')
  380. ->where('BankCard', $PixNum)
  381. ->lock('WITH(NOLOCK)')
  382. ->count();
  383. if ($BindCount >= 3) {
  384. SetNXLock::release($redisKey);
  385. return apiReturnFail(['web.bank.cpf_used_multiple_times', 'The CPF number has been used multiple times and cannot be saved'], [], 302);
  386. }
  387. }
  388. // 验证玩家信息
  389. if (!empty($user->InsurePass)&&!Hash::check($paypass,$user->InsurePass)) {
  390. return apiReturnFail(['web.user.paypass_fail', 'A senha original está errada, digite-a novamente.'], '', 2);
  391. }
  392. $data = compact('PixType', 'BankUserName', 'PhoneNumber','BankNO', 'AccountsBank','BranchBank','PixNum');
  393. $PixNum = $BankNO;
  394. foreach ($data as $key => &$val) {
  395. $data[$key] = trim($val);
  396. }
  397. unset($val);
  398. $AccountWithDrawInfo = DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  399. ->lock('WITH(NOLOCK)')
  400. ->where('UserID', $UserID)
  401. ->first();
  402. if (!$AccountWithDrawInfo) {
  403. $data['UserID'] = $UserID;
  404. $data['Achieves'] = 0;
  405. $data['HistoryWithDraw'] = 0;
  406. try {
  407. DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  408. ->where('UserID', $UserID)
  409. ->insert($data);
  410. } catch (\Exception $e) {
  411. Log::error('insert AccountWithDrawInfo failed', ['data' => $data]);
  412. }
  413. } else {
  414. DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  415. ->where('UserID', $UserID)
  416. ->update($data);
  417. }
  418. // 添加绑定记录
  419. if (empty($AccountWithDrawInfo->PixNum) || $AccountWithDrawInfo->PixNum != $PixNum) {
  420. try {
  421. DB::table(TableName::QPRecordDB() . 'RecordBankCardBind')
  422. ->insert([
  423. 'UserID' => $UserID,
  424. 'BankCard' => $PixNum ?: '',
  425. 'BindDate' => now()
  426. ]);
  427. } catch (\Exception $e) {
  428. Log::error('insert RecordBankCardBind failed', ['data' => $data]);
  429. }
  430. }
  431. SetNXLock::release($redisKey);
  432. return apiReturnSuc();
  433. }
  434. public function withDrawInfo(Request $request)
  435. {
  436. // return apiReturnFail('params error');
  437. $user = $request->user();
  438. $UserID=$user->UserID;
  439. // $UserID = (int)$request->globalUser->UserID;//$request->input('UserID');
  440. // $RequestDynamicPass = $request->input('DynamicPass');
  441. $PixType = $request->input('cbPixType');
  442. $BankUserName = urldecode($request->input('userName'));
  443. $EmailAddress = $request->input('email');
  444. $PixNum = $request->input('PixNum');
  445. if(!empty($EmailAddress))$EmailAddress=Util::cleanEmptyString($EmailAddress);
  446. if(!empty($PixNum))$PixNum=Util::cleanEmptyString($PixNum);
  447. if (!empty($EmailAddress)&&!Util::validateEmail($EmailAddress)) {
  448. return apiReturnFail(['web.user.email_fail','Wrong email format']);
  449. }
  450. $redisKey = 'withDrawInfo_withDrawInfo_'.$UserID;
  451. if (!SetNXLock::getExclusiveLock($redisKey)) {
  452. Util::WriteLog("withdrawInfo",[1, $request->all()]);
  453. return apiReturnFail(['web.withdraw.try_again_later','Tente novamente mais tarde']);
  454. }
  455. if (!$UserID) {
  456. Util::WriteLog("withdrawInfo",[2, $request->all()]);
  457. Log::info('miss UserID', $request->all());
  458. SetNXLock::release($redisKey);
  459. return apiReturnFail(['web.withdraw.params_error','params error']);
  460. }
  461. if (empty($PixType)) {
  462. Util::WriteLog("withdrawInfo",[3, $request->all()]);
  463. SetNXLock::release($redisKey);
  464. return apiReturnFail(["web.withdraw.pix_type_missing",'O tipo PIX está ausente']);
  465. }
  466. // 验证PixNum绑定次数
  467. // if (!empty($PixNum)) {
  468. // $BindCount = DB::table(TableName::QPRecordDB() . 'RecordBankCardBind')
  469. // ->where('BankCard', $PixNum)
  470. // ->lock('WITH(NOLOCK)')
  471. // ->count();
  472. // if ($BindCount >= 6) {
  473. // Util::WriteLog("withdrawInfo",[4, $request->all()]);
  474. // SetNXLock::release($redisKey);
  475. // return apiReturnFail(['web.withdraw.cpf_number_used','O número do CPF foi usado várias vezes e não pode ser salvo'], [], 302);
  476. // }
  477. // }
  478. if ($PixType==1) {
  479. // 验证 cashapp
  480. if (!empty($PixNum)) {
  481. // 如果 PixNum 第一个字符不是 "$",则在前面添加 "$"
  482. if (substr($PixNum, 0, 1) !== '$') {
  483. $PixNum = '$' . $PixNum;
  484. }
  485. // 构建 cash.app URL
  486. $cashAppUrl = 'https://cash.app/' . $PixNum;
  487. try {
  488. // 使用 stream context 来获取 HTTP 响应头
  489. $context = stream_context_create([
  490. 'http' => [
  491. 'method' => 'GET',
  492. 'header' => "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\r\n",
  493. 'ignore_errors' => true
  494. ]
  495. ]);
  496. $htmlContent = @file_get_contents($cashAppUrl, false, $context);
  497. // 检查 HTTP 响应头中的状态码
  498. if ($htmlContent === false || (isset($http_response_header) && preg_match('/HTTP\/\d\.\d\s+404/', implode("\n", $http_response_header)))) {
  499. Util::WriteLog("withdrawInfo", [5, $request->all(), 'Invalid cashapp: ' . $PixNum]);
  500. SetNXLock::release($redisKey);
  501. return apiReturnFail(['web.withdraw.invalid_cashapp', 'Invalid CashApp account']);
  502. }
  503. if ($htmlContent !== false) {
  504. // 去除空格换行,转换成一行字符串
  505. $htmlContent = preg_replace('/\s+/', '', $htmlContent);
  506. Util::WriteLog("withdrawInfo", [5, $request->all(), 'CashApp verification response: ' . $htmlContent]);
  507. // 检查响应内容中是否包含 "404 Not Found"
  508. if (stripos($htmlContent, '404NotFound') !== false) {
  509. Util::WriteLog("withdrawInfo", [5, $request->all(), 'Invalid cashapp: ' . $PixNum]);
  510. SetNXLock::release($redisKey);
  511. return apiReturnFail(['web.withdraw.invalid_cashapp', 'Invalid CashApp account']);
  512. }
  513. }
  514. } catch (\Exception $e) {
  515. // 其他异常也记录日志但不阻止流程
  516. Util::WriteLog("withdrawInfo", [5, $request->all(), 'CashApp verification error: ' . $e->getMessage()]);
  517. }
  518. }
  519. $data = compact('PixType', 'BankUserName', 'PixNum');
  520. } else {
  521. $data = compact('PixType', 'EmailAddress');
  522. }
  523. foreach ($data as $key => &$val) {
  524. $data[$key] = trim($val);
  525. }
  526. unset($val);
  527. $AccountWithDrawInfo = DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  528. ->lock('WITH(NOLOCK)')
  529. ->where('UserID', $UserID)
  530. ->first();
  531. if (!$AccountWithDrawInfo) {
  532. $data['UserID'] = $UserID;
  533. $data['Achieves'] = 0;
  534. $data['HistoryWithDraw'] = 0;
  535. try {
  536. DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  537. ->where('UserID', $UserID)
  538. ->insert($data);
  539. } catch (\Exception $e) {
  540. Log::error('insert AccountWithDrawInfo failed', ['data' => $data]);
  541. Util::WriteLog("withdrawInfo",[6, $request->all(),$data]);
  542. }
  543. } else {
  544. DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  545. ->where('UserID', $UserID)
  546. ->update($data);
  547. }
  548. SetNXLock::release($redisKey);
  549. return apiReturnSuc();
  550. }
  551. public function withDrawInfoSA(Request $request)
  552. {
  553. // return apiReturnFail('params error');
  554. $UserID = $request->input('UserID');
  555. $RequestDynamicPass = $request->input('DynamicPass');
  556. $PixType = $request->input('cbPixType');
  557. $BankNO = $request->input('bank');
  558. $AccountsBank = urldecode($request->input('account'));
  559. $BankUserName = urldecode($request->input('userName'));
  560. // 原始代码
  561. $BankUserName = Util::filterNickName($BankUserName);
  562. // 新增处理:在大写字母前加空格
  563. $BankUserName = preg_replace('/(?<!^)([A-Z])/', ' $1', $BankUserName);
  564. $PhoneNumber = $request->input('phone');
  565. $EmailAddress = $request->input('email');
  566. $IFSCNumber = $request->input('IFSC');
  567. $PANNumber = $request->input('PAN');
  568. $AdhaarNumber = $request->input('adhaar');
  569. $BranchBank = $request->input('branceBank');
  570. $PixNum = $request->input('PixNum');
  571. $redisKey = 'withDrawInfo_withDrawInfo_'.$UserID;
  572. if (!SetNXLock::getExclusiveLock($redisKey)) {
  573. Util::WriteLog("withdrawInfo",[1, $request->all()]);
  574. return apiReturnFail('Tente novamente mais tarde');
  575. }
  576. if (!$UserID) {
  577. Util::WriteLog("withdrawInfo",[2, $request->all()]);
  578. Log::info('miss UserID', $request->all());
  579. SetNXLock::release($redisKey);
  580. return apiReturnFail('params error');
  581. }
  582. if (empty($PixType)) {
  583. Util::WriteLog("withdrawInfo",[3, $request->all()]);
  584. SetNXLock::release($redisKey);
  585. return apiReturnFail('O tipo PIX está ausente');
  586. }
  587. // Util::validateSouthAmericanPhone('',)
  588. // 验证PixNum绑定次数
  589. if (!empty($PixNum)) {
  590. $BindCount = DB::table(TableName::QPRecordDB() . 'RecordBankCardBind')
  591. ->where('BankCard', $PixNum)
  592. ->lock('WITH(NOLOCK)')
  593. ->count();
  594. if ($BindCount >= 8) {
  595. Util::WriteLog("withdrawInfo",[4, $request->all()]);
  596. SetNXLock::release($redisKey);
  597. return apiReturnFail(['web.withdraw.cpf_number_used','The CPF number has been used several times and cannot be saved'], [], 302);
  598. }
  599. }
  600. // if(!is_numeric($PixNum)){
  601. // return apiReturnFail(['web.withdraw.pix_failed','The CPF number has been used several times and cannot be saved'], [], 302);
  602. // }
  603. // 验证玩家信息
  604. $DynamicPass = DB::table(TableName::QPAccountsDB() . 'AccountsInfo')
  605. ->where('UserID', $UserID)
  606. ->lock('WITH(NOLOCK)')
  607. ->value('DynamicPass');
  608. if ($DynamicPass != $RequestDynamicPass || empty($DynamicPass)) {
  609. SetNXLock::release($redisKey);
  610. Util::WriteLog("withdrawInfo",[5, $request->all()]);
  611. return apiReturnFail('As informações do jogador são inconsistentes');
  612. }
  613. $data = compact('PixType', 'BankUserName', 'PhoneNumber', 'EmailAddress', 'PixNum','BankNO', 'AccountsBank', 'IFSCNumber', 'PANNumber', 'AdhaarNumber', 'BranchBank');
  614. foreach ($data as $key => &$val) {
  615. $data[$key] = trim($val);
  616. }
  617. unset($val);
  618. $AccountWithDrawInfo = DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  619. ->lock('WITH(NOLOCK)')
  620. ->where('UserID', $UserID)
  621. ->first();
  622. if (!$AccountWithDrawInfo) {
  623. $data['UserID'] = $UserID;
  624. $data['Achieves'] = 0;
  625. $data['HistoryWithDraw'] = 0;
  626. try {
  627. DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  628. ->where('UserID', $UserID)
  629. ->insert($data);
  630. } catch (\Exception $e) {
  631. Log::error('insert AccountWithDrawInfo failed', ['data' => $data]);
  632. Util::WriteLog("withdrawInfo",[6, $request->all(),$data]);
  633. }
  634. } else {
  635. $data = array_filter($data, function ($value) {
  636. return !is_null($value) && $value !== '';
  637. });
  638. DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  639. ->where('UserID', $UserID)
  640. ->update($data);
  641. }
  642. // 添加绑定记录
  643. if (empty($AccountWithDrawInfo->PixNum) || $AccountWithDrawInfo->PixNum != $PixNum) {
  644. try {
  645. if(!DB::table(TableName::QPRecordDB() . 'RecordBankCardBind')->where('UserID', $UserID)->exists()&&is_numeric($PixNum)) {
  646. DB::table(TableName::QPRecordDB() . 'RecordBankCardBind')
  647. ->insert([
  648. 'UserID' => $UserID,
  649. 'BankCard' => $PixNum ?? '',
  650. 'BindDate' => now()
  651. ]);
  652. Util::WriteLog('update_pix', [
  653. 'UserID' => $UserID,
  654. 'BankCard' => $PixNum ?? '',
  655. 'BindDate' => now()
  656. ]);
  657. }
  658. } catch (\Exception $e) {
  659. Log::error('insert RecordBankCardBind failed', ['data' => $data]);
  660. Util::WriteLog("withdrawInfo",[7, $request->all(),$data]);
  661. }
  662. }
  663. SetNXLock::release($redisKey);
  664. return apiReturnSuc();
  665. }
  666. public function kycSimpleEU(Request $request)
  667. {
  668. // return apiReturnFail('params error');
  669. $user = $request->user();
  670. $UserID=$user->UserID;
  671. $firstName = Util::filterNickName(urldecode($request->input('firstName')));
  672. $lastName = Util::filterNickName(urldecode($request->input('lastName')));
  673. // 原始代码
  674. $BankUserName = $firstName.'|'.$lastName;
  675. $PhoneNumber = $request->input('phone');
  676. $EmailAddress = $request->input('email');
  677. Util::WriteLog("kyc_eu",$request->all());
  678. if(isset($EmailAddress)&&!empty($EmailAddress)){
  679. $validator = Validator::make(
  680. ['email' => $EmailAddress],
  681. ['email' => 'required|email']
  682. );
  683. if ($validator->fails()) {
  684. return apiReturnFail(['web.user.email_fail','Wrong email format']);
  685. }
  686. }
  687. if (!$BankUserName || $BankUserName == 'undefined') {
  688. return apiReturnFail(['web.bank.username_empty', 'The name cannot be empty']);
  689. }
  690. $redisKey = 'withDrawInfo_withDrawInfo_' . $UserID;
  691. if (!SetNXLock::getExclusiveLock($redisKey)) {
  692. return apiReturnFail(['web.bank.try_again_later', 'Please try again later']);
  693. }
  694. if (!$UserID) {
  695. Log::info('miss UserID', $request->all());
  696. SetNXLock::release($redisKey);
  697. return apiReturnFail(['web.bank.missing_userid', 'params error']);
  698. }
  699. $data = compact('BankUserName', 'PhoneNumber', 'EmailAddress');
  700. foreach ($data as $key => &$val) {
  701. $data[$key] = trim($val);
  702. if(empty($val))unset($data[$key]);
  703. }
  704. unset($val);
  705. $AccountWithDrawInfo = DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  706. ->lock('WITH(NOLOCK)')
  707. ->where('UserID', $UserID)
  708. ->first();
  709. if (!$AccountWithDrawInfo) {
  710. $data['UserID'] = $UserID;
  711. $data['Achieves'] = 0;
  712. $data['HistoryWithDraw'] = 0;
  713. try {
  714. DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  715. ->where('UserID', $UserID)
  716. ->insert($data);
  717. } catch (\Exception $e) {
  718. Log::error('insert AccountWithDrawInfo failed', ['data' => $data]);
  719. }
  720. } else {
  721. DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  722. ->where('UserID', $UserID)
  723. ->update($data);
  724. }
  725. SetNXLock::release($redisKey);
  726. return apiReturnSuc();
  727. }
  728. public function withDrawInfoEU(Request $request)
  729. {
  730. // return apiReturnFail('params error');
  731. $user = $request->user();
  732. $UserID=$user->UserID;
  733. // $UserID = $request->input('UserID');
  734. // $RequestDynamicPass = $request->input('DynamicPass');
  735. $PixType = $request->input('cbPixType');
  736. $firstName = Util::filterNickName(urldecode($request->input('firstName')));
  737. $lastName = Util::filterNickName(urldecode($request->input('lastName')));
  738. // 原始代码
  739. $BankUserName = $firstName.'|'.$lastName;
  740. $BankNO = $request->input('account');
  741. $AccountsBank = $request->input('account');
  742. $PhoneNumber = $request->input('phone');
  743. $EmailAddress = $request->input('email');
  744. $IFSCNumber = $request->input('IFSCNumber');
  745. $BranchBank = $request->input('bank');//银行编号
  746. $PixNum = $request->input('account');
  747. Util::WriteLog("euwithdraw",$request->all());
  748. if(isset($EmailAddress)&&!empty($EmailAddress)){
  749. $validator = Validator::make(
  750. ['email' => $EmailAddress],
  751. ['email' => 'required|email']
  752. );
  753. if ($validator->fails()) {
  754. return apiReturnFail(['web.user.email_fail','Wrong email format']);
  755. }
  756. }
  757. if (!$AccountsBank || $AccountsBank == 'undefined') {
  758. return apiReturnFail(['web.bank.account_empty', 'The bank account cannot be empty']);
  759. }
  760. if (!(strlen($AccountsBank) == 16 || strlen($AccountsBank) == 18)) {
  761. return apiReturnFail(['web.bank.account_invalid_length', 'The bank number must have 16 or 18 digits']);
  762. }
  763. if (!(strlen($IFSCNumber) == 18 && $IFSCNumber)) {
  764. return apiReturnFail(['web.bank.clabe_invalid_length', 'The Clabe number must have 18 digits']);
  765. }
  766. if (!$BankUserName || $BankUserName == 'undefined') {
  767. return apiReturnFail(['web.bank.username_empty', 'The name cannot be empty']);
  768. }
  769. if (!$BranchBank || $BranchBank == 'undefined') {
  770. return apiReturnFail(['web.bank.branch_empty', 'The branch code cannot be empty']);
  771. }
  772. if (strlen($AccountsBank) == 16) {
  773. $PixType = 2;
  774. }
  775. if (strlen($AccountsBank) == 18) {
  776. $PixType = 1;
  777. }
  778. $redisKey = 'withDrawInfo_withDrawInfo_' . $UserID;
  779. if (!SetNXLock::getExclusiveLock($redisKey)) {
  780. return apiReturnFail(['web.bank.try_again_later', 'Please try again later']);
  781. }
  782. if (!$UserID) {
  783. Log::info('miss UserID', $request->all());
  784. SetNXLock::release($redisKey);
  785. return apiReturnFail(['web.bank.missing_userid', 'params error']);
  786. }
  787. if (empty($PixType)) {
  788. SetNXLock::release($redisKey);
  789. return apiReturnFail(['web.bank.pix_type_missing', 'The PIX type is missing']);
  790. }
  791. // 验证PixNum绑定次数
  792. if (!empty($PixNum)) {
  793. $BindCount = DB::table(TableName::QPRecordDB() . 'RecordBankCardBind')
  794. ->where('BankCard', $PixNum)
  795. ->lock('WITH(NOLOCK)')
  796. ->count();
  797. if ($BindCount >= 3) {
  798. SetNXLock::release($redisKey);
  799. return apiReturnFail(['web.bank.cpf_used_multiple_times', 'The CPF number has been used multiple times and cannot be saved'], [], 302);
  800. }
  801. }
  802. // 验证玩家信息
  803. if (!empty($user->InsurePass)&&!Hash::check($paypass,$user->InsurePass)) {
  804. return apiReturnFail(['web.user.paypass_fail', 'A senha original está errada, digite-a novamente.'], '', 2);
  805. }
  806. if ($PixType < 10 && false) {
  807. $data = compact('PixType', 'BankUserName', 'PhoneNumber', 'EmailAddress', 'PixNum');
  808. } else {
  809. $data = compact('PixType', 'BankUserName','IFSCNumber', 'PhoneNumber', 'EmailAddress','BankNO', 'AccountsBank','BranchBank','PixNum');
  810. $PixNum = $BankNO;
  811. }
  812. foreach ($data as $key => &$val) {
  813. $data[$key] = trim($val);
  814. }
  815. unset($val);
  816. $AccountWithDrawInfo = DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  817. ->lock('WITH(NOLOCK)')
  818. ->where('UserID', $UserID)
  819. ->first();
  820. if (!$AccountWithDrawInfo) {
  821. $data['UserID'] = $UserID;
  822. $data['Achieves'] = 0;
  823. $data['HistoryWithDraw'] = 0;
  824. try {
  825. DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  826. ->where('UserID', $UserID)
  827. ->insert($data);
  828. } catch (\Exception $e) {
  829. Log::error('insert AccountWithDrawInfo failed', ['data' => $data]);
  830. }
  831. } else {
  832. DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  833. ->where('UserID', $UserID)
  834. ->update($data);
  835. }
  836. // 添加绑定记录
  837. if (empty($AccountWithDrawInfo->PixNum) || $AccountWithDrawInfo->PixNum != $PixNum) {
  838. try {
  839. DB::table(TableName::QPRecordDB() . 'RecordBankCardBind')
  840. ->insert([
  841. 'UserID' => $UserID,
  842. 'BankCard' => $PixNum ?: '',
  843. 'BindDate' => now()
  844. ]);
  845. } catch (\Exception $e) {
  846. Log::error('insert RecordBankCardBind failed', ['data' => $data]);
  847. }
  848. }
  849. SetNXLock::release($redisKey);
  850. return apiReturnSuc();
  851. }
  852. // 获取提现信息
  853. public function getWithDrawInfo(Request $request)
  854. {
  855. // $UserID = (int)$request->globalUser->UserID;//$request->input('UserID');
  856. $user = $request->user();
  857. $UserID=$user->UserID;
  858. // $paypass = $request->input('paypass');
  859. // if (!empty($user->InsurePass)&&!Hash::check($paypass,$user->InsurePass)) {
  860. // return apiReturnFail(['web.user.paypass_fail', 'A senha original está errada, digite-a novamente.'], '', 2);
  861. // }
  862. $info = DB::table(TableName::QPAccountsDB() . 'AccountWithDrawInfo')
  863. ->where('UserID', $UserID)
  864. ->lock('WITH(NOLOCK)')
  865. ->first();
  866. if (!$info) { // 赋值 -- 避免客户端报错
  867. $info = [
  868. // 'BankNO' => '',
  869. // 'AccountsBank' => '',
  870. 'BankUserName' => '',
  871. // 'PhoneNumber' => '',
  872. // 'IFSCNumber' => '',
  873. 'EmailAddress' => '',
  874. // 'Achieves' => '',
  875. // 'PANNumber' => '',
  876. // 'AdhaarNumber' => '',
  877. // 'BranchBank' => '',
  878. 'PixNum' => '',
  879. 'PixType' => '',
  880. ];
  881. }
  882. $info = json_decode(json_encode($info),true);
  883. $info['bank_list'] = config('games.mex_bank_list');
  884. $AccountsInfoModel = new AccountsInfo();
  885. $total = $AccountsInfoModel->accountTotalStatistics([$UserID]);
  886. $totalRecharge= @$total[0]->Recharge ?? 0;
  887. $info['total_recharge'] = intval($totalRecharge);
  888. $info['withdraw_level'] = env('MIN_RECHARGE',20);
  889. return apiReturnSuc(compact('info'));
  890. }
  891. }