Table of Contents
UnionID 机制说明
如果开发者拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过 UnionID 来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的 UnionID 是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。
UnionID获取途径
小程序端调用云函数
绑定了开发者帐号的小程序,可以通过下面 4 种途径获取 UnionID。
小程序端调用云函数时,如果开发者帐号下存在同主体的公众号,并且该用户已经关注了该公众号,可在云函数中通过 cloud.getWXContext 获取 UnionID
小程序端调用云函数时,如果开发者帐号下存在同主体的公众号或移动应用,并且该用户已经授权登录过该公众号或移动应用,也可在云函数中通过 cloud.getWXContext 获取 UnionID。
原文:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/union-id.html
1.正常的方式,这些信息不需要用户授权即可获取,获取unionid
step 1:
使用云函数只能获取的用户的openid 和 appid两项信息,结构如下:
云函数[login] user event:
{
userInfo:
{
appId: 'wxf7058cc***',
openId: 'oQuJV43etcpx6W5gZBLv**'
}
}
step 2.用户图像和昵称授权代码
如果要获取用户的图像等信息,必须要用户显式授权后才可获取到
下面的代码用来显示图像或提示信息,让用户点击(图像或提示文字),以便弹出授权窗口,让用户进行选择授权或拒绝授权。
<view class='info'>
<label>
<image class='avatar' src='{{avatarUrl|| defaultAvatarUrl}}'></image>
<view class='text'>
<view class='name'>{{userInfo.nickName || '登录/注册'}}</view>
<view>{{userInfo.jobTitle || '添加职位'}} @ {{userInfo.company || '添加公司'}}</view>
</view>
<button open-type='getUserInfo' bindgetuserinfo='onGetUserInfo'></button>
</label>
</view>
用户选择授权或拒绝后,立即调用下面的代码。下面这段代码用来判断用户是否授权了。
//用户点击图标后,会弹出“微信授权” 窗口
// 用户点击“允许”,允许开发者获得用户的公开信息(昵称、头像等)
onGetUserInfo: function (e) {
if (!this.logged && e.detail.userInfo) {
this.setData({
logged: true,
avatarUrl: e.detail.userInfo.avatarUrl,
userInfo: e.detail.userInfo
})
}
},
step 3: 后台判断用户是否授权的代码
这段代码用来在任何时候判断用户是否已授权,上面那个是有弹窗后的立马判断。
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// 使用 wx.getSetting 获取用户当前的用户信息授权状态。获取用户图像和昵称信息。
wx.getSetting({
success: res => {
if (res.authSetting['scope.userInfo']) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
console.log('已经授权')
wx.getUserInfo({
success: res => {
this.setData({
avatarUrl: res.userInfo.avatarUrl,
userInfo: res.userInfo
})
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
if (this.userInfoReadyCallback) {
this.userInfoReadyCallback(res)
}
}
})
}
else {
console.log('page/my/my|res.authSetting:', '小程序AspNetCore自定义:检测到当前用户未授权获取图像和昵称')
wx.showToast({
title: "提示:您未授权本程序获取您的图像和昵称。如果您愿意,请点击图像授权(这不是必须的,不授权程序可以正常工作)",
duration: 5000,
icon: "none"
})
}
}
})
},
2.open-data头像、昵称获取方式
如果只是为了展示用户名和头像可以用open-data组件,wx.getUserInfo还是可以使用,只是第一次授权必须要经过button组件而已。
<view class="userinfo">
<view class="userinfo-avatar">
<open-data type="userAvatarUrl"></open-data>
</view>
<open-data type="userNickName"></open-data>
</view
.userinfo {
position: relative;
width: 750rpx;
height: 320rpx;
color: #fff;
display: flex;
flex-direction: column;
align-items: center;
}
.userinfo-avatar {
overflow:hidden;
display: block;
width: 160rpx;
height: 160rpx;
margin: 20rpx;
margin-top: 50rpx;
border-radius: 50%;
border: 2px solid #fff;
box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.2);
}
.userinfo text {
/* color: #fff; */
font-size: 14px;
background-color: #c0c0c0;
border-radius:40%;
}
微信小程序wx.login()、wx.getSetting、wx.getUserInfo的区别
1、wx.login
前端使用wx.login是获取登录凭证(code),将code发送给后台,后台向微信发送请求获取用户的唯一标识(openid)及本次登录的会话密钥(session_key),然后后台传回前台自定义的登录状态,以及自定义的用户唯一标识
2、wx.geUserInfo
wx.getuserinfo是为了获取用户的相关信息
3、wx.getSetting
wx.getsetting是获取用户的当前设置。返回值中只会出现小程序已经向用户请求过的权限
接口还是有的,通过login拿到code,去后台通过restful api可以拿到openid和unoinid.用户使用button(小程序)或UserInfoButton(小游戏)组件,在用户点击后弹窗请求获取用户基本信息。我的建议是能不用getUserInfo的地方尽量不用,可以用open-data替代,从而不需要授权。例如获取头像,昵称等信息,如果后台不需要存储这些数据,就使用open-data(如果应用不需要展示其他好友的头像、昵称,后台就可以不存储这些数 据)。
同时,为了区分用户,只需通过wx.login()来获取openId,作为用户ID给后台存储就行了(需要用到Unionid的除外),这种情况也不需要授权。
let customer = Customer;
//---直接对data赋值,不会引起界面刷新---
customer.Appid = app.globalData.appid,
customer.Unionid = app.globalData.unionid,
customer.Openid = app.globalData.openid,
customer.AuthorOpenid = app.globalData.openid,
customer.UserInfo = {},
customer.UserName = "",
customer.TelephoneNumber = "",
customer.EmployeeRoles = {}, //员工角色
customer.Level = 0, //权限级别
customer.ShopRoles = {}, //员工角色
customer.IsEmployee = true, // 是否员工
customer.IsAuthorized = false, // 是否已取得授权
customer.CreatedOnUtc = db.serverDate(),
customer.UpdatedOnUtc = db.serverDate(),
customer.LastloginOntUtc = db.serverDate(),
console.log("Customer记录", customer)
//如果没有有数据,则插入用户数据, data 字段表示需新增的 JSON 数据
if (!users.data.length) {
db.collection(collection).add({
data: customer,
success: res => {
console.log('pages/adminEmployee/index/index 插入用户数据 ok')
},
fail: err => {
console.error('ppages/adminEmployee/index/index 插入数据 failure', err)
}
})
}
miniprogram/pages/adminEmployee/login/index.js
// miniprogram/pages/adminEmployee/login/index.js
let app = getApp();
// 获取云数据库引用
const db = wx.cloud.database();
const configCollection = require('../../../config/configCollection.js');
const Customer = require('../../../models/Customer/Customer.js');
//const collection = 'Setting';
const collection = configCollection.Setting;
let name = null;
let password = null;
Page({
/**
* 页面的初始数据
*/
data: {
userInputPassword: "",
AdminPassword: "",//从数据库中获取管理后台密码
isEmployee: false, // 是否公司员工
ObjectId: "",
Employee: {
_id: "",
Appid: app.globalData.appid,
AuthorOpenid: app.globalData.openid,
AuthorUnionid: app.globalData.unionid,
riginalId: app.globalData.OriginalId,
UserInfo: {},
IsAuthorized: false, // 是否已取得授权
IsEmployeeAuthorized: false, // 是否员工认证
CreatedOnUtc: db.serverDate(),
UpdatedOnUtc: db.serverDate(),
LastloginOnUtc: db.serverDate(),
},
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
//从数据库中获取管理后台密码
const db = wx.cloud.database();
db.collection(configCollection.Setting).where({
Name: "AdminPassword"
}).get({
success: res => {
this.setData({
AdminPassword: res.data[0], //返回的是一个数组,取第一个,
})
},
fail: err => {
console.log(err)
}
})
//自定义ObjectId
// 调用云函数获取ObjectId,string类型
wx.cloud.callFunction({
name: 'http',
data: {},
success: res => {
this.data.ObjectIdGenerateNewId = res.result;
console.log('[云函数] [http]: ', res)
},
fail: err => {
console.error('[云函数] [http] 调用失败', err)
}
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
//输入用户名
userNameChange: function (e) {
this.data.username = e.detail.value;
},
//输入密码
userPasswordChange: function (e) {
this.data.userInputPassword = e.detail.value;
},
toadmin: function () {
var that = this;
if (that.data.userInputPassword == '') {
wx.showModal({
title: '请填写密码',
showCancel: false
})
return
}
if (that.data.userInputPassword != that.data.AdminPassword.Password) {
wx.showModal({
title: '您填写的密码不对',
showCancel: true
})
return
}
if (that.data.userInputPassword === that.data.AdminPassword.Password) {
//密码验证通过
app.globalData.EmployeeAdminPasswordIsAuthorized = true;
// 调用云函数创建员工用户
wx.cloud.callFunction({
name: 'loginEmployee',
data: {
ObjectIdGenerateNewId:that.data.ObjectIdGenerateNewId, //传给云函数的参数
},
success: res => {
console.log('调用云函数loginEmployee:', res)
},
fail: err => {
console.error('[云函数] [loginEmployee] 调用失败', err)
}
})
//获取员工对象数据结构,并且将Id替换wei_id
// that.getNewEmployeeFromApi();
//that.getNewObjectId();
const db = wx.cloud.database(); //打开数据库连接
//对象赋值
let employee = that.data.Employee;
console.log(configCollection.Employee + "编辑后的记录内容", configCollection.Employee)
employee._id = that.data.ObjectId;
employee.Appid = app.globalData.appid;
employee.OriginalId = app.globalData.minappOrigalid;
employee.AuthorUnionid = app.globalData.unionid;
employee.AuthorOpenid = app.globalData.openid;
employee.EmployeeStatus = 20;
employee.CreatedOnUtc = db.serverDate();
employee.UpdatedOnUtc = db.serverDate();
employee.LastloginOnUtc = db.serverDate();
employee.LastloginIP = "";
console.log(configCollection.Employee + ":", configCollection.Employee)
//避免在直接对 Page.data 进行赋值修改,使用 Page.setData 进行操作才能将数据同步到页面中进行渲染
that.setData({ employee })
//获取该员工的信息
db.collection(configCollection.Employee).where({
AuthorOpenid: app.globalData.openid
}).get({
success: res => {
let employees = res.data;
console.log("后台index获取的员工信息" + res.data)
//有此员工数据
if (Employees && Employees.length > 0) {
}
else //无此员工数据,导航到登录页面
{
wx.navigateTo({
url: '/pages/adminEmployee/login/index'
});
}
},
fail: err => {
console.log(err)
}
})
db.collection(configCollection.Employee).add({
data: that.data.employee,
success: res => {
console.log('pages/adminEmployee/login/index 插入数据 success')
},
fail: err => {
console.error('pages/adminEmployee/login/index 插入数据 failure', err)
}
})
// wx.navigateTo({
// url: '/pages/adminEmployee/index/index'
// });
}
else {
wx.navigateTo({
url: '/pages/my/index'
});
}
},
//getNewObjectId
getNewObjectId: function () {
var that = this;
wx.request({
url: 'https://api.usdotnet.com/api/ObjectId', //仅为示例,并非真实的接口地址
data: {
},
header: {
'content-type': 'application/json' // 默认值
},
success(res) {
console.log(res.data)
that.setData({
ObjectId: res.data
})
},
fail: function (res) {
console.log("失败" + res);
}
})
},
//获取1个员工对象
getNewEmployeeFromApi: function () {
var that = this;
wx.request({
url: 'https://api.usdotnet.com/api/Employee/NewEmployee', //仅为示例,并非真实的接口地址
data: {
},
header: {
'content-type': 'application/json' // 默认值
},
success(res) {
console.log(res.data)
//json对象转成json字符串
var jsonobj = res.data;
var jsonstr = JSON.stringify(jsonobj);
console.log("jsonstr==" + jsonstr)
var idstring = '"Id":';
var _idstring = '"_id":';
jsonstr = jsonstr.replace(idstring, _idstring);
jsonstr = jsonstr.replace(new RegExp(idstring, 'g'), _idstring);
console.log("jsonstr00==" + jsonstr)
let jsonobj2 = JSON.parse(jsonstr);
that.setData({
Employee: jsonobj2
})
},
fail: function (res) {
console.log("失败" + res);
}
})
},
})
常见问题
1.本地云函数被删除后,提示找不到云函数
解决办法:同步云函数列表
2.页面加载后仍未获取到openId
原因:app.js里的onLaunch(异步)方法调用得到数据的速度比页面Page中的onLoad慢,导致在加载index.wxml时openid总是为空
解决办法:采用Promise
普通小程序端调用
目录:
画图Canvas:https://developers.weixin.qq.com/miniprogram/dev/api/canvas/CanvasContext.setTextAlign.html
小程序分享及用户信息授权等接口能力10月10调整