655 lines
28 KiB
PHP
655 lines
28 KiB
PHP
<?php
|
||
|
||
namespace app\common\service;
|
||
|
||
use think\Cache;
|
||
use think\Db;
|
||
use think\Log;
|
||
use EasyWeChat\Pay\Message as PayMessage;
|
||
use app\common\model\Orders;
|
||
use app\common\traits\ServiceTrait;
|
||
use think\Exception;
|
||
|
||
class OrderService
|
||
{
|
||
use ServiceTrait;
|
||
|
||
/** @var Orders */
|
||
public static $Model = Orders::class;
|
||
|
||
const LOCK_ORDER_PREFIX = 'lock_order_cache:'; //重复创建订单锁
|
||
|
||
//订单状态
|
||
const ORDER_STATUS_NO = 0; //关闭
|
||
const ORDER_STATUS_WAIT_PAY = 10; //待付款
|
||
const ORDER_STATUS_WAIT_SHIP = 20; //已支付(待发货)
|
||
const ORDER_STATUS_SHIPPED = 30; //已发货(待收货)
|
||
const ORDER_STATUS_FAILED = 31; //交易失败
|
||
const ORDER_STATUS_TIMEOUT = 33; //订单超时
|
||
const ORDER_STATUS_FINISHED = 40; //已完成
|
||
const ORDER_STATUS_CANCEL = 50; //已取消
|
||
const ORDER_STATUS_REFUNDED = 60; //已退款
|
||
|
||
const ORDER_STATUS_MAP = [
|
||
self::ORDER_STATUS_NO => '订单关闭',
|
||
self::ORDER_STATUS_WAIT_PAY => '待支付',
|
||
self::ORDER_STATUS_WAIT_SHIP => '待发货',
|
||
self::ORDER_STATUS_SHIPPED => '已发货',
|
||
self::ORDER_STATUS_FAILED => '交易失败',
|
||
self::ORDER_STATUS_TIMEOUT => '订单超时',
|
||
self::ORDER_STATUS_CANCEL => '用户取消订单',
|
||
self::ORDER_STATUS_FINISHED => '交易完成',
|
||
self::ORDER_STATUS_REFUNDED => '已退款',
|
||
];
|
||
// 订单操作按钮
|
||
const BUTTON_PAY = 1; // 付款
|
||
const BUTTON_CANCEL = 2; // 取消订单
|
||
const BUTTON_CONFIRM = 3; // 确认收货
|
||
const BUTTON_APPLY_REFUND = 4; // 申请售后
|
||
const BUTTON_VIEW_REFUND = 5; // 查看退款
|
||
const BUTTON_COMMENT = 6; // 评价
|
||
const BUTTON_DELETE = 7; // 删除订单
|
||
const BUTTON_DELIVERY = 8; // 查看物流
|
||
const BUTTON_REBUY = 9; // 再次购买
|
||
const BUTTON_INVITE_GROUPON = 11; //邀请好友拼团
|
||
|
||
const BUTTON_MAP = [
|
||
self::BUTTON_PAY => '付款', // 付款
|
||
self::BUTTON_CANCEL => '取消订单', // 取消订单
|
||
self::BUTTON_CONFIRM => '确认收货', // 确认收货
|
||
self::BUTTON_APPLY_REFUND => '申请售后', // 申请售后
|
||
self::BUTTON_VIEW_REFUND => '查看退款', // 查看退款
|
||
self::BUTTON_COMMENT => '评价', // 评价
|
||
self::BUTTON_DELETE => '删除订单', // 删除订单
|
||
self::BUTTON_DELIVERY => '查看物流', // 查看物流
|
||
self::BUTTON_REBUY => '再次购买', // 再次购买
|
||
self::BUTTON_INVITE_GROUPON => '邀请好友拼团', //邀请好友拼团
|
||
];
|
||
|
||
const ORDER_TYPE_SOFTWARE = 0;//软件产品;
|
||
const ORDER_TYPE_FIRST_PAYMENT = 1;//首付款款订单;
|
||
const ORDER_TYPE_FINAL_PAYMENT = 2; //尾款订单;
|
||
|
||
const ORDER_TYPE_MAP = [
|
||
self::ORDER_TYPE_SOFTWARE => '软件产品',
|
||
self::ORDER_TYPE_FIRST_PAYMENT => '需求首付款',
|
||
self::ORDER_TYPE_FINAL_PAYMENT => '需求尾款',
|
||
];
|
||
|
||
|
||
/**
|
||
* 生成订单
|
||
* @param $requestData
|
||
* @return array
|
||
* @throws \Exception
|
||
*/
|
||
public static function createOrder($requestData)
|
||
{
|
||
try {
|
||
$user = $requestData['userInfo'] ?? [];
|
||
$userId = $user['id'] ?? 0;
|
||
$openid = $user['openid'] ?? '';
|
||
Log::info('创建订单数据-request:' . json_encode($requestData, JSON_UNESCAPED_UNICODE));
|
||
if (empty($requestData['goodsRequestList'])) {
|
||
throw new \Exception('订单数据错误');
|
||
}
|
||
//如果30秒内有重复数据,直接返回缓存订单,不再创建
|
||
$lockOrderKey = self::getLockOrderKey($userId, $requestData);
|
||
if ($lockOrderRes = Cache::get($lockOrderKey)) {
|
||
return json_decode($lockOrderRes, true);
|
||
}
|
||
$goodsRequestList = $requestData['goodsRequestList'];
|
||
$count = count($goodsRequestList);
|
||
if ($count == 0) {
|
||
Log::error('订单创建失败:商品数量不能为0');
|
||
throw new \Exception('订单创建失败:商品数量不能为0');
|
||
}
|
||
$total_amount = 0;
|
||
$total_quantity = 0;
|
||
$goodsDataList = [];
|
||
foreach ($goodsRequestList as $item) {
|
||
$quantity = max(1, $item['quantity']);
|
||
$total_quantity += $quantity;
|
||
$total_amount += $quantity * $item['price'];
|
||
$goodsDataList[] = [
|
||
'spu_id' => $item['spuId'],
|
||
'sku_id' => $item['sku_id'] ?? '',
|
||
'goods_name' => $item['goodsName'],
|
||
'goods_picture_url' => $item['primaryImage'],
|
||
'origin_price' => $item['price'],
|
||
'actual_price' => $item['price'],
|
||
'buy_quantity' => $quantity,
|
||
'item_total_amount' => $item['price'] * $quantity,
|
||
'item_discount_amount' => 0,
|
||
'item_payment_amount' => $item['price'] * $quantity,
|
||
'goods_payment_price' => $item['price'],
|
||
];
|
||
}
|
||
$orderData = [
|
||
'user_id' => $userId,
|
||
'store_id' => 1,
|
||
'order_no' => generate_order_sn(),
|
||
'order_status' => OrderService::ORDER_STATUS_WAIT_PAY,
|
||
'order_type' => 0,
|
||
'total_amount' => $total_amount,
|
||
'payment_amount' => $total_amount,
|
||
'goods_amount' => $total_quantity,
|
||
'discount_amount' => 0,
|
||
'remark' => $requestData['storeInfoList'][0]['remark'] ?? '',
|
||
];
|
||
$existed = OrderService::getOne(['order_no' => $orderData['order_no']]);
|
||
if (!$existed) {
|
||
//创建订单及订单商品
|
||
$orderRes = self::$Model::create($orderData);
|
||
Log::info('创建订单数据:' . json_encode($orderData, JSON_UNESCAPED_UNICODE));
|
||
if (!$orderRes) {
|
||
Log::error('创建订单创建失败:' . json_encode($orderData, JSON_UNESCAPED_UNICODE));
|
||
throw new \Exception('订单创建失败');
|
||
}
|
||
$goodsRes = $orderRes->orderGoods()->saveAll($goodsDataList);
|
||
if (!$goodsRes) {
|
||
Log::error('创建订单产品失败:' . json_encode($orderData, JSON_UNESCAPED_UNICODE));
|
||
throw new \Exception('订单创建数据失败');
|
||
}
|
||
}
|
||
$orderData += [
|
||
'channel' => 'wechat',
|
||
'tradeNo' => $orderData['order_no'],
|
||
'interactId' => 0,
|
||
'transactionId' => 0,
|
||
'payInfo' => self::pay($orderData['order_no'], $total_amount, $openid), //统一下单接口
|
||
];
|
||
//存入缓存
|
||
Cache::set($lockOrderKey, json_encode($orderData), 30);
|
||
|
||
return $orderData;
|
||
|
||
} catch (Exception $e) {
|
||
throw new \Exception('订单数据保存失败:' . $e->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 生成需求订单
|
||
* @param $requestData
|
||
* @throws \Exception
|
||
*/
|
||
public static function createDemandOrder($requestData)
|
||
{
|
||
try {
|
||
$demandId = $requestData['demandId'] ?? 0;
|
||
$formData = $requestData['formData'] ?? [];
|
||
$totalCost = $formData['totalCost'] ?? 0;
|
||
Log::info('创建需求订单数据-request:' . json_encode($requestData, JSON_UNESCAPED_UNICODE));
|
||
$demand = DemandService::getOne(['id' => $demandId]);
|
||
if (!$demand) {
|
||
throw new \Exception('该需求不存在');
|
||
}
|
||
$winBid = DemandBiddingService::getOne(['demand_id' => $demandId, 'bidding_status' => DemandBiddingService::STATUS_BIDDING_WIN]);
|
||
$orderInfo = self::where(['parent_order_no' => $demand->parent_order_no])->find();
|
||
$ratio = 0.5; //分期比率50%
|
||
if (!$orderInfo) {
|
||
$installments = 2;//分期数
|
||
for ($i = 1; $i <= $installments; $i++) {
|
||
$total_amount = $i == 1 ? $totalCost * $ratio : $totalCost * (1 - $ratio);
|
||
$goodsDataList = [[
|
||
'spu_id' => 0,
|
||
'sku_id' => 0,
|
||
'goods_name' => '需求签约-' . ($i == 1 ? '首付款' : '尾款') . $demand->parent_order_no,
|
||
'goods_picture_url' => 'https://soft-market.oss-cn-shenzhen.aliyuncs.com/images/contract.png',
|
||
'origin_price' => $total_amount,
|
||
'actual_price' => $total_amount,
|
||
'buy_quantity' => 1,
|
||
'item_total_amount' => $total_amount,
|
||
'item_discount_amount' => 0,
|
||
'item_payment_amount' => $total_amount,
|
||
'goods_payment_price' => $total_amount,
|
||
]];
|
||
$orderData = [
|
||
'user_id' => $demand->user_id,
|
||
'store_id' => 1,
|
||
'parent_order_no' => $demand->parent_order_no,
|
||
'order_no' => generate_order_sn(),
|
||
'order_status' => OrderService::ORDER_STATUS_WAIT_PAY,
|
||
'order_type' => $i,
|
||
'total_amount' => $total_amount,
|
||
'payment_amount' => $total_amount,
|
||
'goods_amount' => $total_amount,
|
||
'discount_amount' => 0,
|
||
'remark' => '',
|
||
];
|
||
$existed = OrderService::getOne(['order_no' => $orderData['order_no']]);
|
||
if (!$existed) {
|
||
//创建订单及订单商品
|
||
$orderRes = self::$Model::create($orderData);
|
||
Log::info('创建需求订单数据:' . json_encode($orderData, JSON_UNESCAPED_UNICODE));
|
||
if (!$orderRes) {
|
||
Log::error('创建需求订单创建失败:' . json_encode($orderData, JSON_UNESCAPED_UNICODE));
|
||
throw new \Exception('需求订单创建失败');
|
||
}
|
||
$goodsRes = $orderRes->orderGoods()->saveAll($goodsDataList);
|
||
if (!$goodsRes) {
|
||
Log::error('创建需求订单产品失败:' . json_encode($orderData, JSON_UNESCAPED_UNICODE));
|
||
throw new \Exception('需求订单创建数据失败');
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//查找签约记录,没有则创建
|
||
$contractInfo = ContractService::getOne(['demand_id' => $demand, 'bidding_id' => $winBid->id ?? 0]);
|
||
if (!$contractInfo) {
|
||
//创建合同数据
|
||
$firstContract = ContractService::getFirstContract($demandId);
|
||
$depositAmount = $firstContract ? $firstContract->deposit_amount : $formData['totalCost'] * $ratio;
|
||
ContractService::createData($demandId, $winBid->id ?? 0, $depositAmount, $formData);
|
||
}
|
||
return $contractInfo;
|
||
} catch (Exception $e) {
|
||
throw new \Exception('需求订单数据保存失败:' . $e->getMessage());
|
||
}
|
||
}
|
||
|
||
public static function getDemandOrder($parentOrderNo, $contractType)
|
||
{
|
||
$res = self::getOne(['parent_order_no' => $parentOrderNo, 'order_type' => $contractType], ['orderGoods', 'orderPayment']);
|
||
|
||
return $res;
|
||
}
|
||
|
||
public static function orderPay($requestData)
|
||
{
|
||
try {
|
||
$user = $requestData['userInfo'] ?? [];
|
||
$userId = $user['id'] ?? 0;
|
||
$openid = $user['openid'] ?? '';
|
||
$orderNo = $requestData['orderNo'] ?? '';
|
||
if (!$orderNo) {
|
||
throw new \Exception('订单号不存在');
|
||
}
|
||
$fields = 'user_id,store_id,order_no,order_status,order_type,total_amount,payment_amount,goods_amount,discount_amount,remark';
|
||
$orderInfo = OrderService::where(['order_no' => $orderNo, 'user_id' => $userId])->field($fields)->find();
|
||
if (!$orderInfo) {
|
||
throw new \Exception('该订单不存在');
|
||
}
|
||
$orderData = $orderInfo->toArray();
|
||
Log::info('微信下单[发起支付] ' . json_encode([
|
||
'order_no' => $orderNo,
|
||
'user_id' => $userId,
|
||
'order_status' => $orderData['order_status'] ?? null,
|
||
'status_text' => self::ORDER_STATUS_MAP[$orderData['order_status'] ?? -1] ?? '未知',
|
||
'payment_amount' => $orderData['payment_amount'] ?? 0,
|
||
'total_amount' => $orderData['total_amount'] ?? 0,
|
||
], JSON_UNESCAPED_UNICODE));
|
||
$orderData += [
|
||
'channel' => 'wechat',
|
||
'tradeNo' => $orderData['order_no'],
|
||
'interactId' => 1,
|
||
'transactionId' => 0,
|
||
'payInfo' => self::pay($orderInfo->order_no, $orderInfo->total_amount, $openid), //统一下单接口
|
||
];
|
||
Log::info('微信下单[下单成功] ' . json_encode([
|
||
'order_no' => $orderNo,
|
||
'payInfo' => $orderData['payInfo'],
|
||
], JSON_UNESCAPED_UNICODE));
|
||
|
||
return $orderData;
|
||
|
||
} catch (Exception $e) {
|
||
throw new \Exception('订单支付异常:' . $e->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 订单操作
|
||
* @param $request
|
||
* @return mixed
|
||
* @throws \Exception
|
||
*/
|
||
public static function orderOperate($requestData, $userId)
|
||
{
|
||
$goodsInfo = $requestData['goodsInfo'] ?? [];
|
||
$type = $requestData['type'] ?? '';
|
||
switch ($type) {
|
||
case self::BUTTON_CONFIRM:
|
||
$res = self::confirmOrder($goodsInfo['id'] ?? 0, $userId);
|
||
break;
|
||
case self::BUTTON_CANCEL:
|
||
$res = self::cancelOrder($goodsInfo['id'] ?? 0, $userId);
|
||
break;
|
||
default:
|
||
throw new \Exception('非法操作');
|
||
}
|
||
|
||
return $res;
|
||
}
|
||
|
||
/**
|
||
* 取消订单
|
||
* @param $order_id
|
||
* @param $userId
|
||
* @return mixed
|
||
* @throws \Exception
|
||
*/
|
||
public static function cancelOrder($orderId, $userId = 0)
|
||
{
|
||
try {
|
||
$where = ['id' => $orderId, 'user_id' => $userId];
|
||
$order = self::getOne($where);
|
||
if (!$order) {
|
||
throw new \Exception('该订单不存在');
|
||
}
|
||
Db::startTrans();
|
||
if (!in_array($order->order_status, [OrderService::ORDER_STATUS_WAIT_PAY, OrderService::ORDER_STATUS_WAIT_SHIP])) {
|
||
throw new \Exception('该订单为' . OrderService::ORDER_STATUS_MAP[$order->order_status] . ',不能取消');
|
||
}
|
||
//修改订单状态
|
||
$upRes = self::where($where)->update(['order_status' => OrderService::ORDER_STATUS_CANCEL]);
|
||
if (!$upRes) {
|
||
throw new \Exception('更新订单状态失败');
|
||
}
|
||
//退款原路返回
|
||
// OrderRefund::dispatch(['order_sn' => $order->order_sn, 'actual_amount' => $order->actual_amount]);
|
||
//给用户发送出票失败结果通知
|
||
// SendMsg::dispatch(['order_id' => $order->id, 'user_id' => $order->user_id, 'template_id' => SubscribeMessageService::MSG_TEMP_ORDER_FAILED, 'desc' => SubscribeMessageService::ORDER_MSG_MAP['failed'], 'desc2' => SubscribeMessageService::ORDER_MSG_MAP['refund']]);
|
||
|
||
Db::commit();
|
||
$info = OrderService::getOne(['id' => $orderId]);
|
||
|
||
return $info;
|
||
} catch (\Exception $e) {
|
||
Db::rollback();
|
||
throw $e;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 确认收货
|
||
* @param $orderId
|
||
* @param $userId
|
||
* @return mixed
|
||
* @throws \Exception
|
||
*/
|
||
public static function confirmOrder($orderId, $userId = 0)
|
||
{
|
||
try {
|
||
$where = ['id' => $orderId, 'user_id' => $userId];
|
||
$order = self::getOne($where);
|
||
if (!$order) {
|
||
throw new \Exception('该订单不存在');
|
||
}
|
||
Db::startTrans();
|
||
if (!in_array($order->order_status, [OrderService::ORDER_STATUS_SHIPPED])) {
|
||
throw new \Exception('该订单为' . OrderService::ORDER_STATUS_MAP[$order->order_status] . ',不能确认收货');
|
||
}
|
||
//修改订单状态
|
||
$upRes = self::where($where)->update(['order_status' => OrderService::ORDER_STATUS_FINISHED]);
|
||
if (!$upRes) {
|
||
throw new \Exception('更新订单状态失败');
|
||
}
|
||
Db::commit();
|
||
$info = OrderService::getOne(['id' => $orderId]);
|
||
|
||
return $info;
|
||
} catch (\Exception $e) {
|
||
Db::rollback();
|
||
throw $e;
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* 微信支付回调(EasyWeChat 6.x / 支付 v3: 自动验签+解密)
|
||
* @return \Psr\Http\Message\ResponseInterface
|
||
* @throws \Exception
|
||
*/
|
||
public static function payNotify()
|
||
{
|
||
$service = new EasyWeChatService();
|
||
|
||
return $service->handlePayNotify(function (PayMessage $message, $traceId = '') {
|
||
$prefix = '微信支付回调[业务] trace=' . $traceId . ' ';
|
||
$order_no = $message->out_trade_no ?? '';
|
||
$total = $message->amount['total'] ?? 0;
|
||
|
||
Log::info($prefix . '支付成功通知: ' . json_encode([
|
||
'order_no' => $order_no,
|
||
'transaction_id' => $message->transaction_id ?? '',
|
||
'trade_state' => $message->trade_state ?? '',
|
||
'trade_type' => $message->trade_type ?? '',
|
||
'amount_fen' => $total,
|
||
'amount_yuan' => sprintf('%.2f', $total / 100),
|
||
'success_time' => $message->success_time ?? '',
|
||
], JSON_UNESCAPED_UNICODE));
|
||
|
||
$orderInfo = OrderService::getOne(['order_no' => $order_no]);
|
||
if (!$orderInfo) {
|
||
Log::error($prefix . '订单不存在: ' . json_encode(['order_no' => $order_no], JSON_UNESCAPED_UNICODE));
|
||
throw new \Exception('获取订单数据失败');
|
||
}
|
||
|
||
Log::info($prefix . '订单当前状态: ' . json_encode([
|
||
'order_id' => $orderInfo->id,
|
||
'order_no' => $order_no,
|
||
'order_status' => $orderInfo->order_status,
|
||
'status_text' => self::ORDER_STATUS_MAP[$orderInfo->order_status] ?? '未知',
|
||
'order_type' => $orderInfo->order_type,
|
||
'parent_no' => $orderInfo->parent_order_no ?? '',
|
||
'payment_amount'=> $orderInfo->payment_amount,
|
||
], JSON_UNESCAPED_UNICODE));
|
||
|
||
//金额校验(v3 通知金额单位为分)
|
||
$checkMoney = sprintf('%.1f', $total / 100) == sprintf('%.1f', $orderInfo->payment_amount);
|
||
if (!$checkMoney) {
|
||
Log::error($prefix . '金额校验失败: ' . json_encode([
|
||
'notify_amount' => sprintf('%.2f', $total / 100),
|
||
'order_amount' => sprintf('%.2f', $orderInfo->payment_amount),
|
||
], JSON_UNESCAPED_UNICODE));
|
||
throw new \Exception('金额错误:' . sprintf('%.2f', $total / 100) . '----' . sprintf('%.2f', $orderInfo->payment_amount));
|
||
}
|
||
if (($message->trade_state ?? '') != 'SUCCESS') {
|
||
Log::error($prefix . '支付状态异常: trade_state=' . ($message->trade_state ?? ''));
|
||
throw new \Exception('支付失败:' . ($message->trade_state ?? ''));
|
||
}
|
||
|
||
//如果为待支付,才可更新为已支付。防止重复更新状态,导致重复发货。
|
||
if ($orderInfo->order_status != self::ORDER_STATUS_WAIT_PAY) {
|
||
Log::info($prefix . '订单已处理过,跳过状态更新(幂等): ' . json_encode([
|
||
'order_no' => $order_no,
|
||
'order_status' => $orderInfo->order_status,
|
||
'status_text' => self::ORDER_STATUS_MAP[$orderInfo->order_status] ?? '未知',
|
||
], JSON_UNESCAPED_UNICODE));
|
||
|
||
return true;
|
||
}
|
||
|
||
$paymentData = [
|
||
'order_no' => $order_no,
|
||
'pay_status' => 'SUCCESS',
|
||
'amount' => $total / 100,
|
||
'currency' => $message->amount['currency'] ?? 'CNY',
|
||
'pay_type' => '1', // 1微信 2支付宝
|
||
'pay_way' => $message->trade_type ?? 'JSAPI',
|
||
'trace_no' => $message->transaction_id ?? '',
|
||
'pay_time' => time(),
|
||
'pay_success_time' => strtotime((string)($message->success_time ?? '')) ?: time(),
|
||
];
|
||
Log::info($prefix . '开始更新订单状态: ' . json_encode($paymentData, JSON_UNESCAPED_UNICODE));
|
||
|
||
try {
|
||
Db::transaction(function () use ($order_no, $paymentData, $orderInfo, $prefix) {
|
||
$updateRows = self::where('order_no', $order_no)->update(['order_status' => self::ORDER_STATUS_WAIT_SHIP]);
|
||
Log::info($prefix . '订单状态更新: order_no=' . $order_no
|
||
. ' 10(待支付) -> ' . self::ORDER_STATUS_WAIT_SHIP . '(待发货) 影响行数=' . $updateRows);
|
||
|
||
$payment = OrderPaymentService::create($paymentData);
|
||
Log::info($prefix . '支付流水写入: ' . json_encode([
|
||
'payment_id' => $payment->id ?? 0,
|
||
'order_no' => $payment->order_no ?? '',
|
||
'pay_status' => $payment->pay_status ?? '',
|
||
'amount' => $payment->amount ?? 0,
|
||
'trace_no' => $payment->trace_no ?? '',
|
||
], JSON_UNESCAPED_UNICODE));
|
||
|
||
if ($orderInfo->order_type == self::ORDER_TYPE_FIRST_PAYMENT) {
|
||
Log::info($prefix . '需求首付款订单,处理合同成交: parent_order_no=' . $orderInfo->parent_order_no);
|
||
DemandService::customerContractFinishedDeal($orderInfo->parent_order_no);
|
||
} elseif ($orderInfo->order_type == self::ORDER_TYPE_FINAL_PAYMENT) {
|
||
Log::info($prefix . '需求尾款订单,处理验收结算: parent_order_no=' . $orderInfo->parent_order_no);
|
||
DemandService::customerWorkAcceptFinishedDeal($orderInfo->parent_order_no);
|
||
}
|
||
});
|
||
} catch (\Throwable $e) {
|
||
Log::error($prefix . '事务执行失败已回滚: msg=' . $e->getMessage()
|
||
. ' file=' . $e->getFile() . ':' . $e->getLine());
|
||
throw $e;
|
||
}
|
||
|
||
// 复核:确认状态与支付流水真的落库了
|
||
$newOrder = OrderService::getOne(['order_no' => $order_no]);
|
||
$payment = OrderPaymentService::getOne(['order_no' => $order_no]);
|
||
Log::info($prefix . '回调处理成功: ' . json_encode([
|
||
'order_no' => $order_no,
|
||
'new_order_status'=> $newOrder->order_status ?? null,
|
||
'new_status_text' => self::ORDER_STATUS_MAP[$newOrder->order_status ?? -1] ?? '未知',
|
||
'payment_id' => $payment->id ?? 0,
|
||
'payment_status' => $payment->pay_status ?? '',
|
||
'trace_no' => $payment->trace_no ?? '',
|
||
], JSON_UNESCAPED_UNICODE));
|
||
|
||
return true;
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 获取缓存
|
||
* @param $userId
|
||
* @param $data array
|
||
* @return mixed
|
||
*/
|
||
public static function getLockOrderKey($userId, $data)
|
||
{
|
||
$key = self::LOCK_ORDER_PREFIX . md5($userId . json_encode($data));
|
||
|
||
return $key;
|
||
}
|
||
|
||
/**
|
||
* @param $order_sn
|
||
* @param $total_fee
|
||
* @param $openid
|
||
* @param string $body
|
||
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
|
||
* @throws \Exception
|
||
*/
|
||
public static function pay($order_sn, $total_fee, $openid, string $body = '软件产品服务')
|
||
{
|
||
if (!($body && $order_sn && $total_fee && $openid)) {
|
||
Log::error('微信下单[参数错误] ' . json_encode([
|
||
'body' => $body,
|
||
'order_sn' => $order_sn,
|
||
'total_fee' => $total_fee,
|
||
'openid' => $openid,
|
||
], JSON_UNESCAPED_UNICODE));
|
||
throw new \Exception('支付参数错误2');
|
||
}
|
||
|
||
$EasyWeChatService = new EasyWeChatService();
|
||
$payRes = $EasyWeChatService->unify($body, $order_sn, $total_fee, $openid);
|
||
if (!($payRes && !empty($payRes['prepay_id']))) {
|
||
Log::error('微信下单[统一下单失败] order_sn=' . $order_sn . ' res=' . json_encode($payRes, JSON_UNESCAPED_UNICODE));
|
||
throw new \Exception('统一下单接口调用失败:' . ($payRes['message'] ?? ($payRes['errmsg'] ?? '未知错误')));
|
||
}
|
||
Log::info('微信下单[prepay_id] order_sn=' . $order_sn . ' prepay_id=' . $payRes['prepay_id']);
|
||
$payData = $EasyWeChatService->sdkConfig($payRes['prepay_id']);
|
||
|
||
return $payData;
|
||
}
|
||
|
||
/**
|
||
* 获取订单操作按钮
|
||
* @param $orderStatus
|
||
* @return array
|
||
*/
|
||
public static function getOrderButtons($orderStatus): array
|
||
{
|
||
$buttons = [];
|
||
if ($orderStatus == self::ORDER_STATUS_WAIT_PAY) {
|
||
$buttons[] = ['name' => self::BUTTON_MAP[OrderService::BUTTON_CANCEL], 'primary' => false, 'type' => OrderService::BUTTON_CANCEL];
|
||
$buttons[] = ['name' => self::BUTTON_MAP[OrderService::BUTTON_PAY], 'primary' => true, 'type' => OrderService::BUTTON_PAY];
|
||
}
|
||
if ($orderStatus == self::ORDER_STATUS_SHIPPED) {
|
||
$buttons[] = ['name' => self::BUTTON_MAP[OrderService::BUTTON_CONFIRM], 'primary' => true, 'type' => OrderService::BUTTON_CONFIRM];
|
||
}
|
||
|
||
return $buttons;
|
||
}
|
||
|
||
/**
|
||
* 获取订单统计
|
||
* @param $userId
|
||
* @return array[]
|
||
*/
|
||
public static function getOrderCount($userId): array
|
||
{
|
||
$orderCountList = [
|
||
['orderNum' => 0, 'tabType' => OrderService::ORDER_STATUS_WAIT_PAY],
|
||
['orderNum' => 0, 'tabType' => OrderService::ORDER_STATUS_WAIT_SHIP],
|
||
['orderNum' => 0, 'tabType' => OrderService::ORDER_STATUS_SHIPPED],
|
||
['orderNum' => 0, 'tabType' => OrderService::ORDER_STATUS_FINISHED],
|
||
['orderNum' => 0, 'tabType' => OrderService::ORDER_STATUS_REFUNDED],
|
||
];
|
||
$countList = self::where(['user_id' => $userId, 'order_type' => self::ORDER_TYPE_SOFTWARE])->field('order_status, COUNT(*) as total')
|
||
->group('order_status')
|
||
->select();
|
||
|
||
foreach ($orderCountList as &$value) {
|
||
if ($value['tabType'] == OrderService::ORDER_STATUS_FINISHED) {
|
||
continue;
|
||
}
|
||
foreach ($countList as $item) {
|
||
if ($item->order_status == $value['tabType']) {
|
||
$value['orderNum'] = $item->total;
|
||
}
|
||
}
|
||
}
|
||
|
||
return $orderCountList;
|
||
}
|
||
|
||
/**
|
||
* 订单发货
|
||
* @param $id
|
||
* @return void
|
||
* @throws \Exception
|
||
*/
|
||
public static function orderShip($id)
|
||
{
|
||
Db::transaction(function () use ($id) {
|
||
$order = OrderService::getOne(['id' => $id], ['orderGoods']);
|
||
if ($order->order_status != OrderService::ORDER_STATUS_WAIT_SHIP) {
|
||
exception('订单状态异常,不能发货');
|
||
}
|
||
//查询激活码
|
||
$code = SoftCodeService::getAvailableCode();
|
||
//生成发货单
|
||
OrderShipService::createData($order->order_no, $order->orderGoods[0]->spu_id, $code);
|
||
$order->order_status = OrderService::ORDER_STATUS_SHIPPED;
|
||
//修改发货状态
|
||
$saveRes = $order->save();
|
||
if (!$saveRes) {
|
||
exception('更新发货状态失败');
|
||
}
|
||
//发送订单发货通知
|
||
$msgData = [
|
||
'values' => [
|
||
$order->order_no,
|
||
mb_substr($order->orderGoods[0]->goods_name, 0, 20),
|
||
'已发货',
|
||
SubscribeMessageService::MSG_MAP[SubscribeMessageService::MSG_TEMP_ORDER_SHIPPED]['remark'],
|
||
]
|
||
];
|
||
(new EasyWeChatService())->sendMsg($order->user_id, SubscribeMessageService::MSG_TEMP_ORDER_SHIPPED, $msgData);
|
||
});
|
||
}
|
||
|
||
} |