Order.php 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. <?php
  2. namespace addons\unishop\behavior;
  3. use addons\unishop\extend\Ali;
  4. use addons\unishop\extend\Hashids;
  5. use addons\unishop\extend\Wechat;
  6. use addons\unishop\model\Address;
  7. use addons\unishop\model\Config;
  8. use addons\unishop\model\DeliveryRule as DeliveryRuleModel;
  9. use addons\unishop\model\OrderProduct;
  10. use addons\unishop\model\Product;
  11. use app\admin\model\unishop\Coupon;
  12. use think\Db;
  13. use think\Exception;
  14. /**
  15. * 订单相关行为
  16. * Class Order
  17. * @package addons\unishop\behavior
  18. */
  19. class Order
  20. {
  21. /**
  22. * 创建订单之后
  23. * 行为一:根据订单减少商品库存 增加"已下单未支付数量"
  24. * 行为二:如果选了购物车的就删除购物车的信息
  25. * 行为三:如果选了优惠券的就修改掉购物券的状态
  26. * @param array $params 商品属性
  27. * @param array $extra [specNumber] => ['spec1' => 'number1','spec2' => 'number2']
  28. */
  29. public function createOrderAfter(&$params, $extra)
  30. {
  31. // 行为一
  32. $key = 0;
  33. $productExtend = new \addons\unishop\extend\Product;
  34. $prefix = \think\Config::get('database.prefix');
  35. if (1 == 1) {
  36. // 悲观锁
  37. foreach ($extra['specNumber'] as $spec => $number) {
  38. $result = 0;
  39. if (is_numeric($spec) && $params[$key]['use_spec'] == Product::SPEC_OFF) {
  40. $result = Db::execute('UPDATE ' . $prefix . "unishop_product SET no_buy_yet = no_buy_yet+{$number}, real_sales = real_sales+{$number}, stock = stock-{$number} WHERE id = {$params[$key]['id']}");
  41. } else if ($params[$key]['use_spec'] == Product::SPEC_ON) {
  42. $result = 1;
  43. }
  44. if ($result == 0) { // 锁生效
  45. throw new Exception('下单失败,请重试');
  46. }
  47. $key++;
  48. }
  49. }
  50. // More ...
  51. }
  52. /**
  53. * 检查是否符合创建订单的条件
  54. * 条件1:商品是否存在
  55. * 条件2:商品库存情况
  56. * 条件3:收货地址是否在范围内
  57. * 条件4:是否使用优惠券,优惠券能否可用
  58. * @param array $params
  59. * @param array $extra
  60. * @throws Exception
  61. * @throws \think\exception\DbException
  62. */
  63. public function createOrderBefore(&$params, $extra)
  64. {
  65. $specs = [''];
  66. // $numbers = [$extra['number']];
  67. $numbers = [1]; //强制一个
  68. $productIds = [$extra['product_id']];
  69. if (count($specs) !== count($numbers) || count($specs) !== count($productIds)) {
  70. throw new Exception(__('Parameter error'));
  71. }
  72. // 订单价格
  73. $orderPrice = 0;
  74. // 条件一
  75. $products = [];
  76. foreach ($productIds as $key => &$productId) {
  77. $products[$key] = Db::name('unishop_product')
  78. ->where(['id' => $productId, 'switch' => Product::SWITCH_ON])
  79. ->lock(Config::isPessimism()) // Todo 是否使用悲观锁
  80. ->find();
  81. if (!$products[$key]) {
  82. throw new Exception(__('There are not exist or Offline'));
  83. }
  84. }
  85. if (count($products) == 0 || count($productIds) != count($products)) {
  86. throw new Exception(__('There are offline product'));
  87. }
  88. // 从购物车下单多个商品时,有同一个商品的不同规格导致减库存问题
  89. /*if (count($productIds) > 0) {
  90. $reduceStock = [];
  91. foreach ($products as $key => $value) {
  92. if (!isset($reduceStock[$value['id']])) {
  93. $reduceStock[$value['id']] = $numbers[$key];
  94. } else {
  95. $products[$key]['stock'] -= $reduceStock[$value['id']];
  96. $reduceStock[$value['id']] += $numbers[$key];
  97. }
  98. }
  99. }*/
  100. // 条件二
  101. foreach ($products as $key => $product) {
  102. $productInfo = (new \addons\unishop\extend\Product())->getBaseData($product, $specs[$key] ? $specs[$key] : '');
  103. if ($productInfo['stock'] < $numbers[$key]) {
  104. throw new Exception(__('Insufficient inventory,%s pieces left', $productInfo['stock']));
  105. }
  106. $orderPrice = bcadd($orderPrice, bcmul($productInfo['sales_price'], $numbers[$key], 2), 2);
  107. $baseProductInfo[] = $productInfo;
  108. }
  109. // 条件三
  110. /*$delivery = (new DeliveryRuleModel())->cityInScopeOfDelivery($extra['city_id'], $extra['delivery_id']);
  111. if (!$delivery) {
  112. throw new Exception(__('Your receiving address is not within the scope of delivery'));
  113. } else {
  114. if ($delivery['min'] > array_sum($numbers)) {
  115. throw new Exception(__('You must purchase at least %s item to use this shipping method', $delivery['min']));
  116. }
  117. }*/
  118. $delivery = [];
  119. /*$address = (new Address)->where(['id' => $extra['address_id'], 'user_id' => $extra['userId']])->find();
  120. if (!$address) {
  121. throw new Exception(__('Address not exist'));
  122. }*/
  123. $address = [];
  124. // 条件四
  125. /*if ($extra['coupon_id']) {
  126. // $coupon = Coupon::get($extra['coupon_id']);
  127. $coupon = Db::name('unishop_coupon_user')->alias('cu')
  128. ->field(['cu.id as cu_id','c.id','c.title','c.least','c.value','c.starttime','c.endtime'])
  129. ->join('unishop_coupon c','cu.coupon_id = c.id','LEFT')
  130. ->where('cu.user_id',$extra['userId'])
  131. ->where('cu.status',0)
  132. ->where('c.deletetime',NULL)
  133. ->where('c.switch',Coupon::SWITCH_ON)
  134. // ->where('c.starttime','<',time())
  135. // ->where('c.endtime','>',time())
  136. ->where('cu.id',$extra['coupon_id'])
  137. ->find();
  138. if(!empty($coupon)){
  139. if ($coupon['starttime'] > time() || $coupon['endtime'] < time()) {
  140. throw new Exception('此优惠券不可用');
  141. }
  142. // 至少消费多少钱
  143. if ($coupon['least'] > $orderPrice) {
  144. throw new Exception('选中的优惠券不满足使用条件');
  145. }
  146. }else{
  147. $coupon = [];
  148. }
  149. } else {
  150. $coupon = [];
  151. }*/
  152. $coupon = [];
  153. $params = [$products, $delivery, $coupon, $baseProductInfo, $address, $orderPrice, $specs, $numbers];
  154. }
  155. /**
  156. * 支付成功
  157. * 行为一:更改订单的支付状态,更新支付时间。
  158. * 行为二:减少商品的已下单但未支付的数量
  159. * @param $params
  160. * @param $extra
  161. * @throws \think\db\exception\DataNotFoundException
  162. * @throws \think\db\exception\ModelNotFoundException
  163. * @throws \think\exception\DbException
  164. */
  165. public function paidSuccess(&$params, $extra)
  166. {
  167. $order = &$params;
  168. $order->have_paid = time();// 更新支付时间为当前时间
  169. $order->pay_type = $extra['pay_type'];
  170. $order->save();
  171. $orderProductModel = new OrderProduct();
  172. $orderProducts = $orderProductModel
  173. ->with('product')
  174. ->where(['order_id' => $order->id])
  175. ->select();
  176. foreach ($orderProducts as $product) {
  177. if (isset($product->product)) {
  178. $product->product->no_buy_yet -= $product->number;
  179. $product->product->save();
  180. }
  181. }
  182. // More ...
  183. }
  184. /**
  185. * 支付失败
  186. * @param $params
  187. */
  188. public function paidFail(&$params)
  189. {
  190. $order = &$params;
  191. $order->have_paid = \addons\unishop\model\Order::PAID_NO;
  192. $order->save();
  193. // More ...
  194. }
  195. /**
  196. * 订单退款
  197. * 行为一:退款
  198. * @param array $params 订单数据
  199. */
  200. public function orderRefund(&$params)
  201. {
  202. $order = &$params;
  203. // 行为一
  204. switch ($order['pay_type']) {
  205. case \addons\unishop\model\Order::PAY_WXPAY:
  206. $app = Wechat::initEasyWechat('payment');
  207. $result = $app->refund->byOutTradeNumber($params['out_trade_no'], $params['out_trade_no'], bcmul($params['total_price'], 100), bcmul($params['refund']['amount'], 100), [
  208. // 可在此处传入其他参数,详细参数见微信支付文档
  209. 'refund_desc' => $params['refund']['reason_type'],
  210. ]);
  211. break;
  212. case \addons\unishop\model\Order::PAY_ALIPAY:
  213. $alipay = Ali::initAliPay();
  214. $order = [
  215. 'out_trade_no' => $params['out_trade_no'],
  216. 'refund_amount' => $params['total_price'],
  217. ];
  218. $result = $alipay->refund($order);
  219. break;
  220. }
  221. // More ...
  222. }
  223. }