# Overview

uni-id-pages, part of the uni-id system.

Based on uni-id-common, it provides a batch of ready-made, open-source, front-end pages and cloud objects related to login and account management.

It is a uni_modules of a cloud-integrated page group, including front-end pages and back-end cloud objects (uni-id-co).

Developers introduce uni-id-pages into the project, and account management functions do not need to be developed by themselves. Due to the openness of the source code and the clear hierarchical structure, it is also easy to adjust if there are secondary development needs.

Download address: https://ext.dcloud.net.cn/plugin?name=uni-id-pages

Features of uni-id-pages include:

  • Register an account:
    • username and password
  • Password-free login (automatic registration for the first login):
    • App one-click login
    • SMS verification code login
    • WeChat login (automatically get avatar and nickname)
    • Apple login
    • Alipay applet login (not implemented yet)
  • Password login
    • Login with username/mobile number and password
  • Account Management
    • Personal Center
    • Avatar replacement
    • Modify nickname
    • bind mobile number
    • Change password (only visible when the account has a set password)
    • Retrieve the password (only visible if the account has a bound mobile phone number)
    • log out
    • Cancellation of the account (required for listing in the domestic app market)
  • User Service Agreement and Privacy Policy Terms Authorization

# 目录结构


├─uni_modules                                         存放[uni_module](/uni_modules)规范的插件。
│    ├─其他module
│    └─uni-id-pages
│        ├─uniCloud
│        │    └─cloudfunctions                        云函数目录
│        │        └─uni-id-co                         集成调用uni-id方法的云对象
│        │            ├─common                        公用逻辑
│        │            ├─config                        配置
│        │            │  └─permission.js              调用接口所需的权限配置
│        │            ├─lang                          国际化目录
│        │            ├─lib                           基础功能,不建议修改此目录下文件
│        │            │  ├─third-party                三方平台接口
│        │            │  └─utils                      基础功能
│        │            ├─middleware                    中间件
│        │            └─module                        分模块存放的云对象方法
│        ├─common
│        │    ├─login-page.scss                       登录页面公共样式
│        │    ├─login-page.mixin.js                   登录页面公共mixin文件
│        │    └─loginSuccess.js                       登录成功后执行的文件
│        ├─components
│        │    ├─cloud-image                           uniCloud云存储图片解析组件
│        │    │    └─cloud-image.vue
│        │    ├─uni-id-pages-agreements               同意用户服务协议&隐私政策条款组件
│        │    │    └─uni-id-pages-agreements.vue
│        │    ├─uni-id-pages-avatar                   用户头像组件
│        │    │    └─uni-id-pages-avatar.vue
│        │    ├─uni-id-pages-bind-mobile              通过微信获取手机号码绑定个人资料
│        │    │    └─uni-id-pages-bind-mobile.vue
│        │    ├─uni-id-pages-email-form               邮箱验证码组件
│        │    │    └─uni-id-pages-email-form.vue
│        │    ├─uni-id-pages-fab-login                悬浮的切换登录方式组件
│        │    │    └─uni-id-pages-fab-login.vue
│        │    ├─uni-id-pages-sms-form                 获取短信验证码组件
│        │    │    └─uni-id-pages-sms-form.vue
│        │    └─uni-id-pages-user-profile             获取用户信息组件
│        │        └─uni-id-pages-user-profile.vue
│        ├─pages
│        │    ├─common
│        │    │    └─webview                          用于实现应用内浏览或打开《用户协议和隐私协议》URL链接页面
│        │    │        └─webview.vue
│        │    ├─login                        
│        │    │    ├─login-smscode.vue                短信验证码登录
│        │    │    ├─login-withoutpwd.vue             免密码登录
│        │    │    └─login-withpwd.vue                密码登录
│        │    ├─register                    
│        │    │    ├─register.vue                     通过用户名密码注册账号
│        │    │    ├─register-admin.vue               创建超级管理员
│        │    │    ├─register-by-email.vue            通过邮箱验证码注册账号
│        │    │    └─validator.js                     注册账号页的表单验证规则文件
│        │    ├─retrieve                              
│        │    │    ├─retrieve-by-email.vue            通过邮箱验证码重置密码
│        │    │    └─retrieve.vue					            通过手机验证码重置密码
│        │    └─userinfo
│        │        ├─bind-mobile.vue                   绑定手机号码
│        │        ├─change_pwd.vue                    修改密码
│        │        ├─cropImage.vue                     裁剪图片
│        │        ├─deactivate.vue                    注销账号
│        │        ├─set-pwd.vue                       设置密码
│        │        └─userinfo.js                       注册账号页的表单验证规则文件
│        ├─static                                     静态资源目录
│        ├─changelog.md                               更新日志
│        ├─config.js                                  uni-id-pages的配置文件
│        ├─init.js                                    初始化文件
│        ├─package.json                               包管理文件
│        └─readme.md                                  插件自述文件

**Complete uni-app directory structure [View details](https://uniapp.dcloud.io/frame?id=%e7%9b%ae%e5%bd%95%e7%bb%93%e6%9e %84)

# front page

# 初始化

需要在App.vue中初始化uni-id-pagesinit.js文件

The sample code is as follows:

<script>
	import uniIdPageInit from '@/uni_modules/uni-id-pages/init.js';
	export default {
	onLaunch: async function() {
	console.log('App Launch')
	await uniIdPageInit()
},
	onShow: function() {
	console.log('App Show')
},
	onHide: function() {
	console.log('App Hide')
}
}
</script>

# Configure

Path: /uni_modules/uni-id-pages/config.js

Field Type Description
debug Boolean Debug mode details
loginTypes Array Login MethodsDetails
agreements Array Privacy Policy details
appid Object Application id for accessing various services (such as WeChat login service)Details
passwordStrength Object Password configuration details
setPasswordAfterLogin Boolean/Object Set password after login details

Complete example:

export default {
	// debug mode
	"debug":true,
	/*
		登录类型 未列举到的或运行环境不支持的,将被自动隐藏。
		如果需要在不同平台有不同的配置,直接用条件编译即可
	*/
	"loginTypes": [
		"univerify",
		"weixin",
		"username",
		"apple",
		"smsCode"
	],
	// policy agreement
	"agreements": {
		"serviceUrl": "https://xxx", //用户服务协议链接
		"privacyUrl": "https://xxx", //隐私政策条款链接
		// Which scenarios are displayed, 1. Registration (including registration and login, such as: WeChat login, Apple login, SMS verification code login), 2. Login (such as: username and password login)
		"scope": ['register', 'login']
	},
	// The application id that provides access to various services (such as WeChat login service)
	"appid":{
		"weixin":{
			// 微信公众号的appid,来源:登录微信公众号(https://mp.weixin.qq.com)-> 设置与开发 -> 基本配置 -> 公众号开发信息 -> AppID
			"h5":"wx111111111111111",
			// 微信开放平台的appid,来源:登录微信开放平台(https://open.weixin.qq.com) -> 管理中心 -> 网站应用 -> 选择对应的应用名称,点击查看 -> AppID
			"web":"wx22222222222222"
		}
	},
	/**
	 * 密码强度
	 * super(超强:密码必须包含大小写字母、数字和特殊符号,长度范围:8-16位之间)
	 * strong(强: 密密码必须包含字母、数字和特殊符号,长度范围:8-16位之间)
	 * medium (中:密码必须为字母、数字和特殊符号任意两种的组合,长度范围:8-16位之间)
	 * weak(弱:密码必须包含字母和数字,长度范围:6-16位之间)
	 * 为空或false则不验证密码强度
	 */
	"passwordStrength":"medium",
	/**
	 * 登录后允许用户设置密码(只针对未设置密码得用户)
	 * 开启此功能将 setPasswordAfterLogin 设置为 true 即可
	 * "setPasswordAfterLogin": false
	 *
	 * 如果允许用户跳过设置密码 将 allowSkip 设置为 true
	 * "setPasswordAfterLogin": {
	 *   "allowSkip": true
	 * }
	 * */
	"setPasswordAfterLogin": false
}

# Debug mode

In debug mode, starting the application will automatically initiate a network request (calling getSupportedLoginType of uni-id-co).

Check: Whether the login method configured on the uni-id-pages client is not configured correctly on the uniCloud server, otherwise an exception will be thrown.

# Login method

Fields Description Platform Differences
univerify One-click login App 3.0.0+
smsCode SMS verification code login
weixin WeChat login App, WeChat applet, Web (supported from uni-id-pages version 1.0.8)
apple Sign in with Apple Sign in with Apple iOS13+ support, App 2.4.7+
username Login with username and password
# Configuration example
export default {
	"loginTypes": ["username","smsCode"]
}

As shown in the above example configuration, it means to enable: account password login, verification code login.

The same configuration is:

export default {
	"loginTypes": ["weixin","username","smsCode"]
}

It means enable: WeChat login, verification code login, account password login.

Platform difference configuration: If you want to have different login methods on different platforms, directly use [conditional compilation](https://uniapp.dcloud.io/platform?id=%e6%9d%a1%e4%bb% b6%e7%bc%96%e8%af%91) is enough. The following configuration means that SMS verification code login is only enabled on the APP side

export default {
	"loginTypes": [
		"username","univerify","weixin","apple"
		// #ifdef APP-PLUS
		,"smsCode"
		// #endif
	]
}

Note: AppStore rules for iOS: If an app supports three-party social login services (such as: one-key login, WeChat login, etc.), it must also provide users with the option of "Login with Apple Account". That is: if your application does not support three-way login, you can not bring Apple login, if your application supports three-way login, you must also bring Apple login.

The above configuration only opens the front-end login entry. To achieve the function, you need to:

  1. Activate the corresponding login service, obtain the service key, and complete the configuration in the configuration file of the uni-id module of the server. For details, check: [Login service activation and configuration](#%E7%99%BB%E5%BD%95%E6%9C%8D%E5%8A%A1%E5%BC%80%E9%80%9A%E4 %B8%8E%E9%85%8D%E7%BD%AE)
  2. If it is on the APP side, one-click login, WeChat login, Apple login, you need to check the corresponding module in manifest.json (WeChat login must be configured: WeChat development platform application appID value) , and is available after the package is completed (custom debugging base package and official package are available).

# Privacy Policy

Field Type Description
serviceUrl String User service protocol network link
privacyUrl String Privacy Policy Web Link
scope Object Which scenarios does it apply to

scope description:

Field Type Description
register String Register (including registration and login, such as: WeChat login, Apple login, SMS verification code login)
login String Login (eg: login with username and password)

一款规范的小程序或App要上架到国内应用商店必须提供《隐私政策和用户使用协议》,参考模版:隐私权政策模板.zip

More compliance issues [see details](https://uniapp.dcloud.io/tutorial/android-store.html#app%E5%9B%A0%E5%90%88%E8%A7%84%E9% 97%AE%E9%A2%98%E6%97%A0%E6%B3%95%E4%B8%8A%E6%9E%B6)

Recommended use: HBuilderX editor, edit the "Privacy Policy and User Agreement" in markdown document format, by right-clicking in the document one-click sharing to front-end web hosting to get the link

# Application id

Field Type Description
weixin Object WeChat
 |- h5 String WeChat official account appid
Source: WeChat official account-> Settings and Development-> Basic Configuration -> Official Account Development Information -> AppID
 |- web String WeChat Open Platform appid
Source: WeChat Open Platform -> Management Center -> Website Application -> Select the corresponding application name, click View -> AppID

# Password Strength

Field Type Description
empty or false - do not verify password strength
super String Super strong: the password must contain uppercase and lowercase letters, numbers and special symbols, length range: between 8 and 16 characters
strong String Strong: password must contain letters, numbers and special symbols, length range: between 8-16 characters
medium String Medium: password must be a combination of any two letters, numbers and special symbols, length range: between 8-16 characters
weak String Weak: Password must contain letters and numbers, length range: between 6-16 characters

# Set password after login

If the user has not set a password, he will jump to the password setting page after logging in

This function is not enabled by default, please set setPasswordAfterLogin to true to enable it, as follows:

{
	setPasswordAfterLogin: true,
	// setPasswordAfterLogin: {
	// 	allowSkip: false
	// }
}

If you don't need to enforce setting a password, you can set allowSkip to true, and users can choose to skip setting a password.

# Page introduction

uni-id-pages includes: account registration, password-free login, avatar replacement, nickname modification, mobile phone number binding, password retrieval, account cancellation and other pages. Plugin address

There is often a need to open the login page in the project. Here is an introduction to the login page; there are two types of login methods:

  • Password login (account password login), page path: /uni_modules/uni-id-pages/pages/login/login-withpwd
  • Password-free login (one-key login, SMS verification code login, WeChat login, Apple login), page path: /uni_modules/uni-id-pages/pages/login/login-withoutpwd

Execute uni.navigateTo to open the login page, the first item of the loginTypes value in the configuration will be used as the login method by default.

For example loginTypes: ["weixin","apple","univerify"] will use weixin, ie WeChat login as the default login method

uni-id-pages supports specifying the login method by passing the parameter type. For example: to specify Apple login, use the following code

uni.navigateTo({
	"url":"/uni_modules/uni-id-pages/pages/login/login-withoutpwd?type=apple"
})

uniIdRouter can be used together; when the user is not logged in, but visits a page that requires forced login, or the interface prompts that the token is invalid or expired (the response body starts with TOKEN_INVALID) You need to open the login page at all times. You need to define the above two path paths as loginPage.

# Cloud object (uni-id-co)

uni-id-co is the core cloud object of uni-id-pages, including many user-related interfaces. As part of the uni-id system, uni-id-co also uses the uni-id configuration file (cloudfunctions/common/uni-config-center/uni-id/config.json). Currently, this cloud object relies on some client information and does not support being called by other cloud functions/cloud objects. Already supports urlization calls, reference: uni-id-co urlization

The front-end should obtain the reference of the cloud object before calling the method in the cloud object uni-id-co. The code is as follows

const uniIdCo = uniCloud.importObject('uni-id-co')

If there is an error that the lodash.merge module cannot be found when calling the uni-id-co method, please manually execute npm install in the uni-id-co cloud object directory. If the client is running, the uniCloud plugin will automatically install the missing dependencies for uni-id-co.

# Directory description

├─common 					// 公用逻辑
├─config 					// 配置
│  └─permission.js 			// 调用接口所需的权限配置
├─lang 						// 国际化目录
├─lib 						// 基础功能,不建议修改此目录下文件
│  ├─third-party			// 三方平台接口
│  └─utils					// 基础功能
├─middleware				// 中间件
└─module					// 分模块存放的云对象方法

# Public response parameters

All api return values of uni-id-co satisfy the uniCloud response body specification

Return value example

{
	errCode: 0, // 错误码,详见错误码列表
			errMsg: '', // 错误信息,uni-id-co会自动根据客户端语言对错误信息进行国际化
			newToken: { // 注册、登录、刷新token等接口会自动返回新token,uniCloud客户端sdk会自动将新token及过期时间存储在storage内(需要HBuilderX 3.4.13及以上版本)
		token,
				tokenExpired
	},
	// ... the rest of the parameters
}

Notice

  • The interface that needs to verify the token will also return newToken when the token is about to expire. The threshold for the token to be expired is configured by the developer.

# Adapt URL

URLization is supported since uni-id-pages@1.0.29 version What is URLization

Call specification:

  1. The Content-Type in the HTTP request header must be application/json, the request method must be POST, if the conditions are not met, the uni-id-unsupported-request error code will be returned
  2. The request body must be in the following format:
{
	"clientInfo": {},
	"uniIdToken": "",
	"params": {}
}

field description

Field Description
clientInfo Client information; fields returned by uni.getSystemInfo
uniIdToken User Token; Required after user login
params API interface parameter field

如果是在 uni-app 之外的应用中调用 URL 化接口,请确保clientInfo中存在以下字段:

字段 说明
uniPlatform 应用运行平台,与条件编译平台相同。详见
appId manifest 中应用appid,即DCloud appid。如没有请手动指定一个,需确保唯一性。
deviceId 设备 id;通过uni.getSystemInfo获取

Assuming that the URLized domain name PATH has been set in the uniCloud console, take the PATH as /http/uni-id-co as an example to demonstrate the login example:

uni.request({
	url: 'https://{云函数Url化域名}/http/uni-id-co/login',
	method: 'POST',
	data: {
		clientInfo: uni.getSystemInfoSync(),
		uniIdToken: '用户Token',
		params: {
			username:"username",
			password:"password"
		}
	},
	header: {
		'Content-Type': 'application/json'
	},
	success: (res) => {
		// return value
	}
})

Notice

Please do not add the Query parameter, the Query parameter will be ignored after URLization

# API list

API Description
uniIdCo.registerAdmin() Register Admin Details
uniIdCo.addUser() Add User Details
uniIdCo.authorizeAppLogin() Authorize users to log in to the app details
uniIdCo.removeAuthorizedApp() Remove user login authorization Details
uniIdCo.setAuthorizedApp() Set the list of apps that the user is allowed to log in Details
uniIdCo.registerUser() Register ordinary user Details
uniIdCo.registerUserByEmail() Register ordinary users through email verification code Details
uniIdCo.login() Login with username and password Details
uniIdCo.loginBySms() SMS verification code login Details
uniIdCo.loginByUniverify() App-side one-click login Details
uniIdCo.loginByWeixin() WeChat login Details
uniIdCo.loginByAlipay() Alipay login Details
uniIdCo.loginByQQ() QQ login Details
uniIdCo.loginByApple() Apple login Details
uniIdCo.logout() User logout details
uniIdCo.bindMobileBySms() Bind mobile phone number through SMS verification code Details
uniIdCo.bindMobileByUniverify() Bind mobile phone number by one-click login Details
uniIdCo.bindMobileByMpWeixin() Bind mobile phone number through WeChat Details
uniIdCo.bindWeixin() Bind WeChat Details
uniIdCo.bindQQ() Bind QQ Details
uniIdCo.bindAlipay() Bind Alipay account Details
uniIdCo.bindApple() Bind Apple Account Details
uniIdCo.updatePwd() Update password details
uniIdCo.resetPwdBySms() Reset password via SMS verification code Details
uniIdCo.resetPwdByEmail() Reset password by email verification code Details
uniIdCo.closeAccount() Close account Details
uniIdCo.getAccountInfo() Get brief account information Details
uniIdCo.createCaptcha() Create a graphic captcha Details
uniIdCo.refreshCaptcha() Refresh the graphic captcha details
uniIdCo.sendSmsCode() Send SMS verification code details
uniIdCo.sendEmailCode() Send email verification code Details
uniIdCo.refreshToken() Refresh token Details
uniIdCo.acceptInvite() Accept the invitation details
uniIdCo.getInvitedUser() Get invited user Details
uniIdCo.setPushCid() Update the push_clien_id of the device table Details
uniIdCo.getSupportedLoginType() Get the supported login method Details

# Register login and logout

# Register Super Admin

Interface name: registerAdmin

Interface form

await uniIdCo.registerAdmin({
	username,
	password,
	nickname
})

Parameter Description

Parameter Name Type Required Description
username string yes Super admin username
password string yes Super admin password
nickname string No Super Admin Nickname

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • Only one super administrator can exist in the system

# username password registered user

Interface name: registerUser

Interface form

await uniIdCo.registerUser({
	username,
	password,
	captcha,
	nickname,
	inviteCode
})

Parameter Description

Parameter Name Type Required Description
username string yes username
password string yes password
captcha string yes graphic captcha
nickname string no nickname
inviteCode string No InviteCode

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

# Email verification code registered user

Interface name: registerUserByEmail

Interface form

await uniIdCo.registerUserByEmail({
	email,
	password,
	code,
	nickname,
	inviteCode
})

Parameter Description

Parameter Name Type Required Description
email string Yes Email
password string yes password
code string Yes Email Verification Code
nickname string no nickname
inviteCode string No InviteCode

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

# Password login

Interface name: login

Interface form

await uniIdCo.login({
	username,
	password,
	captcha
})

Parameter Description

Parameter Name Type Required Description
username string choose one from mobile, email username
mobile string and username, email three choose one mobile phone number
email string and username, mobile choose one of three email
password string yes password
captcha string no graphic captcha

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

# SMS verification code login

Login if the phone number already exists, otherwise register

Interface name: loginBySms

Interface form

await uniIdCo.loginBySms({
	mobile,
	code,
	captcha,
	inviteCode
})

Parameter Description

参数名 类型 必填 说明
mobile string 手机号
code string 短信验证码
captcha string 图形验证码
inviteCode string No Invite Code, only valid when registering

两小时内登录失败3次的用户必填图形验证码,如果客户端没有使用uni-id-pages,可以参考uni-id-pages验证码登录页面的相关逻辑。

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

# WeChat authorized mobile number login uni-id-co 1.0.25+

Interface name: loginByWeixinMobile

Interface form

await uniIdCo.loginByWeixinMobile({
	phoneCode,
	inviteCode
})

Parameter Description

Parameter name Type Required Description
phoneCode string yes getPhoneNumber event callback gets the dynamic token code
inviteCode string No Invitation code, valid only when registering

return value

parameter name type description
errCode string|number error code
errMsg string error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • This interface will call the WeChat credential interface to obtain the access_token, and uni-id-pages 1.0.8 and above will use uni-open-bridge-common to save the access_token information.
  • If the developer does not use uni-open-bridge-common to manage access_token and other information in other applications, it may cause access_token conflicts.

# One-click login

Login if the phone number already exists, otherwise register

Interface name: loginByUniverify

Interface form

await uniIdCo.loginByUniverify({
	access_token,
	openid,
	inviteCode
})

Parameter Description

Parameter Name Type Required Description
access_token string yes access_token returned by the one-click login client
openid string yes openid returned by one-click login client
inviteCode string No Invite Code, only valid when registering

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

# WeChat login

Login if the WeChat account already exists, otherwise register

Interface name: loginByWeixin

Interface form

await uniIdCo.loginByWeixin({
	code,
	inviteCode
})

Parameter Description

Parameter Name Type Required Description
code string yes The code parameter returned by the uni.login interface
inviteCode string No Invite Code, only valid when registering

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • Supported login methods: WeChat applet, WeChat official account, App, website WeChat scan code login
  • WeChat login will automatically save the user's openid. In uni-id-pages 1.0.8 and later versions, when storing the openid, a copy of the current application's Appid (DCloud AppId in manifest.json) will be stored as the key. openid, see the description of openid below.
  • If there are multiple applications using WeChat applet to log in at the same time, and you want user identities not to be isolated, please ensure that these applications are owned by the same entity on the WeChat applet platform, that is, to ensure that different applications can obtain the same unionid
  • uni-id-pages 1.0.8 and above will use uni-open-bridge-common to save session_key (WeChat MiniApp login), access_token (WeChat official account login, WeChat App login), these information, However, a copy is still stored in the user table for compatibility with legacy logic. Detailed reference: Automatically save user sessionKey, accessToken and other information
    • 如果开发者在其他应用未使用 uni-open-bridge-common 管理 access_token 等信息,可能会造成 access_token 冲突。 关于openid的说明

uni-id-pages 1.0.7 and earlier versions will save WeChat's openid in the following format

{
	"_id": "xx",
		"wx_openid": {
		"mp": "weixin-openid-demo"
	}
}

It can be seen that if there are multiple WeChat applet applications connected to an uniCloud background and associated with the same account, only the openid of one applet can be stored at this time.

This has been adjusted and corrected in the uni-id-pages 1.0.8 version, and multiple DCloud Appids can correspond to different WeChat openids. Taking Appid__UNI_123456 as an example, the openid will be stored in the database in the following form:

{
	"_id": "xx",
		"wx_openid": {
		"mp": "weixin-openid-demo",
		"mp___UNI_123456": "weixin-openid-demo",
	}
}

# QQ login

Log in if the QQ account already exists, otherwise register

Interface name: loginByQQ

Interface form

await uniIdCo.loginByQQ({
	code,
	accessToken,
	inviteCode
})

Parameter Description

Parameter Name Type Required Description
code string No code parameter returned by QQ applet uni.login
accessToken string No accessToken parameter returned by QQ login on the APP side
accessTokenExpired number No accessToken expiration time, the expires_in parameter returned by QQ login on the APP side
inviteCode string No Invite Code, only valid when registering

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • Supported login methods: QQ applet, QQ App
  • QQ login will automatically save the user's openid. In uni-id-pages 1.0.8 and later versions, when storing the openid, a copy of the current application's Appid (DCloud AppId in manifest.json) will be stored as the key. openid, see the description of openid below.
  • If there are multiple applications using the QQ applet to log in at the same time, and you want the user identity not to be isolated, please ensure that these applications are owned by the same entity on the QQ applet platform, that is, to ensure that different applications can obtain the same unionid
  • uni-id-pages 1.0.8 and above will use uni-open-bridge-common to save session_key (QQ applet login), access_token (QQ App login) information, but for compatibility with the old version logic is still in the user table A copy is stored. For details, please refer to: Automatically save user sessionKey, accessToken and other information

Note about openid

uni-id-pages 1.0.7 and earlier versions will store QQ's openid in the following form

{
	"_id": "xx",
		"qq_openid": {
		"mp": "weixin-openid-demo"
	}
}

It can be seen that if there are multiple QQ applets associated with the same account, only the openid of one applet can be stored at this time. This has been adjusted in the uni-id-pages 1.0.8 version. Take Appid__UNI_123456 as an example , the openid will be stored in the database as the following

{
	"_id": "xx",
	"qq_openid": {
		"mp": "weixin-openid-demo",
		"mp___UNI_123456": "weixin-openid-demo",
	}
}

# Alipay login

Login when Alipay account already exists, otherwise register

Interface name: loginByAlipay

Interface form

await uniIdCo.loginByAlipay({
	code,
	inviteCode
})

Parameter Description

Parameter Name Type Required Description
code string Yes The code parameter returned by the Alipay applet uni.login
inviteCode string No Invite Code, only valid when registering

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

# Apple login

Log in if the Apple account already exists, otherwise register

Interface name: loginByApple

Interface form

await uniIdCo.loginByApple({
	identityToken,
	nickname,
	inviteCode
})

Parameter Description

Parameter Name Type Required Description
identityToken string Yes The identityTokenc parameter returned by Apple login on the App side
nickname string no nickname
inviteCode string No Invite Code, only valid when registering

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

# Logout

Interface name: logout

Interface form

await uniIdCo.logout()

Parameter Description

none

return value

parameter name type description
errCode string|number Error code
errMsg string Error message

# logout

After calling this interface, the user status will be set to the logout state. It should be noted that the token will not be automatically invalidated at present, and redis will be introduced to solve this problem in the future. If this function is not required, it is recommended to modify the code manually.

Interface name: closeAccount

Interface form

await uniIdCo.closeAccount()

Parameter Description

none

return value

parameter name type description
errCode string|number Error code
errMsg string Error message

# Get supported login methods

Interface name: getSupportedLoginType

Interface form

await uniIdCo.getSupportedLoginType()

Parameter Description

none

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
supportedLoginType array List of supported login methods, see description below

supportedLoginType

Login Instructions
username-password Login with username and password
mobile-password Mobile phone number password login
email-password Email password login
mobile-code Mobile phone number verification code login
univerify App one-click login
weixin WeChat Login
qq QQ login
apple Apple Login
alipay Alipay login

# Bind account

# Use SMS verification code to bind mobile phone number

Interface name: bindMobileBySms

Interface form

await uniIdCo.bindMobileBySms({
	mobile,
	code,
	captcha
})

Parameter Description

Parameter Name Type Required Description
mobile string yes mobile number
code string Yes SMS verification code
captcha string No Captcha

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • only return a new newToken when the user's token is about to expire

# Use one-click login to bind mobile number

Interface name: bindMobileByUniverify

Interface form

await uniIdCo.bindMobileByUniverify({
	openid,
	access_token
})

Parameter Description

Parameter Name Type Required Description
openid string Yes The openid parameter returned by the client's one-click login
access_token string Yes access_token parameter returned by the client's one-click login

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • only return a new newToken when the user's token is about to expire

# Bind mobile phone number via WeChat

Be careful when using this interface

**The WeChat MiniApp has upgraded the security of the interface for obtaining the mobile phone number. Starting from uni-id-co@1.0.25, the dynamic password code for the getPhoneNumber event callback is supported, and it is reserved for backward compatibilityencryptedData and iv parameters, it is recommended that developers upgrade to enhance the security of MiniApp. **

The rule of the WeChat MiniApp is that the client should first use the checkSession interface to check whether the sessionKey obtained last time is still valid.

If it is valid, you can directly use the sessionKey stored last time. If it is invalid, call the login interface again to refresh the sessionKey again.

The user's sessionKey will be automatically updated when the WeChat applet logs in and binds the WeChat account of the applet.

Interface name: bindMobileByMpWeixin

Interface form

// uni-id-co >= 1.0.25
await uniIdCo.bindMobileByMpWeixin({
	code
})

// uni-id-co < 1.0.25
await uniIdCo.bindMobileByMpWeixin({
	encryptedData,
	iv
})

Parameter Description

Parameter Name Type Required Description
encryptedData string Yes The encryptedData parameter returned by the WeChat MiniApp to obtain the mobile phone number
iv string yes the iv parameter returned by the WeChat MiniApp to obtain the mobile phone number
code string yes the code parameter returned by the WeChat MiniApp to obtain the mobile phone number; uni-id-co >= 1.0.25 support

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • only return a new newToken when the user's token is about to expire

# Bind WeChat

Interface name: bindWeixin

Interface form

await uniIdCo.bindWeixin({
	code
})

Parameter Description

Parameter Name Type Required Description
code string Yes Code parameter returned by WeChat login

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • Only return a new newToken when the user token is about to expire
  • If the developer does not use uni-open-bridge-common to manage access_token and other information in other applications, it may cause access_token conflicts.

# Bind QQ

Interface name: bindQQ

Interface form

await uniIdCo.bindQQ({
	code,
	accessToken
})

Parameter Description

Parameter Name Type Required Description
code string No code parameter returned by QQ applet login
accessToken string No accessToken parameter returned by QQ login on the app side

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • only return a new newToken when the user's token is about to expire

# Bind Alipay account

Interface name: bindAlipay

Interface form

await uniIdCo.bindAlipay({
	code
})

Parameter Description

Parameter Name Type Required Description
code string Yes Code parameter returned by Alipay applet login

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • only return a new newToken when the user's token is about to expire

# Bind Apple account

Interface name: bindApple

Interface form

await uniIdCo.bindApple({
	identityToken
})

Parameter Description

Parameter Name Type Required Description
identityToken string Yes identityToken parameter returned by Apple login

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • only return a new newToken when the user's token is about to expire

# Unbind third-party account uni-id-co 1.0.25+

If there is only one third-party login method for the account, it is necessary to bind the mobile phone number and then unbind it.

# Unbind WeChat

Interface name: unbindWeixin

Interface form

await uniIdCo.unbindWeixin()

return value

parameter name type description
errCode string|number error code
errMsg string error message

# Unbind QQ

Interface name: unbindQQ Interface form

await uniIdCo.unbindQQ()

return value

parameter name type description
errCode string|number error code
errMsg string error message

# Unbind Alipay

Interface name: unbindAlipay Interface form

await uniIdCo.unbindAlipay()

return value

parameter name type description
errCode string|number error code
errMsg string error message

# Unbind Apple account

Interface name: unbindApple Interface form

await uniIdCo.unbindApple()

return value

parameter name type description
errCode string|number error code
errMsg string error message

# User info

# set password

Interface name: setPwd

Interface form

await uniIdCo.setPwd({
	code,
	captcha,
	password
})

Parameter Description

Parameter name Type Required Description
code string Yes Mobile phone verification code
captcha string no graphic verification code
password string yes password

return value

parameter name type description
errCode string|number error code

# Change password

Interface name: updatePwd

Interface form

await uniIdCo.updatePwd({
	oldPassword,
	newPassword
})

Parameter Description

Parameter Name Type Required Description
oldPassword string Yes Old Password
newPassword string Yes NewPassword

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • only return a new newToken when the user's token is about to expire

# Password reset via SMS verification code

Interface name: resetPwdBySms

Interface form

await uniIdCo.resetPwdBySms({
	mobile,
	code,
	password,
	captcha
})

Parameter Description

Parameter Name Type Required Description
mobile string yes mobile number
code string Yes SMS verification code
password string yes password
captcha string no graphic captcha

return value

parameter name type description
errCode string|number error code
errMsg string error message

# Reset password via email verification code

Interface name: resetPwdByEmail

Interface form

await uniIdCo.resetPwdByEmail({
	email,
	code,
	password,
	captcha
})

Parameter Description

Parameter Name Type Required Description
email string Yes Email
code string Yes Email Verification Code
password string yes password
captcha string no graphic captcha

return value

parameter name type description
errCode string|number Error code
errMsg string Error message

# Get account brief information

Interface name: getAccountInfo

Interface form

await uniIdCo.getAccountInfo()

Parameter Description

none

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
isUsernameSet boolean Whether there is a username
isNicknameSet boolean Is there already a nickname
isPasswordSet boolean Is a password set
isMobileBound boolean Whether the mobile phone number is bound
isEmailBound boolean Email is bound
isWeixinBound boolean Whether WeChat is bound
isQQBound boolean Whether QQ is bound
isAlipayBound boolean Is Alipay bound
isAppleBound boolean Is Apple account bound

# Accept the invitation

Interface name: acceptInvite

Interface form

await uniIdCo.acceptInvite({
	inviteCode
})

Parameter Description

Parameter Name Type Required Description
inviteCode string yes inviteCode

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • only return a new newToken when the user's token is about to expire

# Get invited user

Interface name: getInvitedUser

Interface form

await uniIdCo.getInvitedUser({
	level,
	limit,
	offset,
	needTotal
})

Parameter Description

Parameter Name Type Required Description
level number Yes Invite user level, for example, when the value is 1, it means the user you directly invite
limit number No The number returned by this request, default: 20
offset number No List offset value, default: 0, paging by combining with limit
needTotal boolean no whether to return the total number, default: false

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • only return a new newToken when the user's token is about to expire

# 获取账户实名信息(脱敏)uni-id-pages 1.1.2+

接口名:getRealNameInfo

接口形式

await uniIdCo.getRealNameInfo({
	decryptData
})

参数说明

参数名 类型 必填 说明
decryptData boolean 是否解密数据;默认:true

返回值

参数名 类型 说明
errCode string|number 错误码
errMsg string 错误信息
type number 用户类型:0 个人用户 1 企业用户
authStatus number 认证状态:0 未认证 1 等待认证 2 认证通过 3 认证失败
realName string 姓名(脱敏);用户类型为 0 时返回
identity string 身份证号码(脱敏);用户类型为 0 时返回

注意

在uni-id-pages中默认启用敏感数据加解密,如果开发者没有使用uni-id提供的敏感信息加密功能,请将decryptData参数改为false,返回原始信息

# Security Verification

# Create graphic captcha

Interface name: createCaptcha

Interface form

await uniIdCo.createCaptcha({
	scene
})

Parameter Description

Parameter Name Type Required Description
scene string yes The scene where the graphic verification code is used. Make sure that the scene where the verification code is used matches the scene parameters passed when generating the verification code, otherwise the verification will fail. Refer to: [Graphic verification code scene](uni- id-summary.md#captcha-scene)

return value

parameter name type description
errCode string|number Error code
errMsg string error message
captchaBase64 string Captcha: base64 format

# Refresh graphic captcha

Interface name: refreshCaptcha

Interface form

await uniIdCo.refreshCaptcha({
	scene
})

Parameter Description

Parameter Name Type Required Description
scene string Yes The usage scenario of the captcha, refer to: Graphic captcha scene

return value

parameter name type description
errCode string|number Error code
errMsg string error message
captchaBase64 string Captcha: base64 format

# Send SMS

The function of sending SMS requires the following pre-work

  1. Open SMS service in Developer Center and apply for SMS template
  2. Add the SMS template information corresponding to the verification code usage scenario in the uni-id configuration file, refer to: uni-id configuration file

Interface name: sendSmsCode

Interface form

await uniIdCo.sendSmsCode({
	mobile,
	captcha,
	scene
})

Parameter Description

Parameter Name Type Required Description
mobile string yes mobile number
captcha string yes graphic verification code
scene string yes The scene where the SMS verification code is used, make sure that the scene where the verification code is used matches the scene parameters passed when sending the verification code, otherwise the verification will fail, refer to: [SMS verification code usage scene](uni -id-summary.md#sms-scene)

return value

parameter name type description
errCode string|number error code
errMsg string error message

# Send email verification code

Interface name: sendEmailCode

Interface form

await uniIdCo.sendEmailCode({
	email,
	captcha,
	scene
})

Parameter Description

Parameter Name Type Required Description
email string Yes Email
captcha string yes graphic verification code
scene string yes use scene, refer to: mobile phone, email verification code use scene

return value

parameter name type description
errCode string|number Error code
errMsg string Error message

# Other client interfaces

# Refresh token

Interface name: refreshToken

Interface form

await uniIdCo.refreshToken()

Parameter Description

none

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

# update/set uni-push clientId

If you are not using uni-push 2.0, you don't need to pay attention to this interface. This interface is used to update the unipush_clientid field of the uni-id-device table, which is used to push messages by client, user and other dimensions

Interface name: setPushCid

Interface form

await uniIdCo.setPushCid({
	pushClientId
})

Parameter Description

Parameter Name Type Required Description
pushClientId string Yes The clientId corresponding to the uni-push obtained by the client

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

# WeChat secure network handshake

This interface is used for the handshake of the secure network on the WeChat MiniApp side. For related documents on the secure network, please refer to: secure-network

Generally, there is no need to call through uniCloud.importObject. When the client calls uniCloud.initSecureNetworkByWeixin(), session-related information will be obtained through this interface.

This interface will store the session information in the opendb-open-data table. If callLoginByWeixin: true is passed in the initSecureNetworkByWeixin method, it will execute a loginByWeixin of uni-id-co while storing the session information method

# Management interface

# Admin add user

Interface name: addUser

Interface form

await uniIdCo.addUser({
	username,
	password,
	authorizedApp,
	nickname,
	role
})

Parameter Description

Parameter name Type Required Description
username string yes username
password string yes password
authorizedApp Array<string> No A list of apps that allow login
nickname string no nickname
role Array<string> No User role
mobile string No Mobile phone number
email string no email
tags array no user tags
status number No User status, refer to: User Status

return value

parameter name type description
errCode string|number Error code
errMsg string Error message

# 管理员修改用户

接口名:updateUser

接口形式

await uniIdCo.updateUser({
	uid,
	username,
	password,
	nickname,
	authorizedApp,
	role,
	mobile,
	email,
	tags,
	status
})

参数说明

参数名 类型 必填 说明
uid string 要更新的用户id
username string 用户名
password string 密码
nickname string 昵称
authorizedApp Array<string> 允许登录的app列表
role Array<string> 用户角色
mobile string 手机号
email string 邮箱
tags array 用户标签
status number 用户状态,参考:用户状态

返回值

参数名 类型 说明
errCode string|number 错误码
errMsg string 错误信息

# Authorize the user to log in to the specified client

Interface name: authorizeAppLogin

Interface form

await uniIdCo.authorizeAppLogin({
	uid,
	appId
})

Parameter Description

Parameter Name Type Required Description
uid string yes userid
appId string yes DCloud AppId of the app allowed to log in

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • This interface is the management interface
  • only return a new newToken when the user's token is about to expire

# Remove user login authorization

Interface name: removeAuthorizedApp

Interface form

await uniIdCo.removeAuthorizedApp({
	uid,
	appId
})

Parameter Description

Parameter Name Type Required Description
uid string yes userid
appId string yes DCloud AppId of the app for which login is prohibited

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • This interface is the management interface
  • only return a new newToken when the user's token is about to expire

# Set the list of apps allowed to log in

Interface name: setAuthorizedApp

Interface form

await uniIdCo.setAuthorizedApp({
	uid,
	appIdList
})

Parameter Description

Parameter Name Type Required Description
uid string yes userid
appIdList Array<String> Yes The list of DCloud AppIds corresponding to the applications allowed to log in

return value

parameter name type description
errCode string|number Error code
errMsg string Error message
 |- token string token
 |- tokenExpired string token expiration time

Notice

  • This interface is the management interface
  • only return a new newToken when the user's token is about to expire

# 外部系统联登

适合自己有用户系统,同时需要使用依赖UniId的业务,将自身系统的用户账号导入uniId,为其创建一个对应uniId的账号,使得该账号可以使用依赖uniId的系统及功能。 由于此方案的接口不需要密码验证,开发者务必要保证接口只能在服务端调用,同时要求在请求时计算签名来保证安全。

联登相关接口只支持HTTP方式调用,调用时需要携带鉴权签名值,查看URL化请求鉴权签名计算

# 注册用户

外部用户注册,注册成功后,uni-id 返回 uid 与 用户 token ,请务必在自身系统中维护好 uid 与 token。

接口地址

POST /your-uni-id-co-path/externalRegister

HTTP 示例

POST /your-uni-id-co-path/externalRegister HTTP/1.1
Host: xxx.com
uni-id-nonce: xxxxxxx
uni-id-timestamp: 1676882808550
uni-id-signature: 11c965267a4a02c6978949c7135215b0a75aea22b2b84ed491e792365c8269efa
Content-Type: application/json
Cache-Control: no-cache

{"externalUid": "test externalUid", "nickname": "张三", "avatar": "xxxxxxx", "gender": 0}

注意

Request Body 说明

参数名 类型 必填 说明
externalUid string 自身系统的用户id,必须保证唯一性。
nickname string 用户昵称
avatar string 用户头像
gender number 用户性别;0 未知 1 男性 2 女性

Response Body 说明

parameter name type description
errCode string|number error code
errMsg string error message
 |- token string token
 |- tokenExpired string token过期时间
externalUid string 自身系统的用户id
uid string uni-id体系的用户Id
nickname string 用户昵称
avatar string 用户头像
gender string 用户性别;0 未知 1 男性 2 女性

# User login

External user login, used to obtain user token

接口地址

POST /your-uni-id-co-path/externalLogin

HTTP 示例

POST /your-uni-id-co-path/externalLogin HTTP/1.1
Host: xxx.com
uni-id-nonce: xxxxxxx
uni-id-timestamp: 1676882808550
uni-id-signature: 11c965267a4a02c6978949c7135215b0a75aea22b2b84ed491e792365c8269efa
Content-Type: application/json
Cache-Control: no-cache

{"externalUid": "test externalUid"}

注意

Request Body 说明

Parameter name Type Required Description
uid string uni-id体系的用户Id;与externalUid 二选一
externalUid string 自身系统的用户id;与 uid 二选一

Response Body 说明

parameter name type description
errCode string|number error code
errMsg string error message
 |- token string token
 |- tokenExpired string token过期时间
uid string uni-id体系的用户Id

# 修改用户信息

外部用户修改账号信息,如用户在自身系统内修改了用户信息后,通过此接口同步修改uni-id中用户信息。

接口地址

POST /your-uni-id-co-path/updateUserInfoByExternal

HTTP 示例

POST /your-uni-id-co-path/updateUserInfoByExternal HTTP/1.1
Host: xxx.com
uni-id-nonce: xxxxxxx
uni-id-timestamp: 1676882808550
uni-id-signature: 11c965267a4a02c6978949c7135215b0a75aea22b2b84ed491e792365c8269efa
Content-Type: application/json
Cache-Control: no-cache

{"externalUid": "test externalUid", "nickname": "张三"}

注意

Request Body 说明

参数名 类型 必填 说明
uid string uni-id体系的用户Id;与externalUid 二选一
externalUid string 自身系统的用户id;与 uid 二选一
username string 用户名
password string 密码
nickname string 昵称
authorizedApp Array<string> 允许登录的app列表
role Array<string> 用户角色
mobile string 手机号
email string 邮箱
tags array 用户标签
status number 用户状态,参考:用户状态
avatar string 用户头像
gender number 用户性别;0 未知 1 男性 2 女性

Response Body 说明

参数名 类型 说明
errCode string|number 错误码
errMsg string 错误信息

# 实名认证 uni-id-pages 1.1.7+

实人认证相关功能建议或问题,可以加入uni-im交流群进行讨论,点此加入

基于实人认证服务实现,实现用户刷脸核验真实身份,完成实名认证。 uni-id-pages已内置实人认证前端页面与云端云对象,了解如在uni-id-pages中使用。

# 获取认证ID

接口名:getFrvCertifyId

接口形式

await uniIdCo.getFrvCertifyId({
	realName,
	idCard,
	metaInfo
})

参数说明

参数名 类型 必填 说明
realName string 用户真实姓名
idCard string 用户身份证号码
metaInfo String 客户端初始化时返回的metaInfo

返回值

参数名 类型 说明
errCode string|number 错误码
errMsg string 错误信息
certifyId object 认证Id;用于客户端调用认证接口及云函数获取认证结果

# 获取认证结果

接口名:getFrvAuthResult

接口形式

await uniIdCo.getFrvAuthResult({
	certifyId
})

参数说明

参数名 类型 必填 说明
certifyId string 认证Id

返回值

参数名 类型 说明
errCode string|number 错误码
errMsg string 错误信息
authStatus number 认证状态:0 未认证 1 等待认证 2 认证通过 3 认证失败
realName string 姓名(脱敏);敏感信息加密参考
identity string 身份证号码(脱敏);敏感信息加密参考

# Other functions

# Override or add validation rules

uni-id-co mounts the validator instance on the this of the cloud object. After obtaining the validator instance from uni-id-co/index.obj.js, you can use the mixin method of the validator instance to overwrite or add validation rules.

Interface form: validator.mixin(String type, Function handler). Where type is the rule type (string), handler is the verification function

// uni-id-co/index.obj.js
const {
	Validator
} = require('./common/validator.js')
module.exports = {
	_before () {
		this.validator = new Validator()
		/**
		 * 示例:覆盖密码验证规则
		 */
		this.validator.mixin('password', function (password) {
			if (typeof password !== 'string' || password.length < 10) {
				// 调整为密码长度不能小于10
				return {
					errCode: ERROR.INVALID_PASSWORD
				}
			}
		})
		/**
		 * 示例:新增验证规则
		 */
		this.validator.mixin('timestamp', function (timestamp) {
			if (typeof timestamp !== 'number' || timestamp > Date.now()) {
				return {
					errCode: ERROR.INVALID_PARAM
				}
			}
		})
		// // 新增规则同样可以在数组验证规则中使用
		this.validator.valdate({
			timestamp: 123456789
		}, {
			timestamp: 'timestamp'
		})
		this.validator.valdate({
			timestampList: [123456789, 123123123123]
		}, {
			timestampList: 'array<timestamp>'
		})
		// // 甚至更复杂的写法
		this.validator.valdate({
			timestamp: [123456789, 123123123123]
		}, {
			timestamp: 'timestamp|array<timestamp>'
		})
	}
}

# Login service activation and configuration

The key information of the server uni-id is uniformly configured in uni-config-center, the path: uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/uni-id/ config.json Hereinafter referred to as: uni-id configuration file, complete configuration information see details

# One-click login

One-click login is a more convenient, safer, and cheaper solution than SMS verification codes provided by operators. See for details.

  • To use this function, you need to activate and recharge in DCloud Developer Center ->
  • Module configuration: manifest.json-->App module configuration -->OAuth (login authentication)-->One-click login, click on the back of Activate configuration, and then open the web In the interface, agree to the agreement, and click the recharge button to recharge. If it is just a test, you can only recharge 1 yuan. If you have determined the package name, you can click "Add Application" on the web interface to submit for review. This is required for official packaging. You can skip this link in real machine operation. Remember the apiKey and apiSecret shown on the page, which will be used in the next step.
  • uni-id configuration: uni-id configuration file --> service --> univerify, fill in appid, apiKey and apiSecret. appid is the appid in the manifest. apiKey and apiSecret are obtained from the web interface in the previous step.

# WeChat login

uni-id-pages has fully supported: app, applet, web (from uni-id-pages version 1.0.8), WeChat login on three terminals.

WeChat divides applications into 4 categories:

  1. Mobile application: refers to the non-WeChat App, calling WeChat to log in. Belong to WeChat Open Platform WeChat Open Platform Account
  2. Website application: Refers to the browser webpage other than WeChat, and calls WeChat to log in by scanning the code of WeChat on the mobile phone. Belong to WeChat Open Platform WeChat Open Platform Account
  3. Official account: Refers to accessing the official account H5 in the built-in browser of WeChat. It belongs to the WeChat public account platform https://mp.weixin.qq.com/
  4. Small program: refers to the small program in WeChat. It belongs to the WeChat public account platform https://mp.weixin.qq.com/

The website application and official account here are both for web applications, accessing the WeChat login function. But there are the following differences:

Hosting Environment Type Login Method
WeChat APP Official Account Website Authorized Login
Ordinary browser Website application Mobile WeChat scan code login

# How to choose WeChat open platform and WeChat public platform

  • If your application only runs in WeChat, whether it is a WeChat applet or WeChat official account H5, it belongs to WeChat Public Platform.
  • If your app runs outside WeChat, whether it is other apps or other webpages outside WeChat, it belongs to WeChat Open Platform.

You can open a corresponding platform account according to your needs.

Notice

If your application has multiple ends, realize unified identification, information synchronization and behavior tracking of the same user in different scenarios such as official accounts, mini programs, APPs, official websites, etc. (For details, please refer to: "UnionID Association" Function Introduction and Operation Suggestions) It is necessary to bind the Mini Program and Official Account to the same WeChat Open Platform Account.

  • Binding method: log in to WeChat Open Platform -> Management Center -> select Official Account/Mini Program -> Click `Bind Official Account/ applet

# 客户端配置

  • APP side:
    • Open manifest.json -> App module configuration -> OAuth (login authentication) -> Check WeChat login -> fill in appid, ios platform universal link.
    • iOS platform WeChat login SDK needs to configure universal links. For details, please refer to: [https://uniapp.dcloud.io/api/plugins/universal-links.html](https://uniapp.dcloud.io/api/plugins/ universal-links.html).
  • Mini Program: Open manifest.json -> WeChat Mini Program Configuration -> Fill in WeChat Mini Program AppID
  • On the web side: open /uni_modules/uni-id-pages/config.js -> appid -> weixin Configure the appid of the WeChat public account on the h5 node, and configure the WeChat open platform creation on the web node web application appid

# 服务端配置

  • The key information of server uni-id is uniformly configured in uni-config-center, path: uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json, complete Configuration information details view

# web端微信登录专题

登录的流程为:

  1. On the application page, open the WeChat login authorization page link (pass the appid and redirect_uri as get parameters)
  2. Enter the authorization page, the user agrees to authorize to get the code; carry the code in the form of get parameter, and redirect to the redirect_uri filled in in step 1
  3. Go back to the application page, get the code value and call the loginByWeiXin method of the uni-id-co cloud object, and get the token to complete the login
  • appid说明:微信app内打开的网页,为公众号的appid。其他场景则为在微信开放平台创建的网站应用的appid。
  • redirect_uri description: The website link returned after entering the authorization page. The domain name of this link needs to be configured in the service background first. For details, see: Configuration of the callback domain name

Example code is already provided in the uni-id-pages plugin.

# Callback domain name configuration

  • 手机微信扫码登录
    微信开放平台 -> 管理中心 -> 网站应用 -> 选择对应的应用名称,点击查看 -> 开发信息,点击修改 -> 填写授权回调域

  • 基于微信公众号auth登录
    登录微信公众号 -> 设置与开发 -> 公众号设置 -> 设置网页授权域名

# 本地调试

To call back the domain name, you must access the URL address that has been registered on the external network. Otherwise, debugging cannot be performed locally. You can do intranet penetration and map to generate an external network URL address for callback testing. But that is more troublesome, here we introduce a method to start a Web Server locally for debugging based on HBuilderX.

  1. Start a Web Server service on port 80
  • open manifest.json -> H5 configuration -> port -> enter 80

Note: In the mac system, non-root users cannot use common ports less than 1024. Solution Open Terminal, cd to the HBuilderX installation directory (the default is Applications directory, execute cd /Applications), then execute sudo ./HBuilderX.app/Contents/MacOS/HBuilderX, enter the power-on password, and press Enter , HBuilderX will be reopened with root user privileges;

  • Run the project to the browser through HBuilderX to enable a 80-port Web Server

If port 80 is not enabled but 81, etc., your port is occupied. You have two options: 1. Close the suspicious program, or restart the computer directly. 2. Close the port occupied by the command line [Details](https://www.baidu.com/s?&wd=%E5%91%BD%E4 %BB%A4%E8%A1%8C%20%E8%A7%A3%E5%86%B3%E7%AB%AF%E5%8F%A3%E8%A2%AB%E5%8D%A0%E7 %94%A8)

  1. 实现访问域名直接指向你的本地web Server 可以通过内网穿透实现,但比较麻烦且可能会影响线上用户。这里推荐直接修改hosts,hosts是一个没有扩展名的系统文件,其基本作用就是将一些常用的网址域名与其对应的 IP 地址建立一个关联“ 数据库 ”。当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从hosts文件中寻找对应的 IP 地址,一旦找到,系统就会立即打开对应网页,如果没有找到,系统才会将网址提交 DNS 域名解析服务器进行 IP 地址的解析。
    host文件路径: Windows系统一般为:C:\Windows\System32\drivers\etc。mac系统:/etc/
    用HBuilderX打开hosts文件,在末尾添加一行 127.0.0.1 你的域名保存即可。 此时访问域名,如果就能看到和你的项目运行到浏览器一样的效果,说明已经成功了。

# Apple Login Integration Guide

  • Module configuration: manifest.json --> App module configuration --> OAuth (login authentication) check Apple login, [IOS Apple Authorized Login Reference Document](https://ask.dcloud. net.cn/article/36651). If you do not publish to the Appstore, you do not need to configure this
  • uni-id configuration: uni-id configuration file --> app --> oauth --> apple Fill in bundleId.
  • Associated domain configuration: manifest.json --> App common other settings --> iOS settings --> Associated Domains Fill in the configuration [Reference Tutorial](https://ask. dcloud.net.cn/article/36393). If you do not publish to the Appstore, you do not need to configure this

# SMS verification code

为了方便开发调试,uni-id-pages未配置短信登录时,自动启动测试模式;直接使用:123456作为短信验证码即可。

# Upgrade from the old uni-id public module to uni-id-pages

Before HBuilderX 3.5, DCloud provided a common module uni-id (not to be confused with uni-id-common) and an example Cloud function uni-id-cf (integrated in uni-starter and uni-admin).

The old public module uni-id is a large and comprehensive account management public module, which is too large to be referenced by other cloud functions . For example, a business cloud function needs to verify the user token, and the referenced uni-id public module also contains the code for forgetting the password, which is a waste of resources.

From HBuilder 3.5 onwards, both uni-id and uni-id-cf will be phased out and will no longer be updated. The old common module uni-id was disassembled and turned into uni-id-common public module and uni-id-co cloud object .

uni-id-common is very compact, including only tokens and permissions, and is suitable for being referenced by all cloud functions.

uni-id-co is a more complete and standardized user-managed cloud object than uni-id-cf.

Then DCloud introduced uni-id-pages.

At present, uni-starter and uni-admin still use the old version uni-id and uni-id-cf. User management for uni-id-pages is upgraded.

# Upgrade from uni-id common module to uni-id-common + uni-id-co

Significant changes have been made in this upgrade, most of the interfaces have been removed from public modules and implemented by uni-id-co instead. Only the interfaces for creating token, refreshing token, and verifying token remain in the uni-id public module. In addition to interface adjustments, the uni-id system (including uni-id public modules, uni-id-co) has the following adjustments:

  • Completely remove bindTokenToDevice logic and configuration
  • Completely remove the removePermissionAndRoleFromToken logic and its configuration, the user role permissions will definitely be cached in the token
  • uni-id-common 1.0.9 and earlier did not store tokens in the user table, since uni-id-common 1.0.10, the token is still stored in the user table (consistent with the old version of uni-id)
  • Add the valid_token_date field for the user, update this value in the scenario of changing the password, resetting the password, banning the user, and verifying when the token is refreshed. If the token creation time is less than this timestamp, it will be equivalent to the token has expired
  • Add a third_party field for users to cache the user's token, sessionKey and other information on the third-party platform
  • Username and email will be converted to all lowercase when stored
  • preferedAppPlatform, preferedWebPlatform no longer take effect, inside uni-id, app will be used instead of app-plus, and web will be used instead of h5
  • Platform name adjustment under the wx_openid field, please refer to the description of Field name adjustment below
  • The platform name is adjusted under the qq_openid field. For details, please refer to the description of Field name adjustment below.

# Field name adjustment

When uni-id is upgraded to uni-id-co + uni-id-common, individual fields need to be renamed, and the changed fields can be renamed by directly running the following cloud function. In addition, you need to modify the index, delete the index of the old field, and add the index of the new field. It is recommended to operate in the early morning or other low-peak periods to avoid database operations taking too long to affect online users. (In the actual data test, 50,000 user records took about 5 seconds to rename the field)

'use strict';
const db = uniCloud.database()
const dbCmd = db.command
exports.main = async (event, context) => {
	await db.collection('uni-id-users').update({
		wx_openid: {
			'app-plus': dbCmd.rename('wx_openid.app'), // app端微信openid
			'mp-weixin': dbCmd.rename('wx_openid.mp'), // 小程序端微信openid
			'h5-weixin': dbCmd.rename('wx_openid.h5'), // 微信公众号端微信openid
			'h5-web': dbCmd.rename('wx_openid.web') // web端微信openid
		},
		qq_openid: {
			'app-plus': dbCmd.rename('qq_openid.app'), // app端QQ openid
			'mp-qq': dbCmd.rename('qq_openid.mp') // 小程序端QQ openid
		}
	})
	return {}
};

# URL request authentication signature

uni-id-co@1.1.10及以上版本支持使用uni-cloud-s2s进行请求签名验证,uni-cloud-s2s使用方式详见

uni-id-co请求鉴权签名与uni-cloud-s2s不能同时存在,如果存在uni-cloud-s2s,则会优先使用uni-cloud-s2s进行请求签名验证

uni-id-co 在URL化请求时,会对以下 API 进行调用鉴权验证, 在调用 API 时,开发者需要使用请求鉴权密钥(详见配置文件requestAuthSecret按照 uni-id 的约定方式对请求中的关键数据进行签名值计算, And add the signature value to the uni-id-signature parameter of the Header request header and pass it to uni-id for signature verification, and uni-id will calculate the signature value for the received data, And compare it with the received request signature value, if the signature value is inconsistent, it will be regarded as an invalid signature, and the request will be rejected.

List of APIs that need to be signed

API
externalRegister
externalLogin

# Request header public parameters

parameter name type required description
uni-id-nonce string is a random string
uni-id-timestamp string yes current timestamp; in milliseconds
uni-id-signature string yes request authentication signature; signature algorithm see below

# 鉴权签名算法

如下为某请求体参数,介绍如何进行签名:

{
	"clientInfo": {
		"appId": "__test__"
	},
	"uniIdToken": "xxxxxx",
	"params": {
		"foo": 1,
		"bar": 2,
		"foo_bar": 3,
		"foobar": 4
	}
}
  1. 将API请求参数(只包括请求体(body)中的params参数,但除去array与object类型的参数),根据参数名称的ASCII码表的顺序排序。如:foo:1, bar:2, foo_bar:3, foobar:4排序后的顺序是 bar:2, foo:1, foo_bar:3, foobar:4
  2. Assemble the sorted parameter name and parameter value according to key1=value1&key2=value2 format, the result obtained according to the above example is: bar=2&foo=1&foo_bar=3&foobar=4
  3. The assembled string is encoded in utf-8, and the developer uses the request authentication key and random string to perform HmacSHA256 encryption on the timestamp and the string to be signed, and calculate the request signature value, such as: HmacSHA256( timestamp + bar=2&foo=1&foo_bar=3&foobar=4, requestAuthSecret + nonce)
  4. Express the encrypted binary result in hexadecimal, and the value must be uppercase, such as: Hex.stringify(Utf8.parse("helloworld")) = "68656C6C6F776F726C64"

# Signature value calculation example

# Nodejs

const crypto = require('crypto')

class Sign {
	constructor (requestAuthSecret) {
		this.requestAuthSecret = requestAuthSecret
	}

	getSignature (params, nonce, timestamp) {
		const paramsStr = this.getParamsString(params)
		const signature = crypto.createHmac('sha256', `${requestAuthSecret}${nonce}`).update(`${timestamp}${paramsStr}`).digest('hex')

		return signature.toUpperCase()
	}

	getParamsString (params) {
		return Object.keys(params)
				.sort()
				.filter(item => typeof params[item] !== "object")
				.map(item => `${item}=${params[item]}`)
				.join('&')
	}
}

const requestAuthSecret = "testSecret"
const nonce = Math.random().toString(36).substring(2)
const timestamp = Date.now()

const params = {
	foo: 1,
	bar: 2,
	foo_bar: 3,
	foobar: 4
}

const sign = new Sign(requestAuthSecret)
const signature = sign.getSignature(params, nonce, timestamp)

console.log("nonce: ", nonce)
console.log("timestamp: ", timestamp)
console.log("signature: ", signature)

# PHP

<?php

class Sign {
    private $requestAuthSecret;

    public function __construct ($requestAuthSecret) {
        $this->requestAuthSecret = $requestAuthSecret;
    }

    public function getSignature ($params, $nonce, $timestamp) {
        $paramsStr = $this->getParamsString($params);
        $signature = hash_hmac('sha256', ((string)$timestamp . $paramsStr), ($this->requestAuthSecret . $nonce));

        return strtoupper($signature);
    }
    
    private function getParamsString ($params) {
        ksort($params);

        $paramsStr = [];
        foreach($params as $key=>$value){
            if (gettype($value) == "array" || gettype($value) == "object") {
                continue;
            }

            array_push($paramsStr, $key . '=' . $value);
        }
        
        return join('&', $paramsStr);
    }
}

$requestAuthSecret = "testSecret";
$nonce = sprintf("%d", rand());
$timestamp = time() * 1000;

$params = [
    "foo" => 1,
    "bar" => 2,
    "foobar" => 4,
    "foo_bar" => 3,
];

$sign = new Sign($requestAuthSecret);
$signature = $sign->getSignature($params, $nonce, $timestamp);

print_r("nonce: " . $nonce . PHP_EOL);
print_r("timestamp: " . $timestamp . PHP_EOL);
print_r("signature: " . $signature);

# Python

import hmac
import hashlib
import time

class Sign:
  def __init__(self, requestAuthSecret):
        self.requestAuthSecret = requestAuthSecret

  def get_signature (self, params, nonce, timestamp):
    params_str = self.get_params_string(params)
    signature = hmac.new(bytes("%s%s" % (self.requestAuthSecret, nonce), 'utf-8'), bytes("%s%s" % (timestamp, params_str), 'utf-8'), digestmod = hashlib.sha256).hexdigest().upper()
    
    return signature
  
  def get_params_string(self, params):
    params_str = []
    for k in sorted(params):
      if isinstance(params[k], (list, dict)):
        continue 
      params_str.append("%s=%s" % (k, params[k]))
      
    return "&".join(params_str)

if __name__ == "__main__":   
  requestAuthSecret = "testSecret"
  nonce = "xxxxxxx"
  timestamp = int(round(time.time() * 1000))

  params = {
    "foo": 1,
    "bar": 2,
    "foobar": 4,
    "foo_bar": 3,
  }

  sign = Sign(requestAuthSecret)
  signature = sign.get_signature(params, nonce, timestamp)

  print(nonce, timestamp, signature)

# Go

package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"sort"
	"strconv"
	"strings"
	"time"
)

type Sign struct {
	requestAuthSecret string
}

func (sign Sign) getSignature(params map[string]string, nonce string, timestamp int64) string {
	paramsStr := sign.getParamsString(params)

	mac := hmac.New(sha256.New, []byte(sign.requestAuthSecret+nonce))
	mac.Write([]byte(strconv.Itoa(int(timestamp)) + paramsStr))
	hexSignature := mac.Sum(nil)
	signature := hex.EncodeToString(hexSignature)

	return strings.ToUpper(signature)
}

func (sign Sign) getParamsString(params map[string]string) string {
	keys := make([]string, 0, len(params))
	for k := range params {
		keys = append(keys, k)
	}

	sort.Strings(keys)

	var paramsStr string = ""
	i := 0
	for _, k := range keys {
		v := params[k]
		if i != 0 {
			paramsStr += "&"
		}
		paramsStr += k
		paramsStr += "="
		paramsStr += v
		i++
	}

	return paramsStr
}

func main() {
	requestAuthSecret := "testSecret"
	nonce := "xxxxxxx"
	timestamp := time.Now().UnixMilli()

	params := map[string]string{
		"foo":     "1",
		"bar":     "2",
		"foo_bar": "3",
		"foobar":  "4",
	}

	sign := Sign{
		requestAuthSecret: requestAuthSecret,
	}
	signature := sign.getSignature(params, nonce, timestamp)

	result := fmt.Sprintf("nonce: %s, timestamp: %d, signature: %s", nonce, timestamp, signature)

	fmt.Println(result)
}

# Java

import java.util.HashMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;
import java.util.Map;

public class Sign {
    static String requestAuthSecret = "testSecret";

    public static void main(String[] args) {
        String nonce = "xxxxxx";
        long timestamp = System.currentTimeMillis();

        Map<String, String> params = new HashMap<String, String>();

        params.put("foo", "1");
        params.put("bar", "2");
        params.put("foo_bar", "4");
        params.put("foobar", "3");

        String signature = getSignature(params, nonce, timestamp);

        System.out.println("nonce: " + nonce);
        System.out.println("timestamp: " + timestamp);
        System.out.println("signature: " + signature);
    }

    public static String getSignature (Map<String, String> params, String nonce, long timestamp) {
        String paramsStr = getParamsString(params);
        String algorithm = "HmacSHA256";
        Mac hmacSha256;
        String digestHexString = null;

        try {
            hmacSha256 = Mac.getInstance(algorithm);
           
            String key = new StringBuilder().append(requestAuthSecret).append(nonce).toString();
            String message = new StringBuilder().append(Long.toString(timestamp)).append(paramsStr).toString();

            byte[] keyBytes = key.getBytes("utf-8");
            byte[] messageBytes = message.getBytes("utf-8");
            
            hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, algorithm));
            byte[] digestBytes = hmacSha256.doFinal(messageBytes);

            digestHexString = byteArrayToHexString(digestBytes);
        } catch (Exception e) {
            System.out.println("[ERROR] not supposed to happen: " + e.getMessage());
        }

        return digestHexString.toUpperCase();
    }

    private static String getParamsString (Map<String, String> params) {

        String[] keys = params.keySet().toArray(new String[0]);
        Arrays.sort(keys);

        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < keys.length; i ++) {
            String key = keys[i];

            if (i != 0) {
                sb.append("&");
            }
            
            sb.append(key).append("=").append(params.get(key));
        }

        return sb.toString();
    }

    private static String byteArrayToHexString(byte[] b) {
        StringBuilder hs = new StringBuilder();
        String stmp;
        for (int n = 0; b!=null && n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0XFF);
            if (stmp.length() == 1)
                hs.append('0');
            hs.append(stmp);
        }
        return hs.toString();
    }
}
On This Page