Files
hyperf_service/app/Service/ServiceTrait/Api/OrderTrait.php
2025-02-19 18:06:14 +08:00

372 lines
12 KiB
PHP

<?php
/**
* This service file is part of item.
*
* @author ctexthuang
* @contact ctexthuang@qq.com
*/
declare(strict_types=1);
namespace App\Service\ServiceTrait\Api;
use App\Amqp\Producer\OrderGoodStockProducer;
use App\Cache\Redis\Api\ApiRedisKey;
use App\Cache\Redis\Api\SiteCache;
use App\Cache\Redis\RedisCache;
use App\Constants\ApiCode;
use App\Constants\Common\GoodCode;
use App\Constants\Common\OrderCode;
use App\Constants\Common\PayCode;
use App\Constants\ConfigCode;
use App\Exception\ErrException;
use App\Model\Order;
use Exception;
use Hyperf\Amqp\Producer;
use Hyperf\Context\ApplicationContext;
use Hyperf\Di\Annotation\Inject;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
trait OrderTrait
{
/**
* @var SiteCache
*/
#[Inject]
protected SiteCache $siteCache;
/**
* @var RedisCache $redis
*/
#[Inject]
protected RedisCache $redis;
/**
* 生成订单号
* @param int $type
* @param int $userId
* @return string
*/
protected function generateOrderNo(int $type,int $userId): string
{
return match ($type) {
OrderCode::ORDER_TYPE_GOOD => OrderCode::ORDER_TYPE_GOOD_PREFIX . '_' .date("YmdHis") . $userId . mt_rand(10000000, 99999999),
OrderCode::ORDER_TYPE_BALANCE => OrderCode::ORDER_TYPE_BALANCE_PREFIX. '_' .date("YmdHis"). $userId. mt_rand(10000000, 99999999),
};
}
/**
* 生成购物车数据
* @param array $data
* @return void
*/
protected function buildCartData(array $data): void
{
$copies = 0;
foreach ($data as $oneCopies) {
$one = [];
foreach ($oneCopies as $oneGood) {
$this->cartFirstData[$oneGood] = ($this->cartFirstData[$oneGood] ?? 0) + 1;
$one[$oneGood] = ($one[$oneGood] ?? 0) + 1;
}
$this->cartSecondData[] = $one;
$copies++;
}
$this->copies = $copies;
}
/**
* 检测商品
* @return void
*/
protected function checkGood(): void
{
foreach ($this->cartFirstData as $key => $one) {
if (in_array($key, $this->goodIds)) continue;
throw new ErrException('商品不存在',ApiCode::ORDER_GOOD_IN_EXISTENCE);
}
}
/**
* 检测库存
* @return void
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
protected function checkStock(): void
{
foreach ($this->cartFirstData as $key => $one) {
if (($this->redis->zScore($this->stockKey,$key) ?? 0) >= $one) continue;
throw new ErrException('商品库存不足',ApiCode::ORDER_GOOD_INSUFFICIENT_STOCK);
}
}
/**
* 检测地点
* @param int $siteId
* @return int
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
protected function checkSite(int $siteId): int
{
$siteInfo = $this->siteCache->getSiteInfo($siteId);
if (empty($siteInfo)) throw new ErrException('该地点暂时不支持点餐');
$kitchenId = (int)($siteInfo['kitchen_id'] ?? 0);
if ($kitchenId <= 0) throw new ErrException('该地点暂时不支持点餐');
$this->orderRes['site_id'] = $siteId;
$this->orderRes['site_info'] = $siteInfo;
return $kitchenId;
}
/**
* 获取商品信息
* @param int $kitchenId
* @return void
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
protected function getGoodInfo(int $kitchenId): void
{
$this->stockKey = ApiRedisKey::goodStockKey($this->cycleId,$kitchenId);
$mealGoodKey = ApiRedisKey::mealGoodListKey($this->cycleId,$kitchenId);
$optionalGoodKey = ApiRedisKey::optionalGoodListKey($this->cycleId,$kitchenId);
$mealGood = $this->redis->get($mealGoodKey);
$optionalGood = $this->redis->get($optionalGoodKey);
if (empty($mealGood) || empty($optionalGood)) throw new ErrException('商品不存在');
if (!$this->redis->exists($this->stockKey)) throw new ErrException('库存不足');
$mealGood = json_decode($mealGood, true);
$optionalGood = json_decode($optionalGood, true);
$skuArr = [];
foreach ($mealGood as $one){
$skuArr = array_merge($skuArr,$one['sku_list']);
}
foreach ($optionalGood as $one){
$skuArr = array_merge($skuArr,$one['sku_list']);
}
$this->skuArr = array_column($skuArr,null,'id');
$this->goodIds = array_column($skuArr,'id');
unset($skuArr);
}
/**
* @return int
*/
protected function getAutoCouponId(): int
{
return 0;
}
/**
* 计算价格
* @return void
*/
protected function computePrice(): void
{
$this->orderRes['good_ids'] = $this->cartSecondData;
foreach ($this->cartSecondData as $oneCopies) {
$oneCopiesTotalPrice = '0.00';
$copiesType = 1;
$oneCopiesGoodInfo = [];
foreach ($oneCopies as $oneGood) {
if (empty($oneCopiesGoodInfo[$oneGood])) {
$oneCopiesGoodInfo[$oneGood] = [
'num' => 1,
'good_name' => '1',
'good_url' => '1',
'unit_price' => $this->skuArr[$oneGood]['price'],
'type' => $this->skuArr[$oneGood]['type'],
];
} else {
$oneCopiesGoodInfo[$oneGood]['num'] += 1;
}
$oneCopiesTotalPrice = bcadd($oneCopiesTotalPrice, $this->skuArr[$oneGood]['price'],2);
if ($copiesType == 1 && $this->skuArr[$oneGood]['type'] == GoodCode::SPU_TYPE_MEAL) {
$copiesType = 2;
}
}
$this->orderRes['good'][] = [
'good_ids' => $oneCopies,
'good_info' => $oneCopiesGoodInfo,
'price' => $oneCopiesTotalPrice,
];
if ($copiesType == 1) {
$this->orderRes['optional_copies']++;
} else {
$this->orderRes['meal_copies']++;
}
$this->orderRes['total_good_price'] = bcadd($this->orderRes['total_good_price'],$oneCopiesTotalPrice,2);
}
}
/**
* 计算服务费
* @return void
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
protected function computeSundryPrice(): void
{
$this->orderRes['sundry_num'] = match ($this->configCache->getConfigValue(ConfigCode::SUNDRY_PRICE_COMPUTE_TYPE))
{
1 => $this->orderRes['optional_copies'],
2 => $this->orderRes['meal_copies'],
3 => $this->copies,
};
$this->orderRes['sundry_price'] = $this->configCache->getConfigValue(ConfigCode::SUNDRY_UNIT_PRICE);
$this->orderRes['total_sundry_price'] = bcmul($this->orderRes['sundry_price'],$this->orderRes['sundry_num'],2);
}
/**
* 计算优惠
* @return void
*/
protected function computeFavorable(): void
{
if ($this->couponId <= 0 && $this->isAutoSelectCoupon == 1) {
$this->couponId = $this->getAutoCouponId();
}
if ($this->couponId <= 0) {
$this->orderRes['coupon_id'] = 0;
$this->orderRes['coupon'] = [];
$this->orderRes['favorable_good_price'] = '0';
$this->orderRes['favorable_sundry_price'] = '0';
return;
}
$couponInfo = []; // todo 优惠券信息
$this->orderRes['coupon_id'] = $this->couponId;
$this->orderRes['coupon'] = $couponInfo;
//todo 优惠计算
$this->orderRes['favorable_good_price'] = '1.00';
$this->orderRes['favorable_sundry_price'] = '1.00';
}
/**
* 计算最终价格
* @return void
*/
protected function computeFinallyPrice(): void
{
$this->orderRes['good_after_discount_price'] = bcsub($this->orderRes['total_good_price'],$this->orderRes['favorable_good_price'],2);
$this->orderRes['sundry_after_discount_price'] = bcsub($this->orderRes['total_sundry_price'],$this->orderRes['favorable_sundry_price'],2);
$this->orderRes['total_price'] = bcadd($this->orderRes['total_good_price'],$this->orderRes['total_sundry_price'],2);
$this->orderRes['actual_price'] = bcadd($this->orderRes['good_after_discount_price'],$this->orderRes['sundry_after_discount_price'],2);
}
/**
* @param int $orderId
* @param int $orderStatus
* @return void
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
protected function sendStockMq(int $orderId,int $orderStatus): void
{
$message = new OrderGoodStockProducer([
'order_id' => $orderId,
'type' => $orderStatus
]);
$producer = ApplicationContext::getContainer()->get(Producer::class);
$producer->produce($message);
}
/**
* @var Order
*/
#[Inject]
protected Order $orderModel;
/**
* @return void
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
protected function checkGoodOrder(): void
{
$this->orderInfo = $this->orderModel->getInfoByOrderSno($this->orderNo);
if (empty($this->orderInfo)) {
$this->log->debug(__CLASS__.':订单不存在,订单号:'.$this->orderNo);
throw new ErrException('订单不存在');
}
if ($this->orderInfo->status != OrderCode::WAIT_PAY) {
$this->log->debug(__CLASS__.':订单已充值成功或取消,订单信息:'.json_encode($this->orderInfo->toArray()));
throw new ErrException('订单已充值成功');
}
if ($this->orderInfo->action != PayCode::WECHAT_PAY) {
$this->log->debug(__CLASS__.':订单充值渠道错误,订单信息:'.json_encode($this->orderInfo->toArray()));
throw new ErrException('订单充值渠道错误');
}
}
/**
* 操作微信订单
* @return void
*/
protected function manageWxOrder(): void
{
// $this->orderInfo->status = OrderCode::STATUS_PAY;
// $this->orderInfo->isAdd = 1;
// $this->orderInfo->tradeno = $this->callbackData['transaction_id'];
//// $this->orderInfo->payTime = date('Y-m-d H:i:s',strtotime($this->callbackData['time_end']));
// $this->orderInfo->payTime = strtotime($this->callbackData['success_time']);
// $this->orderInfo->jsonData = [
// 'payData' => $this->callbackData,
// 'jsonData' => $this->orderInfo->jsonData
// ];
if (!$this->orderInfo->save()) {
$this->log->debug(__CLASS__.':Function:manageWxOrder:更新充值订单的状态失败:'.$this->orderInfo->id);
throw new ErrException('更新充值订单的状态失败');
}
}
/**
* @return void
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
protected function manageGoodOrder(): void
{
try {
$this->orderInfo->status = OrderCode::PAYED;
// $this->orderInfo->pay_time =
}catch (Exception $e) {
$this->log->error(__CLASS__.':Function:manageGoodOrder:'.$e->getMessage().':orderId:'.$this->orderInfo->id);
throw new ErrException($e->getMessage());
}
}
}