【科技种草】巧用云功能打造微信网页授权公共服务

  经营许可证     |      2023-09-25
【科技种草】巧用云功能打造微信网页授权公共服务

背景

公司在为客户开发微信公众号相关服务时,有时公众号还没有准备好,所以需要使用公司的公众号,但大家都知道,微信网页的授权域名只支持最多两个,这会导致如果需要同时开发多个项目时出现以下问题:

网页的授权地址不够。官方账号还不够。某个功能如微信快速登录突然失效(授权地址改变):

解决方案

关于域名占用,其实github上已经有现成的方法,可以实现多个域名授权,并且实现内容比较简单,就是一个粗略的静态html文件来处理授权参数。博主之前在一个授权网页扫描登录的Demo中使用过这个静态文件。

一般情况下,如果使用网页授权来获取用户信息,一般都需要服务器和注册域名,那么如果没有服务器怎么办?

云函数巧妙地解决了这个问题。我们只需要一个自己(或没有)的域名通过Cloud Functions托管授权文件即可实现通用的授权服务。

我们来看看这样一个简单的基础服务是怎么做的。

需求分析

首先我们知道我们在配置网页授权域名的时候需要将这个域名添加到公众号中,这就需要我们在服务器上上传一个验证文件,而这个文件只能是挂在根目录后才能访问,这就需要我们添加一个文件上传功能。

这种情况下,云功能需要具备以下能力:

静态文件托管txt验证文件上传显然从头开始手动编写一个云函数有点麻烦,但我们也有内置的应用模板来帮助简化工作量。

实现步骤

应用创建

直接在云函数后台创建应用程序,使用koa模板。

应用修改

应用创建后,云函数列表中会出现一个名为koa-starter 的函数。我们需要修改这个函数的代码。

应用程序模板的源代码可以在github - koa-starter 上找到。

下面是几个核心修改实现:

app.js中增加了对文件上传的支持,小文件可以直接上传。 app.use( koaBody({ multipart: true, formidable: { multipart: true, maxFileSize: 400 * 1024 * 1024 //设置最大上传文件大小限制,默认是4M } })) 复制并添加一些全局处理//全局异常处理app.use(async (ctx, next)={ try { wait next() } catch (err) { ctx.body={ code: -1, data: ctx.data, message: ctx.msg | | err .message || '服务运行不足,请稍后重试', etime: Date.now() } }})//漂亮的json resultapp.use(async (ctx, next)={ wait next() if (ctx .data) { ctx.set('Content-Type', 'application/json') ctx.body={ 代码: ctx.code || 0, 数据: ctx.data, 消息: ctx.msg || 'success' , etime: Date.now() } }}) 在routes/index.js中复制并添加上传文件的路由处理router.post('/uptxt', async (ctx, next)={ if (!ctx .request.files) { ctx.data='No file selected' wait next() return } //获取上传的文件let file=ctx.request.files.file //创建可读流let reader=fs.createReadStream( file.path) let filePath=`/tmp/${file.name}` //创建可写流const upStream=fs.createWriteStream(filePath) wait reader.pipe(upStream); ctx.data=file.name ctx.code=0 ctx.msg='上传验证文件成功'await next()});复制前端模板目录,在views下添加两个页面代码。 auth.html文件,用于授权处理,代码参考。 up.html 文件用于文件上传。我们需要关注的是文件上传功能:

云功能执行过程中,有500MB临时磁盘空间/tmp。用户在执行代码时可以对这块空间进行一些读写操作,也可以创建子目录,但这部分数据在函数执行后不会被保存。预订。因为需要上传一个验证文件,所以这个临时目录自然会有这个txt文件,但是微信需要验证这个文件的有效性,所以这就意味着tmp目录下的东西需要被我们访问,那么应该怎么做呢?我们的确是?

当然有一个解决办法,那就是手动修改静态资源目录为tmp。

修改app.js文件:

app.use(require('koa-static')('/tmp')) 复制,以便上传后可以直接访问。

首页和上传页面的路由处理:router.get('/', async (ctx, next)={ wait ctx.render('index');}); router.get('/up', async (ctx, next)={ wait ctx.render('up');});复制授权页面的访问路由处理:router.get('/auth.html', async (ctx, next)={ wait ctx.render('auth');});复制并保存代码并配置接入服务。

前端接入

vue项目为例

插件引入:

将生成回调地址的wechatAuth.js文件添加到项目中。

部分代码参考:

//导入插件import wechatAuth from '@/plugins/wechatAuth'//设置APPID wechatAuth.setAppId(process.env.VUE_APP_WECHAT_APPID)//使用插件生成授权回调地址wechatAuth.redirect_uri=processUrl()/** * 处理url link* @returns {string} */function processUrl() { //本地环境取代码if (process.env.NODE_ENV==='development') { //中间授权页面地址return `${process.env.VUE_APP_WECHAT_AUTH_URL }? backUrl=${window.location.href}` } const url=window.location.href //解决向多个登录url添加重复代码和状态的问题const urlParams=qs.parse(url.split('?') [ 1]) let redirectUrl=url if (urlParams.code urlParams.state) { 删除urlParams.code 删除urlParams.state const query=qs.stringify(urlParams) if (query.length) { redirectUrl=`${url.split ( '?')[0]}?${query}` } else { redirectUrl=`${url.split('?')[0]}` } } 返回redirectUrl} 复制环境变量配置:

#appid可以填写申请的测试公众号id或者其他准备好的IDVUE_APP_WECHAT_APPID=''#authUrl网页授权中间页面VUE_APP_WECHAT_AUTH_URL='云函数http访问服务地址/auth.html'复制整个授权服务的流程可以总结一下如下图:

因为我们只是将获取微信授权码的过程放到云函数中进行处理,所以多个项目在调试时可以使用同一个地址,减少了资源消耗,是一个可用的解决方案。

我们只需要一个云功能就可以实现微信授权的本地调试,并与多个项目的多个公众号共享一个授权服务,免去独立域名、独立服务器的麻烦。

服务 Demo 演示

这里是云功能网页授权服务的演示地址:

http://cloud.xuedingmiao.com/

参考资料

koa-starter应用模板代码通用问题-云函数可写空间网页授权应用案例