OrderService.php 12 KB

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