Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

记一次使用腾讯云Serverless的VS Code插件来定位问题 #6

Open
Juliiii opened this issue Aug 24, 2019 · 0 comments
Open
Labels

Comments

@Juliiii
Copy link
Owner

Juliiii commented Aug 24, 2019

近日发现了一个比较有趣的库,co-wechat

该库封装了微信公共平台消息接口,并将其作为中间件的形式,配合express,koa等框架使用。

所以尝试着配合腾讯云Serverless,api网关以及该库,做一个自动回复的机器人。

根据微信公众平台技术文档中的指引进行了 个人订阅号的申请,开发者基本配置。以及根据腾讯云云函数文档完成云函数的创建以及Api网关触发器的配置,这里就不一一赘述。跟着文档做就行了。

一开始,跟着co-wechat以及serverless-http的文档写出来以下代码:

"use strict";
const Koa = require("koa");
const serverless = require("serverless-http");
const wechat = require("co-wechat");
const config = {
	token: 'token',
  appid: 'appid',
  encodingAESKey: 'encodinAESKey',
};

const app = new Koa();

app.use(
  wechat(config).middleware(async (message, ctx) => {
    console.log(message);
    // 微信输入信息就是这个 message
    if (message.FromUserName === "作者") {
      // 回复屌丝(普通回复)
      return "hehe";
    } else if (message.MsgType === "text") {
      //你也可以这样回复text类型的信息
      return {
        content: "diaosi",
        type: "text"
      };
    } else if (message.FromUserName === "hehe") {
      // 回复一段音乐
      return {
        type: "music",
        content: {
          title: "来段音乐吧",
          description: "一无所有",
          musicUrl: "http://mp3.com/xx.mp3",
          hqMusicUrl: "http://mp3.com/xx.mp3"
        }
      };
    } else if (message.FromUserName === "kf") {
      // 转发到客服接口
      return {
        type: "customerService",
        kfAccount: "test1@test"
      };
    } else {
      // 回复高富帅(图文回复)
      return [
        {
          title: "你来我家接我吧",
          description: "这是女神与高富帅之间的对话",
          picurl: "http://nodeapi.cloudfoundry.com/qrcode.jpg",
          url: "http://nodeapi.cloudfoundry.com/"
        }
      ];
    }
  })
);

const handler = serverless(app);
exports.main_handler = async (event, context, callback) => {
  return await handler(event, context);
};

并上传到腾讯云Serverless中,同时在微信公众号发送了一个词语,触发了一次云函数:

image-20190824144317024

但是,我却得到了这个错误。

错误可能情况有如下几种:

1、云函数执行错误,这个可以否掉了,因为看起来并不像

2、代码逻辑错误,这个也可以否掉了,基本都是看文档,CV文档的demo代码,流行库的demo代码基本没啥问题。

3、微信公众号的相关配置错误,这个也可以否掉,跟着文档一步步走的,除非我的阅读理解有问题。

4、依赖的第三方库,co-wechat以及serverless-http的处理有问题。

错误可能情况4比较有可能,但是线上的日志查看已经无法继续定位问题,不过幸好腾讯云Serverless还提供了另一个利器:

Tencent Serverless Toolkit for VS Code

所以,我开始使用该VS Code插件进行本地调试。

为了完全模拟微信公众号发来的请求信息,我现在控制台的日志中,CV了一份请求信息,并使用VS Code插件新增了一个Api网关的测试模板。

image-20190824145218107

image-20190824145326953

并在.vscode文件夹下,新建一个launch.json,使用快捷键生成了debugger的scf的调试配置,并加上了cwd,指定工作空间。

image-20190824145424122

由于怀疑是co-wechat库的问题,所以去node_modules下的co-wehcat的源码中看了看,发现他们源码中的确有返回:
image-20190824145920027

但是是哪里出了问题呢,所以我在这附近打了个 断点。

并F5,选择了我新建的测试模板,开始debug。

image-20190824150700529

跳到断点处,发现,这个库返回这个错误的原因在于这一句if代码判断微信发给云函数的签名,即signature与库自己算出来的不一致。然后我再在watch栏添加了这两个值,发现微信发给云函数的签名,不见了!

为什么会不见呢?

我的测试模板中,是明确带着的,大家可以回到上面的测试模板的图可以看到queryString中的signature是有值的。

我再在watch栏查看了ctx.query的值。

image

空对象!

那问题就基本可以定位在 serverless-http这个库了。

去到该库的源代码,在create-request文件中发现了如下代码:

image

一目了然。原因为:serverless-http并没有很好兼容腾讯云Api网关的请求格式。腾讯云Api网关的请求格式中,queryString存放着请求的queryString参数,但是serverless-http只取图中两个参数名的参数作为express,koa等的query参数,没有取queryString参数的值

靠着Tencent Serverless Toolkit for VS Code定位了到了问题,所以我在代码中做下兼容,即解决了这个问题。并运行成功,做了个简单的自动回复机器人~

exports.main_handler = async (event, context, callback) => {
  event.queryStringParameters = event.queryString;

  return await handler(
    { ...event, queryStringParameters: event.queryString },
    context
  );
};

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant