我正在参加「掘金·启航计划」
一、微信小程序前端
1.1 小程序前端准备
上微信公众平台注册一个小程序,注册完成之后你就有APPID
和SECRET
。
1、api封装
根目录下定义wxapi
文件夹,我们将api
请求独立出来封装,在wxapi
文件夹下写入request.js
:
const requestObj = require('./request.config.js')
requestObj.request = ({
url,
method,
data = '',
token = ''
}) => {
let _url = requestObj.API_BASE_URL + url
return new Promise((resolve, reject) => {
wx.showLoading({
title: '加载中...',
})
wx.request({
url: _url,
method: method,
data,
header: {
// 'content-type': 'application/x-www-form-urlencoded',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
success(request) {
console.log(request)
if (request.data.code == 401) {
wx.navigateTo({
url: '/pages/authpage/authpage',
})
wx.showToast({
title: '请重新登录',
icon: 'none'
})
}
resolve(request.data)
},
fail(error) {
reject(error)
wx.navigateTo({
url: '../networkerror/networkerror',
})
},
complete() {
// 加载完成
wx.hideLoading()
}
})
})
}
/**
* 小程序的promise扩展finally方法
*/
Promise.prototype.finally = function (callback) {
var Promise = this.constructor;
return this.then(
function (value) {
Promise.resolve(callback()).then(
function () {
return value;
}
);
},
function (reason) {
Promise.resolve(callback()).then(
function () {
throw reason;
}
);
}
);
}
module.exports = requestObj
复制代码
我们将相关的配置写入request.config.js
(与request.js
同层目录):
const requestObj = {
API_BASE_URL: 'http://jtminiprogramapi.com/api', // 小程序接口线上地址
// API_BASE_URL: 'http://192.168.91.112:8085/', // 小程序接口线下地址
}
module.exports = requestObj
复制代码
再在wxapi
文件夹创建api
文件夹,里面写我们各个模块的apis
,apis
文件夹下写入userApi.js
(我们将用户相关的接口全部写在这这里只演示用户登陆):
const requestObj = require('../request')
let userApi = {
/* 微信登录获取token */
getToken: (data, method) => requestObj.request({
url: '/wxlogin', method: method, data
}),
}
module.exports = userApi;
复制代码
在wxapi
文件夹下写入index.js
:
const userApi = require('./apis/userApi');
module.exports = {
userApi,
}
复制代码
api
分模块封装完毕,它的目录结构如下:
2、授权独立页面
微信开发者工具中写入独立授权页面: authpage.wxml
:
<view class='headView'>
<open-data class='icon' mode="aspectFit" type="userAvatarUrl"></open-data>
<view class='icon'></view>
</view>
<view class="auth-btn">
<button bindtap="getUserProfile">授权登录</button>
</view>
<view class="cancel-btn" bindtap="cancelAuth">取消授权登录</view>
<van-toast id="van-toast" />
复制代码
authpage.js
:
import Toast from '@vant/weapp/toast/index';
const WXAPI = require('../../wxapi/index');
Page({
/**
* 页面的初始数据
*/
data: {
},
// 点击取消授权
cancelAuth () {
wx.switchTab({
url: '../index/index'
})
},
getUserProfile () {
wx.getUserProfile({
desc: '完善个人资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (newWes) => {
let userInfo = newWes.userInfo
wx.setStorageSync('userInfo', newWes.userInfo)
wx.login({
success (res) {
let code = res.code
if (code) {
wx.showLoading({
title: '加载中',
})
WXAPI.userApi.getToken({
userInfo,
code
}, 'POST').then((res) => {
console.log(res)
wx.setStorageSync('authFlag', true)
wx.setStorageSync('token', res.access_token)
wx.navigateBack({
delta: 1
})
}, (err) => {
console.log(err)
}).finally(() => {
wx.hideLoading({})
})
}
}
})
},
fail: (err) => {
console.log(err)
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
复制代码
authpage.wxss
:
.headView {
display: flex;
justify-content: center;
align-items:center;
margin-top: 50rpx;
height:300rpx;
width:750rpx;
position:relative;
margin-bottom: 50rpx;
}
/**
*open-data 的头像做不了圆角
*这里是覆盖一个镂空的view在上面 镂空view的边界做成与周围背景颜色一样 做了伪圆角
**/
.headView .icon {
position: absolute;
height: 200rpx;
width: 200rpx;
border-radius: 50%;
border: 50rpx solid #f1f1f1;
}
.cancel-btn {
display: block;
margin-left: auto;
margin-right: auto;
padding-left: 14px;
padding-right: 14px;
box-sizing: border-box;
font-size: 18px;
text-align: center;
text-decoration: none;
line-height: 2.55555556;
border-radius: 5px;
-webkit-tap-highlight-color: transparent;
overflow: hidden;
cursor: pointer;
color: #000;
background-color: #f8f8f8;
margin-top: 50rpx;
padding: 8px 24px;
line-height: 1.41176471;
border-radius: 4px;
font-weight: 700;
font-size: 17px;
width: 184px;
margin-left: auto;
margin-right: auto;
position: relative;
}
.auth-btn {
width: 184px;
margin: 0 auto;
height: 40px;
}
button {
height: 100%;
line-height: 40px;
font-weight: normal;
background-color: #546D7A;
color: #fff;
}
button::after {
border: none;
}
.cancel-btn {
font-weight: normal;
}
复制代码
authpage.json
:
{
"usingComponents": {
"van-toast": "@vant/weapp/toast/index"
},
"navigationBarTitleText": "授权登录"
}
复制代码
二、微信小程序后端(laravel)
2.1 小程序后端准备
1、项目安装dingo/api以及jwt认证
可以参考我的这篇文章。
2、创建小程序用户表和模型
运行命令php artisan make:Model miniProgram/mpUser -m
: 迁移文件写入字段:
Schema::create('mp_users', function (Blueprint $table) {
$table->id();
$table->string('openid')->comment('用户小程序唯一id');
$table->string('nickname')->comment('用户小程序昵称');
$table->string('avatar')->comment('用户小程序头像');
$table->string('country')->comment('用户小程序国家');
$table->string('province')->comment('用户小程序省份');
$table->string('city')->comment('用户小程序城市');
$table->string('weixin_session_key')->comment('用户登陆session');
$table->string('gender')->comment('用户性别: 1 -> 男,0 -> 女');
$table->string('name')->nullable()->comment('用户真实姓名');
$table->string('email')->nullable()->comment('用户邮箱');
$table->timestamps();
});
复制代码
运行迁移命令php artisan migrate
:
3、安装easywechat插件
这个插件让你更快的对接微信的接口。 运行命令composer require "overtrue/laravel-wechat:^6.0"
:
在中间件 App\Http\Middleware\VerifyCsrfToken
排除微信相关的路由:
运行命令php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider"
发布相关配置。 在config/wechat.php
中将小程序的配置打开: 然后在.env
文件下写入:
4、创建小程序授权登陆认证控制器
运行命令php artisan make:controller Auth/mpAuthorizationsController
: 写入方法:
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\miniProgram\mpUser;
use GrahamCampbell\ResultType\Result;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class mpAuthorizationsController extends Controller
{
/**
* name:SWT用户登录,小程序微信登录
*/
public function store(Request $request)
{
Log::debug($request->all());
$code = $request->code;
$nick_name = $request->userInfo['nickName'];
$avatar = $request->userInfo['avatarUrl'];
$gender = $request->userInfo['gender'];
$country = $request->userInfo['country'];
$province = $request->userInfo['province'];
$city = $request->userInfo['city'];
// 根据 code 获取微信 openid 和 session_key
$miniProgram = \EasyWeChat::miniProgram();
$data = $miniProgram->auth->session($code);
// 如果结果错误,说明 code 已过期或不正确,返回 401 错误
if (isset($data['errcode'])) {
return Result::fail('code不正确');
}
// 找到 openid 对应的用户
$userInfo = mpUser::where('openid', $data['openid'])->first();
$attributes['weixin_session_key'] = $data['session_key'];
if(!$userInfo){
//更新用户信息
$userInfo = new mpUser();
$userInfo->openid = $data['openid'];
$userInfo->weixin_session_key = $data['session_key'];
$userInfo->nickname = $nick_name;
$userInfo->avatar = $avatar;
$userInfo->gender = $gender;
$userInfo->country = $country;
$userInfo->province = $province;
$userInfo->city = $city;
$userInfo->save();
}else{
// 更新用户数据
$userInfo->update($attributes);
}
// 为对应用户创建 JWT
$token = auth('api')->login($userInfo);
return $this->respondWithToken($token)->setStatusCode(201);
}
/**
* Get the token array structure.
*
* @param string $token
*
* @return \Illuminate\Http\JsonResponse
*/
protected function respondWithToken($token)
{
return response()->json([
'status_code' => '1',
'msg' => '登陆成功!',
'access_token' => $token,
'token_type' => 'Bearer',
'expires_in' => auth('api')->factory()->getTTL() * 60
]);
}
}
复制代码
5、授权登陆路由
routes/api.php
:
<?php
use App\Http\Controllers\Auth\mpAuthorizationsController;
$api = app('Dingo\Api\Routing\Router');
$api->version('v1', function ($api) {
// 需要登陆的路由
$api->group(['middleware' => 'api.auth'], function($api) {
$api->get('users', [\App\Http\Controllers\TestController::class, 'users']);
});
// 执行登陆
$api->any('wxlogin', [mpAuthorizationsController::class, 'store']);
});
复制代码
三、测试效果
小程序端已发送请求并且拿到了token
。 接着我们去看下数据库中是否有我们登陆小程序的用户信息,以及需要和微信服务器打交道的session_key
: 可以看到这边我们相关的用户信息基本都有了,头像昵称openid
、session_key
。
在学习实战的路上,如果你觉得本文对你有所帮助的话,那就请关注点赞评论三连吧,谢谢,你的肯定是我写博的另一个支持。