where('enabled', 1) ->order('sort asc') ->select(); $list = []; foreach ($rows as $row) { $list[] = [ 'planId' => (string)$row['plan_code'], 'name' => (string)$row['name'], 'price' => (float)$row['price'], 'originPrice' => (float)$row['origin_price'], 'days' => (int)$row['days'], 'tag' => (string)$row['tag'], ]; } $this->ok($list); } /** * M2 会员权益 * GET /api/v1/member/benefits → {freeView,postDiscount,distRate,benefits[]} * 规则:读配置 member.benefit,未配置返回默认 */ public function benefits() { $default = [ 'freeView' => 20, 'postDiscount' => '8 折', 'distRate' => '一级 20% / 二级 10%', 'benefits' => ['每日免费查看 20 条联系方式', '发布信息 8 折', '专属会员标识', '分销佣金加速结算'], ]; $cfg = $this->cfg('member.benefit', null); if (!is_array($cfg)) { $cfg = $default; } $benefits = isset($cfg['benefits']) && is_array($cfg['benefits']) && $cfg['benefits'] ? array_values($cfg['benefits']) : $default['benefits']; $this->ok([ 'freeView' => isset($cfg['freeView']) ? (int)$cfg['freeView'] : $default['freeView'], 'postDiscount' => isset($cfg['postDiscount']) ? (string)$cfg['postDiscount'] : $default['postDiscount'], 'distRate' => isset($cfg['distRate']) ? (string)$cfg['distRate'] : $default['distRate'], 'benefits' => $benefits, ]); } /** * M3 开通会员 * POST /api/v1/member/open {planId,payType} → {orderNo,status,expireAt} * 规则 BR-07;套餐按 plan_code 查;余额支付扣 fa_user.money */ public function open() { $user = $this->auth(); $planId = trim((string)$this->input('planId', '')); if ($planId === '') { $this->fail('请选择会员套餐'); } $payType = (string)$this->input('payType', ''); if (!in_array($payType, ['wxpay', 'balance'], true)) { $this->fail('支付方式不支持'); } $plan = Db::name('fc_plan')->where('plan_code', $planId)->find(); if (!$plan) { $this->fail('套餐不存在'); } $amount = round((float)$plan['price'], 2); $now = time(); $orderNo = $this->orderNo('MO'); $orderId = Db::name('fc_order')->insertGetId([ 'order_no' => $orderNo, 'user_id' => $user['id'], 'type' => 'member', 'title' => (string)$plan['name'], 'amount' => $amount, 'pay_type' => $payType, 'status' => 'paid', 'paytime' => $now, 'related_id' => 0, 'createtime' => $now, 'updatetime' => $now, ]); if ($payType === 'balance') { $balance = (float)$user['money']; if ($balance < $amount) { $this->fail('余额不足'); } $balance = round($balance - $amount, 2); Db::name('user')->where('id', $user['id'])->update([ 'money' => $balance, 'updatetime' => $now, ]); } $ext = $this->ext($user['id']); $base = (int)$ext['member_expiretime']; if ($base < $now) { $base = $now; } $expire = $base + (int)$plan['days'] * 86400; Db::name('fc_user_ext')->where('user_id', $user['id'])->update([ 'is_member' => 1, 'member_level' => (string)$plan['name'], 'member_expiretime' => $expire, 'updatetime' => $now, ]); $this->flow('income', '会员开通', $amount, 0, $orderId); $this->ok([ 'orderNo' => $orderNo, 'status' => 'paid', 'expireAt' => $this->iso($expire), ]); } /** * M4 我的订单 * GET /api/v1/member/orders {page,size} → {list,page,size,total,hasMore} * 规则:按 createtime desc */ public function orders() { $user = $this->auth(); list($page, $size) = $this->pager(); $total = Db::name('fc_order')->where('user_id', $user['id'])->count(); $rows = Db::name('fc_order') ->where('user_id', $user['id']) ->order('createtime desc') ->page($page, $size) ->select(); $list = []; foreach ($rows as $row) { $list[] = [ 'id' => (int)$row['id'], 'orderNo' => (string)$row['order_no'], 'type' => (string)$row['type'], 'title' => (string)$row['title'], 'amount' => (float)$row['amount'], 'payType' => (string)$row['pay_type'], 'status' => (string)$row['status'], 'createdAt' => $this->iso($row['createtime']), ]; } $this->ok($this->paginate($list, $total, $page, $size)); } /** * M5 我的资产 * GET /api/v1/member/assets → {balance,coupons:[],points} */ public function assets() { $user = $this->auth(); $this->ok([ 'balance' => (float)$user['money'], 'coupons' => [], 'points' => (int)$user['score'], ]); } }