bool,'msg'=>string,'data'=>array] */ public static function redeem(int $uid, string $cardno, string $password): array { if ($uid <= 0 || $cardno === '' || $password === '') { return ['success' => false, 'msg' => '参数不完整']; } $card = self::where('cardno', $cardno)->find(); if (empty($card)) { return ['success' => false, 'msg' => '卡密不存在']; } if ($card->delete_at > 0) { return ['success' => false, 'msg' => '卡密已失效']; } if ((int)$card->status === self::STATUS_USED) { return ['success' => false, 'msg' => '该卡密已被使用']; } // 密码校验(存储若为明文,按需改为 password_verify) if ((string)$card->password !== (string)$password) { return ['success' => false, 'msg' => '卡号或密码错误']; } $amount = (float)$card->amount; if ($amount <= 0) { return ['success' => false, 'msg' => '卡密面值异常']; } Db::startTrans(); try { // 1) 卡密标记已用,绑定会员 $card->status = self::STATUS_USED; $card->use_time = time(); $card->uid = $uid; $card->save(); // 2) 会员钱包加余额 + 累计充值(无钱包则自动创建) $wallet = Db::name('member_wallets')->where('uid', $uid)->find(); if (empty($wallet)) { Db::name('member_wallets')->insert([ 'uid' => $uid, 'balance' => $amount, 'total_recharge' => $amount, 'create_at' => time(), 'update_at' => time(), ]); } else { Db::name('member_wallets') ->where('uid', $uid) ->inc('balance', $amount) ->inc('total_recharge', $amount) ->update(['update_at' => time()]); } // 3) 充值流水 Db::name('member_bill')->insert([ 'uid' => $uid, 'type' => 1, // 充值 'amount' => $amount, 'currency' => 1, // 人民币 'channel' => 'card', 'order_no' => 'CARD' . date('YmdHis') . $uid . mt_rand(100, 999), 'status' => 1, // 成功 'description' => '卡密充值:' . $cardno, 'create_at' => time(), 'update_at' => time(), ]); Db::commit(); return [ 'success' => true, 'msg' => '兑换成功,已充值 ¥' . number_format($amount, 2), 'data' => ['amount' => $amount], ]; } catch (\Throwable $e) { Db::rollback(); throw $e; } } /** * 批量生成卡密 * * @param int $count 生成数量 * @param float $amount 面值 * @param string $prefix 卡号前缀(如 YX) * @return array 生成的卡号列表 */ public static function generateBatch(int $count, float $amount, string $prefix = ''): array { $count = max(1, min(200, $count)); // 单次上限保护 $batchNo = date('YmdHis') . mt_rand(1000, 9999); $list = []; $rows = []; for ($i = 0; $i < $count; $i++) { $cardno = ($prefix ?: 'YX') . strtoupper(substr(md5(uniqid((string)mt_rand(), true)), 0, 16)); $password = strtoupper(substr(md5(uniqid((string)mt_rand(), true)), 0, 8)); $list[] = ['cardno' => $cardno, 'password' => $password]; $rows[] = [ 'cardno' => $cardno, 'password' => $password, 'amount' => $amount, 'status' => self::STATUS_UNSOLD, 'batch_no' => $batchNo, 'create_at' => time(), 'update_at' => time(), ]; } self::insertAll($rows); return $list; } }