OrderService.php 8.2 KB

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