fix: 修复在处理生鲜产品订单时的异常; refactor: 重构代码以优化性能和可读性; style: 代码风格调整,增加空格、格式化、修复缺失的分号等; test: 添加测试以验证新订单创建功能的正确性; docs: 更新相关文档,如README; build: 更新项目依赖或版本; ops: 更新基础设施、部署、备份和恢复等操作性组件; chore: 修改.gitignore等;
402 lines
19 KiB
PHP
402 lines
19 KiB
PHP
<?php
|
||
|
||
namespace app\api\controller;
|
||
|
||
use app\api\logic\order\CartLogic;
|
||
use app\api\logic\order\OrderLogic;
|
||
use app\common\enum\PayEnum;
|
||
use app\common\enum\YesNoEnum;
|
||
use app\common\logic\DemoPayNotifyLogic;
|
||
use app\common\logic\PaymentLogic;
|
||
use app\common\logic\PayNotifyLogic;
|
||
use app\common\model\Config;
|
||
use app\common\model\order\Cart;
|
||
use app\common\model\store_branch_product\StoreBranchProduct;
|
||
use app\common\model\store_category\StoreCategory;
|
||
use app\common\model\store_order\StoreOrder;
|
||
use app\common\model\store_order_cart_info\StoreOrderCartInfo;
|
||
use app\common\model\store_product\StoreProduct;
|
||
use app\common\model\store_product_unit\StoreProductUnit;
|
||
use app\common\model\system_store\SystemStore;
|
||
use app\common\model\user\User;
|
||
use app\common\model\user\UserAddress;
|
||
use Picqer\Barcode\BarcodeGeneratorPNG;
|
||
use support\exception\BusinessException;
|
||
use think\facade\Db;
|
||
|
||
class DemoOrderController extends BaseApiController
|
||
{
|
||
public $notNeedLogin = ['aa'];
|
||
|
||
public static $total_price;
|
||
public static $pay_price;
|
||
public static $cost;
|
||
public static $profit;
|
||
public static $store_price; //门店零售价
|
||
public static $activity_price;
|
||
public static $deduction_price;
|
||
public static $frozen_money; //返还金额
|
||
public static $fresh_price; //生鲜金额
|
||
|
||
|
||
public function aa()
|
||
{
|
||
|
||
$data = Db::name('demo_order')->where('store_id', 22)->group('times')->select();
|
||
foreach ($data as $key => $value) {
|
||
$res = Db::name('demo_order')->where('times', $value['times'])->select();
|
||
foreach ($res as $k => $v) {
|
||
$product_id = StoreBranchProduct::where('id', $v['product_id'])->value('product_id');
|
||
if (!$product_id) {
|
||
return $this->fail('商品不存在');
|
||
}
|
||
$datas = [
|
||
'uid' => $v['uid'],
|
||
'type' => 1,
|
||
'product_id' => $product_id,
|
||
'store_id' => $v['store_id'],
|
||
'cart_num' => $v['nums'],
|
||
];
|
||
CartLogic::add($datas);
|
||
}
|
||
$this->create($value['uid'],$value['store_id'],$value['times'],$value['pay_type']);
|
||
}
|
||
}
|
||
/**
|
||
* 创建订单
|
||
*/
|
||
public function create($uid,$store_id,$times,$pay_type)
|
||
{
|
||
$user = User::where('id', $uid)->find();
|
||
|
||
$cartId = Cart::where([
|
||
'uid' => $uid,
|
||
'is_pay' => 0
|
||
])->column('id');
|
||
$params['shipping_type'] = 2;
|
||
$params['store_id'] = $store_id;
|
||
$params['create_time'] = $times;
|
||
$params['pay_type'] = $pay_type;
|
||
$order = self::createOrder($cartId, 0, $user, $params);
|
||
if ($order != false) {
|
||
if ($order['pay_price'] <= 0) {
|
||
$pay_type = 3;
|
||
}
|
||
switch ($pay_type) {
|
||
case PayEnum::PURCHASE_FUNDS:
|
||
//采购款支付
|
||
DemoPayNotifyLogic::handle('purchase_funds', $order['order_id']);
|
||
OrderLogic::writeOff(['verify_code'=>$order['verify_code'],'store_id'=>$order['store_id']]);
|
||
return $this->success('采购款支付成功');
|
||
case PayEnum::BALANCE_PAY:
|
||
//余额支付
|
||
DemoPayNotifyLogic::handle('balancePay', $order['order_id']);
|
||
OrderLogic::writeOff(['verify_code'=>$order['verify_code'],'store_id'=>$order['store_id']]);
|
||
return $this->success('余额支付成功');
|
||
case PayEnum::CASH_PAY:
|
||
//现金支付
|
||
DemoPayNotifyLogic::handle('cash_pay', $order['order_id']);
|
||
return $this->success('现金支付成功');
|
||
case PayEnum::WECHAT_PAY_MINI:
|
||
//微信小程序支付
|
||
$extra['amount']['payer_total'] = bcmul($order['pay_price'], 100, 2);
|
||
$extra['transaction_id'] = time();
|
||
DemoPayNotifyLogic::handle('wechat_common', $order['order_id'], $extra);
|
||
OrderLogic::writeOff(['verify_code'=>$order['verify_code'],'store_id'=>$order['store_id']]);
|
||
return $this->success('微信小程序支付成功');
|
||
case PayEnum::WECHAT_PAY_BARCODE:
|
||
//微信条码支付
|
||
$extra['amount']['payer_total'] = bcmul($order['pay_price'], 100, 2);
|
||
$extra['transaction_id'] = time();
|
||
DemoPayNotifyLogic::handle('wechat_common', $order['order_id'], $extra);
|
||
return $this->success('微信条码支付成功');
|
||
case PayEnum::ALIPAY_BARCODE:
|
||
//支付宝条码支付
|
||
$extra['buyer_pay_amount'] = $order['pay_price'];
|
||
DemoPayNotifyLogic::handle('alipay_cashier', $order['order_id'], $extra);
|
||
return $this->success('支付宝条码支付成功');
|
||
default:
|
||
return $this->fail('支付方式错误');
|
||
}
|
||
// return $this->data(['order_id' => $order->id]);
|
||
} else {
|
||
return $this->fail(OrderLogic::getError());
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @notes 获取购物车商品信息
|
||
* @param $params
|
||
* @return array|bool
|
||
*/
|
||
static public function cartIdByOrderInfo($cartId, $addressId, $user = null, $params = [], $createOrder = 0)
|
||
{
|
||
$where = ['is_pay' => 0];
|
||
$cart_select = Cart::whereIn('id', $cartId)->where($where)->field('id,product_id,cart_num')->select()->toArray();
|
||
if (empty($cart_select)) {
|
||
throw new BusinessException('购物车为空', 3000);
|
||
}
|
||
// try {
|
||
self::$total_price = 0;
|
||
self::$pay_price = 0;
|
||
self::$cost = 0; //成本由采购价替代原成本为门店零售价
|
||
self::$profit = 0; //利润
|
||
self::$activity_price = 0; //活动减少
|
||
self::$store_price = 0; //商户价
|
||
self::$deduction_price = 0;
|
||
self::$frozen_money = 0; //返还金额
|
||
$deduction_price = 0; //抵扣金额
|
||
self::$fresh_price = 0; //生鲜金额
|
||
/** 计算价格 */
|
||
|
||
$off_activity = Config::where('name', 'off_activity')->value('value');
|
||
$field = 'id branch_product_id,store_name,image,unit,price,vip_price,cost,purchase,product_id,top_cate_id';
|
||
foreach ($cart_select as $k => $v) {
|
||
$find = StoreBranchProduct::where(['product_id' => $v['product_id'], 'store_id' => $params['store_id']])->field($field)->find();
|
||
if (!$find) {
|
||
// unset($cart_select[$k]);
|
||
// continue;
|
||
$field = 'id branch_product_id,store_name,image,unit,price,vip_price,cost,purchase, id product_id,cate_id';
|
||
$find = StoreProduct::where(['id' => $v['product_id']])->field($field)->find();
|
||
if ($find) {
|
||
$cate_id = StoreCategory::where('id', $find['cate_id'])->value('pid');
|
||
if ($cate_id > 0) {
|
||
$cate_id = StoreCategory::where('id', $cate_id)->value('pid');
|
||
if ($cate_id > 0) {
|
||
$cate_id = StoreCategory::where('id', $cate_id)->value('pid');
|
||
$find['top_cate_id'] = $cate_id;
|
||
} else {
|
||
$find['top_cate_id'] = $cate_id;
|
||
}
|
||
}
|
||
}
|
||
$cart_select[$k]['status'] = 1; //缺货标识
|
||
}
|
||
unset($cart_select[$k]['id']);
|
||
$cart_select[$k]['total_price'] = bcmul($v['cart_num'], $find['price'], 2); //订单总价
|
||
if ($off_activity == 1 || ($user != null && in_array($user['user_ship'], [4, 5, 6, 7]))) {
|
||
$price = $find['cost'];
|
||
} else {
|
||
$price = $find['price'];
|
||
}
|
||
$cart_select[$k]['price'] = $price;
|
||
$cart_select[$k]['cost'] = $find['cost'];
|
||
$cart_select[$k]['vip'] = 0;
|
||
$cart_select[$k]['unit_name'] = StoreProductUnit::where(['id' => $find['unit']])->value('name') ?? ''; //单位名称
|
||
|
||
//利润
|
||
// $cart_select[$k]['profit'] = bcmul($v['cart_num'], $onePrice, 2); //利润
|
||
$cart_select[$k]['purchase'] = bcmul($v['cart_num'], $find['purchase'], 2) ?? 0; //成本
|
||
$cart_select[$k]['pay_price'] = bcmul($v['cart_num'], $price, 2); //订单支付金额
|
||
$cart_select[$k]['store_price'] = bcmul($v['cart_num'], $find['cost'], 2) ?? 0; //商户价
|
||
$cart_select[$k]['vip_price'] = bcmul($v['cart_num'], $find['vip_price'], 2) ?? 0; //vip售价
|
||
if ($cart_select[$k]['total_price'] > $cart_select[$k]['pay_price']) {
|
||
$deduction_price = bcsub($cart_select[$k]['total_price'], $cart_select[$k]['pay_price'], 2);
|
||
$cart_select[$k]['deduction_price'] = $deduction_price; //抵扣金额
|
||
}
|
||
$cart_select[$k]['product_id'] = $find['product_id'];
|
||
$cart_select[$k]['old_cart_id'] = $v['id'];
|
||
$cart_select[$k]['cart_num'] = $v['cart_num'];
|
||
$cart_select[$k]['verify_code'] = $params['verify_code'] ?? '';
|
||
$cart_select[$k]['vip_frozen_price'] = 0;
|
||
//会员待返回金额
|
||
if ($user && $off_activity == 0) {
|
||
if ($user['user_ship'] == 4) {
|
||
//商户
|
||
$cart_select[$k]['vip_frozen_price'] = bcsub($cart_select[$k]['pay_price'], $cart_select[$k]['store_price'], 2);
|
||
} else {
|
||
//其他会员
|
||
$cart_select[$k]['vip_frozen_price'] = bcsub($cart_select[$k]['pay_price'], $cart_select[$k]['vip_price'], 2);
|
||
}
|
||
}
|
||
// d($cart_select[$k]['pay_price'],$cart_select[$k]['store_price'],$cart_select[$k]['vip_price'] );
|
||
$cartInfo = $cart_select[$k];
|
||
$cartInfo['name'] = $find['store_name'];
|
||
$cartInfo['image'] = $find['image'];
|
||
$cart_select[$k]['cart_info'] = json_encode($cartInfo);
|
||
$cart_select[$k]['branch_product_id'] = $find['branch_product_id'];
|
||
//理论上每笔都是拆分了
|
||
$cart_select[$k]['name'] = $find['store_name'];
|
||
$cart_select[$k]['imgs'] = $find['image'];
|
||
$cart_select[$k]['store_id'] = $params['store_id'] ?? 0;
|
||
$cart_select[$k]['unit_name'] = StoreProductUnit::where(['id' => $find['unit']])->value('name');
|
||
self::$total_price = bcadd(self::$total_price, $cart_select[$k]['total_price'], 2);
|
||
self::$pay_price = bcadd(self::$pay_price, $cart_select[$k]['pay_price'], 2);
|
||
self::$cost = bcadd(self::$cost, $cart_select[$k]['purchase'], 2);
|
||
self::$store_price = bcadd(self::$store_price, $cart_select[$k]['store_price'], 2); //商户价
|
||
self::$deduction_price = bcadd(self::$deduction_price, $deduction_price, 2); //抵扣金额
|
||
self::$frozen_money = bcadd(self::$frozen_money, $cart_select[$k]['vip_frozen_price'], 2); //返还金额
|
||
//计算生鲜
|
||
if ($createOrder == 1 && $find['top_cate_id'] == 15201) {
|
||
self::$fresh_price = bcadd(self::$fresh_price, $cart_select[$k]['pay_price'], 2);
|
||
}
|
||
// self::$profit = bcadd(self::$profit, $cart_select[$k]['profit'], 2);
|
||
}
|
||
//加支付方式限制
|
||
// $pay_type = isset($params['pay_type']) ? $params['pay_type'] : 0;
|
||
// if ($user && $user['user_ship'] == 1 && $pay_type != 17) {
|
||
// $pay_price = self::$pay_price;
|
||
// } else {
|
||
|
||
|
||
$pay_price = bcsub(self::$pay_price, self::$activity_price, 2); //减去活动优惠金额
|
||
//判断生鲜是否大于200
|
||
if ($createOrder == 1 && self::$fresh_price > 0) {
|
||
if (self::$pay_price < 200) {
|
||
throw new BusinessException('订单包含生鲜产品,订单金额必须大于200元,才能下单', 3000);
|
||
}
|
||
}
|
||
// }
|
||
//成本价 收益
|
||
$order = [
|
||
'create_time' => time(),
|
||
'order_id' => $params['order_id'] ?? getNewOrderId('PF'),
|
||
'total_price' => self::$total_price, //总价
|
||
'cost' => self::$cost, //成本价1-
|
||
'pay_price' => $pay_price, //后期可能有降价抵扣
|
||
'vip_price' => 0,
|
||
'total_num' => count($cart_select), //总数
|
||
'pay_type' => $params['pay_type'] ?? 0,
|
||
'reservation_time' => $params['reservation_time'] ?? null,
|
||
'cart_id' => implode(',', $cartId),
|
||
'store_id' => $params['store_id'] ?? 0,
|
||
'shipping_type' => $params['shipping_type'] ?? 2, //配送方式 1=快递 ,2=门店自提
|
||
'activity' => '减免',
|
||
'activity_price' => self::$activity_price,
|
||
'activities' => self::$activity_price > 0 ? 1 : 0,
|
||
'deduction_price' => self::$deduction_price,
|
||
'frozen_money' => self::$frozen_money, //返还金额(活动关闭得时候有)
|
||
'source' => 0,
|
||
'is_storage' => $params['is_storage'] ?? 0,
|
||
];
|
||
$order['default_delivery'] = 0;
|
||
if ($params['store_id']) {
|
||
$order['default_delivery'] = SystemStore::where('id', $params['store_id'])->value('is_send');
|
||
}
|
||
if (isset($params['source']) && $params['source'] > 0) {
|
||
$order['source'] = $params['source'];
|
||
}
|
||
//处理返回最近的店铺
|
||
$store_check = 0;
|
||
if (empty($user)) {
|
||
$store_id = getenv('STORE_ID') ?? 1;
|
||
$store['near_store'] = SystemStore::where('id', $store_id)->field('id,name,phone,address,detailed_address,latitude,longitude')->find() ?? [];
|
||
} else {
|
||
$checkOrderStore = StoreOrder::where('uid', $user['id'])->field('id,store_id')
|
||
->order('id', 'desc')->find();
|
||
if ($checkOrderStore) {
|
||
$store['near_store'] = SystemStore::where('id', $checkOrderStore['store_id'])->field('id,name,phone,address,detailed_address,latitude,longitude')->find() ?? [];
|
||
$store_check = 1;
|
||
} else {
|
||
$store_id = getenv('STORE_ID') ?? 1;
|
||
$store['near_store'] = SystemStore::where('id', $store_id)->field('id,name,phone,address,detailed_address,latitude,longitude')->find() ?? [];
|
||
}
|
||
}
|
||
if (empty($store_check)) {
|
||
if ((isset($params['lat']) && $params['lat'] != '') && (isset($params['long']) && $params['long'] != '')) {
|
||
$storeAll = SystemStore::field('id,name,phone,address,detailed_address,latitude,longitude')->select()->toArray();
|
||
$nearestStore = null;
|
||
$minDistance = PHP_FLOAT_MAX;
|
||
foreach ($storeAll as $value) {
|
||
$value['distance'] = haversineDistance($value['latitude'], $value['longitude'], $params['lat'], $params['long']);
|
||
if ($value['distance'] < $minDistance) {
|
||
$minDistance = $value['distance'];
|
||
$nearestStore = $value;
|
||
}
|
||
}
|
||
$store['near_store'] = [];
|
||
if ($nearestStore) {
|
||
$store['near_store'] = $nearestStore;
|
||
}
|
||
}
|
||
}
|
||
// } catch (\Exception $e) {
|
||
// d($e);
|
||
// throw new BusinessException($e->getMessage(), 3000);
|
||
// }
|
||
return ['order' => $order, 'cart_list' => $cart_select, 'shopInfo' => $store['near_store']];
|
||
}
|
||
|
||
/**
|
||
* 创建新订单
|
||
* @return Object|bool|array
|
||
*/
|
||
static public function createOrder($cartId, $addressId, $user = null, $params = [])
|
||
{
|
||
$order_id = getNewOrderId('PF');
|
||
$code = rand(1, 10) . '-' . substr($order_id, -5);
|
||
$verify_code = createCode($code);
|
||
$params['order_id'] = $order_id;
|
||
$params['verify_code'] = $verify_code;
|
||
$orderInfo = self::cartIdByOrderInfo($cartId, $addressId, $user, $params, 1);
|
||
if (!$orderInfo) {
|
||
return false;
|
||
}
|
||
$uid = $user['id'] ?? 0;
|
||
$_order = $orderInfo['order'];
|
||
$_order['uid'] = $uid;
|
||
$_order['spread_uid'] = $params['spread_uid'] ?? 0;
|
||
$_order['real_name'] = $user['real_name'] ?? '';
|
||
$_order['mobile'] = $user['mobile'] ?? '';
|
||
$_order['pay_type'] = $orderInfo['order']['pay_type'];
|
||
$_order['verify_code'] = $verify_code;
|
||
$_order['reservation_time'] = null;
|
||
$_order['reservation'] = $params['reservation'] ?? 0; //是否需要预约
|
||
if (isset($params['reservation_time']) && $params['reservation_time']) {
|
||
$_order['reservation_time'] = $params['reservation_time'];
|
||
$_order['reservation'] = YesNoEnum::YES;
|
||
}
|
||
if ($addressId > 0 && $uid > 0) {
|
||
$address = UserAddress::where(['id' => $addressId, 'uid' => $uid])->find();
|
||
if ($address) {
|
||
$_order['real_name'] = $address['real_name'];
|
||
$_order['user_phone'] = $address['phone'];
|
||
$_order['user_address'] = $address['detail'];
|
||
}
|
||
}
|
||
if ($params['shipping_type'] == 2) {
|
||
$_order['status'] = 1;
|
||
}
|
||
if ($_order['pay_type'] == PayEnum::BALANCE_PAY && $user != null && $user['now_money'] < $_order['pay_price']) {
|
||
throw new \Exception('余额不足');
|
||
}
|
||
//生成核销码
|
||
$generator = new BarcodeGeneratorPNG();
|
||
$barcode = $generator->getBarcode($verify_code, $generator::TYPE_CODE_128);
|
||
$findPath = '/image/barcode/' . time() . '.png';
|
||
$savePath = public_path() . $findPath;
|
||
file_put_contents($savePath, $barcode);
|
||
$_order['verify_img'] = $findPath;
|
||
Db::startTrans();
|
||
try {
|
||
$times = strtotime($params['create_time']);
|
||
$_order['create_time'] = $times;
|
||
$_order['update_time'] = $times;
|
||
$order = StoreOrder::create($_order);
|
||
$goods_list = $orderInfo['cart_list'];
|
||
foreach ($goods_list as $k => $v) {
|
||
$goods_list[$k]['oid'] = $order->id;
|
||
$goods_list[$k]['uid'] = $uid;
|
||
$goods_list[$k]['cart_id'] = implode(',', $cartId);
|
||
$goods_list[$k]['delivery_id'] = $params['store_id']; //商家id
|
||
$goods_list[$k]['create_time'] = $times; //商家id
|
||
$goods_list[$k]['update_time'] = $times; //商家id
|
||
|
||
// $StoreBranchProduct = StoreBranchProduct::where('id', $v['branch_product_id'])->withTrashed()->find();
|
||
// if ($StoreBranchProduct['stock'] - $v['cart_num'] <= 0) {
|
||
// Db::name('store_product_cate')->where(['cate_id' => $StoreBranchProduct['cate_id'], 'store_id' => $params['store_id']])->update(['count' => 0]);
|
||
// }
|
||
}
|
||
(new StoreOrderCartInfo())->saveAll($goods_list);
|
||
Cart::whereIn('id', $cartId)->update(['is_pay' => 1]);
|
||
Db::commit();
|
||
return $order;
|
||
} catch (\Exception $e) {
|
||
Db::rollback();
|
||
d($e);
|
||
throw new BusinessException($e->getMessage(), 3000);
|
||
}
|
||
}
|
||
}
|