微信小程序+nodeJs+express+mongodb踩坑记录 4、uniAPP wx小程序登录前端+后台实现

3 篇文章 0 订阅
2 篇文章 0 订阅

前言

上个月的加班已经结束了,绩效进行微信小程序商城的开发,后台管理系统初步完成,小程序首页已经展示了商品,下一步就是添加购物车,生成订单;这里就设计到小程序登录。 记载一下自己的实现过程,下次直接copy。

一、实现思路

在添加购物车或着其它需要登录才能进行的操作时,先判断是否登录。进入登录页面,先使用wx.getSetting()方法判断是否授权,如果授权了,直接使用wx.login()获取Code 向后台发送请求,换取openid(下面会讲)。然后再调用wx.getUserInfo()拿到用户信息,调接口更新用户信息,成功后返回之前页面。
如果没有授权,则显示出授权页面,提醒用户点击按钮进行授权,然后重复上面的操作。

二、授权按钮界面

在这里插入图片描述
在这里插入图片描述

三、前端代码

这里贴的代码是通过uniapp写的,如果是原生写法,只需要做对应的修改即可

<template>
	<view class="login">
		<view v-if="isCanUse">
			<view>
				<view class="header"><image src="../../static/wx_login.png"></image></view>
				<view class="content">
					<view>申请获取以下权限</view>
					<text>获得你的公开信息(昵称,头像、地区等)</text>
				</view>

				<button class="bottom" type="primary" open-type="getUserInfo" withCredentials="true" lang="zh_CN" @getuserinfo="wxGetUserInfo">授权登录</button>
			</view>
		</view>
		<u-toast ref="uToast" />
	</view>
</template>

<script>
export default {
	name: 'login',
	data() {
		return {
			SessionKey: '',
			OpenId: '',
			nickName: null,
			avatarUrl: null,
			isCanUse: uni.getStorageSync('isCanUse') || true //默认为true
		};
	},
	onLoad() {
		//默认加载
		this.login();
		this.isCanUse = uni.getStorageSync('isCanUse');
	},
	methods: {
		//第一授权获取用户信息===》按钮触发
		wxGetUserInfo() {
			let _this = this;
			uni.getUserInfo({
				provider: 'weixin',
				success: function(infoRes) {
					uni.setStorageSync('isCanUse', false); //记录是否第一次授权  false:表示不是第一次授权
					_this.userLogin(infoRes.userInfo);
				},
				fail(res) {
					 uni.showToast({title:"微信登录授权失败",icon:"none"});
				}
			});
		},
		//登录
		login() {
			let _this = this;
			wx.getSetting({
				success: function(res) {
					if (res.authSetting['scope.userInfo']) {
						console.log('用户授权了');
						uni.showLoading({
						    	title:"登录中..."
							})
						uni.setStorageSync('isCanUse', false);//记录是否第一次授权  false:表示不是第一次授权
						_this.userLogin();
					} else {
						//用户没有授权

						console.log('用户没有授权');
						_this.isCanUse = true;
					}
				}
			});
		},
		userLogin(data) {
			let _this = this;
			// 1.wx获取登录用户code
			uni.login({
				provider: 'weixin',
				success: function(loginRes) {
					let code = loginRes.code;
					//2.将用户登录code传递到后台置换用户SessionKey、OpenId等信息
					_this.$api.getOpenId({ code }).then(res => {
						uni.hideLoading()
						if (!data) {
							uni.getUserInfo({
								provider: 'weixin',
								success: function(infoRes) {
									_this.$store.commit('SET_STATE', ['userInfo', infoRes.userInfo]);
									//获取用户信息后向调用信息更新方法
									_this.updateUserInfo(infoRes.userInfo, res.data); //调用更新信息方法
								}
							});
						} else {
							_this.updateUserInfo(data, res.data); //调用更新信息方法
						}
					});
				}
			});
		},
		//向后台更新信息
		updateUserInfo(info,openInfo) {
			const { avatarUrl, city, country, gender,language, nickName, province} = info
			const { _id } = openInfo.data
			let _this = this;
			this.$api.login({avatarUrl, city, country, gender,language, nickName, province, _id}).then(res=>{
				if(res.data.isSuccess){
					_this.$store.commit('SET_STATE',['userInfo',res.data.data])
					_this.$store.commit('SET_STATE',['token',res.data.data.token])
					uni.setStorageSync('token',res.data.data.token)
					_this.$refs.uToast.show({
						title: '登录成功',
						type: 'success',
					});
				}else{
					_this.$refs.uToast.show({
						title: '登录失败',
						type: 'fail',
					});
				}
				setTimeout(()=>{
					uni.navigateBack()
				},1500) 
			})
			
		}
	}
};
</script>

<style scoped lang="scss">

.header {
	margin: 90upx 0 90upx 50upx;
	border-bottom: 1px solid #ccc;
	text-align: center;
	width: 650upx;
	height: 300upx;
	line-height: 450upx;
}

.header image {
	width: 200upx;
	height: 200upx;
}

.content {
	margin-left: 50upx;
	margin-bottom: 90upx;
}

.content text {
	display: block;
	color: #9d9d9d;
	margin-top: 40upx;
}

.bottom {
	border-radius: 80upx;
	margin: 70upx 50upx;
	font-size: 35upx;
}
</style>

四、node后端代码实现

后台接口采用node+express+mongoose

  • 获取openid并创建用户接口
//获取openId的时候,查询用户是否存在,不存在则创建用户,反之更新令牌
var express = require('express');
var router = express.Router();
const User = require('./../model/user')
const { createToken, verifyToken } = require('./../utils')

const { WX_CONFIG } = require('./../utils/config')
    // querystring这个模块,用来做url查询参数的解析
const querystring = require('querystring');
const request = require('request');
/**
 * @name: 获取微信用户的openId
 * @param {string} code 微信小程序授权后返回的code 
 * @Author: 471826078@qq.com
 */
router.post('/getOpenId', (req, res, next) => {
    const data = {
            'appid': WX_CONFIG.appId,
            'secret': WX_CONFIG.appScrect,
            'js_code': req.body.code,
            'grant_type': 'authorization_code'
        }
        // querystring的stringify用于拼接查询
    var content = querystring.stringify(data);
    // 根据微信开发者文档给的API
    var url = 'https://api.weixin.qq.com/sns/jscode2session?' + content;
    // 对url发出一个get请求
    request.get({
        'url': url
    }, (error, response, body) => {
        // 将body的内容解析出来
        let abody = JSON.parse(body);
        const { openid, session_key } = abody
        if (openid) {
            User.findOne({ openId: openid }).exec((err, doc) => {
                if (err) {
                    res.send({ isSuccess: false, message: '登录失败' });
                } else {
                    let token = createToken({ isAdmin: 0, openId: openid, session_key }, 3600 * 24 * 3)
                    if (!doc) {
                        new User({ openId: openid, session_key, isAdmin: 0, token }).save((err1, doc) => {
                            if (err1) {
                                res.send({ isSuccess: false, message: '登录失败' });
                            } else {
                                res.send({ isSuccess: true, message: '登录成功', data: doc });
                            }
                        })
                    } else {
                        User.findByIdAndUpdate({ _id: doc._id }, { token, session_key }, { new: true }).exec((err2, doc2) => {
                            if (err2) {
                                res.send({ isSuccess: false, message: '登录失败' });
                            } else {
                                res.send({ isSuccess: true, message: '登录成功', data: doc });
                            }
                        })
                    }
                }

            })
        } else {
            res.send({ isSuccess: false, message: '登录失败' });
        }
    })
})
module.exports = router

授权后更新用户信息接口

//会员注册
var express = require('express');
var router = express.Router();
const User = require('./../model/user')
router.post('/memberRegister', (req, res, next) => {
        const { _id, avatarUrl, city, country, gender, language, nickName, province, } = req.body;
        User.findByIdAndUpdate({ _id }, { avatarUrl, city, country, gender, language, nickName, province, }, { new: true }).exec((err3, doc) => {
            if (err3) {
                res.send({ isSuccess: false, message: '登录失败' });
            } else {
                res.send({ isSuccess: true, message: '登录成功', data: doc });
            }
        })
    })
module.exports = router    

五、返回登录之前的页面

	if(res.data.isSuccess){
		_this.$store.commit('SET_STATE',['userInfo',res.data.data])
		_this.$store.commit('SET_STATE',['token',res.data.data.token])
		uni.setStorageSync('token',res.data.data.token)
		_this.$refs.uToast.show({
			title: '登录成功',
			type: 'success',
		});
	}else{
		_this.$refs.uToast.show({
			title: '登录失败',
			type: 'fail',
		});
	}
	setTimeout(()=>{
		uni.navigateBack()
    },1500) 

//  SET_STATE 方法               
const mutations = {
	SET_STATE(state, e) {
		if (e) {
			state[e[0]] = e[1];
		}
	},
	
}
export default mutations;            

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值