feat: 新增发布额度权益与订单管理功能,优化多端交互细节
这个提交包含在:
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\common\library\CouponService;
|
||||
use app\common\library\OrderClose;
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
@@ -107,4 +109,212 @@ class Order extends V1
|
||||
|
||||
return ['balance' => $balance, 'amount' => $amount];
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/v1/order/cancel
|
||||
* 主动取消未支付订单
|
||||
* 入参:{orderNo} 或 {id}
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cancel()
|
||||
{
|
||||
$user = $this->auth();
|
||||
$orderNo = trim((string)$this->input('orderNo', ''));
|
||||
$orderId = (int)$this->input('id', 0);
|
||||
|
||||
if ($orderNo === '' && $orderId <= 0) {
|
||||
$this->fail('请提供订单编号或订单ID');
|
||||
}
|
||||
|
||||
$query = Db::name('fc_order')->where('user_id', $user['id']);
|
||||
if ($orderNo !== '') {
|
||||
$query->where('order_no', $orderNo);
|
||||
} else {
|
||||
$query->where('id', $orderId);
|
||||
}
|
||||
$order = $query->find();
|
||||
|
||||
if (!$order) {
|
||||
$this->fail('订单不存在', 404);
|
||||
}
|
||||
|
||||
if ((string)$order['status'] === 'paid') {
|
||||
$this->fail('已支付订单无法取消,如需退款请联系客服');
|
||||
}
|
||||
if ((string)$order['status'] === 'closed') {
|
||||
$this->fail('订单已是关闭状态,无需重复取消');
|
||||
}
|
||||
if ((string)$order['status'] !== 'pending') {
|
||||
$this->fail('当前订单状态不支持取消');
|
||||
}
|
||||
|
||||
$closed = OrderClose::close($order, 'user_cancel');
|
||||
if (!$closed) {
|
||||
$this->fail('取消订单失败,请稍后重试');
|
||||
}
|
||||
|
||||
$this->ok([
|
||||
'orderNo' => (string)$order['order_no'],
|
||||
'status' => 'closed',
|
||||
], '订单已成功取消');
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/v1/order/detail
|
||||
* 获取订单详情
|
||||
* 入参:orderNo 或 id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function detail()
|
||||
{
|
||||
$user = $this->auth();
|
||||
$orderNo = trim((string)$this->input('orderNo', ''));
|
||||
$orderId = (int)$this->input('id', 0);
|
||||
|
||||
if ($orderNo === '' && $orderId <= 0) {
|
||||
$this->fail('请提供订单编号或订单ID');
|
||||
}
|
||||
|
||||
$query = Db::name('fc_order')->where('user_id', $user['id']);
|
||||
if ($orderNo !== '') {
|
||||
$query->where('order_no', $orderNo);
|
||||
} else {
|
||||
$query->where('id', $orderId);
|
||||
}
|
||||
$order = $query->find();
|
||||
|
||||
if (!$order) {
|
||||
$this->fail('订单不存在', 404);
|
||||
}
|
||||
|
||||
// 惰性超时检查:如果是待支付且已超时,自动关闭
|
||||
$order = OrderClose::checkAndCloseIfExpired($order);
|
||||
|
||||
$now = time();
|
||||
$timeoutSeconds = OrderClose::getTimeoutSeconds();
|
||||
$createtime = isset($order['createtime']) ? (int)$order['createtime'] : 0;
|
||||
$expireSeconds = 0;
|
||||
if ((string)$order['status'] === 'pending' && $createtime > 0) {
|
||||
$expireSeconds = max(0, ($createtime + $timeoutSeconds) - $now);
|
||||
}
|
||||
|
||||
// 状态与类型文本映射
|
||||
$statusMap = [
|
||||
'pending' => '待支付',
|
||||
'paid' => '已支付',
|
||||
'refunding' => '退款中',
|
||||
'refunded' => '已退款',
|
||||
'closed' => '已关闭',
|
||||
];
|
||||
$typeMap = [
|
||||
'post' => '信息发布',
|
||||
'member' => '开通会员',
|
||||
'recharge' => '余额充值',
|
||||
'payview' => '付费查看',
|
||||
];
|
||||
|
||||
$type = (string)$order['type'];
|
||||
$relatedId = (int)$order['related_id'];
|
||||
$relatedInfo = null;
|
||||
|
||||
// 根据业务类型获取详细关联信息
|
||||
if ($type === 'post' && $relatedId > 0) {
|
||||
$post = Db::name('fc_post')->where('id', $relatedId)->find();
|
||||
if ($post) {
|
||||
$categoryName = Db::name('fc_category')->where('id', (int)$post['category_id'])->value('name') ?: '';
|
||||
$relatedInfo = [
|
||||
'postId' => (int)$post['id'],
|
||||
'title' => (string)$post['title'],
|
||||
'categoryName' => $categoryName,
|
||||
'cover' => (string)$post['cover'],
|
||||
'price' => (float)$post['price'],
|
||||
'priceUnit' => (string)$post['price_unit'],
|
||||
'auditStatus' => (int)$post['audit_status'],
|
||||
'status' => (int)$post['status'],
|
||||
];
|
||||
}
|
||||
} elseif ($type === 'member' && $relatedId > 0) {
|
||||
$plan = Db::name('fc_plan')->where('id', $relatedId)->find();
|
||||
if ($plan) {
|
||||
$postQuota = (int)$plan['post_quota'];
|
||||
$rights = ['专属会员身份标示'];
|
||||
if ($postQuota > 0) {
|
||||
$rights[] = "赠送免费发布 {$postQuota} 条";
|
||||
}
|
||||
$rights[] = '同城专属推广推荐';
|
||||
$rights[] = '信息置顶尊享特惠';
|
||||
$relatedInfo = [
|
||||
'planId' => (int)$plan['id'],
|
||||
'name' => (string)$plan['name'],
|
||||
'days' => (int)$plan['days'],
|
||||
'originPrice' => (float)$plan['origin_price'],
|
||||
'price' => (float)$plan['price'],
|
||||
'postQuota' => $postQuota,
|
||||
'rights' => $rights,
|
||||
];
|
||||
}
|
||||
} elseif ($type === 'payview' && $relatedId > 0) {
|
||||
$post = Db::name('fc_post')->where('id', $relatedId)->find();
|
||||
if ($post) {
|
||||
$categoryName = Db::name('fc_category')->where('id', (int)$post['category_id'])->value('name') ?: '';
|
||||
$relatedInfo = [
|
||||
'postId' => (int)$post['id'],
|
||||
'title' => (string)$post['title'],
|
||||
'categoryName' => $categoryName,
|
||||
'contact' => (string)$post['contact'],
|
||||
'phone' => (string)$post['phone'],
|
||||
];
|
||||
}
|
||||
} elseif ($type === 'recharge') {
|
||||
$relatedInfo = [
|
||||
'target' => '同城便民服务钱包',
|
||||
'usage' => '可用于全平台信息发布、置顶推广及各类便民生活增值服务',
|
||||
];
|
||||
}
|
||||
|
||||
// 优惠券信息
|
||||
$couponName = '';
|
||||
if (!empty($order['coupon_id'])) {
|
||||
$couponName = (string)Db::name('fc_user_coupon')->alias('uc')
|
||||
->join('fc_coupon c', 'c.id = uc.coupon_id', 'LEFT')
|
||||
->where('uc.id', (int)$order['coupon_id'])
|
||||
->value('c.name');
|
||||
}
|
||||
|
||||
// 用户与安全信息
|
||||
$userMobile = isset($user['mobile']) ? (string)$user['mobile'] : '';
|
||||
if ($userMobile !== '' && strlen($userMobile) >= 11) {
|
||||
$userMobile = substr($userMobile, 0, 3) . '****' . substr($userMobile, 7);
|
||||
}
|
||||
|
||||
$detail = [
|
||||
'id' => (int)$order['id'],
|
||||
'orderNo' => (string)$order['order_no'],
|
||||
'type' => $type,
|
||||
'typeText' => isset($typeMap[$type]) ? $typeMap[$type] : '其它订单',
|
||||
'title' => (string)$order['title'],
|
||||
'amount' => (float)$order['amount'],
|
||||
'originAmount' => (!empty($order['origin_amount']) && (float)$order['origin_amount'] > 0) ? (float)$order['origin_amount'] : (float)$order['amount'],
|
||||
'couponAmount' => isset($order['coupon_amount']) ? (float)$order['coupon_amount'] : 0.0,
|
||||
'couponId' => isset($order['coupon_id']) ? (int)$order['coupon_id'] : 0,
|
||||
'couponName' => $couponName,
|
||||
'payType' => (string)$order['pay_type'],
|
||||
'payTypeText' => (string)$order['pay_type'] === 'balance' ? '余额支付' : '微信支付',
|
||||
'status' => (string)$order['status'],
|
||||
'statusText' => isset($statusMap[$order['status']]) ? $statusMap[$order['status']] : (string)$order['status'],
|
||||
'refundReason' => isset($order['refund_reason']) ? (string)$order['refund_reason'] : '',
|
||||
'userAccount' => $userMobile ?: (isset($user['username']) ? (string)$user['username'] : ''),
|
||||
'createdAt' => $this->iso($order['createtime']),
|
||||
'payTime' => !empty($order['paytime']) ? $this->iso($order['paytime']) : null,
|
||||
'closeTime' => ((string)$order['status'] === 'closed' && !empty($order['updatetime'])) ? $this->iso($order['updatetime']) : null,
|
||||
'expireSeconds' => $expireSeconds,
|
||||
'timeoutSeconds' => $timeoutSeconds,
|
||||
'relatedId' => $relatedId,
|
||||
'relatedInfo' => $relatedInfo,
|
||||
];
|
||||
|
||||
$this->ok($detail);
|
||||
}
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户