Seckill.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. <?php
  2. namespace addons\shopro\library\activity\provider;
  3. use addons\shopro\service\StockSale;
  4. use addons\shopro\exception\ShoproException;
  5. /**
  6. * 秒杀
  7. */
  8. class Seckill extends Base
  9. {
  10. protected $rules = [
  11. "is_commission" => "require|boolean",
  12. "is_free_shipping" => "require|boolean",
  13. "sales_show_type" => "require",
  14. "limit_num" => "number|egt:0",
  15. "order_auto_close" => "float|egt:0",
  16. ];
  17. protected $message = [
  18. ];
  19. protected $default = [
  20. "is_commission" => 0, // 是否参与分销
  21. "is_free_shipping" => 0, // 是否包邮
  22. "sales_show_type" => "real", // real=真实活动销量|goods=商品总销量(包含虚拟销量)
  23. "limit_num" => 0, // 每人限购数量 0:不限购
  24. "order_auto_close" => 0, // 订单自动关闭时间,如果为 0 将使用系统级订单自动关闭时间
  25. ];
  26. public function check($params, $activity_id = 0)
  27. {
  28. // 数据验证
  29. $params = parent::check($params);
  30. // 验证添加的活动商品是否至少设置了一个活动规格
  31. $this->checkActivitySkuPrice($params['goods_list']);
  32. // 检测活动之间是否存在冲突
  33. $this->checkActivityConflict($params, $params['goods_list'], $activity_id);
  34. return $params;
  35. }
  36. public function save($activity, $params = [])
  37. {
  38. $goodsList = $params['goods_list'];
  39. $this->saveSkuPrice($goodsList, $activity);
  40. }
  41. public function recoverSkuPrices($goods, $activity)
  42. {
  43. $activitySkuPrices = $activity['activity_sku_prices'];
  44. $skuPrices = $goods->sku_prices;
  45. foreach ($skuPrices as $key => &$skuPrice) {
  46. $stock = $skuPrice->stock; // 下面要用
  47. $skuPrice->stock = 0;
  48. $skuPrice->sales = 0;
  49. foreach ($activitySkuPrices as $activitySkuPrice) {
  50. if ($skuPrice['id'] == $activitySkuPrice['goods_sku_price_id']) {
  51. // 采用活动的 规格内容
  52. $skuPrice->old_price = $skuPrice->price; // 保存原始普通商品规格的价格(计算活动的优惠)
  53. $skuPrice->stock = ($activitySkuPrice['stock'] > $stock) ? $stock : $activitySkuPrice['stock']; // 活动库存不能超过商品库存
  54. $skuPrice->sales = $activitySkuPrice['sales'];
  55. $skuPrice->price = $activitySkuPrice['price'];
  56. $skuPrice->status = $activitySkuPrice['status']; // 采用活动的上下架
  57. $skuPrice->min_price = $activitySkuPrice['price']; // 当前活动规格最小价格,这里是秒杀价
  58. $skuPrice->max_price = $activitySkuPrice['price']; // 用作计算活动中最大价格
  59. $skuPrice->zhekou = bcdiv($skuPrice->price,$skuPrice->old_price,2); // 折扣
  60. // 记录相关活动类型
  61. $skuPrice->activity_type = $activity['type'];
  62. $skuPrice->activity_id = $activity['id'];
  63. $skuPrice->activity_endtime = $activity['end_time'];
  64. $skuPrice->activity_seconds = $activity['end_time'] - time();
  65. // 下单的时候需要存活动 的 sku_price_id)
  66. $skuPrice->item_goods_sku_price = $activitySkuPrice;
  67. break;
  68. }
  69. }
  70. }
  71. return $skuPrices;
  72. }
  73. /**
  74. * 这里要使用 shoproException 抛出异常
  75. *
  76. * @param array $buyInfo
  77. * @param array $activity
  78. * @return array
  79. */
  80. public function buyCheck($buyInfo, $activity)
  81. {
  82. // 秒杀
  83. $rules = $activity['rules'];
  84. $currentSkuPrice = $buyInfo['current_sku_price'];
  85. // 当前库存,小于要购买的数量
  86. $need_num = $buyInfo['goods_num'] + ($need_add_num ?? 0);
  87. if ($currentSkuPrice['stock'] < $need_num) {
  88. throw new ShoproException('商品库存不足');
  89. }
  90. $buyInfo['is_commission'] = $rules['is_commission'] ?? 0; // 是否参与分销
  91. return $buyInfo;
  92. }
  93. public function buy($buyInfo, $activity)
  94. {
  95. $user = auth_user();
  96. // 判断 并 增加 redis 销量
  97. $stockSale = new StockSale();
  98. $stockSale->cacheForwardSale($buyInfo);
  99. return $buyInfo;
  100. }
  101. public function buyOk($order, $user)
  102. {
  103. // 不需要处理
  104. }
  105. /**
  106. * 购买失败
  107. *
  108. * @param array $order
  109. * @return void
  110. */
  111. public function buyFail($order, $type)
  112. {
  113. // 判断扣除预销量 (活动信息还在 redis)
  114. $stockSale = new StockSale();
  115. $stockSale->cacheBackSale($order);
  116. }
  117. }