Laravel 微信小程序后端,用户登录

接上篇微信小程序后端搭建:分享:Laravel 微信小程序后端搭建

后端搭建好后第一件事就是用户登录认证,简单实现微信小程序登录认证

1.user模型
use Laravel\Passport\HasApiTokens;新增

use HasApiTokens, Notifiable;

protected $fillable = [
  'id',
  'name',
  'email',
  'email_verified_at',
  'username',
  'phone',
  'avatar',//我用来把微信头像的/0清晰图片,存到又拍云上
  'weapp_openid',
  'nickname',
  'weapp_avatar',
  'country',
  'province',
  'city',
  'language',
  'location',
  'gender',
  'level',//用户等级
  'is_admin',//is管理员
];

2.新增一条路由

//前端小程序拿到的地址:https://域名/api/v1/自己写的接口
Route::group(['prefix' => '/v1'], function () {
    Route::post('/user/login', 'UserController@weappLogin');
});

3.在UserController控制器里新建function weappLogin(),别忘了use这些

use App\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

写两个function weappLogin(),avatarUpyun()

public function weappLogin(Request $request)
    {
        $code = $request->code;
        // 根据 code 获取微信 openid 和 session_key
        $miniProgram = \EasyWeChat::miniProgram();
        $data = $miniProgram->auth->session($code);
        if (isset($data['errcode'])) {
            return $this->response->errorUnauthorized('code已过期或不正确');
        }
        $weappOpenid = $data['openid'];
        $weixinSessionKey = $data['session_key'];
        $nickname = $request->nickname;
        $avatar = str_replace('/132', '/0', $request->avatar);//拿到分辨率高点的头像
        $country = $request->country?$request->country:'';
        $province = $request->province?$request->province:'';
        $city = $request->city?$request->city:'';
        $gender = $request->gender == '1' ? '1' : '2';//没传过性别的就默认女的吧,体验好些
        $language = $request->language?$request->language:'';

        //找到 openid 对应的用户
        $user = User::where('weapp_openid', $weappOpenid)->first();
        //没有,就注册一个用户
        if (!$user) {
            $user = User::create([
                'weapp_openid' => $weappOpenid,
                'weapp_session_key' => $weixinSessionKey,
                'password' => $weixinSessionKey,
                'avatar' => $request->avatar?$this->avatarUpyun($avatar):'',
                'weapp_avatar' => $avatar,
                'nickname' => $nickname,
                'country' => $country,
                'province' => $province,
                'city' => $city,
                'gender' => $gender,
                'language' => $language,
            ]);
        }
        //如果注册过的,就更新下下面的信息
        $attributes['updated_at'] = now();
        $attributes['weixin_session_key'] = $weixinSessionKey;
        $attributes['weapp_avatar'] = $avatar;
        if ($nickname) {
            $attributes['nickname'] = $nickname;
        }
        if ($request->gender) {
            $attributes['gender'] = $gender;
        }
        // 更新用户数据
        $user->update($attributes);
        // 直接创建token并设置有效期
        $createToken = $user->createToken($user->weapp_openid);
        $createToken->token->expires_at = Carbon::now()->addDays(30);
        $createToken->token->save();
        $token = $createToken->accessToken;

        return response()->json([
            'access_token' => $token,
            'token_type' => "Bearer",
            'expires_in' => Carbon::now()->addDays(30),
            'data' => $user,
        ], 200);
    }

    //我保存到又拍云了,版权归腾讯所有。。。头条闹的
    private function avatarUpyun($avatar)
    {
        $avatarfile = file_get_contents($avatar);
        $filename = 'avatars/' . uniqid() . '.png';//微信的头像链接我也不知道怎么获取后缀,直接保存成png的了
        Storage::disk('upyun')->write($filename, $avatarfile);
        $wexinavatar = config('filesystems.disks.upyun.protocol') . '://' . config('filesystems.disks.upyun.domain') . '/' . $filename;
        return $wexinavatar;//返回链接地址
    }

微信的头像/0
https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTf...

小头像默认/132
https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTf...

4.后端上面就写好了,再看下小程序端怎么做的哈,打开小程序的app.json,添加 "pages/auth/auth",

{
  "pages": [
    "pages/index/index",
    "pages/auth/auth",//做一个登录页面
    "pages/logs/logs"
  ],
  "window": {
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "WeChat",
    "navigationBarTextStyle": "black"
  },
  "sitemapLocation": "sitemap.json",
  "permission": {
    "scope.userLocation": {
      "desc": "你的位置信息将用于小程序位置接口的效果展示"
    }
  }
}

5.打开auth.js

const app = getApp();
Page({
  /**
   * 页面的初始数据
   */
  data: {
    UserData: [],
    isClick: false,
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {

  },
  login: function(e) {
    let that=this
    that.setData({
      isClick: true
    })
    wx.getUserInfo({
      lang: "zh_CN",
      success: response => {
        wx.login({
          success: res => {
            let data = {
              code:res.code,
              nickname: response.userInfo.nickName,
              avatar: response.userInfo.avatarUrl,
              country: response.userInfo.country ? response.userInfo.country : '',
              province: response.userInfo.province ? response.userInfo.province : '',
              city: response.userInfo.city ? response.userInfo.city : '',
              gender: response.userInfo.gender ? response.userInfo.gender : '',
              language: response.userInfo.language ? response.userInfo.language : '',
            }
            console.log(data)
            app.globalData.userInfo = data;
            wx.request({
              url: '你的后端地址',//我用的valet,http://ak.name/api/v1/user/login
              method: 'POST',
              data: data,
              header: {
                'Content-Type': 'application/x-www-form-urlencoded'
              },
              success: function (res) {
                console.log(res)
                if (res.statusCode != '200') {
                  return false;
                }
                wx.setStorageSync('access_token', res.data.access_token)
                wx.setStorageSync('UserData', res.data.data ? res.data.data : '')
                wx.redirectTo({
                  url: '/pages/index/index',
                })
              },
              fail: function (e) {
                wx.showToast({
                  title: '服务器错误',
                  duration: 2000
                });
                that.setData({
                  isClick: false
                })
              },
            });
          }
        })
      },
      fail: function (e) {
        that.setData({
          isClick: false
        })
      },
    })

  }
})

6.打开auth.wxml

<view class='padding-xl'>
  <button class='cu-btn margin-top bg-green shadow lg block' open-type="getUserInfo" bindgetuserinfo="login" disabled="{{isClick}}" type='success'>
    <text wx:if="{{isClick}}" class='cuIcon-loading2 iconfont-spin'></text> 微信登录</button>
</view>
本帖已被设为精华帖!
本帖由系统于 4年前 自动加精
讨论数量: 7

file
这是怎么回事呢?

4年前 评论
jinduo (楼主) 4年前

正在学习小程序的登录授权,刚好不想使用JWT,想使用passport,API部分也不想使用教程的Dingo,版主能否把登录授权部分还有记录更新用户信息部分做个开源项目分享一下?

4年前 评论

https://gitee.com/jduo/jining
小专题的后端
file

4年前 评论
laravel_denghy 4年前
Savory 4年前
gaorenhua 4年前
lovnie 3年前
jinduo (作者) (楼主) 3年前
lovnie 3年前
chenzx
$createToken = $user->createToken($user->weapp_openid);这里为啥可以设置token呢 
4年前 评论

user.php model use HasApiTokens

4年前 评论

怎么感觉 session_key 写到数据库没什么 用

4年前 评论

提示服务器错误,怎么回事

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!