[小程序NO.1]如何在小程序开发工具提供的Node.js快速启动模版的基础上获得微信群信息

本文介绍了在小程序开发中如何从1044状态码进入时获取并解密shareTicket,以获得微信群的encryptedData和iv。通过官方文档和解密算法,详细阐述了获取appid、session_key、encryptedData和iv的过程,以及后台解码的步骤。然而,作者在测试环境中遇到openGid不断变化的问题,导致无法稳定获取群名称。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    LZ最近在做一个基于群的小程序,需要先解决如何获得小程序提供的微信群信息的技术问题。由于LZ之前没有建站经验,所以直接使用了腾讯云的小程序解决方案,就是Node.js快速启动模版。这个模版后台是基于koa框架和微信自己开发的wafer2框架。其中wafer2框架中直接提供了对于用户登陆、上传图片等常见功能的解决方案。大家可以跳到这里查看, https://www.jianshu.com/p/072ff89e723c。但是,不幸的是:wafer2框架中并没有对于获得群信息的封装,所以我们要自己实现。

        根据官方文档中的open-data部分的介绍,为了保护用户隐私,小程序只向开发者提供了openGid。它用来在某个特定小程序中唯一标识一个群,并且可以通过open-data组件来向用户展示群名称(并不能拿到群名称只是展示而已)。可以先看这篇文章:https://www.ifanr.com/minapp/832760  看完之后,大家可以基本理解这个流程。本文主要介绍通过1044状态码进入小程序(即通过其他群成员分享到群中的小程序小卡片进入)如何拿到群信息。

一、第一条线索:查看官方文档关于转发的部分,通过1044进入时,小程序就可以额外获取到 shareTicket。有了 shareTicket,我们就可以通过调用 wx.getShareInfo 函数,获取到目标微信群的encryptedData和iv。注意这是用来获得群id的关键线索。那么我们接着看官方文档:https://developers.weixin.qq.com/miniprogram/dev/api/signature.html#wxchecksessionobject。这里提供了解密算法的下载。然后我们将它下载下来并打开查看node部分。解密算法如下所示:

var crypto = require('crypto')

function WXBizDataCrypt(appId, sessionKey) {
  this.appId = appId
  this.sessionKey = sessionKey
}

WXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) {
  // base64 decode
  var sessionKey = new Buffer(this.sessionKey, 'base64')
  encryptedData = new Buffer(encryptedData, 'base64')
  iv = new Buffer(iv, 'base64')
  try {
     // 解密
    var decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv)
    // 设置自动 padding 为 true,删除填充补位
    decipher.setAutoPadding(true)
    var decoded = decipher.update(encryptedData, 'binary', 'utf8')
    decoded += decipher.final('utf8')
    decoded = JSON.parse(decoded)
  } catch (err) {
    throw new Error('Illegal Buffer')
  }
  if (decoded.watermark.appid !== this.appId) {
    throw new Error('Illegal Buffer')
  }
  return decoded
}
module.exports = WXBizDataCrypt

给出的demo样例如下所示:

var WXBizDataCrypt = require('./WXBizDataCrypt')
var appId = 'wxee6e3f1721fc1c61'
var sessionKey = 'Sc7PC6lZ3IPgcx7h+ZQMvA=='
var encryptedData="7deXSrzADGzvcwWjhWYded3UHMtusTG9kiX5jW14uSSFfbyzqW5xD3SP2x0r+ZSBuMJMCkxGHsgIEBvTDuKAeo5D44hdcIFv9OoYB/pexWDElpVqqxhHvtH22hax2qr3pro4fX2R2Tz6Vw3CL1ZaTQ=="
var pc = new WXBizDataCrypt(appId, sessionKey)
var data = pc.decryptData(encryptedData , iv)
console.log('解密后 data: ', data)

这里我们可以得知:只要为这个算法提供四个输入:appid,session_key,encryptedData和iv,它便可以将openGid返回给我们。问题似乎变得清晰了。


二、那么我们分别通过什么方式可以得到appid,session_key,encryptedData和iv呢?

1、首先是appid,我们打开腾讯云提供的phpadmin数据库操作界面,可以发现在cAuth数据库的cAppinfo表中保存了appid。GOT IT!!如下所示


2、session_key:这个比较复杂,首先我们需要对小程序的登陆流程有所理解,大家可以参见官方文档https://developers.weixin.qq.com/miniprogram/dev/api/api-login.html。通过文档,我们了解到,要拿到session_key,我们需要拿到前端携带在http头部的第三方skey,然后在cAuth数据库中查看cSessionInfo表,用第三方的skey来拿到session_key
3、然后是encryptedData和iv了,它们在小程序app的onshow或onlaunch方法中,可以拿到,如下所示,我们拿到后,使用wx.setStorageSync将其保存下来
App({
    onLaunch: function (ops) {
        qcloud.setLoginUrl(config.service.loginUrl)
        if (ops.scene == 1044) {
          console.log(ops.shareTicket)
          wx.getShareInfo({
            shareTicket: ops.shareTicket,
            complete(res) {
              console.log(res)
              wx.setStorageSync('encryptedData', res.encryptedData)
              wx.setStorageSync('iv', res.iv)
            }
          })
        }
    }
})

我们可以通过小程序开发工具对保存下来的值进行查看


然后通过qcloud.request方法,将它们放到options.data对象中发送给后端即可,然后在success回调函数中,将openGid赋值给data.open_gid,如下所示

doGroup:function(){
      var that=this
      util.showBusy('发送群信息中...')
      var options ={ 
        url:config.service.groupUrl,
        login:false,
        // method:'POST',
        data:{
          encrytedData: wx.getStorageSync('encryptedData'),
          iv:wx.getStorageSync('iv')
        },
        success(result) {
          util.showSuccess('请求成功完成')
          console.log('request success', result)
          that.setData({ open_gid: result.data.data.openGId})
          console.log(that.data.open_gid)
        },
        fail(error) {
          util.showModel('请求失败', error);
          console.log('request fail', error);
        }
      }
      qcloud.request(options)
    },


三、后台拿到后,直接调用我们前面下载的解码函数解码即可得到openGid,具体代码如下:

1、在page.json的dependencies中添加对解码算法使用的crypto包的依赖如下图所示:



2、在route文件夹的index.js下添加如下代码:

router.get( '/group' , validationMiddleware,controllers.group) //[msg|这里填写路由,和转发给谁进行处理]

3、将前文中的解码算法复制到controllers文件夹下(这种做法不够好,但可以解决问题)

4、再在controllers文件夹中新建group.js,输入如下代码

var WXBizDataCrypt = require('./WXBizDataCrypt')
const qcloud = require('../qcloud')
const { mysql } = qcloud
module.exports = async (ctx, next) => {
  if (ctx.state.$wxInfo.loginState === 1) {
    // loginState 为 1,登录态校验成功
    try{
      const appInfo = await mysql('cAppinfo').select('*')//[msg|从数据库取得appInfo对象]
      const appId=appInfo[0].appid//[msg|从appInfo上拿到appId的值]
      const { 'x-wx-skey': skey } = ctx.req.headers//[msg|从请求头拿到skey]
      const sessionInfo = await mysql('cSessionInfo').select('*').where({ skey: skey })//[msg|根据skey从数据库拿到]
      const sessionKey = sessionInfo[0].session_key//[msg|根据skey拿到sessionkey]
      const encryptedData = ctx.query.encrytedData//[msg|从query中拿到encryedData]
      const iv = ctx.query.iv//[msg|从query中拿到iv]
      const pc = new WXBizDataCrypt(appId, sessionKey)//[msg|初始化并调用解码器来解码]
      const data = pc.decryptData(encryptedData, iv)
      ctx.state.data = data//[msg|将得到的数据放到请求体中用于发给前端]
    }catch(e){
      ctx.state.code = -1
    }
  } else {
    ctx.state.code = -1
  }
}

四、写在最后面(LZ目前没有解决的问题)

1、LZ发现:在测试环境下,使用手机将测试版小程序分享到群中,每次拿到的openGid都是不同的

2、更不幸的是:将这个openGid绑定至open-data,如下所示,并不能获得群名称(所以我这七个小时都干了什么)

< open-data type = 'groupName' open-gid = '{{open_gid}}'></ open-data >

3、然后,使用微信web开发工具,通过下图方式编译进入,每次拿到的openGid都不一样

4、所以,在开发环境下,lz并没有解决openGid的问题,而且似乎也不知道该如何解决(如果有大神知道,请指教)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值