小程序用户唯一性识别

通过 UnionID 机制确定小程序与公众号的同一用户

问题

小程序关联微信公众号后,如何确定用户的唯一性?

解答

OpenID 与 UnionID 的区别

微信为每个用户在不同应用中分配不同的 OpenID,因此同一用户在小程序和公众号中的 OpenID 是不同的。要识别同一用户,需要使用 UnionID。

标识作用域特点
OpenID单个应用内唯一同一用户在不同应用中 OpenID 不同
UnionID开放平台账号下唯一同一用户在绑定的所有应用中 UnionID 相同

获取 UnionID 的前提条件

  1. 微信开放平台注册账号
  2. 将小程序和公众号绑定到同一个开放平台账号下

小程序端获取 UnionID

// 方式一:通过 wx.login 获取 code,后端换取 UnionID
wx.login({
  success(res) {
    if (res.code) {
      // 发送 code 到后端
      wx.request({
        url: 'https://your-server.com/api/login',
        method: 'POST',
        data: { code: res.code },
        success(response) {
          // response.data 包含 openid 和 unionid
          console.log('unionid:', response.data.unionid)
        }
      })
    }
  }
})

// 方式二:用户授权后通过 getUserInfo 获取(需用户同意)
wx.getUserProfile({
  desc: '用于完善用户资料',
  success(res) {
    // 加密数据中包含 unionId
    const encryptedData = res.encryptedData
    const iv = res.iv
    // 发送到后端解密获取 unionId
  }
})

后端获取 UnionID(Node.js 示例)

const axios = require('axios')

async function getUnionId(code) {
  const appid = 'your_appid'
  const secret = 'your_secret'
  
  // 调用微信接口,用 code 换取 session_key 和 openid
  const url = `https://api.weixin.qq.com/sns/jscode2session?appid=${appid}&secret=${secret}&js_code=${code}&grant_type=authorization_code`
  
  const response = await axios.get(url)
  const { openid, unionid, session_key } = response.data
  
  // 如果用户已关注公众号或满足其他条件,会返回 unionid
  return { openid, unionid }
}

公众号端获取 UnionID

// 用户授权后,通过网页授权接口获取
async function getWechatUserInfo(code) {
  const appid = 'your_mp_appid'
  const secret = 'your_mp_secret'
  
  // 1. 用 code 换取 access_token
  const tokenUrl = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${appid}&secret=${secret}&code=${code}&grant_type=authorization_code`
  const tokenRes = await axios.get(tokenUrl)
  const { access_token, openid } = tokenRes.data
  
  // 2. 获取用户信息(包含 unionid)
  const userUrl = `https://api.weixin.qq.com/sns/userinfo?access_token=${access_token}&openid=${openid}&lang=zh_CN`
  const userRes = await axios.get(userUrl)
  
  // userRes.data 包含 unionid
  return userRes.data
}

数据库设计建议

CREATE TABLE users (
  id INT PRIMARY KEY AUTO_INCREMENT,
  union_id VARCHAR(64) UNIQUE NOT NULL,  -- 用户唯一标识
  mp_openid VARCHAR(64),                  -- 公众号 OpenID
  mini_openid VARCHAR(64),                -- 小程序 OpenID
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 通过 union_id 关联同一用户在不同平台的数据

关键点

  • UnionID 是跨应用识别用户的唯一标识,同一用户在绑定同一开放平台的应用中 UnionID 相同
  • 必须绑定开放平台:小程序和公众号需绑定到同一个微信开放平台账号
  • 获取 UnionID 的条件:用户关注了公众号、或用户授权登录、或用户在小程序中支付过
  • OpenID 仍有用:在单个应用内部,OpenID 足够标识用户,且获取门槛更低
  • 数据库以 UnionID 为主键:便于合并用户在不同端的行为数据