Recently, when using Tencent cloud, using wechat scanning code login, found that will jump to Tencent cloud assistant small program to confirm login. Feel very good to use, just want to do a scan code login.

Implementation principle:

  1. Open the website, use cloud development, and log in anonymously
  2. The user clicks wechat login, invokes cloud function, obtains anonymous user UID, and generates a small program code with parameter UID
  3. The user’s wechat scan code enters the small program, obtains the UID and binds it with the user _openID
  4. The Web side obtains user information through uid, and the small program side obtains user information through _openID

Web side

1. Anonymous login

Enter the Tencent Cloud development console, under the login authorization option, open the anonymous login

2. Configure secure domain names

3. Under the database option, create a user set. The details page is displayed

{
  "read": "doc._openid == auth.openid||doc.uid == auth.uid"."write": "doc._openid == auth.openid||doc.uid == auth.uid"
}
Copy the code

4. Create the index. HTML page

Mainly more: click wechat login, call weblogin cloud function, obtain the small program code, and render to the page. Based on the UID, listen to the user collection and render the user’s information to the page after the user logs in to the applet.

<! DOCTYPEhtml>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <title>Small program scan code login</title>
</head>

<body>
    <div class="contain">
        <h2>Small program scan code login</h2>
        <button type="button" onclick="getQRCode()" id="button">WeChat login</button>
        <div id="avatar"></div>
        <div id="qrcode"></div>
    </div>

    <script src="/ / imgcache.qq.com/qcloud/cloudbase-js-sdk/1.5.0/cloudbase.full.js"></script>
    <script>
        const app = cloudbase.init({
            env: "ww"   // Enter your environment ID here
        });
        const auth = app.auth();
        async function login() {
            await auth.anonymousAuthProvider().signIn();
            // Successful detection of anonymous login The isAnonymous field is true
            const loginState = await auth.getLoginState();
            console.log(loginState.isAnonymousAuth); // true
        }
        login();

        // Call the cloud function to get the small program code with parameters
        async function getQRCode() {
            const result = await app.callFunction({ name: "weblogin" })

            const { uid, fileId } = result.result;

            const linkresult = await app.getTempFileURL({
                fileList: [fileId]
            })
            const QRCodeUrl = linkresult.fileList[0].tempFileURL;
            window.uid = uid;
            window.QRCodeUrl = QRCodeUrl;
            const qrcodeimg = document.createElement('img');
            qrcodeimg.src = QRCodeUrl;
            document.getElementById('qrcode').appendChild(qrcodeimg);
            interval();
        }

        // Get user information
        async function getUserInfo() {
            const uid = window.uid;
            const userInfo = await app
                .database()
                .collection("user")
                .where({
                    uid: uid,
                })
                .get();
            console.log("Acquired user information", userInfo);
            return userInfo;
        }

        // Listen for the update event of the data in the collection that matches the query criteria
        const interval = async function () {
            const watcher = await app
                .database()
                .collection("user")
                .where({
                    uid: uid
                })
                .watch({
                    onChange: async function (snapshot) {

                        const userData = await getUserInfo();
                        if(userData.data.length ! =0) {
                            const { avatarUrl, city, nickName } = userData.data[0];
                            document.getElementById('qrcode').style.visibility = 'hidden';
                            document.getElementById('avatar').innerHTML = `<img width="100" height="100" src="${avatarUrl}"><br>${nickName}<br>${city}`;

                            document.getElementById("button").style.visibility = "hidden";
                            document.getElementById("qrcode").style.visibility = "hidden"; }},onError: function (err) {
                        console.error("the watch closed because of error", err); }}); };</script>
</body>

</html>
Copy the code

Cloud function

Create a WebLogin cloud function

Main function: obtain the uid of anonymous login user, and generate small program code with parameters

const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
const tcb = require("@cloudbase/node-sdk")

const app = tcb.init({ env: cloud.DYNAMIC_CURRENT_ENV });
const auth = app.auth();

const axios = require('axios')
const APPID = "* * * * * *"  // Use your appid
const APPSECRET= "* * * * * *" // Replace your applet key
exports.main = async (event, context) => {
  const { userInfo } = await auth.getEndUserInfo();
  console.log(userInfo);
  const {uid} = userInfo

    const tokenurl = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}`
    const res = await axios.get(tokenurl)
    const {access_token} = res.data

    const qrcodeurl=`https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${access_token}`
    const wxacodeResult = await axios({
      method: 'post'.url: qrcodeurl,
      responseType: 'arraybuffer'.data: {
        scene:uid,
        page:"pages/login/login"}});const uploadResult = await cloud.uploadFile({
      cloudPath: `${uid}.jpeg`.fileContent: wxacodeResult.data
    })

    return {
      uid:uid,
      fileId:uploadResult.fileID
    }
}
Copy the code

In the package.json file, add the following modules

{
  "dependencies": {
    "@cloudbase/node-sdk": "^ 2.7.1." "."axios": "^ 0.21.1"."wx-server-sdk": "~ 2.5.3." "}}Copy the code

Create the userInfo cloud function

Main functions: Manage user information, query, add and update

// Cloud function entry file
const cloud = require('wx-server-sdk')
const TcbRouter = require('tcb-router');
cloud.init({
  // The API calls are kept consistent with the current environment of the cloud function
  env: cloud.DYNAMIC_CURRENT_ENV
})
const db = cloud.database()

// Cloud function entry function
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()
  const app = new TcbRouter({
    event
  })
  const collection = "user" // Database name

  app.use(async (ctx, next) => {
    ctx.data = {}
    await next();
  });

  app.router('checkUser'.async (ctx, next) => {
    ctx.body = await db.collection(collection).where({
      _openid: wxContext.OPENID // Enter the current user openID
    }).get()
  })

  app.router('addUser'.async (ctx, next) => {
    ctx.body = await db.collection(collection)
      .add({
        data: {
          _openid: wxContext.OPENID, ... event.data } }) }) app.router('updateUser'.async (ctx, next) => {
    ctx.body = await db.collection(collection).where({
      _openid: wxContext.OPENID
    }).update({
      data: {
        uid: event.uid
      },
    })
  })

  return app.serve();
}
Copy the code

Add the following modules to the package.json file

{" dependencies ": {" wx - server - SDK" : "~ 2.5.3", "TCB - the router" : "latest"}}Copy the code

The small program end

Creating a Login page

In the login. WXML file, render the user information

<! --pages/login/login.wxml-->
<view class="container">
    <open-data type="userAvatarUrl"></open-data>
    <open-data type="userNickName"></open-data>
    <view class="padding-xl margin-top-xl" wx:if="{{! isLogin}}">
      <button bindtap="getUserProfile">Confirm the login</button>
    </view>
    <view class="padding-xl margin-top-xl" wx:if="{{isLogin}}">
      <text>You have logged in successfully!</text>
    </view>
</view>
Copy the code

In the login.js file, write the business logic

Page({

  /** * initial data for the page */
  data: {
    hasUser: 0.uid: ' '.isLogin: false
  },

  /** * lifecycle function -- listens for page loading */
  onLoad: function (options) {
    this.checkUser()
    if (options.scene) {
      const scene = decodeURIComponent(options.scene)
      this.setData({
        uid: scene
      })
    }
  },

  /** * call the cloud function -- query the database for the user */
  checkUser() {
    wx.cloud.callFunction({
      name: 'userInfo'.data: {
        $url: "checkUser"
      }
    }).then(res= > {
      this.setData({
        hasUser: res.result.data.length
      })
    }).catch(console.error)
  },

  getUserProfile() {
    wx.showLoading({
      title: 'Loading',})if (this.data.hasUser) {
      wx.cloud.callFunction({
        name: 'userInfo'.data: {
          $url: "updateUser".uid: this.data.uid
        },
      }).then(res= > {
        this.setData({
          isLogin: true
        })
        wx.showToast({
          title: 'Login successful'.icon: 'success'.duration: 2000
        })
      }).catch(console.error)
    } else {
      const that = this;
      wx.getUserProfile({
        desc: 'Show user information'.// Specify the purpose of obtaining the user's personal information, which will be displayed in the subsequent pop-up window
        success: (res) = > {
          wx.cloud.callFunction({
            name: 'userInfo'.data: {
              $url: "addUser".data: {
                uid: that.data.uid, ... res.userInfo } }, }).then(res= > {
            console.log(res.result)
            this.setData({
              isLogin: true
            })
            wx.showToast({
              title: 'Login successful'.icon: 'success'.duration: 2000
            })
          }).catch(console.error)
        }
      })
    }
  }
})
Copy the code

Final effect