小程序接入指南

微信/支付宝/QQ/抖音小程序接入 UserMatrix OAuth 2.1 标准流程。

小程序环境无法跳转外部授权页,需通过各平台的 login() API 获取平台 code,再由 BFF 后端调用 UM OAuth 2.1 端点换取 token。下方为通用接入方式,无需专属 SDK。

接入架构

小程序前端                BFF 后端                    UM OAuth 2.1
    │                       │                            │
    │── wx.login() ────────→│                            │
    │   获取 wx code         │── POST /oauth/token ─────→│
    │                       │   (client_credentials)     │
    │                       │←── access_token ──────────│
    │                       │                            │
    │── POST /api/login ──→│                            │
    │   {wx_code}           │── 调用微信API换openid ─────→│
    │                       │── 创建/查询UM用户           │
    │                       │── 签发 UM access_token      │
    │←── {um_token, user} ──│                            │

微信小程序

前端

// pages/login/login.js
Page({
  async handleLogin() {
    // 1. 调用 wx.login 获取微信登录凭证
    const { code: wxCode } = await wx.login();

    // 2. 发送 wxCode 到你的 BFF 后端
    const res = await new Promise((resolve, reject) => {
      wx.request({
        url: 'https://your-bff.com/api/auth/wxapp',
        method: 'POST',
        data: { code: wxCode },
        success: resolve,
        fail: reject,
      });
    });

    if (res.data.code === 0) {
      // 3. 存储 UM token
      wx.setStorageSync('um_access_token', res.data.access_token);
      wx.setStorageSync('um_refresh_token', res.data.refresh_token);
      wx.setStorageSync('um_user', res.data.user);
      wx.redirectTo({ url: '/pages/index/index' });
    } else {
      wx.showToast({ title: '登录失败', icon: 'error' });
    }
  },
});

BFF 后端(PHP 示例)

<?php
// /api/auth/wxapp.php — 微信小程序登录 BFF
require_once 'UM.class.php';

$um = new UM($appid, $appkey, $callback, 'https://um.yunjii.cn/');

$wxCode = $_POST['code'] ?? '';
if (!$wxCode) {
    json_output(['code' => -1, 'msg' => 'missing code']);
}

// 1. 用 wxCode 调微信 API 换 openid(需微信小程序 appid + secret)
$wxResp = file_get_contents(
    "https://api.weixin.qq.com/sns/jscode2session?" . http_build_query([
        'appid' => $wxAppId,
        'secret' => $wxSecret,
        'js_code' => $wxCode,
        'grant_type' => 'authorization_code',
    ])
);
$wxData = json_decode($wxResp, true);
if (empty($wxData['openid'])) {
    json_output(['code' => -1, 'msg' => '微信登录失败']);
}

// 2. 用 openid 调 UM 旧版 callback 接口换取 UM token(兼容模式)
//    或调用 UM 内部 API 创建/查询用户并签发 token
$params = [
    'act'       => 'callback',
    'appid'     => $um_appid,
    'code'      => $wxData['openid'],  // 微信 openid 作为凭证
    'timestamp' => time(),
];
$params['sign'] = /* 计算 MD5 签名 */;
$umResp = file_get_contents('https://um.yunjii.cn/php/connect.php?' . http_build_query($params));
$umData = json_decode($umResp, true);

// 3. 返回 UM token 给小程序
json_output([
    'code'          => 0,
    'access_token'  => $umData['data']['token'] ?? '',
    'refresh_token' => '',  // 小程序场景按需签发
    'user'          => $umData['data'] ?? null,
]);

小程序场景下,wx.login 返回的 code 不是 OAuth code,而是微信登录凭证。必须在 BFF 后端用微信 API 换取 openid,再通过 UM 接口换取 UM token。

Token 拦截器

// utils/request.js
const app = getApp();

module.exports = function request(options) {
  const token = wx.getStorageSync('um_access_token');
  if (!token) {
    wx.redirectTo({ url: '/pages/login/login' });
    return Promise.reject(new Error('no token'));
  }

  return new Promise((resolve, reject) => {
    wx.request({
      ...options,
      header: {
        ...options.header,
        Authorization: `Bearer ${token}`,
      },
      success(res) {
        if (res.statusCode === 401) {
          // token 过期,尝试刷新或重新登录
          wx.removeStorageSync('um_access_token');
          wx.redirectTo({ url: '/pages/login/login' });
        } else {
          resolve(res);
        }
      },
      fail: reject,
    });
  });
};

支付宝小程序

// 与微信类似,用 my.getAuthCode 替代 wx.login
my.getAuthCode({
  scopes: 'auth_user',
  success: ({ authCode }) => {
    my.request({
      url: 'https://your-bff.com/api/auth/alipayapp',
      method: 'POST',
      data: { code: authCode },
      success: (res) => {
        if (res.data.code === 0) {
          my.setStorageSync('um_access_token', res.data.access_token);
        }
      },
    });
  },
});

跨端框架(Taro / uni-app)

import Taro from '@tarojs/taro';

export async function login() {
  const { code } = await Taro.login();

  const res = await Taro.request({
    url: 'https://your-bff.com/api/auth/wxapp',
    method: 'POST',
    data: { code },
  });

  if (res.data.code === 0) {
    Taro.setStorageSync('um_access_token', res.data.access_token);
    Taro.setStorageSync('um_refresh_token', res.data.refresh_token);
    return res.data.user;
  }
  throw new Error('登录失败');
}

相关文档