用户体系

在涂鸦系的 App 内打开小程序,默认使用 App 的用户体系。 如果开发者需要在小程序业务获取用户信息,并在用户维度处理自己的业务, 那么就需要使用小程序登录能力来对接。

小程序登录

涂鸦官方提供了登录能力,开发者可以通过相关 API 获取 App 的用户身份标识,快速的建立小程序内的用户体系。

登录流程

说明

  1. 需要调用 ty.login() 获取 临时登录凭证 code,并将 code 传到开发者服务器
  2. 开发者服务器调用涂鸦云开发能力 API /1.0/token,传入 code,获取 access_token 及 uid,然后开发者根据 aceess_token 及 uid 自定义登录状态,并返回给前端,然后进行后续的交互。

注意:在开发小程序前,请先确保已经将小程序与云项目进行关联,关联方法请参考下面的服务器开发。

服务器开发

开发者服务器端要调用涂鸦云开发能力 API,需要创建云项目,并需要将云项目应用与小程序进行关联。

  1. 使用 涂鸦开发者平台账号登录到 涂鸦开发者平台,选择云开发菜单,点击创建云项目
  1. 创建成功后,即在云项目的详细页面中查询获取 Client ID 及 Client secret,用于请求 API 签名
  1. 到小程序开发者平台,进入小程序开发设置菜单,点击云项目模块的 添加 按钮,然后选择对应的云项目关联。

相关文档

  1. 云开发开发文档,可参考这里文档。
  2. API 签名机制,可参考这里
  3. ty.login API定义,可参考这里

代码示例

Ray 开发示例

import {
  login,
  getUserInfo,
  request,
  setStorageSync,
  showModal,
} from '@ray-js/ray';

const { code } = await login({});

const { nickName, avatarUrl } = await new Promise((resolve, reject) =>
  getUserInfo({ success: resolve, fail: reject })
);

request({
  url: 'https://www.xxx.com/login',
  method: 'POST',
  header: {
    'Content-Type': 'application/json',
  },
  data: JSON.stringify({
    code,
    nickName,
    avatarUrl,
  }),
  success: ({ data }: any) => {
    setStorageSync({ key: 'session', data });
  },
  fail: () => {
    showModal({
      title: '提示',
      content: '登录失败',
      showCancel: false,
    });
  },
});

原生小程序开发示例

ty.login({
  success: ({ code }) => {
    ty.getUserInfo({
      success: ({ nickName, avatarUrl }) => {
        ty.request({
          url: 'https://www.xxx.com/login',
          method: 'POST',
          header: {
            'Content-Type': 'application/json',
          },
          data: JSON.stringify({
            code,
            nickName,
            avatarUrl,
          }),
          success: ({ data }: any) => {
            ty.setStorageSync({
              key: 'session',
              data,
            });
          },
          fail: (err) => {
            console.log('err', err);
            ty.showModal({
              title: '提示',
              content: '登录失败',
              showCancel: false,
            });
          },
        });
      },
      fail: (err) => {
        console.log('getUserInfo err', err);
      },
    });
  },
});

服务器端代码(这里使用 Nodejs Koa 实现)

import Koa from 'koa';
import KoaRouter from 'koa-router';
import crypto from 'crypto';
import axios from 'axios';
import bodyParser from 'koa-bodyparser';

const app = new Koa();
const router = new KoaRouter();
const accessKey = '云开发 Client ID';
const secretKey = '云开发 Client Secret';

router.post('/login', async (ctx) => {
  const { code, nickName, avatarUrl } = ctx.request.body;

  const path = `/v1.0/token?code=${code}&grant_type=2`;
  const contentHash = crypto.createHash('sha256').update('').digest('hex');
  const t = +new Date();
  const nonce = '';
  const stringToSign = ['GET', contentHash, '', path].join('\n');
  const signStr = [accessKey, t, nonce, stringToSign].join('');
  const sign = crypto
    .createHmac('sha256', secretKey)
    .update(signStr, 'utf8')
    .digest('hex')
    .toUpperCase();

  const { data } = await axios({
    // 不同的地区需要使用不同的域名地址,这里为中国区地址
    url: `https://openapi.tuyacn.com/v1.0/token?code=${code}&grant_type=2`,
    method: 'GET',
    headers: {
      t,
      sign,
      client_id: accessKey,
      sign_method: 'HMAC-SHA256',
      Dev_lang: 'Nodejs',
      'Signature-Headers': '',
    },
  });

  let responseData;
  if (data.success) {
    responseData = {
      success: true,
      result: {
        sessionId: '1234567890', // 服务端自己生成一个唯一id,用于管理小程序登录状态
      },
    };
  } else {
    responseData = {
      success: false,
      errMsg: data.msg,
      errCode: data.code,
    };
  }

  ctx.body = responseData;
});

app.use(bodyParser()).use(router.allowedMethods()).use(router.routes());

app.listen(3000, () => {
  console.log('Server start on http://localhost:3000');
});