Wallet.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. <?php
  2. namespace App\Http\Controllers\api;
  3. use App\Services\WalletService;
  4. use App\Services\ConfigService;
  5. use App\Models\Config;
  6. use App\Models\Recharge;
  7. use App\Models\Wallet as WalletModel;
  8. use App\Models\Withdraw;
  9. use App\Models\User;
  10. use App\Models\Bank;
  11. use App\Models\Address;
  12. use App\Services\BalanceLogService;
  13. use App\Services\Payment\SanJinService;
  14. use App\Services\PaymentOrderService;
  15. use App\Services\QianBaoWithdrawService;
  16. use App\Services\Payment\QianBaoService;
  17. use App\Services\WithdrawService;
  18. use Illuminate\Validation\ValidationException;
  19. use Exception;
  20. /**
  21. * 充值提现接口
  22. */
  23. class Wallet extends BaseController
  24. {
  25. //获取三斤充值通道(微信、支付宝、扫码充值)
  26. public function getChannel()
  27. {
  28. $data = SanJinService::getChannel();
  29. $product = SanJinService::$PRODUCT;
  30. $list = [];
  31. foreach($data as $k => $v) {
  32. foreach($product as $pv) {
  33. if ($k == $pv['type']) {
  34. $config = $pv;
  35. }
  36. }
  37. $list[] = [
  38. 'label' => lang($v),
  39. 'value' => $k,
  40. 'config' => $config ?? [],
  41. ];
  42. }
  43. return $this->success([
  44. 'list' => $list,
  45. ]);
  46. }
  47. /**
  48. * 创建代收订单
  49. */
  50. public function createPay()
  51. {
  52. try {
  53. $params = request()->validate([
  54. 'amount' => ['required', 'numeric', 'min:0.01'],
  55. 'payment_type' => ['required', 'string'],
  56. ]);
  57. $member_id = request()->user->member_id;
  58. $res = PaymentOrderService::createPay($member_id, $params['amount'], $params['payment_type']);
  59. if ($res['code'] == 0) {
  60. return $this->success($res);
  61. }
  62. return $this->error($res['text']);
  63. } catch (ValidationException $e) {
  64. return $this->error($e->validator->errors()->first());
  65. } catch (\Exception $e) {
  66. return $this->error($e->getMessage());
  67. }
  68. }
  69. /**
  70. * 获取充值二维码(USDT充值)
  71. */
  72. public function scan()
  73. {
  74. try {
  75. $member_id = request()->user->member_id;
  76. $params = request()->validate([
  77. 'type' => ['required', 'string'],
  78. ]);
  79. $receivingType = ConfigService::getVal("receiving_type");
  80. //自动充值
  81. if ($receivingType == 1) {
  82. $res = WalletService::getRechargeImageAddress($member_id);
  83. $address = $res['address'];
  84. $qrCode = $res['full_path'];
  85. } else {
  86. //手动充值
  87. if (strtolower($params['type']) === "trc20") {
  88. $address = Config::where('field', 'receiving_address')->first()->val;
  89. } elseif (strtolower($params['type']) === "erc20") {
  90. $address = Config::where('field', 'receiving_address_erc20')->first()->val;
  91. } else {
  92. return $this->error(lang('充值类型错误'));
  93. }
  94. $res = WalletService::getPlatformImageAddress($address);
  95. $res['net'] = $params['type'];
  96. $qrCode = $res['full_path'];
  97. }
  98. return $this->success([
  99. 'qrcode' => $qrCode,
  100. // 'photo' => InputFile::create($qrCode),
  101. ]);
  102. } catch (ValidationException $e) {
  103. return $this->error($e->validator->errors()->first());
  104. } catch (\Exception $e) {
  105. return $this->error($e->getMessage());
  106. }
  107. }
  108. /**
  109. * 提交充值凭证
  110. */
  111. public function recharge()
  112. {
  113. try {
  114. $params = request()->validate([
  115. 'net' => ['required', 'string'],
  116. 'amount' => ['required', 'numeric', 'min:0.01'],
  117. 'toAddress' => ['required', 'string'],
  118. 'image' => ['required', 'url'],
  119. ]);
  120. $member_id = request()->user->member_id;
  121. $recharge = new Recharge();
  122. $recharge->member_id = $member_id;
  123. $recharge->net = $params['net'];
  124. $recharge->coin = "USDT";
  125. $recharge->amount = $params['amount'];
  126. $recharge->to_address = $params['toAddress'];
  127. $recharge->status = 0;
  128. $recharge->type = 2;
  129. $recharge->image = $params['image'];
  130. $recharge->save();
  131. return $this->success($recharge,'提交成功');
  132. } catch (ValidationException $e) {
  133. return $this->error($e->validator->errors()->first());
  134. } catch (Exception $e) {
  135. return $this->error($e->getMessage());
  136. }
  137. }
  138. /**
  139. * 获取提现通道
  140. */
  141. public function withdrawChannel()
  142. {
  143. $list = QianBaoService::withdrawChannel();
  144. $data[] = ['label' => 'USDT', 'value' => 'USDT'];
  145. foreach ($list as $key => $item) {
  146. $data[] = ['label' => $item, 'value' => $key];
  147. }
  148. return $this->success($data);
  149. }
  150. public function withdraw()
  151. {
  152. try {
  153. $member_id = request()->user->member_id;
  154. $params = request()->validate([
  155. 'amount' => ['required', 'numeric', 'min:0.01'],
  156. 'address' => ['required', 'string'],
  157. 'safe_word' => ['required'],
  158. ]);
  159. $user = User::where('member_id', $member_id)->first();
  160. if (empty($user->payment_password)) throw new Exception(lang("请先设置资金密码"));
  161. //校验资金密码
  162. if (!password_verify($params['safe_word'], $user->payment_password)) {
  163. throw new Exception(lang('资金密码错误'));
  164. }
  165. $serviceCharge = (new WithdrawService())->serviceCharge;
  166. $amount = $params['amount'];
  167. $address = $params['address'];
  168. $real = bcsub($amount, $serviceCharge, 10);
  169. $real = floatval($real);
  170. if ($amount <= $serviceCharge) {
  171. throw new Exception(lang("提现不能少于") . "{$serviceCharge} USDT");
  172. }
  173. $wallet = WalletModel::where('member_id', $member_id)->first();
  174. $temp = floatval($wallet->available_balance);
  175. // 汇率
  176. $rate = Config::where('field', 'exchange_rate_rmb')->first()->val ?? 1;
  177. $exchange_rate_difference = Config::where('field', 'exchange_rate_difference')->first()->val ?? 0;
  178. $rate = bcadd($rate, $exchange_rate_difference, 2);
  179. $rate_usdt_amount = bcdiv($temp, $rate, 2); // 钱包可用余额 折合USDT
  180. $rate_rmb_amount = bcmul($amount, $rate, 2); // 提现金额 折合RMB
  181. if ($amount > $rate_usdt_amount) {
  182. throw new Exception(lang("余额不足") . "{$serviceCharge} USDT");
  183. }
  184. $wallet = WalletModel::where('member_id', $member_id)->first();
  185. $changeAmount = bcmul(($amount * -1), $rate, 2);
  186. $beforeBalance = $wallet->available_balance;
  187. $afterBalance = bcsub($wallet->available_balance, $rate_rmb_amount, 2);
  188. $wallet->available_balance = $afterBalance;
  189. $wallet->save();
  190. $withdraw = Withdraw::create([
  191. 'member_id' => $member_id,
  192. 'amount' => $amount,
  193. 'service_charge' => $serviceCharge,
  194. 'to_account' => $real,
  195. 'address' => $address,
  196. 'exchange_rate' => $rate,
  197. 'status' => 0,
  198. 'after_balance' => $afterBalance
  199. ]);
  200. BalanceLogService::addLog($member_id, $changeAmount, $beforeBalance, $afterBalance, '提现', $withdraw->id, '');
  201. return $this->success($withdraw,'提交成功');
  202. } catch (ValidationException $e) {
  203. return $this->error($e->validator->errors()->first());
  204. } catch (\Exception $e) {
  205. return $this->error($e->getMessage());
  206. }
  207. }
  208. /**
  209. * 提现(手动到账): DF001 支付宝转卡; DF002 支付宝转支付宝; DF005数字人民币
  210. */
  211. public function payout() {
  212. try {
  213. $params = request()->validate([
  214. 'amount' => ['required', 'numeric', 'min:0.01'],
  215. 'channel' => ['required', 'string', 'in:DF001,DF002,DF005'],
  216. 'bank_name' => ['required', 'string'],
  217. 'account' => ['required', 'string'],
  218. 'card_no' => ['required', 'string'],
  219. 'safe_word' => ['required'],
  220. ]);
  221. $member_id = request()->user->member_id;
  222. $user = User::where('member_id', $member_id)->first();
  223. if (empty($user->payment_password)) throw new Exception(lang("请先设置资金密码"));
  224. //校验资金密码
  225. if (!password_verify($params['safe_word'], $user->payment_password)) {
  226. throw new Exception(lang('资金密码错误'));
  227. }
  228. $res = QianBaoWithdrawService::createOrder($member_id, $params['amount'], $params['channel'], $params['bank_name'], $params['account'], $params['card_no']);
  229. if ($res['code'] == 0) {
  230. return $this->success($res,'提交成功');
  231. }
  232. return $this->error($res['text']);
  233. } catch (ValidationException $e) {
  234. return $this->error($e->validator->errors()->first());
  235. } catch (\Exception $e) {
  236. return $this->error($e->getMessage());
  237. }
  238. }
  239. /**
  240. * 提现(自动到账): DF001 支付宝转卡/DF002 支付宝转支付宝
  241. */
  242. public function autoPayout()
  243. {
  244. try {
  245. $params = request()->validate([
  246. 'amount' => ['required', 'numeric', 'min:0.01'],
  247. 'channel' => ['required', 'string'],
  248. 'bank_name' => ['required', 'string'],
  249. 'account' => ['required', 'string'],
  250. 'card_no' => ['required', 'string'],
  251. ]);
  252. $member_id = request()->user->member_id;
  253. $res = PaymentOrderService::autoCreatePayout($member_id, $params['amount'], $params['channel'], $params['bank_name'], $params['account'], $params['card_no']);
  254. if (empty($res['text'])) {
  255. return $this->success($res,'提交成功');
  256. }
  257. return $this->error($res['text']);
  258. } catch (ValidationException $e) {
  259. return $this->error($e->validator->errors()->first());
  260. } catch (Exception $e) {
  261. return $this->error($e->getMessage());
  262. }
  263. }
  264. public function addBank()
  265. {
  266. try {
  267. $params = request()->validate([
  268. 'id' => 'nullable|integer',
  269. 'channel' => 'required',
  270. 'account' => 'required',
  271. 'card_no' => 'required',
  272. 'bank_name' => 'required',
  273. 'alias' => 'nullable',
  274. ]);
  275. $member_id = request()->user->member_id;
  276. if (!empty($params['id'])) {
  277. $info = Bank::where('id', $params['id'])->where('member_id', $member_id)->first();
  278. if (empty($info)) throw new Exception(lang('找不到此记录'));
  279. $info->channel = $params['channel'];
  280. $info->account = $params['account'];
  281. $info->card_no = $params['card_no'];
  282. $info->bank_name = $params['bank_name'];
  283. $info->alias = $params['alias'] ?? '';
  284. $info->save();
  285. } else {
  286. $count = Bank::where('member_id', $member_id)->where('channel', $params['channel'])->count();
  287. if ($count >= 5) throw new Exception(lang('已达添加上限'));
  288. Bank::create([
  289. 'member_id' => $member_id,
  290. 'channel' => $params['channel'],
  291. 'account' => $params['account'],
  292. 'card_no' => $params['card_no'],
  293. 'bank_name' => $params['bank_name'],
  294. 'alias' => $params['alias'] ?? '',
  295. ]);
  296. }
  297. return $this->success([],'提交成功');
  298. } catch (ValidationException $e) {
  299. return $this->error($e->validator->errors()->first());
  300. } catch (\Exception $e) {
  301. return $this->error($e->getMessage());
  302. }
  303. }
  304. public function delBank()
  305. {
  306. try {
  307. $params = request()->validate([
  308. 'id' => 'required|integer',
  309. ]);
  310. $member_id = request()->user->member_id;
  311. $info = Bank::where('id', $params['id'])->where('member_id', $member_id)->first();
  312. if (empty($info)) throw new Exception(lang('找不到此记录'));
  313. $info->delete();
  314. return $this->success([],'删除成功');
  315. } catch (ValidationException $e) {
  316. return $this->error($e->validator->errors()->first());
  317. } catch (\Exception $e) {
  318. return $this->error($e->getMessage());
  319. }
  320. }
  321. public function bankList()
  322. {
  323. try {
  324. $params = request()->validate([
  325. 'channel' => 'nullable',
  326. ]);
  327. $member_id = request()->user->member_id;
  328. $where = !empty($params['channel']) ? ['channel' => $params['channel']] : [];
  329. $list = Bank::where('member_id', $member_id)->where($where)->get()->toArray();
  330. return $this->success([
  331. 'list' => $list,
  332. ]);
  333. } catch (\Exception $e) {
  334. return $this->error($e->getMessage());
  335. }
  336. }
  337. public function addAddress()
  338. {
  339. try {
  340. $params = request()->validate([
  341. 'id' => 'nullable|integer',
  342. 'address' => 'required',
  343. 'alias' => 'nullable',
  344. ]);
  345. $member_id = request()->user->member_id;
  346. if (!empty($params['id'])) {
  347. $info = Address::where('id', $params['id'])->where('member_id', $member_id)->first();
  348. if (empty($info)) throw new Exception(lang('找不到此记录'));
  349. $info->address = $params['address'];
  350. $info->alias = $params['alias'] ?? '';
  351. $info->save();
  352. } else {
  353. $count = Address::where('member_id', $member_id)->where('address', $params['address'])->count();
  354. if ($count >= 5) throw new Exception(lang('已达添加上限'));
  355. Address::create([
  356. 'member_id' => $member_id,
  357. 'address' => $params['address'],
  358. 'alias' => $params['alias'] ?? '',
  359. ]);
  360. }
  361. return $this->success([],'提交成功');
  362. } catch (ValidationException $e) {
  363. return $this->error($e->validator->errors()->first());
  364. } catch (\Exception $e) {
  365. return $this->error($e->getMessage());
  366. }
  367. }
  368. public function delAddress()
  369. {
  370. try {
  371. $params = request()->validate([
  372. 'id' => 'required|integer',
  373. ]);
  374. $member_id = request()->user->member_id;
  375. $info = Address::where('id', $params['id'])->where('member_id', $member_id)->first();
  376. if (empty($info)) throw new Exception(lang('找不到此记录'));
  377. $info->delete();
  378. return $this->success([],'删除成功');
  379. } catch (ValidationException $e) {
  380. return $this->error($e->validator->errors()->first());
  381. } catch (\Exception $e) {
  382. return $this->error($e->getMessage());
  383. }
  384. }
  385. public function address()
  386. {
  387. try {
  388. $member_id = request()->user->member_id;
  389. $list = Address::where('member_id', $member_id)->get()->toArray();
  390. return $this->success([
  391. 'list' => $list,
  392. ]);
  393. } catch (\Exception $e) {
  394. return $this->error($e->getMessage());
  395. }
  396. }
  397. }