diff --git a/app/Constants/v3/ErrorCode.php b/app/Constants/v3/ErrorCode.php index a955131..9b89d9b 100644 --- a/app/Constants/v3/ErrorCode.php +++ b/app/Constants/v3/ErrorCode.php @@ -23,10 +23,45 @@ class ErrorCode extends AbstractConstants /* 订单相关 601-650 */ /************************************/ + /** + * 线上下单失败 + * @Message("线上下单失败") + */ + const ORDER_ONLINE_FAIL = 601; + + /** + * 订单中有商品已失效 + * @Message("订单中有商品已失效") + */ + const ORDER_GOODS_NOT_AVAILABLE = 602; + + /** + * 订单中有商品库存不足 + * @Message("订单中有商品库存不足") + */ + const ORDER_GOODS_INVENTORY_LIMIT = 603; + + /** + * 订单总金额有误 + * @Message("订单总金额有误") + */ + const ORDER_TOTAL_AMOUNT_ERROR = 604; + + /** + * 订单不存在或已失效 + * @Message("订单不存在或已失效") + */ + const ORDER_NOT_AVAILABLE = 605; + /************************************/ /* 支付相关 651-700 */ /************************************/ + /** + * @Message("支付失败") + */ + const PAYMENT_FAIL = 651; + /************************************/ /* 用户相关 701-750 */ /************************************/ @@ -98,7 +133,7 @@ class ErrorCode extends AbstractConstants const SMS_SEND_FAILURE = 1003; /************************************/ - /* 商品相关 1101-1200 */ + /* 商品相关 1101-1150 */ /************************************/ /** * 库存不足 @@ -110,11 +145,67 @@ class ErrorCode extends AbstractConstants * 超过商品购买数量限制 * @Message("超过商品购买数量限制") */ - const PURCHASE_LIMIT_ERROR = 1102; + const GOODS_RESTRICT_LIMIT = 1102; + + /** + * 已下架 + * @Message("商品已下架") + */ + const GOODS_ON_SALE_NO = 1103; + + /************************************/ + /* 活动商品相关 1151-1200 */ + /************************************/ /** * 当前特价商品已被购买过 * @Message("当前特价商品已被购买过") */ - const SPERCIAL_OFFER_GOODS_ERROR = 1103; + const GOODS_ACTIVITY_BUY = 1151; + + /** + * 活动商品活动到期 + * @Message("活动商品活动已结束") + */ + const GOODS_ACTIVITY_EXPIRED = 1152; + + /** + * 库存不足 + * @Message("商品库存不足") + */ + const GOODS_ACTIVITY_INVENTORY_ERROR = 1153; + + /** + * 已下架 + * @Message("商品已下架") + */ + const GOODS_ACTIVITY_ON_SALE_NO = 1154; + + /** + * 商品超过限购数量 + * @Message("商品超过限购数量") + */ + const GOODS_ACTIVITY_RESTRICT_LIMIT = 1155; + + /** + * 订单中部分活动商户不可使用优惠券 + * @Message("活动商户不可使用优惠券") + */ + const GOODS_ACTIVITY_CANNOT_USE_COUPON = 1156; + + /************************************/ + /* 优惠券相关 1201-1250 */ + /************************************/ + + /** + * 您的订单中有优惠券已经失效 + * @Message("订单中有优惠券已经失效") + */ + const COUPON_NOT_AVAILABLE = 1201; + + /** + * 优惠券使用失败 + * @Message("优惠券使用失败") + */ + const COUPON_USE_FAILURE = 1202; } \ No newline at end of file diff --git a/app/Constants/v3/LogLabel.php b/app/Constants/v3/LogLabel.php index 3328736..7d5d55c 100644 --- a/app/Constants/v3/LogLabel.php +++ b/app/Constants/v3/LogLabel.php @@ -17,4 +17,14 @@ class LogLabel extends AbstractConstants */ const ERROR_CODE_EXCEPTION = 'error_code_exception'; + /** + * @Message("Order Online Log") + */ + const ORDER_ONLINE_LOG = 'order_online_log'; + + /** + * @Message("Paymetn Log") + */ + const ORDER_PAYMENT_LOG = 'order_payment_log'; + } diff --git a/app/Constants/v3/SsdbKeys.php b/app/Constants/v3/SsdbKeys.php index 28e78f9..6937a5b 100644 --- a/app/Constants/v3/SsdbKeys.php +++ b/app/Constants/v3/SsdbKeys.php @@ -55,4 +55,9 @@ class SsdbKeys extends AbstractConstants */ const USER_INFO = 'user_info_'; + /** + * @Message("用户活动商品限购记录") + */ + const ACTIVITY_GOODS_BUY_RECORD = 'activity_goods_buy_record_'; + } \ No newline at end of file diff --git a/app/Constants/v3/Tabs.php b/app/Constants/v3/Tabs.php index 9431cfc..0b95a4f 100644 --- a/app/Constants/v3/Tabs.php +++ b/app/Constants/v3/Tabs.php @@ -54,4 +54,9 @@ class Tabs extends AbstractConstants * @Message("商品详情页猜你喜欢") */ const RECOMMEND_LIKE_FOR_GOODS_DETAIL = 'recommend_like_goods_detail'; + + /** + * @Message("商品详情页为你推荐") + */ + const RECOMMEND_FOR_CART = 'recommend_cart'; } \ No newline at end of file diff --git a/app/Controller/v3/OrderOnlineController.php b/app/Controller/v3/OrderOnlineController.php index 3962758..3a04c5a 100644 --- a/app/Controller/v3/OrderOnlineController.php +++ b/app/Controller/v3/OrderOnlineController.php @@ -113,10 +113,12 @@ class OrderOnlineController extends BaseController $params['market_id'], $params['user_id'], $params['user_address_id'], - explode(',', $params['cart_ids']), + json_decode($params['store_list']), $params['total_money'], $params['delivery_time_note'], - explode(',', $params['coupon_ids']) + $params['service_money'], + explode(',', $params['coupon_ids']), + $params['plat'] ); return $this->success(['data' => $data]); diff --git a/app/Controller/v3/PaymentController.php b/app/Controller/v3/PaymentController.php new file mode 100644 index 0000000..549b60b --- /dev/null +++ b/app/Controller/v3/PaymentController.php @@ -0,0 +1,48 @@ +validationFactory->make( + $this->request->all(), + [ + 'global_order_id' => 'required|nonempty', + 'user_id' => 'required|nonempty', + ], + [ + 'global_order_id.*' => '订单号错误' + ] + ); + + if ($validator->fails()) { + throw new ValidationException($validator); + } + + $params = $validator->validated(); + $orderMain = OrderMain::query()->select('global_order_id', 'money', 'user_id') + ->where(['global_order_id' => $params['global_order_id']])->first(); + $parameters = $this->paymentService->do($orderMain->global_order_id, $orderMain->money, $orderMain->user_id); + + return $this->success(['parameters' => $parameters]); + } +} \ No newline at end of file diff --git a/app/Exception/ErrorCodeException.php b/app/Exception/ErrorCodeException.php index aabf9be..c6052f9 100644 --- a/app/Exception/ErrorCodeException.php +++ b/app/Exception/ErrorCodeException.php @@ -22,6 +22,8 @@ class ErrorCodeException extends ServerException if (is_null($message)) { $message = ErrorCode::getMessage($code); + } else { + $message = ErrorCode::getMessage($code) . '_' . $message; } parent::__construct($message, $code, $previous); diff --git a/app/Exception/Handler/ErrorCodeExceptionHandler.php b/app/Exception/Handler/ErrorCodeExceptionHandler.php index 7cc8575..775abc0 100644 --- a/app/Exception/Handler/ErrorCodeExceptionHandler.php +++ b/app/Exception/Handler/ErrorCodeExceptionHandler.php @@ -44,7 +44,7 @@ class ErrorCodeExceptionHandler extends ExceptionHandler "message" => $throwable->getMessage() ]; - $this->log->event(LogLabel::ERROR_CODE_EXCEPTION, $content); + $this->log->event(LogLabel::ERROR_CODE_EXCEPTION, ['error_exception_msg' => $content['message']]); return $response->withHeader('Content-Type', 'application/json') ->withStatus(200) diff --git a/app/Listener/ValidatorFactoryResolvedListener.php b/app/Listener/ValidatorFactoryResolvedListener.php index 7423594..3b93553 100644 --- a/app/Listener/ValidatorFactoryResolvedListener.php +++ b/app/Listener/ValidatorFactoryResolvedListener.php @@ -146,5 +146,30 @@ class ValidatorFactoryResolvedListener implements ListenerInterface }); + // 注册了 json_keys 验证器规则 + // 必须是json,同时包含后面的keys + $validatorFactory->extend('json_keys', function ($attribute, $value, $parameters, $validator) { + $rules = $validator->getRules(); + $rules[$attribute] = ['json']; + $validator->setRules($rules); + + $valueArr = json_decode($value, true); + + foreach ($valueArr as $key => $item) { + if (is_array($item)) { + $keys = array_keys($item); + } else { + $keys = array_keys($valueArr); + } + + if (!empty(array_diff($keys,$parameters))) { + return false; + } + } + + return $validator->passes(); + + }); + } } \ No newline at end of file diff --git a/app/Model/v3/Coupon.php b/app/Model/v3/Coupon.php index 931abac..d798c0d 100644 --- a/app/Model/v3/Coupon.php +++ b/app/Model/v3/Coupon.php @@ -9,6 +9,6 @@ class Coupon extends Model const DISCOUNT_TYPE_CASH = 1; const DISCOUNT_TYPE_RATE = 2; - protected $table = 'ims_system_coupon_user'; + protected $table = 'lanzu_coupon'; } diff --git a/app/Model/v3/CouponRec.php b/app/Model/v3/CouponRec.php index b7e38cc..a1db5fb 100644 --- a/app/Model/v3/CouponRec.php +++ b/app/Model/v3/CouponRec.php @@ -7,10 +7,10 @@ use App\Model\Model; class CouponRec extends Model { - protected $table = 'ims_system_coupon_user_receive'; + protected $table = 'lanzu_coupon_receive'; public function coupon() { - return $this->hasOne('App\Models\CouponUser','id','system_coupon_user_id'); + return $this->hasOne(Coupon::class,'id','coupon_id'); } } diff --git a/app/Model/v3/CouponUse.php b/app/Model/v3/CouponUse.php new file mode 100644 index 0000000..d1f98a1 --- /dev/null +++ b/app/Model/v3/CouponUse.php @@ -0,0 +1,16 @@ +hasOne(Coupon::class,'id','coupon_id'); + } +} diff --git a/app/Model/v3/Goods.php b/app/Model/v3/Goods.php index 4c71abc..7b033d7 100644 --- a/app/Model/v3/Goods.php +++ b/app/Model/v3/Goods.php @@ -78,6 +78,15 @@ class Goods extends Model return $query->orderBy('price', $sort); } + public function getCoverImgAttribute($value) + { + if(strripos($value,"http") === false){ + return config('alioss.img_host').'/'.$value; + }else{ + return $value; + } + } + public function getMonthSalesAttribute() { $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class); diff --git a/app/Model/v3/OrderGoods.php b/app/Model/v3/OrderGoods.php index c3f580d..b407092 100644 --- a/app/Model/v3/OrderGoods.php +++ b/app/Model/v3/OrderGoods.php @@ -22,6 +22,11 @@ class OrderGoods extends Model return $this->belongsTo(Goods::class, 'goods_id', 'id'); } + public function goodsActivity() + { + return $this->belongsTo(GoodsActivity::class, 'goods_id', 'id'); + } + public function getTagsAttribute() { return Goods::query()->where(['id' => $this->attributes['goods_id']])->value('tags'); diff --git a/app/Model/v3/OrderMain.php b/app/Model/v3/OrderMain.php index 5f0a7aa..d7de827 100644 --- a/app/Model/v3/OrderMain.php +++ b/app/Model/v3/OrderMain.php @@ -11,6 +11,41 @@ class OrderMain extends Model { protected $table = 'lanzu_order_main'; + protected $fillable = [ + 'market_id', + 'order_num', + 'global_order_id', + 'user_id', + 'pay_type', + 'type', + 'order_type', + 'shipping_type', + 'money', + 'total_money', + 'services_money', + 'coupon_money', + 'delivery_money', + 'state', + 'pay_time', + 'receive_time', + 'delivery_time', + 'complete_time', + 'cancel_time', + 'refund_time', + 'tel', + 'address', + 'area', + 'lat', + 'lng', + 'name', + 'print_num', + 'plat', + 'refuse_refund_note', + 'delivery_time_note', + 'total_refund_note', + 'note' + ]; + protected $appends = [ 'created_at_text', 'state_text', diff --git a/app/Request/v3/OrderOnlineRequest.php b/app/Request/v3/OrderOnlineRequest.php index 1e9a36d..309364a 100644 --- a/app/Request/v3/OrderOnlineRequest.php +++ b/app/Request/v3/OrderOnlineRequest.php @@ -25,10 +25,12 @@ class OrderOnlineRequest extends BaseFormRequest 'market_id' => 'required|nonempty|integer', 'user_id' => 'required|nonempty|integer', 'user_address_id' => 'required|nonempty|integer', - 'cart_ids' => 'required|nonempty', + 'store_list' => 'required|nonempty|json_keys:store_id,note,cart_ids', 'delivery_time_note' => 'required|nonempty', 'total_money' => 'required|nonempty', 'coupon_ids' => 'nonempty', + 'service_money' => 'nonempty|numeric', + 'plat' => 'nonempty', ]; } diff --git a/app/Service/v3/Implementations/CouponRecService.php b/app/Service/v3/Implementations/CouponRecService.php new file mode 100644 index 0000000..910970f --- /dev/null +++ b/app/Service/v3/Implementations/CouponRecService.php @@ -0,0 +1,78 @@ +get(Redis::class); + $couponTodayUsedIds = $redis->sMembers('coupon_'.date('Ymd').'_used_'.$userId); + $currentTime = time(); + + $builder = Db::table('lanzu_coupon_receive as receive') + ->join('lanzu_coupon as coupon', 'coupon.id', '=', 'receive.coupon_id', 'inner'); + + if (is_array($couponTodayUsedIds)&&!empty($couponTodayUsedIds)) { + $builder->whereNotIn('coupon.id', $couponTodayUsedIds); + } + + foreach ($storeTypeIds as $key => &$item) { + $item = (string)$item; + } + + if (!empty($storeTypeIds)) { + $builder->whereJsonContains('coupon.storetype_ids', $storeTypeIds); + } + + $builder->where(['receive.user_id' => $userId]) + ->whereIn('receive.status', [0,1]) + ->where('receive.number_remain', '>', 0) + ->whereIn('coupon.type', [1,$type]) + ->where('coupon.full_amount', '<=', $totalAmount) + ->where('coupon.usable_start_time', '<=', $currentTime) + ->where('coupon.usable_end_time', '>=', $currentTime) + ->where('coupon.usable_number', '<=', Db::raw('receive.number_remain')); + + if ($marketId) { + $builder->whereJsonContains('coupon.market_ids', [(string)$marketId]); + } + + return $builder->orderByRaw('coupon.discounts DESC, coupon.full_amount DESC') + ->get() + ->toArray(); + } +} \ No newline at end of file diff --git a/app/Service/v3/Implementations/CouponService.php b/app/Service/v3/Implementations/CouponService.php index 8ad6a2f..950937b 100644 --- a/app/Service/v3/Implementations/CouponService.php +++ b/app/Service/v3/Implementations/CouponService.php @@ -3,6 +3,8 @@ namespace App\Service\v3\Implementations; use App\Service\v3\Interfaces\CouponServiceInterface; +use Hyperf\Redis\Redis; +use Hyperf\Utils\ApplicationContext; class CouponService implements CouponServiceInterface { @@ -38,4 +40,19 @@ class CouponService implements CouponServiceInterface { return mt_rand(0,10); } + + /** + * 缓存优惠券今日使用情况 + * @param $userId + * @param $couponId + * @param $couponRecId + * @return bool + */ + function cacheTodayCouponUsed($userId, $couponId, $couponRecId) + { + $redis = ApplicationContext::getContainer()->get(Redis::class); + $setRes = $redis->sAdd('coupon_' . date('Ymd') . '_used_' . $userId, $couponId); + $expireRes = $redis->expire('coupon_' . date('Ymd') . '_used_' . $userId, strtotime(date('Y-m-d') . ' 23:59:59') - time()); + return $setRes && $expireRes; + } } \ No newline at end of file diff --git a/app/Service/v3/Implementations/GoodsActivityService.php b/app/Service/v3/Implementations/GoodsActivityService.php index 306c98a..884dfa7 100644 --- a/app/Service/v3/Implementations/GoodsActivityService.php +++ b/app/Service/v3/Implementations/GoodsActivityService.php @@ -2,12 +2,17 @@ namespace App\Service\v3\Implementations; +use App\Constants\v3\ActivityType; +use App\Constants\v3\ErrorCode; +use App\Constants\v3\SsdbKeys; use App\Service\v3\Interfaces\GoodsActivityServiceInterface; -use Hyperf\DbConnection\Db; +use App\TaskWorker\SSDBTask; use App\Constants\v3\Store; use App\Constants\v3\Goods; use App\Model\v3\GoodsActivity; use App\Model\v3\GoodsActivityBanner; +use Hyperf\Utils\ApplicationContext; + class GoodsActivityService implements GoodsActivityServiceInterface { public function do($goodsId) @@ -16,27 +21,43 @@ class GoodsActivityService implements GoodsActivityServiceInterface } - public function check($goodsId,$num = 1) + public function check($goodsId, $num, $userId) { - $data = GoodsActivity::query()->with('store')->where('id', $goodsId)->first(); - //活动商品 校验 - if($data->expire_time < time()){ - return '活动已结束'; + $goods = GoodsActivity::query()->with('store')->where('id', $goodsId)->first(); + + // 活动是否已经结束 + if ($goods->expire_time < time()) { + return ErrorCode::GOODS_ACTIVITY_EXPIRED; + } + + // 商户歇业 + if($goods->store->is_rest != Store::IS_OPEN_YES){ + return ErrorCode::GOODS_ACTIVITY_ON_SALE_NO; } - if($data->store->is_rest != Store::IS_OPEN_YES){ - return '店铺已休息'; + // 商品下架或已删除 + if($goods->on_sale == Goods::ON_SALE_NO || !is_null($goods->deleted_at)){ + return ErrorCode::GOODS_ACTIVITY_ON_SALE_NO; } - if($data->on_sale == Goods::ON_SALE_NO || !is_null($data->deleted_at)){ - return '商品已下架'; + // 商品库存不足 + if($goods->is_infinite != Goods::IS_INVENTORY && $goods->inventory < $num){ + return ErrorCode::GOODS_ACTIVITY_INVENTORY_ERROR; } - if($data->is_infinite != Goods::IS_INVENTORY && $data->inventory < $num){ - return '库存不足'; + // 是否超过限购数量 + if ($goods->restrict_num > $num) { + return ErrorCode::GOODS_ACTIVITY_RESTRICT_LIMIT; } - return ''; + // 是否已经购买过(某个时间段内,时间段有商品的限制) + $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class); + $hasBuy = $ssdb->exec('get', SsdbKeys::ACTIVITY_GOODS_BUY_RECORD.$userId.'_'.$goodsId); + if ($hasBuy && $hasBuy >= $goods->time_limit_num) { + return ErrorCode::GOODS_ACTIVITY_BUY; + } + + return true; } public function undo() @@ -55,4 +76,60 @@ class GoodsActivityService implements GoodsActivityServiceInterface $res = GoodsActivity::query()->with('store')->where('id',$goodsId)->first(); return $res; } + + public function cacheRecord($goodsId, $num, $userId) + { + + $goods = GoodsActivity::query()->select('time_limit_days', 'time_limit_num') + ->where('id', $goodsId) + ->first(); + + $ssdbKey = SsdbKeys::ACTIVITY_GOODS_BUY_RECORD.$userId.'_'.$goodsId; + + $expireTime = 0; + if ($goods->time_limit_days <= 1) { + $expireTime += strtotime(date('Y-m-d 23:59:59')) - time(); + } + $expireTime += ($goods->time_limit_days-1) *86400; + + $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class); + + if (!$ssdb->exec('exists', $ssdbKey)) { + $ssdb->exec('set', $ssdbKey, $num); + $ssdb->exec('expire', $ssdbKey, $expireTime); + } else { + $ssdb->exec('incr', $ssdbKey, $num); + } + + } + + /** + * 统计订单中活动商品的数量,并校验 + * @param $orderGoods + * @param int $limitNum + * @return bool + */ + public function checkOrderActivityCount($orderGoods, $limitNum=1) + { + + $sourceGoods = GoodsActivity::query() + ->whereIn('id', array_values(array_column($orderGoods, 'goods_id'))) + ->get()->toArray(); + + $limitNums = [ + ActivityType::FLASH_SALE => 1, + ActivityType::GROUP_BUY => 1, + ActivityType::NEW_PRODUCT => 1, + ]; + + $buyNum = 0; + foreach ($sourceGoods as $key => &$goods) { + if ($buyNum >= $limitNums[$goods['type']]) { + return false; + } + $buyNum++; + } + + return true; + } } \ No newline at end of file diff --git a/app/Service/v3/Implementations/GoodsService.php b/app/Service/v3/Implementations/GoodsService.php index 455e678..1ed75e7 100644 --- a/app/Service/v3/Implementations/GoodsService.php +++ b/app/Service/v3/Implementations/GoodsService.php @@ -2,6 +2,7 @@ namespace App\Service\v3\Implementations; +use App\Constants\v3\ErrorCode; use App\Service\v3\Interfaces\GoodsServiceInterface; use Hyperf\DbConnection\Db; use App\Model\v3\Goods; @@ -19,19 +20,19 @@ class GoodsService implements GoodsServiceInterface public function check($goodsId,$num = 1) { $data = Goods::query()->with('store')->where('id', $goodsId)->first(); - if($data->store->is_rest != Store::IS_OPEN_YES){ - return '店铺已休息'; + if($data->store->is_rest == 1){ + return ErrorCode::GOODS_ON_SALE_NO; } if($data->on_sale == 0 || !is_null($data->deleted_at)){ - return '商品已下架'; + return ErrorCode::GOODS_ON_SALE_NO; } if($data->is_infinite != 1 && $data->inventory < $num){ - return '库存不足'; + return ErrorCode::GOODS_INVENTORY_ERROR; } - return ''; + return true; } public function undo() diff --git a/app/Service/v3/Implementations/OrderOnlineService.php b/app/Service/v3/Implementations/OrderOnlineService.php index fa41e68..4493eb5 100644 --- a/app/Service/v3/Implementations/OrderOnlineService.php +++ b/app/Service/v3/Implementations/OrderOnlineService.php @@ -2,18 +2,29 @@ namespace App\Service\v3\Implementations; -use App\Constants\LogLabel; +use App\Commons\Log; +use App\Constants\v3\ErrorCode; +use App\Constants\v3\LogLabel; +use App\Constants\v3\OrderState; use App\Constants\v3\OrderType; -use App\Model\CouponRec; -use App\Model\CouponUserUse; -use App\Model\Goods; -use App\Model\OrderGoods; -use App\Model\SpecCombination; +use App\Exception\ErrorCodeException; +use App\Model\v3\Coupon; +use App\Model\v3\CouponRec; +use App\Model\v3\CouponUse; +use App\Model\v3\Goods; +use App\Model\v3\GoodsActivity; use App\Model\v3\Order; +use App\Model\v3\OrderGoods; use App\Model\v3\OrderMain; use App\Model\v3\ShoppingCart; +use App\Model\v3\Store; use App\Model\v3\UserAddress; +use App\Service\v3\Interfaces\CouponRecServiceInterface; +use App\Service\v3\Interfaces\CouponServiceInterface; use App\Service\v3\Interfaces\DeliveryMoneyServiceInterface; +use App\Service\v3\Interfaces\GoodsActivityServiceInterface; +use App\Service\v3\Interfaces\GoodsServiceInterface; +use App\Service\v3\Interfaces\PaymentServiceInterface; use Hyperf\DbConnection\Db; use Hyperf\Di\Annotation\Inject; use App\Service\v3\Interfaces\OrderOnlineServiceInterface; @@ -23,354 +34,272 @@ use Hyperf\Utils\ApplicationContext; class OrderOnlineService implements OrderOnlineServiceInterface { + /** + * @Inject + * @var Log + */ + protected $log; + /** * @Inject * @var DeliveryMoneyServiceInterface */ protected $deliveryService; + /** + * @Inject + * @var CouponRecServiceInterface + */ + protected $couponRecService; + + /** + * @Inject + * @var CouponServiceInterface + */ + protected $couponService; + + /** + * @Inject + * @var GoodsActivityServiceInterface + */ + protected $goodsActivityService; + + /** + * @Inject + * @var GoodsServiceInterface + */ + protected $goodsService; + + /** + * @Inject + * @var PaymentServiceInterface + */ + protected $paymentService; + /** * 下单 * @param $marketId * @param $userId * @param $userAddrId - * @param $cartIds + * @param $storeList * @param $totalMoney * @param string $deliveryTimeNote + * @param int $serviceMoney * @param null $receiveCouponIds - * @return string + * @param string $plat + * @return array[] */ - public function do($marketId, $userId, $userAddrId, $cartIds, $totalMoney, $deliveryTimeNote='尽快送达', $receiveCouponIds=null){ - - bcscale(6); - - // 用户收货地址 - $userAddr = UserAddress::query()->find($userAddrId); - // 用户购物车数据 - $carts = ShoppingCart::query()->whereIn('id', $cartIds)->where(['market_id' => $marketId])->get(); - // 优惠券数据 - $couponRec = CouponRec::query()->whereIn('id', $receiveCouponIds); - - // 获取配送费用 - $deliveryAmount = $this->deliveryService->do($userAddr->lat, $userAddr->lng); - - // 处理购物车数据,计算订单金额、子订单数据处理等 - $totalAmount = bcadd((string)$deliveryAmount, 0); - $orderAmount = 0; - $orderChildren = []; - foreach ($carts as $key => $cart) { - // 查个商品 - $goods = Goods::query()->select('price')->find($cart->goods_id); - $goodsAmount = bcmul((string)$goods->price, (string)$cart->num); - - // 子订单 - $orderChildren[$cart->store_id]['user_id'] = $cart->user_id; - if (!isset($orderChildren[$cart->store_id]['money'])) { - $orderChildren[$cart->store_id]['money'] = 0; - } - $orderChildren[$cart->store_id]['money'] = bcadd((string)$orderChildren[$cart->store_id]['money'], (string)$goodsAmount); - $totalAmount = bcadd((string)$totalAmount, (string)$goodsAmount); - } + public function do($marketId, $userId, $userAddrId, $storeList, $totalMoney, $deliveryTimeNote='尽快送达', $serviceMoney=0, $receiveCouponIds=null, $plat=''){ - // 获取分布式全局ID - $generator = ApplicationContext::getContainer()->get(IdGeneratorInterface::class); - $global_order_id = $generator->generate(); - - $dataMain = [ - 'market_id' => $marketId, - 'order_num' => $global_order_id, - 'global_order_id' => $global_order_id, - 'user_id' => $userId, - 'type' => OrderType::ONLINE, - 'money' => $totalAmount, - 'total_money' => '', - 'services_money' => '', - 'coupon_money' => '', - 'delivery_money' => '', - 'state' => '', - 'pay_time' => '', - 'receive_time' => '', - 'delivery_time' => '', - 'complete_time' => '', - 'cancel_time' => '', - 'refund_time' => '', - 'tel' => '', - 'address' => '', - 'area' => '', - 'lat' => '', - 'lng' => '', - 'name' => '', - 'print_num' => '', - 'plat' => '', - 'refuse_refund_note' => '', - 'delivery_time_note' => '', - 'total_refund_note' => '', - 'note' => '', - 'created_at' => '', - 'updated_at' => '', - 'deleted_at' => '', - ]; - - return ['data_main' => $dataMain]; - $dataMain = $data; - - Db::beginTransaction(); + Db::beginTransaction(); try { - // TODO 这个字段后续可能不用了,之前由达达订单号从前端传上来 - $dataMain['order_num'] = 'o'.date('YmdHis').mt_rand(1000,9999); - - // 计算当前订单可用红包优惠金额 - $couponMoney = 0; - $receiveCouponIds = []; - if (isset($data['receive_coupon_ids'])&&$data['receive_coupon_ids']) { - $receiveCouponIds = explode(',', str_replace(',',',',$data['receive_coupon_ids'])); - $couponMoney = $this->getCouponAmount($receiveCouponIds, $data['money'], $data['user_id'], $data['market_id']); - } - $dataMain['yhq_money2'] = $couponMoney; - - // 获取分布式全局ID - $generator = ApplicationContext::getContainer()->get(IdGeneratorInterface::class); - $dataMain['global_order_id'] = $generator->generate(); - - // 店铺IDs - $dataMain['store_ids'] = ''; - $storeList = json_decode(html_entity_decode($data['store_list']), true); - if (!is_array($storeList)||empty($storeList)) { - Db::rollBack(); - return '订单中商品不存在或已失效'; - } - - // 获取商户IDs - foreach ($storeList as &$item) { - $dataMain['store_ids'] .= empty($dataMain['store_ids']) ? $item['store_id'] : ','.$item['store_id']; - } - - // 主订单插入数据 $currentTime = time(); - $dataMain['time'] = date('Y-m-d H:i:s', $currentTime); - $dataMain['time_add'] = $currentTime; - $dataMain['pay_time'] = ''; - $dataMain['state'] = \App\Model\OrderMain::ORDER_STATE_UNPAY; - $dataMain['code'] = $dataMain['global_order_id']; - $dataMain['jj_note'] = ''; - - // 主订单模型保存 - $orderMain = OrderMain::create($dataMain); - $orderMainId = $orderMain->id; - - // 统计订单中所有店铺当日订单数,做店铺订单序号 - $countsArr = \App\Model\Order::query() - ->selectRaw('store_id, COUNT(*) AS count') - ->whereIn('store_id', explode(',', $dataMain['store_ids'])) - ->where(['type' => OrderMain::ORDER_TYPE_ONLINE]) - ->whereBetween('time', [date('Y-m-d 00:00:00'), date('Y-m-d 23:59:59')]) - ->groupBy('store_id') - ->get() - ->toArray(); - - $storeOrderCounts = []; - foreach ($countsArr as $key => &$row) { - $storeOrderCounts[$row['store_id']] = $row['count']; - } + bcscale(6); + // 用户收货地址 + $userAddr = UserAddress::query()->find($userAddrId); + // 获取配送费用 + $deliveryAmount = $this->deliveryService->do($userAddr->lat, $userAddr->lng); + + // 处理购物车数据,计算订单金额、子订单数据处理等 + $totalAmount = 0; # 实付金额 + $orderAmount = 0; # 订单金额 + $dataMain = []; # 主订单 + $dataChildren = []; # 子订单 + $dataOrderGoods = []; # 订单商品 + $storeTypeIds = []; # 订单中的商户类型,用于校验红包 + + foreach ($storeList as $key => &$storeItem) { + + $storeId = $storeItem->store_id; + + // 子订单金额 + $subAmount = 0; + + // 店铺分类 + $storeType = Store::query()->where(['id' => $storeId])->value('category_id'); + $storeTypeIds[] = (string)$storeType; + // 店铺今天的订单数 + $count = Order::query() + ->where(['store_id' => $storeId]) + ->whereBetween('created_at', [strtotime(date('Y-m-d 00:00:00')), strtotime(date('Y-m-d 23:59:59'))]) + ->count(); + + // 用户购物车数据 + $cartIds = explode(',', $storeItem->cart_ids); + $carts = ShoppingCart::query()->whereIn('id', $cartIds)->where(['market_id' => $marketId])->get(); + foreach ($carts as $k => &$cart) { + + // 查个商品 + $goods = []; + if ($cart->activity_type == 1) { + $goods = Goods::query()->lockForUpdate()->find($cart->goods_id); + $check = $this->goodsService->check($goods->id, $cart->num); + if (true !== $check) { + throw new ErrorCodeException($check, '[商品失效]'.$cart->goods_id); + } + } elseif ($cart->activity_type == 2) { + $goods = GoodsActivity::query()->lockForUpdate()->find($cart->goods_id); + $check = $this->goodsActivityService->check($goods->id, $cart->num, $userId); + if (true !== $check) { + throw new ErrorCodeException($check, '[商品失效]'.$cart->goods_id); + } - // 循环处理订单总额、子订单总额、商品、商户订单等信息 - $orderAmountTotal = 0; # 总订单金额 - $orderGoods = []; - foreach ($storeList as $key => &$item) { - - // 子订单数据处理 - $dataChild = [ - 'uniacid' => $data['uniacid'], - 'order_num' => 's'.date('YmdHis', time()) . rand(1111, 9999), - 'user_id' => $orderMain->user_id, - 'store_id' => $item['store_id'], - 'order_main_id' => $orderMainId, - 'state' => OrderMain::ORDER_STATE_UNPAY, - 'tel' => $orderMain->tel, - 'name' => $orderMain->name, - 'address' => $orderMain->address, - 'area' => $orderMain->area, - 'time' => date("Y-m-d H:i:s"), - 'note' => $item['note'] ?? '', - 'delivery_time' => $orderMain->delivery_time, - 'type' => $orderMain->type, - 'lat' => $orderMain->lat, - 'lng' => $orderMain->lng, - 'pay_type' => $orderMain->pay_type, - 'order_type' => $orderMain->order_type, - 'money' => floatval($item['subtotal']), - 'box_money' => floatval($item['box_money']), - 'mj_money' => floatval($item['mj_money']), - 'yhq_money' => floatval($item['yhq_money']), - 'yhq_money2' => floatval($item['yhq_money2']), - 'zk_money' => floatval($item['zk_money']), - 'coupon_id' => $item['coupon_id'], - 'coupon_id2' => $item['coupon_id2'], - 'xyh_money' => floatval($item['xyh_money']), - 'oid' => (isset($storeOrderCounts[$item['store_id']]) ? $item['store_id'] : 0) + 1, - 'time_add' => date("Y-m-d H:i:s"), - 'jj_note' => '', - 'form_id' => '', - 'form_id2' => '', - 'code' => '', - ]; + if ($goods->can_use_coupon!=1 && $receiveCouponIds) { + throw new ErrorCodeException(ErrorCode::GOODS_ACTIVITY_CANNOT_USE_COUPON, '[商品失效]'.$cart->goods_id); + } + } - $orderChildId = Order::query()->insertGetId($dataChild); + if (empty($goods)) { + throw new ErrorCodeException(ErrorCode::ORDER_GOODS_NOT_AVAILABLE); + } - // 子订单内商品处理 - $goodsAmountTotal = 0; + // 库存判断 + if ($goods->is_infinite !=1 && $goods->inventory < $cart->num) { + throw new ErrorCodeException(ErrorCode::ORDER_GOODS_INVENTORY_LIMIT); + } - if (!is_array($item['good_list'])||empty($item['good_list'])) { - Db::rollBack(); - return '订单商品异常'; - } - foreach ($item['good_list'] as &$goods) { - $goodsAmount = bcadd(floatval($goods['money']), floatval($goods['box_money'])); - $goodsAmount = bcmul($goodsAmount, $goods['num']); - $goodsAmountTotal = bcadd($goodsAmountTotal, $goodsAmount); - - $orderGoods[$goods['id']] = $goods; - $orderGoods[$goods['id']]['uniacid'] = $data['uniacid']; - $orderGoods[$goods['id']]['order_id'] = $orderChildId; - $orderGoods[$goods['id']]['user_id'] = $dataMain['user_id']; - $orderGoods[$goods['id']]['store_id'] = $item['store_id']; + // 算金额 + $goodsAmount = bcmul((string)$goods->price, (string)$cart->num); # 当前商品的金额 + $subAmount = bcadd((string)$subAmount, (string)$goodsAmount); # 当前店铺子订单的金额 + + // 订单商品数据 + $dataOrderGoods[$storeId][] = [ + 'order_id' => 0, + 'goods_id' => $cart->goods_id, + 'activity_type' => $cart->activity_type, + 'number' => $cart->num, + 'price' => $goods->price, + 'original_price' => $goods->original_price, + 'vip_price' => $goods->vip_price, + 'name' => $goods->name, + 'goods_unit' => $goods->goods_unit, + 'cover_img' => $goods->cover_img, + 'spec' => $goods->spec, + ]; } - // 子订单优惠总额 - $discountAmountTotal = bcadd($dataChild['mj_money'], $dataChild['yhq_money']); - $discountAmountTotal = bcadd($discountAmountTotal, $dataChild['yhq_money2']); - $discountAmountTotal = bcadd($discountAmountTotal, $dataChild['zk_money']); - $discountAmountTotal = bcadd($discountAmountTotal, $dataChild['xyh_money']); - - $goodsAmountTotal = bcsub($goodsAmountTotal, $discountAmountTotal, 2); - $orderAmountTotal = bcadd($orderAmountTotal, $goodsAmountTotal, 2); - - // 校验子订单金额 - if ($goodsAmountTotal != $dataChild['money']) { - Db::rollBack(); - return '店铺订单总金额错误'; - } + // 子订单数据 + $dataChildren[] = [ + 'order_main_id' => 0, + 'user_id' => $userId, + 'store_id' => $storeId, + 'money' => bcadd((string)$subAmount, '0', 2), + 'oid' => $count + 1, + 'order_num' => date('YmdHis').mt_rand(1000, 9999), + 'note' => $storeItem->note + ]; + // 订单金额 + $orderAmount = bcadd((string)$orderAmount, (string)$subAmount); } - // 校验库存 - foreach ($orderGoods as $Key => &$goodsItem) { - - $goodsItem['combination_id'] = intval($goodsItem['combination_id']); - - // 存在规格,则去规格处查库存 - $goods = []; - if ($goodsItem['combination_id'] > 0) { - - $combination = SpecCombination::query() - ->select(['good_id AS id', 'number AS inventory']) - ->where(['id' => $goodsItem['combination_id']]) - ->first() - ->toArray(); - - $goods = Goods::query() - ->select(['id', 'name', 'is_max']) - ->where(['id' => $combination['id']]) - ->first() - ->toArray(); - $goods['inventory'] = $combination['inventory']; - - } else { + // 优惠券的使用 + $couponMoney = 0; + // 优惠券数据 + $couponRec = CouponRec::query()->lockForUpdate()->whereIn('id', $receiveCouponIds)->get()->toArray(); + if (!empty($couponRec)) { + $couponsCanUse = $this->couponRecService->allForOrderOlAvailable($totalAmount, $userId, $marketId, 2, $storeTypeIds); + $couponCanUseIds = array_column($couponsCanUse, 'id'); + $couponCanUseIds = array_intersect($couponCanUseIds, $receiveCouponIds); + $couponCannotUseIds = array_diff($receiveCouponIds, $couponCanUseIds); + + if (empty($couponCanUseIds)||!empty($couponCannotUseIds)) { + throw new ErrorCodeException(ErrorCode::COUPON_NOT_AVAILABLE); + } - $goods = Goods::query() - ->select(['id', 'name', 'is_max', 'inventory']) - ->where(['id' => $goodsItem['good_id']]) - ->first() - ->toArray(); + // 计算红包折扣金额 + foreach ($couponsCanUse as $key => $coupon) { + if (!in_array($coupon->id, $receiveCouponIds)) { + continue; + } + if ($coupon->discount_type == Coupon::DISCOUNT_TYPE_CASH) { + $couponMoney = bcadd($couponMoney, $coupon->discounts, 2); + } elseif ($coupon->discount_type == Coupon::DISCOUNT_TYPE_RATE) { + $discountRate = bcdiv($coupon->discounts,10); + $discountRate = bcsub(1,$discountRate); + $discountMoney = bcmul($orderAmount, $discountRate); + $couponMoney = bcadd($couponMoney, $discountMoney, 2); + } } + } - if (!$goods) { - Db::rollBack(); - return '缺少商品'; - } + // 获取分布式全局ID + $generator = ApplicationContext::getContainer()->get(IdGeneratorInterface::class); + $global_order_id = $generator->generate(); - if($goodsItem['num'] > $goods['inventory'] && $goods['is_max'] != Goods::INVENTORY_NOLIMIT){ - Db::rollBack(); - return '商品 '.$goods->name.' 库存不足!'; - } + $orderAmount = bcadd((string)$orderAmount, '0', 2); + $totalAmount = bcadd((string)$totalAmount, (string)$orderAmount); + $totalAmount = bcadd((string)$totalAmount, (string)$deliveryAmount); + $totalAmount = bcadd((string)$totalAmount, (string)$serviceMoney); + $totalAmount = bcsub((string)$totalAmount, (string)$couponMoney, 2); + // 校验订单总金额 + if ($totalAmount != $totalMoney) { + throw new ErrorCodeException(ErrorCode::ORDER_TOTAL_AMOUNT_ERROR); } - // 校验总订单金额 - $deliveryAmount = 0; # 配送费用 - if($dataMain['order_type'] == OrderMain::ORDER_TYPE_ONLINE){ - $deliveryAmount = $dataMain['dada_fee']; - } + $dataMain = [ + 'market_id' => $marketId, + 'order_num' => $global_order_id, + 'global_order_id' => $global_order_id, + 'user_id' => $userId, + 'type' => OrderType::ONLINE, + 'money' => $totalAmount, + 'total_money' => $orderAmount, + 'services_money' => $serviceMoney, + 'coupon_money' => $couponMoney, + 'delivery_money' => $deliveryAmount, + 'state' => OrderState::UNPAID, + 'tel' => $userAddr->tel, + 'address' => $userAddr->address.$userAddr->doorplate, + 'lat' => $userAddr->lat, + 'lng' => $userAddr->lng, + 'name' => $userAddr->user_name, + 'plat' => $plat, + 'delivery_time_note' => $deliveryTimeNote + ]; + + // 生成主订单 + $orderMain = OrderMain::create($dataMain); + $orderMainId = $orderMain->id; - $orderAmountTotal = bcadd($orderAmountTotal, $deliveryAmount); - # 总订单优惠总额 - $discountAmountTotal = bcadd($dataMain['mj_money'], $dataMain['yhq_money']); - $discountAmountTotal = bcadd($discountAmountTotal, $dataMain['yhq_money2']); - $discountAmountTotal = bcadd($discountAmountTotal, $dataMain['zk_money']); - $discountAmountTotal = bcadd($discountAmountTotal, $dataMain['xyh_money']); - $orderAmountTotal = bcsub($orderAmountTotal, $discountAmountTotal, 2); - - if ($orderAmountTotal != bcsub(bcadd($dataMain['money'], $deliveryAmount), $discountAmountTotal, 2)) { - Db::rollBack(); - return '订单总金额错误'; - } + // 处理子订单 + foreach ($dataChildren as $key => &$child) { + $child['order_main_id'] = $orderMainId; + $orderChildId = Order::query()->insertGetId($child); - // 添加订单商品 - $tempGoods = $orderGoods; - $orderGoods = []; - foreach ($tempGoods as $key => &$value) { - $goodsTemp['good_id'] = $value['good_id']; - $goodsTemp['img'] = $value['logo']; - $goodsTemp['number'] = $value['num']; - $goodsTemp['order_id'] = $value['order_id']; - $goodsTemp['name'] = $value['name']; - $goodsTemp['money'] = $value['money']; - $goodsTemp['dishes_id'] = $value['dishes_id']; - $goodsTemp['spec'] = $value['spec']; - $goodsTemp['is_qg'] = $value['is_qg']; - $goodsTemp['good_unit'] = $value['good_unit']; - $goodsTemp['uniacid'] = $value['uniacid']; - $goodsTemp['combination_id'] = $value['combination_id']; - $orderGoods[] = $goodsTemp; + foreach ($dataOrderGoods[$child['store_id']] as $k => &$orderGoods) { + $orderGoods['order_id'] = $orderChildId; + } + OrderGoods::query()->insert($dataOrderGoods[$child['store_id']]); } - $addOrderGoods = OrderGoods::query()->insert($orderGoods); - if (!$addOrderGoods) { - Db::rollBack(); - return '订单商品异常'; + // 判断是否有购买多个特价商品 + $check = $this->goodsActivityService->checkOrderActivityCount($dataOrderGoods); + if(!$check){ + throw new ErrorCodeException(ErrorCode::GOODS_ACTIVITY_RESTRICT_LIMIT, '[同一订单同种类型活动商品]'.json_encode($dataOrderGoods)); } - //判断是否有购买多个特价商品 - $result = $this->purchaseLimitService->PurchaseLimit($orderGoods); - if(!$result){ - Db::rollBack(); - return '同一个订单不能购买多个特价商品'; - } - - //判断是否有购买特价商品 - $this->purchaseLimitService->ssdbPurchaseRecord($orderGoods,$data['user_id'],$dataMain['global_order_id']); - // 修改总订单金额,金额是计算来的 - // TODO 这部分其实可以结合处理优化一下,循环前后关联处理太多 - $updateOrderMain = OrderMain::query()->where(['id' => $orderMainId])->update(['money' => $orderAmountTotal, 'total_money' => $dataMain['money']]); - if (!$updateOrderMain) { - Db::rollBack(); - return '订单总金额记录失败'; + // 订单成功,做一些处理 + // 活动商品购买记录 + foreach ($dataOrderGoods as $key => &$goods) { + foreach ($goods as $k => &$goodsItem) + if ($goodsItem['activity_type'] == 2) { + $this->goodsActivityService->cacheRecord($goodsItem['goods_id'], $goodsItem['number'], $userId); + } } - // 处理红包的使用 - $canUseCoupons = CouponRec::select(['id', 'user_id', 'number', 'number_remain', 'system_coupon_user_id']) - ->whereIn('id', $receiveCouponIds) - ->get()->toArray(); - if (is_array($canUseCoupons)&&!empty($canUseCoupons)) { + // 优惠券红包使用记录 + if (is_array($couponRec)&&!empty($couponRec)) { # 使用记录、更新当前优惠券 - foreach ($canUseCoupons as $key => &$coupon) { + foreach ($couponRec as $key => &$coupon) { $couponUse = [ 'user_id' => $coupon['user_id'], 'user_receive_id' => $coupon['id'], - 'system_coupon_id' => $coupon['system_coupon_user_id'], + 'coupon_id' => $coupon['coupon_id'], 'order_main_id' => $orderMainId, 'use_time' => $currentTime, 'return_time' => 0, @@ -379,8 +308,7 @@ class OrderOnlineService implements OrderOnlineServiceInterface 'update_time' => 0, ]; - $insertRes = CouponUserUse::query()->insert($couponUse); - + $insertRes = CouponUse::query()->insert($couponUse); if ($insertRes) { $numberRemain = $coupon['number_remain'] - 1; if ($numberRemain == 0) { @@ -392,40 +320,32 @@ class OrderOnlineService implements OrderOnlineServiceInterface } $upRes = CouponRec::query()->where(['id' => $coupon['id']])->update(['number_remain' => $numberRemain, 'status' => $status]); - if (!$upRes) { Db::rollBack(); - return '优惠券使用失败'; + throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE); } - // 缓存使用记录 - $usedRes = $this->couponService->cacheTodayCouponUsed($coupon['user_id'], $coupon['system_coupon_user_id'], $coupon['id']); + $usedRes = $this->couponService->cacheTodayCouponUsed($coupon['user_id'], $coupon['coupon_id'], $coupon['id']); if (!$usedRes) { Db::rollBack(); - return '优惠券使用失败'; + throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE); } - } else { Db::rollBack(); - return '优惠券使用失败'; + throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE); } } } Db::commit(); - return $orderMainId; - - } catch (Exception $e) { - - $this->log->event( - LogLabel::ORDER_LOG, - ['message' => $e->getMessage()] - ); + // 支付 + return $this->paymentService->do($global_order_id, $totalAmount, $userId); + } catch (\Exception $e) { Db::rollBack(); - return $e->getMessage(); - + $this->log->event(LogLabel::ORDER_ONLINE_LOG, ['exception_msg' => $e->getMessage()]); + throw new ErrorCodeException(ErrorCode::ORDER_ONLINE_FAIL); } } diff --git a/app/Service/v3/Implementations/PaymentService.php b/app/Service/v3/Implementations/PaymentService.php new file mode 100644 index 0000000..724f078 --- /dev/null +++ b/app/Service/v3/Implementations/PaymentService.php @@ -0,0 +1,137 @@ +where(['state' => OrderState::UNPAID, 'global_order_id' => $globalOrderId, 'user_id' => $userId]) + ->where('created_at', '>=', (time()-900)) + ->first(); + + if (empty($orderMain)) { + throw new ErrorCodeException(ErrorCode::ORDER_NOT_AVAILABLE, '[支付订单号]'.$globalOrderId); + } + + $payMoney = bcmul((string)$orderMain->money, 100, 0); + if (env('APP_ENV') != 'prod') { + $payMoney = 1; + } + + $user = User::select('openid')->find($userId); + $result = $app->order->unify([ + 'body' => '懒族生活 - 外卖下单', + 'out_trade_no' => $orderMain->global_order_id, + 'total_fee' => $payMoney, + 'notify_url' => config('site_host') . '/wechat/notify/wxminionline', + 'trade_type' => 'JSAPI', + 'openid' => $user['openid'], + ]); + + if ($result['return_code'] == 'FAIL') { + throw new ErrorCodeException(ErrorCode::PAYMENT_FAIL, '[支付失败]'.$result['return_msg']); + } + + // 返回支付参数给前端 + $parameters = [ + 'appId' => $result['appid'], + 'timeStamp' => '' . time() . '', + 'nonceStr' => uniqid(), + 'package' => 'prepay_id=' . $result['prepay_id'], + 'signType' => 'MD5' + ]; + + $parameters['paySign'] = $this->signture($parameters, $config['key']); + + return $parameters; + + } catch (\Exception $e) { + $this->log->event(LogLabel::ORDER_PAYMENT_LOG, ['payment_exception_msg' => $e->getMessage()]); + throw new ErrorCodeException(ErrorCode::PAYMENT_FAIL, '[支付失败]'.$e->getMessage()); + } + } + + public function check() + { + // TODO: Implement check() method. + } + + public function undo() + { + // TODO: Implement undo() method. + } + + /** + * 支付参数加签 + * @param $parameters + * @param $key + * @return string + */ + private function signture($parameters, $key) + { + // 按字典序排序参数 + ksort($parameters); + + // http_query + $queryParams = $this->http_query($parameters); + + // 加入KEY + $queryParams = $queryParams . "&key=" . $key; + + // MD5加密 + $queryParams = md5($queryParams); + + // 字符转为大写 + return strtoupper($queryParams); + } + + /** + * 参数转为http query字串 + * @param $parameters + * @return string + */ + private function http_query($parameters) { + + $http_query = []; + foreach ($parameters as $key => $value) { + $http_query[] = $key.'='.$value; + } + + return implode('&', $http_query); + } +} \ No newline at end of file diff --git a/app/Service/v3/Implementations/ShopCartUpdateService.php b/app/Service/v3/Implementations/ShopCartUpdateService.php index 0400c47..2ed2011 100644 --- a/app/Service/v3/Implementations/ShopCartUpdateService.php +++ b/app/Service/v3/Implementations/ShopCartUpdateService.php @@ -16,10 +16,10 @@ class ShopCartUpdateService implements ShopCartUpdateServiceInterface throw new ErrorCodeException(ErrorCode::GOODS_INVENTORY_ERROR); break; case 2000: - throw new ErrorCodeException(ErrorCode::PURCHASE_LIMIT_ERROR); + throw new ErrorCodeException(ErrorCode::GOODS_RESTRICT_LIMIT); break; case 3000: - throw new ErrorCodeException(ErrorCode::SPERCIAL_OFFER_GOODS_ERROR); + throw new ErrorCodeException(ErrorCode::GOODS_ACTIVITY_BUY); break; default: return true; diff --git a/app/Service/v3/Interfaces/CouponRecServiceInterface.php b/app/Service/v3/Interfaces/CouponRecServiceInterface.php new file mode 100644 index 0000000..1931874 --- /dev/null +++ b/app/Service/v3/Interfaces/CouponRecServiceInterface.php @@ -0,0 +1,11 @@ + \App\Service\v3\Implementations\GoodsActivityService::class, \App\Service\v3\Interfaces\DeliveryMoneyServiceInterface::class => \App\Service\v3\Implementations\DeliveryMoneyService::class, \App\Service\v3\Interfaces\RevenueListServiceInterface::class => \App\Service\v3\Implementations\RevenueListService::class, + \App\Service\v3\Interfaces\CouponRecServiceInterface::class => \App\Service\v3\Implementations\CouponRecService::class, + \App\Service\v3\Interfaces\PaymentServiceInterface::class => \App\Service\v3\Implementations\PaymentService::class, \App\Service\v3\Interfaces\WithdrawalListServiceInterface::class => \App\Service\v3\Implementations\WithdrawalListService::class, ]; diff --git a/config/routes.php b/config/routes.php index aa393d1..4acfd98 100644 --- a/config/routes.php +++ b/config/routes.php @@ -117,4 +117,5 @@ Router::addGroup('/v3/', function () { Router::post('balanceStatement/getRevenueListByUser', 'App\Controller\v3\BalanceStatementController@getRevenueListByUser'); Router::post('orderOnline/add', 'App\Controller\v3\OrderOnlineController@add'); Router::post('store/storeWithdrawalList', 'App\Controller\v3\BalanceStatementController@getWithdrawalListByStore'); + Router::post('payment/wechatpayOnline', 'App\Controller\v3\PaymentController@wechatpayOnline'); },['middleware' => [\App\Middleware\Auth\ApiMiddleware::class, \App\Middleware\Auth\UserMiddleware::class]]); \ No newline at end of file