OrderService.php 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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 DB;
  8. use Log;
  9. class OrderService
  10. {
  11. public static $order;
  12. public static $user;
  13. public static $goods;
  14. public static $payment;
  15. public function __construct(Order $order)
  16. {
  17. // 获取需要的信息
  18. self::$order = $order;
  19. self::$user = $order->user;
  20. self::$goods = $order->goods;
  21. self::$payment = $order->payment;
  22. }
  23. // 支付成功后处理
  24. public function receivedPayment(): bool
  25. {
  26. if (self::$payment) {// 是否为余额购买套餐
  27. if (self::$payment->status === 1) {// 已处理
  28. return true;
  29. }
  30. self::$payment->complete();
  31. // 余额充值
  32. if (self::$order->goods_id === 0 || self::$order->goods_id === null) {
  33. return $this->chargeCredit();
  34. }
  35. }
  36. $goods = self::$order->goods;
  37. switch ($goods->type) {// 商品为流量或者套餐
  38. case 1:// 流量包
  39. $this->activatePackage();
  40. break;
  41. case 2:// 套餐
  42. $this->activatePlan();
  43. // if (Order::userActivePlan(self::$user->id)->where('id', '<>', self::$order->id)->exists()) {// 判断套餐是否直接激活
  44. // $this->setPrepaidPlan();
  45. // } else {
  46. // $this->activatePlan();
  47. // }
  48. $this->setCommissionExpense(self::$user); // 返利
  49. break;
  50. default:
  51. Log::warning('【处理订单】出现错误-未知套餐类型');
  52. }
  53. return true;
  54. }
  55. // 余额充值
  56. private function chargeCredit(): bool
  57. {
  58. $credit = self::$user->credit;
  59. $ret = self::$user->updateCredit(self::$order->origin_amount);
  60. // 余额变动记录日志
  61. if ($ret) {
  62. Helpers::addUserCreditLog(self::$order->user_id, self::$order->id, $credit, self::$user->credit, self::$order->amount, '用户通过'.self::$order->pay_way.'充值余额');
  63. }
  64. return $ret;
  65. }
  66. // 激活流量包
  67. private function activatePackage(): bool
  68. {
  69. if (self::$user->incrementData(self::$goods->traffic * MB)) {
  70. return Helpers::addUserTrafficModifyLog(
  71. self::$order->user_id,
  72. self::$order->id,
  73. self::$user->transfer_enable - self::$goods->traffic * MB,
  74. self::$user->transfer_enable,
  75. '['.self::$order->pay_way.']加上用户购买的套餐流量'
  76. );
  77. }
  78. return false;
  79. }
  80. // 设置预支付套餐
  81. private function setPrepaidPlan(): bool
  82. {
  83. self::$order->status = 3; // 3为预支付
  84. $oldData = self::$user->transfer_enable;
  85. // 预支付订单, 刷新账号有效时间用于流量重置判断
  86. return self::$order->save()
  87. && self::$user->update(['expired_at' => date('Y-m-d H:i:s', strtotime(self::$user->expired_at.' +'.self::$goods->days.' days'))]);
  88. }
  89. // 激活套餐
  90. private function activatePlan(): bool
  91. {
  92. Order::whereId(self::$order->id)->update(['status'=>2,'expired_at' => date('Y-m-d H:i:s', strtotime('+'.self::$goods->days.' days'))]);
  93. $oldData = self::$user->transfer_enable;
  94. $expired_at = self::$user->expired_at;
  95. //如果用户到期 就用当前时间增加....
  96. if (self::$user->expired_at >= date('Y-m-d H:i:s')){
  97. $expired_at = date('Y-m-d H:i:s', strtotime("$expired_at +".self::$goods->days.' days'));
  98. }
  99. else {
  100. $expired_at = date('Y-m-d H:i:s', strtotime(' +'.self::$goods->days.' days'));
  101. }
  102. Log::info('购买用户'.self::$user->email.'到期时间'.self::$user->expired_at."修改时间".$expired_at);
  103. foreach (Order::userPrepay(self::$order->user_id)->get() as $paidOrder) {//拿出可能存在的其余套餐, 推算最新的到期时间
  104. //取出对应套餐信息
  105. $expired_at = date('Y-m-d H:i:s', strtotime("$expired_at +".$paidOrder->goods->days.' days'));
  106. }
  107. //账号流量重置日期
  108. $nextResetTime = $expired_at;
  109. if ($nextResetTime >= self::$user->expired_at) {
  110. $nextResetTime = null;
  111. }
  112. //用户的 剩余流量
  113. $totalTransfer = self::$user->transfer_enable;
  114. $usedTransfer = self::$user->u + self::$user->d;
  115. $unusedTraffic = max($totalTransfer - $usedTransfer, 0);
  116. $googstraffic = self::$goods->traffic * MB;
  117. // 套餐流量加上剩余流量
  118. $countt = $googstraffic + $unusedTraffic;
  119. Log::info('用户购买'.self::$user->email.'到期时间'.self::$user->expired_at."流量".flowAutoShow($countt)."剩余流量".flowAutoShow($unusedTraffic));
  120. $updateData = [
  121. 'invite_num' => self::$user->invite_num + (self::$goods->invite_num ?: 0),
  122. 'level' => self::$goods->level,
  123. 'enable' => 1,
  124. 'expired_at' => $expired_at,
  125. 'reset_time' => $nextResetTime,
  126. 'transfer_enable' => $countt,
  127. 'd' => 0,
  128. 'u' => 0
  129. ];
  130. // 无端口用户 添加端口
  131. if (self::$user->port === null || self::$user->port === 0) {
  132. $updateData['port'] = 0;
  133. }
  134. $ret = self::$user->update($updateData);
  135. //$ret = self::$user->update(array_merge($this->resetTimeAndData(), $updateData));
  136. if ($ret) {
  137. return Helpers::addUserTrafficModifyLog(
  138. self::$order->user_id,
  139. self::$order->id,
  140. $oldData,
  141. self::$user->transfer_enable,
  142. '【'.self::$order->pay_way.'】加上用户购买的套餐流量'
  143. );
  144. }
  145. return false;
  146. }
  147. // 计算下次重置与账号过期时间
  148. public function resetTimeAndData($expired_at = null): array
  149. {
  150. $data = ['u' => 0, 'd' => 0];
  151. // 账号有效期
  152. if (! $expired_at) {
  153. $expired_at = date('Y-m-d H:i:s', strtotime('+'.self::$goods->days.' days'));
  154. foreach (Order::userPrepay(self::$order->user_id)->get() as $paidOrder) {//拿出可能存在的其余套餐, 推算最新的到期时间
  155. //取出对应套餐信息
  156. $expired_at = date('Y-m-d H:i:s', strtotime("$expired_at +".$paidOrder->goods->days.' days'));
  157. }
  158. $data['expired_at'] = $expired_at;
  159. }
  160. //账号流量重置日期
  161. $nextResetTime = date('Y-m-d H:i:s', strtotime('+'.self::$goods->period.' days'));
  162. if ($nextResetTime >= $expired_at) {
  163. $nextResetTime = null;
  164. }
  165. return array_merge($data, [
  166. 'transfer_enable' => self::$goods->traffic * MB,
  167. 'reset_time' => $nextResetTime,
  168. ]);
  169. }
  170. // 佣金计算
  171. private function setCommissionExpense(User $user): bool
  172. {
  173. $referralType = sysConfig('referral_type');
  174. if ($referralType && $user->inviter_id) {// 是否需要支付佣金
  175. $inviter = $user->inviter;
  176. // 获取历史返利记录
  177. $referral = ReferralLog::whereInviteeId(self::$order->user_id)->doesntExist();
  178. // 无记录 / 首次返利
  179. if ($referral && sysConfig('is_invite_register')) {
  180. // 邀请注册功能开启时,返还邀请者邀请名额
  181. $inviter->update(['invite_num' => $inviter->invite_num + 1]);
  182. }
  183. // 按照返利模式进行返利判断
  184. if ($referralType == 2 || $referral) {
  185. // 可以考虑将此操作移至数据库事务中,以便在出错时回滚
  186. return $this->addReferralLog(
  187. $user->id,
  188. $inviter->id,
  189. self::$order->id,
  190. self::$order->amount,
  191. self::$order->amount * sysConfig('referral_percent')
  192. );
  193. }
  194. }
  195. return true;
  196. }
  197. /**
  198. * 添加返利日志.
  199. *
  200. * @param int $inviteeId 用户ID
  201. * @param int $inviterId 返利对象ID
  202. * @param int $oid 订单ID
  203. * @param int $amount 发生金额
  204. * @param int $commission 返利金额
  205. *
  206. * @return bool
  207. */
  208. private function addReferralLog(int $inviteeId, int $inviterId, int $oid, int $amount, int $commission): bool
  209. {
  210. // $log = new ReferralLog();
  211. // $log->invitee_id = $inviteeId;
  212. // $log->inviter_id = $inviterId;
  213. // $log->order_id = $oid;
  214. // $log->amount = $amount;
  215. // $log->commission = $commission;
  216. //
  217. // return $log->save();
  218. try {
  219. $log = new ReferralLog();
  220. $log->invitee_id = $inviteeId;
  221. $log->inviter_id = $inviterId;
  222. $log->order_id = $oid;
  223. $log->amount = $amount;
  224. $log->commission = $commission;
  225. return $log->save();
  226. } catch (\Exception $e) {
  227. // 记录错误日志,包括异常信息和相关数据
  228. Log::error("Failed to add referral log", [
  229. 'exception' => $e->getMessage(),
  230. 'userid' => $inviteeId,
  231. 'inviterId' => $inviterId,
  232. 'orderId' => $oid,
  233. 'amount' => $amount,
  234. 'commission' => $commission
  235. ]);
  236. return false;
  237. }
  238. }
  239. // 激活预支付套餐
  240. public function activatePrepaidPlan(): bool
  241. {
  242. self::$order->update([
  243. 'expired_at' => date('Y-m-d H:i:s', strtotime('+'.self::$goods->days.' days')),
  244. 'status' => 2,
  245. ]);
  246. return $this->activatePlan();
  247. }
  248. }