MerchantService.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
  4. // +----------------------------------------------------------------------
  5. // | 版权所有 2017~2021 LARAVEL研发中心
  6. // +----------------------------------------------------------------------
  7. // | 官方网站: http://www.laravel.cn
  8. // +----------------------------------------------------------------------
  9. // | Author: laravel开发员 <laravel.qq.com>
  10. // +----------------------------------------------------------------------
  11. namespace App\Services\Api;
  12. use App\Models\AccountLogModel;
  13. use App\Models\BalanceLogModel;
  14. use App\Models\MemberModel;
  15. use App\Models\MerchantCategoryModel;
  16. use App\Models\MerchantModel;
  17. use App\Services\BaseService;
  18. use App\Services\ConfigService;
  19. use App\Services\RedisService;
  20. use App\Services\SmsService;
  21. use App\Services\WalletService;
  22. use Illuminate\Support\Facades\DB;
  23. /**
  24. * 商户服务管理-服务类
  25. * @author laravel开发员
  26. * @since 2020/11/11
  27. * Class MerchantService
  28. * @package App\Services\Api
  29. */
  30. class MerchantService extends BaseService
  31. {
  32. // 静态对象
  33. protected static $instance = null;
  34. /**
  35. * 构造函数
  36. * @author laravel开发员
  37. * @since 2020/11/11
  38. * MerchantService constructor.
  39. */
  40. public function __construct()
  41. {
  42. $this->model = new MerchantModel();
  43. }
  44. /**
  45. * 静态入口
  46. * @return static|null
  47. */
  48. public static function make()
  49. {
  50. if (!self::$instance) {
  51. self::$instance = (new static());
  52. }
  53. return self::$instance;
  54. }
  55. /**
  56. * 获取缓存列表
  57. * @param $position
  58. * @param int $num
  59. * @return array|mixed
  60. */
  61. public function getDataList($params, $pageSize = 15, $refresh = false, $field = '')
  62. {
  63. $page = request()->post('page', 1);
  64. $cacheKey = "caches:merchant:page_{$page}_" . md5(json_encode($params).$pageSize);
  65. $datas = RedisService::get($cacheKey);
  66. $data = isset($datas['data'])? $datas['data'] : [];
  67. if ($datas && $data && !$refresh) {
  68. return [
  69. 'list'=> $data,
  70. 'total'=> isset($datas['total'])? $datas['total'] : 0,
  71. 'pageSize'=>$pageSize
  72. ];
  73. }
  74. $field = $field ? $field : 'lev_a.id,lev_a.user_id,lev_a.name,lev_a.logo,lev_a.type,lev_a.country,lev_a.city,lev_a.category_id,lev_c.name as category_name,lev_a.description,lev_a.service_time,lev_a.receive_num,lev_a.status';
  75. $order = 'lev_a.id desc';
  76. $sortType = isset($params['sort_type'])? $params['sort_type'] : 0;
  77. if($sortType == 1){
  78. $order = 'lev_a.receive_num desc, lev_a.create_time desc';
  79. }
  80. $datas = $this->model->from('merchant as a')
  81. ->leftJoin('member as b','b.id','=','a.user_id')
  82. ->leftJoin('merchant_category as c','c.id','=','a.category_id')
  83. ->where(['a.mark' => 1,'b.mark'=>1])
  84. ->where(function ($query) use ($params) {
  85. $kw = isset($params['kw']) ? trim($params['kw']) : '';
  86. if ($kw) {
  87. $query->where('a.name', 'like', "%{$kw}%");
  88. }
  89. })
  90. ->where(function ($query) use ($params) {
  91. // 商户类型
  92. $type = isset($params['type']) ? intval($params['type']) : 0;
  93. if ($type) {
  94. $query->where('a.type', $type);
  95. }
  96. // 状态
  97. $status = isset($params['status']) && $params['status']>=0 ? intval($params['status']) : 2;
  98. if ($status>0) {
  99. $query->where('a.status', $status);
  100. }else{
  101. $query->whereIn('a.status',[1,2]);
  102. }
  103. // 经营类目
  104. $category = isset($params['category_id']) ? intval($params['category_id']) : 0;
  105. if ($category) {
  106. $query->where('a.category_id', $category);
  107. }
  108. // 市
  109. $city = isset($params['city']) ? trim($params['city']) : '';
  110. if ($city) {
  111. $query->where(function($query) use($city){
  112. $query->where('a.city', $city)->orWhere('a.address','like',"%{$city}%");
  113. });
  114. }
  115. $locale = isset($params['locale']) ? trim($params['locale']) : '';
  116. if ($locale) {
  117. $query->where(function($query) use($locale){
  118. $query->where('a.country_code', $locale);
  119. });
  120. }
  121. })
  122. ->selectRaw($field)
  123. ->orderByRaw($order)
  124. ->paginate($pageSize > 0 ? $pageSize : 9999999);
  125. $datas = $datas ? $datas->toArray() : [];
  126. if ($datas) {
  127. foreach($datas['data'] as &$item){
  128. $item['logo'] = $item['logo'] ? get_image_url($item['logo']) : '';
  129. }
  130. unset($item);
  131. RedisService::set($cacheKey, $datas, rand(3, 5));
  132. }
  133. return [
  134. 'list'=> isset($datas['data'])? $datas['data'] : [],
  135. 'total'=> isset($datas['total'])? $datas['total'] : 0,
  136. 'pageSize'=>$pageSize
  137. ];
  138. }
  139. /**
  140. * 获取详情
  141. * @param $id 商家ID
  142. * @param string $type
  143. * @return array|mixed
  144. */
  145. public function getInfoById($userId, $type='info', $id=0)
  146. {
  147. $cacheKey = "caches:merch:{$type}_{$userId}_{$id}";
  148. $info = RedisService::get($cacheKey);
  149. if($info){
  150. return $info;
  151. }
  152. $where = ['a.mark'=>1,'b.mark'=>1];
  153. if($id){
  154. $where['a.id'] = $id;
  155. }else if($userId){
  156. $where['a.user_id'] = $userId;
  157. }
  158. $field = ['a.id','a.name','a.user_id','a.type','a.logo','a.category_id','a.business_img','a.albums','a.country','a.city','a.address','a.usdt','a.service_time','a.withdraw_total','a.status','b.username','b.nickname'];
  159. $info = $this->model->from('merchant as a')->with(['category'])
  160. ->leftJoin('member as b','b.id','=','a.user_id')
  161. ->where($where)
  162. ->select($field)
  163. ->first();
  164. $info = $info? $info->toArray() : [];
  165. if($info){
  166. if(isset($info['logo'])){
  167. $info['logo'] = $info['logo']? get_image_url($info['logo']) : '';
  168. }
  169. if(isset($info['business_img']) && $info['business_img']){
  170. $info['business_img'] = get_image_url($info['business_img']);
  171. }
  172. if(isset($info['albums'])){
  173. $info['albums'] = $info['albums']? json_decode($info['albums'], true) : [];
  174. $info['albums'] = $info['albums']? get_images_preview($info['albums']) : [];
  175. }
  176. // 收款二维码
  177. $data = ['mid'=> $info['id'],'scene'=>'merch','type'=>'payment'];
  178. $qrcode = MemberService::make()->makeQrcode(json_encode($data));
  179. $info['qrcode'] = $qrcode? get_image_url($qrcode):'';
  180. $info['day_usdt'] = moneyFormat(AccountLogService::make()->getCountDataByDate($info['id'],1,2,1),2);
  181. $info['total_usdt'] = moneyFormat(AccountLogService::make()->getCountDataByDate($info['id'],1,2,0),2);
  182. RedisService::set($cacheKey, $info, rand(2, 3));
  183. }
  184. return $info;
  185. }
  186. /**
  187. * 获取缓存信息
  188. * @param $where
  189. * @param array $field
  190. * @param int $expired
  191. * @return array|mixed
  192. */
  193. public function getCacheInfo($where, $field = [], $expired = 0)
  194. {
  195. $cacheKey = "caches:merchant:info:cache_" . md5(json_encode($where, 256) . json_encode($field, 256) . $expired);
  196. $info = RedisService::get($cacheKey);
  197. if ($info) {
  198. return $info;
  199. }
  200. $defaultField = ['id','user_id', 'name', 'mobile', 'logo', 'category', 'usdt', 'status'];
  201. $field = $field ? $field : $defaultField;
  202. $info = $this->model->where($where)->where('mark', 1)->select($field)->first();
  203. $info = $info ? $info->toArray() : [];
  204. if ($info) {
  205. if (isset($info['logo'])) {
  206. $info['logo'] = $info['logo']? $info['logo'] : '/images/member/logo.png';
  207. $info['logo_preview'] = $info['logo']? get_image_url($info['logo']) : '';
  208. }
  209. RedisService::set($cacheKey, $info, $expired ? $expired : rand(3, 5));
  210. }
  211. return $info;
  212. }
  213. /**
  214. * 添加或编辑
  215. * @return array
  216. * @since 2020/11/11
  217. * @author laravel开发员
  218. */
  219. public function edit()
  220. {
  221. $data = request()->all();
  222. // 图片处理
  223. $cover = $data['cover'] ? trim($data['cover']) : '';
  224. if (strpos($cover, "temp")) {
  225. $data['cover'] = save_image($cover, 'ad');
  226. } else {
  227. $data['cover'] = str_replace(IMG_URL, "", $data['cover']);
  228. }
  229. // 开始时间
  230. if (isset($data['start_time'])) {
  231. $data['start_time'] = strtotime($data['start_time']);
  232. }
  233. // 结束时间
  234. if (isset($data['end_time'])) {
  235. $data['end_time'] = strtotime($data['end_time']);
  236. }
  237. return parent::edit($data); // TODO: Change the autogenerated stub
  238. }
  239. /**
  240. * 修改信息
  241. * @param $userId
  242. * @param $params
  243. * @return array|false|int[]
  244. */
  245. public function saveInfo($userId, $params)
  246. {
  247. // 验证是否入驻过和入驻状态
  248. $info = $this->model->where(['user_id'=> $userId])->select('id','name','status','mark')->first();
  249. $status = isset($info['status'])? $info['status'] : 0;
  250. $mark = isset($info['mark'])? $info['mark'] : 0;
  251. $merchId = isset($info['id'])? $info['id'] : 0;
  252. if($merchId && empty($info)){
  253. $this->error = 2216;
  254. return false;
  255. }
  256. // 是否被冻结
  257. if($merchId && $status == 3 && $mark){
  258. $this->error = 2202;
  259. return false;
  260. }
  261. // 验证账户是否正常
  262. $userInfo = MemberService::make()->getCacheInfo(['id'=>$userId], ['id','status']);
  263. $status = isset($userInfo['status'])? $userInfo['status'] : 0;
  264. if(empty($userInfo) || $status != 1){
  265. $this->error = 2017;
  266. return false;
  267. }
  268. $type = isset($params['type'])? intval($params['type']) : 0;
  269. $category = isset($params['category'])? intval($params['category']) : 0;
  270. $lng = isset($params['lng'])? floatval($params['lng']) : 0;
  271. $lat = isset($params['lat'])? floatval($params['lat']) : 0;
  272. $address = isset($params['address'])? trim($params['address']) : '';
  273. $albums = isset($params['albums'])? get_format_images($params['albums']) : '';
  274. $file1 = isset($params['file1'])? get_format_images($params['file1']) : '';
  275. $file2 = isset($params['file2'])? get_format_images($params['file2']) : '';
  276. $file3 = isset($params['file3'])? get_format_images($params['file3']) : '';
  277. $alipayQrcodeData = isset($params['alipay_qrcode'])? $params['alipay_qrcode'] : [];
  278. $alipayQrcode = isset($alipayQrcodeData[0]['url'])? get_image_path($alipayQrcodeData[0]['url']) : '';
  279. $wxpayQrcodeData = isset($params['wxpay_qrcode'])? $params['wxpay_qrcode'] : [];
  280. $wxpayQrcode = isset($wxpayQrcodeData[0]['url'])? get_image_path($wxpayQrcodeData[0]['url']) : '';
  281. $logoData = isset($params['logo'])? $params['logo'] : [];
  282. $logo = isset($logoData[0]['url'])? get_image_path($logoData[0]['url']) : '';
  283. $name = isset($params['name'])? $params['name'] : '';
  284. // 验证分类
  285. if($category && !MerchantCategoryModel::where(['id'=> $category,'status'=>1,'mark'=>1])->value('id')){
  286. $this->error = 2203;
  287. return false;
  288. }
  289. // 验证logo
  290. if(empty($logo)){
  291. $this->error = 2204;
  292. return false;
  293. }
  294. // 位置信息
  295. if($type == 1 && (empty($lat) || empty($lng) || empty($address))){
  296. $this->error = 2210;
  297. //return false;
  298. }
  299. // 证书
  300. if(empty($file1)){
  301. $this->error = $type == 1? 2206 : 2211;
  302. return false;
  303. }
  304. if(empty($file2)){
  305. $this->error = 2207;
  306. return false;
  307. }
  308. if(empty($file3)){
  309. $this->error = $type==1? 2208 : 2209;
  310. return false;
  311. }
  312. // 收款码
  313. if(empty($alipayQrcode) || empty($wxpayQrcode)){
  314. $this->error = 2205;
  315. return false;
  316. }
  317. // 入驻数据
  318. $data = [
  319. 'name' => $name,
  320. 'user_id' => $userId,
  321. 'category'=> $category,
  322. 'type'=> $type,
  323. 'logo'=> $logo,
  324. 'albums'=> $albums? $albums : '',
  325. 'qualification_imgs'=> $file1? $file1 : '',
  326. 'other_certificates'=> $file2? $file2 : '',
  327. 'idcard_imgs'=> $file3? $file3 : '',
  328. 'alipay_qrcode'=> $alipayQrcode? $alipayQrcode : '',
  329. 'wxpay_qrcode'=> $wxpayQrcode? $wxpayQrcode : '',
  330. 'lng'=> $lng,
  331. 'lat'=> $lat,
  332. 'address'=> $address,
  333. 'province'=> isset($params['province'])? trim($params['province']) : '',
  334. 'city'=> isset($params['city'])? trim($params['city']) : '',
  335. 'district'=> isset($params['district'])? trim($params['district']) : '',
  336. 'intro'=> isset($params['intro'])? trim($params['intro']) : '',
  337. 'mobile'=> isset($params['mobile'])? trim($params['mobile']) : '',
  338. 'business_scope'=> isset($params['business_scope'])? trim($params['business_scope']) : '',
  339. 'service_time'=> isset($params['service_time'])? trim($params['service_time']) : '',
  340. 'create_time'=> time(),
  341. 'update_time'=> time(),
  342. 'status'=> 1,
  343. 'mark'=> 1,
  344. ];
  345. // 写入数据
  346. if($merchId){
  347. if($this->model->where(['id'=> $merchId])->update($data)){
  348. $this->error = 2228;
  349. RedisService::keyDel("caches:merchant:info:temp_{$userId}*");
  350. return ['id'=> $merchId];
  351. }else{
  352. $this->error = 2229;
  353. return false;
  354. }
  355. }else{
  356. if($merchId = $this->model->insertGetId($data)){
  357. $this->error = 2228;
  358. RedisService::keyDel("caches:merchant:info:temp_{$userId}*");
  359. return ['id'=> $merchId];
  360. }else{
  361. $this->error = 2229;
  362. return false;
  363. }
  364. }
  365. }
  366. /**
  367. * 申请入驻
  368. * @param $userId
  369. * @param $params
  370. * @return array|false|int[]
  371. */
  372. public function apply($userId, $params)
  373. {
  374. // 验证是否入驻过和入驻状态
  375. $info = $this->model->where(['user_id'=> $userId])->select('id','name','status','mark')->first();
  376. $status = isset($info['status'])? $info['status'] : 0;
  377. $mark = isset($info['mark'])? $info['mark'] : 0;
  378. $merchId = isset($info['id'])? $info['id'] : 0;
  379. if($merchId && $status == 2 && $mark){
  380. $this->error = 2801;
  381. return false;
  382. }
  383. // 是否被冻结
  384. if($merchId && $status == 4){
  385. $this->error = 2802;
  386. return false;
  387. }
  388. // 验证账户是否正常
  389. $userInfo = MemberService::make()->getCacheInfo(['id'=>$userId], ['id','status']);
  390. $status = isset($userInfo['status'])? $userInfo['status'] : 0;
  391. if(empty($userInfo) || $status != 1){
  392. $this->error = 2017;
  393. return false;
  394. }
  395. $type = isset($params['type'])? intval($params['type']) : 1;
  396. $category = isset($params['categoty_id'])? intval($params['categoty_id']) : 0;
  397. $currency = isset($params['currency'])? trim($params['currency']) : '';
  398. $country = isset($params['country'])? trim($params['country']) : '';
  399. $city = isset($params['city'])? trim($params['city']) : '';
  400. $address = isset($params['address'])? trim($params['address']) : '';
  401. $albums = isset($params['albums'])? get_format_images($params['albums']) : '';
  402. $businessImg = isset($params['business_img'])? get_image_path($params['business_img']) : '';
  403. $logo = isset($params['logo'])? get_image_path($params['logo']) : '';
  404. $name = isset($params['name'])? $params['name'] : '';
  405. // 验证分类
  406. if($category && !MerchantCategoryModel::where(['id'=> $category,'status'=>1,'mark'=>1])->value('id')){
  407. $this->error = 2803;
  408. return false;
  409. }
  410. // 验证logo
  411. if(empty($logo)){
  412. $this->error = 2804;
  413. return false;
  414. }
  415. $mobile = isset($params['mobile'])? trim($params['mobile']) : '';
  416. $telegram = isset($params['telegram'])? trim($params['telegram']) : '';
  417. if(empty($mobile) && empty($telegram)){
  418. $this->error = 2805;
  419. return false;
  420. }
  421. // 地址信息
  422. if(empty($country) || empty($city) || empty($address)){
  423. $this->error = 2806;
  424. return false;
  425. }
  426. if(empty($currency)){
  427. $this->error = 2807;
  428. return false;
  429. }
  430. // 营业执照
  431. if(empty($businessImg)){
  432. $this->error = 2808;
  433. return false;
  434. }
  435. // 入驻数据
  436. $data = [
  437. 'name' => $name,
  438. 'user_id' => $userId,
  439. 'category_id'=> $category,
  440. 'type'=> $type,
  441. 'logo'=> $logo,
  442. 'albums'=> $albums? $albums : '',
  443. 'business_img'=> $businessImg? $businessImg : '',
  444. 'currency'=> $currency,
  445. 'country'=> $country,
  446. 'city'=> $city,
  447. 'address'=> $address,
  448. 'description'=> isset($params['description'])? trim($params['description']) : '',
  449. 'mobile'=> $mobile,
  450. 'telegram'=> $telegram,
  451. 'service_time'=> isset($params['service_time'])? trim($params['service_time']) : '',
  452. 'create_time'=> time(),
  453. 'update_time'=> time(),
  454. 'status'=> 1,
  455. 'mark'=> 1,
  456. ];
  457. // 写入数据
  458. if($merchId){
  459. if($this->model->where(['id'=> $merchId])->update($data)){
  460. $this->error = 2809;
  461. return ['id'=> $merchId];
  462. }else{
  463. $this->error = 2810;
  464. return false;
  465. }
  466. }else{
  467. if($merchId = $this->model->insertGetId($data)){
  468. $this->error = 2811;
  469. return ['id'=> $merchId];
  470. }else{
  471. $this->error = 2810;
  472. return false;
  473. }
  474. }
  475. }
  476. /**
  477. * 获取商家入驻信息
  478. * @param $userId
  479. * @return mixed
  480. */
  481. public function getApplyInfo($userId)
  482. {
  483. $info = $this->model->with(['category'])->where(['user_id'=> $userId,'mark'=>1])
  484. ->orderBy('id','desc')
  485. ->first();
  486. $info = $info? $info->setHidden(['usdt','update_time','mark'])->toArray() : [];
  487. if($info){
  488. $info['logo'] = isset($info['logo']) && $info['logo']? get_image_url($info['logo']) : '';
  489. $info['business_img'] = isset($info['business_img']) && $info['business_img']? get_image_url($info['business_img']) : '';
  490. $albums = isset($info['albums']) && $info['albums']? json_decode($info['albums'], true) : [];
  491. $info['albums'] = $albums? get_images_preview($albums) : [];
  492. if(isset($info['category']) && $info['category']){
  493. $info['category_name'] = isset($info['category']['name'])? $info['category']['name'] : '';
  494. $info['category_id'] = isset($info['category']['id'])? $info['category']['id'] : '';
  495. }
  496. }
  497. return $info;
  498. }
  499. /**
  500. * 修改
  501. * @param $userId
  502. * @param $params
  503. * @return bool
  504. */
  505. public function modify($userId, $params)
  506. {
  507. // 用户验证
  508. $info = $this->model->with(['member'])->where(['user_id' => $userId, 'mark' => 1])
  509. ->select(['id','user_id', 'status'])
  510. ->first();
  511. if (!$info || $info['status'] != 2) {
  512. $this->error = 2812;
  513. return false;
  514. }
  515. // 验证账户是否正常
  516. $userInfo = MemberService::make()->getCacheInfo(['id'=>$userId], ['id','status']);
  517. $status = isset($userInfo['status'])? $userInfo['status'] : 0;
  518. if(empty($userInfo) || $status != 1){
  519. $this->error = 2017;
  520. return false;
  521. }
  522. // 手机号
  523. $mobile = isset($params['mobile']) ? $params['mobile'] : '';
  524. if (isset($params['mobile']) && $mobile) {
  525. $data['mobile'] = $mobile;
  526. }
  527. $telegram = isset($params['telegram']) ? $params['telegram'] : '';
  528. if (isset($params['telegram']) && $telegram) {
  529. $data['telegram'] = $telegram;
  530. }
  531. if(isset($params['name']) && $params['name']){
  532. $data['name'] = trim($params['name']);
  533. }
  534. if(isset($params['service_time']) && $params['service_time']){
  535. $data['service_time'] = trim($params['service_time']);
  536. }
  537. $address = isset($params['address'])? trim($params['address']) : '';
  538. $albums = isset($params['albums'])? get_format_images($params['albums']) : '';
  539. $logo = isset($params['logo'])? get_image_path($params['logo']) : '';
  540. if(isset($params['address']) && $address){
  541. $data['address'] = $address;
  542. }
  543. if(isset($params['logo']) && $logo){
  544. $data['logo'] = $logo;
  545. }
  546. if(isset($params['albums']) && $albums){
  547. $data['albums'] = $albums;
  548. }
  549. // 修改数据
  550. RedisService::clear("caches:merch:detail_{$info['id']}");
  551. RedisService::keyDel("caches:merchant:info:temp*");
  552. $this->model->where(['user_id' => $userId])->update($data);
  553. $this->error = 1008;
  554. return true;
  555. }
  556. /**
  557. * 余额提现
  558. * @param $userId
  559. * @param $params
  560. * @return array|false
  561. */
  562. public function withdraw($userId, $params)
  563. {
  564. $money = isset($params['money'])? floatval($params['money']) : 0;
  565. $payPassword = isset($params['pay_password'])? trim($params['pay_password']) : '';
  566. $userType = isset($params['user_type']) && $params['user_type']? intval($params['user_type']) : 1;
  567. if($money<=0){
  568. $this->error = 2401;
  569. return false;
  570. }
  571. if(!in_array($userType,[1,2,3])){
  572. $this->error = 2404;
  573. return false;
  574. }
  575. $merchant = $this->model->with(['member'])->where(['user_id' => $userId, 'mark' => 1])
  576. ->select(['id','user_id','name','usdt','status','trade_status'])
  577. ->first();
  578. $userInfo = $merchant['member'];
  579. $status = isset($userInfo['status'])? $userInfo['status'] : 0;
  580. $userUsdt = isset($userInfo['usdt'])? $userInfo['usdt'] : 0;
  581. if(isset($userInfo['pay_password'])){
  582. $userPayPassword = $userInfo['pay_password'];
  583. }else{
  584. $userPayPassword = DB::table('member')->where('id',$userId)->value('pay_password');
  585. }
  586. $merchantUsdt = isset($merchant['usdt'])? $merchant['usdt'] : 0;
  587. $merchantId = isset($merchant['id'])? $merchant['id'] : 0;
  588. $merchantTradeStatus = isset($merchant['trade_status'])? $merchant['trade_status'] : 0;
  589. if(empty($userInfo) || $status != 1){
  590. $this->error = 2024;
  591. return false;
  592. }
  593. if($userType == 2 && (empty($merchant) || !in_array($merchantTradeStatus,[1,2]))){
  594. $this->error = 2024;
  595. return false;
  596. }
  597. // 提现金额验证
  598. $accountUsdt = $userType==1? $userUsdt : $merchantUsdt;
  599. if ($money > $accountUsdt) {
  600. $this->error = web_lang(2402, ['money' => $accountUsdt]);
  601. return false;
  602. }
  603. // 提现账户
  604. $trcUrl = isset($userInfo['trc_url']) ? $userInfo['trc_url'] : '';
  605. if (empty($trcUrl)) {
  606. $this->error = 2403;
  607. return false;
  608. }
  609. // 提现验证usdt钱包余额
  610. $balance = (new \App\Services\WalletService)->getTrcUsdtBalance($userInfo['trc_url']);
  611. if($balance < $money){
  612. $this->error = web_lang(2402, ['trcUsdtBalance' => $balance]);
  613. return false;
  614. }
  615. if($userPayPassword != get_password($payPassword)){
  616. $this->error = 2038;
  617. return false;
  618. }
  619. $cacheKey = "caches:member:withdraw:lock_{$userId}";
  620. if(RedisService::get($cacheKey)){
  621. $this->error = 1034;
  622. return false;
  623. }
  624. DB::beginTransaction();
  625. RedisService::set($cacheKey, $userInfo, rand(2,3));
  626. // 提现记录
  627. $orderNo = get_order_num('DW');
  628. $feeRate = ConfigService::make()->getConfigByCode('withdraw_fee_rate',5);
  629. $feeRate = $feeRate>0 && $feeRate<100? moneyFormat($feeRate/100,2) : 0;
  630. $fee = round($money*$feeRate, 2);
  631. $realUsdt = moneyFormat($money - $fee, 2);
  632. $data = [
  633. 'order_no'=> $orderNo,
  634. 'user_id'=> $userId,
  635. 'type'=> 2,
  636. 'user_type'=> $userType,
  637. 'coin_type'=> 1,
  638. 'money'=> $money,
  639. 'actual_money'=> $realUsdt,
  640. 'fee'=> $fee,
  641. 'trc_url'=> $trcUrl,
  642. 'pay_type'=> 20,
  643. 'date'=> date('Y-m-d'),
  644. 'create_time'=> time(),
  645. 'update_time'=> time(),
  646. 'status'=> 1,
  647. 'mark'=> 1,
  648. ];
  649. if(!$id = BalanceLogModel::insertGetId($data)){
  650. DB::rollBack();
  651. $this->error = 2405;
  652. RedisService::clear($cacheKey);
  653. return false;
  654. }
  655. // 商户扣款
  656. if($userType == 2){
  657. $updateData = ['usdt'=>DB::raw("usdt - {$money}"),'update_time'=> time()];
  658. if(!MerchantModel::where(['user_id'=> $userId,'mark'=>1])->update($updateData)){
  659. DB::rollBack();
  660. $this->error = 2406;
  661. RedisService::clear($cacheKey);
  662. return false;
  663. }
  664. // 明细
  665. $log = [
  666. 'user_id' => $merchantId,
  667. 'source_id' => $userId,
  668. 'source_order_no' => $orderNo,
  669. 'type' => 5,
  670. 'coin_type' => 1,
  671. 'user_type'=> 2,
  672. 'money' => -$money,
  673. 'actual_money' => -$money,
  674. 'balance' => $merchantUsdt,
  675. 'create_time' => time(),
  676. 'update_time' => time(),
  677. 'remark' => "商户账户余额提现",
  678. 'status' => 1,
  679. 'mark' => 1,
  680. ];
  681. if (!AccountLogModel::insertGetId($log)) {
  682. $this->error = 2407;
  683. DB::rollBack();
  684. RedisService::clear($cacheKey);
  685. return false;
  686. }
  687. }
  688. // 用户扣款
  689. else{
  690. $updateData = ['usdt'=>DB::raw("usdt - {$money}"),'update_time'=> time()];
  691. if(!MemberModel::where(['id'=> $userId,'mark'=>1])->update($updateData)){
  692. DB::rollBack();
  693. $this->error = 2406;
  694. RedisService::clear($cacheKey);
  695. return false;
  696. }
  697. // 明细
  698. $log = [
  699. 'user_id' => $userId,
  700. 'source_id' => 0,
  701. 'source_order_no' => $orderNo,
  702. 'type' => 5,
  703. 'coin_type' => 1,
  704. 'user_type'=> 1,
  705. 'money' => -$money,
  706. 'actual_money' => -$money,
  707. 'balance' => $userUsdt,
  708. 'create_time' => time(),
  709. 'update_time' => time(),
  710. 'remark' => "USDT余额提现",
  711. 'status' => 1,
  712. 'mark' => 1,
  713. ];
  714. if (!AccountLogModel::insertGetId($log)) {
  715. $this->error = 2407;
  716. DB::rollBack();
  717. RedisService::clear($cacheKey);
  718. return false;
  719. }
  720. }
  721. DB::commit();
  722. // 站内消息
  723. $dateTime = date('Y-m-d H:i:s');
  724. $title = $userType == 1 ? 'USDT余额提现申请成功' : '商户余额提现申请成功';
  725. $message = $userType == 1 ? "您在{$dateTime}(UTC+8)申请提现{$money}USDT余额成功,请耐心等候审核!!!" : "您在{$dateTime}(UTC+8)申请提现{$money}USDT商户余额成功,请耐心等候审核!!!";
  726. MessageService::make()->pushMessage($userId, $title, $message);
  727. // 提现自动审核,低于该金额自动审核
  728. $autoCheckUsdt = ConfigService::make()->getConfigByCode('withdraw_auto_money', 300);
  729. $autoCheckUsdt = $autoCheckUsdt > 0 ? $autoCheckUsdt : 0;
  730. if ($money <= $autoCheckUsdt) {
  731. // 打款处理
  732. $result = WalletService::make()->usdtTrcTransfer($trcUrl, $realUsdt);
  733. $txID = isset($result['txId']) ? $result['txId'] : '';
  734. $payAddress = isset($result['address']) ? $result['address'] : '';
  735. if ($txID && $payAddress) {
  736. $updateData = ['hash'=> $txID,'wallet_url'=> $payAddress,'audit_remark'=>'自动审核打款','status'=>2,'update_time'=>time()];
  737. if(BalanceLogModel::where(['order_no'=> $orderNo,'user_type'=> $userType])->update($updateData)){
  738. $title = $userType == 1 ? 'USDT余额提现审核成功' : '商户余额提现审核成功';
  739. $message = $userType == 1 ? "您在{$dateTime}(UTC+8)申请提现{$money}USDT余额审核成功,请耐心等候打款到账!!!" : "您在{$dateTime}(UTC+8)申请提现{$money}USDT商户余额审核成功,请耐心等候打款到账!!!";
  740. MessageService::make()->pushMessage($userId, $title, $message);
  741. AccountLogModel::where(['source_order_no'=> $orderNo])->update(['hash'=> $txID,'update_time'=>time()]);
  742. // 平台明细
  743. $log = [
  744. 'user_id' => 0,
  745. 'source_id' => $userId,
  746. 'source_order_no' => $orderNo,
  747. 'type' => 5,
  748. 'coin_type' => 1,
  749. 'user_type'=> 4,
  750. 'money' => $fee,
  751. 'actual_money' => $fee,
  752. 'balance' => 0,
  753. 'create_time' => time(),
  754. 'update_time' => time(),
  755. 'hash' => $txID,
  756. 'remark' => "USDT余额提现",
  757. 'status' => 1,
  758. 'mark' => 1,
  759. ];
  760. AccountLogModel::insertGetId($log);
  761. // 平台流水
  762. FinanceService::make()->saveLog(0, $fee, 1);
  763. }
  764. }
  765. }
  766. $this->error = $title;
  767. RedisService::clear($cacheKey);
  768. return [
  769. 'id'=> $id,
  770. 'money'=> $money,
  771. 'user_type'=> $userType,
  772. ];
  773. }
  774. }