TradeOrderService.php 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833
  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\CapitalLogModel;
  13. use App\Models\MemberModel;
  14. use App\Models\MemberPaymentModel;
  15. use App\Models\TradeOrderModel;
  16. use App\Services\Api\MemberPaymentService;
  17. use App\Services\BaseService;
  18. use App\Services\ChatMessageService;
  19. use App\Services\ConfigService;
  20. use App\Services\RedisService;
  21. use App\Services\UsdtWalletService;
  22. /**
  23. * 用户交易订单-服务类
  24. * Class TradeOrderService
  25. * @package App\Services\Common
  26. */
  27. class TradeOrderService extends BaseService
  28. {
  29. // 静态对象
  30. protected static $instance = null;
  31. /**
  32. * 构造函数
  33. * @since 2020/11/10
  34. * TradeOrderService constructor.
  35. */
  36. public function __construct()
  37. {
  38. $this->model = new TradeOrderModel();
  39. $this->memberModel = new MemberModel();
  40. $this->capitalModel = new CapitalLogModel();
  41. $this->paymentModel = new MemberPaymentModel();
  42. }
  43. /**
  44. * 静态入口
  45. * @return static|null
  46. */
  47. public static function make()
  48. {
  49. if (!self::$instance) {
  50. self::$instance = (new static());
  51. }
  52. return self::$instance;
  53. }
  54. /**
  55. * 订单列表
  56. * @param $params
  57. * @param int $pageSize
  58. * @return array
  59. */
  60. public function getDataList($params, $pageSize = 15)
  61. {
  62. $list = $this->model->from('trade_order as a')
  63. ->leftJoin('member as b', 'b.id', '=', 'a.business_id')
  64. ->leftJoin('member as c', 'c.id', '=', 'a.user_id')
  65. ->where(function ($query) use ($params) {
  66. $query->where(['a.mark' => 1])->where('a.status', '>', 0);
  67. $orderNo = isset($params['order_no']) && $params['order_no'] ? trim($params['order_no']) : '';
  68. if ($orderNo) {
  69. $query->where('a.order_no', 'like', "%{$orderNo}%");
  70. }
  71. $type = isset($params['type']) ? intval($params['type']) : 0;
  72. if ($type > 0) {
  73. $query->where(['a.type' => $type]);
  74. }
  75. $businessName = isset($params['business_name']) ? trim($params['business_name']) : '';
  76. if ($businessName) {
  77. $query->where('b.username','like',"%{$businessName}%");
  78. }
  79. $userName = isset($params['username']) ? trim($params['username']) : '';
  80. if ($userName) {
  81. $query->where('c.username','like',"%{$userName}%");
  82. }
  83. $apiId = isset($params['api_id']) ? intval($params['api_id']) : 0;
  84. if ($apiId > 0) {
  85. $query->where(['a.api_id' => $apiId]);
  86. }
  87. $tradeType = isset($params['trade_type']) ? intval($params['trade_type']) : 0;
  88. if ($tradeType > 0) {
  89. $query->where(['a.trade_type' => $tradeType]);
  90. }
  91. // 日期
  92. $date = isset($params['date']) ? $params['date'] : [];
  93. $start = isset($date[0]) ? $date[0] : '';
  94. $end = isset($date[1]) ? $date[1] : '';
  95. $end = $start >= $end ? '' : $end;
  96. if ($start) {
  97. $query->where('a.create_time', '>=', strtotime($start));
  98. }
  99. if ($end) {
  100. $query->where('a.create_time', '<', strtotime($end));
  101. }
  102. $exceptionStatus = isset($params['exception_status']) ? intval($params['exception_status']) : 0;
  103. if ($exceptionStatus > 0) {
  104. $query->where(['a.exception_status' => $exceptionStatus]);
  105. }
  106. $status = isset($params['status']) ? intval($params['status']) : 0;
  107. if ($status > 0) {
  108. $query->where(['a.status' => $status]);
  109. }
  110. $userId = isset($params['user_id']) ? $params['user_id'] : 0;
  111. if ($userId > 0) {
  112. $query->where('a.user_id', $userId);
  113. }
  114. $businessId = isset($params['business_id']) ? $params['business_id'] : 0;
  115. if ($businessId > 0) {
  116. $query->where('a.business_id', $businessId);
  117. }
  118. })
  119. ->select(['a.*', 'b.username', 'c.username as c_username'])
  120. ->orderBy('a.create_time', 'desc')
  121. ->orderBy('a.id', 'desc')
  122. ->paginate($pageSize > 0 ? $pageSize : 9999999);
  123. $list = $list ? $list->toArray() : [];
  124. if ($list) {
  125. $payTypes = [1 => '银行卡', 2 => '微信', 3 => '支付宝', 4 => '其他'];
  126. $overTime = ConfigService::make()->getConfigByCode('trade_order_overtime');
  127. $overTime = $overTime ? $overTime : 0;
  128. foreach ($list['data'] as &$item) {
  129. $item['idcardData'] = $item['idcard_data'] ? json_decode($item['idcard_data'], true) : [];
  130. $item['paymentData'] = $item['payment_data'] ? json_decode($item['payment_data'], true) : [];
  131. $item['create_time_text'] = $item['create_time'] ? datetime($item['create_time'], 'Y-m-d H:i:s') : '';
  132. $item['update_time_text'] = $item['update_time'] ? datetime($item['update_time'], 'Y-m-d H:i:s') : '';
  133. $item['time_text'] = $item['create_time'] ? datetime($item['create_time'], 'H:i') : '';
  134. $item['utime_text'] = $item['update_time'] ? datetime($item['update_time'], 'H:i') : '';
  135. $item['pay_time_text'] = $item['pay_time'] ? datetime($item['pay_time'], 'Y-m-d H:i') : '';
  136. $item['username_text'] = $item['username'] ? format_account($item['username']) : '';
  137. $item['c_username_text'] = $item['c_username'] ? format_account($item['c_username']) : '';
  138. $item['exception_img'] = $item['exception_img'] ? get_image_url($item['exception_img']) : '';
  139. $item['exception_img1'] = $item['exception_img1'] ? get_image_url($item['exception_img1']) : '';
  140. $item['exception_img2'] = $item['exception_img2'] ? get_image_url($item['exception_img2']) : '';
  141. $item['pay_img'] = $item['pay_img'] ? get_image_url($item['pay_img']) : '';
  142. $item['paymentData']['qrcode'] = isset($item['paymentData']['qrcode']) && $item['paymentData']['qrcode'] ? get_image_url($item['paymentData']['qrcode']) : '';
  143. $overTime = max(0, intval(strtotime($item['create_time'])) + $overTime * 60 - time());
  144. $item['overtime_text'] = in_array($item['status'], [1, 2]) && $overTime ? date('H:i', $overTime) : '';
  145. $payType = isset($item['pay_type']) ? $item['pay_type'] : 0;
  146. $item['pay_name'] = isset($payTypes[$payType]) ? $payTypes[$payType] : '其他';
  147. $item['chat_key'] = getChatKey($item['user_id'], $item['business_id']);
  148. }
  149. }
  150. return [
  151. 'pageSize' => $pageSize,
  152. 'total' => isset($list['total']) ? $list['total'] : 0,
  153. 'list' => isset($list['data']) ? $list['data'] : []
  154. ];
  155. }
  156. /**
  157. * @param $orderNo
  158. * @return array
  159. */
  160. public function getInfoByNo($orderNo, $userId = 0)
  161. {
  162. $info = $this->model->from('trade_order as a')
  163. ->leftJoin('member as b', 'b.id', '=', 'a.business_id')
  164. ->leftJoin('member as c', 'c.id', '=', 'a.user_id')
  165. ->leftJoin('user as u', 'u.user_id', '=', 'a.business_id')
  166. ->where(['order_no' => $orderNo])
  167. ->where(function ($query) use ($userId) {
  168. $query->where(['a.mark' => 1])->where('a.status', '>', 0);
  169. if ($userId > 0) {
  170. $query->where(['a.user_id' => $userId]);
  171. }
  172. })
  173. ->select(['a.*', 'b.username', 'b.idcard_check', 'b.credit', 'u.bond', 'c.username as c_username'])
  174. ->first();
  175. $info = $info ? $info->toArray() : [];
  176. if ($info) {
  177. $overTime = ConfigService::make()->getConfigByCode('trade_order_overtime');
  178. $overTime = $overTime ? $overTime : 5;
  179. $info['idcardData'] = $info['idcard_data'] ? json_decode($info['idcard_data'], true) : [];
  180. $info['paymentData'] = $info['payment_data'] ? json_decode($info['payment_data'], true) : [];
  181. $info['create_time_text'] = $info['create_time'] ? datetime($info['create_time'], 'Y-m-d H:i:s') : '';
  182. $info['update_time_text'] = $info['update_time'] ? datetime($info['update_time'], 'Y-m-d H:i:s') : '';
  183. $info['time_text'] = $info['create_time'] ? datetime($info['create_time'], 'H:i') : '';
  184. $info['utime_text'] = $info['update_time'] ? datetime($info['update_time'], 'H:i') : '';
  185. $info['pay_time_text'] = $info['pay_time'] ? datetime($info['pay_time'], 'Y-m-d H:i') : '';
  186. $info['username_text'] = $info['username'] ? format_account($info['username']) : '';
  187. $info['c_username_text'] = $info['c_username'] ? format_account($info['c_username']) : '';
  188. $info['exception_img'] = $info['exception_img'] ? get_image_url($info['exception_img']) : '';
  189. $info['pay_img'] = $info['pay_img'] ? get_image_url($info['pay_img']) : '';
  190. $info['paymentData']['qrcode'] = isset($info['paymentData']['qrcode']) && $info['paymentData']['qrcode'] ? get_image_url($info['paymentData']['qrcode']) : '';
  191. $payType = isset($info['pay_type']) ? $info['pay_type'] : 0;
  192. $info['pay_name'] = isset($payTypes[$payType]) ? $payTypes[$payType] : '其他';
  193. $info['chat_key'] = getChatKey($info['user_id'], $info['business_id']);
  194. $overTime = max(0, intval(strtotime($info['create_time'])) + $overTime * 60 - time());
  195. $info['overtime_text'] = in_array($info['status'], [1, 2]) && $overTime ? date('i:s', $overTime) : '';
  196. $info['overtime'] = $overTime;
  197. }
  198. return $info;
  199. }
  200. /**
  201. * 获取待处理订单
  202. * @param $params
  203. * @return array
  204. */
  205. public function getWaitOrder($params)
  206. {
  207. $info = $this->model->from('trade_order as a')
  208. ->leftJoin('member as b', 'b.id', '=', 'a.business_id')
  209. ->where(function ($query) use ($params) {
  210. $query->where(['a.mark' => 1])->whereIn('a.status', [1, 2, 3, 7])->where('a.status', '>', 0);
  211. $orderNo = isset($params['order_no']) && $params['order_no'] ? trim($params['order_no']) : '';
  212. if ($orderNo) {
  213. $query->where('a.order_no', 'like', "%{$orderNo}%");
  214. }
  215. $type = isset($params['type']) ? intval($params['type']) : 0;
  216. if ($type > 0) {
  217. $query->where(['a.type' => $type]);
  218. }
  219. $userId = isset($params['user_id']) ? $params['user_id'] : 0;
  220. if ($userId > 0) {
  221. $query->where('a.user_id', $userId);
  222. }
  223. $businessId = isset($params['business_id']) ? $params['business_id'] : 0;
  224. if ($businessId > 0) {
  225. $query->where('a.business_id', $businessId);
  226. }
  227. })
  228. ->select(['a.id', 'a.order_no', 'a.type', 'a.pay_type', 'a.user_id', 'a.business_id', 'a.num', 'a.total', 'a.payment_data', 'a.status', 'a.create_time', 'b.username'])
  229. ->orderBy('a.create_time', 'desc')
  230. ->first();
  231. $info = $info ? $info->toArray() : [];
  232. if ($info) {
  233. $overTime = ConfigService::make()->getConfigByCode('trade_order_overtime');
  234. $overTime = $overTime ? $overTime : 5;
  235. $info['paymentData'] = $info['payment_data'] ? json_decode($info['payment_data'], true) : [];
  236. $info['create_time_text'] = $info['create_time'] ? format_time(strtotime($info['create_time'])) : '';
  237. $info['time_text'] = $info['create_time'] ? datetime($info['create_time'], 'H:i') : '';
  238. $info['username_text'] = $info['username'] ? format_account($info['username']) : '';
  239. $info['paymentData']['qrcode'] = isset($info['paymentData']['qrcode']) && $info['paymentData']['qrcode'] ? get_image_url($info['paymentData']['qrcode']) : '';
  240. $info['paymentData']['bank_card_text'] = isset($info['paymentData']['bank_card']) && $info['paymentData']['bank_card'] ? format_bank_card($info['paymentData']['bank_card']) : '未设置';
  241. $info['paymentData']['account_text'] = isset($info['paymentData']['account']) && $info['paymentData']['account'] ? format_account($info['paymentData']['account']) : '未设置';
  242. $overTime = max(0, intval(strtotime($info['create_time'])) + $overTime * 60 - time());
  243. $info['overtime_text'] = in_array($info['status'], [1, 2]) && $overTime ? date('H:i', $overTime) : '';
  244. }
  245. return $info;
  246. }
  247. /**
  248. * 成交交易笔数
  249. * @param int $type 类型:1-买单,2-卖单
  250. * @param int $bsid 承兑商用户ID
  251. * @param int $status 状态:4-成交
  252. * @return mixed
  253. */
  254. public function getCompleteCount($type = 1, $bsid = 0, $status = 4)
  255. {
  256. return (int)$this->model->where(['type' => $type, 'status' => $status, 'mark' => 1])
  257. ->where(function ($query) use ($bsid) {
  258. if ($bsid > 0) {
  259. $query->where('business_id', '=', $bsid);
  260. }
  261. })->count('id');
  262. }
  263. /**
  264. * 成交交易金额
  265. * @param int $type 类型:1-买单,2-卖单
  266. * @param int $bsid 承兑商用户ID
  267. * @param int $status 状态:4-成交
  268. * @param string $field 统计字段:total-总金额(默认),num-交易USDT数量
  269. * @return mixed
  270. */
  271. public function getCompleteTotal($type = 1, $bsid = 0, $status = 4, $field = 'total')
  272. {
  273. $total = $this->model->where(['type' => $type, 'status' => $status, 'mark' => 1])
  274. ->where(function ($query) use ($bsid) {
  275. if ($bsid > 0) {
  276. $query->where('business_id', '=', $bsid);
  277. }
  278. })->sum($field);
  279. return moneyFormat($total, 2);
  280. }
  281. /**
  282. * 今日成交交易金额
  283. * @param int $type 类型:1-买单,2-卖单
  284. * @param int $bsid 承兑商用户ID
  285. * @param int $status 状态:4-成交
  286. * @param string $field 统计字段:total-总金额(默认),num-交易USDT数量
  287. * @return mixed
  288. */
  289. public function getCompleteTotalByDay($type = 1, $bsid = 0, $status = 4, $field = 'total')
  290. {
  291. $total = $this->model->where(['type' => $type, 'status' => $status, 'mark' => 1])
  292. ->where('pay_time', '>=', strtotime(date('Y-m-d')))
  293. ->where(function ($query) use ($bsid) {
  294. if ($bsid > 0) {
  295. $query->where('business_id', '=', $bsid);
  296. }
  297. })->sum($field);
  298. return moneyFormat($total, 6);
  299. }
  300. /**
  301. * 24小时成交交易金额
  302. * @param int $time 时间/小时
  303. * @param int $bsid 承兑商用户ID
  304. * @param int $status 状态:4-成交
  305. * @param string $field 统计字段:total-总金额(默认),num-交易USDT数量
  306. * @return mixed
  307. */
  308. public function getCompleteTotalByTime($time = 24, $bsid = 0, $status = 4, $field = 'total')
  309. {
  310. $total = $this->model->where(['status' => $status, 'mark' => 1])
  311. ->where('pay_time', '>=', time() - $time * 3600)
  312. ->where(function ($query) use ($bsid) {
  313. if ($bsid > 0) {
  314. $query->where('business_id', '=', $bsid);
  315. }
  316. })->sum($field);
  317. return moneyFormat($total, 4);
  318. }
  319. /**
  320. * 24小时成交交易金额
  321. * @param int $time 时间/小时
  322. * @param int $bsid 承兑商用户ID
  323. * @param int $status 状态:4-成交
  324. * @param string $field 统计字段:total-总金额(默认),num-交易USDT数量
  325. * @return mixed
  326. */
  327. public function getCompleteCountByTime($time = 24, $bsid = 0, $status = 4, $field = 'id')
  328. {
  329. $total = $this->model->where(['status' => $status, 'mark' => 1])
  330. ->where('pay_time', '>=', time() - $time * 3600)
  331. ->where(function ($query) use ($bsid) {
  332. if ($bsid > 0) {
  333. $query->where('business_id', '=', $bsid);
  334. }
  335. })->count($field);
  336. return intval($total);
  337. }
  338. /**
  339. * 获取某个时间段的买卖交易量比
  340. * @param int $type 状态类型:1-成交的
  341. * @param int $bsid 承兑商用户ID
  342. * @param int $time 时间/分钟,默认15分钟
  343. * @return array
  344. */
  345. public function getCountRateByTime($type = 1, $bsid = 0, $time = 15)
  346. {
  347. $where = ['mark' => 1];
  348. if ($type == 1) {
  349. $where['status'] = 4;
  350. }
  351. $buyCount = $this->model->where(['type' => 1])->where($where)
  352. ->where(function ($query) use ($bsid) {
  353. if ($bsid > 0) {
  354. $query->where('business_id', '=', $bsid);
  355. }
  356. })
  357. ->where('pay_time', '>=', time() - $time * 60)
  358. ->count('id');
  359. $sellCount = $this->model->where(['type' => 2])->where($where)
  360. ->where(function ($query) use ($bsid) {
  361. if ($bsid > 0) {
  362. $query->where('business_id', '=', $bsid);
  363. }
  364. })
  365. ->where('pay_time', '>=', time() - $time * 60)
  366. ->count('id');
  367. $rate = ($buyCount || $sellCount) > 0 ? moneyFormat($buyCount / ($buyCount + $sellCount)) * 100 : 0;
  368. return ['buy' => $buyCount, 'sell' => $sellCount, 'buy_rate' => $rate, 'sell_rate' => ($sellCount > 0 ? 100 - $rate : 0)];
  369. }
  370. /**
  371. * 获取某个时间段的交易成功率
  372. * @param int $type 状态类型:1-成交的
  373. * @param int $bsid 承兑商用户ID
  374. * @param int $time 时间/小时,默认24小时
  375. * @return array
  376. */
  377. public function getRateByTime($bsid = 0, $time = 24)
  378. {
  379. $successCount = $this->model->where(['status' => 4, 'mark' => 1])
  380. ->where(function ($query) use ($bsid) {
  381. if ($bsid > 0) {
  382. $query->where('business_id', '=', $bsid);
  383. }
  384. })
  385. ->where('pay_time', '>=', time() - $time * 3600)
  386. ->count('id');
  387. $count = $this->model->where(['mark' => 1])
  388. ->where(function ($query) use ($bsid) {
  389. if ($bsid > 0) {
  390. $query->where('business_id', '=', $bsid);
  391. }
  392. })
  393. ->where(function ($query) use ($time) {
  394. $time = time() - $time * 3600;
  395. $query->where('pay_time', '>=', $time)
  396. ->orWhereRaw("(pay_time = 0 and create_time >={$time})");
  397. })
  398. ->count('id');
  399. $rate = $count > 0 ? moneyFormat($successCount / $count * 100) : 0;
  400. return ['rate' => $rate, 'success' => $successCount, 'count' => $count];
  401. }
  402. /**
  403. * 获取未支付或处理的订单数
  404. * @param $userId
  405. * @param int $type
  406. * @return mixed
  407. */
  408. public function checkOrderNoCatch($userId, $type = 1)
  409. {
  410. return $this->model->where(['user_id' => $userId, 'type' => $type, 'mark' => 1])->whereIn('status', [1, 2, 5, 7])->count('id');
  411. }
  412. /**
  413. * 客户买入
  414. * @param $userId
  415. * @param $params
  416. * @return false|int|number
  417. */
  418. public function buy($userId, $params)
  419. {
  420. $num = isset($params['num']) ? floatval($params['num']) : 0;
  421. $numType = isset($params['num_type']) ? intval($params['num_type']) : 1;
  422. if ($userId <= 0) {
  423. $this->error = '1013';
  424. return false;
  425. }
  426. // 验证参数
  427. $config = ConfigService::make()->getConfigOptionByGroup(5);
  428. $tradeOpen = isset($config['trade_usdt_open']) ? $config['trade_usdt_open'] : 0;
  429. $tradeMinNum = isset($config['trade_min_num']) ? $config['trade_min_num'] : 0;
  430. $tradeMaxNum = isset($config['trade_max_num']) ? $config['trade_max_num'] : 0;
  431. $trademinMoney = isset($config['trade_min_money']) ? $config['trade_min_money'] : 0;
  432. $tradeMaxMoney = isset($config['trade_max_money']) ? $config['trade_max_money'] : 0;
  433. $tradePrice = isset($config['usdt_buy_price']) ? $config['usdt_buy_price'] : 0;
  434. $tradeLimitNum = isset($config['trade_no_catch']) ? $config['trade_no_catch'] : 0;
  435. // 是否开启交易
  436. if ($tradeOpen != 1) {
  437. $this->error = '1013';
  438. return false;
  439. }
  440. if ($tradePrice <= 0) {
  441. $this->error = '3002';
  442. return false;
  443. }
  444. // 验证数量或金额
  445. $total = 0;
  446. if ($numType == 1) {
  447. if ($num < $tradeMinNum || $num > $tradeMaxNum) {
  448. $this->error = '3003';
  449. return false;
  450. }
  451. $total = moneyFormat($num * $tradePrice, 6);
  452. } else {
  453. if ($num < $trademinMoney || $num > $tradeMaxMoney) {
  454. $this->error = '3003';
  455. return false;
  456. }
  457. $total = moneyFormat($num, 6);
  458. $num = moneyFormat($num / $tradePrice, 6);
  459. }
  460. // 用户信息
  461. $userInfo = MemberService::make()->getInfo($userId);
  462. $status = isset($userInfo['status']) ? $userInfo['status'] : 0;
  463. $idcardCheck = isset($userInfo['idcard_check']) ? $userInfo['idcard_check'] : 0;
  464. $username = isset($userInfo['username']) && $userInfo['username'] ? format_account($userInfo['username']) : '';
  465. if ($status != 1) {
  466. $this->error = '2009';
  467. return false;
  468. }
  469. if ($idcardCheck != 1) {
  470. $this->error = '2014';
  471. return false;
  472. }
  473. // 未处理订单
  474. $noCatchOrder = $this->checkOrderNoCatch($userId, 1);
  475. if ($tradeLimitNum > 0 && $noCatchOrder >= $tradeLimitNum) {
  476. $this->error = lang(3005, ['num' => $tradeLimitNum]);
  477. return false;
  478. }
  479. // 匹配交易商家
  480. $businessInfo = \App\Services\Api\MemberService::make()->getTradeMember($num, 1, $userId);
  481. if (empty($businessInfo)) {
  482. $this->error = '3004';
  483. return false;
  484. }
  485. if ($businessInfo['usdt_num'] < $num) {
  486. $this->error = '3004';
  487. return false;
  488. }
  489. // 客户身份信息
  490. $idcardData = [
  491. 'idcard' => isset($userInfo['idcard']) ? $userInfo['idcard'] : '',
  492. 'idcard_check' => isset($userInfo['idcard_check']) ? $userInfo['idcard_check'] : 0,
  493. 'idcard_front_img' => isset($userInfo['idcard_front_img']) ? $userInfo['idcard_front_img'] : '',
  494. 'idcard_back_img' => isset($userInfo['idcard_back_img']) ? $userInfo['idcard_back_img'] : '',
  495. 'idcard_hand_img' => isset($userInfo['idcard_hand_img']) ? $userInfo['idcard_hand_img'] : '',
  496. ];
  497. // 币商收款方式
  498. $payment = MemberPaymentService::make()->getPayment($businessInfo['id']);
  499. if (empty($payment)) {
  500. $this->error = '3015';
  501. return false;
  502. }
  503. $this->model->startTrans();
  504. $orderNo = get_order_num('OT');
  505. $data = [
  506. 'user_id' => $userId,
  507. 'business_id' => isset($businessInfo['id']) ? $businessInfo['id'] : 0,
  508. 'order_no' => $orderNo,
  509. 'type' => 1,
  510. 'pay_type' => isset($params['pay_type']) ? floatval($params['pay_type']) : 1,
  511. 'price' => $tradePrice,
  512. 'num' => $num,
  513. 'total' => $total,
  514. 'payment_id' => isset($payment['id']) ? intval($payment['id']) : 0,
  515. 'idcard_data' => $idcardData ? json_encode($idcardData, 256) : '',
  516. 'payment_data' => $payment ? json_encode($payment, 256) : '',
  517. 'create_time' => time(),
  518. 'update_time' => time(),
  519. 'status' => 1,
  520. 'mark' => 1,
  521. ];
  522. if (!$order = $this->model->edit($data)) {
  523. $this->model->rollBack();
  524. $this->error = '3023';
  525. return false;
  526. }
  527. if (!$this->memberModel->where(['id' => $businessInfo['id']])->decrement('usdt_num', $num)) {
  528. $this->model->rollBack();
  529. $this->error = '3020';
  530. return false;
  531. }
  532. $data = [
  533. 'order_no' => $orderNo,
  534. 'user_id' => $businessInfo['id'],
  535. 'type' => 2,
  536. 'pay_type' => 1,
  537. 'change_type' => 2,
  538. 'num' => $num,
  539. 'total' => $total,
  540. 'balance' => floatval($businessInfo['usdt_num'] - $num),
  541. 'create_time' => time(),
  542. 'update_time' => time(),
  543. 'status' => 1,
  544. 'mark' => 1,
  545. 'remark' => '交易员卖出',
  546. ];
  547. if (!$this->capitalModel->edit($data)) {
  548. $this->model->rollBack();
  549. $this->error = '3014';
  550. return false;
  551. }
  552. // 订单通知
  553. $data = [
  554. 'from_uid' => $userId,
  555. 'to_uid' => $businessInfo['id'],
  556. 'type' => 2,
  557. 'order_no' => $orderNo,
  558. 'chat_key' => getChatKey($userId, $businessInfo['id']),
  559. 'message' => "您有来自客户买单订单:{$orderNo}的消息,请尽快回复!",
  560. 'message_type' => 1,
  561. 'data_type' => 2,
  562. 'create_time' => time(),
  563. 'update_time' => time(),
  564. 'status' => 1,
  565. 'mark' => 1,
  566. ];
  567. if (!ChatMessageService::make()->pushMessage($data)) {
  568. $this->model->rollBack();
  569. $this->error = '3031';
  570. return false;
  571. }
  572. $this->model->commit();
  573. return $order;
  574. }
  575. /**
  576. * 客户卖出
  577. * @param $userId
  578. * @param $params
  579. * @return false|int|number
  580. */
  581. public function sell($userId, $params)
  582. {
  583. $num = isset($params['num']) ? floatval($params['num']) : 0;
  584. if ($userId <= 0) {
  585. $this->error = '1013';
  586. return false;
  587. }
  588. // 验证参数
  589. $config = ConfigService::make()->getConfigOptionByGroup(5);
  590. $tradeOpen = isset($config['trade_usdt_open']) ? $config['trade_usdt_open'] : 0;
  591. $tradeMinNum = isset($config['trade_min']) ? $config['trade_min'] : 0;
  592. $tradeMaxNum = isset($config['trade_max']) ? $config['trade_max'] : 0;
  593. $tradePrice = isset($config['usdt_sell_price']) ? $config['usdt_sell_price'] : 0;
  594. $tradeLimitNum = isset($config['trade_no_catch']) ? $config['trade_no_catch'] : 0;
  595. // 是否开启交易
  596. if ($tradeOpen != 1) {
  597. $this->error = '1013';
  598. return false;
  599. }
  600. if ($tradePrice <= 0) {
  601. $this->error = '3002';
  602. return false;
  603. }
  604. // 验证数量或金额
  605. $total = moneyFormat($num * $tradePrice, 6);
  606. if ($num < $tradeMinNum || ($tradeMaxNum && $num > $tradeMaxNum)) {
  607. $this->error = '3003';
  608. return false;
  609. }
  610. // 用户信息
  611. $userInfo = MemberService::make()->getInfo($userId);
  612. $status = isset($userInfo['status']) ? $userInfo['status'] : 0;
  613. $idcardCheck = isset($userInfo['idcard_check']) ? $userInfo['idcard_check'] : 0;
  614. $usdtNum = isset($userInfo['usdt_num']) ? $userInfo['usdt_num'] : 0;
  615. $username = isset($userInfo['username']) && $userInfo['username'] ? format_account($userInfo['username']) : '';
  616. if ($status != 1) {
  617. $this->error = '2009';
  618. return false;
  619. }
  620. if ($idcardCheck != 1) {
  621. $this->error = '2014';
  622. return false;
  623. }
  624. if ($usdtNum < $num) {
  625. $this->error = '3011';
  626. return false;
  627. }
  628. // 未处理订单
  629. $noCatchOrder = $this->checkOrderNoCatch($userId, 2);
  630. if ($tradeLimitNum > 0 && $noCatchOrder >= $tradeLimitNum) {
  631. $this->error = lang(3005, ['num' => $tradeLimitNum]);
  632. return false;
  633. }
  634. // 匹配交易商家
  635. $businessInfo = \App\Services\Api\MemberService::make()->getTradeMember($num, 2, $userId);
  636. if (empty($businessInfo)) {
  637. $this->error = '3004';
  638. return false;
  639. }
  640. $idcardData = [
  641. 'idcard' => isset($userInfo['idcard']) ? $userInfo['idcard'] : '',
  642. 'idcard_check' => isset($userInfo['idcard_check']) ? $userInfo['idcard_check'] : 0,
  643. 'idcard_front_img' => isset($userInfo['idcard_front_img']) ? $userInfo['idcard_front_img'] : '',
  644. 'idcard_back_img' => isset($userInfo['idcard_back_img']) ? $userInfo['idcard_back_img'] : '',
  645. 'idcard_hand_img' => isset($userInfo['idcard_hand_img']) ? $userInfo['idcard_hand_img'] : '',
  646. ];
  647. // 收款方式
  648. $paymentId = isset($params['payment_id']) ? $params['payment_id'] : 0;
  649. $paymentInfo = MemberPaymentService::make()->getInfo($paymentId);
  650. if (empty($paymentInfo)) {
  651. $this->error = '3010';
  652. return false;
  653. }
  654. $paymentData = [
  655. 'payment_id' => $paymentInfo['id'],
  656. 'type' => $paymentInfo['type'],
  657. 'logo' => $paymentInfo['logo'] ? get_image_url($paymentInfo['logo']) : '',
  658. 'real_name' => $paymentInfo['real_name'],
  659. 'bank_name' => $paymentInfo['bank_name'],
  660. 'bank_card' => $paymentInfo['bank_card'],
  661. 'branch_name' => $paymentInfo['branch_name'],
  662. 'qrcode' => $paymentInfo['qrcode'] ? get_image_url($paymentInfo['qrcode']) : '',
  663. 'account' => $paymentInfo['account'],
  664. ];
  665. $orderNo = get_order_num('OT');
  666. $data = [
  667. 'user_id' => $userId,
  668. 'business_id' => isset($businessInfo['id']) ? $businessInfo['id'] : 0,
  669. 'order_no' => $orderNo,
  670. 'type' => 2,
  671. 'pay_type' => isset($params['pay_type']) ? floatval($params['pay_type']) : 1,
  672. 'price' => $tradePrice,
  673. 'num' => $num,
  674. 'payment_id' => $paymentId,
  675. 'idcard_data' => json_encode($idcardData, 256),
  676. 'payment_data' => json_encode($paymentData, 256),
  677. 'total' => $total,
  678. 'create_time' => time(),
  679. 'status' => 1,
  680. 'mark' => 1,
  681. ];
  682. $this->model->startTrans();
  683. if (!$order = $this->model->edit($data)) {
  684. $this->error = '3012';
  685. $this->model->rollBack();
  686. return false;
  687. }
  688. // 扣除币
  689. if (!$this->memberModel->where(['id' => $userId])->decrement('usdt_num', $num)) {
  690. $this->error = '3013';
  691. $this->model->rollBack();
  692. return false;
  693. }
  694. // 账户明细
  695. $data = [
  696. 'order_no' => $data['order_no'],
  697. 'user_id' => $userId,
  698. 'type' => 2,
  699. 'change_type' => 2,
  700. 'num' => $num,
  701. 'total' => $total,
  702. 'balance' => floatval($userInfo['usdt_num'] - $num),
  703. 'create_time' => time(),
  704. 'update_time' => time(),
  705. 'remark' => '客户卖出',
  706. 'status' => 1,
  707. 'mark' => 1,
  708. ];
  709. if (!$this->capitalModel->edit($data)) {
  710. $this->error = '3014';
  711. $this->model->rollBack();
  712. return false;
  713. }
  714. // 订单通知
  715. $data = [
  716. 'from_uid' => $userId,
  717. 'to_uid' => $businessInfo['id'],
  718. 'type' => 2,
  719. 'order_no' => $orderNo,
  720. 'chat_key' => getChatKey($userId, $businessInfo['id']),
  721. 'message' => "您有来自客户卖单订单:{$orderNo}的消息,请尽快回复!",
  722. 'message_type' => 1,
  723. 'data_type' => 3,
  724. 'create_time' => time(),
  725. 'update_time' => time(),
  726. 'status' => 1,
  727. 'mark' => 1,
  728. ];
  729. if (!ChatMessageService::make()->pushMessage($data)) {
  730. $this->model->rollBack();
  731. $this->error = '3023';
  732. return false;
  733. }
  734. $this->model->commit();
  735. return $order;
  736. }
  737. /**
  738. * 订单打款处理
  739. * @param $userId 用户ID
  740. * @param $params 打款参数
  741. * @return false
  742. */
  743. public function pay($userId, $params)
  744. {
  745. $orderId = isset($params['id']) ? $params['id'] : 0;
  746. if ($orderId <= 0) {
  747. $this->error = '1013';
  748. return false;
  749. }
  750. $orderInfo = $this->model->where(['user_id' => $userId, 'id' => $orderId, 'mark' => 1, 'type' => 1])
  751. ->whereIn('status', [1, 2, 5, 7])
  752. ->select(['id', 'order_no', 'business_id', 'type', 'payment_id', 'num', 'total', 'status'])
  753. ->first();
  754. $tradeType = isset($orderInfo['type']) ? $orderInfo['type'] : 0;
  755. if (empty($orderInfo)) {
  756. $this->error = '3016';
  757. return false;
  758. }
  759. if ($tradeType != 1) {
  760. $this->error = '3024';
  761. return false;
  762. }
  763. // 用户信息
  764. $userInfo = MemberService::make()->getInfo($userId);
  765. $status = isset($userInfo['status']) ? $userInfo['status'] : 0;
  766. if ($status != 1) {
  767. $this->error = '2009';
  768. return false;
  769. }
  770. // 交易密码
  771. $tradePassword = isset($params['trade_password']) ? trim($params['trade_password']) : '';
  772. $password = isset($userInfo['trade_password']) ? trim($userInfo['trade_password']) : '';
  773. if (empty($password)) {
  774. $this->error = '2015';
  775. return false;
  776. }
  777. if (!$tradePassword || get_password($tradePassword . md5($tradePassword . 'otc')) != $password) {
  778. $this->error = '2016';
  779. return false;
  780. }
  781. $data = [
  782. 'status' => 3,
  783. 'pay_type' => $params['pay_type'],
  784. 'pay_img' => $params['pay_img'],
  785. 'pay_remark' => $params['pay_remark'],
  786. 'pay_time' => time(),
  787. ];
  788. if (!$this->model->where(['user_id' => $userId, 'id' => $orderId, 'mark' => 1])->update($data)) {
  789. $this->error = '3018';
  790. return false;
  791. }
  792. return true;
  793. }
  794. /**
  795. * 商家订单打款处理
  796. * @param $userId 用户ID
  797. * @param $params 打款参数
  798. * @return false
  799. */
  800. public function businessPay($businessId, $params)
  801. {
  802. $orderId = isset($params['id']) ? $params['id'] : 0;
  803. if ($orderId <= 0) {
  804. $this->error = '1013';
  805. return false;
  806. }
  807. $orderInfo = $this->model->where(['business_id' => $businessId, 'id' => $orderId, 'mark' => 1, 'type' => 2])
  808. ->whereIn('status', [1, 2, 5, 7])
  809. ->select(['id', 'user_id', 'order_no', 'business_id', 'type', 'payment_id', 'num', 'total', 'status'])
  810. ->first();
  811. $tradeType = isset($orderInfo['type']) ? $orderInfo['type'] : 0;
  812. if (empty($orderInfo)) {
  813. $this->error = '3016';
  814. return false;
  815. }
  816. if ($tradeType != 2) {
  817. $this->error = '3025';
  818. return false;
  819. }
  820. // 用户信息
  821. $userInfo = MemberService::make()->getInfo($businessId);
  822. $status = isset($userInfo['status']) ? $userInfo['status'] : 0;
  823. $username = isset($userInfo['username']) ? $userInfo['username'] : 0;
  824. if ($status != 1) {
  825. $this->error = '2009';
  826. return false;
  827. }
  828. // 交易密码
  829. $tradePassword = isset($params['trade_password']) ? trim($params['trade_password']) : '';
  830. $password = isset($userInfo['trade_password']) ? trim($userInfo['trade_password']) : '';
  831. if (empty($password)) {
  832. $this->error = '2015';
  833. return false;
  834. }
  835. if (!$tradePassword || get_password($tradePassword . md5($tradePassword . 'otc')) != $password) {
  836. $this->error = '2016';
  837. return false;
  838. }
  839. if (strpos($params['pay_img'], "temp")) {
  840. $params['pay_img'] = save_image($params['pay_img'], 'images');
  841. } else {
  842. $params['pay_img'] = str_replace(IMG_URL, "", $params['pay_img']);
  843. }
  844. $data = [
  845. 'status' => 3,
  846. 'pay_type' => $params['pay_type'],
  847. 'pay_img' => $params['pay_img'],
  848. 'pay_remark' => $params['pay_remark'],
  849. 'pay_time' => time(),
  850. ];
  851. if (!$this->model->where(['business_id' => $businessId, 'id' => $orderId, 'mark' => 1])->update($data)) {
  852. $this->error = '3018';
  853. return false;
  854. }
  855. $this->error = '3017';
  856. return true;
  857. }
  858. /**
  859. * 订单确认处理
  860. * @param $userId 用户ID
  861. * @param $params 打款参数
  862. * @return false
  863. */
  864. public function collection($userId, $params)
  865. {
  866. $orderId = isset($params['id']) ? $params['id'] : 0;
  867. if ($orderId <= 0) {
  868. $this->error = '1013';
  869. return false;
  870. }
  871. $orderInfo = $this->model->where(['user_id' => $userId, 'id' => $orderId, 'mark' => 1, 'type' => 2])
  872. ->select(['id', 'user_id', 'order_no', 'business_id', 'payment_id', 'type', 'num', 'total', 'status'])
  873. ->first();
  874. $businessId = isset($orderInfo['business_id']) ? $orderInfo['business_id'] : 0;
  875. $tradeType = isset($orderInfo['type']) ? $orderInfo['type'] : 0;
  876. if (empty($orderInfo) || empty($businessId)) {
  877. $this->error = '3016';
  878. return false;
  879. }
  880. if ($orderInfo['status'] != 3) {
  881. $this->error = '3026';
  882. return false;
  883. }
  884. if ($tradeType != 2) {
  885. $this->error = '3024';
  886. return false;
  887. }
  888. $this->model->startTrans();
  889. // 订单状态更新
  890. if (!$this->model->where(['user_id' => $userId, 'id' => $orderId, 'mark' => 1])->update(['status' => 4, 'update_time' => time()])) {
  891. $this->model->rollBack();
  892. $this->error = '3023';
  893. return false;
  894. }
  895. // 交易处理
  896. if ($orderInfo['num'] > 0) {
  897. $info = $this->memberModel->where(['id' => $businessId, 'status' => 1, 'mark' => 1])->select(['id', 'username', 'usdt_num', 'user_type'])->first();
  898. if (empty($info)) {
  899. $this->model->rollBack();
  900. $this->error = '3019';
  901. return false;
  902. }
  903. // 商家进币
  904. if (!$this->memberModel->where(['id' => $businessId, 'mark' => 1])->increment('usdt_num', $orderInfo['num'])) {
  905. $this->model->rollBack();
  906. $this->error = '3019';
  907. return false;
  908. }
  909. // 明细处理
  910. $data = [
  911. 'order_no' => $orderInfo['order_no'],
  912. 'user_id' => $businessId,
  913. 'type' => 1,
  914. 'pay_type' => 1,
  915. 'change_type' => 1,
  916. 'num' => $orderInfo['num'],
  917. 'total' => $orderInfo['total'],
  918. 'balance' => floatval($info['usdt_num'] + $orderInfo['num']),
  919. 'create_time' => time(),
  920. 'remark' => '交易员买入',
  921. 'status' => 1,
  922. 'mark' => 1,
  923. ];
  924. if (!$this->capitalModel->edit($data)) {
  925. $this->error = '3014';
  926. $this->model->rollBack();
  927. return false;
  928. }
  929. }
  930. $this->model->commit();
  931. return true;
  932. }
  933. /**
  934. * 商家订单确认处理
  935. * @param $businessId 币商用户ID,平台处理时为0
  936. * @param $params 打款参数
  937. * @return false
  938. */
  939. public function businessCollection($businessId, $params)
  940. {
  941. $orderId = isset($params['id']) ? $params['id'] : 0;
  942. $catchUid = isset($params['catch_uid']) ? $params['catch_uid'] : 0;
  943. $type = isset($params['type']) ? $params['type'] : 0;
  944. if ($orderId <= 0) {
  945. $this->error = '1013';
  946. return false;
  947. }
  948. // 平台或币商处理
  949. $where = ['id' => $orderId, 'mark' => 1];
  950. if ($businessId) {
  951. $where['business_id'] = $businessId;
  952. }
  953. if ($type) {
  954. $where['type'] = $type;
  955. }
  956. $orderInfo = $this->model->where($where)
  957. ->select(['id', 'user_id','api_id','pt_order_no', 'order_no', 'business_id', 'type','contact_type','usdt_address','notify_url', 'trade_type', 'num', 'total','pay_time', 'status'])
  958. ->first();
  959. $userId = isset($orderInfo['user_id']) ? $orderInfo['user_id'] : 0;
  960. $orderType = isset($orderInfo['type']) ? $orderInfo['type'] : 0;
  961. $tradeType = isset($orderInfo['trade_type']) ? $orderInfo['trade_type'] : 0;
  962. if (empty($orderInfo) || (empty($userId) && $tradeType != 2)) {
  963. $this->error = '3016';
  964. return false;
  965. }
  966. $status = isset($params['status']) ? intval($params['status']) : 4;
  967. if ($status == 4 && $orderInfo['status'] != 3 && $businessId > 0) {
  968. $this->error = '3026';
  969. return false;
  970. }
  971. if ($status == 5 && $orderInfo['status'] == 8 && $businessId > 0) {
  972. $this->error = '3026';
  973. return false;
  974. }
  975. if ($status == 5 && $businessId <= 0 && $orderInfo['status'] == 4) {
  976. $this->error = '3026';
  977. return false;
  978. }
  979. if ($orderType != 1 && $status != 5) {
  980. $this->error = '3024';
  981. return false;
  982. }
  983. // 用户信息
  984. if ($businessId > 0) {
  985. $userInfo = MemberService::make()->getInfo($businessId);
  986. $userStatus = isset($userInfo['status']) ? $userInfo['status'] : 0;
  987. $username = isset($userInfo['username']) ? $userInfo['username'] : 0;
  988. if ($userStatus != 1) {
  989. $this->error = '2009';
  990. return false;
  991. }
  992. // 交易密码
  993. $tradePassword = isset($params['trade_password']) ? trim($params['trade_password']) : '';
  994. $password = isset($userInfo['trade_password']) ? trim($userInfo['trade_password']) : '';
  995. if (empty($password)) {
  996. $this->error = '2015';
  997. return false;
  998. }
  999. if (!$tradePassword || get_password($tradePassword . md5($tradePassword . 'otc')) != $password) {
  1000. $this->error = '2016';
  1001. return false;
  1002. }
  1003. }
  1004. $this->model->startTrans();
  1005. // 订单状态更新,异常或确认
  1006. $updateData = ['status' => $status, 'exception_catch_user' => $catchUid, 'update_time' => time()];
  1007. // 异常处理数据
  1008. if (isset($params['exception_type'])) {
  1009. $updateData['exception_type'] = intval($params['exception_type']);
  1010. }
  1011. if (isset($params['exception_sub_type'])) {
  1012. $updateData['exception_sub_type'] = intval($params['exception_sub_type']);
  1013. }
  1014. if (isset($params['exception_img'])) {
  1015. $updateData['exception_img'] = trim($params['exception_img']);
  1016. if (strpos($updateData['exception_img'], "temp")) {
  1017. $updateData['exception_img'] = save_image($updateData['exception_img'], 'images');
  1018. } else {
  1019. $updateData['exception_img'] = str_replace(IMG_URL, "", $updateData['exception_img']);
  1020. }
  1021. }
  1022. if (isset($params['exception_remark'])) {
  1023. $updateData['exception_remark'] = trim($params['exception_remark']);
  1024. }
  1025. if (isset($params['exception_status'])) {
  1026. $updateData['exception_status'] = intval($params['exception_status']);
  1027. }
  1028. if (!$this->model->where($where)->update($updateData)) {
  1029. $this->model->rollBack();
  1030. $this->error = '3023';
  1031. return false;
  1032. }
  1033. // 交易处理,如果是确认状态
  1034. if ($orderInfo['num'] > 0 && $status == 4 && $userId > 0 && $tradeType == 1) {
  1035. $info = $this->memberModel->where(['id' => $userId, 'status' => 1, 'mark' => 1])->select(['id', 'username', 'usdt_num', 'user_type'])->first();
  1036. if (empty($info)) {
  1037. $this->model->rollBack();
  1038. $this->error = '3019';
  1039. return false;
  1040. }
  1041. // 客户币进账
  1042. if (!$this->memberModel->where(['id' => $userId, 'mark' => 1])->increment('usdt_num', $orderInfo['num'])) {
  1043. $this->model->rollBack();
  1044. $this->error = '3019';
  1045. return false;
  1046. }
  1047. // 明细处理
  1048. $data = [
  1049. 'order_no' => $orderInfo['order_no'],
  1050. 'user_id' => $userId,
  1051. 'type' => 1,
  1052. 'pay_type' => 1,
  1053. 'change_type' => 1,
  1054. 'num' => $orderInfo['num'],
  1055. 'total' => $orderInfo['total'],
  1056. 'balance' => floatval($info['usdt_num'] + $orderInfo['num']),
  1057. 'create_time' => time(),
  1058. 'update_time' => time(),
  1059. 'remark' => '客户买入',
  1060. 'status' => 1,
  1061. 'mark' => 1,
  1062. ];
  1063. if (!$this->capitalModel->edit($data)) {
  1064. $this->error = '3014';
  1065. $this->model->rollBack();
  1066. return false;
  1067. }
  1068. // 更新收款地址数据
  1069. $paymentId = isset($orderInfo['payment_id']) ? $orderInfo['payment_id'] : 0;
  1070. $info = $this->paymentModel->where(['id' => $paymentId, 'mark' => 1])->select(['id', 'used_at'])->first();
  1071. if ($paymentId && $info) {
  1072. $usedAt = isset($info['used_at']) ? $info['used_at'] : '';
  1073. if ($usedAt < date('Y-m-d')) {
  1074. if (!$this->paymentModel->where(['id' => $paymentId])->update(['used_num' => 1, 'used_quota' => $orderInfo['total'], 'update_time' => time()])) {
  1075. $this->model->rollBack();
  1076. $this->error = '3018';
  1077. return false;
  1078. }
  1079. } else {
  1080. $res1 = $this->paymentModel->where(['id' => $paymentId])->increment('used_num', 1);
  1081. $res2 = $this->paymentModel->where(['id' => $paymentId])->increment('used_quota', floatval($orderInfo['total']));
  1082. if (!$res1 || !$res2) {
  1083. $this->model->rollBack();
  1084. $this->error = '3014';
  1085. return false;
  1086. }
  1087. }
  1088. }
  1089. }
  1090. // 外来平台需要出币和回调通知
  1091. else if(in_array($tradeType, [2,3])){
  1092. $usdtAddress = isset($orderInfo['usdt_address'])? $orderInfo['usdt_address'] : '';
  1093. $contactType = isset($orderInfo['contact_type'])? $orderInfo['contact_type'] : '';
  1094. $notifyUrl = isset($orderInfo['notify_url'])? $orderInfo['notify_url'] : '';
  1095. if($usdtAddress && $contactType && $notifyUrl){
  1096. // TRC 出币
  1097. if($contactType == 1 && !$result = UsdtWalletService::make()->usdtTrcTransfer($usdtAddress,$orderInfo['num'])){
  1098. $this->model->rollBack();
  1099. $this->error = '3045';
  1100. return false;
  1101. }
  1102. // ERC 出币
  1103. else if($contactType == 2 && !$result = UsdtWalletService::make()->usdtErcTransfer($usdtAddress,$orderInfo['num'])){
  1104. $this->model->rollBack();
  1105. $this->error = '3045';
  1106. return false;
  1107. }
  1108. // 更新出币数据和发送回调
  1109. $txid = isset($result['txID'])? $result['txID'] : '';
  1110. if($txid) {
  1111. if (!$this->model->where($where)->update(['txid' => $txid, 'notify_num' => 1, 'notify_time' => date('Y-m-d H:i:s')])) {
  1112. $this->model->rollBack();
  1113. $this->error = '3045';
  1114. return false;
  1115. }
  1116. // 发送回调通知
  1117. $notifyData = [
  1118. 'transaction_id' => $orderInfo['order_no'],
  1119. 'order_no' => $orderInfo['pt_order_no'],
  1120. 'usdt' => $orderInfo['num'],
  1121. 'amount' => $orderInfo['total'],
  1122. 'contact_type' => $orderInfo['contact_type'],
  1123. 'usdt_address' => $orderInfo['usdt_address'],
  1124. 'hash' => $txid,
  1125. 'status'=> 1,
  1126. 'pay_time'=> $orderInfo['pay_time']? $orderInfo['pay_time'] : time(),
  1127. 'trade_time'=> time(),
  1128. ];
  1129. \App\Services\Oapi\TradeOrderService::make()->notify($notifyUrl, $notifyData);
  1130. }
  1131. }
  1132. }
  1133. $this->model->commit();
  1134. $this->error = $status == 5 ? 3032 : 3021;
  1135. return true;
  1136. }
  1137. /**
  1138. * 取消订单
  1139. * @param $userId
  1140. * @param $params
  1141. * @return false
  1142. */
  1143. public function cancel($userId, $params)
  1144. {
  1145. $orderId = isset($params['id']) ? intval($params['id']) : 0;
  1146. if ($orderId <= 0) {
  1147. $this->error = '1013';
  1148. return false;
  1149. }
  1150. $orderInfo = $this->model->where(['user_id' => $userId, 'id' => $orderId, 'mark' => 1])
  1151. ->select(['id', 'order_no', 'business_id', 'type', 'num', 'total', 'status'])
  1152. ->first();
  1153. $tradeType = isset($orderInfo['type']) ? $orderInfo['type'] : 0;
  1154. $businessId = isset($orderInfo['business_id']) ? $orderInfo['business_id'] : 0;
  1155. if (empty($orderInfo) || $businessId <= 0) {
  1156. $this->error = '3016';
  1157. return false;
  1158. }
  1159. if ($orderInfo['status'] == 3) {
  1160. $this->error = '3027';
  1161. return false;
  1162. }
  1163. if ($orderInfo['status'] == 4) {
  1164. $this->error = '3028';
  1165. return false;
  1166. }
  1167. if ($orderInfo['status'] == 7) {
  1168. $this->error = '3030';
  1169. return false;
  1170. }
  1171. if (!in_array($orderInfo['status'], [1, 2])) {
  1172. $this->error = '3029';
  1173. return false;
  1174. }
  1175. $this->model->startTrans();
  1176. // 订单状态更新
  1177. $updateData = ['status' => 8, 'update_time' => time(), 'exception_remark' => '客户取消'];
  1178. if (!$this->model->where(['user_id' => $userId, 'id' => $orderId, 'mark' => 1])->update($updateData)) {
  1179. $this->model->rollBack();
  1180. $this->error = '3023';
  1181. return false;
  1182. }
  1183. // 出售订单,USDT退回
  1184. if ($tradeType == 2 && $orderInfo['num'] > 0) {
  1185. $info = $this->memberModel->where(['id' => $userId, 'status' => 1, 'mark' => 1])->select(['id', 'username', 'usdt_num', 'user_type'])->first();
  1186. if (empty($info)) {
  1187. $this->model->rollBack();
  1188. $this->error = '3019';
  1189. return false;
  1190. }
  1191. // 退还币给客户
  1192. if (!$this->memberModel->where(['id' => $userId, 'mark' => 1])->increment('usdt_num', $orderInfo['num'])) {
  1193. $this->model->rollBack();
  1194. $this->error = '3019';
  1195. return false;
  1196. }
  1197. // 明细处理
  1198. $data = [
  1199. 'order_no' => $orderInfo['order_no'],
  1200. 'user_id' => $userId,
  1201. 'type' => 3,
  1202. 'pay_type' => 1,
  1203. 'change_type' => 1,
  1204. 'num' => $orderInfo['num'],
  1205. 'total' => $orderInfo['total'],
  1206. 'balance' => floatval($info['usdt_num'] + $orderInfo['num']),
  1207. 'create_time' => time(),
  1208. 'update_time' => time(),
  1209. 'remark' => '客户取消退还',
  1210. 'status' => 1,
  1211. 'mark' => 1,
  1212. ];
  1213. if (!$this->capitalModel->edit($data)) {
  1214. $this->error = '3014';
  1215. $this->model->rollBack();
  1216. return false;
  1217. }
  1218. } // 买入取消
  1219. else if ($tradeType == 1 && $orderInfo['num'] > 0) {
  1220. $info = $this->memberModel->where(['id' => $businessId, 'status' => 1, 'mark' => 1])->select(['id', 'username', 'usdt_num', 'user_type'])->first();
  1221. if (empty($info)) {
  1222. $this->model->rollBack();
  1223. $this->error = '3019';
  1224. return false;
  1225. }
  1226. // 退还币给客户
  1227. if (!$this->memberModel->where(['id' => $businessId, 'mark' => 1])->increment('usdt_num', $orderInfo['num'])) {
  1228. $this->model->rollBack();
  1229. $this->error = '3019';
  1230. return false;
  1231. }
  1232. // 明细处理
  1233. $data = [
  1234. 'order_no' => $orderInfo['order_no'],
  1235. 'user_id' => $businessId,
  1236. 'type' => 3,
  1237. 'pay_type' => 1,
  1238. 'change_type' => 1,
  1239. 'num' => $orderInfo['num'],
  1240. 'total' => $orderInfo['total'],
  1241. 'balance' => floatval($info['usdt_num'] + $orderInfo['num']),
  1242. 'create_time' => time(),
  1243. 'update_time' => time(),
  1244. 'remark' => '客户取消退还',
  1245. 'status' => 1,
  1246. 'mark' => 1,
  1247. ];
  1248. if (!$this->capitalModel->edit($data)) {
  1249. $this->error = '3014';
  1250. $this->model->rollBack();
  1251. return false;
  1252. }
  1253. }
  1254. $this->model->commit();
  1255. return true;
  1256. }
  1257. /**
  1258. * 取消订单
  1259. * @param $businessId 币商用户,平台为0
  1260. * @param $params
  1261. * @return false
  1262. */
  1263. public function businessCancel($businessId, $params)
  1264. {
  1265. $orderId = isset($params['id']) ? intval($params['id']) : 0;
  1266. $catchUid = isset($params['catch_uid']) ? intval($params['catch_uid']) : 0;
  1267. if ($orderId <= 0) {
  1268. $this->error = '1013';
  1269. return false;
  1270. }
  1271. $where = ['id' => $orderId, 'mark' => 1];
  1272. if ($businessId) {
  1273. $where['business_id'] = $businessId;
  1274. }
  1275. $orderInfo = $this->model->where($where)
  1276. ->select(['id', 'user_id', 'order_no', 'business_id', 'type', 'num', 'total', 'status'])
  1277. ->first();
  1278. $tradeType = isset($orderInfo['type']) ? $orderInfo['type'] : 0;
  1279. $userId = isset($orderInfo['user_id']) ? $orderInfo['user_id'] : 0;
  1280. $orderBusinessId = isset($orderInfo['business_id']) ? $orderInfo['business_id'] : 0;
  1281. if (empty($orderInfo) || $orderBusinessId <= 0) {
  1282. $this->error = '3016';
  1283. return false;
  1284. }
  1285. if (empty($userId)) {
  1286. $this->error = '3019';
  1287. return false;
  1288. }
  1289. if ($orderInfo['status'] == 4) {
  1290. $this->error = '3028';
  1291. return false;
  1292. }
  1293. if (!in_array($orderInfo['status'], [1, 2, 3, 5, 7])) {
  1294. $this->error = '3029';
  1295. return false;
  1296. }
  1297. // 用户信息
  1298. $status = isset($params['status']) ? $params['status'] : 8;
  1299. if ($businessId > 0 && $status != 8) {
  1300. $userInfo = MemberService::make()->getInfo($businessId);
  1301. $status = isset($userInfo['status']) ? $userInfo['status'] : 0;
  1302. $username = isset($userInfo['username']) ? $userInfo['username'] : 0;
  1303. if ($status != 1) {
  1304. $this->error = '2009';
  1305. return false;
  1306. }
  1307. // 交易密码
  1308. $tradePassword = isset($params['trade_password']) ? trim($params['trade_password']) : '';
  1309. $password = isset($userInfo['trade_password']) ? trim($userInfo['trade_password']) : '';
  1310. if (empty($password)) {
  1311. $this->error = '2015';
  1312. return false;
  1313. }
  1314. if (!$tradePassword || get_password($tradePassword . md5($tradePassword . 'otc')) != $password) {
  1315. $this->error = '2016';
  1316. return false;
  1317. }
  1318. }
  1319. $this->model->startTrans();
  1320. // 订单状态更新,或异常处理
  1321. $updateData = ['status' => $status, 'exception_catch_user' => $catchUid, 'update_time' => time(), 'exception_remark' => '交易员取消'];
  1322. // 异常处理数据
  1323. if (isset($params['exception_type'])) {
  1324. $updateData['exception_type'] = intval($params['exception_type']);
  1325. }
  1326. if (isset($params['exception_sub_type'])) {
  1327. $updateData['exception_sub_type'] = intval($params['exception_sub_type']);
  1328. }
  1329. if (isset($params['exception_img'])) {
  1330. $updateData['exception_img'] = trim($params['exception_img']);
  1331. if (strpos($updateData['exception_img'], "temp")) {
  1332. $updateData['exception_img'] = save_image($updateData['exception_img'], 'images');
  1333. } else {
  1334. $updateData['exception_img'] = str_replace(IMG_URL, "", $updateData['exception_img']);
  1335. }
  1336. }
  1337. if (isset($params['exception_remark'])) {
  1338. $updateData['exception_remark'] = trim($params['exception_remark']);
  1339. }
  1340. if (isset($params['exception_status'])) {
  1341. $updateData['exception_status'] = intval($params['exception_status']);
  1342. }
  1343. if (isset($params['refund_status'])) {
  1344. $updateData['refund_status'] = intval($params['refund_status']);
  1345. }
  1346. if (isset($params['refund_money'])) {
  1347. $updateData['refund_money'] = intval($params['refund_money']);
  1348. }
  1349. if (!$this->model->where($where)->update($updateData)) {
  1350. $this->model->rollBack();
  1351. $this->error = '3023';
  1352. return false;
  1353. }
  1354. // 出售订单,状态已取消,USDT退回
  1355. if ($tradeType == 2 && $status == 8 && $orderInfo['num'] > 0) {
  1356. $info = $this->memberModel->where(['id' => $userId, 'status' => 1, 'mark' => 1])->select(['id', 'username', 'usdt_num', 'user_type'])->first();
  1357. if (empty($info)) {
  1358. $this->model->rollBack();
  1359. $this->error = '3019';
  1360. return false;
  1361. }
  1362. // 退还币给客户
  1363. if (!$this->memberModel->where(['id' => $userId, 'mark' => 1])->increment('usdt_num', $orderInfo['num'])) {
  1364. $this->model->rollBack();
  1365. $this->error = '3019';
  1366. return false;
  1367. }
  1368. // 明细处理
  1369. $data = [
  1370. 'order_no' => $orderInfo['order_no'],
  1371. 'user_id' => $userId,
  1372. 'type' => 3,
  1373. 'pay_type' => 1,
  1374. 'change_type' => 1,
  1375. 'num' => $orderInfo['num'],
  1376. 'total' => $orderInfo['total'],
  1377. 'balance' => floatval($info['usdt_num'] + $orderInfo['num']),
  1378. 'create_time' => time(),
  1379. 'update_time' => time(),
  1380. 'remark' => '交易员取消买入退还',
  1381. 'status' => 1,
  1382. 'mark' => 1,
  1383. ];
  1384. if (!$this->capitalModel->edit($data)) {
  1385. $this->error = '3014';
  1386. $this->model->rollBack();
  1387. return false;
  1388. }
  1389. } // 客户买入订单取消
  1390. else if ($tradeType == 1 && $status == 8 && $orderInfo['num'] > 0) {
  1391. $info = $this->memberModel->where(['id' => $orderBusinessId, 'status' => 1, 'mark' => 1])->select(['id', 'username', 'usdt_num', 'user_type'])->first();
  1392. if (empty($info)) {
  1393. $this->model->rollBack();
  1394. $this->error = '3019';
  1395. return false;
  1396. }
  1397. // 退还币给客户
  1398. if (!$this->memberModel->where(['id' => $orderBusinessId, 'mark' => 1])->increment('usdt_num', $orderInfo['num'])) {
  1399. $this->model->rollBack();
  1400. $this->error = '3019';
  1401. return false;
  1402. }
  1403. // 明细处理
  1404. $data = [
  1405. 'order_no' => $orderInfo['order_no'],
  1406. 'user_id' => $orderBusinessId,
  1407. 'type' => 3,
  1408. 'pay_type' => 1,
  1409. 'change_type' => 1,
  1410. 'num' => $orderInfo['num'],
  1411. 'total' => $orderInfo['total'],
  1412. 'balance' => floatval($info['usdt_num'] + $orderInfo['num']),
  1413. 'create_time' => time(),
  1414. 'update_time' => time(),
  1415. 'remark' => '交易员取消卖出退还',
  1416. 'status' => 1,
  1417. 'mark' => 1,
  1418. ];
  1419. if (!$this->capitalModel->edit($data)) {
  1420. $this->error = '3014';
  1421. $this->model->rollBack();
  1422. return false;
  1423. }
  1424. }
  1425. $this->model->commit();
  1426. $this->error = $status == 5 ? 3032 : 3034;
  1427. return true;
  1428. }
  1429. /**
  1430. * 无效订单处理
  1431. * @return false
  1432. */
  1433. public function catchInvalidOrder()
  1434. {
  1435. $cacheKey = "caches:trades:cancels:";
  1436. if (RedisService::get($cacheKey . 'lock')) {
  1437. return false;
  1438. }
  1439. RedisService::set($cacheKey . 'lock', 1, rand(3, 5));
  1440. $overtime = ConfigService::make()->getConfigByCode('trade_order_overtime');
  1441. $cancelTime = ConfigService::make()->getConfigByCode('trade_order_cancel');
  1442. $catchNum = ConfigService::make()->getConfigByCode('trade_order_catch_num');
  1443. $catchNum = $catchNum > 0 ? $catchNum : 200;
  1444. // 处理超时订单
  1445. if ($overtime > 0) {
  1446. $this->model->where(['mark' => 1])
  1447. ->where('status', '<=', 2)
  1448. ->where('create_time', '<=', time() - $overtime * 60)
  1449. ->update(['status' => 7, 'catch_at' => time()]);
  1450. }
  1451. if ($cancelTime <= 0) {
  1452. $this->error = '1023';
  1453. return false;
  1454. }
  1455. $fail = 0;
  1456. $success = 0;
  1457. $this->model->where(function ($query) use ($cancelTime) {
  1458. // 已更新为超时的订单
  1459. $query->where(['mark' => 1, 'status' => 7])
  1460. ->where('catch_at', '<=', time() - $cancelTime * 60);
  1461. })
  1462. ->orWhere(function ($query) use ($cancelTime, $overtime) {
  1463. $query->where('mark', '=', 1)
  1464. ->where('status', '<=', 2)
  1465. ->where('create_time', '<=', time() - ($cancelTime + $overtime) * 60);
  1466. })
  1467. ->select(['id', 'user_id', 'business_id', 'order_no', 'type', 'trade_type', 'num', 'total'])
  1468. ->take($catchNum)
  1469. ->get()
  1470. ->each(function ($item, $k) use ($cacheKey, &$fail, &$success) {
  1471. // 客户卖出订单退还
  1472. $date = date('Y-m-d H:i:s');
  1473. $type = isset($item['type']) ? $item['type'] : 0;
  1474. if ($type == 2) {
  1475. // 内部订单退还USDT给客户
  1476. if ($item['trade_type'] == 1) {
  1477. if (!$this->orderReback($item['user_id'], $item)) {
  1478. $fail++;
  1479. RedisService::set($cacheKey . "order_{$item['order_no']}:u{$item['user_id']}_fail", ['order' => $item, 'msg' => lang($this->error), 'date' => $date], 3600);
  1480. } else {
  1481. $success++;
  1482. RedisService::set($cacheKey . "order_{$item['order_no']}:u{$item['user_id']}_success", ['order' => $item, 'msg' => lang($this->error), 'date' => $date], 3600);
  1483. }
  1484. }
  1485. } else {
  1486. if (!$this->orderReback($item['business_id'], $item)) {
  1487. $fail++;
  1488. RedisService::set($cacheKey . "order_{$item['order_no']}:b{$item['business_id']}_fail", ['order' => $item, 'msg' => lang($this->error), 'date' => $date], 3600);
  1489. } else {
  1490. $success++;
  1491. RedisService::set($cacheKey . "order_{$item['order_no']}:b{$item['business_id']}_success", ['order' => $item, 'msg' => lang($this->error), 'date' => $date], 3600);
  1492. }
  1493. }
  1494. });
  1495. return ['success' => $success, 'fail' => $fail];
  1496. }
  1497. /**
  1498. * 订单取消退还处理
  1499. * @param $userId
  1500. * @param $orderInfo
  1501. * @return bool
  1502. */
  1503. protected function orderReback($userId, $orderInfo)
  1504. {
  1505. try {
  1506. if ($orderInfo['num'] <= 0) {
  1507. return false;
  1508. }
  1509. $this->model->startTrans();
  1510. $updateData = ['status' => 8, 'update_time' => time(), 'catch_at' => time(),'exception_status'=> 0, 'exception_remark' => '系统取消'];
  1511. if (!$this->model->where(['id' => $orderInfo['id']])->update($updateData)) {
  1512. $this->model->rollBack();
  1513. $this->error = '3043';
  1514. return false;
  1515. }
  1516. $info = $this->memberModel->where(['id' => $userId, 'status' => 1, 'mark' => 1])->select(['id', 'username', 'usdt_num', 'user_type'])->first();
  1517. if (empty($info)) {
  1518. $this->model->rollBack();
  1519. $this->error = '3019';
  1520. return false;
  1521. }
  1522. // 退还币给客户
  1523. if (!$this->memberModel->where(['id' => $userId, 'mark' => 1])->increment('usdt_num', $orderInfo['num'])) {
  1524. $this->model->rollBack();
  1525. $this->error = '3019';
  1526. return false;
  1527. }
  1528. // 明细处理
  1529. $data = [
  1530. 'order_no' => $orderInfo['order_no'],
  1531. 'user_id' => $userId,
  1532. 'type' => 3,
  1533. 'pay_type' => 1,
  1534. 'change_type' => 1,
  1535. 'num' => $orderInfo['num'],
  1536. 'total' => $orderInfo['total'],
  1537. 'balance' => floatval($info['usdt_num'] + $orderInfo['num']),
  1538. 'create_time' => time(),
  1539. 'update_time' => time(),
  1540. 'remark' => '系统自动取消退还',
  1541. 'status' => 1,
  1542. 'mark' => 1,
  1543. ];
  1544. if (!$this->capitalModel->edit($data)) {
  1545. $this->error = '3014';
  1546. $this->model->rollBack();
  1547. return false;
  1548. }
  1549. $this->model->commit();
  1550. $this->error = '3044';
  1551. return true;
  1552. } catch (\Exception $exception) {
  1553. $this->error = $exception->getMessage();
  1554. return false;
  1555. }
  1556. }
  1557. /**
  1558. * 重新派单
  1559. * @param $id 订单ID
  1560. * @param $businessId 新派单用户
  1561. * @return false
  1562. */
  1563. public function reassign($id, $businessId)
  1564. {
  1565. if (empty($id) || empty($businessId)) {
  1566. $this->error = '1013';
  1567. return false;
  1568. }
  1569. $orderInfo = $this->model->where(['id' => $id])
  1570. ->select(['id', 'user_id', 'order_no', 'business_id', 'type', 'num', 'total', 'status'])
  1571. ->first();
  1572. $tradeType = isset($orderInfo['type']) ? $orderInfo['type'] : 0;
  1573. if (empty($orderInfo)) {
  1574. $this->error = '3016';
  1575. return false;
  1576. }
  1577. // 状态
  1578. if (!in_array($orderInfo['status'], [1, 2, 3, 5, 7])) {
  1579. $this->error = '3039';
  1580. return false;
  1581. }
  1582. if ($businessId == $orderInfo['business_id']) {
  1583. $this->error = '3035';
  1584. return false;
  1585. }
  1586. // 派单用户信息
  1587. $businessInfo = $this->memberModel->from('member as a')
  1588. ->leftJoin('member_setting as ms', 'ms.user_id', '=', 'a.id')
  1589. ->where(['a.id' => $businessId, 'a.status' => 1, 'a.mark' => 1])
  1590. ->select(['a.id', 'a.username', 'a.usdt_num', 'ms.buy_online', 'ms.buy_online_time', 'ms.sell_online', 'ms.sell_online_time'])
  1591. ->first();
  1592. if (empty($businessInfo)) {
  1593. $this->error = '3036';
  1594. return false;
  1595. }
  1596. // 余额
  1597. if ($businessInfo['usdt_num'] < $orderInfo['num']) {
  1598. $this->error = '3036';
  1599. return false;
  1600. }
  1601. // 在线状态
  1602. if ($tradeType == 1) {
  1603. if ($businessInfo['buy_online'] != 1 || $businessInfo['buy_online_time'] <= time()) {
  1604. $this->error = '3036';
  1605. return false;
  1606. }
  1607. } else if ($tradeType == 2) {
  1608. if ($businessInfo['sell_online'] != 1 || $businessInfo['sell_online_time'] <= time()) {
  1609. $this->error = '3036';
  1610. return false;
  1611. }
  1612. }
  1613. $payment = MemberPaymentService::make()->getPayment($businessId);
  1614. if (empty($payment)) {
  1615. $this->error = '3040';
  1616. return false;
  1617. }
  1618. $updateData = ['business_id' => $businessId, 'status' => 1, 'mark' => 1, 'create_time' => time(), 'pay_time' => 0, 'pay_img' => '', 'payment_data' => json_encode($payment, 256), 'exception_type' => 0, 'exception_remark' => '平台重新派单'];
  1619. if ($this->model->where(['id' => $id])->update($updateData)) {
  1620. $this->error = '3041';
  1621. return true;
  1622. }
  1623. $this->error = '3042';
  1624. return false;
  1625. }
  1626. }