巧用腾讯云云函数打造微信网页授权公用服务

使用云函数实现微信网页授权公用服务

# 背景

公司为客户开发微信公众号相关服务时,有时未能准备好公众号,所以需要使用公司的公众号,但是大家都知道微信网页授权域名最多只支持两个,这就造成了如果有多个项目需要同时开发时产生了如下问题:

  • 网页授权地址不够用
  • 公众号不够用
  • 某功能比如微信快捷登录突然失效(授权地址被改掉)

# 解决方案

关于域名占用的问题,其实在github上已经有现成的方法了,可以实现多域名的授权,而且实现内容也比较简单,就是一个粗暴的静态html文件去处理授权用的参数。博主之前曾经做过一个网页授权扫码登录的Demo就用到了这个静态文件。

正常情况下如果用到了网页授权获取用户信息,一般是需要一台服务器一个备案过的域名的,那么如果没有服务器改咋整呢?

云函数很巧妙地解决了这个问题,我们只需要一个自己的域名(不用其实也可以)就可以通过云函数来托管这个授权用的文件来实现通用的授权服务。

下面我们来看一下如何去做这么一个简易的基础服务。

# 需求分析

首先我们知道配置网页授权域名的时候需要在公众号添加这个域名,要求我们在服务器上上传一个验证文件,并且这个文件要挂在根目录下才可以访问到,这就要求我们增加一个文件上传的功能。

这种情况下云函数就需要具备如下能力:

  • 静态文件托管
  • txt 验证文件上传

显然自己手动从零编写一个云函数就有些繁琐了,不过还有我们有内置应用模板 帮助简化工作量。

# 实现步骤

# 应用创建

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

# 应用修改

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

应用模板的源码在 github 上就可以获取->koa-starter

这里讲解一下几个核心修改的实现吧:

  1. app.js 内增加文件上传的支持,小文件是可以直接上传的。
app.use(
  koaBody({
    multipart: true,
    formidable: {
      multipart: true,
      maxFileSize: 400 * 1024 * 1024, // 设置上传文件大小最大限制,默认4M
    },
  })
)
  1. 然后增加一些全局的处理
// 全局异常处理
app.use(async (ctx, next) => {
  try {
    await next()
  } catch (err) {
    ctx.body = {
      code: -1,
      data: ctx.data,
      message: ctx.msg || err.message || '服务开小差了,请稍后再试',
      etime: Date.now(),
    }
  }
})

// pretty json result
app.use(async (ctx, next) => {
  await next()
  if (ctx.data) {
    ctx.set('Content-Type', 'application/json')
    ctx.body = {
      code: ctx.code || 0,
      data: ctx.data,
      message: ctx.msg || 'success',
      etime: Date.now(),
    }
  }
})
  1. routes/index.js中增加上传文件的路由处理
router.post('/uptxt', async (ctx, next) => {
  if (!ctx.request.files) {
    ctx.data = '未选择文件'
    await next()
    return
  }
  // 获取上传文件
  let file = ctx.request.files.file
  // 创建可读流
  let reader = fs.createReadStream(file.path)
  let filePath = `/tmp/${file.name}`

  // 创建可写流
  const upStream = fs.createWriteStream(filePath)
  await reader.pipe(upStream)
  ctx.data = file.name
  ctx.code = 0
  ctx.msg = '上传验证文件成功'
  await next()
})
  1. 前端的模板目录views下面增加两份页面代码。
  • auth.html文件,用于授权处理,代码参考
  • up.html文件,用于文件上传。

文件上传功能我们需要注意一点:

  • 云函数在执行过程中,都拥有一块 500MB 的临时磁盘空间 /tmp,用户可以在执行代码时对该空间进行一些读写操作,也可以创建子目录,但这部分数据在函数执行完成后不会保留。

因为需要上传一个验证文件所以这个临时目录自然会有这个 txt 文件,但是微信需要验证这个文件的有效性,所以这就意味着 tmp 目录下的东西需要被我们访问到,那该怎么办?

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

修改 app.js 文件:

app.use(require('koa-static')('/tmp'))

这样在上传之后就可以直接访问到了。

  1. 首页及上传页的路由处理:
router.get('/', async (ctx, next) => {
  await ctx.render('index')
})
router.get('/up', async (ctx, next) => {
  await ctx.render('up')
})
  1. 授权页的访问路由处理:
router.get('/auth.html', async (ctx, next) => {
  await ctx.render('auth')
})
  1. 保存代码并配置访问服务。

# 前端接入

vue 项目为例

插件引入:

在项目中加入生成回调地址的wechatAuth.js 文件。

部分代码参考:

// 引入插件
import wechatAuth from '@/plugins/wechatAuth'

// 设置APPID
wechatAuth.setAppId(process.env.VUE_APP_WECHAT_APPID)

// 使用插件生成授权回调地址
wechatAuth.redirect_uri = processUrl()

/**
 * 处理url链接
 * @returns {string}
 */
function processUrl() {
  // 本地环境拿code
  if (process.env.NODE_ENV === 'development') {
    // 中间授权页地址
    return `${process.env.VUE_APP_WECHAT_AUTH_URL}?backUrl=${
      window.location.href
    }`
  }
  const url = window.location.href
  // 解决多次登录url添加重复的code与state问题
  const urlParams = qs.parse(url.split('?')[1])
  let redirectUrl = url
  if (urlParams.code && urlParams.state) {
    delete urlParams.code
    delete urlParams.state
    const query = qs.stringify(urlParams)
    if (query.length) {
      redirectUrl = `${url.split('?')[0]}?${query}`
    } else {
      redirectUrl = `${url.split('?')[0]}`
    }
  }
  return redirectUrl
}

环境变量配置:

#appid 可填入申请的测试公众号id或者其它准备好的ID
VUE_APP_WECHAT_APPID=''

#authUrl 网页授权中间页
VUE_APP_WECHAT_AUTH_URL='云函数http访问服务地址/auth.html'

整个授权服务的流程可概括为下图:

因为我们只是把获取微信授权 code 的过程统一放到了云函数去处理,所以多个项目在调试时都可以使用同一个地址,减少了资源占用,不失为一个可用方案。

我们仅需要一个云函数就可以实现微信授权的本地调试以及几个项目几个公众号共用一个授权服务,免去独立域名、独立服务器的烦恼。

# 服务 Demo 演示

这里提供了一个云函数网页授权服务的 Demo 地址: http://cloud.xuedingmiao.com/

# 参考资料

原文地址:https://cloud.tencent.com/developer/article/1903771

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340