关注微信公众号登录小程序

关注微信公众号登录小程序

通过 关注微信公众号实现登录,本质是利用微信的 OpenID/UnionID 机制 将公众号用户与小程序的账号体系打通。以下是具体实现步骤和代码示例:


一、整体流程

sequenceDiagram
    participant 用户
    participant 小程序
    participant 公众号
    participant 服务端

    用户->>小程序: 点击「公众号登录」
    小程序->>服务端: 生成临时二维码(带场景值scene_id)
    服务端->>小程序: 返回二维码
    用户->>公众号: 扫码关注(或已关注用户扫码)
    公众号->>服务端: 推送扫码事件(带scene_id和用户OpenID)
    服务端->>小程序: 通过WebSocket/轮询通知登录成功
    小程序->>用户: 完成登录

二、详细步骤

1. 准备工作

  • 公众号要求

    • 必须是服务号(订阅号部分接口无权限)。

    • 开通 网页授权模板消息 权限(在微信公众平台配置)。

  • 小程序要求

    • 与公众号在同一微信开放平台账号下绑定(获取UnionID必须)。

  • 服务端

    • 准备存储用户关联关系(如 openid_mapping 表)。

2. 生成带场景值的二维码

在小程序中生成临时二维码,关联当前登录会话:

// 小程序端:请求服务端生成二维码
wx.request({
  url: 'https://your-server.com/api/generate-qrcode',
  data: { session_id: '用户临时标识' },
  success(res) {
    // 显示二维码(res.data.qrcode_url)
  }
});

服务端示例(Node.js)

const qrcode = require('qrcode');
const { createTempQRCode } = require('微信公众平台API');

app.post('/api/generate-qrcode', async (req, res) => {
  const scene_id = `login_${Date.now()}`; // 唯一场景值
  const qrCodeUrl = await createTempQRCode(scene_id, 300); // 有效期300秒
  // 存储scene_id与session_id的关联
  cache.set(`scene:${scene_id}`, req.body.session_id);
  res.json({ qrcode_url: qrCodeUrl });
});

3. 用户扫码并关注公众号

  • 用户扫描二维码后:

    • 如果已关注公众号,微信会立即推送事件到你的服务器。

    • 如果未关注,关注后才会推送。

公众号服务器配置(接收事件)

// 微信配置的公众号消息接口
router.post('/wechat/event', (req, res) => {
  const { Event, EventKey, FromUserName } = req.body;
  if (Event === 'SCAN' && EventKey.startsWith('login_')) {
    const scene_id = EventKey;
    const openid = FromUserName;
    // 1. 获取用户UnionID(需网页授权)
    // 2. 关联小程序账号
    linkAccount(scene_id, openid);
  }
  res.send('success');
});

4. 关联小程序账号

通过 UnionID 打通公众号和小程序用户:

async function linkAccount(scene_id, openid) {
  // 1. 获取UnionID(需公众号网页授权)
  const unionid = await getUnionID(openid);
  
  // 2. 查询是否已绑定过小程序用户
  const miniUser = db.query('SELECT * FROM users WHERE unionid = ?', [unionid]);
  
  // 3. 通知小程序登录成功
  const session_id = cache.get(`scene:${scene_id}`);
  if (miniUser) {
    ws.send(session_id, { action: 'login_success', user_id: miniUser.id });
  } else {
    // 新用户注册逻辑
    ws.send(session_id, { action: 'register', unionid });
  }
}

5. 小程序完成登录

通过 WebSocket 或轮询接收登录状态:

// 小程序端:轮询检查登录状态
function checkLoginStatus(session_id) {
  setInterval(() => {
    wx.request({
      url: 'https://your-server.com/api/check-login',
      data: { session_id },
      success(res) {
        if (res.data.logged_in) {
          clearInterval();
          wx.setStorageSync('token', res.data.token);
        }
      }
    });
  }, 1000);
}

三、关键API与配置


四、注意事项

  1. 用户未关注公众号

    需在二维码旁提示“扫码后关注公众号自动登录”。

  2. 安全性

    • 使用 HTTPS 传输数据。

    • 二维码有效期建议 3-5 分钟。

  3. UnionID 必须

    若公众号和小程序未绑定到同一开放平台,只能通过 OpenID 匹配(不推荐)。

  4. 用户体验

    • 提供备选登录方式(如手机号登录)。

    • 扫码后可在公众号内发送登录成功提示。


五、优化方案

  • 静默授权:通过公众号菜单提前获取用户授权,避免扫码后二次确认。

  • 跨设备登录:若用户手机扫描PC端二维码,可通过公众号模板消息发送登录确认。

通过以上流程,即可实现“关注公众号即登录小程序”的无缝体验。

# 关注微信公众号登录小程序

通过 **关注微信公众号实现登录**,本质是利用微信的 **OpenID/UnionID 机制** 将公众号用户与小程序的账号体系打通。以下是具体实现步骤和代码示例:

---

### **一、整体流程**

```mermaid
sequenceDiagram
    participant 用户
    participant 小程序
    participant 公众号
    participant 服务端

    用户->>小程序: 点击「公众号登录」
    小程序->>服务端: 生成临时二维码(带场景值scene_id)
    服务端->>小程序: 返回二维码
    用户->>公众号: 扫码关注(或已关注用户扫码)
    公众号->>服务端: 推送扫码事件(带scene_id和用户OpenID)
    服务端->>小程序: 通过WebSocket/轮询通知登录成功
    小程序->>用户: 完成登录
```

---

### **二、详细步骤**

#### 1. **准备工作**

- **公众号要求**:
  - 必须是**服务号**(订阅号部分接口无权限)。
  - 开通 **网页授权** 和 **模板消息** 权限(在微信公众平台配置)。
- **小程序要求**:
  - 与公众号在同一微信开放平台账号下绑定(获取UnionID必须)。
- **服务端**:
  - 准备存储用户关联关系(如 `openid_mapping` 表)。

#### 2. **生成带场景值的二维码**

在小程序中生成临时二维码,关联当前登录会话:

```javascript
// 小程序端:请求服务端生成二维码
wx.request({
  url: 'https://your-server.com/api/generate-qrcode',
  data: { session_id: '用户临时标识' },
  success(res) {
    // 显示二维码(res.data.qrcode_url)
  }
});
```

**服务端示例(Node.js)**:

```javascript
const qrcode = require('qrcode');
const { createTempQRCode } = require('微信公众平台API');

app.post('/api/generate-qrcode', async (req, res) => {
  const scene_id = `login_${Date.now()}`; // 唯一场景值
  const qrCodeUrl = await createTempQRCode(scene_id, 300); // 有效期300秒
  // 存储scene_id与session_id的关联
  cache.set(`scene:${scene_id}`, req.body.session_id);
  res.json({ qrcode_url: qrCodeUrl });
});
```

#### 3. **用户扫码并关注公众号**

- 用户扫描二维码后:
  - 如果已关注公众号,微信会**立即推送事件**到你的服务器。
  - 如果未关注,关注后才会推送。

**公众号服务器配置(接收事件)**:

```javascript
// 微信配置的公众号消息接口
router.post('/wechat/event', (req, res) => {
  const { Event, EventKey, FromUserName } = req.body;
  if (Event === 'SCAN' && EventKey.startsWith('login_')) {
    const scene_id = EventKey;
    const openid = FromUserName;
    // 1. 获取用户UnionID(需网页授权)
    // 2. 关联小程序账号
    linkAccount(scene_id, openid);
  }
  res.send('success');
});
```

#### 4. **关联小程序账号**

通过 **UnionID** 打通公众号和小程序用户:

```javascript
async function linkAccount(scene_id, openid) {
  // 1. 获取UnionID(需公众号网页授权)
  const unionid = await getUnionID(openid);
  
  // 2. 查询是否已绑定过小程序用户
  const miniUser = db.query('SELECT * FROM users WHERE unionid = ?', [unionid]);
  
  // 3. 通知小程序登录成功
  const session_id = cache.get(`scene:${scene_id}`);
  if (miniUser) {
    ws.send(session_id, { action: 'login_success', user_id: miniUser.id });
  } else {
    // 新用户注册逻辑
    ws.send(session_id, { action: 'register', unionid });
  }
}
```

#### 5. **小程序完成登录**

通过 WebSocket 或轮询接收登录状态:

```javascript
// 小程序端:轮询检查登录状态
function checkLoginStatus(session_id) {
  setInterval(() => {
    wx.request({
      url: 'https://your-server.com/api/check-login',
      data: { session_id },
      success(res) {
        if (res.data.logged_in) {
          clearInterval();
          wx.setStorageSync('token', res.data.token);
        }
      }
    });
  }, 1000);
}
```

---

### **三、关键API与配置**

---

### **四、注意事项**

1. **用户未关注公众号**:
  需在二维码旁提示“扫码后关注公众号自动登录”。
2. **安全性**:
  - 使用 HTTPS 传输数据。
  - 二维码有效期建议 3-5 分钟。
3. **UnionID 必须**:
  若公众号和小程序未绑定到同一开放平台,只能通过 OpenID 匹配(不推荐)。
4. **用户体验**:
  - 提供备选登录方式(如手机号登录)。
  - 扫码后可在公众号内发送登录成功提示。

---

### **五、优化方案**

- **静默授权**:通过公众号菜单提前获取用户授权,避免扫码后二次确认。
- **跨设备登录**:若用户手机扫描PC端二维码,可通过公众号模板消息发送登录确认。

通过以上流程,即可实现“关注公众号即登录小程序”的无缝体验。