You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

516 lines
21 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace app\mall\service;
use app\distribution\logic\Commission;
use app\distribution\model\DistributionCommissionIncome;
use app\distribution\model\DistributionConfig;
use app\mall\model\MallCart;
use app\mall\model\MallOrder;
use app\mall\model\MallOrderProduct;
use app\mall\model\MallProduct;
use app\mall\model\MallProductSku;
use app\mall\model\MallSpikeProduct;
use app\mall\model\MallSpikeProductSku;
use app\money\logic\Money;
use Godruoyi\Snowflake\Snowflake;
use think\facade\Db;
use think\facade\Request;
class Order extends Base
{
/**
* 获取下单时购买商品数组列表
* @param int $buy_type 购买方式 1--购物车 2--立即购买
* @param int $product_id buy_type=2时产品ID
* @param string $product_sku buy_type=2时产品SKU
* @param int $number buy_type=2时购买数量
* @param int $type 下单类型 1--商城 2--秒杀
* @param int $spike_product_id type=2时秒杀产品ID
* @date 2022-10-13
*/
public function getOrderProduct($buy_type, $product_id = '', $product_sku = '', $number = 1, $type = 1, $spike_product_id = '')
{
$cart_model = new MallCart();
$product_model = new MallProduct();
$sku_model = new MallProductSku();
$spike_product_model = new MallSpikeProduct();
$spike_sku_model = new MallSpikeProductSku();
// 购物车结算
if ($buy_type == 1) {
$where = [
['uid', '=', $this->mid],
['user_id', '=', $this->userId],
// 是否选中 0-未选中 1--选中
['is_select', '=', 1],
// 是否失效 0--失效 1--有效
['is_effective', '=', 1]
];
$cart_product = $cart_model->getAllCart($where, 'id,product_id,is_product_spec_open,product_sku,number');
// 释放无用字段
foreach ($cart_product as $k => &$v) {
unset($v['product_is_publish']);
unset($v['product_delete_time']);
}
// 立即购买
} else if ($buy_type == 2) {
// 产品
$product = $product_model->getOneData([
['id', '=', $product_id],
['is_publish', '=', 1]
], 'id,name,is_spec_open,stock,cover_img,price,freight_type,freight_id,freight_money,weight');
// 商品有规格
if (!empty($product_sku)) {
$product_sku_list = $sku_model->getOneData([
['product_id', '=', $product_id],
['sku', '=', $product_sku],
], 'id,product_id,sku,cover_img,price,stock');
}
// 秒杀商城(秒杀商城只有立即购买)
if ($type == 2) {
// 秒杀商品
$spike_product = $spike_product_model->getOneData([
['id', '=', $spike_product_id]
]);
// 秒杀有规格
if (!empty($product_sku)) {
$spike_product_sku = $spike_sku_model->getOneData([
['spike_product_id', '=', $spike_product_id],
['sku', '=', $product_sku]
]);
}
}
$cart_product[] = [
// 产品ID
'product_id' => $product['id'],
// 产品是否开启规格
'is_product_spec_open' => $product['is_spec_open'],
// 产品SKU
'product_sku' => $product_sku,
// 产品购买数量
'number' => $number,
// 产品名称
'product_name' => $product['name'],
// 产品SKU名称
'product_sku_name' => $product['is_spec_open'] == 0 ? '' : $product_sku_list['sku_name'],
// 产品封面图
'product_cover_img' => $product['cover_img'],
// 产品价钱
'product_price' => $product['is_spec_open'] == 0
? ($type == 1 ? $product['price'] : $spike_product['price_spike'])
: ($type == 1 ? $product_sku_list['price'] : $spike_product_sku['price_spike']),
// 产品库存
'product_stock' => $product['is_spec_open'] == 0
? ($type == 1 ? $product['stock'] : $spike_product['number'])
: ($type == 1 ? $product_sku_list['stock'] : $spike_product_sku['number']),
// 运费类型
'freight_type' => $product['freight_type'],
// 运费模板ID
'freight_id' => $product['freight_id'],
// 运费金额
'freight_money' => $product['freight_money'],
// 产品总重量
'weight' => $product['weight'],
// 秒杀产品ID 仅仅立即购买的时候有此字段
'spike_product_id' => $spike_product_id
];
}
return $cart_product;
}
/**
* 产品库存变动
* @param int $product_id 产品ID
* @param int $number 变动数量 >0 增加 <0 减少
* @param string $product_sku 产品SKU
* @param int $order_type 订单类型 1--商城订单 2--秒杀订单
* @param int $spike_product_id 秒杀产品ID
* @date 2022-10-21
*/
public function productStockChange($product_id, $number, $product_sku = '', $order_type = 1, $spike_product_id = '')
{
$product_model = new MallProduct();
$product_sku_model = new MallProductSku();
$spike_product_model = new MallSpikeProduct();
$spike_sku_model = new MallSpikeProductSku();
// 符号
$symbol = $number > 0 ? '+' : '-';
// 更新产品表库存
$product_update_data = [
'id' => $product_id,
'stock' => Db::raw('stock' . $symbol . abs($number))
];
$res = $product_model->dataUpdate($product_update_data);
if (!$res) {
return sendErrorArray(2001, '更新产品库存失败');
}
// 更新秒杀产品表库存
if ($order_type == 2) { //秒杀商城订单
$spike_product_update_data = [
'id' => $spike_product_id,
'number' => Db::raw('number' . $symbol . abs($number))
];
$res = $spike_product_model->dataUpdate($spike_product_update_data);
if (!$res) {
return sendErrorArray(2002, '更新秒杀产品库存失败');
}
}
// 商品有SKU
if (!empty($product_sku)) {
// 获取SKU_ID
$sku_id = $product_sku_model->getOneData([
['product_id', '=', $product_id],
['sku', '=', $product_sku]
], 'id');
// 如果还能找到该规格项 则减库存 否则暂时不减
if (!empty($sku_id)) {
// 更改产品SKU库存
$product_data_sku = [
'stock' => Db::raw('stock' . $symbol . abs($number))
];
$res = $product_sku_model->dataUpdate($product_data_sku, [
['product_id', '=', $product_id],
['sku', '=', $product_sku]
]);
if (!$res) {
return sendErrorArray(2003, '更新产品SKU库存失败');
}
// 更改秒杀产品SKU库存
if ($order_type == 2) {
$spike_product_data_sku = [
'number' => Db::raw('number' . $symbol . abs($number))
];
$res = $spike_sku_model->dataUpdate($spike_product_data_sku, [
['spike_product_id', '=', $spike_product_id],
['sku', '=', $product_sku]
]);
if (!$res) {
return sendErrorArray(2004, '更新库存失败');
}
}
}
}
return sendSuccessArray();
}
/**
* 产品销量变动
* @param int $product_id 产品ID
* @param int $number 变动数量 >0 增加 <0 减少
* @param int $order_type 订单类型 1--商城订单 2--秒杀订单
* @param int $spike_product_id 秒杀产品ID
* @date 2022-10-31
*/
public function productSalesChange($product_id, $number, $order_type = 1, $spike_product_id = '')
{
$product_model = new MallProduct();
$spike_product_model = new MallSpikeProduct();
$symbol = $number > 0 ? '+' : '-';
// 更新产品表销量
$product_update_data = [
'id' => $product_id,
'sales_actual_number' => Db::raw('sales_actual_number' . $symbol . abs($number))
];
$res = $product_model->dataUpdate($product_update_data);
if (!$res) {
return sendErrorArray(2001, '更新产品销量失败');
}
//更新秒杀产品表销量
if ($order_type == 2) {
$spike_product_update_data = [
'id' => $spike_product_id,
'sales_number' => Db::raw('sales_number' . $symbol . abs($number))
];
$res = $spike_product_model->dataUpdate($spike_product_update_data);
if (!$res) {
return sendErrorArray(2002, '更新秒杀产品销量失败');
}
}
return sendSuccessArray();
}
/**
* 订单支付成功
* @param int $order_id 订单ID
* @param string $transaction_id 微信支付环境:微信支付系统生成的订单号 支付宝支付环境:支付宝交易号
* @date 2022-10-21
*/
public function afterOrderPaySuccess($order_id, $transaction_id = '')
{
$order_model = new MallOrder();
$order_product_model = new MallOrderProduct();
$income_model = new DistributionCommissionIncome();
$config_model = new DistributionConfig();
$commission_logic = new Commission();
$snow_flake_class = new Snowflake();
// 查找订单
$order = $order_model->getOneData([
['id', '=', $order_id]
], 'id,uid,user_agent,type,user_id,pay_money');
// 1 - 更改订单状态
$data_update = [
'id' => $order['id'],
'is_pay' => 1,
'pay_time' => time(),
'status' => 2,
'transaction_id' => $transaction_id
];
$res = $order_model->dataUpdate($data_update);
if (!$res) {
return sendErrorArray(2001, '订单状态修改失败');
}
// 订单产品表
$order_product = $order_product_model->getAllData([
['order_id', '=', $order_id]
], 'id,product_id,spike_product_id,number');
// 2 - 付款之后,产品增加销量
foreach ($order_product as $k => $v) {
$res = $this->productSalesChange($v['product_id'], $v['number'], $order['type'], $v['spike_product_id']);
if ($res['code'] != 0) {
return $res;
}
}
// 3 - 存入佣金收入表(佣金在路上)
if ($order['pay_money']) {
// 查找订单产品表的购买商品的名称
$product_name_arr = array_column($order_product->toArray(), 'product_name');
$product_name = implode(',', $product_name_arr);
// 查找分销比例
$config = $config_model->getOneData([
['uid', '=', $order['uid']]
], 'first_percent,first_commission,second_percent,second_commission,third_percent,third_commission');
// 获取上三级以及分销佣金
$commission = $commission_logic->getCommission($order['pay_money'], $order['user_id'], $config);
foreach ($commission as $k => $v) {
$data_income[] = [
'id' => $snow_flake_class->id(),
'uid' => $order['uid'],
'user_agent' => $order['user_agent'],
'user_id' => $order['user_id'],
'distributor_user_id' => $v['user_id'],
'relation_type' => 2,
'money' => $order['pay_money'],
'commission' => $v['commission'],
'rank' => $k + 1,
'show_text' => '购买商品"' . $product_name . '"',
'status' => 1,
'remark' => serialize([
'mall_order_id' => $order['id']
]),
'create_time' => time(),
'update_time' => time()
];
}
if (!empty($data_income)) {
$res = $income_model->insertAll($data_income);
if (!$res) {
return sendErrorArray(2002, '生成佣金记录失败');
}
}
}
// 4 - 统计系统 - 新增订单信息
$statistics_class = new \jucheng\tongji\Statistics();
$statistics_class->updateOrderInfo($order['pay_money']);
return sendSuccessArray();
}
/**
* 调起支付
* @param int $order_id 订单ID
* @date 2022-10-26
*/
public function createPayOrder($order_id)
{
$order_model = new MallOrder();
// 获取订单信息
$order = $order_model->getOneData([
['id', '=', $order_id]
], 'id,user_agent,user_id,order_number,pay_type,pay_money');
// 调起支付
switch ($order['pay_type']) {
// 微信支付
case 1:
$wxpay_param = get_wxpay_config_with_weixin($order['user_agent']);
$wxpay_class = new \tencent\wechat\pay\Wxpay($wxpay_param);
$openid = $this->openid;
$notify_url = Request::domain() . '/index.php/mall/api/Callback/weixinNotify/agent/' . $order['user_agent'] . '/uid/' . $this->mid;
// 生成支付订单
$result = $wxpay_class->createOrder($openid, $order['pay_money'], $order['order_number'], '商城支付订单', $notify_url, $order['user_agent']);
if ($result['return_code'] == 'FAIL' || $result['result_code'] == 'FAIL') {
return sendErrorArray(3100, $result['return_code'] != 'SUCCESS' ? $result['return_msg'] : $result['err_code_des']);
}
/* --H5平台微信支付--
直接返回 */
if ($order['user_agent'] == 'h5') {
// mweb_url为拉起微信支付收银台的中间页面可通过访问该url来拉起微信客户端完成支付,mweb_url的有效期为5分钟
return sendSuccessArray(['need_pay' => 1, 'pay_params' => $result['mweb_url']]);
}
/* --其他平台微信支付--
获取支付参数 */
$result_pay = $wxpay_class->wxPay($result['prepay_id'], $order['user_agent']);
return sendSuccessArray([
// 是否需要支付
'need_pay' => 1,
// 支付参数
'pay_params' => $result_pay
]);
break;
// $fubei_param = get_fubei_config();
// switch ($order['user_agent']) {
// // app 支付宝支付
// case 'mp_weixin':
// $mp_weixin_param = get_mp_weixin_config();
// $fubei_param['sub_appid'] = $mp_weixin_param['app_id'];
// break;
// case 'weixin':
// $weixin_param = get_weixin_config();
// $fubei_param['sub_appid'] = $weixin_param['app_id'];
// break;
// }
// $pay_class = new \fubei\pay\Pay($fubei_param);
// $openid = $this->openid;
// $notify_url = Request::domain() . '/index.php/mall/api/Callback/fubeiNotify/agent/' . $order['user_agent'] . '/uid/' . $this->mid;
// $result = $pay_class->pay($openid, $order['pay_money'], $order['order_number'], $order['fubri_order_number'], '商城支付订单', $notify_url, $fubei_param['store_id'], $order['user_agent']);
//
// // 没有调起支付,返回报错
// if ($result['result_code'] != 200) {
// return sendErrorArray($result['result_code'], $result['result_message']);
// }
// return sendSuccessArray([
// // 是否需要支付
// 'need_pay' => 1,
// // 支付参数
// 'pay_params' => $result['data']['sign_package']
// ]);
// break;
// 支付宝支付
case 2:
switch ($order['user_agent']) {
// app 支付宝支付
case 'app':
$ali_pay_param = get_app_alipay_config();
$ali_pay_class = new \ali\alipay\pay\AliPay($ali_pay_param);
$notify_url = Request::domain() . '/index.php/mall/api/Callback/alipayNotify/agent/' . $order['user_agent'] . '/uid/' . $this->mid;
$result = $ali_pay_class->aliPay($order['pay_money'], $order['order_number'], '商城支付订单', $notify_url);
if (empty($result['body'])) {
return sendErrorArray(3101, '生成支付宝订单失败');
}
return sendSuccessArray([
'need_pay' => 1,
'pay_params' => $result['body']
]);
break;
// 支付宝小程序 支付宝支付
case 'mp_alipay':
$ali_pay_param = get_mp_alipay_config();
$ali_pay_class = new \ali\alipay\pay\AliPay($ali_pay_param);
$notify_url = Request::domain() . '/index.php/mall/api/Callback/alipayNotify/agent/' . $order['user_agent'] . '/uid/' . $this->mid;
// 统一下单
$result = $ali_pay_class->mpAliPay($order['pay_money'], $order['order_number'], $this->openid, '商城支付订单', $notify_url);
if ($result['code'] != 10000) {
return sendErrorArray($result['code'], $result['sub_msg']);
}
return sendSuccessArray(['need_pay' => 1, 'pay_params' => $result['trade_no']]);
break;
// H5 支付宝支付
case 'h5':
$ali_pay_param = get_h5_alipay_config();
$ali_pay_class = new \ali\alipay\pay\AliPay($ali_pay_param);
$notify_url = Request::domain() . '/index.php/mall/api/Callback/alipayNotify/agent/' . $order['user_agent'] . '/uid/' . $this->mid;
// 用户付款中途退出返回商户网站的地址 添加该参数后在H5支付收银台会出现返回按钮可用于用户付款中途退出并返回到该参数指定的商家网站地址
$quit_url = Request::domain() . '/h5/#/pages/mall/my/orderList';
$return_url = $quit_url;
// 统一下单
$result = $ali_pay_class->h5AliPay($order['pay_money'], $order['order_number'], '商城支付订单', $quit_url, $return_url, $notify_url);
if (empty($result['body'])) {
return sendErrorArray(2001, '生成支付宝订单失败');
}
return sendSuccessArray(['need_pay' => 1, 'pay_params' => $result['body']]);
break;
default:
break;
}
break;
// 余额支付
case 3:
$money_service = new \app\money\service\Money();
Db::startTrans();
//支付成功
$res = $this->afterOrderPaySuccess($order_id);
if ($res['code'] != 0) {
Db::rollback();
return $res;
}
// 扣除余额
$res = $money_service->change($order['user_id'], 2, -$order['pay_money'], '商城购物', $order['order_number'], [
'mall_order_id' => $order_id
]);
if ($res['code'] != 0) {
Db::rollback();
return $res;
}
Db::commit();
return sendSuccessArray(['need_pay' => 0], '支付成功');
break;
// 其他
default:
break;
}
}
}