# 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

uni-id-co所有api返回值均满足uniCloud响应体规范

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.

# 适配URL化

uni-id-pages@1.0.29版本起支持URL化 什么是URL化

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 密码
captcha string 否(此操作错误3次以上为必填) 图形验证码

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 否(此操作错误3次以上为必填) 图形验证码
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.
  • 如果有多个应用同时使用微信小程序登录,且希望用户身份不隔离请确保这些应用在微信小程序平台为同一主体所有,即保证不同应用可以获取同样的unionid
  • uni-id-pages 1.0.8及以上版本会使用uni-open-bridge-common保存session_key(微信小程序登录)、access_token(微信公众号登录、微信App登录)这些信息,但是为了兼容旧版逻辑仍在用户表存储了一份副本。详细说明参考:自动保存用户sessionKey、accessToken等信息
    • 如果开发者在其他应用未使用 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.
  • 如果有多个应用同时使用QQ小程序登录,且希望用户身份不隔离请确保这些应用在QQ小程序平台为同一主体所有,即保证不同应用可以获取同样的unionid
  • uni-id-pages 1.0.8及以上版本会使用uni-open-bridge-common保存session_key(QQ小程序登录)、access_token(QQ App登录)这些信息,但是为了兼容旧版逻辑仍在用户表存储了一份副本。详细说明参考:自动保存用户sessionKey、accessToken等信息

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 短信验证码
captcha string 否(此操作错误3次以上为必填) 图形验证码

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

  • 仅在用户token即将过期时返回新newToken
  • 如果开发者在其他应用未使用 uni-open-bridge-common 管理 access_token 等信息,可能会造成 access_token 冲突。

# 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 手机验证码
captcha string 否(此操作错误3次以上为必填) 图形验证码
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 密码
captcha string 否(此操作错误3次以上为必填) 图形验证码

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 密码
captcha string 否(此操作错误3次以上为必填) 图形验证码

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 图形验证码使用场景,务必确保使用验证码的场景和生成验证码时传的场景参数相匹配,否则会校验不通过,参考:图形验证码场景

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 图形验证码使用场景,参考:图形验证码场景

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. 开发者中心开通短信服务,并申请短信模板
  2. 在uni-id的配置文件里面添加验证码使用场景对应的短信模板信息,参考:uni-id配置文件

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 图形验证码
scene string 短信验证码使用场景,务必确保使用验证码的场景和发送验证码时传的场景参数相匹配,否则会校验不通过,参考:短信验证码使用场景

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

此接口用于微信小程序端安全网络的握手,安全网络相关文档请参考:安全网络

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 用户标签
status number 用户状态,参考:用户状态

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

服务端uni-id的密钥信息统一在uni-config-center中配置,路径:uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json 以下简称:uni-id配置文件,完整的配置信息详情查看

# 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

# 服务端配置

  • 服务端uni-id的密钥信息统一在uni-config-center中配置,路径:uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json,完整的配置信息详情查看

# 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