Browse Source

Merge branch 'phoenix' into master

master
weigang 5 years ago
parent
commit
dfa4cd93b6
  1. 14
      app/Constants/v3/ErrorCode.php
  2. 5
      app/Constants/v3/LogLabel.php
  3. 4
      app/Controller/v3/NotifyController.php
  4. 5
      app/Controller/v3/OrderOnlineController.php
  5. 15
      app/Controller/v3/WithdrawController.php
  6. 25
      app/Crontab/AutoCancelOrder.php
  7. 11
      app/JsonRpc/OrdersService.php
  8. 16
      app/Middleware/Auth/ApiMiddleware.php
  9. 8
      app/Model/v3/Coupon.php
  10. 13
      app/Model/v3/Feprint.php
  11. 18
      app/Model/v3/GoodsActivityBanner.php
  12. 11
      app/Model/v3/GoodsBanner.php
  13. 2
      app/Model/v3/GoodsCategory.php
  14. 9
      app/Model/v3/Market.php
  15. 17
      app/Model/v3/ServicePersonnel.php
  16. 27
      app/Service/v3/Implementations/CouponRecService.php
  17. 5
      app/Service/v3/Implementations/DistributionPriceService.php
  18. 5
      app/Service/v3/Implementations/FeiePrintService.php
  19. 18
      app/Service/v3/Implementations/GoodsActivityService.php
  20. 7
      app/Service/v3/Implementations/GoodsService.php
  21. 15
      app/Service/v3/Implementations/LocationService.php
  22. 25
      app/Service/v3/Implementations/OrderListService.php
  23. 112
      app/Service/v3/Implementations/OrderOnlineService.php
  24. 2
      app/Service/v3/Implementations/PaymentService.php
  25. 5
      app/Service/v3/Implementations/SearchService.php
  26. 3
      app/Service/v3/Implementations/ServiceEvaluateService.php
  27. 14
      app/Service/v3/Implementations/ShopCartService.php
  28. 21
      app/Service/v3/Implementations/ShopCartUpdateService.php
  29. 8
      app/Service/v3/Implementations/TabsService.php
  30. 11
      app/Service/v3/Implementations/UserAddressService.php
  31. 2
      app/Service/v3/Interfaces/GoodsActivityServiceInterface.php
  32. 6
      app/Service/v3/Interfaces/OrderOnlineServiceInterface.php
  33. 3
      composer.json
  34. 61
      composer.lock
  35. 5
      config/autoload/crontab.php
  36. 1
      config/autoload/dependencies.php
  37. 1
      config/autoload/processes.php

14
app/Constants/v3/ErrorCode.php

@ -25,7 +25,7 @@ class ErrorCode extends AbstractConstants
/**
* 线上下单失败
* @Message("线上下单失败")
* @Message("下单失败")
*/
const ORDER_ONLINE_FAIL = 601;
@ -233,8 +233,8 @@ class ErrorCode extends AbstractConstants
/* 商品相关 1101-1150 */
/************************************/
/**
* 已卖光
* @Message("该商品已卖光")
* 库存不足
* @Message("库存不足")
*/
const GOODS_INVENTORY_ERROR = 1101;
@ -252,7 +252,7 @@ class ErrorCode extends AbstractConstants
/**
* 已下架
* @Message("商品可能已下架")
* @Message("商品不存在")
*/
const GOODS_NOT_EXISTS = 1104;
@ -262,7 +262,7 @@ class ErrorCode extends AbstractConstants
/**
* 当前特价商品已被购买过
* @Message("活动商品您已买过")
* @Message("活动商品您已买过")
*/
const GOODS_ACTIVITY_BUY = 1151;
@ -274,7 +274,7 @@ class ErrorCode extends AbstractConstants
/**
* 已卖光
* @Message("商品已卖光")
* @Message("商品已卖光")
*/
const GOODS_ACTIVITY_INVENTORY_ERROR = 1153;
@ -286,7 +286,7 @@ class ErrorCode extends AbstractConstants
/**
* 商品超过限购数量
* @Message("活动商品超过限购数量")
* @Message("同类活动商品超过限购数量")
*/
const GOODS_ACTIVITY_RESTRICT_LIMIT = 1155;

5
app/Constants/v3/LogLabel.php

@ -102,4 +102,9 @@ class LogLabel extends AbstractConstants
*/
const PAY_TO_WX_FAIL_LOG = 'pay_to_wx_fail_log';
/**
* @Message("自动取消订单失败")
*/
const ORDER_AUTO_CANCEL_FAIL_LOG = 'order_auto_cancel_fail_log';
}

4
app/Controller/v3/NotifyController.php

@ -322,8 +322,8 @@ class NotifyController extends BaseController
// 查询订单
$orderMain = OrderMain::query()
->whereIn('state', [OrderState::PAID, OrderState::DELIVERY, OrderState::COMPLETED, OrderState::EVALUATED, OrderState::REFUNDING])
->where(['global_order_id' => $reqInfo['out_trade_no'], 'pay_type' => Payment::WECHAT, 'refund_time' => 0])
->whereNotIn('state', [OrderState::UNPAID])
->where(['global_order_id' => $reqInfo['out_trade_no'], 'pay_type' => Payment::WECHAT])
->first();
// 订单不存在

5
app/Controller/v3/OrderOnlineController.php

@ -129,7 +129,10 @@ class OrderOnlineController extends BaseController
$res['store_list'] = $this->shopCartService->getGoodsByShopcartId($shopcartIds);
//获取用户优惠券
$coupons = $this->couponRecService->allForOnlineOrderAvailable($userId, $marketId);
$res['coupon'] = [];
$res['coupon'] = [
'available' => [],
'not_available' => [],
];
foreach ($coupons as $key => &$item) {
foreach ($item as $k => &$rec) {
for ($i=0; $i<$rec->number_remain; $i++) {

15
app/Controller/v3/WithdrawController.php

@ -82,15 +82,16 @@ class WithdrawController extends BaseController
);
$data['notice'] = [
[
'title' => '用户须知',
'content' => '<p>请仔细填写相关信息,如果由于您填写的信息有误导致资金流失,平台概不负责。</p><p>注意:因微信限制当前用户账户余额满<span style="color:red;">1</span>元后才可提现</p>'
],
// [
// 'title' => '用户须知',
// 'content' => '<p>请仔细填写相关信息,如果由于您填写的信息有误导致资金流失,平台概不负责。</p><p>注意:因微信限制当前用户账户余额满<span style="color:red;">1</span>元后才可提现</p>'
// ],
[
'title' => '提现须知',
'content' => '<p>一次提现金额最低为<span style="color:red;">1</span>元</p>'
.'<p>一次提现金额最高为<span style="color:red;">5000</span>元</p>'
.'<p>每天可提现<span style="color:red;">10</span>次</p>'
'content' => '<p>1、提金额最低为<span style="color:red;">1</span>元,最高为<span style="color:red;">5000</span>元,一天最多可提现<span style="color:red;">10</span>次。</p>'
.'<p>2、提现到账时间为一个工作日内。</p>'
.'<p>3、提现成功后,提现款会自动转入您当前登录的微信账号</p>'
.'<p>4、如果您在提现方面遇到问题,请致电联系我们的服务站。</p>'
],
];

25
app/Crontab/AutoCancelOrder.php

@ -0,0 +1,25 @@
<?php
namespace App\Crontab;
use App\Service\v3\Interfaces\OrderOnlineServiceInterface;
use Hyperf\Crontab\Annotation\Crontab;
use Hyperf\Di\Annotation\Inject;
/**
* @Crontab(name="autocancelorder", rule="*\/1 * * * *", callback="execute", memo="自定取消15分钟过期订单")
*/
class AutoCancelOrder
{
/**
* @Inject
* @var OrderOnlineServiceInterface
*/
protected $orderOnlineService;
public function execute()
{
$this->orderOnlineService->autoCancel();
}
}

11
app/JsonRpc/OrdersService.php

@ -129,7 +129,7 @@ class OrdersService implements OrdersServiceInterface
* @param $note
* @return array
*/
public function onlineSingleRefund($user_id, $note, $global_order_id, $order_child_id=null, $order_goods_id=null)
public function onlineSingleRefund($user_id, $note, $global_order_id, $order_child_id='', $order_goods_id='')
{
Db::beginTransaction();
@ -154,7 +154,7 @@ class OrdersService implements OrdersServiceInterface
// 主订单
$orderMain = OrderMain::query()
->where(['global_order_id' => $global_order_id, 'user_id' => $user_id])
->whereIn('state', OrderState::CAN_REFUND_DIRECT)
->whereIn('state', array_merge(OrderState::CAN_REFUND_DIRECT, [OrderState::REFUNDED]))
->first();
if (is_null($orderMain)) {
@ -168,7 +168,7 @@ class OrdersService implements OrdersServiceInterface
// 子订单
$orderChild = null;
if ($order_child_id) {
$orderChild = Order::query()->with('store:user_id')->where(['order_main_id' => $orderMain->global_order_id, 'id' => $order_child_id])->first();
$orderChild = Order::query()->with('store')->where(['order_main_id' => $orderMain->global_order_id, 'id' => $order_child_id])->first();
}
// 订单商品
@ -222,13 +222,14 @@ class OrdersService implements OrdersServiceInterface
]);
throw new ErrorCodeException(ErrorCode::ORDER_REFUND_FAIL);
}
// 开始退款
$config = config('wxpay');
$app = Factory::payment($config);
$app['guzzle_handler'] = CoroutineHandler::class;
$result = $app->refund->byOutTradeNumber(
$orderMain->global_order_id,
$orderMain->global_order_id,
$orderMain->global_order_id.$order_child_id.$order_goods_id,
bcmul($orderMain->money, 100, 0),
bcmul($refundAmount, 100, 0),
[
@ -302,7 +303,7 @@ class OrdersService implements OrdersServiceInterface
$this->financialRecordService->storeRefundDirect($order->store->user_id, $order->id, $refundStoreAmount);
}
} elseif ($refundType == 'sub') { # 退子订单或者退单品的话,商户只有一个
} elseif ($refundType == 'sub'||$refundType == 'goods') { # 退子订单或者退单品的话,商户只有一个
$this->financialRecordService->storeRefundDirect($orderChild->store->user_id, $orderChild->id, $refundAmount);
}

16
app/Middleware/Auth/ApiMiddleware.php

@ -9,6 +9,7 @@ use App\TaskWorker\SSDBTask;
use Hashids\Hashids;
use Hyperf\HttpServer\Contract\RequestInterface as HttpRequest;
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
use Hyperf\HttpServer\Router\Router;
use Hyperf\Utils\ApplicationContext;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
@ -42,6 +43,21 @@ class ApiMiddleware implements MiddlewareInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
// 拦截v1路由
// $routePath = $this->request->getPathInfo();
// $routePath = explode('/', $routePath);
// if ($routePath[1] == 'v1') {
// $content = [
// "status" => 'ok',
// "code" => 99999,
// "result" => [],
// "message" => '服务已停止升级,稍后请升级更新小程序(如不能自动更新,请删除小程序后重新进入小程序)'
// ];
//
// return $this->response->json($content);
// }
// 签名校验
# 获取参数

8
app/Model/v3/Coupon.php

@ -13,7 +13,8 @@ class Coupon extends Model
protected $appends = [
'full_amount_text',
'discounts_text'
'discounts_text',
'time_text'
];
protected $casts = [
@ -35,4 +36,9 @@ class Coupon extends Model
}
}
public function getTimeTextAttribute()
{
return date("Y-m-d H:i:s",$this->attributes['usable_start_time']). ' - ' .date("Y-m-d H:i:s",$this->attributes['usable_end_time']);
}
}

13
app/Model/v3/Feprint.php

@ -0,0 +1,13 @@
<?php
namespace App\Model\v3;
use App\Model\Model;
use Hyperf\Database\Model\SoftDeletes;
class Feprint extends Model
{
use SoftDeletes;
protected $table = 'lanzu_feprint';
}

18
app/Model/v3/GoodsActivityBanner.php

@ -2,12 +2,19 @@
namespace App\Model\v3;
use App\Constants\v3\OssThumbnail;
use App\Model\Model;
use Hyperf\Database\Model\Builder;
use Hyperf\Database\Model\SoftDeletes;
use App\Service\v3\Interfaces\AttachmentServiceInterface;
use Hyperf\Di\Annotation\Inject;
class GoodsActivityBanner extends Model
{
/**
* @Inject
* @var AttachmentServiceInterface
*/
protected $attachmentService;
use SoftDeletes;
protected $table = 'lanzu_goods_activity_banners';
@ -18,11 +25,10 @@ class GoodsActivityBanner extends Model
public function getBannerUrlAttribute()
{
$url = $this->attributes['path'];
if(strripos($url,"http") === false){
return config('alioss.img_host').'/'.$url;
}else{
return $url;
if ($this->attributes['type'] == 1) {
return $this->attachmentService->switchImgToAliOss($this->attributes['path'], OssThumbnail::THUMBNAIL_600_Q90);
} elseif ($this->attributes['type'] == 2) {
return $this->attachmentService->switchImgToAliOss($this->attributes['path']);
}
}
}

11
app/Model/v3/GoodsBanner.php

@ -27,13 +27,10 @@ class GoodsBanner extends Model
public function getBannerUrlAttribute()
{
// $url = $this->attributes['path'];
// if(strripos($url,"http") === false){
// return config('alioss.img_host').'/'.$url;
// }else{
// return $url;
// }
if($this->attributes['type'] == 1){
return $this->attachmentService->switchImgToAliOss($this->attributes['path'], OssThumbnail::THUMBNAIL_600_Q90);
}elseif ($this->attributes['type'] == 2){
return $this->attachmentService->switchImgToAliOss($this->attributes['path']);
}
}
}

2
app/Model/v3/GoodsCategory.php

@ -3,8 +3,10 @@
namespace App\Model\v3;
use App\Model\Model;
use Hyperf\Database\Model\SoftDeletes;
class GoodsCategory extends Model
{
use SoftDeletes;
protected $table = 'lanzu_goods_category';
}

9
app/Model/v3/Market.php

@ -3,6 +3,7 @@
namespace App\Model\v3;
use App\Model\Model;
use Hyperf\Database\Model\Builder;
class Market extends Model
{
@ -14,6 +15,14 @@ class Market extends Model
'region_name'
];
protected function boot(): void
{
parent::boot();
self::addGlobalScope('normal', function (Builder $builder) {
$builder->where([$this->getTable().'.status' => 1]);
});
}
public function getProvinceNameAttribute()
{
$area = Area::query()->find($this->attributes['province_id']);

17
app/Model/v3/ServicePersonnel.php

@ -3,10 +3,20 @@
declare (strict_types=1);
namespace App\Model\v3;
use App\Constants\v3\OssThumbnail;
use App\Model\Model;
use App\Service\v3\Interfaces\AttachmentServiceInterface;
use Hyperf\Database\Model\SoftDeletes;
use Hyperf\Di\Annotation\Inject;
class ServicePersonnel extends Model
{
use SoftDeletes;
/**
* @Inject
* @var AttachmentServiceInterface
*/
protected $attachmentService;
/**
* The table associated with the model.
*
@ -19,6 +29,7 @@ class ServicePersonnel extends Model
* @var array
*/
protected $fillable = [];
/**
* The attributes that should be cast to native types.
*
@ -27,4 +38,8 @@ class ServicePersonnel extends Model
// protected $casts = [
// 'set_reward' => 'array'
// ];
public function getHeadUrlAttribute($value)
{
return $this->attachmentService->switchImgToAliOss($value, OssThumbnail::THUMBNAIL_600_Q90);
}
}

27
app/Service/v3/Implementations/CouponRecService.php

@ -103,7 +103,7 @@ class CouponRecService implements CouponRecServiceInterface
public function getListByUser($userId,$type,$page = 1,$pagesize = 5)
{
//查询优惠券
$builder = CouponRec::query()->join('lanzu_coupon', 'lanzu_coupon.id', '=', 'lanzu_coupon_receive.coupon_id')
$builder = CouponRec::query()->join('lanzu_coupon', 'lanzu_coupon.id', '=', 'lanzu_coupon_receive.coupon_id')->with('coupon')
->where([
['lanzu_coupon_receive.user_id' ,'=', $userId],
]);
@ -130,32 +130,11 @@ class CouponRecService implements CouponRecServiceInterface
break;
}
$builder = $builder->select(
'lanzu_coupon.title',
'lanzu_coupon.discounts',
'lanzu_coupon.full_amount',
'lanzu_coupon.discount_type',
'lanzu_coupon.introduce',
'lanzu_coupon.tags',
'lanzu_coupon.usable_start_time',
'lanzu_coupon.usable_end_time',
'lanzu_coupon_receive.number',
'lanzu_coupon_receive.number_remain'
'lanzu_coupon_receive.*'
)
->orderBy('lanzu_coupon.weigh','desc');
$paginate = $builder->paginate($pagesize);
$couponList = $paginate->toArray();
foreach ($couponList['data'] as $key => &$coupon) {
//拼接满减文字提示
$coupon['full_amount_text'] = '满' . $coupon['full_amount'] . "可用";
//判断是折扣优惠券还是满减优惠券
if($coupon['discount_type'] == 1){
$coupon['discounts_text'] = '¥'.$coupon['discounts'];
}elseif($coupon['discount_type'] == 2){
$coupon['discounts_text'] = floatval($coupon['discounts'])."";
}
//拼接时间文字提示
$coupon['time_text'] = date("Y-m-d H:i:s",$coupon['usable_start_time']). ' - ' .date("Y-m-d H:i:s",$coupon['usable_end_time']);
}
return ['has_more_pages' => $paginate->hasMorePages(), 'list' => $couponList['data']];
}
@ -302,7 +281,7 @@ class CouponRecService implements CouponRecServiceInterface
->where('user_id',$userId)
->get();
foreach ($coupons as $coupon){
if($coupon->coupon->usable_end_time < time() || $coupon->coupon->status != 1){
if($coupon->coupon->usable_end_time < time()){
$res['expired'] += $coupon->number_remain;
}else{
$res['unused'] += $coupon->number_remain;

5
app/Service/v3/Implementations/DistributionPriceService.php

@ -11,6 +11,7 @@ class DistributionPriceService implements DistributionPriceServiceInterface
{
public function do($distance)
{
return 0;
$deliveryDistance = config('distance.delivery_distance');
$deliveryDistance = ceil($deliveryDistance/1000);
$km = ceil($distance/1000);
@ -21,10 +22,10 @@ class DistributionPriceService implements DistributionPriceServiceInterface
case ($km >= 5 && $km < 7) :
$distributionRrice = bcmul(1.00,($km-3),2);
break;
case ($km >= 7 && $km < $deliveryDistance) :
case ($km >= 7 && $km <= $deliveryDistance) :
$distributionRrice = bcmul(1.50,($km-3),2);
break;
case ($km >= $deliveryDistance) :
case ($km > $deliveryDistance) :
throw new ErrorCodeException(ErrorCode::LOCATION_LONG_DISTANCE);
break;
default:

5
app/Service/v3/Implementations/FeiePrintService.php

@ -3,6 +3,7 @@
namespace App\Service\v3\Implementations;
use App\Libs\FeiePrintClient;
use App\Model\v3\Feprint;
use App\Model\v3\OrderMain;
use App\Service\v3\Interfaces\FeiePrintServiceInterface;
use Hyperf\DbConnection\Db;
@ -52,9 +53,9 @@ class FeiePrintService implements FeiePrintServiceInterface
// foreach ($data['order'] as $key => &$item) {
// $item = (array)$item;
// }
$printSn = Feprint::query()->where('market_id',$data->market_id)->value('sn');
$content = $this->printFormat($data, 4, 14, 7, 7);
$res = $this->printMsg('920527381', $content, 1);
$res = $this->printMsg($printSn, $content, 1);
return $res;
}

18
app/Service/v3/Implementations/GoodsActivityService.php

@ -49,20 +49,12 @@ class GoodsActivityService implements GoodsActivityServiceInterface
// 商品库存不足
// 获取冻结的库存
//$inventoryFrozen = (int)$redis->get($inventoryKey);
$inventoryFrozen = 0;
$inventoryFrozen = (int)$redis->get($inventoryKey);
// $inventoryFrozen = 0;
if($goods->is_infinite != 1 && $goods->inventory < ($num+$inventoryFrozen)){
return ErrorCode::GOODS_ACTIVITY_INVENTORY_ERROR;
}
// 压redis库存
// redis记录当前商品的购买数量,压库存,下单失败、下单成功扣库存成功、订单取消的时候释放
if (!$redis->exists($inventoryKey)) {
$redis->set($inventoryKey, $num);
} else {
$redis->incrBy($inventoryKey, intval($num));
}
// 是否超过限购数量
if ($goods->restrict_num != 0 && $goods->restrict_num < $num) {
return ErrorCode::GOODS_ACTIVITY_RESTRICT_LIMIT;
@ -141,15 +133,15 @@ class GoodsActivityService implements GoodsActivityServiceInterface
/**
* 统计订单中活动商品的数量,并校验
* @param $orderGoods
* @param $goodsIds
* @param int $limitNum
* @return bool
*/
public function checkOrderActivityCount($orderGoods, $limitNum=1)
public function checkOrderActivityCount($goodsIds, $limitNum=1)
{
$sourceGoods = GoodsActivity::query()
->whereIn('id', array_values(array_column($orderGoods, 'goods_id')))
->whereIn('id', $goodsIds)
->get()->toArray();
$limitNums = [

7
app/Service/v3/Implementations/GoodsService.php

@ -45,13 +45,6 @@ class GoodsService implements GoodsServiceInterface
if($goods->is_infinite != 1 && $goods->inventory < ($num+$inventoryFrozen)){
return ErrorCode::GOODS_INVENTORY_ERROR;
}
// 压redis库存
// redis记录当前商品的购买数量,压库存,下单失败、下单成功扣库存成功、订单取消的时候释放
if (!$redis->exists($inventoryKey)) {
$redis->set($inventoryKey, $num);
} else {
$redis->incrBy($inventoryKey, intval($num));
}
// 是否超过限购数量
if ($goods->restrict_num != 0 && $goods->restrict_num < $num) {

15
app/Service/v3/Implementations/LocationService.php

@ -30,7 +30,7 @@ class LocationService implements LocationServiceInterface
public function getMarketListByLocation($lng,$lat)
{
$cityIds = Market::query()->pluck('city_id');
$cityIds = Market::query()->where(['status' => 1])->pluck('city_id');
$res = Area::query()->with('markets')->whereIn('id',$cityIds)->get();
foreach ($res as &$v){
@ -74,19 +74,22 @@ class LocationService implements LocationServiceInterface
['city_id','=',$cityId]
])
->get();
foreach ($res as &$v){
foreach ($res as &$m){
if(!empty($lng) && !empty($lat)){
$v->distance = ($this->getDistance($v->lng,$v->lat,$lng,$lat)).' km';
$m->distance_num = $this->getDistance($m->lng, $m->lat, $lng, $lat);
$m->distance = $m->distance_num.' km';
}else{
$v->distance = '';
$m->distance_num = 0;
$m->distance = '';
}
}
return $res;
$res = collect($res)->sortBy('distance_num');
return $res->values()->all();
}
public function getNearestMarket($lng,$lat)
{
$markets = Market::query()->get()->toArray();
$markets = Market::query()->where(['status' => 1])->get()->toArray();
$result = [];
$distinctMin = 0;
foreach ($markets as &$market){

25
app/Service/v3/Implementations/OrderListService.php

@ -8,6 +8,7 @@ use App\Model\v3\OrderMain;
use App\Model\v3\Order;
use App\Service\v3\Interfaces\BadgeServiceInterface;
use App\Service\v3\Interfaces\OrderListServiceInterface;
use App\Service\v3\Interfaces\OrderOnlineServiceInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\ApplicationContext;
@ -20,6 +21,12 @@ class OrderListService implements OrderListServiceInterface
*/
protected $badgeService;
/**
* @Inject
* @var OrderOnlineServiceInterface
*/
protected $orderOnlineService;
public function do()
{
// TODO: Implement do() method.
@ -61,11 +68,6 @@ class OrderListService implements OrderListServiceInterface
// 清除badge
$this->badgeService->clearUserOrder($userId, $tab);
co(function () use ($userId) {
// 自动取消超时订单
$this->autoCancel($userId);
});
$paginate = $builder->orderBy('created_at', 'desc')->paginate($pagesize);
$orders = $paginate->toArray();
return ['has_more_pages' => $paginate->hasMorePages(), 'orders' => $orders['data'], 'note' => '待付款订单15分钟后将自动取消,请尽快支付!'];
@ -95,8 +97,8 @@ class OrderListService implements OrderListServiceInterface
->select(''.$childTable.'.*')
->join($mainTable, ''.$childTable.'.order_main_id', '=', ''.$mainTable.'.global_order_id')
->with(['orderMain', 'orderGoods'])
->where(['store_id' => $storeId, ''.$mainTable.'.type' => OrderType::ONLINE]);
->where(['store_id' => $storeId, ''.$mainTable.'.type' => OrderType::ONLINE])
->whereNull($mainTable.'.deleted_at');
switch ($tab) {
case 'all':
break;
@ -161,6 +163,7 @@ class OrderListService implements OrderListServiceInterface
->select(''.$mainTable.'.*', ''.$childTable.'.order_num')
->join($childTable, ''.$childTable.'.order_main_id', '=', ''.$mainTable.'.global_order_id')
->where([''.$childTable.'.store_id' => $storeId, ''.$mainTable.'.type' => OrderType::OFFLINE])
->whereNull($mainTable.'.deleted_at')
->with('user');
// if(!empty($start_time) && !empty($end_time)){
@ -193,12 +196,4 @@ class OrderListService implements OrderListServiceInterface
$orders = $paginate->toArray();
return ['has_more_pages' => $paginate->hasMorePages(), 'orders' => $orders['data']];
}
public function autoCancel($userId)
{
return OrderMain::query()
->where(['user_id' => $userId, 'state' => OrderState::UNPAID])
->where('created_at', '<', time()-900)
->update(['state' => OrderState::CANCELED]);
}
}

112
app/Service/v3/Implementations/OrderOnlineService.php

@ -117,6 +117,7 @@ class OrderOnlineService implements OrderOnlineServiceInterface
public function do($marketId, $userId, $userAddrId, $storeList, $totalMoney, $deliveryTimeNote='尽快送达', $serviceMoney=0, $receiveCouponIds=null, $plat=''){
$redis = ApplicationContext::getContainer()->get(Redis::class);
$isCacheInventory = false;
$carts = [];
Db::beginTransaction();
try {
@ -157,6 +158,7 @@ class OrderOnlineService implements OrderOnlineServiceInterface
$dataChildren = []; # 子订单
$dataOrderGoods = []; # 订单商品
$storeTypeIds = []; # 订单中的商户类型,用于校验红包
$activityGoodsIds = []; # 活动商品IDs
foreach ($storeList as $key => &$storeItem) {
@ -189,7 +191,7 @@ class OrderOnlineService implements OrderOnlineServiceInterface
}
$check = $this->goodsService->check($goods, $cart->num);
if (true !== $check) {
throw new ErrorCodeException($check, '['.$goods->name.'/'.$goods->goods_unit.']');
throw new ErrorCodeException($check, '['.$goods->name.']');
}
} elseif ($cart->activity_type == 2) {
$goods = GoodsActivity::query()->lockForUpdate()->with('store')->find($cart->goods_id);
@ -198,11 +200,25 @@ class OrderOnlineService implements OrderOnlineServiceInterface
}
$check = $this->goodsActivityService->check($goods, $cart->num, $userId);
if (true !== $check) {
throw new ErrorCodeException($check, '['.$goods->name.'/'.$goods->goods_unit.']');
throw new ErrorCodeException($check, '['.$goods->name.']');
}
}
// 压redis库存
// redis记录当前商品的购买数量,压库存,下单失败、下单成功扣库存成功、订单取消的时候释放
$inventoryKey = 'goods_inventory_sold_'.$cart->activity_type.'_'.$cart->goods_id; // 拼接activity_type和goods_id
if (!$redis->exists($inventoryKey)) {
$redis->set($inventoryKey, $cart->num);
} else {
$redis->incrBy($inventoryKey, intval($cart->num));
}
$isCacheInventory = true;
if ($cart->activity_type == 2) {
$activityGoodsIds[] = $cart->goods_id;
}
// 算金额
$goodsAmount = bcmul((string)$goods->price, (string)$cart->num); # 当前商品的金额
$subAmount = bcadd((string)$subAmount, (string)$goodsAmount); # 当前店铺子订单的金额
@ -319,7 +335,7 @@ class OrderOnlineService implements OrderOnlineServiceInterface
}
// 判断是否有购买多个特价商品
$check = $this->goodsActivityService->checkOrderActivityCount($dataOrderGoods);
$check = $this->goodsActivityService->checkOrderActivityCount($activityGoodsIds);
if(!$check){
$this->log->event(LogLabel::ORDER_ONLINE_LOG, ['msg' => '订单中有活动商品超过限购数量', 'data' => json_encode($dataOrderGoods)]);
throw new ErrorCodeException(ErrorCode::GOODS_ACTIVITY_RESTRICT_LIMIT);
@ -328,11 +344,12 @@ class OrderOnlineService implements OrderOnlineServiceInterface
// 订单成功,做一些处理
// 活动商品购买记录
foreach ($dataOrderGoods as $key => &$goods) {
foreach ($goods as $k => &$goodsItem)
foreach ($goods as $k => &$goodsItem) {
if ($goodsItem['activity_type'] == 2) {
$this->goodsActivityService->cacheRecord($goodsItem['goods_id'], $goodsItem['number'], $userId);
}
}
}
Db::commit();
@ -350,6 +367,8 @@ class OrderOnlineService implements OrderOnlineServiceInterface
return $this->paymentService->do($globalOrderId, $totalAmount, $userId, config('wechat.notify_url.online'));
} catch (Exception $e) {
Db::rollBack();
if ($isCacheInventory) {
// 释redis库存
foreach ($carts as $k => &$cart) {
// 拼接activity_type和goods_id
@ -358,11 +377,17 @@ class OrderOnlineService implements OrderOnlineServiceInterface
if (!$redis->exists($inventoryKey)) {
$redis->set($inventoryKey, 0);
} else {
$redis->decrBy($inventoryKey, $cart->num);
$redis->decrBy($inventoryKey, intval($cart->num));
}
}
}
$this->log->event(LogLabel::ORDER_ONLINE_LOG, ['msg' => $e->getMessage()]);
throw new ErrorCodeException(ErrorCode::ORDER_ONLINE_FAIL);
$message = '';
if ($e instanceof ErrorCodeException) {
$message = $e->getMessage();
}
throw new ErrorCodeException(ErrorCode::ORDER_ONLINE_FAIL, $message);
}
}
@ -425,7 +450,7 @@ class OrderOnlineService implements OrderOnlineServiceInterface
if (!$redis->exists($inventoryKey)) {
$redis->set($inventoryKey, 0);
} else {
$redis->decrBy($inventoryKey, $goodsItem['number']);
$redis->decrBy($inventoryKey, intval($goodsItem['number']));
}
}
@ -520,7 +545,7 @@ class OrderOnlineService implements OrderOnlineServiceInterface
if (!$redis->exists($inventoryKey)) {
$redis->set($inventoryKey, 0);
} else {
$redis->decrBy($inventoryKey, $goodsItem['number']);
$redis->decrBy($inventoryKey, intval($goodsItem['number']));
}
}
@ -630,9 +655,80 @@ class OrderOnlineService implements OrderOnlineServiceInterface
$orderMain = $this->check($globalOrderId, $userId, OrderState::REFUNDING);
$orderIds = Order::query()->where(['order_main_id' => $orderMain->global_order_id])->pluck('id');
$orderGoods = OrderGoods::query()->whereIn('order_id', $orderIds)->get()->toArray();
// 释redis库存
$redis = ApplicationContext::getContainer()->get(Redis::class);
foreach ($orderGoods as $k => &$goodsItem) {
// 拼接activity_type和goods_id
$inventoryKey = 'goods_inventory_sold_'.$goodsItem['activity_type'].'_'.$goodsItem['goods_id'];
// redis记录当前商品的购买数量,压库存,下单失败、下单成功扣库存成功、订单取消的时候释放
if (!$redis->exists($inventoryKey)) {
$redis->set($inventoryKey, 0);
} else {
$redis->decrBy($inventoryKey, intval($goodsItem['number']));
}
}
// 微信退款
if ($orderMain->pay_type == Payment::WECHAT) {
return $this->paymentService->undo($orderMain->global_order_id, $userId);
}
}
public function autoCancel()
{
try {
$orderMains = OrderMain::query()
->where(['state' => OrderState::UNPAID])
->where('created_at', '<', time()-900)
->limit(100)
->get();
foreach ($orderMains as $key => &$orderMain) {
// 订单取消
OrderMain::query()->where(['id' => $orderMain->id])->update(['state' => OrderState::CANCELED]);
// 退还优惠券
$this->couponService->orderRefundCoupons($orderMain->global_order_id);
// 撤销活动商品购买记录
$orders = Order::query()->where(['order_main_id' => $orderMain->global_order_id])->get()->toArray();
$orderGoods = OrderGoods::query()
->whereIn('order_id', array_values(array_column($orders, 'id')))
->get()
->toArray();
foreach ($orderGoods as $key => &$goods) {
if ($goods['activity_type'] == 2) {
$this->goodsActivityService->clearCacheRecord($goods['goods_id'], $goods['number'], $orderMain->user_id);
}
}
// 释redis库存
$redis = ApplicationContext::getContainer()->get(Redis::class);
foreach ($orderGoods as $k => &$goodsItem) {
// 拼接activity_type和goods_id
$inventoryKey = 'goods_inventory_sold_'.$goodsItem['activity_type'].'_'.$goodsItem['goods_id'];
// redis记录当前商品的购买数量,压库存,下单失败、下单成功扣库存成功、订单取消的时候释放
if (!$redis->exists($inventoryKey)) {
$redis->set($inventoryKey, 0);
} else {
$redis->decrBy($inventoryKey, intval($goodsItem['number']));
}
}
// 记录badge
$orderChildIds = array_values(array_column($orders, 'store_id'));
$this->badgeService->doByOrder($orderMain->user_id, $orderChildIds, $orderMain->global_order_id, OrderState::CANCELED);
}
} catch (Exception $e) {
$this->log->event(LogLabel::ORDER_AUTO_CANCEL_FAIL_LOG, ['message' => $e->getMessage()]);
}
}
}

2
app/Service/v3/Implementations/PaymentService.php

@ -60,7 +60,7 @@ class PaymentService implements PaymentServiceInterface
$payMoney = bcmul((string)$orderMain->money, 100, 0);
if (env('APP_ENV') != 'prod' && $orderMain->type == OrderType::ONLINE) {
$payMoney = 1;
// $payMoney = 1;
}
$user = User::select('openid')->find($userId);

5
app/Service/v3/Implementations/SearchService.php

@ -56,7 +56,10 @@ class SearchService implements SearchServiceInterface
if (isset($params['goods_category_ids']) && $params['goods_category_ids']) {
$typeIds = explode(',', $params['goods_category_ids']);
$builder->whereIn(''.$goodsTable.'.goods_category_id', $typeIds);
$builder->where(function ($query) use ($goodsTable, $typeIds) {
$query->whereIn(''.$goodsTable.'.goods_category_id', $typeIds)
->orWhere(''.$goodsTable.'.goods_category_id', 0);
});
}
if (isset($params['keyword']) && $params['keyword']) {

3
app/Service/v3/Implementations/ServiceEvaluateService.php

@ -3,6 +3,7 @@
namespace App\Service\v3\Implementations;
use App\Model\v3\ServiceEvaluate;
use App\Model\v3\ServicePersonnel;
use App\Model\v3\User;
use App\Service\v3\Interfaces\ServiceEvaluateServiceInterface;
use Hyperf\DbConnection\Db;
@ -47,7 +48,7 @@ class ServiceEvaluateService implements ServiceEvaluateServiceInterface
public function getPersonnelInfo($service_personnel_id)
{
$res = Db::table('lanzu_service_personnel')
$res = ServicePersonnel::query()
->where([
['id','=',$service_personnel_id],
['status','=',1]

14
app/Service/v3/Implementations/ShopCartService.php

@ -2,6 +2,8 @@
namespace App\Service\v3\Implementations;
use App\Constants\v3\ErrorCode;
use App\Exception\ErrorCodeException;
use App\Model\v3\Goods;
use App\Model\v3\GoodsActivity;
use App\Model\v3\ShoppingCart;
@ -166,8 +168,13 @@ class ShopCartService implements ShopCartServiceInterface
$cartList = [];
$totalAmount = 0;
foreach ($carts as $key => &$cart) {
if (empty($cart->store)) {
throw new ErrorCodeException(ErrorCode::STORE_NOT_AVAILABLE);
continue;
}
if (empty($cart->store)||empty($cart->goods)) {
if (empty($cart->goods)) {
throw new ErrorCodeException(ErrorCode::GOODS_NOT_EXISTS);
continue;
}
@ -178,6 +185,7 @@ class ShopCartService implements ShopCartServiceInterface
// 商户是否歇业
$checkStore = $this->storeService->check($store['id']);
if (!$checkStore) {
throw new ErrorCodeException(ErrorCode::STORE_NOT_AVAILABLE);
continue;
}
@ -191,7 +199,6 @@ class ShopCartService implements ShopCartServiceInterface
}
if ($res === true) {
$cartList['store_lists'][$store['id']]['store'] = $store;
$cartList['store_lists'][$store['id']]['shopping_cart'][] = $shoppingCart;
@ -205,6 +212,8 @@ class ShopCartService implements ShopCartServiceInterface
}
$totalAmount = bcadd($totalAmount, bcmul($cart->goods->price, $cart->num));
}else{
throw new ErrorCodeException($res);
}
}
@ -215,7 +224,6 @@ class ShopCartService implements ShopCartServiceInterface
}
$cartList['total'] = bcadd($totalAmount, '0', 2);
return $cartList['store_lists'];
}

21
app/Service/v3/Implementations/ShopCartUpdateService.php

@ -11,6 +11,7 @@ use App\Model\v3\ShoppingCart;
use App\Model\v3\Goods;
use App\Model\v3\GoodsActivity;
use App\Constants\v3\Goods as GoodsConstants;
use App\Service\v3\Interfaces\StoreServiceInterface;
use Hyperf\Di\Annotation\Inject;
class ShopCartUpdateService implements ShopCartUpdateServiceInterface
{
@ -26,6 +27,12 @@ class ShopCartUpdateService implements ShopCartUpdateServiceInterface
*/
protected $goodsActivityService;
/**
* @Inject
* @var StoreServiceInterface
*/
protected $storeService;
public function do($userId,$goodsId,$num,$activityType)
{
$goodsType = '';
@ -37,6 +44,15 @@ class ShopCartUpdateService implements ShopCartUpdateServiceInterface
if(empty($goods)){
throw new ErrorCodeException(ErrorCode::GOODS_NOT_EXISTS);
}
//特价商品限购
$goodsArr = ShoppingCart::query()
->where(['user_id' => $userId,'market_id' => $goods->market_id,'activity_type' => GoodsConstants::IS_ACTIVITY])
->pluck('goods_id')->toArray();
array_push($goodsArr,$goodsId);
$checkGoodsActivity = $this->goodsActivityService->checkOrderActivityCount($goodsArr);
if(!$checkGoodsActivity){
throw new ErrorCodeException(ErrorCode::GOODS_ACTIVITY_BUY);
}
$goodsCheck = $this->goodsActivityService->check($goods,$num,$userId);
}else{
$builder = Goods::query();
@ -56,7 +72,7 @@ class ShopCartUpdateService implements ShopCartUpdateServiceInterface
throw new ErrorCodeException($goodsCheck);
}
return ShoppingCart::query()->lockForUpdate()->updateOrCreate(
$shoppingCart = ShoppingCart::query()->lockForUpdate()->updateOrCreate(
[
'user_id' => $userId,
'goods_id' => $goodsId,
@ -69,6 +85,9 @@ class ShopCartUpdateService implements ShopCartUpdateServiceInterface
'goods_type' => $goodsType
]
);
$storeCheck = $this->storeService->check($goods->store_id);
$shoppingCart->check = $storeCheck;
return $shoppingCart;
}
public function check()

8
app/Service/v3/Implementations/TabsService.php

@ -26,10 +26,10 @@ class TabsService implements TabsServiceInterface
public function allForAppletIndex()
{
return [
['tab' => Tabs::APPLET_INDEX_RECOMMEND, 'title' => '推荐', 'subtitle' => '猜你喜欢', 'badge' => '', 'bg_color' => '#FF0000', 'font_color' => '#FFFFFF'],
['tab' => Tabs::APPLET_INDEX_NEW, 'title' => '懒族上新', 'subtitle' => '买点不一样', 'badge' => '限时', 'bg_color' => '#FF0000', 'font_color' => '#FFFFFF'],
['tab' => Tabs::APPLET_INDEX_FRESH, 'title' => '实时鲜货', 'subtitle' => '今天辛苦了', 'badge' => '好新鲜', 'bg_color' => '#FF0000', 'font_color' => '#FFFFFF'],
['tab' => Tabs::APPLET_INDEX_OFFICE, 'title' => '上班带餐', 'subtitle' => '轻奢快手菜', 'badge' => '不慌', 'bg_color' => '#FF0000', 'font_color' => '#FFFFFF'],
['tab' => Tabs::APPLET_INDEX_RECOMMEND, 'title' => '猜你喜欢', 'subtitle' => '我是你的菜', 'badge' => '', 'bg_color' => '#FF0000', 'font_color' => '#FFFFFF'],
['tab' => Tabs::APPLET_INDEX_NEW, 'title' => '每日上新', 'subtitle' => '新鲜当日达', 'badge' => '好新鲜', 'bg_color' => '#FF0000', 'font_color' => '#FFFFFF'],
['tab' => Tabs::APPLET_INDEX_FRESH, 'title' => '懒族优选', 'subtitle' => '发现不一样', 'badge' => '', 'bg_color' => '#FF0000', 'font_color' => '#FFFFFF'],
['tab' => Tabs::APPLET_INDEX_OFFICE, 'title' => '白领餐食', 'subtitle' => '轻奢快手菜', 'badge' => '手到食来', 'bg_color' => '#FF0000', 'font_color' => '#FFFFFF'],
];
}
}

11
app/Service/v3/Implementations/UserAddressService.php

@ -10,7 +10,7 @@ use App\Service\v3\Interfaces\DistributionPriceServiceInterface;
use App\Service\v3\Interfaces\LocationServiceInterface;
use App\Service\v3\Interfaces\UserAddressServiceInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\DbConnection\Db;
class UserAddressService implements UserAddressServiceInterface
{
/**
@ -39,6 +39,13 @@ class UserAddressService implements UserAddressServiceInterface
'tel' => $tel,
'tags' => $tags
]);
if(empty($userAddressId)){
$userAddressId = $userAddress->id;
Db::transaction(function () use ($user_id,$userAddressId) {
UserAddress::query()->where(['user_id'=> $user_id,'is_default'=> 1])->update(['is_default' => 0]);
UserAddress::query()->where('id',$userAddressId)->update(['is_default' => 1]);
});
}
return $userAddress;
}
@ -89,7 +96,7 @@ class UserAddressService implements UserAddressServiceInterface
throw new ErrorCodeException(ErrorCode::LOCATION_USER_ADDRESS);
}
$distance = $this->locationService->getDistanceByTencent($address['address']->lng,$address['address']->lat,$market->lng,$market->lat);
$distance = $this->locationService->getDistanceByTencent($market->lng,$market->lat,$address['address']->lng,$address['address']->lat);
$distributionPrice = $this->distributionPriceService->do($distance);
$res['address'] = $address;
$res['delivery_distance'] = $distance;

2
app/Service/v3/Interfaces/GoodsActivityServiceInterface.php

@ -13,5 +13,5 @@ interface GoodsActivityServiceInterface
public function detail($goodsId);
public function cacheRecord($goodsId, $num, $userId);
public function clearCacheRecord($goodsId, $num, $userId);
public function checkOrderActivityCount($orderGoods, $limitNum=1);
public function checkOrderActivityCount($goodsIds, $limitNum=1);
}

6
app/Service/v3/Interfaces/OrderOnlineServiceInterface.php

@ -70,4 +70,10 @@ interface OrderOnlineServiceInterface
* @return mixed
*/
public function doRefund($globalOrderId, $userId);
/**
* 自动取消订单
* @return mixed
*/
public function autoCancel();
}

3
composer.json

@ -42,7 +42,8 @@
"hyperf/rpc-client": "^2.0",
"hyperf/consul": "^2.0",
"alibabacloud/client": "^1.5",
"hashids/hashids": "^4.0"
"hashids/hashids": "^4.0",
"hyperf/crontab": "^2.0"
},
"require-dev": {
"swoole/ide-helper": "^4.5",

61
composer.lock

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "9f238a6a5e556f4061e56600f28bacfd",
"content-hash": "7ab1eb814ce8a0d34cfec6c2c0725022",
"packages": [
{
"name": "adbario/php-dot-notation",
@ -1593,6 +1593,65 @@
],
"time": "2020-06-24T23:15:36+00:00"
},
{
"name": "hyperf/crontab",
"version": "v2.0.9",
"source": {
"type": "git",
"url": "https://github.com/hyperf/crontab.git",
"reference": "3167a34acdb53d19a12bce4a29139c6e51ed62a4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/hyperf/crontab/zipball/3167a34acdb53d19a12bce4a29139c6e51ed62a4",
"reference": "3167a34acdb53d19a12bce4a29139c6e51ed62a4",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"hyperf/utils": "~2.0.0",
"nesbot/carbon": "^2.0",
"php": ">=7.2"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.9",
"malukenho/docheader": "^0.1.6",
"mockery/mockery": "^1.0",
"phpunit/phpunit": "^7.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
},
"hyperf": {
"config": "Hyperf\\Crontab\\ConfigProvider"
}
},
"autoload": {
"psr-4": {
"Hyperf\\Crontab\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "A crontab component for Hyperf.",
"homepage": "https://hyperf.io",
"keywords": [
"crontab",
"hyperf",
"php",
"swoole"
],
"time": "2020-08-24T08:37:21+00:00"
},
{
"name": "hyperf/database",
"version": "v2.0.1",

5
config/autoload/crontab.php

@ -0,0 +1,5 @@
<?php
return [
// 是否开启定时任务
'enable' => true,
];

1
config/autoload/dependencies.php

@ -89,4 +89,5 @@ return [
\App\Service\v3\Interfaces\BadgeServiceInterface::class => \App\Service\v3\Implementations\BadgeService::class,
\App\Service\v3\Interfaces\InitialDeliveryServiceInterface::class => \App\Service\v3\Implementations\InitialDeliveryService::class,
\App\Service\v3\Interfaces\ServiceEvaluateServiceInterface::class => \App\Service\v3\Implementations\ServiceEvaluateService::class,
// \Hyperf\Crontab\Strategy\StrategyInterface::class => \Hyperf\Crontab\Strategy\TaskWorkerStrategy::class,
];

1
config/autoload/processes.php

@ -10,4 +10,5 @@ declare(strict_types=1);
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
return [
Hyperf\Crontab\Process\CrontabDispatcherProcess::class,
];
Loading…
Cancel
Save