AdvertOrderService.php 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021
  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\Common;
  12. use App\Models\AdvertModel;
  13. use App\Models\AdvertOrderModel;
  14. use App\Models\CapitalLogModel;
  15. use App\Models\MemberModel;
  16. use App\Services\Api\MemberPaymentService;
  17. use App\Services\BaseService;
  18. use App\Services\ConfigService;
  19. use App\Services\ChatMessageService;
  20. use App\Services\RedisService;
  21. /**
  22. * 用户广告订单-服务类
  23. * Class AdvertOrderService
  24. * @package App\Services\Common
  25. */
  26. class AdvertOrderService extends BaseService
  27. {
  28. // 静态对象
  29. protected static $instance = null;
  30. /**
  31. * 构造函数
  32. * @since 2020/11/10
  33. * LoginService constructor.
  34. */
  35. public function __construct()
  36. {
  37. $this->model = new AdvertOrderModel();
  38. $this->advertModel = new AdvertModel();
  39. $this->memberModel = new MemberModel();
  40. $this->capitalModel = new CapitalLogModel();
  41. }
  42. /**
  43. * 静态入口
  44. * @return static|null
  45. */
  46. public static function make()
  47. {
  48. if (!self::$instance) {
  49. self::$instance = (new static());
  50. }
  51. return self::$instance;
  52. }
  53. /**
  54. * 订单列表
  55. * @param $params
  56. * @param int $pageSize
  57. * @return array
  58. */
  59. public function getDataList($params, $pageSize = 15)
  60. {
  61. $list = $this->model->from('advert_order as a')
  62. ->leftJoin('member as b', 'b.id', '=', 'a.business_id')
  63. ->leftJoin('member as c', 'c.id', '=', 'a.user_id')
  64. ->where(function ($query) use ($params) {
  65. $query->where(['a.mark' => 1])->where('a.status', '>', 0);
  66. $orderNo = isset($params['order_no']) && $params['order_no'] ? trim($params['order_no']) : '';
  67. if ($orderNo) {
  68. $query->where('a.order_no', 'like', "%{$orderNo}%");
  69. }
  70. $type = isset($params['type']) ? intval($params['type']) : 0;
  71. if ($type > 0) {
  72. $query->where(['a.type' => $type]);
  73. }
  74. $businessId = isset($params['business_id']) ? $params['business_id'] : 0;
  75. $userType = isset($params['user_type']) ? intval($params['user_type']) : 0;
  76. if ($userType > 0 && $businessId<=0) {
  77. $query->where(['c.user_type' => $userType]);
  78. }
  79. // 日期
  80. $date = isset($params['date']) ? $params['date'] : [];
  81. $start = isset($date[0])? $date[0] : '';
  82. $end = isset($date[1])? $date[1] : '';
  83. $end = $start>=$end? '' : $end;
  84. if ($start) {
  85. $query->where('a.create_time','>=', strtotime($start));
  86. }
  87. if($end){
  88. $query->where('a.create_time','<', strtotime($end));
  89. }
  90. $exceptionStatus = isset($params['exception_status']) ? intval($params['exception_status']) : 0;
  91. if ($exceptionStatus > 0) {
  92. $query->where(['a.exception_status' => $exceptionStatus]);
  93. }
  94. $status = isset($params['status']) ? intval($params['status']) : 0;
  95. if ($status > 0) {
  96. $query->where(['a.status' => $status]);
  97. }
  98. $userId = isset($params['user_id']) ? $params['user_id'] : 0;
  99. if ($userId > 0) {
  100. $query->where('a.user_id', $userId);
  101. }
  102. if ($businessId > 0) {
  103. $query->where('a.business_id', $businessId);
  104. }
  105. })
  106. ->select(['a.*', 'b.username', 'c.username as c_username'])
  107. ->orderBy('a.create_time', 'desc')
  108. ->orderBy('a.id', 'desc')
  109. ->paginate($pageSize > 0 ? $pageSize : 9999999);
  110. $list = $list ? $list->toArray() : [];
  111. if ($list) {
  112. $payTypes = [1 => '银行卡', 2 => '微信', 3 => '支付宝', 4 => '其他'];
  113. $overTime = ConfigService::make()->getConfigByCode('trade_order_overtime');
  114. $overTime = $overTime ? $overTime : 0;
  115. foreach ($list['data'] as &$item) {
  116. $item['idcardData'] = $item['idcard_data'] ? json_decode($item['idcard_data'], true) : [];
  117. $item['paymentData'] = $item['payment_data'] ? json_decode($item['payment_data'], true) : [];
  118. $item['create_time_text'] = $item['create_time'] ? datetime($item['create_time'], 'Y-m-d H:i:s') : '';
  119. $item['update_time_text'] = $item['update_time'] ? datetime($item['update_time'], 'Y-m-d H:i:s') : '';
  120. $item['time_text'] = $item['create_time'] ? datetime($item['create_time'], 'H:i') : '';
  121. $item['utime_text'] = $item['update_time'] ? datetime($item['update_time'], 'H:i') : '';
  122. $item['pay_time_text'] = $item['pay_time'] ? datetime($item['pay_time'], 'Y-m-d H:i') : '';
  123. $item['username_text'] = $item['username'] ? format_account($item['username']) : '';
  124. $item['c_username_text'] = $item['c_username'] ? format_account($item['c_username']) : '';
  125. $item['exception_img'] = $item['exception_img'] ? get_image_url($item['exception_img']) : '';
  126. $item['pay_img'] = $item['pay_img'] ? get_image_url($item['pay_img']) : '';
  127. $item['paymentData']['qrcode'] = isset($item['paymentData']['qrcode']) && $item['paymentData']['qrcode'] ? get_image_url($item['paymentData']['qrcode']) : '';
  128. $overTime = max(0, intval($item['create_time']) + $overTime * 60 - time());
  129. $item['overtime_text'] = in_array($item['status'], [1, 2]) && $overTime ? date('H:i', $overTime) : '';
  130. $payType = isset($item['pay_type']) ? $item['pay_type'] : 0;
  131. $item['pay_name'] = isset($payTypes[$payType]) ? $payTypes[$payType] : '其他';
  132. $item['chat_key'] = getChatKey($item['user_id'],$item['business_id']);
  133. }
  134. }
  135. return [
  136. 'pageSize' => $pageSize,
  137. 'total' => isset($list['total']) ? $list['total'] : 0,
  138. 'list' => isset($list['data']) ? $list['data'] : []
  139. ];
  140. }
  141. /**
  142. * 购买
  143. * @param $userId
  144. * @param $params
  145. * @return false|int|number
  146. */
  147. public function buy($userId, $params)
  148. {
  149. $id = isset($params['id']) ? intval($params['id']) : 0;
  150. $num = isset($params['num']) ? intval($params['num']) : 0;
  151. if ($id <= 0 || $num<=0) {
  152. $this->error = '1013';
  153. return false;
  154. }
  155. // 验证参数
  156. $config = \App\Services\ConfigService::make()->getConfigOptionByGroup(5);
  157. $tradeOpen = isset($config['trade_usdt_open']) ? $config['trade_usdt_open'] : 0;
  158. $tradePrice = isset($config['usdt_buy_price']) ? $config['usdt_buy_price'] : 0;
  159. $tradeLimitNum = isset($config['trade_no_catch']) ? $config['trade_no_catch'] : 0;
  160. // 是否开启交易
  161. if ($tradeOpen != 1) {
  162. $this->error = '1013';
  163. return false;
  164. }
  165. $info = AdvertService::make()->getInfo($id);
  166. $tradeType = isset($info['type'])? $info['type'] : 0;
  167. $priceType = isset($info['price_type'])? $info['price_type'] : 0;
  168. $price = isset($info['price'])? $info['price'] : 0;
  169. $businessId = isset($info['user_id'])? $info['user_id'] : 0;
  170. if(empty($info) || $info['status'] != 1 || $businessId<=0){
  171. $this->error = '4001';
  172. return false;
  173. }
  174. $expiredAt = isset($info['expired_at']) && $info['expired_at']? strtotime($info['expired_at']) : 0;
  175. if($expiredAt <= time()){
  176. $this->error = '4007';
  177. return false;
  178. }
  179. if($tradeType != 2){
  180. $this->error = '4003';
  181. return false;
  182. }
  183. if ($tradePrice <= 0 && $priceType == 2) {
  184. $this->error = '3002';
  185. return false;
  186. }
  187. // 浮动价格计算
  188. if ($priceType == 2) {
  189. $price = floatval($tradePrice + $price);
  190. }
  191. // 总价
  192. $total = floatval($price * $num);
  193. if($total<=0){
  194. $this->error = '4002';
  195. return false;
  196. }
  197. // 单笔限额
  198. if($total< $info['limit_min'] || $total> $info['limit_max']){
  199. $this->error = lang('4005',['min'=> $info['limit_min'],'max'=>$info['limit_max']]);
  200. return false;
  201. }
  202. // 购买用户信息
  203. $userInfo = MemberService::make()->getInfo($userId);
  204. $status = isset($userInfo['status']) ? $userInfo['status'] : 0;
  205. $idcardCheck = isset($userInfo['idcard_check']) ? $userInfo['idcard_check'] : 0;
  206. $username = isset($userInfo['username']) ? format_account($userInfo['username']) : '';
  207. if (empty($userInfo) || $status != 1) {
  208. $this->error = '2009';
  209. return false;
  210. }
  211. if($idcardCheck != 1){
  212. $this->error = '2014';
  213. return false;
  214. }
  215. // 未处理订单
  216. $noCatchOrder = $this->checkOrderNoCatch($userId, 1);
  217. if ($tradeLimitNum > 0 && $noCatchOrder >= $tradeLimitNum) {
  218. $this->error = lang(3005, ['num' => $tradeLimitNum]);
  219. return false;
  220. }
  221. // 交易商家
  222. $businessInfo = MemberService::make()->getInfo($businessId);
  223. if (empty($businessInfo)) {
  224. $this->error = '3004';
  225. return false;
  226. }
  227. $setting = MemberSettingService::make()->getInfo($businessId);
  228. $advertOnline = isset($setting['advert_online'])? $setting['advert_online'] : 0;
  229. if($advertOnline != 1){
  230. $this->error = '4006';
  231. return false;
  232. }
  233. // 购买者身份信息
  234. $idcardData = [
  235. 'idcard' => isset($userInfo['idcard']) ? $userInfo['idcard'] : '',
  236. 'idcard_check' => isset($userInfo['idcard_check']) ? $userInfo['idcard_check'] : 0,
  237. 'idcard_front_img' => isset($userInfo['idcard_front_img']) ? $userInfo['idcard_front_img'] : '',
  238. 'idcard_back_img' => isset($userInfo['idcard_back_img']) ? $userInfo['idcard_back_img'] : '',
  239. 'idcard_hand_img' => isset($userInfo['idcard_hand_img']) ? $userInfo['idcard_hand_img'] : '',
  240. ];
  241. // 收款方式
  242. $payment = MemberPaymentService::make()->getPayment($businessInfo['id']);
  243. if (empty($payment)) {
  244. $this->error = '3015';
  245. return false;
  246. }
  247. $this->model->startTrans();
  248. $orderNo = get_order_num('TA');
  249. $data = [
  250. 'user_id' => $userId,
  251. 'business_id' => isset($businessInfo['id']) ? $businessInfo['id'] : 0,
  252. 'order_no' => $orderNo,
  253. 'type' => 1,
  254. 'pay_type' => isset($params['pay_type']) ? floatval($params['pay_type']) : 1,
  255. 'price' => $price,
  256. 'num' => $num,
  257. 'total' => $total,
  258. 'payment_id' => isset($payment['id']) ? intval($payment['id']) : 0,
  259. 'idcard_data' => $idcardData ? json_encode($idcardData, 256) : '',
  260. 'payment_data' => $payment ? json_encode($payment, 256) : '',
  261. 'create_time' => time(),
  262. 'update_time' => time(),
  263. 'status' => 1,
  264. 'mark' => 1,
  265. ];
  266. if (!$order = $this->model->edit($data)) {
  267. $this->model->rollBack();
  268. $this->error = '3023';
  269. return false;
  270. }
  271. if(!$this->memberModel->where(['id'=> $businessInfo['id']])->decrement('usdt_num', $num)){
  272. $this->model->rollBack();
  273. $this->error = '3020';
  274. return false;
  275. }
  276. $data = [
  277. 'order_no'=> $orderNo,
  278. 'user_id'=> $businessInfo['id'],
  279. 'type'=> 2,
  280. 'pay_type'=> 1,
  281. 'trade_type'=> 2,
  282. 'change_type'=> 2,
  283. 'num'=> $num,
  284. 'total'=> $total,
  285. 'balance'=> floatval($businessInfo['usdt_num']-$num),
  286. 'create_time'=> time(),
  287. 'update_time'=> time(),
  288. 'status'=> 1,
  289. 'mark'=>1,
  290. 'remark'=> '交易员卖出',
  291. ];
  292. if(!$this->capitalModel->edit($data)){
  293. $this->model->rollBack();
  294. $this->error = '3014';
  295. return false;
  296. }
  297. // 订单通知
  298. $data = [
  299. 'from_uid' => $userId,
  300. 'to_uid' => $businessInfo['id'],
  301. 'type' => 3,
  302. 'order_no' => $orderNo,
  303. 'chat_key' => getChatKey($userId, $businessInfo['id']),
  304. 'message' => "您有来自客户购买广告订单:{$orderNo}的消息,请尽快回复!",
  305. 'message_type' => 1,
  306. 'data_type' => 2,
  307. 'create_time' => time(),
  308. 'update_time' => time(),
  309. 'status' => 1,
  310. 'mark' => 1,
  311. ];
  312. if (!ChatMessageService::make()->pushMessage($data)) {
  313. $this->model->rollBack();
  314. $this->error = '3031';
  315. return false;
  316. }
  317. $this->model->commit();
  318. return $order;
  319. }
  320. /**
  321. * 购买
  322. * @param $userId
  323. * @param $params
  324. * @return false|int|number
  325. */
  326. public function sell($userId, $params)
  327. {
  328. $id = isset($params['id']) ? intval($params['id']) : 0;
  329. $num = isset($params['num']) ? intval($params['num']) : 0;
  330. $paymentId = isset($params['payment_id']) ? intval($params['payment_id']) : 0;
  331. if ($id <= 0 || $num<=0 || $paymentId<=0) {
  332. $this->error = '1013';
  333. return false;
  334. }
  335. // 验证参数
  336. $config = \App\Services\ConfigService::make()->getConfigOptionByGroup(5);
  337. $tradeOpen = isset($config['trade_usdt_open']) ? $config['trade_usdt_open'] : 0;
  338. $tradePrice = isset($config['usdt_buy_price']) ? $config['usdt_sell_price'] : 0;
  339. $tradeLimitNum = isset($config['trade_no_catch']) ? $config['trade_no_catch'] : 0;
  340. // 是否开启交易
  341. if ($tradeOpen != 1) {
  342. $this->error = '1013';
  343. return false;
  344. }
  345. $info = AdvertService::make()->getInfo($id);
  346. $tradeType = isset($info['type'])? $info['type'] : 0;
  347. $priceType = isset($info['price_type'])? $info['price_type'] : 0;
  348. $price = isset($info['price'])? $info['price'] : 0;
  349. $businessId = isset($info['user_id'])? $info['user_id'] : 0;
  350. if(empty($info) || $info['status'] != 1){
  351. $this->error = '4001';
  352. return false;
  353. }
  354. $expiredAt = isset($info['expired_at']) && $info['expired_at']? strtotime($info['expired_at']) : 0;
  355. if($expiredAt <= time()){
  356. $this->error = '4007';
  357. return false;
  358. }
  359. if($tradeType != 1){
  360. $this->error = '4004';
  361. return false;
  362. }
  363. if ($tradePrice <= 0 && $priceType == 2) {
  364. $this->error = '3002';
  365. return false;
  366. }
  367. // 验证数量或金额
  368. if ($priceType == 2) {
  369. $price = floatval($tradePrice + $price);
  370. }
  371. // 单笔限额
  372. $total = floatval($price * $num);
  373. if($total<=0){
  374. $this->error = '4002';
  375. return false;
  376. }
  377. if($total< $info['limit_min'] || $total> $info['limit_max']){
  378. $this->error = lang('4005',['min'=> $info['limit_min'],'max'=>$info['limit_max']]);
  379. return false;
  380. }
  381. // 用户信息
  382. $userInfo = MemberService::make()->getInfo($userId);
  383. $status = isset($userInfo['status']) ? $userInfo['status'] : 0;
  384. $idcardCheck = isset($userInfo['idcard_check']) ? $userInfo['idcard_check'] : 0;
  385. $username = isset($userInfo['username']) && $userInfo['username'] ? format_account($userInfo['username']) : '';
  386. if ($status != 1) {
  387. $this->error = '2009';
  388. return false;
  389. }
  390. if($idcardCheck != 1){
  391. $this->error = '2014';
  392. return false;
  393. }
  394. // 未处理订单
  395. $noCatchOrder = $this->checkOrderNoCatch($userId, 2);
  396. if ($tradeLimitNum > 0 && $noCatchOrder >= $tradeLimitNum) {
  397. $this->error = lang(3005, ['num' => $tradeLimitNum]);
  398. return false;
  399. }
  400. // 交易商家
  401. $businessInfo = MemberService::make()->getInfo($businessId);
  402. if (empty($businessInfo)) {
  403. $this->error = '3004';
  404. return false;
  405. }
  406. $setting = MemberSettingService::make()->getInfo($businessId);
  407. $advertOnline = isset($setting['advert_online'])? $setting['advert_online'] : 0;
  408. if($advertOnline != 1){
  409. $this->error = '4006';
  410. return false;
  411. }
  412. // 购买者身份信息
  413. $idcardData = [
  414. 'idcard' => isset($userInfo['idcard']) ? $userInfo['idcard'] : '',
  415. 'idcard_check' => isset($userInfo['idcard_check']) ? $userInfo['idcard_check'] : 0,
  416. 'idcard_front_img' => isset($userInfo['idcard_front_img']) ? $userInfo['idcard_front_img'] : '',
  417. 'idcard_back_img' => isset($userInfo['idcard_back_img']) ? $userInfo['idcard_back_img'] : '',
  418. 'idcard_hand_img' => isset($userInfo['idcard_hand_img']) ? $userInfo['idcard_hand_img'] : '',
  419. ];
  420. // 收款方式
  421. $paymentInfo = MemberPaymentService::make()->getInfo($paymentId);
  422. if (empty($paymentInfo)) {
  423. $this->error = '3010';
  424. return false;
  425. }
  426. $paymentData = [
  427. 'payment_id' => $paymentInfo['id'],
  428. 'type' => $paymentInfo['type'],
  429. 'logo' => $paymentInfo['logo'] ? get_image_url($paymentInfo['logo']) : '',
  430. 'real_name' => $paymentInfo['real_name'],
  431. 'bank_name' => $paymentInfo['bank_name'],
  432. 'bank_card' => $paymentInfo['bank_card'],
  433. 'branch_name' => $paymentInfo['branch_name'],
  434. 'qrcode' => $paymentInfo['qrcode'] ? get_image_url($paymentInfo['qrcode']) : '',
  435. 'account' => $paymentInfo['account'],
  436. ];
  437. $this->model->startTrans();
  438. $orderNo = get_order_num('TA');
  439. $data = [
  440. 'user_id' => $userId,
  441. 'business_id' => isset($businessInfo['id']) ? $businessInfo['id'] : 0,
  442. 'order_no' => $orderNo,
  443. 'type' => 2,
  444. 'pay_type' => isset($params['pay_type']) ? floatval($params['pay_type']) : 1,
  445. 'price' => $price,
  446. 'num' => $num,
  447. 'total' => $total,
  448. 'payment_id' => $paymentId,
  449. 'idcard_data' => $idcardData ? json_encode($idcardData, 256) : '',
  450. 'payment_data' => $paymentData ? json_encode($paymentData, 256) : '',
  451. 'create_time' => time(),
  452. 'update_time' => time(),
  453. 'status' => 1,
  454. 'mark' => 1,
  455. ];
  456. if (!$order = $this->model->edit($data)) {
  457. $this->model->rollBack();
  458. $this->error = '3023';
  459. return false;
  460. }
  461. // 扣除出售用户的USDT
  462. if(!$this->memberModel->where(['id'=> $userId])->decrement('usdt_num', $num)){
  463. $this->model->rollBack();
  464. $this->error = '3020';
  465. return false;
  466. }
  467. $data = [
  468. 'order_no'=> $orderNo,
  469. 'user_id'=> $userId,
  470. 'type'=> 2,
  471. 'pay_type'=> 1,
  472. 'trade_type'=> 2,
  473. 'change_type'=> 2,
  474. 'num'=> $num,
  475. 'total'=> $total,
  476. 'balance'=> floatval($userInfo['usdt_num']-$num),
  477. 'create_time'=> time(),
  478. 'update_time'=> time(),
  479. 'status'=> 1,
  480. 'mark'=>1,
  481. 'remark'=> '客户卖出',
  482. ];
  483. if(!$this->capitalModel->edit($data)){
  484. $this->model->rollBack();
  485. $this->error = '3014';
  486. return false;
  487. }
  488. // 订单通知
  489. $data = [
  490. 'from_uid' => $userId,
  491. 'to_uid' => $businessInfo['id'],
  492. 'type' => 3,
  493. 'order_no' => $orderNo,
  494. 'chat_key' => getChatKey($userId, $businessInfo['id']),
  495. 'message' => "您有来自客户出售广告订单:{$orderNo}的消息,请尽快回复!",
  496. 'message_type' => 1,
  497. 'data_type' => 3,
  498. 'create_time' => time(),
  499. 'update_time' => time(),
  500. 'status' => 1,
  501. 'mark' => 1,
  502. ];
  503. if (!ChatMessageService::make()->pushMessage($data)) {
  504. $this->model->rollBack();
  505. $this->error = '3031';
  506. return false;
  507. }
  508. $this->model->commit();
  509. return $order;
  510. }
  511. /**
  512. * 订单打款处理
  513. * @param $userId 用户ID
  514. * @param $params 打款参数
  515. * @return false
  516. */
  517. public function pay($userId, $params)
  518. {
  519. $orderId = isset($params['id']) ? $params['id'] : 0;
  520. if ($orderId <= 0) {
  521. $this->error = '1013';
  522. return false;
  523. }
  524. $orderInfo = $this->model->where(['user_id' => $userId, 'id' => $orderId, 'mark' => 1, 'type' => 1])
  525. ->whereIn('status', [1, 2, 5, 7])
  526. ->select(['id', 'order_no', 'business_id', 'type', 'payment_id', 'num', 'total', 'status'])
  527. ->first();
  528. $tradeType = isset($orderInfo['type']) ? $orderInfo['type'] : 0;
  529. if (empty($orderInfo)) {
  530. $this->error = '3016';
  531. return false;
  532. }
  533. if ($tradeType != 1) {
  534. $this->error = '3024';
  535. return false;
  536. }
  537. // 用户信息
  538. $userInfo = MemberService::make()->getInfo($userId);
  539. $status = isset($userInfo['status']) ? $userInfo['status'] : 0;
  540. if ($status != 1) {
  541. $this->error = '2009';
  542. return false;
  543. }
  544. // 交易密码
  545. $tradePassword = isset($params['trade_password']) ? trim($params['trade_password']) : '';
  546. $password = isset($userInfo['trade_password']) ? trim($userInfo['trade_password']) : '';
  547. if (empty($password)) {
  548. $this->error = '2015';
  549. return false;
  550. }
  551. if (!$tradePassword || get_password($tradePassword . md5($tradePassword . 'otc')) != $password) {
  552. $this->error = '2016';
  553. return false;
  554. }
  555. $data = [
  556. 'status' => 3,
  557. 'pay_type' => $params['pay_type'],
  558. 'pay_img' => $params['pay_img'],
  559. 'pay_remark' => $params['pay_remark'],
  560. 'pay_time' => time(),
  561. ];
  562. if (!$this->model->where(['user_id' => $userId, 'id' => $orderId, 'mark' => 1])->update($data)) {
  563. $this->error = '3018';
  564. return false;
  565. }
  566. return true;
  567. }
  568. /**
  569. * 订单确认处理
  570. * @param $userId 用户ID
  571. * @param $params 打款参数
  572. * @return false
  573. */
  574. public function collection($userId, $params)
  575. {
  576. $orderId = isset($params['id']) ? $params['id'] : 0;
  577. if ($orderId <= 0) {
  578. $this->error = '1013';
  579. return false;
  580. }
  581. $orderInfo = $this->model->where(['user_id' => $userId, 'id' => $orderId, 'mark' => 1, 'type' => 2])
  582. ->select(['id', 'user_id', 'order_no', 'business_id', 'payment_id', 'type', 'num', 'total', 'status'])
  583. ->first();
  584. $businessId = isset($orderInfo['business_id']) ? $orderInfo['business_id'] : 0;
  585. $tradeType = isset($orderInfo['type']) ? $orderInfo['type'] : 0;
  586. if (empty($orderInfo) || empty($businessId)) {
  587. $this->error = '3016';
  588. return false;
  589. }
  590. if ($orderInfo['status'] != 3) {
  591. $this->error = '3026';
  592. return false;
  593. }
  594. if ($tradeType != 2) {
  595. $this->error = '3024';
  596. return false;
  597. }
  598. $this->model->startTrans();
  599. // 订单状态更新
  600. if (!$this->model->where(['user_id' => $userId, 'id' => $orderId, 'mark' => 1])->update(['status' => 4, 'update_time' => time()])) {
  601. $this->model->rollBack();
  602. $this->error = '3023';
  603. return false;
  604. }
  605. // 交易处理
  606. if ($orderInfo['num'] > 0) {
  607. $info = $this->memberModel->where(['id' => $businessId, 'status' => 1, 'mark' => 1])->select(['id', 'username','usdt_num', 'user_type'])->first();
  608. if (empty($info)) {
  609. $this->model->rollBack();
  610. $this->error = '3019';
  611. return false;
  612. }
  613. // 商家进币
  614. if (!$this->memberModel->where(['id' => $businessId, 'mark' => 1])->increment('usdt_num', $orderInfo['num'])) {
  615. $this->model->rollBack();
  616. $this->error = '3019';
  617. return false;
  618. }
  619. // 明细处理
  620. $data = [
  621. 'order_no' => $orderInfo['order_no'],
  622. 'user_id' => $businessId,
  623. 'type' => 1,
  624. 'trade_type' => 2,
  625. 'pay_type' => 1,
  626. 'change_type' => 1,
  627. 'num' => $orderInfo['num'],
  628. 'total' => $orderInfo['total'],
  629. 'balance' => floatval($info['usdt_num'] + $orderInfo['num']),
  630. 'create_time' => time(),
  631. 'remark' => '交易员购买广告',
  632. 'status' => 1,
  633. 'mark' => 1,
  634. ];
  635. if (!$this->capitalModel->edit($data)) {
  636. $this->error = '3014';
  637. $this->model->rollBack();
  638. return false;
  639. }
  640. }
  641. $this->model->commit();
  642. return true;
  643. }
  644. /**
  645. * 取消订单
  646. * @param $userId
  647. * @param $params
  648. * @return false
  649. */
  650. public function cancel($userId, $params)
  651. {
  652. $orderId = isset($params['id']) ? intval($params['id']) : 0;
  653. if ($orderId <= 0) {
  654. $this->error = '1013';
  655. return false;
  656. }
  657. $orderInfo = $this->model->where(['user_id' => $userId, 'id' => $orderId, 'mark' => 1])
  658. ->select(['id', 'order_no', 'business_id', 'type', 'num', 'total', 'status'])
  659. ->first();
  660. $tradeType = isset($orderInfo['type']) ? $orderInfo['type'] : 0;
  661. $businessId = isset($orderInfo['business_id']) ? $orderInfo['business_id'] : 0;
  662. if (empty($orderInfo) || $businessId<=0) {
  663. $this->error = '3016';
  664. return false;
  665. }
  666. if ($orderInfo['status'] == 3) {
  667. $this->error = '3027';
  668. return false;
  669. }
  670. if ($orderInfo['status'] == 4) {
  671. $this->error = '3028';
  672. return false;
  673. }
  674. if ($orderInfo['status'] == 7) {
  675. $this->error = '3030';
  676. return false;
  677. }
  678. if (!in_array($orderInfo['status'], [1, 2])) {
  679. $this->error = '3029';
  680. return false;
  681. }
  682. $this->model->startTrans();
  683. // 订单状态更新
  684. $updateData = ['status' => 8, 'update_time' => time(), 'exception_remark' => '客户取消'];
  685. if (!$this->model->where(['user_id' => $userId, 'id' => $orderId, 'mark' => 1])->update($updateData)) {
  686. $this->model->rollBack();
  687. $this->error = '3023';
  688. return false;
  689. }
  690. // 出售订单,USDT退回
  691. if ($tradeType == 2 && $orderInfo['num']>0) {
  692. $info = $this->memberModel->where(['id' => $userId, 'status' => 1, 'mark' => 1])->select(['id', 'username', 'usdt_num', 'user_type'])->first();
  693. if (empty($info)) {
  694. $this->model->rollBack();
  695. $this->error = '3019';
  696. return false;
  697. }
  698. // 退还币给客户
  699. if (!$this->memberModel->where(['id' => $userId, 'mark' => 1])->increment('usdt_num', $orderInfo['num'])) {
  700. $this->model->rollBack();
  701. $this->error = '3019';
  702. return false;
  703. }
  704. // 明细处理
  705. $data = [
  706. 'order_no' => $orderInfo['order_no'],
  707. 'user_id' => $userId,
  708. 'type' => 3,
  709. 'trade_type' => 2,
  710. 'pay_type' => 1,
  711. 'change_type' => 1,
  712. 'num' => $orderInfo['num'],
  713. 'total' => $orderInfo['total'],
  714. 'balance' => floatval($info['usdt_num'] + $orderInfo['num']),
  715. 'create_time' => time(),
  716. 'update_time' => time(),
  717. 'remark' => '客户取消退还',
  718. 'status' => 1,
  719. 'mark' => 1,
  720. ];
  721. if (!$this->capitalModel->edit($data)) {
  722. $this->error = '3014';
  723. $this->model->rollBack();
  724. return false;
  725. }
  726. }
  727. // 买入取消
  728. else if($tradeType == 1 && $orderInfo['num']>0){
  729. $info = $this->memberModel->where(['id' => $businessId, 'status' => 1, 'mark' => 1])->select(['id', 'username', 'usdt_num', 'user_type'])->first();
  730. if (empty($info)) {
  731. $this->model->rollBack();
  732. $this->error = '3019';
  733. return false;
  734. }
  735. // 退还币给币商
  736. if (!$this->memberModel->where(['id' => $businessId, 'mark' => 1])->increment('usdt_num', $orderInfo['num'])) {
  737. $this->model->rollBack();
  738. $this->error = '3019';
  739. return false;
  740. }
  741. // 明细处理
  742. $data = [
  743. 'order_no' => $orderInfo['order_no'],
  744. 'user_id' => $businessId,
  745. 'type' => 3,
  746. 'trade_type' => 2,
  747. 'pay_type' => 1,
  748. 'change_type' => 1,
  749. 'num' => $orderInfo['num'],
  750. 'total' => $orderInfo['total'],
  751. 'balance' => floatval($info['usdt_num'] + $orderInfo['num']),
  752. 'create_time' => time(),
  753. 'update_time' => time(),
  754. 'remark' => '客户取消退还',
  755. 'status' => 1,
  756. 'mark' => 1,
  757. ];
  758. if (!$this->capitalModel->edit($data)) {
  759. $this->error = '3014';
  760. $this->model->rollBack();
  761. return false;
  762. }
  763. }
  764. $this->model->commit();
  765. return true;
  766. }
  767. /**
  768. * 获取未支付或处理的订单数
  769. * @param $userId
  770. * @param int $type
  771. * @return mixed
  772. */
  773. public function checkOrderNoCatch($userId, $type = 1)
  774. {
  775. return $this->model->where(['user_id' => $userId, 'type' => $type, 'mark' => 1])
  776. ->whereIn('status', [1, 2, 5, 7])
  777. ->count('id');
  778. }
  779. /**
  780. * 自动取消广告订单处理
  781. * @return false
  782. */
  783. public function catchInvalidOrder(){
  784. $cacheKey = "caches:adverts:cancels:";
  785. if(RedisService::get($cacheKey.'lock')){
  786. return false;
  787. }
  788. RedisService::set($cacheKey.'lock', 1, rand(3, 5));
  789. $overtime = ConfigService::make()->getConfigByCode('trade_order_overtime');
  790. $cancelTime = ConfigService::make()->getConfigByCode('trade_order_cancel');
  791. $catchNum = ConfigService::make()->getConfigByCode('trade_order_catch_num');
  792. $catchNum = $catchNum > 0 ? $catchNum : 200;
  793. // 处理超时订单
  794. if ($overtime > 0) {
  795. $this->model->where(['mark' => 1])
  796. ->where('status', '<=', 2)
  797. ->where('create_time', '<=', time() - $overtime * 60)
  798. ->update(['status' => 7, 'catch_at' => time()]);
  799. }
  800. if ($cancelTime <= 0) {
  801. $this->error = '1023';
  802. return false;
  803. }
  804. $fail = 0;
  805. $success = 0;
  806. $this->model->where(function ($query) use ($cancelTime) {
  807. // 已更新为超时的订单
  808. $query->where(['mark' => 1, 'status' => 7])
  809. ->where('catch_at', '<=', time() - $cancelTime * 60);
  810. })
  811. ->orWhere(function ($query) use ($cancelTime, $overtime) {
  812. $query->where('mark', '=', 1)
  813. ->where('status', '<=', 2)
  814. ->where('create_time', '<=', time() - ($cancelTime + $overtime) * 60);
  815. })
  816. ->select(['id', 'user_id', 'business_id','advert_id','order_no', 'type', 'num','total'])
  817. ->take($catchNum)
  818. ->get()
  819. ->each(function ($item, $k) use($cacheKey, &$fail, &$success){
  820. // 客户卖出订单退还
  821. $date = date('Y-m-d H:i:s');
  822. $type = isset($item['type']) ? $item['type'] : 0;
  823. if ($type == 2) {
  824. if(!$this->orderReback($item['user_id'], $item)){
  825. $fail++;
  826. RedisService::set($cacheKey."order_{$item['order_no']}:u{$item['user_id']}_fail", ['order'=> $item,'msg'=> lang($this->error),'date'=> $date], 3600);
  827. }else{
  828. $success++;
  829. RedisService::set($cacheKey."order_{$item['order_no']}:u{$item['user_id']}_success", ['order'=> $item,'msg'=> lang($this->error),'date'=> $date], 3600);
  830. }
  831. }
  832. else{
  833. if(!$this->orderReback($item['business_id'], $item)){
  834. $fail++;
  835. RedisService::set($cacheKey."order_{$item['order_no']}:b{$item['business_id']}_fail", ['order'=> $item,'msg'=> lang($this->error),'date'=> $date], 3600);
  836. }else{
  837. $success++;
  838. RedisService::set($cacheKey."order_{$item['order_no']}:b{$item['business_id']}_success", ['order'=> $item,'msg'=> lang($this->error),'date'=> $date], 3600);
  839. }
  840. }
  841. });
  842. return ['success'=> $success,'fail'=> $fail];
  843. }
  844. /**
  845. * 订单取消退还处理
  846. * @param $userId
  847. * @param $orderInfo
  848. * @return bool
  849. */
  850. protected function orderReback($userId, $orderInfo){
  851. try {
  852. if($orderInfo['num']<=0){
  853. return false;
  854. }
  855. $this->model->startTrans();
  856. $updateData = ['status'=> 8, 'update_time'=> time(),'catch_at'=>time(),'exception_status'=> 0,'exception_remark'=>'系统取消'];
  857. if(!$this->model->where(['id'=> $orderInfo['id']])->update($updateData)){
  858. $this->model->rollBack();
  859. $this->error = '3043';
  860. return false;
  861. }
  862. $info = $this->memberModel->where(['id' => $userId, 'status' => 1, 'mark' => 1])->select(['id', 'username', 'usdt_num', 'user_type'])->first();
  863. if (empty($info)) {
  864. $this->model->rollBack();
  865. $this->error = '3019';
  866. return false;
  867. }
  868. // 退还币给客户
  869. if (!$this->memberModel->where(['id' => $userId, 'mark' => 1])->increment('usdt_num', $orderInfo['num'])) {
  870. $this->model->rollBack();
  871. $this->error = '3019';
  872. return false;
  873. }
  874. // 明细处理
  875. $data = [
  876. 'order_no' => $orderInfo['order_no'],
  877. 'user_id' => $userId,
  878. 'type' => 3,
  879. 'pay_type' => 1,
  880. 'trade_type' => 2,
  881. 'change_type' => 1,
  882. 'num' => $orderInfo['num'],
  883. 'total' => $orderInfo['total'],
  884. 'balance' => floatval($info['usdt_num'] + $orderInfo['num']),
  885. 'create_time' => time(),
  886. 'update_time' => time(),
  887. 'remark' => '系统自动取消退还',
  888. 'status' => 1,
  889. 'mark' => 1,
  890. ];
  891. if (!$this->capitalModel->edit($data)) {
  892. $this->error = '3014';
  893. $this->model->rollBack();
  894. return false;
  895. }
  896. $this->model->commit();
  897. $this->error = '3044';
  898. return true;
  899. } catch (\Exception $exception){
  900. $this->error = $exception->getMessage();
  901. return false;
  902. }
  903. }
  904. }