OrderService.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. <?php
  2. /**
  3. * Author: luzheng.liu
  4. * Time: 2020/12/24 13:44
  5. */
  6. namespace app\common\service;
  7. use app\api\controller\Order;
  8. use app\api\exception\ApiException;
  9. use app\api\model\AllocateModel;
  10. use app\api\model\CartModel;
  11. use app\api\model\OrderModel;
  12. use app\api\model\OrderProductModel;
  13. use app\api\model\ProductModel;
  14. use app\api\model\RechargeOrder;
  15. use app\api\model\RechargeRecordModel;
  16. use app\api\model\StaffModel;
  17. use app\api\model\StoreModel;
  18. use app\api\model\UserModel;
  19. use app\api\model\WriteOffModel;
  20. use app\common\until\Until;
  21. use GuzzleHttp\Client;
  22. use think\Exception;
  23. use think\facade\Cache;
  24. use think\facade\Config;
  25. use think\Model;
  26. use const http\Client\Curl\Features\UNIX_SOCKETS;
  27. class OrderService {
  28. public $userName = 'heshen';
  29. public $passwd = 'heshenit@0563';
  30. public $time = [];
  31. public function payOrder($input) {
  32. $userId = empty($input['userId']) ? Until::$userId : $input['userId'];
  33. $payCode = (new StoreModel())->getPayCode($input['storeId']);
  34. $this->time[] = 'start' . time();
  35. $orderSn = Until::createSn();
  36. $productModel = new ProductModel();
  37. $productModel->setWhere(['p.id' => $input['productId'],'spt.store_id' => $input['storeId']]);
  38. $productInfo = $productModel->getProductInfo();
  39. $userInfo = (new UserModel())::where(['id' => $userId])->find();
  40. $userInfo = Until::modelToArray($userInfo);
  41. if (empty($userInfo)) {
  42. throw new ApiException('无此用户');
  43. }
  44. $model = new OrderModel();
  45. try {
  46. $orderType = 1;
  47. if (Until::$isAdmin) {
  48. $orderType = 2;
  49. }
  50. $model->startTrans();
  51. $orderMoney = $productInfo['realPrice'] * (int)abs($input['num']);
  52. $orderId = $model->insertGetId([
  53. 'order_sn' => $orderSn,
  54. 'order_money' => $orderMoney,
  55. 'product_id' => $input['productId'],
  56. 'staff_id' => $input['staffId'] ?? 0,
  57. 'num' => (int)abs($input['num']),
  58. 'store_id' => $input['storeId'],
  59. 'appointment_time' => $input['appointmentTime'],
  60. 'end_time' => $input['endTime'],
  61. 'mobile' => $input['mobile'],
  62. 'status' => 1,
  63. 'order_type' => $orderType,
  64. 'user_id' => $userId,
  65. 'admin_id' => Until::$adminId
  66. ]);
  67. (new AllocateModel())->insertGetId([
  68. 'order_id' => $orderId,
  69. 'staff_id' => $input['staffId'],
  70. 'assign_admin_id' => Until::$adminId,
  71. 'server_start_time' => $input['appointmentTime'],
  72. ]);
  73. (new StaffModel())::where(['id' => $input['staffId']])->update(['server_status' => 2]);
  74. $opModel = new OrderProductModel();
  75. $opModel->insert([
  76. 'order_id' => $orderId,
  77. 'product_id' => $input['productId'],
  78. 'product_num' => (int)abs($input['num']),
  79. 'current_price' => $productInfo['current_price'],
  80. 'real_price' => $productInfo['realPrice'],
  81. 'product_name' => $productInfo['product_name'],
  82. 'product_img' => $productInfo['product_img'],
  83. 'old_price' => $productInfo['old_price'],
  84. 'company_id' => $productInfo['company_id'],
  85. 'brand_id' => $productInfo['brand_id'],
  86. 'product_type_id' => $productInfo['product_type_id'],
  87. 'type' => $productInfo['type'],
  88. 'product_snap' => json_encode($productInfo)
  89. ]);
  90. (new WriteOffModel())->insertGetId([
  91. 'write_off_code' => '',
  92. 'order_id' => $orderId,
  93. 'write_off_status' => 1,
  94. ]);
  95. $model->commit();
  96. } catch (\Exception $e) {
  97. $model->rollback();
  98. throw new ApiException($e->getMessage());
  99. }
  100. //{attach string支付主体的标识
  101. //mark string商品信息
  102. //money integer($int32)金额,分为单位
  103. //openId string小程序的openid
  104. //orderId string订单号
  105. //payCode string支付标识
  106. //username string用户名
  107. //}
  108. if (!Until::$isAdmin) {
  109. $otherData = [
  110. 'openId' => $userInfo['open_id'],
  111. 'attach' => 'storeId:' . $input['storeId'],
  112. 'money' => $orderMoney * 100,
  113. 'mark' => '购买了' . $productInfo['product_name'],
  114. 'orderId' => $orderSn,
  115. 'username' => $userInfo['name'],
  116. 'payCode' => strtoupper($payCode),
  117. ];
  118. $this->time[] = 'leo-start' . time();
  119. $wxOrderInfo = $this->createOrderForOther($otherData);
  120. $order = [
  121. 'nonceStr' => $wxOrderInfo['nonceStr'],
  122. 'package' => $wxOrderInfo['pack'],
  123. 'paySign' => $wxOrderInfo['paySign'],
  124. 'timeStamp' => $wxOrderInfo['timeStamp'],
  125. 'signType' => $wxOrderInfo['signType'],
  126. 'orderSn' => $orderSn,
  127. 'orderId' => $orderId
  128. ];
  129. }
  130. $this->time[] = 'leo-end' . time();
  131. $order['time'] = $this->time;
  132. return $order;
  133. }
  134. public function payFoodOrder($input) {
  135. $orderSn = Until::createSn();
  136. $cartModel = new CartModel();
  137. $cartModel->setFields('c.store_id,cp.num,p.*');
  138. $cartModel->setWhere(['c.id' => $input['cartId']]);
  139. $cartInfo = $cartModel->getCartList();
  140. $orderMoney = 0;
  141. $recordData = [];
  142. $storeId = 0;
  143. foreach ($cartInfo as $info) {
  144. $storeId = $info['store_id'];
  145. $orderMoney += $info['num'] * $info['current_price'];
  146. }
  147. $payCode = (new StoreModel())->getPayCode($storeId);
  148. $userInfo = (new UserModel())::where(['id' => Until::$userId])->find();
  149. $userInfo = Until::modelToArray($userInfo);
  150. if (empty($userInfo)) {
  151. throw new ApiException('无此用户');
  152. }
  153. $model = new OrderModel();
  154. try {
  155. $userId = Until::$userId;
  156. $orderType = 3;
  157. $model->startTrans();
  158. $cartModel::where(['id' => $input['cartId']])->update(['status' => 0]);
  159. $orderId = $model->insertGetId([
  160. 'order_sn' => $orderSn,
  161. 'order_money' => $orderMoney,
  162. 'product_id' => 0,
  163. 'num' => 0,
  164. 'store_id' => $storeId,
  165. 'table_id' => $input['tableId'],
  166. 'appointment_time' => null,
  167. 'end_time' => null,
  168. 'mobile' => '',
  169. 'order_type' => $orderType,
  170. 'user_id' => $userId,
  171. ]);
  172. $opModel = new OrderProductModel();
  173. foreach ($cartInfo as $info) {
  174. $recordData[] = [
  175. 'order_id' => $orderId,
  176. 'product_id' => $info['id'],
  177. 'product_num' => $info['num'],
  178. 'current_price' => $info['current_price'],
  179. 'product_name' => $info['product_name'],
  180. 'product_img' => $info['product_img'],
  181. 'old_price' => $info['old_price'],
  182. 'company_id' => $info['company_id'],
  183. 'brand_id' => $info['brand_id'],
  184. 'product_type_id' => $info['product_type_id'],
  185. 'type' => $info['type'],
  186. 'product_snap' => json_encode($info)
  187. ];
  188. }
  189. $opModel->insertAll($recordData);
  190. $cartModel::where(['id' => $input['cartId']])->update(['status' => 0]);
  191. $model->commit();
  192. } catch (\Exception $e) {
  193. $model->rollback();
  194. throw new ApiException($e->getMessage());
  195. }
  196. //{attach string支付主体的标识
  197. //mark string商品信息
  198. //money integer($int32)金额,分为单位
  199. //openId string小程序的openid
  200. //orderId string订单号
  201. //payCode string支付标识
  202. //username string用户名
  203. //}
  204. if (!Until::$isAdmin) {
  205. $otherData = [
  206. 'openId' => $userInfo['open_id'],
  207. 'attach' => 'storeId:' . $storeId,
  208. 'money' => $orderMoney * 100,
  209. 'mark' => '购买了小食',
  210. 'orderId' => $orderSn,
  211. 'username' => $userInfo['name'],
  212. 'payCode' => strtoupper($payCode),
  213. ];
  214. $this->time[] = 'leo-start' . time();
  215. $wxOrderInfo = $this->createOrderForOther($otherData);
  216. $order = [
  217. 'nonceStr' => $wxOrderInfo['nonceStr'],
  218. 'package' => $wxOrderInfo['pack'],
  219. 'paySign' => $wxOrderInfo['paySign'],
  220. 'timeStamp' => $wxOrderInfo['timeStamp'],
  221. 'signType' => $wxOrderInfo['signType'],
  222. 'orderSn' => $orderSn,
  223. 'orderId' => $orderId
  224. ];
  225. }
  226. $this->time[] = 'leo-end' . time();
  227. $order['time'] = $this->time;
  228. return $order;
  229. }
  230. public function payAgain(int $orderId) {
  231. $model = new OrderModel();
  232. $info = $model::where(['id' => $orderId])->find();
  233. $payCode = (new StoreModel())->getPayCode($info['store_id']);
  234. // $productInfo = (new ProductModel())::where(['id' => $info['product_id']])->find();
  235. if ($info['status'] === OrderModel::IS_PAY) {
  236. throw new ApiException('订单已支付');
  237. }
  238. $userInfo = (new UserModel())::where(['id' => Until::$userId])->find();
  239. if (empty($userInfo)) {
  240. throw new ApiException('无此用户');
  241. }
  242. $paySn = Until::createSn();
  243. $model::where(['id' => $orderId])->update(['pay_sn' => $paySn]);
  244. $otherData = [
  245. 'openId' => $userInfo['open_id'],
  246. 'attach' => 'storeId:' . $info['store_id'],
  247. 'money' => $info['order_money'] * 100,
  248. 'mark' => '购买了商品',
  249. 'orderId' => $paySn,
  250. 'username' => $userInfo['name'],
  251. 'payCode' => strtoupper($payCode),
  252. ];
  253. $wxOrderInfo = $this->createOrderForOther($otherData);
  254. $order = [
  255. 'nonceStr' => $wxOrderInfo['nonceStr'],
  256. 'package' => $wxOrderInfo['pack'],
  257. 'paySign' => $wxOrderInfo['paySign'],
  258. 'timeStamp' => $wxOrderInfo['timeStamp'],
  259. 'signType' => $wxOrderInfo['signType'],
  260. 'orderSn' => $info['order_sn'],
  261. 'orderId' => $orderId
  262. ];
  263. return $order;
  264. }
  265. public function getPayToken() {
  266. $this->time[] = 'payToken-start-' . time();
  267. $key = 'payToken' . $this->userName;
  268. $token = Cache::get($key);
  269. if (empty($token)) {
  270. $token = $this->getAuthPay();
  271. Cache::set($key, $token, '7100');
  272. return $token;
  273. }
  274. $this->time[] = 'payToken-end-' . time();
  275. return $token;
  276. }
  277. public function getAuthPay() {
  278. $client = new Client();
  279. $time = Until::msectime();
  280. $res = $client->request('Post',
  281. Config::get('domain') . "api/auth/create", [
  282. 'json' => [
  283. 'username' => $this->userName,
  284. "password" => $this->passwd,
  285. 'timestamp' => $time,
  286. 'sign' => md5($this->userName . $time . $this->passwd)
  287. ]
  288. ]);
  289. $info = json_decode((string)$res->getBody(), true);
  290. if ($info['code'] != 200) {
  291. throw new ApiException($info['msg']);
  292. }
  293. return $info['data']['token'];
  294. }
  295. public function createOrderForOther(array $data) {
  296. // var_dump('start'.time());
  297. $this->time[] = 'createOrder-start-' . time();
  298. $client = new Client();
  299. $res = $client->request('Post',
  300. Config::get('domain') . "api/supers/wx-pay/gateway-no-order", [
  301. 'json' => $data,
  302. 'headers' => [
  303. 'API-TOKEN-V1' => $this->getPayToken()
  304. ]
  305. ]);
  306. $info = json_decode((string)$res->getBody(), true);
  307. if ($info['code'] != 200) {
  308. throw new ApiException($info['msg']);
  309. }
  310. $this->time[] = 'createOrder-end-' . time();
  311. // var_dump('end'.time());
  312. return $info['data'];
  313. }
  314. public function notify(string $orderSn) {
  315. $model = new OrderModel();
  316. $rs = $model::where(['order_sn' => $orderSn])->whereOr(['pay_sn' => $orderSn])->find();
  317. if (empty($rs) || $rs['status'] === 2) {
  318. $this->rechargeNotify($orderSn);
  319. return;
  320. }
  321. // var_dump($rs);
  322. $model::where(['order_sn' => $orderSn])->update(['status' => 2, 'pay_time' => date('Y-m-d H:i:s')]);
  323. $model::where(['pay_sn' => $orderSn])->update(['status' => 2, 'pay_time' => date('Y-m-d H:i:s')]);
  324. $wModel = new WriteOffModel();
  325. $code = $this->changeCode();
  326. $wModel::where(['order_id' => $rs['id']])->update([
  327. 'write_off_code' => $code,
  328. 'over_time' => date('Y-m-d H:i:s', time() + 2 * 60),
  329. ]);
  330. }
  331. public function changeCode() {
  332. $wModel = new WriteOffModel();
  333. $codeList = $wModel::where(['write_off_status' => WriteOffModel::NO_WRITE_OFF])->field('write_off_code')->select();
  334. $codeList = Until::modelToArray($codeList);
  335. $codeArr = [];
  336. foreach ($codeList as $v) {
  337. $codeArr[] = $v['write_off_code'];
  338. }
  339. $code = $this->makeUniqCode($codeArr);
  340. return $code;
  341. }
  342. public function makeUniqCode(array $codeList) {
  343. $code = random_int(10000, 99999);
  344. if (in_array($code, $codeList)) {
  345. $this->makeUniqCode($codeList);
  346. }
  347. return $code;
  348. }
  349. public function createRechargeOrder(string $money) {
  350. $model = new RechargeOrder();
  351. $payCode = 'HESHEN';
  352. $orderSn = Until::createSn();
  353. $userModel = new UserModel();
  354. $userInfo = $userModel::where(['id' => Until::$userId])->find();
  355. $orderId = $model->insertGetId([
  356. 'user_id' => Until::$userId,
  357. 'recharge' => $money,
  358. 'order_sn' => $orderSn,
  359. ]);
  360. $otherData = [
  361. 'openId' => $userInfo['open_id'],
  362. 'attach' => 'recharge',
  363. 'money' => $money * 100,
  364. 'mark' => '充值',
  365. 'orderId' => $orderSn,
  366. 'username' => $userInfo['name'],
  367. 'payCode' => strtoupper($payCode),
  368. ];
  369. $wxOrderInfo = $this->createOrderForOther($otherData);
  370. $order = [
  371. 'nonceStr' => $wxOrderInfo['nonceStr'],
  372. 'package' => $wxOrderInfo['pack'],
  373. 'paySign' => $wxOrderInfo['paySign'],
  374. 'timeStamp' => $wxOrderInfo['timeStamp'],
  375. 'signType' => $wxOrderInfo['signType'],
  376. 'orderSn' => $orderSn,
  377. 'orderId' => $orderId
  378. ];
  379. return $order;
  380. }
  381. /**
  382. * 充值订单的回调
  383. * @param string $orderSn
  384. * @throws \think\exception\PDOException
  385. */
  386. public function rechargeNotify(string $orderSn) {
  387. $rechargeOrderModel = new RechargeOrder();
  388. $rechargeInfo = $rechargeOrderModel::where(['order_sn' => $orderSn])->find();
  389. if (empty($rechargeInfo) || $rechargeInfo['pay_status'] == RechargeOrder::PAY) {
  390. return;
  391. }
  392. $rechargeModel = new RechargeRecordModel();
  393. $userModel = new UserModel();
  394. try {
  395. $rechargeOrderModel->startTrans();
  396. $userInfo = $userModel::where(['id' => $rechargeInfo['user_id']])->find();
  397. $userModel::where(['id' => $rechargeInfo['user_id']])->inc('money', $rechargeInfo['recharge'])->update();
  398. $rechargeOrderModel::where(['order_sn' => $orderSn, 'pay_status' => $rechargeOrderModel::NO_PAY])
  399. ->update([
  400. 'pay_status' => $rechargeOrderModel::PAY,
  401. 'pay_success_time' => date('Y-m-d H:i:s'),
  402. ]);
  403. $rechargeModel->insert([
  404. 'user_id' => $userInfo['id'],
  405. 'before_recharge' => $userInfo['money'],
  406. 'recharge' => $rechargeInfo['recharge'],
  407. 'after_recharge' => $userInfo['money'] + $rechargeInfo['recharge'],
  408. ]);
  409. $rechargeOrderModel->commit();
  410. } catch (Exception $e) {
  411. $rechargeOrderModel->rollback();
  412. throw new ApiException($e->getMessage());
  413. }
  414. }
  415. }