CouponService.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. <?php
  2. namespace App\Services\Pay;
  3. use App\Exceptions\AlertException;
  4. use App\Exceptions\ApiException;
  5. use App\Http\Controllers\Order;
  6. use App\Models\CouponModel;
  7. class CouponService
  8. {
  9. /**
  10. * @var int uid
  11. */
  12. public $uid;
  13. /**
  14. * 商品种类
  15. * @var
  16. */
  17. private $goods_scope;
  18. /**
  19. * 优惠券ID
  20. * @var int
  21. */
  22. public $coupon_id;
  23. private $attributes = [];
  24. /**
  25. * 生成数量
  26. * @var int
  27. */
  28. public $number = 1;
  29. /**
  30. * 批号ID
  31. * @var int
  32. */
  33. public $batch_id;
  34. /**
  35. * 商品ID
  36. * @var int
  37. */
  38. public $goods_id;
  39. /**
  40. * 折扣
  41. * @var int
  42. */
  43. public $discount = 0;
  44. /**
  45. * 商品总价格
  46. * @var int
  47. */
  48. public $total_amount;
  49. /**
  50. * 优惠后价格
  51. * @var int
  52. */
  53. public $settlement_total_amount;
  54. /**
  55. * 优惠券金额
  56. * @var int
  57. */
  58. public $coupon_amount;
  59. /**
  60. * 优惠券
  61. * @var CouponModel
  62. */
  63. private $coupon;
  64. /**
  65. * 设置uid
  66. * @param int $uid
  67. * @return $this
  68. */
  69. public function setUid(int $uid)
  70. {
  71. $this->uid = $uid;
  72. return $this;
  73. }
  74. public function getUid(): int
  75. {
  76. return $this->uid;
  77. }
  78. /**
  79. * 设置优惠券ID
  80. * @param int $id
  81. * @return $this
  82. */
  83. public function setCouponId(int $id)
  84. {
  85. $this->coupon_id = $id;
  86. return $this;
  87. }
  88. public function getCouponId(): int
  89. {
  90. return $this->coupon_id;
  91. }
  92. /**
  93. * 设置商品ID
  94. * @param int $id
  95. * @return $this
  96. */
  97. public function setGoodsId(int $id)
  98. {
  99. $this->goods_id = $id;
  100. return $this;
  101. }
  102. /**
  103. * 获取商品ID
  104. * @return int
  105. */
  106. public function getGoodsId(): int
  107. {
  108. return $this->goods_id;
  109. }
  110. /**
  111. * 设置批量ID
  112. * @param $batch_id
  113. * @return $this
  114. */
  115. public function setBatchId($batch_id)
  116. {
  117. $this->batch_id = $batch_id;
  118. return $this;
  119. }
  120. /**
  121. * 获取批号ID
  122. * @return string
  123. */
  124. public function getBatchId(): string
  125. {
  126. return $this->batch_id;
  127. }
  128. /**
  129. * 设置券的数量
  130. * @param int $number
  131. * @return $this
  132. */
  133. public function setNumber(int $number)
  134. {
  135. $this->number = $number;
  136. return $this;
  137. }
  138. /**
  139. * 优惠券信息
  140. * @return mixed
  141. * @throws AlertException
  142. */
  143. public function getCoupon()
  144. {
  145. if (!isset($this->coupon_id)) {
  146. throw new AlertException("coupon_id 未设置", 500);
  147. }
  148. if (!isset($this->coupon)) {
  149. $this->coupon = CouponModel::find($this->coupon_id);
  150. }
  151. return $this->coupon;
  152. }
  153. /**
  154. * 使用优惠券
  155. * @param int $order_id
  156. * @return mixed
  157. * @throws AlertException
  158. * @throws ApiException
  159. */
  160. public function use($order_id = 0)
  161. {
  162. $this->getCoupon();
  163. $settlement_total_amount = $this->getSettlementAmount();
  164. if ($order_id) {
  165. $this->coupon->order_id = $order_id;
  166. $this->coupon->used_at = time();
  167. } else {
  168. $this->coupon->used_at = time();
  169. }
  170. $this->coupon->save();
  171. return $settlement_total_amount;
  172. }
  173. /**
  174. * 优惠券返还
  175. * @return bool
  176. * @throws AlertException
  177. */
  178. public function unUse()
  179. {
  180. $this->getCoupon();
  181. try {
  182. $this->coupon->order_id = 0;
  183. $this->coupon->used_at = 0;
  184. if ($this->coupon->save()) {
  185. return true;
  186. }
  187. } catch (\Exception $e) {
  188. app('sentry')->captureException($e);
  189. }
  190. return false;
  191. }
  192. /**
  193. * 计算优惠券
  194. * @return float|int
  195. * @throws AlertException
  196. * @throws ApiException
  197. */
  198. public function getSettlementAmount()
  199. {
  200. $this->getCoupon();
  201. if (!$this->isExist()) {
  202. throw new ApiException("兑换码不正确哦");
  203. }
  204. if (!$this->coupon->isOwner($this->uid)) {
  205. throw new ApiException("兑换码不正确哦");
  206. }
  207. if ($this->coupon->isUsed()) {
  208. throw new ApiException("卡券已使用");
  209. }
  210. if (!$this->coupon->isOpened()) {
  211. throw new ApiException("卡券未到使用时间");
  212. }
  213. if ($this->coupon->isOverdue()) {
  214. throw new ApiException("卡券过期啦");
  215. }
  216. if (!$this->coupon->isGoodsScope($this->goods_id)) {
  217. throw new ApiException("该商品/业务不可使用此优惠券");
  218. }
  219. if (!$this->coupon->isSatisfyPrice($this->goods_id)) {
  220. throw new AlertException("未满优惠券使用金额");
  221. }
  222. $goods = $this->getGoods();
  223. $this->total_amount = $goods['total_fee'];
  224. switch ($this->coupon->type) {
  225. case "无门槛券":
  226. case "72小时入场券":
  227. case "满减券":
  228. $coupon_amount = ($this->coupon->coupon_amount > $this->total_amount)
  229. ? $this->total_amount
  230. : $this->coupon->coupon_amount;
  231. break;
  232. case "折扣券":
  233. $coupon_amount = floor($goods['total_fee'] * (1 - $this->coupon->discount / 10) / 10) * 10;
  234. break;
  235. default:
  236. throw new AlertException("未定义的卡券");
  237. }
  238. $this->coupon_amount = $coupon_amount;
  239. $this->settlement_total_amount = (int)($this->total_amount - $this->coupon_amount);
  240. return $this->settlement_total_amount;
  241. }
  242. /**
  243. * 获取商品信息
  244. * @return mixed
  245. */
  246. public function getGoods()
  247. {
  248. return Order::GOODS[$this->goods_id];
  249. }
  250. /**
  251. * 是否存在
  252. * @return bool
  253. * @throws AlertException
  254. */
  255. public function isExist()
  256. {
  257. $this->getCoupon();
  258. return $this->getCoupon() ? true : false;
  259. }
  260. /**
  261. * 是否主人
  262. * @return bool
  263. * @throws AlertException
  264. * @throws ApiException
  265. */
  266. public function isOwner()
  267. {
  268. $this->getCoupon();
  269. if (!isset($this->uid)) {
  270. throw new ApiException("uid 未设置", 500);
  271. }
  272. return ($this->coupon->uid == $this->uid) ? true : false;
  273. }
  274. /**
  275. * 是否使用
  276. * @return bool
  277. * @throws AlertException
  278. */
  279. public function isUse()
  280. {
  281. $this->getCoupon();
  282. return ($this->coupon->used_at != 0) ? true : false;
  283. }
  284. /**
  285. * 是否过期
  286. * @return bool
  287. * @throws AlertException
  288. */
  289. public function isOverdue()
  290. {
  291. $this->getCoupon();
  292. return ($this->coupon->overdue_at <= time()) ? true : false;
  293. }
  294. public function isOpen()
  295. {
  296. $this->getCoupon();
  297. return ($this->coupon->open_at <= time()) ? true : false;
  298. }
  299. /**
  300. * 是否符合商品
  301. * @return bool
  302. * @throws AlertException
  303. * @throws ApiException
  304. */
  305. public function isGoods()
  306. {
  307. $this->getCoupon();
  308. if (!isset($this->goods_id)) {
  309. throw new ApiException("goods_id 未设置", 500);
  310. }
  311. $goods_list = $this->getGoodsScope($this->coupon->goods_scope);
  312. return (in_array($this->goods_id, $goods_list)) ? true : false;
  313. }
  314. /**
  315. * 获取此种类的商品
  316. * @param $goods_scope
  317. * @return mixed
  318. */
  319. public function getGoodsScope($goods_scope)
  320. {
  321. return CouponModel::GOODS_TYPE[$goods_scope];
  322. }
  323. /**
  324. * 是否满足满减价格
  325. * @return bool
  326. */
  327. public function isSatisfy()
  328. {
  329. $goods = $this->getGoods();
  330. return ($goods['total_fee'] >= $this->coupon->min_amount) ? true : false;
  331. }
  332. /**
  333. * 生成券
  334. * @return bool
  335. */
  336. public function make()
  337. {
  338. $data = [];
  339. $number = $this->number;
  340. while ($number) {
  341. $attributes = $this->attributes;
  342. $attributes['code'] = $this->getCode();
  343. array_push($data, $attributes);
  344. $number--;
  345. }
  346. return CouponModel::insert($data);
  347. }
  348. /**
  349. * vip券
  350. * @return $this
  351. * @return bool
  352. */
  353. public function makeVip()
  354. {
  355. $this->batch_id = "vip" . date("Ym");
  356. $this->attributes = [
  357. 'uid' => $this->uid,
  358. 'goods_scope' => 'pair',
  359. 'type' => '72小时入场券',
  360. 'name' => '72小时CP直升入场券',
  361. 'describe' => 'SVIP专属,直升全场最高匹配成功率',
  362. 'coupon_amount' => 990,
  363. 'min_amount' => 990,
  364. 'created_at' => time(),
  365. 'updated_at' => time(),
  366. 'get_at' => time(),
  367. 'open_at' => time(),
  368. 'overdue_at' => now()->addWeek(1)->addHour(12)->getTimestamp(),
  369. 'batch_id' => $this->getBatchId(),
  370. ];
  371. return $this->make();
  372. }
  373. /**
  374. * 签到超级会员满减折扣
  375. * @return $this
  376. * @return bool
  377. */
  378. public function makeSignSvip()
  379. {
  380. $this->batch_id = "sign" . date("Ym");
  381. $this->attributes = [
  382. 'uid' => $this->uid,
  383. 'goods_scope' => 'super_vip',
  384. 'type' => '满减券',
  385. 'name' => '分配对象超级会员满减券',
  386. 'describe' => '开通SVIP时使用,可享受相应优惠',
  387. 'coupon_amount' => 900,
  388. 'min_amount' => 1000,
  389. 'created_at' => time(),
  390. 'updated_at' => time(),
  391. 'get_at' => time(),
  392. 'open_at' => time(),
  393. 'overdue_at' => now()->addMonth(1)->getTimestamp(),
  394. 'batch_id' => $this->getBatchId(),
  395. ];
  396. return $this->make();
  397. }
  398. /**
  399. * 签到72小时折扣
  400. * @return $this
  401. * @return bool
  402. */
  403. public function makeSign72Dis()
  404. {
  405. $this->batch_id = "sign" . date("Ym");
  406. $this->attributes = [
  407. 'uid' => $this->uid,
  408. 'goods_scope' => 'pair',
  409. 'type' => '折扣券',
  410. 'name' => '72小时CP报名折扣券',
  411. 'describe' => '非免费入场时,可享受相应折扣',
  412. 'discount' => 6.8,
  413. 'min_amount' => 990,
  414. 'created_at' => time(),
  415. 'updated_at' => time(),
  416. 'get_at' => time(),
  417. 'open_at' => time(),
  418. 'overdue_at' => now()->addMonth(1)->getTimestamp(),
  419. 'batch_id' => $this->getBatchId(),
  420. ];
  421. return $this->make();
  422. }
  423. /**
  424. * 生成兑换码
  425. * @return string
  426. */
  427. private function getCode()
  428. {
  429. return \getChars(8);
  430. }
  431. }