OrderService.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. <?php
  2. namespace App\Services;
  3. use App\Components\Helpers;
  4. use App\Models\Order;
  5. use App\Models\ReferralLog;
  6. use App\Models\User;
  7. use Log;
  8. class OrderService {
  9. public static $order;
  10. public static $user;
  11. public static $goods;
  12. public static $payment;
  13. public function __construct(Order $order) {
  14. // 获取需要的信息
  15. self::$order = $order;
  16. self::$user = $order->user;
  17. self::$goods = $order->goods;
  18. self::$payment = $order->payment;
  19. }
  20. // 支付成功后处理
  21. public function receivedPayment(): bool {
  22. if(self::$payment){// 是否为余额购买套餐
  23. if(self::$payment->status === 1){// 已处理
  24. return true;
  25. }
  26. self::$payment->update(['status' => 1]);
  27. // 余额充值
  28. if(self::$order->goods_id === 0 || self::$order->goods_id === null){
  29. return $this->chargeCredit();
  30. }
  31. }
  32. $goods = self::$order->goods;
  33. switch($goods->type){// 商品为流量或者套餐
  34. case 1:// 流量包
  35. $this->activatePackage();
  36. break;
  37. case 2:// 套餐
  38. if(Order::userActivePlan(self::$user->id)->where('id', '<>', self::$order->id)->exists()){// 判断套餐是否直接激活
  39. $this->setPrepaidPlan();
  40. }else{
  41. $this->activatePlan();
  42. }
  43. $this->setCommissionExpense(self::$user);// 返利
  44. break;
  45. default:
  46. Log::error('【处理订单】出现错误-未知套餐类型');
  47. }
  48. return true;
  49. }
  50. // 余额充值
  51. private function chargeCredit(): bool {
  52. $credit = self::$user->credit;
  53. $ret = (new UserService(self::$user))->updateCredit(self::$order->origin_amount);
  54. // 余额变动记录日志
  55. if($ret){
  56. Helpers::addUserCreditLog(self::$order->user_id, self::$order->id, $credit, self::$user->credit,
  57. self::$order->amount, '用户通过'.self::$order->pay_way.'充值余额');
  58. }
  59. return $ret;
  60. }
  61. // 激活流量包
  62. private function activatePackage(): bool {
  63. $ret = (new UserService(self::$user))->incrementData(self::$goods->traffic * MB);
  64. if($ret){
  65. return Helpers::addUserTrafficModifyLog(self::$order->user_id, self::$order->id,
  66. self::$user->transfer_enable - self::$goods->traffic * MB, self::$user->transfer_enable,
  67. '['.self::$order->pay_way.']加上用户购买的套餐流量');
  68. }
  69. return false;
  70. }
  71. // 设置预支付套餐
  72. private function setPrepaidPlan(): bool {
  73. self::$order->status = 3;// 3为预支付
  74. // 预支付订单, 刷新账号有效时间用于流量重置判断
  75. return self::$order->save()
  76. && self::$user->update([
  77. 'expired_at' => date('Y-m-d', strtotime(self::$user->expired_at." +".self::$goods->days." days"))
  78. ]);
  79. }
  80. // 激活套餐
  81. private function activatePlan(): bool {
  82. Order::whereId(self::$order->id)->update([
  83. 'expired_at' => date('Y-m-d H:i:s', strtotime("+".self::$goods->days." days"))
  84. ]);
  85. $oldData = self::$user->transfer_enable;
  86. $ret = self::$user->update(array_merge($this->resetTimeAndData(), [
  87. 'invite_num' => self::$user->invite_num + (self::$goods->invite_num?: 0),
  88. 'level' => self::$goods->level,
  89. 'enable' => 1
  90. ]));
  91. if($ret){
  92. return Helpers::addUserTrafficModifyLog(self::$order->user_id, self::$order->id, $oldData,
  93. self::$user->transfer_enable, '【'.self::$order->pay_way.'】加上用户购买的套餐流量');
  94. }
  95. return false;
  96. }
  97. // 计算下次重置与账号过期时间
  98. public function resetTimeAndData($expired_at = null): array {
  99. $data = ['u' => 0, 'd' => 0];
  100. // 账号有效期
  101. if(!$expired_at){
  102. $expired_at = date('Y-m-d', strtotime("+".self::$goods->days." days"));
  103. foreach(Order::userPrepay(self::$order->user_id)->get() as $paidOrder){//拿出可能存在的其余套餐, 推算最新的到期时间
  104. //取出对应套餐信息
  105. $expired_at = date('Y-m-d', strtotime("$expired_at +".$paidOrder->goods->days." days"));
  106. }
  107. $data['expired_at'] = $expired_at;
  108. }
  109. //账号流量重置日期
  110. $nextResetTime = date('Y-m-d', strtotime("+".self::$goods->period." days"));
  111. if($nextResetTime >= $expired_at){
  112. $nextResetTime = null;
  113. }
  114. return array_merge($data, [
  115. 'transfer_enable' => self::$goods->traffic * MB,
  116. 'reset_time' => $nextResetTime
  117. ]);
  118. }
  119. // 佣金计算
  120. private function setCommissionExpense(User $user): bool {
  121. $referralType = sysConfig('referral_type');
  122. if($referralType && $user->inviter_id){// 是否需要支付佣金
  123. $inviter = $user->inviter;
  124. // 获取历史返利记录
  125. $referral = ReferralLog::whereInviteeId(self::$order->user_id)->doesntExist();
  126. // 无记录 / 首次返利
  127. if($referral && sysConfig('is_invite_register')){
  128. // 邀请注册功能开启时,返还邀请者邀请名额
  129. $inviter->update(['invite_num' => $inviter->invite_num + 1]);
  130. }
  131. // 按照返利模式进行返利判断
  132. if($referralType == 2 || $referral){
  133. return $this->addReferralLog($user->id, $inviter->id, self::$order->id, self::$order->amount,
  134. self::$order->amount * sysConfig('referral_percent'));
  135. }
  136. }
  137. return true;
  138. }
  139. /**
  140. * 添加返利日志
  141. *
  142. * @param int $inviteeId 用户ID
  143. * @param int $inviterId 返利对象ID
  144. * @param int $oid 订单ID
  145. * @param int $amount 发生金额
  146. * @param int $commission 返利金额
  147. *
  148. * @return bool
  149. */
  150. private function addReferralLog($inviteeId, $inviterId, $oid, $amount, $commission): bool {
  151. $log = new ReferralLog();
  152. $log->invitee_id = $inviteeId;
  153. $log->inviter_id = $inviterId;
  154. $log->order_id = $oid;
  155. $log->amount = $amount;
  156. $log->commission = $commission;
  157. $log->status = 0;
  158. return $log->save();
  159. }
  160. // 激活预支付套餐
  161. public function activatePrepaidPlan(): bool {
  162. self::$order->update([
  163. 'expired_at' => date("Y-m-d H:i:s", strtotime("+".self::$goods->days." days")),
  164. 'status' => 2
  165. ]);
  166. return $this->activatePlan();
  167. }
  168. }