OrderService.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <?php
  2. namespace App\Services;
  3. use App\Models\Goods;
  4. use App\Models\Order;
  5. use App\Models\Payment;
  6. use App\Models\ReferralLog;
  7. use App\Models\User;
  8. use App\Utils\Helpers;
  9. use Log;
  10. class OrderService
  11. {
  12. public static User $user;
  13. public static ?Goods $goods;
  14. public static ?Payment $payment;
  15. public function __construct(private readonly Order $order)
  16. { // 获取需要的信息
  17. self::$user = $order->user;
  18. self::$goods = $order->goods;
  19. self::$payment = $order->payment;
  20. }
  21. public function receivedPayment(): bool
  22. { // 支付成功后处理
  23. $payment = self::$payment;
  24. if ($payment && $payment->status !== 1) {// 是否为余额购买套餐
  25. $payment->complete();
  26. }
  27. $goods = self::$goods;
  28. if ($goods === null) {
  29. $ret = $this->chargeCredit();
  30. } else {
  31. switch ($goods->type) {// 商品为流量或者套餐
  32. case 1: // 流量包
  33. $ret = $this->activatePackage();
  34. break;
  35. case 2: // 套餐
  36. if (Order::userActivePlan(self::$user->id)->where('id', '<>', $this->order->id)->exists()) {// 判断套餐是否直接激活
  37. $ret = $this->order->prepay();
  38. } else {
  39. $ret = $this->activatePlan();
  40. }
  41. $this->setCommissionExpense(self::$user); // 返利
  42. break;
  43. default:
  44. Log::emergency('【处理订单】出现错误-未知套餐类型');
  45. }
  46. }
  47. return $ret ?? true;
  48. }
  49. private function chargeCredit(): bool
  50. { // 余额充值
  51. $credit = self::$user->credit;
  52. $ret = self::$user->updateCredit($this->order->origin_amount);
  53. // 余额变动记录日志
  54. if ($ret) {
  55. Helpers::addUserCreditLog($this->order->user_id, $this->order->id, $credit, self::$user->credit, $this->order->amount, 'The user topped up the balance.');
  56. }
  57. return $ret;
  58. }
  59. private function activatePackage(): bool
  60. { // 激活流量包
  61. if (self::$user->incrementData(self::$goods->traffic * MiB)) {
  62. return Helpers::addUserTrafficModifyLog($this->order->user_id, self::$user->transfer_enable - self::$goods->traffic * MiB, self::$user->transfer_enable, trans("[:payment] plus the user's purchased data plan.", ['payment' => $this->order->pay_way]));
  63. }
  64. return false;
  65. }
  66. public function activatePlan(): bool
  67. { // 激活套餐
  68. $this->order->refresh()->update(['expired_at' => date('Y-m-d H:i:s', strtotime(self::$goods->days.' days'))]);
  69. $oldData = self::$user->transfer_enable;
  70. $updateData = [
  71. 'invite_num' => self::$user->invite_num + (self::$goods->invite_num ?: 0),
  72. 'level' => self::$goods->level,
  73. 'speed_limit' => self::$goods->speed_limit,
  74. 'enable' => 1,
  75. ...$this->resetTimeAndData(),
  76. ];
  77. // 无端口用户 添加端口
  78. if (empty(self::$user->port)) {
  79. $updateData['port'] = Helpers::getPort();
  80. }
  81. if (self::$user->update($updateData)) {
  82. return Helpers::addUserTrafficModifyLog($this->order->user_id, $oldData, self::$user->transfer_enable, trans("[:payment] plus the user's purchased data plan.", ['payment' => $this->order->pay_way]), $this->order->id);
  83. }
  84. return false;
  85. }
  86. public function resetTimeAndData(?string $expired_at = null): array
  87. { // 计算下次重置与账号过期时间
  88. if (! $expired_at) { // 账号有效期
  89. $expired_at = $this->getFinallyExpiredTime();
  90. }
  91. // 账号流量重置日期
  92. $nextResetTime = now()->addDays(self::$goods->period)->toDateString();
  93. if ($nextResetTime >= $expired_at) {
  94. $nextResetTime = null;
  95. }
  96. return [
  97. 'u' => 0,
  98. 'd' => 0,
  99. 'transfer_enable' => self::$goods->traffic * MiB,
  100. 'expired_at' => $expired_at,
  101. 'reset_time' => $nextResetTime,
  102. ];
  103. }
  104. private function getFinallyExpiredTime(): string
  105. { // 推算最新的到期时间
  106. $orders = self::$user->orders()->whereIn('status', [2, 3])->whereIsExpire(0)->isPlan()->get();
  107. $current = $orders->where('status', '==', 2)->first();
  108. return ($current->expired_at ?? now())->addDays($orders->except($current->id ?? 0)->sum('goods.days'))->toDateString();
  109. }
  110. private function setCommissionExpense(User $user): void
  111. { // 佣金计算
  112. $referralType = sysConfig('referral_reward_type');
  113. if ($referralType && $user->inviter_id) {// 是否需要支付佣金
  114. $inviter = $user->inviter;
  115. // 获取历史返利记录
  116. $referral = ReferralLog::whereInviteeId($user->id)->doesntExist();
  117. // 无记录 / 首次返利
  118. if ($referral && sysConfig('is_invite_register')) {
  119. // 邀请注册功能开启时,返还邀请者邀请名额
  120. $inviter->increment('invite_num');
  121. }
  122. // 按照返利模式进行返利判断
  123. if ($referralType === '2' || $referral) {
  124. $inviter->commissionLogs()
  125. ->create([
  126. 'invitee_id' => $user->id,
  127. 'order_id' => $this->order->id,
  128. 'amount' => $this->order->amount,
  129. 'commission' => $this->order->amount * sysConfig('referral_percent'),
  130. ]);
  131. }
  132. }
  133. }
  134. public function refreshAccountExpiration(): bool
  135. { // 刷新账号有效时间
  136. $data = ['expired_at' => $this->getFinallyExpiredTime()];
  137. if ($data['expired_at'] < now()->toDateString()) {
  138. $data += [
  139. 'u' => 0,
  140. 'd' => 0,
  141. 'transfer_enable' => 0,
  142. 'enable' => 0,
  143. 'level' => 0,
  144. 'reset_time' => null,
  145. 'ban_time' => null,
  146. ];
  147. }
  148. return self::$user->update($data);
  149. }
  150. public function activatePrepaidPlan(): bool
  151. { // 激活预支付套餐
  152. $this->order->complete();
  153. return $this->activatePlan();
  154. }
  155. }