WithdrawController.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. <?php
  2. namespace Modules\Api\Controllers;
  3. use App\Constants\ChangeLogConstant;
  4. use App\Jobs\SendTgWithdrawMegJob;
  5. use App\Model\CoinsLogModel;
  6. use App\Model\WithdrawalLogModel;
  7. use App\Model\WithdrawalMethodModel;
  8. use App\Repositories\ConfigRepoistory;
  9. use App\Repositories\Service\QueueService;
  10. use App\Repositories\UserRepository;
  11. use Carbon\Carbon;
  12. use Hyperf\DbConnection\Db;
  13. use Hyperf\Validation\Contract\ValidatorFactoryInterface;
  14. use App\Constants\CommonConstant;
  15. /**
  16. * 提现相关
  17. */
  18. class WithdrawController extends BaseController
  19. {
  20. /**
  21. * 提现方式列表
  22. */
  23. public function userWithdrawalMethodList()
  24. {
  25. return json_success(WithdrawalMethodModel::query()->where('user_uid', $this->getUserId())
  26. ->get(['id', 'type', 'username', 'account', 'bank']));
  27. }
  28. /**
  29. * 提币网络
  30. * @return mixed
  31. */
  32. public function usdtNetwork()
  33. {
  34. $configRepo = make(ConfigRepoistory::class);
  35. $usdtNet = $configRepo->get('usdt_net', 'sys', '');
  36. $arrUsdtNet = !empty($usdtNet) ? explode(',', $usdtNet) : [];
  37. return json_success($arrUsdtNet);
  38. }
  39. /**
  40. * 添加提现方式
  41. * @param ValidatorFactoryInterface $validatorFactory
  42. * @return mixed
  43. */
  44. public function createWithdrawalMethod(ValidatorFactoryInterface $validatorFactory)
  45. {
  46. $inputData = $this->getJsonData();
  47. $rules = [
  48. 'type' => 'required|numeric|between:1,3',// 收款类型 (1USDT,2银行卡,3支付宝)
  49. 'username' => 'nullable|min:1|max:10',// 姓名
  50. 'account' => 'required|min:4|max:40',// 账号,卡号,usdt地址
  51. 'bank' => 'nullable|min:4|max:20',// 所属银行或,usdt提币方式
  52. ];
  53. $validator = $validatorFactory->make($inputData, $rules);
  54. if ($validator->fails()) {
  55. return json_fail($validator->errors()->first());
  56. }
  57. if ($inputData['type'] === 1) {
  58. // USDT
  59. if (!$inputData['bank']) {
  60. return json_fail('请检查usdt提币方式!');
  61. }
  62. } elseif ($inputData['type'] === 2) {
  63. // 银行卡
  64. if (!$inputData['username'] || !$inputData['bank']) {
  65. return json_fail('请检查姓名或所属银行!');
  66. }
  67. } elseif ($inputData['type'] === 3) {
  68. // 支付宝
  69. if (!$inputData['username']) {
  70. return json_fail('请检查姓名!');
  71. }
  72. }
  73. $userId = $this->getUserId();
  74. $withdrawalMethod = WithdrawalMethodModel::query();
  75. $withdrawalMethodClone = clone $withdrawalMethod;
  76. if ($withdrawalMethod->where(['type' => $inputData['type'], 'user_uid' => $userId])->count()) {
  77. return json_fail('该提现方式已存在!');
  78. }
  79. $array = [
  80. 'user_uid' => $userId,
  81. 'type' => $inputData['type'],
  82. 'username' => $inputData['username'],
  83. 'account' => $inputData['account'],
  84. 'bank' => $inputData['bank'],
  85. ];
  86. if (!$withdrawalMethodClone->create($array)) {
  87. return json_fail('添加失败请联系客服!');
  88. }
  89. return json_success('添加成功!');
  90. }
  91. /**
  92. * 删除提现方式
  93. */
  94. public function deleteWithdrawalMethod(ValidatorFactoryInterface $validatorFactory)
  95. {
  96. $inputData = $this->getJsonData();
  97. $rules = [
  98. 'type' => 'required|numeric|between:1,3',// 收款类型 (1USDT,2银行卡,3支付宝)
  99. ];
  100. $validator = $validatorFactory->make($inputData, $rules);
  101. if ($validator->fails()) {
  102. return json_fail($validator->errors()->first());
  103. }
  104. // 查询是否有这个方法
  105. $userInfo = make(UserRepository::class)->findWhere(['code' => $this->getUserId()])->first();
  106. if (!$userInfo) {
  107. return json_fail('操作有误!');
  108. }
  109. $resData = WithdrawalMethodModel::query()
  110. ->where(['user_uid' => $userInfo->code, 'type' => $inputData['type']])
  111. ->first();
  112. if (!$resData) {
  113. return json_fail('提现方式不存在!');
  114. }
  115. if (!$resData->delete()) {
  116. return json_fail('删除失败!');
  117. }
  118. return json_success($inputData);
  119. }
  120. /**
  121. * 提现记录
  122. * @param ValidatorFactoryInterface $validatorFactory
  123. * @return mixed
  124. */
  125. public function withdrawalLogList(ValidatorFactoryInterface $validatorFactory)
  126. {
  127. $inputData = $this->getJsonData();
  128. $rules = [
  129. 'page' => 'required|int',
  130. 'page_size' => 'required|int',
  131. ];
  132. $validator = $validatorFactory->make($inputData, $rules);
  133. if ($validator->fails()) {
  134. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  135. return json_fail($validator->errors()->first());
  136. }
  137. $page = $inputData['page'] ?? 1;
  138. $pageSize = $inputData['page_size'] ?? CommonConstant::PAGE_SIZE;
  139. if ($pageSize > 100) {
  140. $pageSize = CommonConstant::PAGE_SIZE;
  141. }
  142. $page = format_page($page);
  143. $pageSize = intval($pageSize);
  144. if ($pageSize <= 0) {
  145. $pageSize = CommonConstant::PAGE_SIZE;
  146. }
  147. return json_success(WithdrawalLogModel::query()
  148. ->where([
  149. ['user_uid', '=', $this->getUserId()],
  150. ['type', '!=', 4]
  151. ])
  152. ->select('order_number',
  153. 'amount',
  154. 'type',
  155. 'username',
  156. 'account',
  157. 'bank',
  158. 'status',
  159. 'remark',
  160. 'created_at',
  161. 'updated_at')
  162. ->orderBy('created_at', 'desc')
  163. ->paginate($pageSize, ['*'], 'page', $page));
  164. }
  165. /**
  166. * 申请提现列表
  167. */
  168. public function applyDorWithdrawalList()
  169. {
  170. // 提现列表
  171. $dataList = WithdrawalMethodModel::query()->where('user_uid', $this->getUserId())
  172. ->get(['id', 'type', 'username', 'account', 'bank']);
  173. // 查询用户
  174. $userInfo = make(UserRepository::class)->findWhere(['code' => $this->getUserId()])->first();
  175. if (!$userInfo) {
  176. return json_fail('操作有误!');
  177. }
  178. if ($dataList) {
  179. $configRepo = make(ConfigRepoistory::class);
  180. $usdtNet = $configRepo->gets(['withdraw_money', 'usdt_conf', 'withdraw_usdt'], 'sys', '');
  181. $withdrawMoney = $usdtNet['withdraw_money']; // 最低提现
  182. $usdt_conf = $usdtNet['usdt_conf'];// utdt汇率
  183. $withdraw_usdt = $usdtNet['withdraw_usdt'];// utdt最低提现
  184. foreach ($dataList as &$item) {
  185. if ($item->type === 1) {
  186. // usdt提现
  187. $item->low_withdraw = (int)$withdraw_usdt;//最低提现
  188. $item->withdraw = floor($userInfo->balance / $usdt_conf);//可提现
  189. $item->exchange = (float)$usdt_conf;//汇率
  190. } else {
  191. $item->low_withdraw = (int)$withdrawMoney;
  192. $item->withdraw = (float)$userInfo->balance;
  193. $item->exchange = 0;
  194. }
  195. }
  196. }
  197. $userWithdraw = [
  198. '周*雨提现9000元',
  199. '白*惠提现8000元',
  200. '李*提现10000元',
  201. '黄*提现50000元',
  202. ];
  203. $resData = [
  204. 'user_withdraw_list' => $userWithdraw,
  205. 'dataList' => $dataList,
  206. 'balance' => $userInfo->balance,//我的金额
  207. 'coins' => $userInfo->balance * 10,// 可提现金币
  208. 'coins_proportion' => 10,// 金币比例
  209. 'usdt_proportion' => $usdt_conf,// usdt 比例
  210. 'coins_low_withdraw' => 20,// 最低提现金币
  211. 'usdt_low_withdraw' => $withdraw_usdt,// usdt 最低提现
  212. 'money_low_proportion' => $withdrawMoney,// 人名币最低提现
  213. ];
  214. return json_success($resData);
  215. }
  216. /**
  217. * 申请提现
  218. * @param ValidatorFactoryInterface $validatorFactory
  219. * @return mixed
  220. */
  221. public function applyDorWithdrawal(ValidatorFactoryInterface $validatorFactory)
  222. {
  223. $inputData = $this->getJsonData();
  224. $rules = [
  225. 'amount' => 'required|numeric',
  226. 'withdrawal_method_id' => 'required|numeric'
  227. ];
  228. $validator = $validatorFactory->make($inputData, $rules);
  229. if ($validator->fails()) {
  230. return json_fail($validator->errors()->first());
  231. }
  232. $userId = $this->getUserId();
  233. // 查询提现方式
  234. $withdrawalMethodInfo = WithdrawalMethodModel::query()
  235. ->where([
  236. 'id' => $inputData['withdrawal_method_id'],
  237. 'user_uid' => $userId,
  238. ])
  239. ->first(['id', 'type', 'username', 'account', 'bank']);
  240. if (!$withdrawalMethodInfo) {
  241. return json_fail('没有该提现方式!');
  242. }
  243. $amount = $inputData['amount'];
  244. // 查询用户
  245. $userInfo = make(UserRepository::class)->findWhere(['code' => $userId])->first();
  246. $configRepo = make(ConfigRepoistory::class);
  247. $usdtNet = $configRepo->gets(['usdt_conf', 'withdraw_usdt','withdraw_money'], 'sys', '');
  248. $usdt_conf = floatval($usdtNet['usdt_conf']);//utdt汇率
  249. $withdrawUsdtConf = intval($usdtNet['withdraw_usdt']);// ustd最低提现
  250. $withdrawConf = intval($usdtNet['withdraw_money']);// ustd最低提现
  251. //判断提现的类型
  252. if ($withdrawalMethodInfo->type === 1) {
  253. // utdt最低提现
  254. if ($amount < $withdrawUsdtConf) {
  255. return json_fail('最低提现要求' . $withdrawUsdtConf . 'U');
  256. }
  257. // 可提现U
  258. $withdrawalUsdt = floor($userInfo->balance / $usdt_conf);
  259. if ($amount > $withdrawalUsdt) {
  260. return json_fail('余额不足!');
  261. }
  262. } else {
  263. if ($amount < $withdrawConf) {
  264. return json_fail('最低提现要求' . $withdrawConf . '元');
  265. }
  266. if ($amount > $userInfo->balance) {
  267. return json_fail('余额不足!');
  268. }
  269. }
  270. // 金额变动
  271. $dataArray = [
  272. 'order_number' => date('YmdHis') . random_int(10000, 99999),
  273. 'amount' => $amount,//提现金额
  274. 'withdrawal_method_id' => $inputData['withdrawal_method_id'],//提现方式id
  275. 'balance_forward' => $userInfo->balance,//提现前金额
  276. 'freeze_forward' => $userInfo->freeze,//提现前冻结金额
  277. 'user_uid' => $userInfo->code,
  278. 'type' => $withdrawalMethodInfo->type,
  279. 'username' => $withdrawalMethodInfo->username,
  280. 'account' => $withdrawalMethodInfo->account,
  281. 'bank' => $withdrawalMethodInfo->bank,
  282. 'status' => 1,//1打款中,2已到账,3失败,4冻结
  283. 'created_at' => Carbon::now()->toDateTimeString(),// 申请时间
  284. 'updated_at' => Carbon::now()->toDateTimeString(),// 处理时间
  285. ];
  286. if ($withdrawalMethodInfo->type === 1) {
  287. // usdt计算
  288. $amount = $amount * $usdt_conf;// usdt转现金
  289. $dataArray['usdt_to_amount'] = $amount;//usdt转现金
  290. $dataArray['usdt_proportion'] = $usdt_conf;
  291. }
  292. $dataArray['balance_rear'] = $userInfo->balance - $amount;//提现后金额
  293. $dataArray['freeze_rear'] = $userInfo->freeze + $amount;//提现后冻结金额
  294. $withdrawalLog = WithdrawalLogModel::query();
  295. // 事物执行
  296. Db::beginTransaction();
  297. try {
  298. $userInfo->balance = $userInfo->balance - $amount;// 余额
  299. $userInfo->freeze = $userInfo->freeze + $amount;// 冻结余额
  300. if (!$userInfo->save()) {
  301. Db::rollback();
  302. return json_fail('提现失败!请重试 -001');
  303. }
  304. $res = $withdrawalLog->create($dataArray);
  305. if (!$res) {
  306. Db::rollback();
  307. return json_fail('提现失败!请重试 -002');
  308. }
  309. Db::commit();
  310. } catch (\Exception $exception) {
  311. Db::rollback();
  312. return json_fail('提现失败!请重试 -003');
  313. }
  314. dispatch_job(new SendTgWithdrawMegJob(
  315. '雏姬',
  316. $userInfo->code,
  317. $userInfo->nick,
  318. $withdrawalMethodInfo->type,
  319. $inputData['amount'],
  320. Carbon::now()->toDateTimeString()
  321. ));
  322. // 帐变记录
  323. $changeData = [
  324. 'user_uid' => $userId,
  325. 'currency_type' => ChangeLogConstant::CHANGE_AMOUNT,
  326. 'amount' => $amount,
  327. 'way' => ChangeLogConstant::WAY_2,
  328. 'type' => ChangeLogConstant::TYPE_20,
  329. ];
  330. make(QueueService::class)->saveChangeLogJob($changeData);
  331. return json_success('申请提现成功!');
  332. }
  333. /**
  334. * 余额转金币列表
  335. * @param ValidatorFactoryInterface $validatorFactory
  336. */
  337. public function BalanceChangeCoinList(ValidatorFactoryInterface $validatorFactory)
  338. {
  339. $inputData = $this->getJsonData();
  340. $rules = [
  341. 'page' => 'required|int',
  342. 'page_size' => 'required|int',
  343. ];
  344. $validator = $validatorFactory->make($inputData, $rules);
  345. if ($validator->fails()) {
  346. // 如果有错误(可能是多个信息),这里只取第一个错误信息返回.
  347. return json_fail($validator->errors()->first());
  348. }
  349. $page = $inputData['page'] ?? 1;
  350. $pageSize = $inputData['page_size'] ?? CommonConstant::PAGE_SIZE;
  351. if ($pageSize > 100) {
  352. $pageSize = CommonConstant::PAGE_SIZE;
  353. }
  354. $page = format_page($page);
  355. $pageSize = intval($pageSize);
  356. if ($pageSize <= 0) {
  357. $pageSize = CommonConstant::PAGE_SIZE;
  358. }
  359. return json_success(WithdrawalLogModel::query()
  360. ->where([
  361. ['user_uid', '=', $this->getUserId()],
  362. ['type', '=', 4]
  363. ])
  364. ->select('amount', 'coins', 'updated_at')
  365. ->paginate($pageSize, ['*'], 'page',$page));
  366. }
  367. /**
  368. * 余额转金币
  369. * @param ValidatorFactoryInterface $validatorFactory
  370. * @return mixed
  371. * @throws \Exception
  372. */
  373. public function BalanceChangeCoin(ValidatorFactoryInterface $validatorFactory)
  374. {
  375. $inputData = $this->getJsonData();
  376. $rules = [
  377. 'amount' => 'required|numeric|min:10',
  378. ];
  379. $validator = $validatorFactory->make($inputData, $rules);
  380. if ($validator->fails()) {
  381. return json_fail($validator->errors()->first());
  382. }
  383. $amount = $inputData['amount'];
  384. $userId = $this->getUserId();
  385. // 查询用户
  386. $userInfo = make(UserRepository::class)->findWhere(['code' => $userId])->first();
  387. if ($userInfo->balance < $amount) {
  388. return json_fail('余额不足!');
  389. }
  390. $coinConf = 10;
  391. $coin = $amount * $coinConf;
  392. $dataArray = [
  393. 'order_number' => date('YmdHis') . random_int(10000, 99999),
  394. 'amount' => $amount,// 兑换的金额
  395. 'balance_forward' => $userInfo->balance,//提现前金额
  396. 'balance_rear' => $userInfo->balance - $amount,//提现后金额
  397. 'withdrawal_method_id' => 0,
  398. 'coins' => $coin, // 兑换的金币
  399. 'forward_coins' => $userInfo->coins, // 兑换前
  400. 'rear_coins' => $userInfo->coins + $coin, // 兑换后
  401. 'user_uid' => $userInfo->code,
  402. 'type' => 4,// 4兑换金币
  403. 'status' => 2,//1打款中,2已到账,3失败,4冻结
  404. 'coin_proportion' => $coinConf,
  405. 'created_at' => Carbon::now()->toDateTimeString(),// 申请时间
  406. 'updated_at' => Carbon::now()->toDateTimeString(),// 处理时间
  407. ];
  408. $withdrawalLog = WithdrawalLogModel::query();
  409. //--记录帐变使用日志
  410. $changeData = [
  411. 'user_uid' => $userInfo->code,
  412. 'currency_type' => ChangeLogConstant::CHANGE_COIN,
  413. 'amount' => $coin,
  414. 'way' => ChangeLogConstant::WAY_1,
  415. 'type' => ChangeLogConstant::TYPE_5,
  416. ];
  417. $changeBalanceData = [
  418. 'user_uid' => $userInfo->code,
  419. 'currency_type' => ChangeLogConstant::CHANGE_AMOUNT,
  420. 'amount' => $amount,
  421. 'way' => ChangeLogConstant::WAY_2,
  422. 'type' => ChangeLogConstant::TYPE_5,
  423. ];
  424. // 事物执行
  425. Db::beginTransaction();
  426. try {
  427. $userInfo->balance = $userInfo->balance - $amount;// 余额
  428. $userInfo->coins = $userInfo->coins + $coin;
  429. make(UserRepository::class)->delUserCache($userInfo->code);
  430. if (!$userInfo->save()) {
  431. Db::rollback();
  432. return json_fail('兑换失败!请重试 -001');
  433. }
  434. $res = $withdrawalLog->create($dataArray);
  435. if (!$res) {
  436. Db::rollback();
  437. return json_fail('兑换失败!请重试 -002');
  438. }
  439. Db::commit();
  440. // 帐变记录
  441. $queue = make(QueueService::class);
  442. $queue->saveChangeLogJob($changeData); // 金币
  443. $queue->saveChangeLogJob($changeBalanceData); // 余额
  444. } catch (\Exception $exception) {
  445. Db::rollback();
  446. return json_fail('兑换失败!请重试 -003');
  447. }
  448. return json_success('兑换成功!');
  449. }
  450. }