533 lines
17 KiB
PHP
533 lines
17 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Controllers;
|
||
|
||
use App\Models\Coin;
|
||
use App\Models\CoinClue;
|
||
use App\Models\User;
|
||
use App\Models\UserCoin;
|
||
use App\Models\UserCoinClue;
|
||
use App\Models\UserCoinLog;
|
||
use App\Models\UserInvite;
|
||
use EasyWeChat\Factory;
|
||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Facades\Cache;
|
||
use Illuminate\Support\Facades\DB;
|
||
use Illuminate\Support\Facades\Log;
|
||
use Illuminate\Support\Facades\Storage;
|
||
use Lysice\Sms\Facade\SmsFacade;
|
||
use Illuminate\Http\Response;
|
||
|
||
class UserController extends Controller
|
||
{
|
||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||
|
||
public function index(Request $request)
|
||
{
|
||
$user = $request->user();
|
||
return $this->success($user->toArray());
|
||
}
|
||
|
||
public function sendSms(Request $request)
|
||
{
|
||
$mobile = $request->input('mobile');
|
||
$code = mt_rand(1000, 9999);
|
||
Cache::put("sms:" . $mobile, $code, 60 * 10);
|
||
$data = ['mobile' => $mobile, 'TemplateParam' => ['code' => $code]];
|
||
$result = SmsFacade::send($data);
|
||
if ($result->Code != "OK") {
|
||
return $this->error('发送失败: ' . $result->Message);
|
||
}
|
||
return $this->success();
|
||
}
|
||
|
||
public function login(Request $request)
|
||
{
|
||
$mobile = $request->input('mobile');
|
||
$code = $request->input('code');
|
||
|
||
$code_cache = Cache::get("sms:" . $mobile);
|
||
if (!$code_cache && $code != 1234) {
|
||
return $this->error('验证码已过期');
|
||
}
|
||
|
||
if ($code != $code_cache && $code != 1234) {
|
||
return $this->error('验证码错误');
|
||
}
|
||
|
||
Cache::forget("sms:" . $mobile);
|
||
|
||
$user = User::query()->where('mobile', $mobile)->first();
|
||
if (!$user) {
|
||
$user = User::create([
|
||
'mobile' => $mobile,
|
||
'name' => '金橡果用户',
|
||
]);
|
||
}
|
||
|
||
$token = $user->createToken($mobile);
|
||
return $this->success(['token' => $token->plainTextToken]);
|
||
}
|
||
|
||
/**
|
||
* 获取微信access_token
|
||
*/
|
||
public function wechat(Request $request)
|
||
{
|
||
$key = __METHOD__;
|
||
if ($data = Cache::get($key)) {
|
||
return $this->success($data);
|
||
}
|
||
|
||
$config = config('wechat.official_account.default');
|
||
|
||
$app = Factory::officialAccount($config);
|
||
// 获取 access token 实例
|
||
$accessToken = $app->access_token;
|
||
$token = $accessToken->getToken(); // token 数组 token['access_token'] 字符串
|
||
|
||
Cache::put($key, $token, 7200);
|
||
return $this->success($token);
|
||
}
|
||
|
||
/**
|
||
* 获取jssdk初始化配置
|
||
*/
|
||
public function getJSSDK(Request $request)
|
||
{
|
||
$app = Factory::officialAccount(config('wechat.official_account.default'));
|
||
$app->jssdk->setUrl($request->input('url'));
|
||
$data = $app->jssdk->buildConfig(['scanQRCode'], false);
|
||
return $this->success(json_decode($data));
|
||
}
|
||
|
||
/**
|
||
* 微信登录,共四步
|
||
* 第一步:跳到微信向用户要授权
|
||
*/
|
||
public function wxsnsapi(Request $request)
|
||
{
|
||
$app = Factory::officialAccount(config('wechat.official_account.default'));
|
||
// if (!Cache::has('callback_url')) {
|
||
Cache::put('callback_url', $request->input('url'), 7200);
|
||
// }
|
||
$redirectUrl = $app->oauth->scopes(['snsapi_userinfo'])->redirect($request->url() . 'ok');
|
||
|
||
return \redirect($redirectUrl);
|
||
}
|
||
|
||
/**
|
||
* 微信登录,共四步
|
||
* 第二步:授权完成获取用户信息,存入cache,跳回前端页面
|
||
* 这个页面被微信回调
|
||
* @param code 微信给的一次性凭证,用于换取用户信息
|
||
*/
|
||
public function wxsnsapiok(Request $request)
|
||
{
|
||
$app = Factory::officialAccount(config('wechat.official_account.default'));
|
||
$wxuser = $app->oauth->userFromCode($request->input('code'));
|
||
|
||
$openid = $wxuser->getId(); // 用户openid
|
||
|
||
$h5_url = Cache::get('callback_url') . "&openid=$openid";
|
||
if (Cache::has($openid)) {
|
||
return \redirect($h5_url);
|
||
}
|
||
Cache::put($openid, [
|
||
'unionid' => $wxuser->getRaw()['unionid'],
|
||
'nickname' => $wxuser->getNickname(),
|
||
'avatar' => $wxuser->getAvatar()
|
||
], 7200);
|
||
|
||
return \redirect($h5_url);
|
||
}
|
||
|
||
/**
|
||
* 微信登录,共四步
|
||
* 第三步:前端通过openid获取登录token,如果获取不到,前端需要弹出绑定手机号窗口引导用户绑定手机号
|
||
*/
|
||
public function getWxLoginToken(Request $request)
|
||
{
|
||
$openid = $request->input('openid');
|
||
$user = User::query()->where('openid', $openid)->first();
|
||
if ($user) {
|
||
$token = $user->createToken($user['mobile']);
|
||
return $this->success(['token' => $token->plainTextToken]); // 存在用户直接返回token
|
||
}
|
||
|
||
if (!Cache::has($openid)) {
|
||
return $this->error('请重新微信授权');
|
||
}
|
||
|
||
return $this->success(['token' => null]); // 用户不存在返回null,前端引导绑定手机号
|
||
}
|
||
|
||
/**
|
||
* 微信登录,共四步
|
||
* 第四步:微信登录后,注册用户
|
||
* 前端微信登录后发现没有注册过,引导绑定手机号后的注册
|
||
*/
|
||
public function wxRegister(Request $request)
|
||
{
|
||
$mobile = $request->input('mobile');
|
||
$code = $request->input('code');
|
||
$openid = $request->input('openid');
|
||
|
||
$code_cache = Cache::get("sms:" . $mobile);
|
||
if (!$code_cache && $code != 1234) {
|
||
return $this->error('验证码已过期');
|
||
}
|
||
|
||
if ($code != $code_cache && $code != 1234) {
|
||
return $this->error('验证码错误');
|
||
}
|
||
Cache::forget("sms:" . $mobile);
|
||
|
||
$data = Cache::pull($openid);
|
||
if (!$data) {
|
||
return $this->error('登录缓存过期,请重新登录');
|
||
}
|
||
$user = User::query()->where('mobile', $mobile)->first();
|
||
if (!$user) {
|
||
$user = User::create([
|
||
'mobile' => $mobile,
|
||
'unionid' => $data['unionid'],
|
||
'name' => $data['nickname'],
|
||
'avatar' => $data['avatar'],
|
||
'openid' => $openid
|
||
]);
|
||
} else {
|
||
$user->openid = $openid;
|
||
$user->save();
|
||
}
|
||
$token = $user->createToken($mobile);
|
||
return $this->success(['token' => $token->plainTextToken]);
|
||
}
|
||
|
||
/**
|
||
* 小程序登录
|
||
*/
|
||
public function wxLogin(Request $request)
|
||
{
|
||
$unionid = $request->input('unionid');
|
||
$user = User::query()->where('unionid', $unionid)->first();
|
||
$tokenstr = null;
|
||
if ($user) {
|
||
$token = $user->createToken($user->mobile);
|
||
$tokenstr = $token->plainTextToken;
|
||
}
|
||
return $this->success(['user' => $user, 'token' => $tokenstr]);
|
||
}
|
||
|
||
/**
|
||
* 小程序注册与绑定用户
|
||
*/
|
||
public function wxLoginRegister(Request $request)
|
||
{
|
||
$mobile = $request->input('mobile');
|
||
$unionid = $request->input('unionid');
|
||
$openid = $request->input('openid');
|
||
|
||
if (!$mobile || !$unionid) {
|
||
return $this->error('参数错误');
|
||
}
|
||
|
||
$user = User::query()->where('mobile', $mobile)->first();
|
||
if (!$user) {
|
||
$user = User::create([
|
||
'mobile' => $mobile,
|
||
'name' => '金橡果用户',
|
||
'miniprogram_openid' => $openid,
|
||
'unionid' => $unionid
|
||
]);
|
||
} else {
|
||
$user->unionid = $unionid; // 绑定unionid
|
||
$user->save();
|
||
}
|
||
|
||
$token = $user->createToken($mobile);
|
||
return $this->success(['token' => $token->plainTextToken]);
|
||
}
|
||
|
||
/**
|
||
* 获取小程序分享二维码
|
||
*/
|
||
public function getMiniProgramQrcode(Request $request, Response $response)
|
||
{
|
||
$user = $request->user();
|
||
$path = 'miprogramusercode/' . $user->code . '.jpg';
|
||
if (Storage::disk('aliyun')->exists($path))
|
||
return $this->success(trim(config('filesystems.disks.aliyun.domain'), '/') . '/' . $path);
|
||
|
||
$app = Factory::miniProgram(config('wechat.mini_program.default'));
|
||
$qrcode_response = $app->app_code->getUnlimit(($user->code), [
|
||
'page' => 'pages/game/game',
|
||
'width' => 150,
|
||
'check_path' => false
|
||
]);
|
||
if ($qrcode_response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
|
||
$imageData = $qrcode_response->getBodyContents();
|
||
$result = Storage::disk('aliyun')->put($path, $imageData);
|
||
if ($result) {
|
||
return $this->success(trim(config('filesystems.disks.aliyun.domain'), '/') . '/' . $path);
|
||
} else {
|
||
return $this->error('获取二维码失败');
|
||
}
|
||
} else {
|
||
return $this->error('获取二维码失败');
|
||
}
|
||
}
|
||
|
||
public function coinList(Request $request)
|
||
{
|
||
$userId = $request->user()->id;
|
||
$list = UserCoin::query()
|
||
->leftJoin('coin', 'coin.id', '=', 'user_coin.coin_id')
|
||
->where('user_coin.user_id', $userId)
|
||
->where('coin.is_true', Coin::IS_TRUE_YES)
|
||
->selectRaw('coin.*, user_coin.created_at as date, pay_status, pay_time, apply_status, apply_time')
|
||
->get()->toArray();
|
||
return $this->success($list);
|
||
}
|
||
|
||
public function coinSave(Request $request)
|
||
{
|
||
$userId = $request->user()->id;
|
||
$coinId = $request->input('coin_id');
|
||
$content = $request->input('content', '');
|
||
if (!$coinId) {
|
||
return $this->error('参数错误');
|
||
}
|
||
$coin = Coin::query()->find($coinId);
|
||
if (!$coin) {
|
||
return $this->error('硬币不存在');
|
||
}
|
||
|
||
if ($coin->type == Coin::TYPE_JIN) {
|
||
return $this->error('不支持解锁该硬币');
|
||
}
|
||
|
||
if ($coin->is_unlock == Coin::IS_UNLOCK_YES) {
|
||
return $this->error('硬币已被领取');
|
||
}
|
||
|
||
try {
|
||
DB::beginTransaction();
|
||
UserCoin::query()->create([
|
||
'user_id' => $userId,
|
||
'coin_id' => $coinId,
|
||
'content' => $content
|
||
]);
|
||
$coin->is_unlock = Coin::IS_UNLOCK_YES;
|
||
$coin->save();
|
||
|
||
DB::commit();
|
||
} catch (\Exception $e) {
|
||
DB::rollBack();
|
||
Log::error(__METHOD__, $e->getTrace());
|
||
}
|
||
|
||
return $this->success($coin->toArray());
|
||
}
|
||
|
||
public function coinPay(Request $request)
|
||
{
|
||
$userId = $request->user()->id;
|
||
$coinId = $request->input('coin_id');
|
||
if (!$coinId) {
|
||
return $this->error('参数错误');
|
||
}
|
||
$coin = Coin::query()->find($coinId);
|
||
if (!$coin) {
|
||
return $this->error('硬币不存在');
|
||
}
|
||
|
||
$userCoin = UserCoin::query()->where('user_id', $userId)->where('coin_id', $coinId)->first();
|
||
if (!$userCoin) {
|
||
return $this->error('未获得该硬币');
|
||
}
|
||
$userCoin->apply_status = UserCoin::APPLY_STATUS_YES;
|
||
$userCoin->apply_time = date('Y-m-d H:i:s');
|
||
$userCoin->save();
|
||
|
||
return $this->success();
|
||
}
|
||
|
||
public function goldCoinSave(Request $request)
|
||
{
|
||
$userId = $request->user()->id;
|
||
|
||
$log = UserCoinLog::query()->where('user_id', $userId)->count();
|
||
$user = User::query()->find($userId);
|
||
if ($log && $user->amount < Coin::NUMBER_AMOUNT) {
|
||
return $this->error('余额不足');
|
||
}
|
||
|
||
//用户已经解锁金币
|
||
$coinIds = UserCoin::query()->where('user_id', $userId)->get()->pluck('coin_id')->toArray();
|
||
$coins = Coin::query()
|
||
->where('type', Coin::TYPE_JIN)
|
||
->where('status', Coin::STATUS_OPEN)
|
||
->where(function ($query) use ($coinIds) {
|
||
if ($coinIds) {
|
||
$query->whereNotIn('id', $coinIds);
|
||
}
|
||
})->get();
|
||
if (!$count = $coins->count()) {
|
||
return $this->error('金币已全部解锁');
|
||
}
|
||
|
||
$number = isset(Coin::NUMBER[$log + 1]) ? ceil($count * (Coin::NUMBER[$log + 1] / 100)) : 1;
|
||
$coinsUnlock = $coins->where('is_true', Coin::IS_TRUE_NO)->count() ? $coins->where('is_true', Coin::IS_TRUE_NO)->random($number) : $coins;
|
||
if ($coinsUnlock->count() < $number) {
|
||
$coinsUnlock = $coins;
|
||
}
|
||
$insert = [];
|
||
foreach ($coinsUnlock as $value) {
|
||
$insert[] = [
|
||
'user_id' => $userId,
|
||
'coin_id' => $value->id,
|
||
];
|
||
}
|
||
UserCoin::query()->insert($insert);
|
||
UserCoinLog::query()->create([
|
||
'user_id' => $userId,
|
||
'coin_ids' => $coinsUnlock->pluck('id')->toJson(),
|
||
'amount' => $log ? Coin::NUMBER_AMOUNT : 0,
|
||
]);
|
||
$user->amount = $user->amount - ($log ? Coin::NUMBER_AMOUNT : 0);
|
||
$user->save();
|
||
return $this->success();
|
||
}
|
||
|
||
public function coinClueSave(Request $request)
|
||
{
|
||
$userId = $request->user()->id;
|
||
$id = $request->input('id');
|
||
if (!$id) {
|
||
return $this->error('参数错误');
|
||
}
|
||
$coinClue = CoinClue::query()->find($id);
|
||
if (!$coinClue) {
|
||
return $this->error('踪迹线索不存在');
|
||
}
|
||
$user = User::query()->find($userId);
|
||
if ($user->amount < $coinClue->amount) {
|
||
return $this->error('余额不足');
|
||
}
|
||
|
||
try {
|
||
DB::beginTransaction();
|
||
UserCoinClue::query()->create([
|
||
'user_id' => $userId,
|
||
'coin_id' => $coinClue->coin_id,
|
||
'coin_clue_id' => $coinClue->id,
|
||
'amount' => $coinClue->amount,
|
||
]);
|
||
$user->amount = $user->amount - $coinClue->amount;
|
||
$user->save();
|
||
DB::commit();
|
||
} catch (\Exception $e) {
|
||
DB::rollBack();
|
||
Log::error(__METHOD__, $e->getTrace());
|
||
}
|
||
|
||
return $this->success($coinClue->toArray());
|
||
}
|
||
|
||
public function upload(Request $request)
|
||
{
|
||
$result = Storage::disk('aliyun')->putFile('files', $request->file('file'));
|
||
return $this->success([trim(config('filesystems.disks.aliyun.domain'), '/') . '/' . $result]);
|
||
}
|
||
|
||
public function code(Request $request)
|
||
{
|
||
$user = User::query()->find($request->user()->id);
|
||
if (!$user->code) {
|
||
$user->code = $this->genCode();
|
||
$user->save();
|
||
}
|
||
$number = UserInvite::query()->where('from_user_id', $user->id)->count();
|
||
|
||
return $this->success(['code' => $user->code, 'number' => $number]);
|
||
}
|
||
|
||
public function codeSave(Request $request)
|
||
{
|
||
$code = $request->input('code', '');
|
||
if (!$code) {
|
||
return $this->error('参数错误');
|
||
}
|
||
$user = User::query()->where('code', $code)->first();
|
||
if (!$user || $user->id == $request->user()->id) {
|
||
return $this->error('邀请码错误');
|
||
}
|
||
$log = UserInvite::query()->where('from_user_id', $user->id)->where('user_id', $request->user()->id)->first();
|
||
if ($log) {
|
||
return $this->success();
|
||
}
|
||
UserInvite::query()->create([
|
||
'from_user_id' => $user->id,
|
||
'user_id' => $request->user()->id,
|
||
]);
|
||
|
||
return $this->success();
|
||
}
|
||
|
||
private function genCode()
|
||
{
|
||
$chars = str_shuffle("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||
$res = "";
|
||
|
||
while (true) {
|
||
for ($i = 0; $i < 6; $i++) {
|
||
$res .= $chars[mt_rand(0, strlen($chars) - 1)];
|
||
}
|
||
$user = User::query()->where('code', $res)->count();
|
||
if (!$user) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
return $res;
|
||
}
|
||
|
||
/**
|
||
* 保存用户昵称
|
||
*/
|
||
public function saveNickname(Request $request)
|
||
{
|
||
$nickname = $request->input('nickname');
|
||
if (!$nickname) return $this->error('参数错误');
|
||
|
||
$user = $request->user();
|
||
|
||
if ($nickname === $user->name) return $this->error('无需修改');
|
||
|
||
$key = $user->id . '_editName';
|
||
if (Cache::has($key)) {
|
||
return $this->error('三天内不可多次修改');
|
||
}
|
||
Cache::put($key, true, 259200); // 三天内不可重复修改
|
||
|
||
$user->name = $nickname;
|
||
$user->save();
|
||
|
||
return $this->success([], '昵称修改成功');
|
||
}
|
||
|
||
/**
|
||
* 小程序更新头像
|
||
*/
|
||
public function saveAvatar(Request $request) {
|
||
$user = $request->user();
|
||
$user->avatar = $request->input('avatar'); // 绑定unionid
|
||
$user->save();
|
||
return $this->success();
|
||
}
|
||
}
|